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:
valeski%netscape.com 1999-11-02 04:04:23 +00:00
Родитель eab20fe1b3
Коммит b7021722f9
8 изменённых файлов: 205 добавлений и 218 удалений

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

@ -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___ */