stripped out the stream listener support (and thus the async state machine) from nsFtpProtocolConnection. nsFtpConnectionThread class now takes on the listener notification.

added nsFtpStreamListenerEvent (cpp|h) which declares the events used to push data back across the thread boundry.
This commit is contained in:
valeski%netscape.com 1999-04-22 17:58:42 +00:00
Родитель 2fcc9b1a59
Коммит 2ebae55f56
7 изменённых файлов: 428 добавлений и 434 удалений

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

@ -26,6 +26,8 @@ LCFLAGS = -DWIN32_LEAN_AND_MEAN -D_IMPL_NS_NET
CPP_OBJS = \
.\$(OBJDIR)\nsFtpProtocolHandler.obj \
.\$(OBJDIR)\nsFtpProtocolConnection.obj \
.\$(OBJDIR)\nsFtpStreamListenerEvent.obj \
.\$(OBJDIR)\nsFtpConnectionThread.obj \
.\$(OBJDIR)\nsFtpFactory.obj \
$(NULL)

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

@ -17,16 +17,50 @@
*/
#include "nsFtpConnectionThread.h"
#include "nsFtpStreamListenerEvent.h" // the various events we fire off to the
// owning thread.
#include "nsITransport.h"
#include "nsISocketTransportService.h"
#include "nsIUrl.h"
#include "nsIInputStream.h"
#include "prcmon.h"
#include "prprf.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
NS_IMPL_ADDREF(nsFtpConnectionThread);
NS_IMPL_RELEASE(nsFtpConnectionThread);
NS_IMETHODIMP
nsFtpConnectionThread::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
NS_ASSERTION(aInstancePtr, "no instance pointer");
if (aIID.Equals(nsIRunnable::GetIID()) ||
aIID.Equals(kISupportsIID) ) {
*aInstancePtr = NS_STATIC_CAST(nsFtpConnectionThread*, this);
NS_ADDREF_THIS();
return NS_OK;
}
/*if (aIID.Equals(nsIStreamListener::GetIID()) ||
aIID.Equals(nsIStreamObserver::GetIID())) {
*aInstancePtr = NS_STATIC_CAST(nsIStreamListener*, this);
NS_ADDREF_THIS();
return NS_OK;
}*/
return NS_NOINTERFACE;
}
nsFtpConnectionThread::nsFtpConnectionThread(PLEventQueue* aEventQ) {
mEventQueue = aEventQ;
mEventQueue = aEventQ; // whoever creates us must provide an event queue
// so we can post events back to them.
}
nsFtpConnectionThread::~nsFtpConnectionThread() {
NS_IF_RELEASE(mThread);
NS_IF_RELEASE(mListener);
}
@ -34,7 +68,7 @@ nsFtpConnectionThread::~nsFtpConnectionThread() {
NS_IMETHODIMP
nsFtpConnectionThread::Run() {
nsresult rv;
nsISocketTransport* lCPipe = nsnull;
nsITransport* lCPipe = nsnull;
mState = FTP_CONNECT;
@ -49,6 +83,18 @@ nsFtpConnectionThread::Run() {
rv = mUrl->GetPort(port);
if (NS_FAILED(rv)) return rv;
// tell the user that we've begun the transaction.
nsFtpOnStartBindingEvent* event =
new nsFtpOnStartBindingEvent(mListener, nsnull);
if (event == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
rv = event->Fire(mEventQueue);
if (NS_FAILED(rv)) {
delete event;
return rv;
}
rv = sts->CreateTransport(host, port, &lCPipe); // the command channel
if (NS_FAILED(rv)) return rv;
@ -74,7 +120,7 @@ nsFtpConnectionThread::Run() {
switch(mState) {
case FTP_READ_BUF:
if (mState == mNextState)
NS_ASSERTION(0);
NS_ASSERTION(0, "ftp read state mixup");
rv = Read();
mState = mNextState;
@ -86,7 +132,7 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer);
// send off the command
rv = lOut->Write(buffer, bufLen, &bytes);
rv = mOutStream->Write(buffer, bufLen, &bytes);
if (NS_FAILED(rv)) return rv;
if (bytes < bufLen) {
@ -120,7 +166,7 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer);
// PR_smprintf(buffer, "PASS %.256s\r\n", mPassword);
rv = lOut->Write(buffer, bufLen, &bytes);
rv = mOutStream->Write(buffer, bufLen, &bytes);
if (NS_FAILED(rv)) return rv;
if (bytes < bufLen) {
@ -139,7 +185,7 @@ nsFtpConnectionThread::Run() {
// logged in
mState = FTP_S_SYST;
} else {
NS_ASSERTION(0);
NS_ASSERTION(0, "ftp unexpected condition");
}
break;
// END: FTP_R_PASS
@ -149,7 +195,7 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer);
// send off the command
rv = mOut->(buffer, bufLen, &bytes);
rv = mOutStream->Write(buffer, bufLen, &bytes);
if (NS_FAILED(rv)) return rv;
if (bytes < bufLen) {
@ -184,10 +230,10 @@ nsFtpConnectionThread::Run() {
case FTP_S_ACCT:
buffer = "ACCT noaccount\r\n";
bufLen = PL_strlen(buffer):
bufLen = PL_strlen(buffer);
// send off the command
rv = mOut->(buffer, bufLen, &bytes);
rv = mOutStream->Write(buffer, bufLen, &bytes);
if (NS_FAILED(rv)) return rv;
if (bytes < bufLen) {
@ -215,7 +261,7 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer);
// send off the command
rv = mOut->Write(buffer, bufLen, &bytes);
rv = mOutStream->Write(buffer, bufLen, &bytes);
if (bytes < bufLen) {
break;
@ -245,7 +291,7 @@ nsFtpConnectionThread::Run() {
bufLen = PL_strlen(buffer);
// send off the command
rv = mOut->Write(buffer, bufLen, &bytes);
rv = mOutStream->Write(buffer, bufLen, &bytes);
if (bytes < bufLen) {
break;
@ -351,24 +397,41 @@ nsFtpConnectionThread::Run() {
}
// Close the command channel
lCPipe->CloseConnection();
//lCPipe->CloseConnection();
}
nsresult nsFtpConnectionThread::Init(nsIThread* aThread, nsIStreamListener* aListener) {
mThread = aThread;
NS_ADDREF(mThread);
mListener = aListener;
NS_ADDREF(mListener);
PRThread* prthread;
aThread->GetPRThread(&prthread);
PR_CEnterMonitor(this);
mEventQueue = PL_CreateEventQueue("ftp worker thread event loop", prthread);
// wake up event loop
PR_CNotify(this);
PR_CExitMonitor(this);
return NS_OK;
}
nsresult
nsFtpConnectionThread::Read(void) {
PRUint32 read, len;
nsresult rv;
char *buffer = nsnull;
rv = mIn->GetLength(&len);
if (NS_FAILURE(rv)) return rv;
rv = mInStream->GetLength(&len);
if (NS_FAILED(rv)) return rv;
buffer = new char[len+1];
if (!buffer) return 0; // XXX need a better return code
rv = mIn->(buffer, len, &read);
rv = mInStream->Read(buffer, len, &read);
if (NS_FAILED(rv)) {
delete [] buffer;
return rv;
}
*aOutLen = read;
// get the response code out.
PR_sscanf(buffer, "%d", &mResponseCode);

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

@ -19,7 +19,10 @@
#include "nsIThread.h"
#include "nsISocketTransportService.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
#include "nsIOutputStream.h"
#include "nsString2.h"
#include "plevent.h"
@ -70,17 +73,21 @@ typedef enum _FTP_ACTION {
GET,
POST,
MKDIR,
DELETE,
DEL
} FTP_ACTION;
class nsFtpConnectionThread : public nsIRunnable {
public:
NS_DECL_ISUPPORTS
nsFtpConnectionThread(PLEventQueue* aEventQ);
~nsFtpConnectionThread();
// nsIRunnable method
NS_IMETHOD Run();
nsresult Init(nsIThread* aThread, nsIStreamListener* aListener);
// user level setup
private:
@ -88,6 +95,8 @@ private:
void SetSystInternals(void);
PLEventQueue* mEventQueue; // used to communicate outside this thread
nsIThread* mThread; // the worker thread
FTP_STATE mState; // the current state
FTP_STATE mNextState; // the next state
nsIInputStream* mInStream;
@ -96,8 +105,17 @@ private:
nsString2 mResponseMsg; // the last command response text
nsString2 mUsername;
nsString2 mPassword;
// these members should be hung off of a specific transport connection
PRInt32 mServerType;
PRBool mList;
PRBool mPasv;
PRBool mList; // use LIST instead of NLST
// end "these ...."
PRBool mConnected;
PRBool mUseDefaultPath; // use PWD to figure out path
nsIUrl* mUrl;
}
nsIStreamListener* mListener; // the listener we want to call
// during our event firing.
};

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

@ -22,14 +22,12 @@
#include "nscore.h"
#include "nsIUrl.h"
#include "nsIFtpEventSink.h"
#include "nsISocketTransportService.h"
#include "nsIServiceManager.h"
#include "nsIByteBufferInputStream.h"
#include "prprf.h" // PR_sscanf
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
// There are actually two transport connections established for an
// ftp connection. One is used for the command channel , and
@ -40,9 +38,7 @@ static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
// Client initiation is the most command case and is attempted first.
nsFtpProtocolConnection::nsFtpProtocolConnection()
: mUrl(nsnull), mEventSink(nsnull), mPasv(TRUE),
mServerType(FTP_GENERIC_TYPE), mConnected(FALSE),
mResponseCode(0), mList(FALSE), mUseDefaultPath(TRUE) {
: mUrl(nsnull), mEventSink(nsnull), mConnected(PR_FALSE) {
mEventQueue = PL_CreateEventQueue("FTP Event Queue", PR_CurrentThread());
}
@ -50,8 +46,7 @@ nsFtpProtocolConnection::nsFtpProtocolConnection()
nsFtpProtocolConnection::~nsFtpProtocolConnection() {
NS_IF_RELEASE(mUrl);
NS_IF_RELEASE(mEventSink);
NS_IF_RELEASE(mCPipe);
NS_IF_RELEASE(mDPipe);
NS_IF_RELEASE(mListener);
}
NS_IMPL_ADDREF(nsFtpProtocolConnection);
@ -67,12 +62,12 @@ nsFtpProtocolConnection::QueryInterface(const nsIID& aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIStreamListener::GetIID()) ||
/*if (aIID.Equals(nsIStreamListener::GetIID()) ||
aIID.Equals(nsIStreamObserver::GetIID())) {
*aInstancePtr = NS_STATIC_CAST(nsIStreamListener*, this);
NS_ADDREF_THIS();
return NS_OK;
}
}*/
return NS_NOINTERFACE;
}
@ -118,9 +113,7 @@ nsFtpProtocolConnection::Resume(void) {
// establishes the connection and initiates the file transfer.
NS_IMETHODIMP
nsFtpProtocolConnection::Open(void) {
nsresult rv;
mState = FTP_CONNECT;
/* nsresult rv;
NS_WITH_SERVICE(nsISocketTransportService, sts, kSocketTransportServiceCID, &rv);
if(NS_FAILED(rv)) return rv;
@ -141,9 +134,9 @@ nsFtpProtocolConnection::Open(void) {
// XXX don't know when the transport does that so, we're going to
// XXX consider ourselves conencted.
mConnected = TRUE;
mState = FTP_S_USER;
*/
return NS_OK;
}
NS_IMETHODIMP
@ -177,21 +170,12 @@ NS_IMETHODIMP
nsFtpProtocolConnection::Put(void) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsFtpProtocolConnection::UsePASV(PRBool aComm) {
if (mConnected)
return NS_ERROR_NOT_IMPLEMENTED;
mPasv = aComm;
return NS_ERROR_NOT_IMPLEMENTED;
}
/*
////////////////////////////////////////////////////////////////////////////////
// nsIStreamObserver methods:
NS_IMETHODIMP
nsFtpProtocolConnection::OnStartBinding(nsISupports* context) {
// up call OnStartBinding
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -199,347 +183,26 @@ NS_IMETHODIMP
nsFtpProtocolConnection::OnStopBinding(nsISupports* context,
nsresult aStatus,
nsIString* aMsg) {
nsresult rv;
char *buffer = nsnull; // the buffer to be sent to the server
nsIByteBufferInputStream* stream = nsnull; // stream to be filled, with buffer, then written to the server
PRUint32 bytesWritten = 0;
rv = NS_NewByteBufferInputStream(&stream);
if (NS_FAILED(rv)) return rv;
// each hunk of data that comes in is evaluated, appropriate action
// is taken and the state is incremented.
// XXX some of the "buffer"s allocated below in the individual states can be removed
// XXX and replaced with static char or #defines.
switch(mState) {
case FTP_CONNECT:
case FTP_S_USER:
buffer = "USER anonymous";
stream->Fill(buffer, strlen(buffer), &bytesWritten);
// send off the command
mState = FTP_R_USER;
mCPipe->AsyncWrite(stream, nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamObserver*, this));
break;
case FTP_R_USER:
mCPipe->AsyncRead(nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamListener*, this));
break;
case FTP_S_PASS:
if (!mPassword) {
// XXX we need to prompt the user to enter a password.
// sendEventToUIThreadToPostADialog(&mPassword);
}
buffer = "PASS guest\r\n";
// PR_smprintf(buffer, "PASS %.256s\r\n", mPassword);
stream->Fill(buffer, strlen(buffer), &bytesWritten);
// send off the command
mState = FTP_R_PASV;
mCPipe->AsyncWrite(stream, nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamObserver*, this));
break;
case FTP_R_PASS:
mCPipe->AsyncRead(nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamListener*, this));
break;
case FTP_S_SYST:
buffer = "SYST\r\n";
stream->Fill(buffer, strlen(buffer), &bytesWritten);
// send off the command
mState = FTP_R_SYST;
mCPipe->AsyncWrite(stream, nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamObserver*, this));
break;
case FTP_R_SYST:
mCPipe->AsyncRead(nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamListener*, this));
break;
case FTP_S_ACCT:
buffer = "ACCT noaccount\r\n";
stream->Fill(buffer, strlen(buffer), &bytesWritten);
// send off the command
mState = FTP_R_ACCT;
mCPipe->AsyncWrite(stream, nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamObserver*, this));
break;
case FTP_R_ACCT:
mCPipe->AsyncRead(nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamListener*, this));
break;
case FTP_S_MACB:
buffer = "MACB ENABLE\r\n";
stream->Fill(buffer, strlen(buffer), &bytesWritten);
mState = FTP_R_MACB;
mCPipe->AsyncWrite(stream, nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamObserver*, this));
break;
case FTP_R_MACB:
mCPipe->AsyncRead(nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamListener*, this));
break;
case FTP_S_PWD:
buffer = "PWD\r\n";
stream->Fill(buffer, strlen(buffer), &bytesWritten);
// send off the command
mState = FTP_R_PWD;
mCPipe->AsyncWrite(stream, nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamObserver*, this));
break;
case FTP_R_PWD:
mCPipe->AsyncRead(nsnull, mEventQueue, NS_STATIC_CAST(nsIStreamListener*, this));
break;
case FTP_COMPLETE:
default:
;
}
// up call OnStopBinding
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////////////
// nsIStreamListener methods:
// this is the command channel's OnDataAvailable(). It's job is to processes AsyncReads.
// It absorbs the data from the stream, parses it, and passes the data onto the appropriate
// routine/logic for handling.
NS_IMETHODIMP
nsFtpProtocolConnection::OnDataAvailable(nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength) {
nsresult rv;
// we've got some data. suck it out of the inputSteam.
char *buffer = new char[aLength+1];
// XXX maybe use an nsString2
PRUint32 read = 0;
rv = aIStream->Read(buffer, aLength, &read);
if (NS_FAILED(rv)) return rv;
// get the response code out.
PR_sscanf(buffer, "%d", &mResponseCode);
// get the rest of the line
mResponseMsg = buffer+4;
// these are states in which data is coming back to us. read states.
// This switch is a state incrementor using the server response to
// determine what the next state shall be.
switch(mState) {
case FTP_R_USER:
if (mResponseCode == 3) {
// send off the password
mState = FTP_S_PASV;
} else if (mResponseCode == 2) {
// no password required, we're already logged in
mState = FTP_S_SYST;
}
break;
case FTP_R_PASS:
if (mResponseCode == 3) {
// send account info
mState = FTP_S_ACCT;
} else if (mResponseCode == 2) {
// logged in
mState = FTP_S_SYST;
}
break;
case FTP_R_SYST:
if (mResponseCode == 2) {
if (mUseDefaultPath)
mState = FTP_S_PWD;
else
; // ftp figure out what to do.
SetSystInternals(); // must be called first to setup member vars.
// setup next state based on server type.
if (mServerType == FTP_PETER_LEWIS_TYPE || mServerType == FTP_WEBSTAR_TYPE) {
mState = FTP_S_MACB;
} else if (mServerType == FTP_TCPC_TYPE || mServerType == FTP_GENERIC_TYPE) {
mState = FTP_S_PWD;
}
} else {
mState = FTP_S_PWD;
}
break;
case FTP_R_ACCT:
if (mResponseCode == 2) {
mState = FTP_S_SYST;
} else {
// failure. couldn't login
// XXX use a more descriptive error code.
return NS_ERROR_NOT_IMPLEMENTED;
}
break;
case FTP_R_MACB:
if (mResponseCode == 2) {
// set the mac binary
if (mServerType == FTP_UNIX_TYPE) {
// This state is carry over from the old ftp implementation
// I'm not sure what's really going on here.
// original comment /* we were unsure here */
mServerType = FTP_NCSA_TYPE;
}
}
break;
case FTP_R_PWD:
{
// fun response interpretation begins :)
PRInt32 start = mResponseMsg.Find('"', FALSE, 5);
nsString2 lNewMsg;
if (start > -1) {
mResponseMsg.Left(lNewMsg, start);
} else {
lNewMsg = mResponseMsg;
}
// default next state
// mState = figure out what to do
// reset server types if necessary
if (mServerType == FTP_TCPC_TYPE) {
if (lNewMsg.CharAt(1) == '/') {
mServerType = FTP_NCSA_TYPE;
}
}
else if(mServerType == FTP_GENERIC_TYPE) {
if (lNewMsg.CharAt(1) == '/') {
// path names ending with '/' imply unix
mServerType = FTP_UNIX_TYPE;
mList = TRUE;
} else if (lNewMsg.Last() == ']') {
// path names ending with ']' imply vms
mServerType = FTP_VMS_TYPE;
mList = TRUE;
}
}
if (mUseDefaultPath && mServerType != FTP_VMS_TYPE) {
// we want to use the default path specified by the PWD command.
PRInt32 start = lNewMsg.Find('"', FALSE, 1);
nsString2 path, ptr;
lNewMsg.Right(path, start);
if (path.First() != '/') {
start = path.Find('/');
if (start > -1) {
path.Right(ptr, start);
} else {
// if we couldn't find a slash, check for back slashes and switch them out.
PRInt32 start = path.Find('\\');
if (start > -1) {
path.ReplaceChar('\\', '/');
}
}
} else {
ptr = path;
}
// construct the new url
if (ptr.Length()) {
nsString2 newPath;
newPath = ptr;
const char *initialPath = nsnull;
rv = mUrl->GetPath(&initialPath);
if (NS_FAILED(rv)) return rv;
if (initialPath && *initialPath) {
if (newPath.Last() == '/')
newPath.Cut(newPath.Length()-1, 1);
newPath.Append(initialPath);
}
char *p = newPath.ToNewCString();
mUrl->SetPath(p);
delete [] p;
}
}
// change state for these servers.
if (mServerType == FTP_GENERIC_TYPE
|| mServerType == FTP_NCSA_TYPE
|| mServerType == FTP_TCPC_TYPE
|| mServerType == FTP_WEBSTAR_TYPE
|| mServerType == FTP_PETER_LEWIS_TYPE)
mState = FTP_S_MACB;
break;
}
case FTP_R_PORT:
case FTP_COMPLETE:
default:
;
}
delete [] buffer;
// XXX this may not be necessary. presumably OnStopBinding will be called
// XXX right after this call, so we probably don't need to explicitly call
// XXX it here.
// call back into the sending state machine.
OnStopBinding(nsnull, rv, nsnull);
PRUint32 aLength)
return NS_ERROR_NOT_IMPLEMENTED;
}
*/
NS_IMETHODIMP
nsFtpProtocolConnection::SetStreamListener(nsIStreamListener *aListener) {
mListener = aListener;
NS_ADDREF(mListener);
return NS_OK;
}
// Here's where we do all the string whacking/parsing magic to determine
// what type of server it is we're dealing with.
void
nsFtpProtocolConnection::SetSystInternals(void) {
if (mResponseMsg.Equals("UNIX Type: L8 MAC-OS MachTen", 28)) {
mServerType = FTP_MACHTEN_TYPE;
mList = TRUE;
}
else if (mResponseMsg.Find("UNIX") > -1) {
mServerType = FTP_UNIX_TYPE;
mList = TRUE;
}
else if (mResponseMsg.Find("Windows_NT") > -1) {
mServerType = FTP_NT_TYPE;
mList = TRUE;
}
else if (mResponseMsg.Equals("VMS", 3)) {
mServerType = FTP_VMS_TYPE;
mList = TRUE;
}
else if (mResponseMsg.Equals("VMS/CMS", 6) || mResponseMsg.Equals("VM ", 3)) {
mServerType = FTP_CMS_TYPE;
}
else if (mResponseMsg.Equals("DCTS", 4)) {
mServerType = FTP_DCTS_TYPE;
}
else if (mResponseMsg.Find("MAC-OS TCP/Connect II") > -1) {
mServerType = FTP_TCPC_TYPE;
mList = TRUE;
}
else if (mResponseMsg.Equals("MACOS Peter's Server", 20)) {
mServerType = FTP_PETER_LEWIS_TYPE;
mList = TRUE;
}
else if (mResponseMsg.Equals("MACOS WebSTAR FTP", 17)) {
mServerType = FTP_WEBSTAR_TYPE;
mList = TRUE;
}
}
////////////////////////////////////////////////////////////////////////////////

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

@ -30,46 +30,8 @@
class nsIConnectionGroup;
class nsIFtpEventSink;
// ftp server types
#define FTP_GENERIC_TYPE 0
#define FTP_UNIX_TYPE 1
#define FTP_DCTS_TYPE 2
#define FTP_NCSA_TYPE 3
#define FTP_PETER_LEWIS_TYPE 4
#define FTP_MACHTEN_TYPE 5
#define FTP_CMS_TYPE 6
#define FTP_TCPC_TYPE 7
#define FTP_VMS_TYPE 8
#define FTP_NT_TYPE 9
#define FTP_WEBSTAR_TYPE 10
// ftp states
typedef enum _FTP_STATE {
FTP_CONNECT,
FTP_S_USER, // send username
FTP_R_USER,
FTP_S_PASS, // send password
FTP_R_PASS,
// FTP_S_REST, // send restart
// FTP_R_REST,
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_PASV, // send passive
FTP_R_PASV,
FTP_S_PORT, // send port
FTP_R_PORT,
FTP_COMPLETE
} FTP_STATE;
class nsFtpProtocolConnection : public nsIFtpProtocolConnection,
public nsIStreamListener {
class nsFtpProtocolConnection : public nsIFtpProtocolConnection
/*,public nsIStreamListener*/ {
public:
NS_DECL_ISUPPORTS
@ -87,8 +49,7 @@ public:
// nsIFtpProtocolConnection methods:
NS_IMETHOD Get(void);
NS_IMETHOD Put(void);
NS_IMETHOD UsePASV(PRBool aComm);
/*
// nsIStreamObserver methods:
NS_IMETHOD OnStartBinding(nsISupports* context);
NS_IMETHOD OnStopBinding(nsISupports* context,
@ -100,36 +61,22 @@ public:
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength);
*/
// nsFtpProtocolConnection methods:
NS_IMETHOD SetStreamListener(nsIStreamListener* aListener);
nsFtpProtocolConnection();
virtual ~nsFtpProtocolConnection();
nsresult Init(nsIUrl* aUrl, nsISupports* aEventSink, PLEventQueue* aEventQueue);
private:
void SetSystInternals(void);
protected:
nsIUrl* mUrl;
nsIFtpEventSink* mEventSink;
PLEventQueue* mEventQueue;
// these members should be hung off of a specific transport connection
PRInt32 mServerType;
PRBool mPasv;
PRBool mList; // use LIST instead of NLST
// end "these ...."
PRBool mConnected;
PRBool mUseDefaultPath; // use PWD to figure out path
FTP_STATE mState;
nsITransport* mCPipe; // the command channel
nsITransport* mDPipe; // the data channel
PRInt32 mResponseCode; // the last command response code.
nsString2 mResponseMsg; // the last command response text
nsString2 mUsername;
nsString2 mPassword;
nsIStreamListener* mListener;
};
#endif /* nsFtpProtocolConnection_h___ */

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

@ -0,0 +1,213 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsFtpStreamListenerEvent.h"
#include "nsIInputStream.h"
#include "nscore.h"
#include "nsIString.h"
nsFtpStreamListenerEvent::nsFtpStreamListenerEvent(nsIStreamListener* listener,
nsISupports* context)
: mListener(listener), mContext(context)
{
NS_ADDREF(mListener);
NS_IF_ADDREF(mContext);
}
nsFtpStreamListenerEvent::~nsFtpStreamListenerEvent()
{
NS_RELEASE(mListener);
NS_IF_RELEASE(mContext);
}
void PR_CALLBACK nsFtpStreamListenerEvent::HandlePLEvent(PLEvent* aEvent)
{
// WARNING: This is a dangerous cast since it must adjust the pointer
// to compensate for the vtable...
nsFtpStreamListenerEvent *ev = (nsFtpStreamListenerEvent*)aEvent;
nsresult rv = ev->HandleEvent();
//ev->mListener->SetStatus(rv);
}
void PR_CALLBACK nsFtpStreamListenerEvent::DestroyPLEvent(PLEvent* aEvent)
{
// WARNING: This is a dangerous cast since it must adjust the pointer
// to compensate for the vtable...
nsFtpStreamListenerEvent *ev = (nsFtpStreamListenerEvent*)aEvent;
delete ev;
}
nsresult
nsFtpStreamListenerEvent::Fire(PLEventQueue* aEventQueue)
{
NS_PRECONDITION(nsnull != aEventQueue, "PLEventQueue for thread is null");
PL_InitEvent(this, nsnull,
(PLHandleEventProc) nsFtpStreamListenerEvent::HandlePLEvent,
(PLDestroyEventProc) nsFtpStreamListenerEvent::DestroyPLEvent);
PRStatus status = PL_PostEvent(aEventQueue, this);
return status == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
}
////////////////////////////////////////////////////////////////////////////////
//
// OnStartBinding...
//
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsFtpOnStartBindingEvent::HandleEvent()
{
nsIStreamObserver* receiver = (nsIStreamObserver*)mListener;
return receiver->OnStartBinding(mContext);
}
/*
NS_IMETHODIMP
nsMarshalingStreamObserver::OnStartBinding(nsISupports* context)
{
nsresult rv = GetStatus();
if (NS_FAILED(rv)) return rv;
nsOnStartBindingEvent* event =
new nsOnStartBindingEvent(this, context);
if (event == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
rv = event->Fire(mEventQueue);
if (NS_FAILED(rv)) goto failed;
return rv;
failed:
delete event;
return rv;
}
*/
////////////////////////////////////////////////////////////////////////////////
//
// OnDataAvailable
//
////////////////////////////////////////////////////////////////////////////////
nsFtpOnDataAvailableEvent::~nsFtpOnDataAvailableEvent()
{
NS_RELEASE(mIStream);
}
nsresult
nsFtpOnDataAvailableEvent::Init(nsIInputStream* aIStream, PRUint32 aLength)
{
mLength = aLength;
mIStream = aIStream;
NS_ADDREF(mIStream);
return NS_OK;
}
NS_IMETHODIMP
nsFtpOnDataAvailableEvent::HandleEvent()
{
nsIStreamListener* receiver = (nsIStreamListener*)mListener;
return receiver->OnDataAvailable(mContext, mIStream, mLength);
}
/*
NS_IMETHODIMP
nsMarshalingStreamListener::OnDataAvailable(nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aLength)
{
nsresult rv = GetStatus();
if (NS_FAILED(rv)) return rv;
nsOnDataAvailableEvent* event =
new nsOnDataAvailableEvent(this, context);
if (event == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
rv = event->Init(aIStream, aLength);
if (NS_FAILED(rv)) goto failed;
rv = event->Fire(mEventQueue);
if (NS_FAILED(rv)) goto failed;
return rv;
failed:
delete event;
return rv;
}
*/
////////////////////////////////////////////////////////////////////////////////
//
// OnStopBinding
//
////////////////////////////////////////////////////////////////////////////////
nsFtpOnStopBindingEvent::~nsFtpOnStopBindingEvent()
{
NS_IF_RELEASE(mMessage);
}
nsresult
nsFtpOnStopBindingEvent::Init(nsresult status, nsIString* aMsg)
{
mStatus = status;
mMessage = aMsg;
NS_IF_ADDREF(mMessage);
return NS_OK;
}
NS_IMETHODIMP
nsFtpOnStopBindingEvent::HandleEvent()
{
nsIStreamObserver* receiver = (nsIStreamObserver*)mListener;
return receiver->OnStopBinding(mContext, mStatus, mMessage);
}
/*
NS_IMETHODIMP
nsMarshalingStreamObserver::OnStopBinding(nsISupports* context,
nsresult aStatus,
nsIString* aMsg)
{
nsresult rv = GetStatus();
if (NS_FAILED(rv)) return rv;
nsOnStopBindingEvent* event =
new nsOnStopBindingEvent(this, context);
if (event == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
rv = event->Init(aStatus, aMsg);
if (NS_FAILED(rv)) goto failed;
rv = event->Fire(mEventQueue);
if (NS_FAILED(rv)) goto failed;
return rv;
failed:
delete event;
return rv;
}
*/
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

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

@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef ___nsftpstreamlistener_h__
#define ___nsftpstreamlistener_h__
#include "nsIStreamListener.h"
#include "plevent.h"
#include "nscore.h"
class nsFtpStreamListenerEvent : public PLEvent {
public:
nsFtpStreamListenerEvent(nsIStreamListener* listener, nsISupports* context);
virtual ~nsFtpStreamListenerEvent();
nsresult Fire(PLEventQueue* aEventQ);
NS_IMETHOD HandleEvent() = 0;
protected:
static void PR_CALLBACK HandlePLEvent(PLEvent* aEvent);
static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent);
nsIStreamListener* mListener;
nsISupports* mContext;
};
class nsFtpOnStartBindingEvent : public nsFtpStreamListenerEvent
{
public:
nsFtpOnStartBindingEvent(nsIStreamListener* listener, nsISupports* context)
: nsFtpStreamListenerEvent(listener, context) {}
virtual ~nsFtpOnStartBindingEvent() {}
NS_IMETHOD HandleEvent();
};
class nsFtpOnDataAvailableEvent : public nsFtpStreamListenerEvent
{
public:
nsFtpOnDataAvailableEvent(nsIStreamListener* listener, nsISupports* context)
: nsFtpStreamListenerEvent(listener, context),
mIStream(nsnull), mLength(0) {}
virtual ~nsFtpOnDataAvailableEvent();
nsresult Init(nsIInputStream* aIStream, PRUint32 aLength);
NS_IMETHOD HandleEvent();
protected:
nsIInputStream* mIStream;
PRUint32 mLength;
};
class nsFtpOnStopBindingEvent : public nsFtpStreamListenerEvent
{
public:
nsFtpOnStopBindingEvent(nsIStreamListener* listener, nsISupports* context)
: nsFtpStreamListenerEvent(listener, context),
mStatus(NS_OK), mMessage(nsnull) {}
virtual ~nsFtpOnStopBindingEvent();
nsresult Init(nsresult status, nsIString* aMsg);
NS_IMETHOD HandleEvent();
protected:
nsresult mStatus;
nsIString* mMessage;
};
#endif // ___nsftpstreamlistener_h__