21723, a=chofmann, r=rpotts. landing new FTP implementation. It's now much leaner on event processing, and no longer buffers data between the socket transport and consumer. This change went in in order to unblock the xpinstall guys on a UI thread starvation problem

This commit is contained in:
valeski%netscape.com 1999-12-15 03:35:15 +00:00
parent e51a9fb7c2
commit 2c8ae74076
10 changed files with 450 additions and 945 deletions

View File

@ -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);

View File

@ -35,6 +35,7 @@ CPPSRCS = \
nsFTPChannel.cpp \
nsFtpConnectionThread.cpp \
nsFtpModule.cpp \
nsFTPListener.cpp \
$(NULL)
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)

View File

@ -36,6 +36,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsFTPChannel.obj \
.\$(OBJDIR)\nsFtpConnectionThread.obj \
.\$(OBJDIR)\nsFtpModule.obj \
.\$(OBJDIR)\nsFTPListener.obj \
$(NULL)
LLIBS= \

View File

@ -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<nsIBufferOutputStream> bufOutStream;
nsCOMPtr<nsIBufferInputStream> bufInStream;
rv = NS_NewPipe(getter_AddRefs(bufInStream), getter_AddRefs(bufOutStream),
nsnull, NS_FTP_SEGMENT_SIZE, NS_FTP_BUFFER_SIZE);
nsCOMPtr<nsIBufferOutputStream> bufOutStream; // we don't use this piece
nsCOMPtr<nsIStreamListener> 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);

View File

@ -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<nsILoadGroup> mLoadGroup;
nsAutoString mContentType;
nsCAutoString mContentType;
PRInt32 mContentLength;
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsIRequest> mThreadRequest;
nsCOMPtr<nsIRequest> mProxiedThreadRequest;
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.

File diff suppressed because it is too large Load Diff

View File

@ -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<nsIEventQueue> mFTPEventQueue; // the eventq for this thread.
nsCOMPtr<nsIURI> 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<nsIChannel> mCPipe; // the command channel transport
nsCOMPtr<nsIChannel> mDPipe; // the data channel transport
nsCOMPtr<nsIOutputStream> mCOutStream; // command channel output
nsCOMPtr<nsIInputStream> mCInStream; // command channel input
nsCOMPtr<nsIOutputStream> mDOutStream; // data channel output
nsCOMPtr<nsIInputStream> 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<nsIEventQueue> 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<nsISocketTransportService> mSTS; // the socket transport service
nsCOMPtr<nsIChannel> mCPipe; // the command channel transport
nsCOMPtr<nsIChannel> mDPipe; // the data channel transport
nsCOMPtr<nsIOutputStream> mCOutStream; // command channel output
nsCOMPtr<nsIInputStream> mCInStream; // command channel input
nsCAutoString mCacheKey; // the key into the cache hash.
// ****** consumer vars
nsCOMPtr<nsIStreamListener> mListener; // the consumer of our read events
nsCOMPtr<nsISupports> mListenerContext; // the context we pass through our read events
nsCOMPtr<nsIStreamObserver> mObserver; // the consumer of our open events
nsCOMPtr<nsISupports> mObserverContext; // the context we pass through our open events
nsCOMPtr<nsIChannel> 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<nsIConnectionCache> mConnCache;// the nsISupports proxy ptr to our connection cache
nsConnectionCacheObj *mConn; // The cached connection.
nsCOMPtr<nsIStreamListener> mListener; // the listener we want to call
// during our event firing.
nsCOMPtr<nsIStreamListener> mSyncListener; // a syncronous version of our listener
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<nsIConnectionCache> 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<nsPIFTPChannel> mFTPChannel;
// ****** URI vars
nsCOMPtr<nsIURI> 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<nsIBufferInputStream> mBufInStream;
nsCOMPtr<nsIBufferOutputStream> mBufOutStream;
nsCOMPtr<nsIBufferOutputStream> mCallerOutputStream;
nsCOMPtr<nsIStreamObserver> mObserver;
nsCOMPtr<nsISupports> 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<nsPIFTPChannel> mFTPChannel;// used to synchronize w/ our owning channel.
PRUint32 mBufferSegmentSize;
PRUint32 mBufferMaxSize;
PRLock *mLock;
PRMonitor *mMonitor;
nsCOMPtr<nsIEventQueue>mUIEventQ;
PLEvent *mAsyncReadEvent;
};
#define NS_FTP_BUFFER_READ_SIZE (8*1024)

View File

@ -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<nsIGenericFactory> 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<nsIGenericFactory> 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)

View File

@ -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;
}

View File

@ -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<nsIThreadPool> mPool; // thread pool for FTP connections
nsHashtable* mRootConnectionList; // hash of FTP connections
nsCOMPtr<nsIThreadPool> 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___ */