Added synchronous file input. Worked on cancel/suspend/resume work for file transfer.

This commit is contained in:
warren%netscape.com 1999-04-13 18:10:15 +00:00
Родитель 9424f0948b
Коммит 8f99982227
15 изменённых файлов: 573 добавлений и 148 удалений

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

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