r=warren. a=jar. 30634, 30635. something caused event timing changes which aggrivated some FTP bugs. FTP no longer pumps it's own event loop, no longer implements AsyncOpen, and has changed the synchronization between the channel object and the FTP thread. The current changes aggrivate a bug in the socket transport which manifests itself as the throbber not always stopping when a download completes.

This commit is contained in:
valeski%netscape.com 2000-03-09 09:46:56 +00:00
parent 26f0eab67f
commit ec891ecf55
8 changed files with 162 additions and 293 deletions

View File

@ -31,7 +31,6 @@ interface nsIEventQueue;
interface nsPIFTPChannel : nsIChannel
{
void SetContentLength(in long aLength);
void Stopped(in nsresult aStatus, in wstring aMsg);
};

View File

@ -21,6 +21,10 @@
*/
#include "nsAsyncEvent.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
static NS_DEFINE_CID(eventQCID, NS_EVENTQUEUESERVICE_CID);
nsAsyncEvent::nsAsyncEvent(nsIChannel* channel, nsISupports* context)
: mChannel(channel), mContext(context), mEvent(nsnull)
@ -54,10 +58,16 @@ void PR_CALLBACK nsAsyncEvent::DestroyPLEvent(PLEvent* aEvent)
}
nsresult
nsAsyncEvent::Fire(nsIEventQueue* aEventQueue)
nsAsyncEvent::Fire()
{
NS_PRECONDITION(nsnull != aEventQueue, "nsIEventQueue for thread is null");
nsresult rv = NS_OK;
nsCOMPtr<nsIEventQueueService> eqServ = do_GetService(eventQCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> eventQ;
rv = eqServ->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eventQ));
if (NS_FAILED(rv)) return rv;
NS_PRECONDITION(nsnull == mEvent, "Init plevent only once.");
mEvent = new PLEvent;
@ -67,7 +77,7 @@ nsAsyncEvent::Fire(nsIEventQueue* aEventQueue)
(PLHandleEventProc) nsAsyncEvent::HandlePLEvent,
(PLDestroyEventProc) nsAsyncEvent::DestroyPLEvent);
PRStatus status = aEventQueue->PostEvent(mEvent);
PRStatus status = eventQ->PostEvent(mEvent);
return status == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
}

View File

@ -36,7 +36,7 @@ public:
nsAsyncEvent(nsIChannel* channel, nsISupports* context);
virtual ~nsAsyncEvent();
nsresult Fire(nsIEventQueue* aEventQ);
nsresult Fire();
NS_IMETHOD HandleEvent() = 0;

View File

@ -24,11 +24,8 @@
#include "nsFTPChannel.h"
#include "nsIStreamListener.h"
#include "nscore.h"
#include "prlog.h"
#include "nsIServiceManager.h"
#include "nsIMIMEService.h"
#include "nsIPipe.h"
#include "nsNetUtil.h"
#include "nsMimeTypes.h"
@ -53,14 +50,13 @@ nsFTPChannel::nsFTPChannel() {
mSourceOffset = 0;
mAmount = 0;
mContentLength = -1;
mConnThread = nsnull;
mAsyncOpen = PR_FALSE;
mLock = nsnull;
}
nsFTPChannel::~nsFTPChannel() {
NS_ASSERTION(!mConnThread, "FTP: connection thread ref still exists");
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("~nsFTPChannel() called"));
nsXPIDLCString spec;
mURL->GetSpec(getter_Copies(spec));
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("~nsFTPChannel() for %s", (const char*)spec));
if (mLock) PR_DestroyLock(mLock);
}
@ -89,8 +85,10 @@ nsFTPChannel::Init(const char* verb,
{
nsresult rv = NS_OK;
if (mConnected)
if (mConnected) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("ERROR nsFTPChannel:Init called while connected.\n"));
return NS_ERROR_ALREADY_CONNECTED;
}
// parameter validation
NS_ASSERTION(aPool, "FTP: channel needs a thread pool to play in");
@ -154,6 +152,7 @@ nsFTPChannel::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
NS_IMETHODIMP
nsFTPChannel::IsPending(PRBool *result) {
nsAutoLock lock(mLock);
if (mProxyChannel)
return mProxyChannel->IsPending(result);
return NS_ERROR_NOT_IMPLEMENTED;
@ -161,37 +160,39 @@ nsFTPChannel::IsPending(PRBool *result) {
NS_IMETHODIMP
nsFTPChannel::Cancel(void) {
if (mProxyChannel)
nsresult rv;
nsAutoLock lock(mLock);
if (mProxyChannel) {
return mProxyChannel->Cancel();
// if we hit this assert, someone's hanging onto the channel too long.
NS_ASSERTION(mConnThread, "lost the connection thread.");
// it's ok for this method to *not* have the underlying thread because
// the user obviously want's the underlying channel/connection to go away.
return mConnThread->Cancel();
} else if (mConnThread) {
rv = mConnThread->Cancel();
mConnThread = nsnull;
mConnected = PR_FALSE;
return rv;
}
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::Suspend(void) {
if (mProxyChannel)
nsAutoLock lock(mLock);
if (mProxyChannel) {
return mProxyChannel->Suspend();
// if we hit this assert, someone's hanging onto the channel too long.
NS_ASSERTION(mConnThread, "lost the connection thread.");
return mConnThread->Suspend();
} else if (mConnThread) {
return mConnThread->Suspend();
}
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::Resume(void) {
if (mProxyChannel)
nsAutoLock lock(mLock);
if (mProxyChannel) {
return mProxyChannel->Resume();
// if we hit this assert, someone's hanging onto the channel too long.
NS_ASSERTION(mConnThread, "lost the connection thread.");
return mConnThread->Resume();
} else if (mConnThread) {
return mConnThread->Resume();
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
@ -225,7 +226,10 @@ nsFTPChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount,
return mProxyChannel->OpenInputStream(startPosition, readCount, _retval);
}
if (mConnected) return NS_ERROR_ALREADY_CONNECTED;
if (mConnected) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("ERROR nsFTPChannel:OpenInputStream called while connected.\n"));
return NS_ERROR_ALREADY_CONNECTED;
}
// create a pipe. The caller gets the input stream end,
// and the FTP thread get's the output stream end.
@ -237,6 +241,8 @@ nsFTPChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount,
getter_AddRefs(listener));
if (NS_FAILED(rv)) return rv;
mListener = listener; // ensure that we insert ourselves as the proxy listener
///////////////////////////
//// setup channel state
mSourceOffset = startPosition;
@ -244,35 +250,25 @@ 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);
nsFtpConnectionThread *thread = nsnull;
NS_NEWXPCOM(thread, nsFtpConnectionThread);
if (!thread) return NS_ERROR_OUT_OF_MEMORY;
mConnThread = thread;
rv = mConnThread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize);
rv = thread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize);
mHandler = 0;
if (NS_FAILED(rv)) {
NS_RELEASE(mConnThread);
return rv;
}
if (NS_FAILED(rv)) return rv;
rv = mConnThread->SetStreamListener(listener);
if (NS_FAILED(rv)) {
NS_RELEASE(mConnThread);
return rv;
}
rv = thread->SetStreamListener(this, nsnull);
if (NS_FAILED(rv)) return rv;
if (mLoadGroup) {
rv = mLoadGroup->AddChannel(this, nsnull);
if (NS_FAILED(rv)) return rv;
}
rv = mPool->DispatchRequest((nsIRunnable*)mConnThread);
if (NS_FAILED(rv)) return rv;
mConnected = PR_TRUE;
return NS_OK;
return mPool->DispatchRequest((nsIRunnable*)thread);
}
NS_IMETHODIMP
@ -286,44 +282,7 @@ nsFTPChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **_retval
NS_IMETHODIMP
nsFTPChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
nsresult rv;
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::AsyncOpen() called\n"));
mObserver = observer;
if (mProxyChannel) {
return mProxyChannel->AsyncOpen(this, ctxt);
}
if (mConnected) return NS_ERROR_ALREADY_CONNECTED;
////////////////////////////////
//// setup the channel thread
NS_NEWXPCOM(mConnThread, nsFtpConnectionThread);
if (!mConnThread) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mConnThread);
rv = mConnThread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize);
mHandler = 0;
if (NS_FAILED(rv)) {
NS_RELEASE(mConnThread);
return rv;
}
rv = mConnThread->SetStreamObserver(this, ctxt);
if (NS_FAILED(rv)) return rv;
mConnected = PR_TRUE;
mAsyncOpen = PR_TRUE;
if (mLoadGroup) {
rv = mLoadGroup->AddChannel(this, nsnull);
if (NS_FAILED(rv)) return rv;
}
return mPool->DispatchRequest((nsIRunnable*)mConnThread);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
@ -336,6 +295,7 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::AsyncRead() called\n"));
mListener = listener;
mUserContext = ctxt;
if (mEventSink) {
nsAutoString statusMsg("Beginning FTP transaction.");
@ -357,46 +317,28 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
return mProxyChannel->AsyncRead(startPosition, readCount, ctxt, this);
}
if (mAsyncOpen) {
NS_ASSERTION(mConnThread, "FTP: underlying connection thread went away");
// we already initialized the connection thread via a prior call
// to AsyncOpen().
// The connection thread is suspended right now.
// Set our AsyncRead pertinent state and then wake it up.
rv = mConnThread->SetStreamListener(this);
if (NS_FAILED(rv)) return rv;
mConnThread->Resume();
} else {
if (mConnected) return NS_ERROR_ALREADY_CONNECTED;
////////////////////////////////
//// setup the channel thread
NS_NEWXPCOM(mConnThread, nsFtpConnectionThread);
if (!mConnThread) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mConnThread);
rv = mConnThread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize);
mHandler = 0;
if (NS_FAILED(rv)) {
NS_RELEASE(mConnThread);
return rv;
}
rv = mConnThread->SetStreamListener(this, ctxt);
if (NS_FAILED(rv)) {
NS_RELEASE(mConnThread);
return rv;
}
rv = mPool->DispatchRequest((nsIRunnable*)mConnThread);
mConnected = PR_TRUE;
if (mConnected) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("ERROR nsFTPChannel:AsyncRead called while connected.\n"));
return NS_ERROR_ALREADY_CONNECTED;
}
return NS_OK;
////////////////////////////////
//// setup the channel thread
nsFtpConnectionThread *thread = nsnull;
NS_NEWXPCOM(thread, nsFtpConnectionThread);
if (!thread) return NS_ERROR_OUT_OF_MEMORY;
mConnThread = thread;
rv = thread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize);
mHandler = nsnull;
if (NS_FAILED(rv)) return rv;
rv = thread->SetStreamListener(this, ctxt);
if (NS_FAILED(rv)) return rv;
mConnected = PR_TRUE;
return mPool->DispatchRequest((nsIRunnable*)thread);
}
NS_IMETHODIMP
@ -409,45 +351,39 @@ nsFTPChannel::AsyncWrite(nsIInputStream *fromStream,
nsresult rv = NS_OK;
mObserver = observer;
mUserContext = ctxt;
if (mProxyChannel) {
return mProxyChannel->AsyncOpen(this, ctxt);
return mProxyChannel->AsyncWrite(fromStream, startPosition,
writeCount, ctxt, observer);
}
NS_ASSERTION(writeCount > 0, "FTP requires stream len info");
if (writeCount < 1) return NS_ERROR_NOT_INITIALIZED;
NS_NEWXPCOM(mConnThread, nsFtpConnectionThread);
if (!mConnThread) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mConnThread);
nsFtpConnectionThread *thread = nsnull;
NS_NEWXPCOM(thread, nsFtpConnectionThread);
if (!thread) return NS_ERROR_OUT_OF_MEMORY;
mConnThread = thread;
rv = mConnThread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize);
rv = thread->Init(mHandler, this, mBufferSegmentSize, mBufferMaxSize);
mHandler = 0;
if (NS_FAILED(rv)) {
NS_RELEASE(mConnThread);
return rv;
}
if (NS_FAILED(rv)) return rv;
rv = mConnThread->SetWriteStream(fromStream, writeCount);
if (NS_FAILED(rv)) {
NS_RELEASE(mConnThread);
return rv;
}
rv = thread->SetWriteStream(fromStream, writeCount);
if (NS_FAILED(rv)) return rv;
rv = mConnThread->SetStreamObserver(this, ctxt);
if (NS_FAILED(rv))
NS_RELEASE(mConnThread);
rv = thread->SetStreamObserver(this, ctxt);
if (NS_FAILED(rv)) return rv;
if (mLoadGroup) {
rv = mLoadGroup->AddChannel(this, nsnull);
if (NS_FAILED(rv)) return rv;
}
rv = mPool->DispatchRequest((nsIRunnable*)mConnThread);
mConnected = PR_TRUE;
return rv;
return mPool->DispatchRequest((nsIRunnable*)thread);
}
NS_IMETHODIMP
@ -572,16 +508,6 @@ nsFTPChannel::SetContentLength(PRInt32 aLength) {
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::Stopped(nsresult aStatus, const PRUnichar *aMsg) {
nsAutoLock lock(mLock);
// the underlying connection thread has gone away.
mConnected = PR_FALSE;
NS_ASSERTION(mConnThread, "lost the connection thread before Stopped");
NS_RELEASE(mConnThread);
return NS_OK;
}
// nsIInterfaceRequestor method
NS_IMETHODIMP
nsFTPChannel::GetInterface(const nsIID &anIID, void **aResult ) {
@ -623,8 +549,9 @@ nsFTPChannel::OnProgress(nsIChannel* aChannel, nsISupports* aContext,
// nsIStreamObserver methods.
NS_IMETHODIMP
nsFTPChannel::OnStopRequest(nsIChannel* aChannel, nsISupports* aContext,
nsresult aStatus, const PRUnichar* aMsg) {
nsresult aStatus, const PRUnichar* aMsg) {
nsresult rv = NS_OK;
mConnThread = nsnull;
if (mLoadGroup) {
rv = mLoadGroup->RemoveChannel(this, nsnull, aStatus, aMsg);

View File

@ -27,7 +27,7 @@
#include "nsPIFTPChannel.h"
#include "nsIURI.h"
#include "nsString2.h"
#include "nsString.h"
#include "nsILoadGroup.h"
#include "nsCOMPtr.h"
#include "nsIProtocolHandler.h"
@ -85,7 +85,6 @@ protected:
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
PRBool mConnected;
PRBool mAsyncOpen; // was AsyncOpen called
PRUint32 mLoadAttributes;
PRUint32 mSourceOffset;
@ -100,12 +99,13 @@ protected:
nsCOMPtr<nsIProtocolHandler> mHandler;
nsCOMPtr<nsIThreadPool> mPool; // the thread pool we want to use to fire off connections.
nsFtpConnectionThread *mConnThread; // the raw pointer to the thread object.
nsCOMPtr<nsIRequest> mConnThread;
PRUint32 mBufferSegmentSize;
PRUint32 mBufferMaxSize;
nsCOMPtr<nsIChannel> mProxyChannel; // a proxy channel
nsXPIDLCString mHost;
PRLock* mLock;
nsCOMPtr<nsISupports> mUserContext;
};
#endif /* nsFTPChannel_h___ */

View File

@ -21,15 +21,11 @@
*/
#include "nsFtpConnectionThread.h"
#include "nsIEventQueueService.h"
#include "nsIStringStream.h"
#include "nsISocketTransport.h"
#include "nsIPipe.h"
#include "nsIMIMEService.h"
#include "nsIStreamConverterService.h"
#include "prprf.h"
#include "prlog.h"
#include "prmon.h"
#include "netCore.h"
#include "ftpCore.h"
#include "nsProxiedService.h"
@ -38,6 +34,7 @@
#include "nsAsyncEvent.h"
#include "nsIURL.h"
#include "nsEscape.h"
#include "nsNetUtil.h"
#include "nsAppShellCIDs.h" // TODO remove later
#include "nsIAppShellService.h" // TODO remove later
@ -46,12 +43,12 @@
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
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(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
#define FTP_COMMAND_CHANNEL_SEG_SIZE 64
#define FTP_COMMAND_CHANNEL_MAX_SIZE 512
@ -62,12 +59,12 @@ extern PRLogModuleInfo* gFTPLog;
NS_IMPL_THREADSAFE_ADDREF(nsFtpConnectionThread);
NS_IMPL_THREADSAFE_RELEASE(nsFtpConnectionThread);
NS_IMPL_QUERY_INTERFACE3(nsFtpConnectionThread, nsIRunnable, nsIRequest, nsIStreamObserver);
NS_IMPL_QUERY_INTERFACE2(nsFtpConnectionThread, nsIRunnable, nsIRequest);
nsFtpConnectionThread::nsFtpConnectionThread() {
NS_INIT_REFCNT();
// bool init
mAsyncOpened = mConnected = mList = mRetryPass = mCachedConn = mSentStart = PR_FALSE;
mConnected = mList = mRetryPass = mCachedConn = mSentStart = PR_FALSE;
mFireCallbacks = mUsePasv = mBin = mKeepRunning = mAnonymous = PR_TRUE;
mAction = GET;
@ -81,20 +78,13 @@ nsFtpConnectionThread::nsFtpConnectionThread() {
mPort = 21;
mLock = nsnull;
mMonitor = nsnull;
}
nsFtpConnectionThread::~nsFtpConnectionThread() {
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("~nsFtpConnectionThread() called"));
if (mLock) {
PR_DestroyLock(mLock);
mLock = nsnull;
}
if (mMonitor) {
PR_DestroyMonitor(mMonitor);
mMonitor = nsnull;
}
nsXPIDLCString spec;
mURL->GetSpec(getter_Copies(spec));
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("~nsFtpConnectionThread() for %s", (const char*)spec));
if (mLock) PR_DestroyLock(mLock);
}
nsresult
@ -665,10 +655,6 @@ nsFtpConnectionThread::Process() {
break;
}
mNextState = FTP_READ_BUF;
PLEvent *event = nsnull;
if ( NS_FAILED(mFTPEventQueue->WaitForEvent(&event))
|| NS_FAILED(mFTPEventQueue->HandleEvent(event))) return rv;
break;
}
// END: FTP_R_PASV
@ -770,17 +756,9 @@ nsresult
nsFtpConnectionThread::SetStreamObserver(nsIStreamObserver* aObserver, nsISupports *aContext) {
nsresult rv = NS_OK;
if (mConnected) return NS_ERROR_ALREADY_CONNECTED;
if (aObserver) {
mObserverContext = aContext;
NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv);
if(NS_FAILED(rv)) return rv;
rv = pIProxyObjectManager->GetProxyObject(NS_UI_THREAD_EVENTQ,
NS_GET_IID(nsIStreamObserver),
aObserver,
PROXY_ASYNC | PROXY_ALWAYS,
getter_AddRefs(mObserver));
}
NS_ASSERTION(aObserver, "null observer");
mObserver = aObserver;
mObserverContext = aContext;
return rv;
}
@ -1125,12 +1103,6 @@ nsFtpConnectionThread::R_size() {
}
if (mAsyncOpened && mObserver) {
rv = mObserver->OnStartRequest(mChannel, mObserverContext);
if (NS_FAILED(rv)) return FTP_ERROR;
nsAutoCMonitor mon(this);
mon.Wait();
}
return retState;
}
@ -1220,12 +1192,13 @@ nsFtpConnectionThread::S_list() {
mListenerContext);
if (!event) return NS_ERROR_OUT_OF_MEMORY;
mFireCallbacks = PR_FALSE; // listener callbacks will be handled by the transport.
return event->Fire(mUIEventQ);
return event->Fire();
}
FTP_STATE
nsFtpConnectionThread::R_list() {
if ((mResponseCode/100 == 4) || (mResponseCode/100 == 5)) {
mFireCallbacks = PR_TRUE;
return FTP_ERROR;
}
return FTP_READ_BUF;
@ -1249,14 +1222,32 @@ nsFtpConnectionThread::S_retr() {
mListenerContext);
if (!event) return NS_ERROR_OUT_OF_MEMORY;
mFireCallbacks = PR_FALSE; // listener callbacks will be handled by the transport.
return event->Fire(mUIEventQ);
return event->Fire();
}
FTP_STATE
nsFtpConnectionThread::R_retr() {
if (mResponseCode/100 == 1) {
// see if there's another response in this read.
// this can happen if the server sends back two
// responses before we've processed the first one.
PRInt32 loc = -1;
loc = mResponseMsg.FindChar(LF);
if (loc > -1) {
PRInt32 err;
nsCAutoString response;
mResponseMsg.Mid(response, loc, mResponseMsg.Length() - (loc+1));
if (response.Length()) {
PRInt32 code = response.ToInteger(&err);
if (code/100 != 2)
return FTP_ERROR;
else
return FTP_COMPLETE;
}
}
return FTP_READ_BUF;
}
mFireCallbacks = PR_TRUE;
return FTP_ERROR;
}
@ -1282,7 +1273,7 @@ nsFtpConnectionThread::S_stor() {
mObserverContext);
if (!event) return NS_ERROR_OUT_OF_MEMORY;
mFireCallbacks = PR_FALSE; // observer callbacks will be handled by the transport.
return event->Fire(mUIEventQ);
return event->Fire();
}
FTP_STATE
@ -1379,11 +1370,6 @@ nsFtpConnectionThread::R_pasv() {
if (NS_FAILED(sTrans->SetReuseConnection(PR_FALSE))) 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<nsIInterfaceRequestor> progressProxy(do_QueryInterface(mChannel));
rv = mDPipe->SetNotificationCallbacks(progressProxy);
@ -1476,18 +1462,6 @@ NS_IMETHODIMP
nsFtpConnectionThread::Run() {
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->CreateThreadEventQueue();
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mFTPEventQueue));
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(mUIEventQ));
if (NS_FAILED(rv)) return rv;
rv = nsServiceManager::GetService(kSocketTransportServiceCID,
NS_GET_IID(nsISocketTransportService),
getter_AddRefs(mSTS));
@ -1591,18 +1565,6 @@ nsFtpConnectionThread::Resume(void)
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,
@ -1618,9 +1580,6 @@ nsFtpConnectionThread::Init(nsIProtocolHandler* aHandler,
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");
@ -1674,8 +1633,11 @@ nsFtpConnectionThread::Init(nsIProtocolHandler* aHandler,
mCacheKey.SetString(host);
mCacheKey.Append(port);
NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv);
if(NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIEventQueueService, eqs, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue));
if (NS_FAILED(rv)) return rv;
mFTPChannel = do_QueryInterface(aChannel, &rv);
if (NS_FAILED(rv)) return rv;
@ -1693,13 +1655,6 @@ nsFtpConnectionThread::SetWriteStream(nsIInputStream* aInStream, PRUint32 aWrite
return NS_OK;
}
nsresult
nsFtpConnectionThread::SetAsyncOpen(PRBool aAsyncOpen) {
if (mConnected) return NS_ERROR_ALREADY_CONNECTED;
mAsyncOpened = aAsyncOpen;
return NS_OK;
}
nsresult
nsFtpConnectionThread::StopProcessing() {
nsresult rv;
@ -1714,48 +1669,39 @@ nsFtpConnectionThread::StopProcessing() {
rv = MapResultCodeToString(mInternalError, &errorMsg);
if (NS_FAILED(rv)) return rv;
if (mCPipe) (void)mCPipe->Cancel();
if (mDPipe) (void)mDPipe->Cancel();
//if (mCPipe) (void)mCPipe->Cancel();
//if (mDPipe) (void)mDPipe->Cancel();
}
// Release the transports
mCPipe = 0;
mDPipe = 0;
rv = mFTPChannel->Stopped(mInternalError, errorMsg);
if (NS_FAILED(rv)) return rv;
// if we have an observer, end the transaction
if (mAsyncOpened && mObserver) {
rv = mObserver->OnStopRequest(mChannel, mObserverContext, mInternalError, errorMsg);
}
if (mFireCallbacks) {
// we never got to the point that the transport would be
// taking over notifications. we'll handle them our selves.
if (mObserver && !mAsyncOpened) {
rv = mObserver->OnStartRequest(mChannel, mObserverContext);
if (mObserver) {
nsCOMPtr<nsIStreamObserver> asyncObserver;
rv = NS_NewAsyncStreamObserver(mObserver, mEventQueue, getter_AddRefs(asyncObserver));
if(NS_FAILED(rv)) return rv;
rv = asyncObserver->OnStartRequest(mChannel, mObserverContext);
if (NS_FAILED(rv)) return rv;
rv = mObserver->OnStopRequest(mChannel, mObserverContext, mInternalError, errorMsg);
rv = asyncObserver->OnStopRequest(mChannel, mObserverContext, mInternalError, errorMsg);
if (NS_FAILED(rv)) return rv;
}
if (mListener) {
NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv);
nsCOMPtr<nsIStreamListener> asyncListener;
rv = NS_NewAsyncStreamListener(mListener, mEventQueue, getter_AddRefs(asyncListener));
if(NS_FAILED(rv)) return rv;
nsCOMPtr<nsIStreamListener> listener;
rv = pIProxyObjectManager->GetProxyObject(NS_UI_THREAD_EVENTQ,
NS_GET_IID(nsIStreamListener),
mListener,
PROXY_ASYNC | PROXY_ALWAYS,
getter_AddRefs(listener));
rv = asyncListener->OnStartRequest(mChannel, mListenerContext);
if (NS_FAILED(rv)) return rv;
rv = listener->OnStartRequest(mChannel, mListenerContext);
if (NS_FAILED(rv)) return rv;
rv = listener->OnStopRequest(mChannel, mListenerContext, mInternalError, errorMsg);
rv = asyncListener->OnStopRequest(mChannel, mListenerContext, mInternalError, errorMsg);
if (NS_FAILED(rv)) return rv;
}
}

View File

@ -30,9 +30,7 @@
#include "nsIStreamListener.h"
#include "nsIURI.h"
#include "prtime.h"
#include "prmon.h"
#include "nsString2.h"
#include "nsIEventQueue.h"
#include "nsString.h"
#include "nsPIFTPChannel.h"
#include "nsIConnectionCache.h"
#include "nsConnectionCacheObj.h"
@ -42,6 +40,7 @@
#include "nsIBufferInputStream.h"
#include "nsIBufferOutputStream.h"
#include "nsAutoLock.h"
#include "nsIEventQueueService.h"
// ftp server types
#define FTP_GENERIC_TYPE 0
@ -85,13 +84,11 @@ typedef enum _FTP_STATE {
typedef enum _FTP_ACTION { GET, PUT, MKDIR, DEL} FTP_ACTION;
class nsFtpConnectionThread : public nsIRunnable,
public nsIRequest,
public nsIStreamObserver {
public nsIRequest {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSIREQUEST
NS_DECL_NSISTREAMOBSERVER
nsFtpConnectionThread();
virtual ~nsFtpConnectionThread();
@ -110,10 +107,6 @@ public:
// use this to provide a stream to be written to the server.
nsresult SetWriteStream(nsIInputStream* aInStream, PRUint32 aWriteCount);
// use this to indicate that the transaction started w/ AsyncOpen. This
// affects how observers are notified.
nsresult SetAsyncOpen(PRBool aAsyncOpen);
private:
///////////////////////////////////
// BEGIN: STATE METHODS
@ -211,13 +204,13 @@ private:
PRUint32 mBufferSegmentSize;
PRUint32 mBufferMaxSize;
PRLock *mLock;
PRMonitor *mMonitor;
nsCOMPtr<nsIEventQueue>mUIEventQ;
PLEvent *mAsyncReadEvent;
nsCOMPtr<nsIInputStream> mWriteStream; // This stream is written to the server.
PRUint32 mWriteCount; // The amount of data to write to the server.
PRBool mAsyncOpened; // This is set when the consumer wants AsyncOpen info.
PRBool mFireCallbacks; // Fire the listener callbacks.
nsCOMPtr<nsIEventQueue> mEventQueue;
};
#define NS_FTP_BUFFER_READ_SIZE (8*1024)

View File

@ -28,12 +28,12 @@
#include "nsIComponentManager.h"
#include "nsIInterfaceRequestor.h"
#include "nsIProgressEventSink.h"
#include "nsConnectionCacheObj.h"
#include "prlog.h"
#include "nsIProtocolProxyService.h"
#include "nsNetUtil.h"
// For proxification of FTP URLs
#include "nsIHTTPProtocolHandler.h"
#include "nsIHTTPChannel.h"
#include "nsNetUtil.h"
#if defined(PR_LOGGING)
@ -128,9 +128,7 @@ NS_IMETHODIMP
nsFtpProtocolHandler::NewURI(const char *aSpec, nsIURI *aBaseURI,
nsIURI **result)
{
nsresult rv;
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("FTP attempt at %s ", aSpec));
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> url;
nsCOMPtr<nsIURLParser> urlparser;
if (aBaseURI) {
@ -153,14 +151,10 @@ nsFtpProtocolHandler::NewURI(const char *aSpec, nsIURI *aBaseURI,
rv = url->SetSpec((char*)aSpec);
}
if (NS_FAILED(rv)) {
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("FAILED\n"));
return rv;
}
if (NS_FAILED(rv)) return rv;
*result = url.get();
NS_ADDREF(*result);
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("SUCCEEDED\n"));
return rv;
}