mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
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:
parent
e51a9fb7c2
commit
2c8ae74076
@ -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);
|
||||
|
@ -35,6 +35,7 @@ CPPSRCS = \
|
||||
nsFTPChannel.cpp \
|
||||
nsFtpConnectionThread.cpp \
|
||||
nsFtpModule.cpp \
|
||||
nsFTPListener.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
|
||||
|
@ -36,6 +36,7 @@ CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsFTPChannel.obj \
|
||||
.\$(OBJDIR)\nsFtpConnectionThread.obj \
|
||||
.\$(OBJDIR)\nsFtpModule.obj \
|
||||
.\$(OBJDIR)\nsFTPListener.obj \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
@ -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)
|
||||
|
@ -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)
|
@ -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;
|
||||
}
|
||||
|
@ -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___ */
|
||||
|
Loading…
Reference in New Issue
Block a user