зеркало из https://github.com/mozilla/gecko-dev.git
16910, r=mcafee. FTP now uses thread pools. it also provides some status to the webshell. and it no longer uses the server's defualt path.
This commit is contained in:
Родитель
eab20fe1b3
Коммит
b7021722f9
|
@ -18,21 +18,12 @@
|
|||
|
||||
#include "nsIChannel.idl"
|
||||
|
||||
interface nsIStreamListener;
|
||||
interface nsIEventQueue;
|
||||
|
||||
[scriptable, uuid(64718e40-18c2-11d3-9337-00104ba0fd40)]
|
||||
interface nsIFTPChannel : nsIChannel
|
||||
{
|
||||
// PRE connect
|
||||
|
||||
// POST connect
|
||||
|
||||
// Initiate connect
|
||||
void Get();
|
||||
|
||||
void Put();
|
||||
|
||||
void SetStreamListener(in nsIStreamListener aListener);
|
||||
void SetConnectionQueue(in nsIEventQueue aEventQ);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ public:
|
|||
|
||||
mServerType = 0;
|
||||
mList = PR_FALSE;
|
||||
mUseDefaultPath = PR_TRUE;
|
||||
};
|
||||
~nsConnectionCacheObj()
|
||||
{
|
||||
|
@ -61,7 +60,6 @@ public:
|
|||
PRUint32 mServerType; // what kind of server is it.
|
||||
nsCAutoString mCwd; // what dir are we in
|
||||
PRBool mList; // are we sending LIST or NLST
|
||||
PRBool mUseDefaultPath; // do we need to use the default path.
|
||||
};
|
||||
|
||||
#endif // __nsconnectioncacheobj__h____
|
||||
|
|
|
@ -61,12 +61,34 @@ nsFTPChannel::nsFTPChannel() {
|
|||
nsFTPChannel::~nsFTPChannel() {
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsFTPChannel, nsIChannel, nsIFTPChannel, nsIStreamListener, nsIStreamObserver);
|
||||
NS_IMETHODIMP_(nsrefcnt) nsFTPChannel::AddRef(void)
|
||||
{
|
||||
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
|
||||
++mRefCnt;
|
||||
NS_LOG_ADDREF(this, mRefCnt, "nsFTPChannel", sizeof(*this));
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt) nsFTPChannel::Release(void)
|
||||
{
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||
--mRefCnt;
|
||||
NS_LOG_RELEASE(this, mRefCnt, "nsFTPChannel");
|
||||
if (mRefCnt == 0) {
|
||||
mRefCnt = 1; /* stabilize */
|
||||
NS_DELETEXPCOM(this);
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
NS_IMPL_QUERY_INTERFACE4(nsFTPChannel, nsIChannel, nsIFTPChannel, nsIStreamListener, nsIStreamObserver);
|
||||
|
||||
//NS_IMPL_ISUPPORTS4(nsFTPChannel, nsIChannel, nsIFTPChannel, nsIStreamListener, nsIStreamObserver);
|
||||
|
||||
nsresult
|
||||
nsFTPChannel::Init(const char* verb, nsIURI* uri, nsILoadGroup *aGroup,
|
||||
nsIEventSinkGetter* getter, nsIURI* originalURI,
|
||||
nsIProtocolHandler* aHandler)
|
||||
nsIProtocolHandler* aHandler, nsIThreadPool* aPool)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
@ -75,13 +97,19 @@ nsFTPChannel::Init(const char* verb, nsIURI* uri, nsILoadGroup *aGroup,
|
|||
|
||||
mHandler = aHandler;
|
||||
|
||||
NS_ASSERTION(aPool, "FTP channel needs a thread pool to play in");
|
||||
if (!aPool) return NS_ERROR_NULL_POINTER;
|
||||
mPool = aPool;
|
||||
|
||||
mOriginalURI = originalURI ? originalURI : uri;
|
||||
mURL = uri;
|
||||
|
||||
mLoadGroup = aGroup;
|
||||
|
||||
if (getter) {
|
||||
rv = getter->GetEventSink(verb, NS_GET_IID(nsIProgressEventSink),
|
||||
mEventSinkGetter = getter;
|
||||
|
||||
if (mEventSinkGetter) {
|
||||
rv = mEventSinkGetter->GetEventSink(verb, NS_GET_IID(nsIProgressEventSink),
|
||||
(nsISupports**)(nsIProgressEventSink**)getter_AddRefs(mEventSink));
|
||||
if (NS_FAILED(rv)) {
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::Init() (couldn't find event sink)\n"));
|
||||
|
@ -96,28 +124,6 @@ nsFTPChannel::Init(const char* verb, nsIURI* uri, nsILoadGroup *aGroup,
|
|||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), getter_AddRefs(mEventQueue));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// go ahead and create the thread for the connection.
|
||||
// we'll init it and kick it off later
|
||||
rv = NS_NewThread(getter_AddRefs(mConnectionThread));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// we'll create the FTP connection's event queue here, on this thread.
|
||||
// it will be passed to the FTP connection upon FTP connection
|
||||
// initialization. at that point it's up to the FTP conn thread to
|
||||
// turn the crank on it.
|
||||
#if 1
|
||||
PRThread *thread; // does not need deleting
|
||||
rv = mConnectionThread->GetPRThread(&thread);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PLEventQueue* PLEventQ = PL_CreateEventQueue("FTP thread", thread);
|
||||
if (!PLEventQ) return rv;
|
||||
|
||||
rv = eventQService->CreateFromPLEventQueue(PLEventQ, getter_AddRefs(mConnectionEventQueue));
|
||||
#else
|
||||
rv = eventQService->CreateFromIThread(mConnectionThread, getter_AddRefs(mConnectionEventQueue));
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -152,8 +158,8 @@ NS_IMETHODIMP
|
|||
nsFTPChannel::Cancel(void)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (mThreadRequest)
|
||||
rv = mThreadRequest->Cancel();
|
||||
if (mProxiedThreadRequest)
|
||||
rv = mProxiedThreadRequest->Cancel();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -161,8 +167,8 @@ NS_IMETHODIMP
|
|||
nsFTPChannel::Suspend(void)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (mThreadRequest)
|
||||
rv = mThreadRequest->Suspend();
|
||||
if (mProxiedThreadRequest)
|
||||
rv = mProxiedThreadRequest->Suspend();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -170,8 +176,8 @@ NS_IMETHODIMP
|
|||
nsFTPChannel::Resume(void)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (mThreadRequest)
|
||||
rv = mThreadRequest->Resume();
|
||||
if (mProxiedThreadRequest)
|
||||
rv = mProxiedThreadRequest->Resume();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -200,40 +206,6 @@ NS_IMETHODIMP
|
|||
nsFTPChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount,
|
||||
nsIInputStream **_retval)
|
||||
{
|
||||
#if 0
|
||||
// The ftp channel will act as the listener which will receive
|
||||
// events from the ftp connection thread. It then uses a syncstreamlistener
|
||||
// as it's mListener which receives the listener notifications and writes
|
||||
// data down the output stream end of a pipe.
|
||||
nsresult rv;
|
||||
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::OpenInputStream() called\n"));
|
||||
|
||||
rv = serv->NewSyncStreamListener(_retval /* nsIInputStream **inStream */,
|
||||
&mBufferOutputStream /* nsIBufferOutputStream **outStream */,
|
||||
&mListener/* nsIStreamListener **listener */);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mSourceOffset = startPosition;
|
||||
mAmount = readCount;
|
||||
|
||||
////////////////////////////////
|
||||
//// setup the channel thread
|
||||
|
||||
nsIThread* workerThread = nsnull;
|
||||
nsFtpConnectionThread* protocolInterpreter =
|
||||
new nsFtpConnectionThread(mEventQueue, this, this, nsnull);
|
||||
if (!protocolInterpreter)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
protocolInterpreter->Init(mURL);
|
||||
protocolInterpreter->SetUsePasv(PR_TRUE);
|
||||
|
||||
rv = NS_NewThread(&workerThread, protocolInterpreter);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
#endif // 0
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -258,17 +230,24 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
|
|||
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::AsyncRead() called\n"));
|
||||
|
||||
if (mEventSink) {
|
||||
nsAutoString statusMsg("Beginning FTP transaction.");
|
||||
#ifndef BUG_16273_FIXED //TODO
|
||||
rv = mEventSink->OnStatus(this, ctxt, statusMsg.ToNewUnicode());
|
||||
#else
|
||||
rv = mEventSink->OnStatus(this, ctxt, statusMsg.GetUnicode());
|
||||
#endif
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
//// setup channel state
|
||||
|
||||
// XXX we should be using these. esp. for FTP restart.
|
||||
mSourceOffset = startPosition;
|
||||
mAmount = readCount;
|
||||
|
||||
mContext = ctxt;
|
||||
|
||||
mListener = listener;
|
||||
|
||||
mSourceOffset = startPosition;
|
||||
mAmount = readCount;
|
||||
|
||||
|
@ -279,39 +258,19 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
|
|||
if (!protocolInterpreter) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(protocolInterpreter);
|
||||
|
||||
rv = protocolInterpreter->Init(mConnectionEventQueue, /* FTP thread queue */
|
||||
mURL, /* url to load */
|
||||
mThreadRequest = do_QueryInterface((nsISupports*)(nsIRequest*)protocolInterpreter, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = protocolInterpreter->Init(mURL, /* url to load */
|
||||
mEventQueue, /* event queue for this thread */
|
||||
mHandler,
|
||||
this, ctxt);
|
||||
this, ctxt, mEventSinkGetter);
|
||||
mHandler = 0; // XXX this can go away when the channel is no longer being leaked.
|
||||
if (NS_FAILED(rv)) return 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;
|
||||
rv = mPool->DispatchRequest((nsIRunnable*)protocolInterpreter);
|
||||
|
||||
rv = proxyManager->GetProxyObject(mConnectionEventQueue,
|
||||
NS_GET_IID(nsIRequest),
|
||||
(nsISupports*)(nsIRequest*)protocolInterpreter,
|
||||
PROXY_SYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(mThreadRequest));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mConnectionThread->Init((nsIRunnable*)protocolInterpreter,
|
||||
0, /* stack size */
|
||||
PR_PRIORITY_NORMAL,
|
||||
PR_GLOBAL_THREAD,
|
||||
PR_UNJOINABLE_THREAD);
|
||||
|
||||
// this extra release is a result of a discussion with
|
||||
// dougt. GetProxyObject is doing an extra addref. dougt
|
||||
// can best explain why. If this is suddenly an *extra*
|
||||
// release, yank it.
|
||||
NS_RELEASE2(protocolInterpreter, rv);
|
||||
NS_RELEASE(protocolInterpreter);
|
||||
mConnectionThread = 0; // this is necessary because there is a circular dependency
|
||||
// between the FTPChannel and the connection thread.
|
||||
// we need to ditch our ref to the connection thread asap.
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mConnected = PR_TRUE;
|
||||
|
@ -424,20 +383,22 @@ nsFTPChannel::SetOwner(nsISupports * aOwner)
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIFTPChannel methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFTPChannel::Get(void) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
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;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFTPChannel::Put(void) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
// 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;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFTPChannel::SetStreamListener(nsIStreamListener *aListener) {
|
||||
mListener = aListener;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -446,6 +407,7 @@ nsFTPChannel::SetStreamListener(nsIStreamListener *aListener) {
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsFTPChannel::OnStartRequest(nsIChannel* channel, nsISupports* context) {
|
||||
//MOZ_TIMER_START(channelTime, "nsFTPChannel::OnStart(): hit.");
|
||||
nsresult rv = NS_OK;
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::OnStartRequest(channel = %x, context = %x)\n", channel, context));
|
||||
if (mListener) {
|
||||
|
@ -459,6 +421,15 @@ nsFTPChannel::OnStopRequest(nsIChannel* channel, nsISupports* context,
|
|||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
nsresult rv = NS_OK;
|
||||
if (mEventSink) {
|
||||
nsAutoString statusMsg("FTP transaction complete.");
|
||||
#ifndef BUG_16273_FIXED //TODO
|
||||
rv = mEventSink->OnStatus(this, context, statusMsg.ToNewUnicode());
|
||||
#else
|
||||
rv = mEventSink->OnStatus(this, context, statusMsg.GetUnicode());
|
||||
#endif
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::OnStopRequest(channel = %x, context = %x, status = %d, msg = N/A)\n",channel, context, aStatus));
|
||||
if (mListener) {
|
||||
rv = mListener->OnStopRequest(channel, mContext, aStatus, aMsg);
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include "nsIFTPChannel.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsString2.h"
|
||||
#include "nsIEventQueue.h"
|
||||
|
@ -32,6 +31,8 @@
|
|||
#include "nsHashtable.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIEventSinkGetter.h"
|
||||
#include "nsIThreadPool.h"
|
||||
|
||||
class nsIEventSinkGetter;
|
||||
class nsIProgressEventSink;
|
||||
|
@ -59,13 +60,14 @@ public:
|
|||
// join() it on shutdown.
|
||||
nsresult Init(const char* verb, nsIURI* uri, nsILoadGroup *aGroup,
|
||||
nsIEventSinkGetter* getter, nsIURI* originalURI,
|
||||
nsIProtocolHandler* aHandler);
|
||||
nsIProtocolHandler* aHandler, nsIThreadPool* aPool);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
nsCOMPtr<nsIURI> mURL;
|
||||
nsCOMPtr<nsIEventQueue> mEventQueue;
|
||||
nsCOMPtr<nsIProgressEventSink> mEventSink;
|
||||
nsCOMPtr<nsIEventSinkGetter> mEventSinkGetter;
|
||||
|
||||
PRBool mConnected;
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
|
@ -78,11 +80,11 @@ protected:
|
|||
nsAutoString mContentType;
|
||||
PRInt32 mContentLength;
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsCOMPtr<nsIThread> mConnectionThread; // the thread for this connection.
|
||||
|
||||
nsCOMPtr<nsIEventQueue> mConnectionEventQueue;
|
||||
nsCOMPtr<nsIRequest> mThreadRequest; // the nsIRequest proxy object.
|
||||
nsCOMPtr<nsIRequest> mThreadRequest;
|
||||
nsCOMPtr<nsIRequest> mProxiedThreadRequest;
|
||||
nsCOMPtr<nsIProtocolHandler> mHandler;
|
||||
nsCOMPtr<nsIThreadPool> mPool; // the thread pool we want to use to fire off connections.
|
||||
};
|
||||
|
||||
#define NS_FTP_SEGMENT_SIZE (4*1024)
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "nsProxiedService.h"
|
||||
#include "nsINetSupportDialogService.h"
|
||||
#include "nsFtpProtocolHandler.h"
|
||||
#include "nsIFTPChannel.h"
|
||||
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
|
||||
|
@ -104,8 +105,28 @@ NS_IMPL_ISUPPORTS(nsFTPContext, kIFTPContextIID);
|
|||
|
||||
|
||||
// BEGIN: nsFtpConnectionThread implementation
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsFtpConnectionThread, nsIRunnable, nsIRequest);
|
||||
NS_IMETHODIMP_(nsrefcnt) nsFtpConnectionThread::AddRef(void)
|
||||
{
|
||||
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
|
||||
++mRefCnt;
|
||||
NS_LOG_ADDREF(this, mRefCnt, "nsFtpConnectionThread", sizeof(*this));
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt) nsFtpConnectionThread::Release(void)
|
||||
{
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||
--mRefCnt;
|
||||
NS_LOG_RELEASE(this, mRefCnt, "nsFtpConnectionThread");
|
||||
if (mRefCnt == 0) {
|
||||
mRefCnt = 1; /* stabilize */
|
||||
NS_DELETEXPCOM(this);
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
NS_IMPL_QUERY_INTERFACE2(nsFtpConnectionThread, nsIRunnable, nsIRequest);
|
||||
//NS_IMPL_ISUPPORTS2(nsFtpConnectionThread, nsIRunnable, nsIRequest);
|
||||
|
||||
nsFtpConnectionThread::nsFtpConnectionThread() {
|
||||
NS_INIT_REFCNT();
|
||||
|
@ -119,7 +140,6 @@ nsFtpConnectionThread::nsFtpConnectionThread() {
|
|||
mResetMode = PR_FALSE;
|
||||
mList = PR_FALSE;
|
||||
mKeepRunning = PR_TRUE;
|
||||
mUseDefaultPath = PR_FALSE;
|
||||
mContinueRead = PR_FALSE;
|
||||
mAnonymous = PR_TRUE;
|
||||
mRetryPass = PR_FALSE;
|
||||
|
@ -253,7 +273,6 @@ nsFtpConnectionThread::Process() {
|
|||
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;
|
||||
mConn->mUseDefaultPath = mUseDefaultPath;
|
||||
rv = mConnCache->InsertConn(mCacheKey.GetBuffer(), mConn);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
@ -866,12 +885,11 @@ nsFtpConnectionThread::R_syst() {
|
|||
|
||||
SetSystInternals(); // must be called first to setup member vars.
|
||||
|
||||
if (!mUseDefaultPath)
|
||||
state = FindActionState();
|
||||
|
||||
// setup next state based on server type.
|
||||
if (mServerType == FTP_PETER_LEWIS_TYPE || mServerType == FTP_WEBSTAR_TYPE)
|
||||
state = FTP_S_MACB;
|
||||
else
|
||||
state = FindActionState();
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -932,7 +950,6 @@ nsFtpConnectionThread::S_pwd() {
|
|||
|
||||
FTP_STATE
|
||||
nsFtpConnectionThread::R_pwd() {
|
||||
nsresult rv;
|
||||
FTP_STATE state = FTP_ERROR;
|
||||
nsCAutoString lNewMsg(mResponseMsg);
|
||||
// fun response interpretation begins :)
|
||||
|
@ -971,53 +988,6 @@ nsFtpConnectionThread::R_pwd() {
|
|||
}
|
||||
}
|
||||
|
||||
// we only want to use the parent working directory (pwd) when
|
||||
// the url supplied provides ambiguous path info (such as /./, or
|
||||
// no slash at all.
|
||||
|
||||
if (mUseDefaultPath && mServerType != FTP_VMS_TYPE) {
|
||||
mUseDefaultPath = PR_FALSE;
|
||||
// we want to use the default path specified by the PWD command.
|
||||
nsCAutoString ptr;
|
||||
|
||||
if (lNewMsg.First() != '/') {
|
||||
PRInt32 start = lNewMsg.FindChar('/');
|
||||
if (start > -1) {
|
||||
lNewMsg.Right(ptr, start); // use everything after the first slash (inclusive)
|
||||
} else {
|
||||
// if we couldn't find a slash, check for back slashes and switch them out.
|
||||
start = lNewMsg.FindChar('\\');
|
||||
if (start > -1) {
|
||||
lNewMsg.ReplaceChar("\\", '/');
|
||||
}
|
||||
ptr = lNewMsg;
|
||||
}
|
||||
} else {
|
||||
ptr = lNewMsg;
|
||||
}
|
||||
|
||||
// construct the new url by appending
|
||||
// the initial path to the new path.
|
||||
if (ptr.Length()) {
|
||||
|
||||
nsXPIDLCString initialPath;
|
||||
rv = mURL->GetPath(getter_Copies(initialPath));
|
||||
if (NS_FAILED(rv)) return FTP_ERROR;
|
||||
|
||||
if (ptr.Last() == '/') {
|
||||
PRUint32 insertionOffset = ptr.Length() - 1;
|
||||
ptr.Cut(insertionOffset, 1);
|
||||
ptr.Insert(initialPath, insertionOffset);
|
||||
} else {
|
||||
ptr.Append(initialPath);
|
||||
}
|
||||
|
||||
const char *p = ptr.GetBuffer();
|
||||
rv = mURL->SetPath(p);
|
||||
if (NS_FAILED(rv)) return FTP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// change state for these servers.
|
||||
if (mServerType == FTP_GENERIC_TYPE
|
||||
|| mServerType == FTP_NCSA_TYPE
|
||||
|
@ -1280,7 +1250,8 @@ nsFtpConnectionThread::R_list() {
|
|||
|
||||
rv = StreamConvService->AsyncConvertData(fromStr.GetUnicode(),
|
||||
toStr.GetUnicode(),
|
||||
mSyncListener, mURL, getter_AddRefs(converterListener));
|
||||
mSyncListener,
|
||||
mURL, getter_AddRefs(converterListener));
|
||||
if (NS_FAILED(rv)) {
|
||||
return FTP_ERROR;
|
||||
}
|
||||
|
@ -1511,7 +1482,9 @@ nsFtpConnectionThread::R_pasv() {
|
|||
nsAllocator::Free(response);
|
||||
|
||||
// now we know where to connect our data channel
|
||||
rv = mSTS->CreateTransport(host.GetBuffer(), port, nsnull, getter_AddRefs(mDPipe)); // the data channel
|
||||
rv = mSTS->CreateTransport(host.GetBuffer(), port,
|
||||
nsnull, /* don't push the event sink getter through for the data channel */
|
||||
getter_AddRefs(mDPipe)); // the data channel
|
||||
if (NS_FAILED(rv)) return FTP_ERROR;
|
||||
|
||||
if (mAction == GET) {
|
||||
|
@ -1635,7 +1608,33 @@ nsFtpConnectionThread::R_mkdir() {
|
|||
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(PR_GetCurrentThread(), 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<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(mFTPEventQueue);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
rv = nsServiceManager::GetService(kSocketTransportServiceCID,
|
||||
NS_GET_IID(nsISocketTransportService),
|
||||
(nsISupports **)&mSTS);
|
||||
|
@ -1666,10 +1665,9 @@ nsFtpConnectionThread::Run() {
|
|||
mServerType = mConn->mServerType;
|
||||
mCwd = mConn->mCwd;
|
||||
mList = mConn->mList;
|
||||
mUseDefaultPath = mConn->mUseDefaultPath;
|
||||
} else {
|
||||
// build our own
|
||||
rv = mSTS->CreateTransport(host, port, nsnull, getter_AddRefs(mCPipe)); // the command channel
|
||||
rv = mSTS->CreateTransport(host, port, mEventSinkGetter, getter_AddRefs(mCPipe)); // the command channel
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// get the output stream so we can write to the server
|
||||
|
@ -1753,6 +1751,10 @@ nsFtpConnectionThread::Run() {
|
|||
mConnected = PR_TRUE;
|
||||
|
||||
rv = Process();
|
||||
mListener = 0;
|
||||
mSyncListener = 0;
|
||||
mChannel = 0;
|
||||
mConnCache = 0;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -1822,43 +1824,52 @@ nsFtpConnectionThread::Resume(void)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsFtpConnectionThread::Init(nsIEventQueue* aFTPEventQ,
|
||||
nsIURI* aUrl,
|
||||
nsFtpConnectionThread::Init(nsIURI* aUrl,
|
||||
nsIEventQueue* aEventQ,
|
||||
nsIProtocolHandler* aHandler,
|
||||
nsIChannel* aChannel,
|
||||
nsISupports* aContext) {
|
||||
nsISupports* aContext,
|
||||
nsIEventSinkGetter* aEventSinkGetter) {
|
||||
nsresult rv;
|
||||
|
||||
NS_ASSERTION(aFTPEventQ, "FTP: thread needs an event queue to process");
|
||||
mFTPEventQueue = aFTPEventQ;
|
||||
|
||||
NS_ASSERTION(aChannel, "FTP: thread needs a channel");
|
||||
|
||||
mOutsideEventQueue = aEventQ;
|
||||
mEventSinkGetter = aEventSinkGetter;
|
||||
|
||||
NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv);
|
||||
if(NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = pIProxyObjectManager->GetProxyObject(aEventQ,
|
||||
rv = pIProxyObjectManager->GetProxyObject(mOutsideEventQueue,
|
||||
NS_GET_IID(nsIStreamListener),
|
||||
aChannel,
|
||||
PROXY_ASYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(mListener));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = pIProxyObjectManager->GetProxyObject(aEventQ,
|
||||
rv = pIProxyObjectManager->GetProxyObject(mOutsideEventQueue,
|
||||
NS_GET_IID(nsIStreamListener),
|
||||
aChannel,
|
||||
PROXY_SYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(mSyncListener));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = pIProxyObjectManager->GetProxyObject(aEventQ,
|
||||
rv = pIProxyObjectManager->GetProxyObject(mOutsideEventQueue,
|
||||
NS_GET_IID(nsIChannel),
|
||||
aChannel,
|
||||
PROXY_SYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(mChannel));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// get a proxied ptr to the FTP protocol handler service so we can control
|
||||
// the connection cache from here.
|
||||
rv = pIProxyObjectManager->GetProxyObject(nsnull,
|
||||
NS_GET_IID(nsIConnectionCache),
|
||||
aHandler,
|
||||
PROXY_SYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(mConnCache));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mContext = aContext;
|
||||
mURL = aUrl;
|
||||
|
||||
|
@ -1904,24 +1915,6 @@ nsFtpConnectionThread::Init(nsIEventQueue* aFTPEventQ,
|
|||
getter_AddRefs(mConnCache));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX this entire check can probably go away.
|
||||
// figure out whether or not we want to use the default path supplied by the server.
|
||||
// we want to do this when there's some ambiguity in our path.
|
||||
nsXPIDLCString path;
|
||||
rv = mURL->GetPath(getter_Copies(path));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (!path || !*path || !PL_strncmp(path, "/.", 2) ) {
|
||||
// scoot past the '/.'
|
||||
char *newPath = nsCRT::strdup((const char*)path+2);
|
||||
if (!newPath) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
rv = mURL->SetPath(newPath);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mUseDefaultPath = PR_TRUE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "nsIRunnable.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsISocketTransportService.h"
|
||||
#include "nsIEventSinkGetter.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIOutputStream.h"
|
||||
|
@ -124,17 +125,16 @@ public:
|
|||
nsFtpConnectionThread();
|
||||
virtual ~nsFtpConnectionThread();
|
||||
|
||||
nsresult Init(nsIEventQueue* aFTPEventQ,
|
||||
nsIURI* aUrl,
|
||||
nsresult Init(nsIURI* aUrl,
|
||||
nsIEventQueue* aEventQ,
|
||||
nsIProtocolHandler* aHandler,
|
||||
nsIChannel* channel,
|
||||
nsISupports* ctxt);
|
||||
nsISupports* ctxt,
|
||||
nsIEventSinkGetter* aEventSink);
|
||||
nsresult Process();
|
||||
|
||||
// user level setup
|
||||
nsresult SetAction(FTP_ACTION aAction);
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////
|
||||
|
@ -187,6 +187,7 @@ private:
|
|||
// Private members
|
||||
|
||||
nsCOMPtr<nsIEventQueue> mFTPEventQueue; // the eventq for this thread.
|
||||
nsCOMPtr<nsIEventQueue> mOutsideEventQueue; // the eventq for the using thread.
|
||||
nsCOMPtr<nsIURI> mURL;
|
||||
|
||||
FTP_STATE mState; // the current state
|
||||
|
@ -223,7 +224,6 @@ private:
|
|||
nsCAutoString mCacheKey; // the key into the cache hash.
|
||||
|
||||
PRBool mConnected;
|
||||
PRBool mUseDefaultPath; // use PWD to figure out path
|
||||
PRBool mUsePasv; // use a passive data connection.
|
||||
PRBool mDirectory; // this url is a directory
|
||||
PRBool mBin; // transfer mode (ascii or binary)
|
||||
|
@ -248,6 +248,7 @@ private:
|
|||
|
||||
nsString2 mContentType; // the content type of the data we're dealing w/.
|
||||
nsXPIDLCString mURLSpec;
|
||||
nsCOMPtr<nsIEventSinkGetter> mEventSinkGetter;
|
||||
};
|
||||
|
||||
#define NS_FTP_BUFFER_READ_SIZE (8*1024)
|
||||
|
|
|
@ -50,6 +50,9 @@ static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
|
|||
nsFtpProtocolHandler::nsFtpProtocolHandler() {
|
||||
NS_INIT_REFCNT();
|
||||
NS_NEWXPCOM(mRootConnectionList, nsHashtable);
|
||||
NS_NewThreadPool(getter_AddRefs(mPool), NS_FTP_CONNECTION_COUNT,
|
||||
NS_FTP_CONNECTION_COUNT,
|
||||
NS_FTP_CONNECTION_STACK_SIZE);
|
||||
}
|
||||
|
||||
// cleans up a connection list entry
|
||||
|
@ -64,7 +67,30 @@ nsFtpProtocolHandler::~nsFtpProtocolHandler() {
|
|||
NS_DELETEXPCOM(mRootConnectionList);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsFtpProtocolHandler, nsIProtocolHandler, nsIConnectionCache);
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt) nsFtpProtocolHandler::AddRef(void)
|
||||
{
|
||||
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
|
||||
++mRefCnt;
|
||||
NS_LOG_ADDREF(this, mRefCnt, "nsFtpProtocolHandler", sizeof(*this));
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt) nsFtpProtocolHandler::Release(void)
|
||||
{
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||
--mRefCnt;
|
||||
NS_LOG_RELEASE(this, mRefCnt, "nsFtpProtocolHandler");
|
||||
if (mRefCnt == 0) {
|
||||
mRefCnt = 1; /* stabilize */
|
||||
NS_DELETEXPCOM(this);
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE2(nsFtpProtocolHandler, nsIProtocolHandler, nsIConnectionCache);
|
||||
//NS_IMPL_ISUPPORTS2(nsFtpProtocolHandler, nsIProtocolHandler, nsIConnectionCache);
|
||||
|
||||
NS_METHOD
|
||||
nsFtpProtocolHandler::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
|
||||
|
@ -181,7 +207,7 @@ nsFtpProtocolHandler::NewChannel(const char* verb, nsIURI* url,
|
|||
rv = nsFTPChannel::Create(nsnull, NS_GET_IID(nsIFTPChannel), (void**)&channel);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = channel->Init(verb, url, aGroup, eventSinkGetter, originalURI, this);
|
||||
rv = channel->Init(verb, url, aGroup, eventSinkGetter, originalURI, this, mPool);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(channel);
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFtpProtocolHandler::NewChannel() FAILED\n"));
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "nsVoidArray.h"
|
||||
#include "nsIConnectionCache.h"
|
||||
#include "nsConnectionCacheObj.h"
|
||||
#include "nsIThreadPool.h"
|
||||
|
||||
// {25029490-F132-11d2-9588-00805F369F95}
|
||||
#define NS_FTPPROTOCOLHANDLER_CID \
|
||||
|
@ -52,6 +53,10 @@ public:
|
|||
protected:
|
||||
nsISupports* mEventSinkGetter;
|
||||
nsHashtable* mRootConnectionList; // hash of FTP connections
|
||||
nsCOMPtr<nsIThreadPool> mPool; // thread pool for FTP connections
|
||||
};
|
||||
|
||||
#define NS_FTP_CONNECTION_COUNT 6
|
||||
#define NS_FTP_CONNECTION_STACK_SIZE (64 * 1024)
|
||||
|
||||
#endif /* nsFtpProtocolHandler_h___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче