зеркало из https://github.com/mozilla/pjs.git
Added synchronous file input. Worked on cancel/suspend/resume work for file transfer.
This commit is contained in:
Родитель
9424f0948b
Коммит
8f99982227
|
@ -27,6 +27,7 @@ EXPORTS = \
|
|||
nsIProtocolConnection.h \
|
||||
nsIProtocolHandler.h \
|
||||
nsIStreamListener.h \
|
||||
nsIStreamObserver.h \
|
||||
nsITransport.h \
|
||||
nsIUrl.h \
|
||||
$(NULL)
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
class nsIStreamObserver;
|
||||
class nsIStreamListener;
|
||||
class nsITransport;
|
||||
class nsIInputStream;
|
||||
class nsIOutputStream;
|
||||
|
||||
#define NS_IFILETRANSPORTSERVICE_IID \
|
||||
{ /* 2355dca0-ea35-11d2-931b-00104ba0fd40 */ \
|
||||
|
@ -47,20 +49,34 @@ class nsIFileTransportService : public nsISupports
|
|||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFILETRANSPORTSERVICE_IID);
|
||||
|
||||
// Async routines: By calling these the calling thread agrees
|
||||
// to eventually return to an event loop that will be notified
|
||||
// with incoming data, calling the listener.
|
||||
|
||||
NS_IMETHOD AsyncRead(PLEventQueue* appEventQueue,
|
||||
NS_IMETHOD AsyncRead(const char* path,
|
||||
nsISupports* context,
|
||||
PLEventQueue* appEventQueue,
|
||||
nsIStreamListener* listener,
|
||||
const char* path,
|
||||
nsITransport* *result) = 0;
|
||||
|
||||
NS_IMETHOD AsyncWrite(PLEventQueue* appEventQueue,
|
||||
nsISupports* context,
|
||||
nsIStreamObserver* observer,
|
||||
NS_IMETHOD AsyncWrite(nsIInputStream* fromStream,
|
||||
const char* path,
|
||||
nsISupports* context,
|
||||
PLEventQueue* appEventQueue,
|
||||
nsIStreamObserver* observer,
|
||||
nsITransport* *result) = 0;
|
||||
|
||||
NS_IMETHOD Shutdown() = 0;
|
||||
// Synchronous routines
|
||||
|
||||
NS_IMETHOD OpenInputStream(const char* path,
|
||||
nsISupports* context,
|
||||
nsIInputStream* *result) = 0;
|
||||
|
||||
NS_IMETHOD OpenOutputStream(const char* path,
|
||||
nsISupports* context,
|
||||
nsIOutputStream* *result) = 0;
|
||||
|
||||
NS_IMETHOD ProcessPendingRequests(void) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -38,8 +38,6 @@ class nsIProtocolConnection : public nsICancelable
|
|||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPROTOCOLCONNECTION_IID);
|
||||
|
||||
NS_IMETHOD Open(nsIUrl* url, nsISupports* eventSink) = 0;
|
||||
|
||||
// can be called after Open
|
||||
// freed by caller with delete[]
|
||||
NS_IMETHOD GetContentType(char* *contentType) = 0;
|
||||
|
@ -57,5 +55,7 @@ public:
|
|||
|
||||
};
|
||||
|
||||
#define NS_ERROR_NOT_CONNECTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 3)
|
||||
|
||||
#endif /* nsIIProtocolConnection_h___ */
|
||||
|
||||
|
|
|
@ -19,14 +19,10 @@
|
|||
#ifndef nsIStreamListener_h___
|
||||
#define nsIStreamListener_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nscore.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "plevent.h"
|
||||
|
||||
class nsIUrl;
|
||||
class nsIInputStream;
|
||||
class nsIProtocolConnection;
|
||||
class nsIString;
|
||||
|
||||
#define NS_ISTREAMLISTENER_IID \
|
||||
{ /* 68d9d640-ea35-11d2-931b-00104ba0fd40 */ \
|
||||
|
@ -36,20 +32,11 @@ class nsIString;
|
|||
{0x93, 0x1b, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
|
||||
class nsIStreamListener : public nsISupports
|
||||
class nsIStreamListener : public nsIStreamObserver
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISTREAMLISTENER_IID);
|
||||
|
||||
/**
|
||||
* Notify the listener that the URL has started to load. This method is
|
||||
* called only once, at the beginning of a URL load.<BR><BR>
|
||||
*
|
||||
* @return The return value is currently ignored. In the future it may be
|
||||
* used to cancel the URL load..
|
||||
*/
|
||||
NS_IMETHOD OnStartBinding(nsISupports* context) = 0;
|
||||
|
||||
/**
|
||||
* Notify the client that data is available in the input stream. This
|
||||
* method is called whenver data is written into the input stream by the
|
||||
|
@ -64,34 +51,20 @@ public:
|
|||
nsIInputStream *aIStream,
|
||||
PRUint32 aLength) = 0;
|
||||
|
||||
/**
|
||||
* Notify the listener that the URL has finished loading. This method is
|
||||
* called once when the networking library has finished processing the
|
||||
* URL transaction initiatied via the nsINetService::Open(...) call.<BR><BR>
|
||||
*
|
||||
* This method is called regardless of whether the URL loaded successfully.<BR><BR>
|
||||
*
|
||||
* @param status Status code for the URL load.
|
||||
* @param msg A text string describing the error.
|
||||
* @return The return value is currently ignored.
|
||||
*/
|
||||
NS_IMETHOD OnStopBinding(nsISupports* context,
|
||||
nsresult aStatus,
|
||||
nsIString* aMsg) = 0;
|
||||
|
||||
};
|
||||
|
||||
// Generic status codes for OnStopBinding:
|
||||
#define NS_BINDING_SUCCEEDED NS_OK
|
||||
#define NS_BINDING_FAILED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 1)
|
||||
#define NS_BINDING_ABORTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 2)
|
||||
|
||||
// A marshaling stream listener is used to ship data over to another thread specified
|
||||
// An asynchronous stream listener is used to ship data over to another thread specified
|
||||
// by the thread's event queue. The receiver stream listener is then used to receive
|
||||
// the data on the other thread.
|
||||
extern nsresult
|
||||
NS_NewMarshalingStreamListener(PLEventQueue* eventQueue,
|
||||
nsIStreamListener* receiver,
|
||||
nsIStreamListener* *result);
|
||||
NS_NewAsyncStreamListener(nsIStreamListener* *result,
|
||||
PLEventQueue* eventQueue,
|
||||
nsIStreamListener* receiver);
|
||||
|
||||
// A synchronous stream listener pushes data through a pipe that ends up
|
||||
// in an input stream to be read by another thread.
|
||||
extern nsresult
|
||||
NS_NewSyncStreamListener(nsIStreamListener* *listener,
|
||||
nsIInputStream* *inStream);
|
||||
|
||||
#endif /* nsIIStreamListener_h___ */
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/* -*- 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 nsIStreamObserver_h___
|
||||
#define nsIStreamObserver_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIUrl;
|
||||
class nsIString;
|
||||
|
||||
// XXX regenerate:
|
||||
#define NS_ISTREAMOBSERVER_IID \
|
||||
{ /* 00ca4510-f14a-11d2-9322-000000000000 */ \
|
||||
0x00ca4510, \
|
||||
0xf14a, \
|
||||
0x11d2, \
|
||||
{0x93, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} \
|
||||
}
|
||||
|
||||
class nsIStreamObserver : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISTREAMOBSERVER_IID);
|
||||
|
||||
/**
|
||||
* Notify the observer that the URL has started to load. This method is
|
||||
* called only once, at the beginning of a URL load.<BR><BR>
|
||||
*
|
||||
* @return The return value is currently ignored. In the future it may be
|
||||
* used to cancel the URL load..
|
||||
*/
|
||||
NS_IMETHOD OnStartBinding(nsISupports* context) = 0;
|
||||
|
||||
/**
|
||||
* Notify the observer that the URL has finished loading. This method is
|
||||
* called once when the networking library has finished processing the
|
||||
* URL transaction initiatied via the nsINetService::Open(...) call.<BR><BR>
|
||||
*
|
||||
* This method is called regardless of whether the URL loaded successfully.<BR><BR>
|
||||
*
|
||||
* @param status Status code for the URL load.
|
||||
* @param msg A text string describing the error.
|
||||
* @return The return value is currently ignored.
|
||||
*/
|
||||
NS_IMETHOD OnStopBinding(nsISupports* context,
|
||||
nsresult aStatus,
|
||||
nsIString* aMsg) = 0;
|
||||
|
||||
};
|
||||
|
||||
// Generic status codes for OnStopBinding:
|
||||
#define NS_BINDING_SUCCEEDED NS_OK
|
||||
#define NS_BINDING_FAILED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 1)
|
||||
#define NS_BINDING_ABORTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 2)
|
||||
|
||||
#endif /* nsIIStreamObserver_h___ */
|
|
@ -31,6 +31,7 @@ EXPORTS = \
|
|||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsConnectionGroup.obj \
|
||||
.\$(OBJDIR)\nsMarshalingStreamListener.obj \
|
||||
.\$(OBJDIR)\nsSyncStreamListener.obj \
|
||||
.\$(OBJDIR)\nsFileTransport.obj \
|
||||
.\$(OBJDIR)\nsFileTransportService.obj \
|
||||
.\$(OBJDIR)\nsNetService.obj \
|
||||
|
|
|
@ -31,26 +31,28 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|||
// nsFileTransport methods:
|
||||
|
||||
nsFileTransport::nsFileTransport()
|
||||
: mContext(nsnull), mPath(nsnull), mListener(nsnull), mCanceled(PR_FALSE)
|
||||
: mPath(nsnull), mContext(nsnull), mListener(nsnull), mState(STARTING),
|
||||
mFileStream(nsnull), mBufferStream(nsnull), mStatus(NS_OK)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsFileTransport::~nsFileTransport()
|
||||
{
|
||||
if (mPath)
|
||||
delete mPath;
|
||||
if (mPath) delete[] mPath;
|
||||
NS_IF_RELEASE(mListener);
|
||||
NS_IF_RELEASE(mContext);
|
||||
NS_IF_RELEASE(mService);
|
||||
NS_IF_RELEASE(mFileStream);
|
||||
NS_IF_RELEASE(mBufferStream);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFileTransport::Init(const char* path,
|
||||
nsISupports* context,
|
||||
nsIStreamListener* listener,
|
||||
PLEventQueue* appEventQueue,
|
||||
nsISupports* context)
|
||||
nsFileTransportService* service)
|
||||
{
|
||||
nsresult rv;
|
||||
mPath = nsCRT::strdup(path);
|
||||
if (mPath == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -58,10 +60,13 @@ nsFileTransport::Init(const char* path,
|
|||
mContext = context;
|
||||
NS_IF_ADDREF(mContext);
|
||||
|
||||
rv = NS_NewMarshalingStreamListener(appEventQueue, listener, &mListener);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mListener = listener;
|
||||
NS_ADDREF(mListener);
|
||||
|
||||
return rv;
|
||||
mService = service;
|
||||
NS_ADDREF(mService);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsFileTransport);
|
||||
|
@ -94,20 +99,133 @@ nsFileTransport::QueryInterface(const nsIID& aIID, void* *aInstancePtr)
|
|||
NS_IMETHODIMP
|
||||
nsFileTransport::Cancel(void)
|
||||
{
|
||||
mCanceled = PR_TRUE;
|
||||
return NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
PR_CEnterMonitor(this);
|
||||
mStatus = NS_BINDING_ABORTED;
|
||||
switch (mState) {
|
||||
case RUNNING:
|
||||
mState = ENDING;
|
||||
break;
|
||||
case SUSPENDED:
|
||||
rv = Resume();
|
||||
break;
|
||||
default:
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
PR_CExitMonitor(this);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileTransport::Suspend(void)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsresult rv = NS_OK;
|
||||
PR_CEnterMonitor(this);
|
||||
switch (mState) {
|
||||
case RUNNING:
|
||||
// XXX close the stream here?
|
||||
mStatus = mService->Suspend(this);
|
||||
|
||||
mState = SUSPENDED;
|
||||
break;
|
||||
default:
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
PR_CExitMonitor(this);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileTransport::Resume(void)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsresult rv = NS_OK;
|
||||
PR_CEnterMonitor(this);
|
||||
switch (mState) {
|
||||
case SUSPENDED:
|
||||
mStatus = mService->Resume(this);
|
||||
|
||||
mState = RUNNING;
|
||||
break;
|
||||
default:
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
PR_CExitMonitor(this);
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
nsFileTransport::Continue(void)
|
||||
{
|
||||
PR_CEnterMonitor(this);
|
||||
switch (mState) {
|
||||
case STARTING: {
|
||||
nsISupports* fs;
|
||||
nsFileSpec spec(mPath);
|
||||
|
||||
mStatus = mListener->OnStartBinding(mContext); // always send the start notification
|
||||
if (NS_FAILED(mStatus)) goto error;
|
||||
|
||||
mStatus = NS_NewTypicalInputFileStream(&fs, spec);
|
||||
if (NS_FAILED(mStatus)) goto error;
|
||||
|
||||
mStatus = fs->QueryInterface(nsIInputStream::GetIID(), (void**)&mFileStream);
|
||||
NS_RELEASE(fs);
|
||||
if (NS_FAILED(mStatus)) goto error;
|
||||
|
||||
mStatus = NS_NewByteBufferInputStream(&mBufferStream, PR_FALSE, NS_FILE_TRANSPORT_BUFFER_SIZE);
|
||||
if (NS_FAILED(mStatus)) goto error;
|
||||
|
||||
mState = RUNNING;
|
||||
break;
|
||||
}
|
||||
case RUNNING: {
|
||||
if (NS_FAILED(mStatus)) goto error;
|
||||
|
||||
PRUint32 amt;
|
||||
mStatus = mBufferStream->Fill(mFileStream, &amt);
|
||||
if (mStatus == NS_BASE_STREAM_EOF) goto error;
|
||||
if (NS_FAILED(mStatus)) goto error;
|
||||
|
||||
// and feed the buffer to the application via the byte buffer stream:
|
||||
mStatus = mListener->OnDataAvailable(mContext, mBufferStream, amt); // XXX maybe amt should be bufStr->GetLength()
|
||||
if (NS_FAILED(mStatus)) goto error;
|
||||
|
||||
// stay in the RUNNING state
|
||||
break;
|
||||
}
|
||||
case SUSPENDED: {
|
||||
NS_NOTREACHED("trying to continue a suspended file transfer");
|
||||
break;
|
||||
}
|
||||
case ENDING: {
|
||||
NS_IF_RELEASE(mBufferStream);
|
||||
mBufferStream = nsnull;
|
||||
NS_IF_RELEASE(mFileStream);
|
||||
mFileStream = nsnull;
|
||||
|
||||
// XXX where do we get the error message?
|
||||
(void)mListener->OnStopBinding(mContext, mStatus, nsnull);
|
||||
|
||||
mState = ENDED;
|
||||
break;
|
||||
}
|
||||
case ENDED: {
|
||||
NS_NOTREACHED("trying to continue an ended file transfer");
|
||||
break;
|
||||
}
|
||||
}
|
||||
PR_CExitMonitor(this);
|
||||
return;
|
||||
|
||||
error:
|
||||
mState = ENDING;
|
||||
PR_CExitMonitor(this);
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -115,46 +233,10 @@ nsFileTransport::Resume(void)
|
|||
NS_IMETHODIMP
|
||||
nsFileTransport::Run(void)
|
||||
{
|
||||
nsresult rv;
|
||||
nsISupports* fs;
|
||||
nsIInputStream* fileStr = nsnull;
|
||||
nsIByteBufferInputStream* bufStr = nsnull;
|
||||
nsFileSpec spec(mPath);
|
||||
|
||||
rv = mListener->OnStartBinding(mContext); // always send the start notification
|
||||
if (NS_FAILED(rv)) goto done; // XXX should this abort the transfer?
|
||||
|
||||
rv = NS_NewTypicalInputFileStream(&fs, spec);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
rv = fs->QueryInterface(nsIInputStream::GetIID(), (void**)&fileStr);
|
||||
NS_RELEASE(fs);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
rv = NS_NewByteBufferInputStream(NS_FILE_TRANSPORT_BUFFER_SIZE, &bufStr);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
while (PR_TRUE) {
|
||||
PRUint32 amt;
|
||||
rv = bufStr->Fill(fileStr, &amt);
|
||||
if (rv == NS_BASE_STREAM_EOF) {
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
// and feed the buffer to the application via the byte buffer stream:
|
||||
rv = mListener->OnDataAvailable(mContext, bufStr, amt); // XXX maybe amt should be bufStr->GetLength()
|
||||
if (NS_FAILED(rv)) break;
|
||||
while (mState != ENDED && mState != SUSPENDED) {
|
||||
Continue();
|
||||
}
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(bufStr);
|
||||
NS_IF_RELEASE(fileStr);
|
||||
|
||||
// XXX where do we get the error message?
|
||||
rv = mListener->OnStopBinding(mContext, rv, nsnull);
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
class nsFileTransportService;
|
||||
class nsIInputStream;
|
||||
class nsIString;
|
||||
class nsIByteBufferInputStream;
|
||||
|
||||
class nsFileTransport : public nsITransport, public nsIRunnable
|
||||
{
|
||||
|
@ -47,16 +48,30 @@ public:
|
|||
virtual ~nsFileTransport();
|
||||
|
||||
nsresult Init(const char* path,
|
||||
nsISupports* context,
|
||||
nsIStreamListener* listener,
|
||||
PLEventQueue* appEventQueue,
|
||||
nsISupports* context);
|
||||
nsFileTransportService* service);
|
||||
void Continue(void);
|
||||
|
||||
enum State {
|
||||
STARTING,
|
||||
RUNNING,
|
||||
SUSPENDED,
|
||||
ENDING,
|
||||
ENDED
|
||||
};
|
||||
|
||||
protected:
|
||||
nsISupports* mContext;
|
||||
char* mPath;
|
||||
nsIStreamListener* mListener;
|
||||
PRBool mCanceled;
|
||||
|
||||
char* mPath;
|
||||
nsISupports* mContext;
|
||||
nsIStreamListener* mListener;
|
||||
nsFileTransportService* mService;
|
||||
State mState;
|
||||
|
||||
// state variables:
|
||||
nsIInputStream* mFileStream;
|
||||
nsIByteBufferInputStream* mBufferStream;
|
||||
nsresult mStatus;
|
||||
};
|
||||
|
||||
#define NS_FILE_TRANSPORT_BUFFER_SIZE (4*1024)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "nsIFileStream.h"
|
||||
#include "prcmon.h"
|
||||
#include "prmem.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsFileTransportService methods:
|
||||
|
@ -43,23 +44,31 @@ nsFileTransportService::Init()
|
|||
|
||||
nsFileTransportService::~nsFileTransportService()
|
||||
{
|
||||
// this will wait for all outstanding requests to be processed, then
|
||||
// join with the worker threads, and finally free the pool:
|
||||
NS_IF_RELEASE(mPool);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsFileTransportService, nsIFileTransportService::GetIID());
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileTransportService::AsyncRead(PLEventQueue* appEventQueue,
|
||||
nsFileTransportService::AsyncRead(const char* path,
|
||||
nsISupports* context,
|
||||
PLEventQueue* appEventQueue,
|
||||
nsIStreamListener* listener,
|
||||
const char* path,
|
||||
nsITransport* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsFileTransport* trans = new nsFileTransport();
|
||||
if (trans == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = trans->Init(path, listener, appEventQueue, context);
|
||||
nsIStreamListener* asyncListener;
|
||||
rv = NS_NewAsyncStreamListener(&asyncListener, appEventQueue, listener);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = trans->Init(path, context, asyncListener, this);
|
||||
NS_RELEASE(asyncListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete trans;
|
||||
return rv;
|
||||
|
@ -77,19 +86,90 @@ nsFileTransportService::AsyncRead(PLEventQueue* appEventQueue,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileTransportService::AsyncWrite(PLEventQueue* appEventQueue,
|
||||
nsISupports* context,
|
||||
nsIStreamObserver* observer,
|
||||
nsFileTransportService::AsyncWrite(nsIInputStream* fromStream,
|
||||
const char* path,
|
||||
nsISupports* context,
|
||||
PLEventQueue* appEventQueue,
|
||||
nsIStreamObserver* observer,
|
||||
nsITransport* *result)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileTransportService::Shutdown()
|
||||
nsFileTransportService::OpenInputStream(const char* path,
|
||||
nsISupports* context,
|
||||
nsIInputStream* *result)
|
||||
{
|
||||
return mPool->Shutdown();
|
||||
nsresult rv;
|
||||
nsFileTransport* trans = new nsFileTransport();
|
||||
if (trans == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsIStreamListener* syncListener;
|
||||
nsIInputStream* inStr;
|
||||
rv = NS_NewSyncStreamListener(&syncListener, &inStr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = trans->Init(path, context, syncListener, this);
|
||||
NS_RELEASE(syncListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(inStr);
|
||||
delete trans;
|
||||
return rv;
|
||||
}
|
||||
NS_ADDREF(trans);
|
||||
|
||||
rv = mPool->DispatchRequest(NS_STATIC_CAST(nsIRunnable*, trans));
|
||||
NS_RELEASE(trans);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(inStr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
*result = inStr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileTransportService::OpenOutputStream(const char* path,
|
||||
nsISupports* context,
|
||||
nsIOutputStream* *result)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileTransportService::ProcessPendingRequests(void)
|
||||
{
|
||||
return mPool->ProcessPendingRequests();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
nsFileTransportService::Suspend(nsFileTransport* request)
|
||||
{
|
||||
nsresult rv;
|
||||
if (mSuspended == nsnull) {
|
||||
rv = NS_NewISupportsArray(&mSuspended);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
return mSuspended->AppendElement(NS_STATIC_CAST(nsITransport*, request));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFileTransportService::Resume(nsFileTransport* request)
|
||||
{
|
||||
nsresult rv;
|
||||
if (mSuspended == nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
rv = mSuspended->RemoveElement(NS_STATIC_CAST(nsITransport*, request));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// restart the request
|
||||
rv = mPool->DispatchRequest(NS_STATIC_CAST(nsIRunnable*, request));
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "nscore.h"
|
||||
#include "plevent.h"
|
||||
|
||||
class nsFileTransport;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define NS_FILE_TRANSPORT_WORKER_COUNT 4
|
||||
|
@ -35,26 +37,36 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFileTransportService methods:
|
||||
NS_IMETHOD AsyncRead(PLEventQueue* appEventQueue,
|
||||
NS_IMETHOD AsyncRead(const char* path,
|
||||
nsISupports* context,
|
||||
PLEventQueue* appEventQueue,
|
||||
nsIStreamListener* listener,
|
||||
const char* path,
|
||||
nsITransport* *result);
|
||||
NS_IMETHOD AsyncWrite(PLEventQueue* appEventQueue,
|
||||
nsISupports* context,
|
||||
nsIStreamObserver* observer,
|
||||
NS_IMETHOD AsyncWrite(nsIInputStream* fromStream,
|
||||
const char* path,
|
||||
nsISupports* context,
|
||||
PLEventQueue* appEventQueue,
|
||||
nsIStreamObserver* observer,
|
||||
nsITransport* *result);
|
||||
NS_IMETHOD Shutdown();
|
||||
NS_IMETHOD OpenInputStream(const char* path,
|
||||
nsISupports* context,
|
||||
nsIInputStream* *result);
|
||||
NS_IMETHOD OpenOutputStream(const char* path,
|
||||
nsISupports* context,
|
||||
nsIOutputStream* *result);
|
||||
NS_IMETHOD ProcessPendingRequests(void);
|
||||
|
||||
// nsFileTransportService methods:
|
||||
nsFileTransportService();
|
||||
virtual ~nsFileTransportService();
|
||||
|
||||
nsresult Init();
|
||||
nsresult Suspend(nsFileTransport* request);
|
||||
nsresult Resume(nsFileTransport* request);
|
||||
|
||||
protected:
|
||||
nsIThreadPool* mPool;
|
||||
nsISupportsArray* mSuspended;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -306,9 +306,9 @@ nsMarshalingStreamListener::OnStopBinding(nsISupports* context,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewMarshalingStreamListener(PLEventQueue* eventQueue,
|
||||
nsIStreamListener* receiver,
|
||||
nsIStreamListener* *result)
|
||||
NS_NewAsyncStreamListener(nsIStreamListener* *result,
|
||||
PLEventQueue* eventQueue,
|
||||
nsIStreamListener* receiver)
|
||||
{
|
||||
nsMarshalingStreamListener* l =
|
||||
new nsMarshalingStreamListener(eventQueue, receiver);
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/* -*- 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 "nsIStreamListener.h"
|
||||
#include "nsIByteBufferInputStream.h"
|
||||
#include "nsIString.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsSyncStreamListener : public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIStreamListener methods:
|
||||
NS_IMETHOD OnStartBinding(nsISupports* context);
|
||||
NS_IMETHOD OnDataAvailable(nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aLength);
|
||||
NS_IMETHOD OnStopBinding(nsISupports* context,
|
||||
nsresult aStatus,
|
||||
nsIString* aMsg);
|
||||
|
||||
// nsSyncStreamListener methods:
|
||||
nsSyncStreamListener()
|
||||
: mOutputStream(nsnull) {
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
virtual ~nsSyncStreamListener();
|
||||
|
||||
nsresult Init(nsIInputStream* *result);
|
||||
|
||||
protected:
|
||||
nsIByteBufferOutputStream* mOutputStream;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
nsSyncStreamListener::Init(nsIInputStream* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIInputStream* in;
|
||||
nsIOutputStream* out;
|
||||
|
||||
rv = NS_NewPipe(&in, &out);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = out->QueryInterface(nsIByteBufferOutputStream::GetIID(), (void**)&mOutputStream);
|
||||
NS_RELEASE(out);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(in);
|
||||
return rv;
|
||||
}
|
||||
*result = in;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsSyncStreamListener::~nsSyncStreamListener()
|
||||
{
|
||||
NS_IF_RELEASE(mOutputStream);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsSyncStreamListener);
|
||||
NS_IMPL_RELEASE(nsSyncStreamListener);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSyncStreamListener::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
NS_ASSERTION(aInstancePtr, "no instance pointer");
|
||||
if (aIID.Equals(nsIStreamListener::GetIID()) ||
|
||||
aIID.Equals(nsIStreamObserver::GetIID()) ||
|
||||
aIID.Equals(nsISupports::GetIID())) {
|
||||
*aInstancePtr = NS_STATIC_CAST(nsIStreamListener*, this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSyncStreamListener::OnStartBinding(nsISupports* context)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSyncStreamListener::OnDataAvailable(nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 amt;
|
||||
PRInt32 count = (PRInt32)aLength;
|
||||
while (count > 0) {
|
||||
rv = mOutputStream->Write(aIStream, &amt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
count -= amt;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSyncStreamListener::OnStopBinding(nsISupports* context,
|
||||
nsresult aStatus,
|
||||
nsIString* aMsg)
|
||||
{
|
||||
// XXX what do we do with the status and error message?
|
||||
return mOutputStream->Close();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewSyncStreamListener(nsIStreamListener* *listener,
|
||||
nsIInputStream* *inStream)
|
||||
{
|
||||
nsSyncStreamListener* l = new nsSyncStreamListener();
|
||||
if (l == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = l->Init(inStream);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete l;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_ADDREF(l);
|
||||
*listener = l;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -20,9 +20,18 @@
|
|||
#include "nscore.h"
|
||||
#include "nsIUrl.h"
|
||||
#include "nsIHttpEventSink.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
//#include "nsISocketTransportService.h"
|
||||
#include "nsIFileTransportService.h" // XXX temporary
|
||||
|
||||
//static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
|
||||
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID); // XXX temporary
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHttpProtocolConnection::nsHttpProtocolConnection()
|
||||
: mUrl(nsnull), mEventSink(nsnull)
|
||||
: mUrl(nsnull), mEventSink(nsnull), mConnected(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -68,54 +77,62 @@ nsHttpProtocolConnection::Init(nsIUrl* url, nsISupports* eventSink)
|
|||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::Cancel(void)
|
||||
{
|
||||
return NS_OK;
|
||||
if (!mConnected)
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::Suspend(void)
|
||||
{
|
||||
return NS_OK;
|
||||
if (!mConnected)
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::Resume(void)
|
||||
{
|
||||
return NS_OK;
|
||||
if (!mConnected)
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIProtocolConnection methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::Open(nsIUrl* url, nsISupports* eventSink)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::GetContentType(char* *contentType)
|
||||
{
|
||||
return NS_OK;
|
||||
if (!mConnected)
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::GetInputStream(nsIInputStream* *result)
|
||||
{
|
||||
return NS_OK;
|
||||
if (!mConnected)
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::GetOutputStream(nsIOutputStream* *result)
|
||||
{
|
||||
return NS_OK;
|
||||
if (!mConnected)
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::AsyncWrite(nsIInputStream* data, PRUint32 count,
|
||||
nsresult (*callback)(void* closure, PRUint32 count),
|
||||
void* closure)
|
||||
nsresult (*callback)(void* closure, PRUint32 count),
|
||||
void* closure)
|
||||
{
|
||||
return NS_OK;
|
||||
if (!mConnected)
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -124,25 +141,32 @@ nsHttpProtocolConnection::AsyncWrite(nsIInputStream* data, PRUint32 count,
|
|||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::Get(void)
|
||||
{
|
||||
return NS_OK;
|
||||
nsresult rv;
|
||||
// NS_WITH_SERVICE(nsISocketTransportService, sts, kSocketTransportServiceCID, &rv);
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, sts, kFileTransportServiceCID, &rv);
|
||||
|
||||
// rv = sts->AsyncWrite();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::GetByteRange(PRUint32 from, PRUint32 to)
|
||||
{
|
||||
return NS_OK;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::Put(void)
|
||||
{
|
||||
return NS_OK;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpProtocolConnection::Post(void)
|
||||
{
|
||||
return NS_OK;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -35,7 +35,6 @@ public:
|
|||
NS_IMETHOD Resume(void);
|
||||
|
||||
// nsIProtocolConnection methods:
|
||||
NS_IMETHOD Open(nsIUrl* url, nsISupports* eventSink);
|
||||
NS_IMETHOD GetContentType(char* *contentType);
|
||||
NS_IMETHOD GetInputStream(nsIInputStream* *result);
|
||||
NS_IMETHOD GetOutputStream(nsIOutputStream* *result);
|
||||
|
@ -58,6 +57,7 @@ public:
|
|||
protected:
|
||||
nsIUrl* mUrl;
|
||||
nsIHttpEventSink* mEventSink;
|
||||
PRBool mConnected;
|
||||
};
|
||||
|
||||
#endif /* nsHttpProtocolConnection_h___ */
|
||||
|
|
|
@ -182,7 +182,7 @@ Simulated_nsFileTransport_Run(nsReader* reader, const char* path)
|
|||
NS_RELEASE(fs);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
rv = NS_NewByteBufferInputStream(NS_FILE_TRANSPORT_BUFFER_SIZE, &bufStr);
|
||||
rv = NS_NewByteBufferInputStream(&bufStr, PR_FALSE, NS_FILE_TRANSPORT_BUFFER_SIZE);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
while (PR_TRUE) {
|
||||
|
@ -301,8 +301,8 @@ ParallelReadTest(char* dirName, nsIFileTransportService* fts)
|
|||
NS_ASSERTION(listener, "QI failed");
|
||||
|
||||
nsITransport* trans;
|
||||
rv = fts->AsyncRead(reader->GetEventQueue(),
|
||||
nsnull, listener, spec, &trans);
|
||||
rv = fts->AsyncRead(spec, nsnull, reader->GetEventQueue(),
|
||||
listener, &trans);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "AsyncRead failed");
|
||||
|
||||
// the reader thread will hang on to these objects until it quits
|
||||
|
@ -348,7 +348,7 @@ main(int argc, char* argv[])
|
|||
SerialReadTest(dirName);
|
||||
ParallelReadTest(dirName, fts);
|
||||
|
||||
fts->Shutdown();
|
||||
fts->ProcessPendingRequests();
|
||||
|
||||
printf("duration %d ms, volume %d\n",
|
||||
PR_IntervalToMilliseconds(gDuration),
|
||||
|
|
Загрузка…
Ссылка в новой задаче