Bug 62566. nsIChannel::AsyncWrite interface revision and related cleanup.

r=dougt@netcape.com, sr=mscott@netscape.com.
This commit is contained in:
darin%netscape.com 2001-01-23 22:10:34 +00:00
Родитель ef7f12f026
Коммит 6bfaf3912c
73 изменённых файлов: 4428 добавлений и 2056 удалений

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

@ -557,6 +557,7 @@ sub BuildClientDist()
InstallFromManifest(":mozilla:uriloader:exthandler:MANIFEST_IDL", "$distdirectory:idl:");
#NETWERK
InstallFromManifest(":mozilla:netwerk:build:MANIFEST", "$distdirectory:netwerk:");
InstallFromManifest(":mozilla:netwerk:base:public:MANIFEST", "$distdirectory:netwerk:");
InstallFromManifest(":mozilla:netwerk:base:public:MANIFEST_IDL", "$distdirectory:idl:");
InstallFromManifest(":mozilla:netwerk:socket:base:MANIFEST_IDL", "$distdirectory:idl:");

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

@ -271,7 +271,7 @@ nsCachedChromeChannel::AsyncRead(nsIStreamListener *listener, nsISupports *ctxt)
}
NS_IMETHODIMP
nsCachedChromeChannel::AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt)
nsCachedChromeChannel::AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;

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

@ -349,7 +349,7 @@ public:
NS_IMETHOD OpenOutputStream(nsIOutputStream **_retval) { *_retval = nsnull; return NS_OK; }
NS_IMETHOD AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncRead(nsIStreamListener *listener, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes) { *aLoadAttributes = nsIChannel::LOAD_NORMAL; return NS_OK; }
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes) { return NS_OK; }
NS_IMETHOD GetContentType(char * *aContentType) { *aContentType = nsnull; return NS_OK; }

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

@ -219,7 +219,7 @@ NS_IMETHODIMP nsWebBrowserPersist::SaveURI(nsIURI *aURI, nsIInputStream *aPostDa
mInputStream = inStream;
// Get the output channel ready for writing
rv = outputChannel->AsyncWrite(inStream, NS_STATIC_CAST(nsIStreamObserver *, this), nsnull);
rv = NS_AsyncWriteFromStream(outputChannel, inStream, NS_STATIC_CAST(nsIStreamObserver *, this), nsnull);
if (NS_FAILED(rv))
{
OnEndDownload();

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

@ -202,8 +202,7 @@ nsDateTimeChannel::AsyncRead(nsIStreamListener *aListener,
}
NS_IMETHODIMP
nsDateTimeChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsDateTimeChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{
NS_NOTREACHED("nsDateTimeChannel::AsyncWrite");

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

@ -32,6 +32,7 @@
#include "nsMimeTypes.h"
#include "nsIStreamConverterService.h"
#include "nsITXTToHTMLConv.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
@ -250,8 +251,7 @@ nsFingerChannel::AsyncRead(nsIStreamListener *aListener, nsISupports *ctxt)
}
NS_IMETHODIMP
nsFingerChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsFingerChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{
NS_NOTREACHED("nsFingerChannel::AsyncWrite");
@ -540,7 +540,7 @@ nsFingerChannel::SendRequest(nsIChannel* aChannel) {
rv = aChannel->SetTransferCount(requestBuffer.Length());
if (NS_FAILED(rv)) return rv;
rv = aChannel->AsyncWrite(charstream, this, 0);
rv = NS_AsyncWriteFromStream(aChannel, charstream, this, nsnull);
return rv;
}

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

@ -316,8 +316,8 @@ NS_IMETHODIMP nsDOMParserChannel::AsyncRead(nsIStreamListener *listener, nsISupp
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void asyncWrite (in nsIInputStream fromStream, in nsIStreamObserver observer, in nsISupports ctxt); */
NS_IMETHODIMP nsDOMParserChannel::AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt)
/* void asyncWrite (in nsIStreamProvider provider, in nsISupports ctxt); */
NS_IMETHODIMP nsDOMParserChannel::AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

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

@ -656,9 +656,8 @@ public:
NS_IMETHOD SetURI(nsIURI* aURI) { gURI = aURI; NS_ADDREF(gURI); return NS_OK; }
NS_IMETHOD OpenInputStream(nsIInputStream **_retval) { *_retval = nsnull; return NS_OK; }
NS_IMETHOD OpenOutputStream(nsIOutputStream **_retval) { *_retval = nsnull; return NS_OK; }
NS_IMETHOD AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncRead(nsIStreamListener *listener, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes) { *aLoadAttributes = nsIChannel::LOAD_NORMAL; return NS_OK; }
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes) { return NS_OK; }
NS_IMETHOD GetContentType(char * *aContentType) { *aContentType = nsnull; return NS_OK; }

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

@ -656,9 +656,8 @@ public:
NS_IMETHOD SetURI(nsIURI* aURI) { gURI = aURI; NS_ADDREF(gURI); return NS_OK; }
NS_IMETHOD OpenInputStream(nsIInputStream **_retval) { *_retval = nsnull; return NS_OK; }
NS_IMETHOD OpenOutputStream(nsIOutputStream **_retval) { *_retval = nsnull; return NS_OK; }
NS_IMETHOD AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncRead(nsIStreamListener *listener, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes) { *aLoadAttributes = nsIChannel::LOAD_NORMAL; return NS_OK; }
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes) { return NS_OK; }
NS_IMETHOD GetContentType(char * *aContentType) { *aContentType = nsnull; return NS_OK; }

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

@ -416,7 +416,7 @@ NS_IMETHODIMP nsMsgProtocol::AsyncRead(nsIStreamListener *listener, nsISupports
return LoadUrl(m_url, nsnull);
}
NS_IMETHODIMP nsMsgProtocol::AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt)
NS_IMETHODIMP nsMsgProtocol::AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt)
{
NS_NOTREACHED("AsyncWrite");
return NS_ERROR_NOT_IMPLEMENTED;

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

@ -341,7 +341,7 @@ NS_IMETHODIMP nsMailtoChannel::AsyncRead(nsIStreamListener *listener, nsISupport
return listener->OnStartRequest(this, ctxt);
}
NS_IMETHODIMP nsMailtoChannel::AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt)
NS_IMETHODIMP nsMailtoChannel::AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt)
{
NS_NOTREACHED("AsyncWrite");
return NS_ERROR_NOT_IMPLEMENTED;

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

@ -7008,7 +7008,7 @@ NS_IMETHODIMP nsImapMockChannel::AsyncRead(nsIStreamListener *listener, nsISuppo
return rv;
}
NS_IMETHODIMP nsImapMockChannel::AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt)
NS_IMETHODIMP nsImapMockChannel::AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt)
{
NS_NOTREACHED("nsImapMockChannel::AsyncWrite");
return NS_ERROR_NOT_IMPLEMENTED;

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

@ -392,8 +392,7 @@ nsJARChannel::AsyncReadJARElement()
}
NS_IMETHODIMP
nsJARChannel::AsyncWrite(nsIInputStream* fromStream,
nsIStreamObserver* observer,
nsJARChannel::AsyncWrite(nsIStreamProvider* provider,
nsISupports* ctxt)
{
NS_NOTREACHED("nsJARChannel::AsyncWrite");

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

@ -28,7 +28,7 @@
* nsISupports implementation
*--------------------------------------------*/
NS_IMPL_ISUPPORTS1(nsJARInputStream, nsIInputStream);
NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARInputStream, nsIInputStream);
/*----------------------------------------------------------
* nsJARInputStream implementation

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

@ -19,6 +19,7 @@ nsIStreamListener.idl
nsIStreamLoader.idl
nsIDownloader.idl
nsIStreamObserver.idl
nsIStreamProvider.idl
nsIURI.idl
nsIURL.idl
nsIURLParser.idl

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

@ -51,10 +51,11 @@ XPIDLSRCS = \
nsISocketTransport.idl \
nsISocketTransportService.idl \
nsIStreamIO.idl \
nsIStreamObserver.idl \
nsIStreamListener.idl \
nsIStreamProvider.idl \
nsIStreamLoader.idl \
nsISocketTransport.idl \
nsIStreamObserver.idl \
nsIURI.idl \
nsIURL.idl \
nsIURLParser.idl \

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

@ -54,6 +54,7 @@ XPIDLSRCS = \
.\nsISocketTransportService.idl \
.\nsIStreamIO.idl \
.\nsIStreamListener.idl \
.\nsIStreamProvider.idl \
.\nsIStreamLoader.idl \
.\nsIDownloader.idl \
.\nsIStreamObserver.idl \

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -27,6 +27,7 @@ interface nsIInputStream;
interface nsIOutputStream;
interface nsIStreamObserver;
interface nsIStreamListener;
interface nsIStreamProvider;
interface nsILoadGroup;
interface nsIInterfaceRequestor;
interface nsIFile;
@ -43,7 +44,7 @@ typedef unsigned long nsLoadFlags;
* request can be issued in one of several ways:
*
* - AsyncRead and AsyncWrite allow for asynchronous requests, calling
* back the user's stream listener or observer,
* back the user's stream listener or provider,
* - OpenInputStream and OpenOutputStream allow for synchronous reads
* and writes on the underlying channel.
*
@ -187,7 +188,7 @@ interface nsIChannel : nsIRequest
readonly attribute nsIFile localFile;
/**
* Setting pipeliningAllowed causes the load of a URL (issued via asyncOpen,
* Setting pipeliningAllowed causes the load of a URL (issued via
* asyncRead or asyncWrite) to be deferred in order to allow the request to
* be pipelined for greater throughput efficiency. Pipelined requests will
* be forced to load when the first non-pipelined request is issued.
@ -209,13 +210,16 @@ interface nsIChannel : nsIRequest
*/
const unsigned long LOAD_NORMAL = 0;
/**
* Don't deliver status notifications to the nsIProgressEventSink, or keep
* this load from completing the nsILoadGroup it may belong to:
*/
const unsigned long LOAD_BACKGROUND = 1 << 0;
/**
* Used exclusively by the uriloader and docshell to indicate whether or
* not this channel corresponds to the toplevel document.
*/
const unsigned long LOAD_DOCUMENT_URI = 1 << 1;
/**
@ -288,45 +292,35 @@ interface nsIChannel : nsIRequest
////////////////////////////////////////////////////////////////////////////
/**
* Opens a blocking input stream to the URL's specified source.
* @param startPosition - The offset from the start of the data
* from which to read.
* @param readCount - The number of bytes to read. If -1, everything
* up to the end of the data is read. If greater than the end of
* the data, the amount available is returned in the stream.
* Opens a blocking input stream to the URI's specified source. This
* call may block until the input stream is available.
*/
nsIInputStream openInputStream();
/**
* Opens a blocking output stream to the URL's specified destination.
* @param startPosition - The offset from the start of the data
* from which to begin writing.
* Opens a blocking output stream to the URI's specified destination. This
* call may block until the output stream is available.
*/
nsIOutputStream openOutputStream();
/**
* Reads asynchronously from the URL's specified source. Notifications
* are provided to the stream listener on the thread of the specified
* event queue.
* The startPosition argument designates the offset in the source where
* the data will be read.
* If the readCount == -1 then all the available data is delivered to
* the stream listener.
* Reads asynchronously from the URI's specified source. Notifications
* are provided to the stream listener on the calling thread.
*
* @param listener - notification handler.
* @param ctxt - application context passed to methods invoked on listener.
*/
void asyncRead(in nsIStreamListener listener,
in nsISupports ctxt);
/**
* Writes asynchronously to the URL's specified destination. Notifications
* are provided to the stream observer on the thread of the specified
* event queue.
* The startPosition argument designates the offset in the destination where
* the data will be written.
* If the writeCount == -1, then all the available data in the input
* stream is written.
* Writes asynchronously to the URI's specified destination. Notifications
* are provided to the stream provider on the calling thread.
*
* @param provider - notification handler.
* @param ctxt - application context passed to methods invoked on provider.
*/
void asyncWrite(in nsIInputStream fromStream,
in nsIStreamObserver observer,
void asyncWrite(in nsIStreamProvider provider,
in nsISupports ctxt);
};

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -22,21 +22,85 @@
#include "nsIStreamObserver.idl"
interface nsIInputStream;
interface nsIChannel;
interface nsIInputStream;
interface nsIOutputStream;
interface nsIEventQueue;
/**
* The nsIChannel::AsyncRead notification handler. It accepts
* data from the channel, when the channel is ready to provide it.
*/
[scriptable, uuid(1a637020-1482-11d3-9333-00104ba0fd40)]
interface nsIStreamListener : nsIStreamObserver
{
/**
* Called when there is data to be read from the channel.
*
* @param channel - the channel being read
* @param ctxt - opaque parameter passed to AsyncRead
* @param input - temporary input stream for reading data chunk
* @param offset - current stream position (informational)
* @param count - number of bytes that can be read without blocking
*
* @return NS_OK - if successfully read something.
* @return NS_BASE_STREAM_CLOSED - if done reading data. NOTE: this is
* NOT equivalent to reading zero bytes and returning NS_OK.
* @return NS_BASE_STREAM_WOULD_BLOCK - if no data can be read at
* this time. This implicitly calls Suspend on the channel. Call
* Resume on the channel to continue the AsyncRead when more data
* becomes available.
* @return <other-error> - if failure.
*/
void onDataAvailable(in nsIChannel channel,
in nsISupports ctxt,
in nsIInputStream inStr,
in unsigned long sourceOffset,
in nsIInputStream input,
in unsigned long offset,
in unsigned long count);
};
/**
* A stream listener proxy is used to ship data over to another thread specified
* by the thread's event queue. The "true" stream listener's methods are
* invoked on the other thread.
*
* This interface only provides the initialization needed after construction.
* Otherwise, these objects may be used as a nsIStreamListener.
*/
[scriptable, uuid(e400e688-6b54-4a84-8c4e-56b40281981a)]
interface nsIStreamListenerProxy : nsIStreamListener
{
/**
* Initializes an nsIStreamListenerProxy.
*
* @param listener - receives listener notifications on the other thread
* @param eventQ - may be NULL indicating the calling thread's event queue
* @param bufferSegmentSize - passing zero indicates the default
* @param bufferMaxSize - passing zero indicates the default
*/
void init(in nsIStreamListener listener,
in nsIEventQueue eventQ,
in unsigned long bufferSegmentSize,
in unsigned long bufferMaxSize);
};
/**
* A simple stream listener can be used with AsyncRead to supply data to
* a output stream.
*/
[scriptable, uuid(a9b84f6a-0824-4278-bae6-bfca0570a26e)]
interface nsISimpleStreamListener : nsIStreamListener
{
/**
* Initialize the simple stream listener.
*
* @param sink - data will be read from the channel to this output stream
* @param observer - optional stream observer (can be NULL)
*/
void init(in nsIOutputStream sink,
in nsIStreamObserver observer);
};
/**
* 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
@ -55,42 +119,3 @@ interface nsIAsyncStreamListener : nsIStreamListener
void init(in nsIStreamListener receiver,
in nsIEventQueue eventQueue);
};
/**
* A synchronous stream listener pushes data through a pipe that ends up
* in an input stream to be read by another thread.
*
* This interface only provides the initialization needed after construction. Otherwise,
* these objects are used simply as nsIStreamListener.
*/
[scriptable, uuid(1f9fb93e-91bf-11d3-8cd9-0060b0fc14a3)]
interface nsISyncStreamListener : nsIStreamListener
{
/**
* Initializes an nsISyncStreamListener.
*/
void init(out nsIInputStream inStream,
out nsIOutputStream outStream);
};
%{C++
// Use this CID to construct an nsIAsyncStreamListener
#define NS_ASYNCSTREAMLISTENER_CID \
{ /* 60047bb2-91c0-11d3-8cd9-0060b0fc14a3 */ \
0x60047bb2, \
0x91c0, \
0x11d3, \
{0x8c, 0xd9, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
}
// Use this CID to construct an nsISyncStreamListener
#define NS_SYNCSTREAMLISTENER_CID \
{ /* 65fa5cb2-91c0-11d3-8cd9-0060b0fc14a3 */ \
0x65fa5cb2, \
0x91c0, \
0x11d3, \
{0x8c, 0xd9, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
}
%}

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -22,27 +22,55 @@
#include "nsISupports.idl"
interface nsIEventQueue;
interface nsIChannel;
interface nsIEventQueue;
[scriptable, uuid(fd91e2e0-1481-11d3-9333-00104ba0fd40)]
interface nsIStreamObserver : nsISupports
{
/**
* Called to signify the beginning of an asyncronous request.
* Called to signify the beginning of an asynchronous request.
*
* @param channel - channel being observed
* @param ctxt - user specified data passed to AsyncRead/Write
*/
void onStartRequest(in nsIChannel channel,
in nsISupports ctxt);
/**
* Called to signify the end of an asyncronous request.
* @param notif - a notification object containing any error code and error parameters
* (may be null if the notification status is NS_OK)
* Called to signify the end of an asynchronous request. This
* call is always preceded by a call to onStartRequest.
*
* @param channel - channel being observed
* @param ctxt - user specified data passed to AsyncRead/Write
* @param statusCode - reason for stopping (NS_OK if completed successfully)
* @param statusText - human readable reason for stopping (can be NULL)
*/
void onStopRequest(in nsIChannel channel,
in nsISupports ctxt,
in nsresult status,
in wstring statusArg);
in nsresult statusCode,
in wstring statusText);
};
/**
* A stream observer proxy is used to ship data over to another thread specified
* by the thread's event queue. The "true" stream observer's methods are
* invoked on the other thread.
*
* This interface only provides the initialization needed after construction. Otherwise,
* these objects are used simply as nsIStreamObserver's.
*/
[scriptable, uuid(3c9b532e-db84-4ecf-aa6a-4d38a9c4c5f0)]
interface nsIStreamObserverProxy : nsIStreamObserver
{
/**
* Initializes an nsIStreamObserverProxy.
*
* @param observer - receives observer notifications on the other thread
* @param eventQ - may be NULL indicating the calling thread's event queue
*/
void init(in nsIStreamObserver observer,
in nsIEventQueue eventQ);
};
/**
@ -65,22 +93,8 @@ interface nsIAsyncStreamObserver : nsIStreamObserver
};
%{C++
// Use this CID to construct an nsIAsyncStreamObserver
#define NS_ASYNCSTREAMOBSERVER_CID \
{ /* fcc7c380-91b3-11d3-8cd9-0060b0fc14a3 */ \
0xfcc7c380, \
0x91b3, \
0x11d3, \
{0x8c, 0xd9, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
}
////////////////////////////////////////////////////////////////////////////////
// Generic status codes for OnStopRequest:
#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)
#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)
%}

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

@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsIStreamObserver.idl"
interface nsIChannel;
interface nsIInputStream;
interface nsIOutputStream;
interface nsIEventQueue;
/**
* The nsIChannel::AsyncWrite notification handler. It provides
* data to the channel, when the channel is ready to accept it.
*/
[scriptable, uuid(d10ef7a9-b728-43d4-9c49-74172186d691)]
interface nsIStreamProvider : nsIStreamObserver
{
/**
* Called when data may be written to the channel.
*
* @param channel - the channel being written to
* @param ctxt - opaque parameter passed to AsyncWrite
* @param output - output stream for writing data chunk
* @param offset - current stream position (informational)
* @param count - number of bytes that can be written without blocking
*
* @return NS_OK - if successfully wrote something.
* @return NS_BASE_STREAM_CLOSED - if done writing data. NOTE: this is
* NOT equivalent to writing zero bytes and returning NS_OK.
* @return NS_BASE_STREAM_WOULD_BLOCK - if no data can be written at
* this time. This implicitly calls Suspend on the channel. Call
* Resume on the channel to continue the AsyncWrite when more data
* becomes available.
* @return <other-error> - if failure.
*/
void onDataWritable(in nsIChannel channel,
in nsISupports ctxt,
in nsIOutputStream output,
in unsigned long offset,
in unsigned long count);
};
/**
* A stream provider proxy is used to ship data over to another thread specified
* by the thread's event queue. The "true" stream provider's methods are
* invoked on the other thread.
*
* This interface only provides the initialization needed after construction.
* Otherwise, these objects may be used as a nsIStreamProvider.
*/
[scriptable, uuid(5c3b0bac-605a-49ac-880e-5c8b993f7d2b)]
interface nsIStreamProviderProxy : nsIStreamProvider
{
/**
* Initializes an nsIStreamProviderProxy.
*
* @param provider - receives provider notifications on the other thread.
* @param eventQ - may be NULL indicating the calling thread's event queue.
*/
void init(in nsIStreamProvider provider,
in nsIEventQueue eventQ,
in unsigned long bufferSegmentSize,
in unsigned long bufferMaxSize);
};
/**
* A simple stream provider can be used with AsyncWrite to supply data from
* an existing input stream.
*/
[scriptable, uuid(c20bb3b9-0755-4eff-9222-3537f9e89082)]
interface nsISimpleStreamProvider : nsIStreamProvider
{
/**
* Initialize the simple stream provider.
*
* @param - data will be read from this input stream to the channel
* @param - optional stream observer (can be NULL)
*/
void init(in nsIInputStream source,
in nsIStreamObserver observer);
};

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

@ -26,7 +26,9 @@
#include "nsIURI.h"
#include "netCore.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIStreamListener.h"
#include "nsIStreamProvider.h"
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "nsString.h"
@ -40,9 +42,12 @@
#include "nsIDownloader.h"
#include "nsIStreamLoader.h"
#include "nsIStreamIO.h"
#include "nsIPipe.h"
#include "nsXPIDLString.h"
#include "prio.h" // for read/write flags, permissions, etc.
#include "nsNetCID.h"
// Helper, to simplify getting the I/O service.
inline const nsGetServiceByCID
do_GetIOService(nsresult* error = 0)
@ -368,6 +373,139 @@ NS_NewStreamLoader(nsIStreamLoader* *result,
return rv;
}
inline nsresult
NS_NewStreamObserverProxy(nsIStreamObserver **aResult,
nsIStreamObserver *aObserver,
nsIEventQueue *aEventQ=nsnull)
{
NS_ENSURE_ARG_POINTER(aResult);
nsresult rv;
nsCOMPtr<nsIStreamObserverProxy> proxy;
static NS_DEFINE_CID(kStreamObserverProxyCID, NS_STREAMOBSERVERPROXY_CID);
rv = nsComponentManager::CreateInstance(kStreamObserverProxyCID,
nsnull,
NS_GET_IID(nsIStreamObserverProxy),
getter_AddRefs(proxy));
if (NS_FAILED(rv)) return rv;
rv = proxy->Init(aObserver, aEventQ);
if (NS_FAILED(rv)) return rv;
*aResult = proxy;
NS_ADDREF(*aResult);
return NS_OK;
}
inline nsresult
NS_NewStreamListenerProxy(nsIStreamListener **aResult,
nsIStreamListener *aListener,
nsIEventQueue *aEventQ=nsnull,
PRUint32 aBufferSegmentSize=0,
PRUint32 aBufferMaxSize=0)
{
NS_ENSURE_ARG_POINTER(aResult);
nsresult rv;
nsCOMPtr<nsIStreamListenerProxy> proxy;
static NS_DEFINE_CID(kStreamListenerProxyCID, NS_STREAMLISTENERPROXY_CID);
rv = nsComponentManager::CreateInstance(kStreamListenerProxyCID,
nsnull,
NS_GET_IID(nsIStreamListenerProxy),
getter_AddRefs(proxy));
if (NS_FAILED(rv)) return rv;
rv = proxy->Init(aListener, aEventQ, aBufferSegmentSize, aBufferMaxSize);
if (NS_FAILED(rv)) return rv;
*aResult = proxy;
NS_ADDREF(*aResult);
return NS_OK;
}
inline nsresult
NS_NewStreamProviderProxy(nsIStreamProvider **aResult,
nsIStreamProvider *aProvider,
nsIEventQueue *aEventQ=nsnull,
PRUint32 aBufferSegmentSize=0,
PRUint32 aBufferMaxSize=0)
{
NS_ENSURE_ARG_POINTER(aResult);
nsresult rv;
nsCOMPtr<nsIStreamProviderProxy> proxy;
static NS_DEFINE_CID(kStreamProviderProxyCID, NS_STREAMPROVIDERPROXY_CID);
rv = nsComponentManager::CreateInstance(kStreamProviderProxyCID,
nsnull,
NS_GET_IID(nsIStreamProviderProxy),
getter_AddRefs(proxy));
if (NS_FAILED(rv)) return rv;
rv = proxy->Init(aProvider, aEventQ, aBufferSegmentSize, aBufferMaxSize);
if (NS_FAILED(rv)) return rv;
*aResult = proxy;
NS_ADDREF(*aResult);
return NS_OK;
}
inline nsresult
NS_NewSimpleStreamListener(nsIStreamListener **aResult,
nsIOutputStream *aSink,
nsIStreamObserver *aObserver=nsnull)
{
NS_ENSURE_ARG_POINTER(aResult);
nsresult rv;
nsCOMPtr<nsISimpleStreamListener> listener;
static NS_DEFINE_CID(kSimpleStreamListenerCID, NS_SIMPLESTREAMLISTENER_CID);
rv = nsComponentManager::CreateInstance(kSimpleStreamListenerCID,
nsnull,
NS_GET_IID(nsISimpleStreamListener),
getter_AddRefs(listener));
if (NS_FAILED(rv)) return rv;
rv = listener->Init(aSink, aObserver);
if (NS_FAILED(rv)) return rv;
*aResult = listener.get();
NS_ADDREF(*aResult);
return NS_OK;
}
inline nsresult
NS_NewSimpleStreamProvider(nsIStreamProvider **aResult,
nsIInputStream *aSource,
nsIStreamObserver *aObserver=nsnull)
{
NS_ENSURE_ARG_POINTER(aResult);
nsresult rv;
nsCOMPtr<nsISimpleStreamProvider> provider;
static NS_DEFINE_CID(kSimpleStreamProviderCID, NS_SIMPLESTREAMPROVIDER_CID);
rv = nsComponentManager::CreateInstance(kSimpleStreamProviderCID,
nsnull,
NS_GET_IID(nsISimpleStreamProvider),
getter_AddRefs(provider));
if (NS_FAILED(rv)) return rv;
rv = provider->Init(aSource, aObserver);
if (NS_FAILED(rv)) return rv;
*aResult = provider.get();
NS_ADDREF(*aResult);
return NS_OK;
}
// Depracated, prefer NS_NewStreamObserverProxy
inline nsresult
NS_NewAsyncStreamObserver(nsIStreamObserver **result,
nsIStreamObserver *receiver,
@ -389,6 +527,7 @@ NS_NewAsyncStreamObserver(nsIStreamObserver **result,
return NS_OK;
}
// Depracated, prefer NS_NewStreamListenerProxy
inline nsresult
NS_NewAsyncStreamListener(nsIStreamListener **result,
nsIStreamListener *receiver,
@ -410,25 +549,79 @@ NS_NewAsyncStreamListener(nsIStreamListener **result,
return NS_OK;
}
// Depracated, prefer a true synchonous implementation
inline nsresult
NS_NewSyncStreamListener(nsIInputStream **inStream,
nsIOutputStream **outStream,
nsIStreamListener **listener)
NS_NewSyncStreamListener(nsIInputStream **aInStream,
nsIOutputStream **aOutStream,
nsIStreamListener **aResult)
{
nsresult rv;
nsCOMPtr<nsISyncStreamListener> lsnr;
static NS_DEFINE_CID(kSyncStreamListenerCID, NS_SYNCSTREAMLISTENER_CID);
rv = nsComponentManager::CreateInstance(kSyncStreamListenerCID,
nsnull,
NS_GET_IID(nsISyncStreamListener),
getter_AddRefs(lsnr));
if (NS_FAILED(rv)) return rv;
rv = lsnr->Init(inStream, outStream);
NS_ENSURE_ARG_POINTER(aInStream);
NS_ENSURE_ARG_POINTER(aOutStream);
nsCOMPtr<nsIInputStream> pipeIn;
nsCOMPtr<nsIOutputStream> pipeOut;
rv = NS_NewPipe(getter_AddRefs(pipeIn),
getter_AddRefs(pipeOut),
4*1024, // NS_SYNC_STREAM_LISTENER_SEGMENT_SIZE
32*1024); // NS_SYNC_STREAM_LISTENER_BUFFER_SIZE
if (NS_FAILED(rv)) return rv;
*listener = lsnr;
NS_ADDREF(*listener);
rv = NS_NewSimpleStreamListener(aResult, pipeOut);
if (NS_FAILED(rv)) return rv;
*aInStream = pipeIn;
NS_ADDREF(*aInStream);
*aOutStream = pipeOut;
NS_ADDREF(*aOutStream);
return NS_OK;
}
//
// Calls AsyncWrite on the specified channel, with a stream provider that
// reads data from the specified input stream.
//
inline nsresult
NS_AsyncWriteFromStream(nsIChannel *aChannel,
nsIInputStream *aSource,
nsIStreamObserver *aObserver=NULL,
nsISupports *aContext=NULL)
{
NS_ENSURE_ARG_POINTER(aChannel);
nsresult rv;
nsCOMPtr<nsIStreamProvider> provider;
rv = NS_NewSimpleStreamProvider(getter_AddRefs(provider),
aSource,
aObserver);
if (NS_FAILED(rv)) return rv;
return aChannel->AsyncWrite(provider, aContext);
}
//
// Calls AsyncRead on the specified channel, with a stream listener that
// writes data to the specified output stream.
//
inline nsresult
NS_AsyncReadToStream(nsIChannel *aChannel,
nsIOutputStream *aSink,
nsIStreamObserver *aObserver=NULL,
nsISupports *aContext=NULL)
{
NS_ENSURE_ARG_POINTER(aChannel);
nsresult rv;
nsCOMPtr<nsIStreamListener> listener;
rv = NS_NewSimpleStreamListener(getter_AddRefs(listener),
aSink,
aObserver);
if (NS_FAILED(rv)) return rv;
return aChannel->AsyncRead(listener, aContext);
}
#endif // nsNetUtil_h__

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

@ -34,13 +34,16 @@ CPPSRCS = \
nsURLHelper.cpp \
nsFileStreams.cpp \
nsBufferedStreams.cpp \
nsAsyncStreamListener.cpp \
nsSyncStreamListener.cpp \
nsIOService.cpp \
nsSocketTransport.cpp \
nsSocketTransportService.cpp \
nsFileTransport.cpp \
nsFileTransportService.cpp \
nsSimpleStreamListener.cpp \
nsSimpleStreamProvider.cpp \
nsStreamObserverProxy.cpp \
nsStreamListenerProxy.cpp \
nsStreamProviderProxy.cpp \
nsStdURLParser.cpp \
nsAuthURLParser.cpp \
nsNoAuthURLParser.cpp \
@ -55,6 +58,7 @@ CPPSRCS = \
nsDownloader.cpp \
nsProtocolProxyService.cpp \
nsProxyAutoConfigUtils.cpp \
nsAsyncStreamListener.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a

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

@ -30,13 +30,16 @@ CPP_OBJS = \
.\$(OBJDIR)\nsURLHelper.obj \
.\$(OBJDIR)\nsFileStreams.obj \
.\$(OBJDIR)\nsBufferedStreams.obj \
.\$(OBJDIR)\nsAsyncStreamListener.obj \
.\$(OBJDIR)\nsSyncStreamListener.obj \
.\$(OBJDIR)\nsIOService.obj \
.\$(OBJDIR)\nsSocketTransport.obj \
.\$(OBJDIR)\nsSocketTransportService.obj \
.\$(OBJDIR)\nsFileTransport.obj \
.\$(OBJDIR)\nsFileTransportService.obj \
.\$(OBJDIR)\nsSimpleStreamListener.obj \
.\$(OBJDIR)\nsSimpleStreamProvider.obj \
.\$(OBJDIR)\nsStreamObserverProxy.obj \
.\$(OBJDIR)\nsStreamListenerProxy.obj \
.\$(OBJDIR)\nsStreamProviderProxy.obj \
.\$(OBJDIR)\nsStdURLParser.obj \
.\$(OBJDIR)\nsAuthURLParser.obj \
.\$(OBJDIR)\nsNoAuthURLParser.obj \

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

@ -36,6 +36,12 @@ static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
PRLogModuleInfo* gStreamEventLog = 0;
#endif
// prevent name conflicts
#define nsStreamListenerEvent nsStreamListenerEvent0
#define nsOnStartRequestEvent nsOnStartRequestEvent0
#define nsOnStopRequestEvent nsOnStopRequestEvent0
#define nsOnDataAvailableEvent nsOnDataAvailableEvent0
////////////////////////////////////////////////////////////////////////////////
class nsStreamListenerEvent

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -32,6 +32,7 @@
#include "nsILoadGroup.h"
#include "nsCOMPtr.h"
#include "nsIStreamListener.h"
#include "nsIStreamProvider.h"
#include "nsIProgressEventSink.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
@ -41,19 +42,20 @@
#include "prlog.h"
#include "nsFileTransportService.h"
//#define TIMING
class nsIInterfaceRequestor;
class nsFileTransportSourceWrapper;
class nsFileTransportSinkWrapper;
class nsFileTransport : public nsIChannel,
public nsIRunnable,
public nsIInputStreamObserver,
public nsIOutputStreamObserver
public nsIRunnable
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
NS_DECL_NSIINPUTSTREAMOBSERVER
NS_DECL_NSIOUTPUTSTREAMOBSERVER
NS_DECL_NSIRUNNABLE
nsFileTransport();
@ -99,7 +101,7 @@ protected:
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIProgressEventSink> mProgress;
nsCOMPtr<nsIStreamIO> mStreamIO;
char* mContentType;
char *mContentType;
PRUint32 mBufferSegmentSize;
PRUint32 mBufferMaxSize;
@ -107,11 +109,16 @@ protected:
// mXferState is only changed by the file transport thread:
XferState mXferState;
// mRunState is only changed by the user's thread, but looked at by the
// file transport thread:
RunState mRunState;
nsresult mCancelStatus;
PRMonitor* mMonitor;
PRInt32 mSuspendCount;
PRLock *mLock;
// The transport is active if it is currently being processed by a thread.
PRBool mActive;
// state variables:
nsresult mStatus;
@ -120,18 +127,22 @@ protected:
PRInt32 mTransferAmount;
nsLoadFlags mLoadAttributes;
// reading state varialbles:
// reading state variables:
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsIInputStream> mSource;
nsCOMPtr<nsIInputStream> mInputStream;
nsCOMPtr<nsIOutputStream> mOutputStream;
nsFileTransportSourceWrapper *mSourceWrapper;
// writing state variables:
nsCOMPtr<nsIStreamObserver> mObserver;
nsCOMPtr<nsIStreamProvider> mProvider;
nsCOMPtr<nsIOutputStream> mSink;
char* mBuffer;
nsFileTransportSinkWrapper *mSinkWrapper;
nsCString mStreamName;
nsFileTransportService* mService;
nsFileTransportService *mService;
#ifdef TIMING
PRIntervalTime mStartTime;
#endif
};
#define NS_FILE_TRANSPORT_DEFAULT_SEGMENT_SIZE (2*1024)

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

@ -170,12 +170,18 @@ nsStreamIOChannel::Init(nsIURI* uri, nsIStreamIO* io)
return NS_OK;
}
NS_IMPL_THREADSAFE_ISUPPORTS5(nsStreamIOChannel,
nsIStreamIOChannel,
nsIChannel,
nsIRequest,
nsIStreamObserver,
nsIStreamListener);
NS_IMPL_THREADSAFE_ADDREF(nsStreamIOChannel)
NS_IMPL_THREADSAFE_RELEASE(nsStreamIOChannel)
NS_INTERFACE_MAP_BEGIN(nsStreamIOChannel)
NS_INTERFACE_MAP_ENTRY(nsIStreamIOChannel)
NS_INTERFACE_MAP_ENTRY(nsIChannel)
NS_INTERFACE_MAP_ENTRY(nsIRequest)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIStreamProvider)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIStreamObserver, nsIStreamListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
NS_INTERFACE_MAP_END_THREADSAFE
////////////////////////////////////////////////////////////////////////////////
// nsIRequest methods:
@ -349,13 +355,12 @@ nsStreamIOChannel::AsyncRead(nsIStreamListener *listener, nsISupports *ctxt)
}
NS_IMETHODIMP
nsStreamIOChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer, nsISupports *ctxt)
nsStreamIOChannel::AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt)
{
nsresult rv;
NS_ASSERTION(observer, "no observer");
mUserObserver = observer;
NS_ASSERTION(provider, "no provider");
SetProvider(provider);
if (mLoadGroup) {
nsCOMPtr<nsILoadGroupListenerFactory> factory;
@ -364,12 +369,15 @@ nsStreamIOChannel::AsyncWrite(nsIInputStream *fromStream,
//
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
if (factory) {
NS_WARNING("load group proxy listener not implemented for AsyncWrite");
#if 0
nsIStreamListener *newListener;
rv = factory->CreateLoadGroupListener(GetListener(), &newListener);
if (NS_SUCCEEDED(rv)) {
mUserObserver = newListener;
NS_RELEASE(newListener);
}
#endif
}
rv = mLoadGroup->AddChannel(this, nsnull);
@ -398,7 +406,7 @@ nsStreamIOChannel::AsyncWrite(nsIInputStream *fromStream,
if (NS_FAILED(rv)) goto done;
}
#endif
rv = mFileTransport->AsyncWrite(fromStream, this, ctxt);
rv = mFileTransport->AsyncWrite(this, ctxt);
done:
if (NS_FAILED(rv)) {
@ -600,7 +608,7 @@ nsStreamIOChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
}
////////////////////////////////////////////////////////////////////////////////
// nsIStreamListener methods:
// nsIStreamObserver implementation:
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
@ -635,6 +643,10 @@ nsStreamIOChannel::OnStopRequest(nsIChannel* transportChannel, nsISupports* cont
return mStreamIO->Close(aStatus);
}
////////////////////////////////////////////////////////////////////////////////
// nsIStreamListener implementation:
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsStreamIOChannel::OnDataAvailable(nsIChannel* transportChannel, nsISupports* context,
nsIInputStream *aIStream, PRUint32 aSourceOffset,
@ -645,3 +657,16 @@ nsStreamIOChannel::OnDataAvailable(nsIChannel* transportChannel, nsISupports* co
}
////////////////////////////////////////////////////////////////////////////////
// nsIStreamProvider implementation:
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsStreamIOChannel::OnDataWritable(nsIChannel* transportChannel, nsISupports* context,
nsIOutputStream *aOStream, PRUint32 aOffset,
PRUint32 aLength)
{
return GetProvider()->OnDataWritable(this, context, aOStream,
aOffset, aLength);
}
////////////////////////////////////////////////////////////////////////////////

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

@ -29,6 +29,7 @@
#include "nsCRT.h"
#include "nsILoadGroup.h"
#include "nsIStreamListener.h"
#include "nsIStreamProvider.h"
#include "nsIInterfaceRequestor.h"
#include "nsIStreamIO.h"
@ -56,7 +57,8 @@ protected:
////////////////////////////////////////////////////////////////////////////////
class nsStreamIOChannel : public nsIStreamIOChannel,
public nsIStreamListener
public nsIStreamListener,
public nsIStreamProvider
{
public:
NS_DECL_ISUPPORTS
@ -65,6 +67,7 @@ public:
NS_DECL_NSISTREAMIOCHANNEL
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSISTREAMPROVIDER
nsStreamIOChannel();
virtual ~nsStreamIOChannel();
@ -75,6 +78,8 @@ public:
protected:
nsIStreamListener* GetListener() { return (nsIStreamListener*)mUserObserver.get(); }
void SetListener(nsIStreamListener* listener) { mUserObserver = listener; }
nsIStreamProvider* GetProvider() { return (nsIStreamProvider*)mUserObserver.get(); }
void SetProvider(nsIStreamProvider* provider) { mUserObserver = provider; }
protected:
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;

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

@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsSimpleStreamListener.h"
//
//----------------------------------------------------------------------------
// nsISupports implementation...
//----------------------------------------------------------------------------
//
NS_IMPL_ISUPPORTS3(nsSimpleStreamListener,
nsISimpleStreamListener,
nsIStreamListener,
nsIStreamObserver)
//
//----------------------------------------------------------------------------
// nsIStreamObserver implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsSimpleStreamListener::OnStartRequest(nsIChannel *aChannel,
nsISupports *aContext)
{
return mObserver ?
mObserver->OnStartRequest(aChannel, aContext) : NS_OK;
}
NS_IMETHODIMP
nsSimpleStreamListener::OnStopRequest(nsIChannel *aChannel,
nsISupports *aContext,
nsresult aStatus,
const PRUnichar *aStatusText)
{
return mObserver ?
mObserver->OnStopRequest(aChannel, aContext, aStatus, aStatusText) : NS_OK;
}
//
//----------------------------------------------------------------------------
// nsIStreamListener implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsSimpleStreamListener::OnDataAvailable(nsIChannel *aChannel,
nsISupports *aContext,
nsIInputStream *aSource,
PRUint32 aOffset,
PRUint32 aCount)
{
PRUint32 writeCount;
nsresult rv = mSink->WriteFrom(aSource, aCount, &writeCount);
//
// Equate zero bytes read and NS_SUCCEEDED to stopping the read.
//
if (NS_SUCCEEDED(rv) && (writeCount == 0))
return NS_BASE_STREAM_CLOSED;
return rv;
}
//
//----------------------------------------------------------------------------
// nsISimpleStreamListener implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsSimpleStreamListener::Init(nsIOutputStream *aSink,
nsIStreamObserver *aObserver)
{
NS_PRECONDITION(aSink, "null output stream");
mSink = aSink;
mObserver = aObserver;
return NS_OK;
}

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

@ -0,0 +1,19 @@
#include "nsIStreamListener.h"
#include "nsIOutputStream.h"
#include "nsCOMPtr.h"
class nsSimpleStreamListener : public nsISimpleStreamListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSISIMPLESTREAMLISTENER
nsSimpleStreamListener() { NS_INIT_ISUPPORTS(); }
virtual ~nsSimpleStreamListener() {}
protected:
nsCOMPtr<nsIOutputStream> mSink;
nsCOMPtr<nsIStreamObserver> mObserver;
};

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

@ -0,0 +1,96 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsSimpleStreamProvider.h"
#include "nsIOutputStream.h"
//
//----------------------------------------------------------------------------
// nsISupports implementation...
//----------------------------------------------------------------------------
//
NS_IMPL_ISUPPORTS3(nsSimpleStreamProvider,
nsISimpleStreamProvider,
nsIStreamProvider,
nsIStreamObserver)
//
//----------------------------------------------------------------------------
// nsIStreamObserver implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsSimpleStreamProvider::OnStartRequest(nsIChannel *aChannel,
nsISupports *aContext)
{
return mObserver ?
mObserver->OnStartRequest(aChannel, aContext) : NS_OK;
}
NS_IMETHODIMP
nsSimpleStreamProvider::OnStopRequest(nsIChannel *aChannel,
nsISupports *aContext,
nsresult aStatus,
const PRUnichar *aStatusText)
{
return mObserver ?
mObserver->OnStopRequest(aChannel, aContext, aStatus, aStatusText) : NS_OK;
}
//
//----------------------------------------------------------------------------
// nsIStreamProvider implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsSimpleStreamProvider::OnDataWritable(nsIChannel *aChannel,
nsISupports *aContext,
nsIOutputStream *aOutput,
PRUint32 aOffset,
PRUint32 aCount)
{
PRUint32 writeCount;
nsresult rv = aOutput->WriteFrom(mSource, aCount, &writeCount);
//
// Equate zero bytes written and NS_SUCCEEDED to EOF
//
if (NS_SUCCEEDED(rv) && (writeCount == 0))
return NS_BASE_STREAM_CLOSED;
return rv;
}
//
//----------------------------------------------------------------------------
// nsISimpleStreamProvider implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsSimpleStreamProvider::Init(nsIInputStream *aSource,
nsIStreamObserver *aObserver)
{
NS_PRECONDITION(aSource, "null input stream");
mSource = aSource;
mObserver = aObserver;
return NS_OK;
}

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

@ -0,0 +1,19 @@
#include "nsIStreamProvider.h"
#include "nsIInputStream.h"
#include "nsCOMPtr.h"
class nsSimpleStreamProvider : public nsISimpleStreamProvider
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMPROVIDER
NS_DECL_NSISIMPLESTREAMPROVIDER
nsSimpleStreamProvider() { NS_INIT_ISUPPORTS(); }
virtual ~nsSimpleStreamProvider() {}
protected:
nsCOMPtr<nsIInputStream> mSource;
nsCOMPtr<nsIStreamObserver> mObserver;
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -35,6 +35,7 @@
#include "nsIOutputStream.h"
#include "nsIEventQueueService.h"
#include "nsIStreamListener.h"
#include "nsIStreamProvider.h"
#include "nsIDNSListener.h"
#include "nsIPipe.h"
#include "nsIProgressEventSink.h"
@ -114,6 +115,8 @@ enum nsSocketReadWriteInfo {
// Forward declarations...
class nsSocketTransportService;
class nsSocketInputStream;
class nsSocketOutputStream;
class nsIInterfaceRequestor;
class nsSocketTransport : public nsISocketTransport,
@ -166,7 +169,9 @@ protected:
nsresult doConnection(PRInt16 aSelectFlags);
nsresult doResolveHost(void);
nsresult doRead(PRInt16 aSelectFlags);
nsresult doReadAsync(PRInt16 aSelectFlags);
nsresult doWrite(PRInt16 aSelectFlags);
nsresult doWriteAsync(PRInt16 aSelectFlags);
nsresult doWriteFromBuffer(PRUint32 *aCount);
nsresult doWriteFromStream(PRUint32 *aCount);
@ -222,40 +227,41 @@ protected:
nsSocketOperation mOperation;
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsISupports> mSecurityInfo;
PRInt32 mProxyPort;
char* mProxyHost;
PRBool mProxyTransparent;
PRBool mSSLProxy;
nsCOMPtr<nsISupports> mReadContext;
nsCOMPtr<nsIStreamListener> mReadListener;
nsCOMPtr<nsIInputStream> mReadPipeIn;
nsCOMPtr<nsIOutputStream> mReadPipeOut;
nsSocketTransportService* mService;
PRUint32 mReadWriteState;
PRInt16 mSelectFlags;
nsSocketTransportService* mService;
nsresult mStatus;
PRInt32 mSuspendCount;
PRFileDesc* mSocketFD;
PRUint32 mSocketTypeCount;
char* *mSocketTypes;
nsCOMPtr<nsIStreamListener> mReadListener;
nsCOMPtr<nsISupports> mReadContext;
PRUint32 mReadOffset;
PRUint32 mWriteOffset;
nsresult mStatus;
PRInt32 mSuspendCount;
PRInt32 mWriteCount;
nsCOMPtr<nsIStreamProvider> mWriteProvider;
nsCOMPtr<nsISupports> mWriteContext;
PRInt32 mBytesExpected;
PRUint32 mWriteOffset;
PRInt32 mWriteCount;
PRInt32 mBytesExpected;
PRUint32 mReuseCount;
PRUint32 mLastReuseCount;
nsSocketInputStream *mSocketInputStream;
nsSocketOutputStream *mSocketOutputStream;
// The following four members are used when AsyncWrite(...) is called
// with an nsIInputStream which does not also support the
// nsIBufferedInputStream interface...
//
nsCOMPtr<nsIInputStream> mWriteFromStream;
char * mWriteBuffer;
PRUint32 mWriteBufferIndex;
PRUint32 mWriteBufferLength;
nsCOMPtr<nsIStreamObserver> mWriteObserver;
nsCOMPtr<nsIInputStream> mReadPipeIn;
nsCOMPtr<nsIOutputStream> mReadPipeOut;
nsCOMPtr<nsIInputStream> mWritePipeIn;
nsCOMPtr<nsIOutputStream> mWritePipeOut;
PRUint32 mBufferSegmentSize;

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

@ -0,0 +1,395 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsStreamListenerProxy.h"
#include "nsIGenericFactory.h"
#include "nsIInputStream.h"
#include "nsIPipe.h"
#include "nsAutoLock.h"
#define LOG(args) PR_LOG(gStreamProxyLog, PR_LOG_DEBUG, args)
#define DEFAULT_BUFFER_SEGMENT_SIZE 2048
#define DEFAULT_BUFFER_MAX_SIZE (4*2048)
//
//----------------------------------------------------------------------------
// Design Overview
//
// A stream listener proxy maintains a pipe. When the channel makes data
// available, the proxy copies as much of that data as possible into the pipe.
// If data was written to the pipe, then the proxy posts an asynchronous event
// corresponding to the amount of data written. If no data could be written,
// because the pipe was full, then WOULD_BLOCK is returned to the channel,
// indicating that the channel should suspend itself.
//
// Once suspended in this manner, the channel is only resumed when the pipe is
// emptied.
//
// XXX The current design does NOT allow the channel to be "externally"
// suspended!! For the moment this is not a problem, but it should be fixed.
//----------------------------------------------------------------------------
//
//
//----------------------------------------------------------------------------
// nsStreamListenerProxy implementation...
//----------------------------------------------------------------------------
//
nsStreamListenerProxy::nsStreamListenerProxy()
: mLock(nsnull)
, mPendingCount(0)
, mListenerStatus(NS_OK)
{ }
nsStreamListenerProxy::~nsStreamListenerProxy()
{
if (mLock) {
PR_DestroyLock(mLock);
mLock = nsnull;
}
}
PRUint32
nsStreamListenerProxy::GetPendingCount()
{
return PR_AtomicSet((PRInt32 *) &mPendingCount, 0);
}
//
//----------------------------------------------------------------------------
// nsOnDataAvailableEvent internal class...
//----------------------------------------------------------------------------
//
class nsOnDataAvailableEvent : public nsStreamObserverEvent
{
public:
nsOnDataAvailableEvent(nsStreamProxyBase *aProxy,
nsIChannel *aChannel,
nsISupports *aContext,
nsIInputStream *aSource,
PRUint32 aOffset)
: nsStreamObserverEvent(aProxy, aChannel, aContext)
, mSource(aSource)
, mOffset(aOffset)
{
MOZ_COUNT_CTOR(nsOnDataAvailableEvent);
}
~nsOnDataAvailableEvent()
{
MOZ_COUNT_DTOR(nsOnDataAvailableEvent);
}
NS_IMETHOD HandleEvent();
protected:
nsCOMPtr<nsIInputStream> mSource;
PRUint32 mOffset;
};
NS_IMETHODIMP
nsOnDataAvailableEvent::HandleEvent()
{
LOG(("nsOnDataAvailableEvent: HandleEvent [event=%x, chan=%x]", this, mChannel.get()));
nsStreamListenerProxy *listenerProxy =
NS_STATIC_CAST(nsStreamListenerProxy *, mProxy);
if (NS_FAILED(listenerProxy->GetListenerStatus())) {
LOG(("nsOnDataAvailableEvent: Discarding event [listener_status=%x, chan=%x]\n",
listenerProxy->GetListenerStatus(), mChannel.get()));
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIStreamListener> listener = listenerProxy->GetListener();
if (!listener) {
LOG(("nsOnDataAvailableEvent: Already called OnStopRequest (listener is NULL), [chan=%x]\n",
mChannel.get()));
return NS_ERROR_FAILURE;
}
nsresult status = NS_OK;
nsresult rv = mChannel->GetStatus(&status);
NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed");
//
// We should only forward this event to the listener if the channel is
// still in a "good" state. Because these events are being processed
// asynchronously, there is a very real chance that the listener might
// have cancelled the channel after _this_ event was triggered.
//
if (NS_SUCCEEDED(status)) {
//
// Find out from the listener proxy how many bytes to report.
//
PRUint32 count = listenerProxy->GetPendingCount();
#if defined(PR_LOGGING)
{
PRUint32 avail;
mSource->Available(&avail);
LOG(("nsOnDataAvailableEvent: Calling the consumer's OnDataAvailable "
"[offset=%u count=%u avail=%u chan=%x]\n",
mOffset, count, avail, mChannel.get()));
}
#endif
// Forward call to listener
rv = listener->OnDataAvailable(mChannel, mContext, mSource, mOffset, count);
LOG(("nsOnDataAvailableEvent: Done with the consumer's OnDataAvailable "
"[rv=%x, chan=%x]\n",
rv, mChannel.get()));
//
// XXX Need to suspend the underlying channel... must consider
// other pending events (such as OnStopRequest). These
// should not be forwarded to the listener if the channel
// is suspended. Also, handling the Resume could be tricky.
//
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
NS_NOTREACHED("listener returned NS_BASE_STREAM_WOULD_BLOCK"
" -- support for this is not implemented");
rv = NS_ERROR_NOT_IMPLEMENTED;
}
//
// Update the listener status
//
listenerProxy->SetListenerStatus(rv);
}
else
LOG(("nsOnDataAvailableEvent: Not calling OnDataAvailable [chan=%x]",
mChannel.get()));
return NS_OK;
}
//
//----------------------------------------------------------------------------
// nsISupports implementation...
//----------------------------------------------------------------------------
//
NS_IMPL_ISUPPORTS_INHERITED3(nsStreamListenerProxy,
nsStreamProxyBase,
nsIStreamListenerProxy,
nsIStreamListener,
nsIInputStreamObserver)
//
//----------------------------------------------------------------------------
// nsIStreamObserver implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsStreamListenerProxy::OnStartRequest(nsIChannel *aChannel,
nsISupports *aContext)
{
return nsStreamProxyBase::OnStartRequest(aChannel, aContext);
}
NS_IMETHODIMP
nsStreamListenerProxy::OnStopRequest(nsIChannel *aChannel,
nsISupports *aContext,
nsresult aStatus,
const PRUnichar *aStatusText)
{
//
// We are done with the pipe.
//
mPipeIn = 0;
mPipeOut = 0;
return nsStreamProxyBase::OnStopRequest(aChannel, aContext,
aStatus, aStatusText);
}
//
//----------------------------------------------------------------------------
// nsIStreamListener implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsStreamListenerProxy::OnDataAvailable(nsIChannel *aChannel,
nsISupports *aContext,
nsIInputStream *aSource,
PRUint32 aOffset,
PRUint32 aCount)
{
nsresult rv;
PRUint32 bytesWritten=0;
LOG(("nsStreamListenerProxy: OnDataAvailable [offset=%u count=%u chan=%x]\n",
aOffset, aCount, aChannel));
NS_PRECONDITION(mChannelToResume == 0, "Unexpected call to OnDataAvailable");
NS_PRECONDITION(mPipeIn, "Pipe not initialized");
NS_PRECONDITION(mPipeOut, "Pipe not initialized");
//
// Any non-successful listener status gets passed back to the caller
//
{
nsresult status = mListenerStatus;
if (NS_FAILED(status)) {
LOG(("nsStreamListenerProxy: Listener failed [status=%x chan=%x]\n", status, aChannel));
return status;
}
}
//
// Enter the ChannelToResume lock
//
{
nsAutoLock lock(mLock);
//
// Try to copy data into the pipe.
//
// If the pipe is full, then suspend the calling channel. It
// will be resumed when the pipe is emptied. Being inside the
// ChannelToResume lock ensures that the resume will follow
// the suspend.
//
rv = mPipeOut->WriteFrom(aSource, aCount, &bytesWritten);
LOG(("nsStreamListenerProxy: Wrote data to pipe [rv=%x count=%u bytesWritten=%u chan=%x]\n",
rv, aCount, bytesWritten, aChannel));
if (NS_FAILED(rv)) {
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
LOG(("nsStreamListenerProxy: Setting channel to resume [chan=%x]\n", aChannel));
mChannelToResume = aChannel;
}
return rv;
}
else if (bytesWritten == 0) {
LOG(("nsStreamListenerProxy: Copied zero bytes; not posting an event [chan=%x]\n", aChannel));
return NS_BASE_STREAM_CLOSED; // there was no more data to read!
}
}
//
// Update the pending count; return if able to piggy-back on a pending event.
//
PRUint32 total = PR_AtomicAdd((PRInt32 *) &mPendingCount, bytesWritten);
if (total > bytesWritten) {
LOG(("nsStreamListenerProxy: Piggy-backing pending event [total=%u, chan=%x]\n",
total, aChannel));
return NS_OK;
}
//
// Post an event for the number of bytes actually written.
//
nsOnDataAvailableEvent *ev =
new nsOnDataAvailableEvent(this, aChannel, aContext, mPipeIn, aOffset);
if (!ev) return NS_ERROR_OUT_OF_MEMORY;
rv = ev->FireEvent(GetEventQueue());
if (NS_FAILED(rv)) {
delete ev;
return rv;
}
return NS_OK;
}
//
//----------------------------------------------------------------------------
// nsIStreamListenerProxy implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsStreamListenerProxy::Init(nsIStreamListener *aListener,
nsIEventQueue *aEventQ,
PRUint32 aBufferSegmentSize,
PRUint32 aBufferMaxSize)
{
NS_PRECONDITION(GetReceiver() == nsnull, "Listener already set");
NS_PRECONDITION(GetEventQueue() == nsnull, "Event queue already set");
//
// Create the ChannelToResume lock
//
mLock = PR_NewLock();
if (!mLock) return NS_ERROR_OUT_OF_MEMORY;
//
// Create the pipe
//
if (aBufferSegmentSize == 0)
aBufferSegmentSize = DEFAULT_BUFFER_SEGMENT_SIZE;
if (aBufferMaxSize == 0)
aBufferMaxSize = DEFAULT_BUFFER_MAX_SIZE;
// The segment size must not exceed the maximum
aBufferSegmentSize = PR_MIN(aBufferMaxSize, aBufferSegmentSize);
nsresult rv = NS_NewPipe(getter_AddRefs(mPipeIn),
getter_AddRefs(mPipeOut),
aBufferSegmentSize,
aBufferMaxSize,
PR_TRUE, PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = mPipeIn->SetObserver(this);
if (NS_FAILED(rv)) return rv;
SetReceiver(aListener);
return SetEventQueue(aEventQ);
}
//
//----------------------------------------------------------------------------
// nsIInputStreamObserver implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsStreamListenerProxy::OnEmpty(nsIInputStream *aInputStream)
{
LOG(("nsStreamListenerProxy: OnEmpty\n"));
//
// The pipe has been emptied by the listener. If the channel
// has been suspended (waiting for the pipe to be emptied), then
// go ahead and resume it. But take care not to resume while
// holding the "ChannelToResume" lock.
//
nsCOMPtr<nsIChannel> chan;
{
nsAutoLock lock(mLock);
chan = mChannelToResume;
mChannelToResume = 0;
}
if (chan) {
LOG(("nsStreamListenerProxy: Resuming channel\n"));
chan->Resume();
}
return NS_OK;
}
NS_IMETHODIMP
nsStreamListenerProxy::OnClose(nsIInputStream *aInputStream)
{
LOG(("nsStreamListenerProxy: OnClose\n"));
return NS_OK;
}

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

@ -0,0 +1,51 @@
#ifndef nsStreamListenerProxy_h__
#define nsStreamListenerProxy_h__
#include "nsStreamObserverProxy.h"
#include "nsIStreamListener.h"
#include "nsIChannel.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsCOMPtr.h"
class nsStreamListenerProxy : public nsStreamProxyBase
, public nsIStreamListenerProxy
, public nsIInputStreamObserver
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSISTREAMLISTENERPROXY
NS_DECL_NSIINPUTSTREAMOBSERVER
nsStreamListenerProxy();
virtual ~nsStreamListenerProxy();
nsIStreamListener *GetListener()
{
return NS_STATIC_CAST(nsIStreamListener *, GetReceiver());
}
void SetListenerStatus(nsresult status)
{
mListenerStatus = status;
}
nsresult GetListenerStatus()
{
return mListenerStatus;
}
PRUint32 GetPendingCount();
protected:
nsCOMPtr<nsIInputStream> mPipeIn;
nsCOMPtr<nsIOutputStream> mPipeOut;
nsCOMPtr<nsIChannel> mChannelToResume;
PRLock *mLock;
PRUint32 mPendingCount;
nsresult mListenerStatus;
};
#endif /* !nsStreamListenerProxy_h__ */

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

@ -0,0 +1,274 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsStreamObserverProxy.h"
#include "nsIGenericFactory.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
#include "nsString.h"
#if defined(PR_LOGGING)
PRLogModuleInfo *gStreamProxyLog;
#endif
#define LOG(args) PR_LOG(gStreamProxyLog, PR_LOG_DEBUG, args)
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
//
//----------------------------------------------------------------------------
// nsStreamObserverEvent implementation...
//----------------------------------------------------------------------------
//
nsStreamObserverEvent::nsStreamObserverEvent(nsStreamProxyBase *aProxy,
nsIChannel *aChannel,
nsISupports *aContext)
: mProxy(aProxy)
, mChannel(aChannel)
, mContext(aContext)
{
NS_IF_ADDREF(mProxy);
}
nsStreamObserverEvent::~nsStreamObserverEvent()
{
NS_IF_RELEASE(mProxy);
}
nsresult
nsStreamObserverEvent::FireEvent(nsIEventQueue *aEventQ)
{
NS_PRECONDITION(aEventQ, "null event queue");
PL_InitEvent(&mEvent, nsnull,
(PLHandleEventProc) nsStreamObserverEvent::HandlePLEvent,
(PLDestroyEventProc) nsStreamObserverEvent::DestroyPLEvent);
PRStatus status = aEventQ->PostEvent(&mEvent);
return status == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
}
void PR_CALLBACK
nsStreamObserverEvent::HandlePLEvent(PLEvent *aEvent)
{
nsStreamObserverEvent *ev = GET_STREAM_OBSERVER_EVENT(aEvent);
NS_ASSERTION(ev, "null event");
// Pass control the real event handler
if (ev)
ev->HandleEvent();
}
void PR_CALLBACK
nsStreamObserverEvent::DestroyPLEvent(PLEvent *aEvent)
{
nsStreamObserverEvent *ev = GET_STREAM_OBSERVER_EVENT(aEvent);
NS_ASSERTION(ev, "null event");
delete ev;
}
//
//----------------------------------------------------------------------------
// nsOnStartRequestEvent internal class...
//----------------------------------------------------------------------------
//
class nsOnStartRequestEvent : public nsStreamObserverEvent
{
public:
nsOnStartRequestEvent(nsStreamProxyBase *aProxy,
nsIChannel *aChannel,
nsISupports *aContext)
: nsStreamObserverEvent(aProxy, aChannel, aContext)
{
MOZ_COUNT_CTOR(nsOnStartRequestEvent);
}
~nsOnStartRequestEvent()
{
MOZ_COUNT_DTOR(nsOnStartRequestEvent);
}
NS_IMETHOD HandleEvent();
};
NS_IMETHODIMP
nsOnStartRequestEvent::HandleEvent()
{
LOG(("nsOnStartRequestEvent: HandleEvent [event=%x chan=%x]\n",
this, mChannel.get()));
nsCOMPtr<nsIStreamObserver> observer = mProxy->GetReceiver();
if (!observer) {
LOG(("nsOnStartRequestEvent: Already called OnStopRequest (observer is NULL)\n"));
return NS_ERROR_FAILURE;
}
return observer->OnStartRequest(mChannel, mContext);
}
//
//----------------------------------------------------------------------------
// nsOnStopRequestEvent internal class...
//----------------------------------------------------------------------------
//
class nsOnStopRequestEvent : public nsStreamObserverEvent
{
public:
nsOnStopRequestEvent(nsStreamProxyBase *aProxy,
nsIChannel *aChannel, nsISupports *aContext,
nsresult aStatus, const PRUnichar *aStatusText)
: nsStreamObserverEvent(aProxy, aChannel, aContext)
, mStatus(aStatus)
, mStatusText(aStatusText)
{
MOZ_COUNT_CTOR(nsOnStopRequestEvent);
}
~nsOnStopRequestEvent()
{
MOZ_COUNT_DTOR(nsOnStopRequestEvent);
}
NS_IMETHOD HandleEvent();
protected:
nsresult mStatus;
nsString mStatusText;
};
NS_IMETHODIMP
nsOnStopRequestEvent::HandleEvent()
{
LOG(("nsOnStopRequestEvent: HandleEvent [event=%x chan=%x]\n",
this, mChannel.get()));
nsCOMPtr<nsIStreamObserver> observer = mProxy->GetReceiver();
if (!observer) {
LOG(("nsOnStopRequestEvent: Already called OnStopRequest (observer is NULL)\n"));
return NS_ERROR_FAILURE;
}
//
// Do not allow any more events to be handled after OnStopRequest
//
mProxy->SetReceiver(nsnull);
return observer->OnStopRequest(mChannel,
mContext,
mStatus,
mStatusText.GetUnicode());
}
//
//----------------------------------------------------------------------------
// nsStreamProxyBase: nsISupports implementation...
//----------------------------------------------------------------------------
//
NS_IMPL_THREADSAFE_ISUPPORTS1(nsStreamProxyBase,
nsIStreamObserver)
//
//----------------------------------------------------------------------------
// nsStreamProxyBase: nsIStreamObserver implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsStreamProxyBase::OnStartRequest(nsIChannel *aChannel,
nsISupports *aContext)
{
LOG(("nsStreamProxyBase: OnStartRequest [this=%x chan=%x]\n", this, aChannel));
nsOnStartRequestEvent *ev =
new nsOnStartRequestEvent(this, aChannel, aContext);
if (!ev)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = ev->FireEvent(GetEventQueue());
if (NS_FAILED(rv))
delete ev;
return rv;
}
NS_IMETHODIMP
nsStreamProxyBase::OnStopRequest(nsIChannel *aChannel,
nsISupports *aContext,
nsresult aStatus,
const PRUnichar *aStatusText)
{
LOG(("nsStreamProxyBase: OnStopRequest [this=%x chan=%x status=%x]\n",
this, aChannel, aStatus));
nsOnStopRequestEvent *ev =
new nsOnStopRequestEvent(this, aChannel, aContext, aStatus, aStatusText);
if (!ev)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = ev->FireEvent(GetEventQueue());
if (NS_FAILED(rv))
delete ev;
return rv;
}
//
//----------------------------------------------------------------------------
// nsStreamProxyBase: implementation...
//----------------------------------------------------------------------------
//
nsresult
nsStreamProxyBase::SetEventQueue(nsIEventQueue *aEventQ)
{
#if defined(PR_LOGGING)
if (!gStreamProxyLog)
gStreamProxyLog = PR_NewLogModule("nsStreamProxy");
#endif
nsresult rv = NS_OK;
if ((aEventQ == NS_CURRENT_EVENTQ) || (aEventQ == NS_UI_THREAD_EVENTQ)) {
nsCOMPtr<nsIEventQueueService> serv =
do_GetService(kEventQueueService, &rv);
if (NS_FAILED(rv))
return rv;
rv = serv->GetSpecialEventQueue((PRInt32) aEventQ,
getter_AddRefs(mEventQ));
} else
mEventQ = aEventQ;
return rv;
}
//
//----------------------------------------------------------------------------
// nsStreamObserverProxy: nsISupports implementation...
//----------------------------------------------------------------------------
//
NS_IMPL_ISUPPORTS_INHERITED1(nsStreamObserverProxy,
nsStreamProxyBase,
nsIStreamObserverProxy)
//
//----------------------------------------------------------------------------
// nsStreamObserverProxy: nsIStreamObserverProxy implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsStreamObserverProxy::Init(nsIStreamObserver *aObserver,
nsIEventQueue *aEventQ)
{
NS_PRECONDITION(aObserver, "null observer");
SetReceiver(aObserver);
return SetEventQueue(aEventQ);
}

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

@ -0,0 +1,93 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsStreamObserverProxy_h__
#define nsStreamObserverProxy_h__
#include "nsIStreamObserver.h"
#include "nsIEventQueue.h"
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "prlog.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo *gStreamProxyLog;
#endif
class nsStreamProxyBase : public nsIStreamObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
nsStreamProxyBase() { NS_INIT_ISUPPORTS(); }
virtual ~nsStreamProxyBase() {}
nsIEventQueue *GetEventQueue() { return mEventQ.get(); }
nsIStreamObserver *GetReceiver() { return mReceiver.get(); }
nsresult SetEventQueue(nsIEventQueue *);
nsresult SetReceiver(nsIStreamObserver *aReceiver) {
mReceiver = aReceiver;
return NS_OK;
}
private:
nsCOMPtr<nsIEventQueue> mEventQ;
nsCOMPtr<nsIStreamObserver> mReceiver;
};
class nsStreamObserverProxy : public nsStreamProxyBase
, public nsIStreamObserverProxy
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_NSISTREAMOBSERVER(nsStreamProxyBase::)
NS_DECL_NSISTREAMOBSERVERPROXY
};
class nsStreamObserverEvent
{
public:
nsStreamObserverEvent(nsStreamProxyBase *proxy,
nsIChannel *channel, nsISupports *context);
virtual ~nsStreamObserverEvent();
nsresult FireEvent(nsIEventQueue *);
NS_IMETHOD HandleEvent() = 0;
protected:
static void PR_CALLBACK HandlePLEvent(PLEvent *);
static void PR_CALLBACK DestroyPLEvent(PLEvent *);
PLEvent mEvent;
nsStreamProxyBase *mProxy;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsISupports> mContext;
};
#define GET_STREAM_OBSERVER_EVENT(_mEvent_ptr) \
((nsStreamObserverEvent *) \
((char *)(_mEvent_ptr) - offsetof(nsStreamObserverEvent, mEvent)))
#endif /* !nsStreamObserverProxy_h__ */

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

@ -0,0 +1,285 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsStreamProviderProxy.h"
#include "nsIPipe.h"
#define LOG(args) PR_LOG(gStreamProxyLog, PR_LOG_DEBUG, args)
#define DEFAULT_BUFFER_SEGMENT_SIZE 2048
#define DEFAULT_BUFFER_MAX_SIZE (4*2048)
//
//----------------------------------------------------------------------------
// Design Overview
//
// A stream provider proxy maintains a pipe. When requested to provide data
// to the channel, whatever data is in the pipe (up to the amount requested)
// is provided to the channel. If there is no data in the pipe, then the
// proxy posts an asynchronous event for more data, and returns WOULD_BLOCK
// indicating that the channel should suspend itself.
//
// The channel is only resumed once the event has been successfully handled;
// meaning that data has been written to the pipe.
//----------------------------------------------------------------------------
//
nsStreamProviderProxy::nsStreamProviderProxy()
: mProviderStatus(NS_OK)
{ }
nsStreamProviderProxy::~nsStreamProviderProxy()
{ }
//
//----------------------------------------------------------------------------
// nsOnDataWritableEvent internal class...
//----------------------------------------------------------------------------
//
class nsOnDataWritableEvent : public nsStreamObserverEvent
{
public:
nsOnDataWritableEvent(nsStreamProxyBase *aProxy,
nsIChannel *aChannel,
nsISupports *aContext,
nsIOutputStream *aSink,
PRUint32 aOffset,
PRUint32 aCount)
: nsStreamObserverEvent(aProxy, aChannel, aContext)
, mSink(aSink)
, mOffset(aOffset)
, mCount(aCount)
{
MOZ_COUNT_CTOR(nsOnDataWritableEvent);
}
~nsOnDataWritableEvent()
{
MOZ_COUNT_DTOR(nsOnDataWritableEvent);
}
NS_IMETHOD HandleEvent();
protected:
nsCOMPtr<nsIOutputStream> mSink;
PRUint32 mOffset;
PRUint32 mCount;
};
NS_IMETHODIMP
nsOnDataWritableEvent::HandleEvent()
{
LOG(("nsOnDataWritableEvent: HandleEvent [event=%x chan=%x]",
this, mChannel.get()));
nsStreamProviderProxy *providerProxy =
NS_STATIC_CAST(nsStreamProviderProxy *, mProxy);
nsCOMPtr<nsIStreamProvider> provider = providerProxy->GetProvider();
if (!provider) {
LOG(("nsOnDataWritableEvent: Already called OnStopRequest (provider is NULL)\n"));
return NS_ERROR_FAILURE;
}
nsresult status = NS_OK;
nsresult rv = mChannel->GetStatus(&status);
NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed");
//
// We should only forward this event to the provider if the channel is
// still in a "good" state. Because these events are being processed
// asynchronously, there is a very real chance that the provider might
// have cancelled the channel after _this_ event was triggered.
//
if (NS_SUCCEEDED(status)) {
LOG(("nsOnDataWritableEvent: Calling the consumer's OnDataWritable\n"));
rv = provider->OnDataWritable(mChannel, mContext, mSink, mOffset, mCount);
LOG(("nsOnDataWritableEvent: Done with the consumer's OnDataWritable [rv=%x]\n", rv));
//
// Mask NS_BASE_STREAM_WOULD_BLOCK return values.
//
providerProxy->SetProviderStatus(
rv != NS_BASE_STREAM_WOULD_BLOCK ? rv : NS_OK);
//
// The channel is already suspended, so unless the provider returned
// NS_BASE_STREAM_WOULD_BLOCK, we should wake up the channel.
//
if (rv != NS_BASE_STREAM_WOULD_BLOCK)
mChannel->Resume();
}
else
LOG(("nsOnDataWritableEvent: Not calling OnDataWritable"));
return NS_OK;
}
//
//----------------------------------------------------------------------------
// nsISupports implementation...
//----------------------------------------------------------------------------
//
NS_IMPL_ISUPPORTS_INHERITED2(nsStreamProviderProxy,
nsStreamProxyBase,
nsIStreamProviderProxy,
nsIStreamProvider)
//
//----------------------------------------------------------------------------
// nsIStreamObserver implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsStreamProviderProxy::OnStartRequest(nsIChannel *aChannel,
nsISupports *aContext)
{
return nsStreamProxyBase::OnStartRequest(aChannel, aContext);
}
NS_IMETHODIMP
nsStreamProviderProxy::OnStopRequest(nsIChannel *aChannel,
nsISupports *aContext,
nsresult aStatus,
const PRUnichar *aStatusText)
{
//
// Close the pipe
//
mPipeIn = 0;
mPipeOut = 0;
return nsStreamProxyBase::OnStopRequest(aChannel, aContext,
aStatus, aStatusText);
}
//
//----------------------------------------------------------------------------
// nsIStreamProvider implementation...
//----------------------------------------------------------------------------
//
static NS_METHOD
nsWriteToSink(nsIInputStream *source,
void *closure,
const char *fromRawSegment,
PRUint32 offset,
PRUint32 count,
PRUint32 *writeCount)
{
nsIOutputStream *sink = (nsIOutputStream *) closure;
return sink->Write(fromRawSegment, count, writeCount);
}
NS_IMETHODIMP
nsStreamProviderProxy::OnDataWritable(nsIChannel *aChannel,
nsISupports *aContext,
nsIOutputStream *aSink,
PRUint32 aOffset,
PRUint32 aCount)
{
nsresult rv;
LOG(("nsStreamProviderProxy: OnDataWritable [offset=%u, count=%u]\n",
aOffset, aCount));
NS_PRECONDITION(aCount > 0, "Invalid parameter");
NS_PRECONDITION(mPipeIn, "Pipe not initialized");
NS_PRECONDITION(mPipeOut, "Pipe not initialized");
NS_PRECONDITION(mProviderStatus != NS_BASE_STREAM_WOULD_BLOCK,
"Invalid provider status");
//
// Any non-successful provider status gets passed back to the caller
//
if (NS_FAILED(mProviderStatus)) {
LOG(("nsStreamProviderProxy: Provider failed [status=%x]\n", mProviderStatus));
return mProviderStatus;
}
//
// Provide the channel with whatever data is already in the pipe (not
// exceeding aCount).
//
PRUint32 count;
rv = mPipeIn->Available(&count);
if (NS_FAILED(rv)) return rv;
if (count > 0) {
count = PR_MIN(count, aCount);
PRUint32 bytesWritten;
rv = mPipeIn->ReadSegments(nsWriteToSink, aSink, count, &bytesWritten);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
//
// Post an event requesting the provider for more data.
//
nsOnDataWritableEvent *ev =
new nsOnDataWritableEvent(this, aChannel, aContext,
mPipeOut, aOffset, aCount);
if (!ev)
return NS_ERROR_OUT_OF_MEMORY;
rv = ev->FireEvent(GetEventQueue());
if (NS_FAILED(rv)) {
delete ev;
return rv;
}
return NS_BASE_STREAM_WOULD_BLOCK;
}
//
//----------------------------------------------------------------------------
// nsIStreamProviderProxy implementation...
//----------------------------------------------------------------------------
//
NS_IMETHODIMP
nsStreamProviderProxy::Init(nsIStreamProvider *aProvider,
nsIEventQueue *aEventQ,
PRUint32 aBufferSegmentSize,
PRUint32 aBufferMaxSize)
{
NS_PRECONDITION(GetReceiver() == nsnull, "Listener already set");
NS_PRECONDITION(GetEventQueue() == nsnull, "Event queue already set");
//
// Create the pipe
//
if (aBufferSegmentSize == 0)
aBufferSegmentSize = DEFAULT_BUFFER_SEGMENT_SIZE;
if (aBufferMaxSize == 0)
aBufferMaxSize = DEFAULT_BUFFER_MAX_SIZE;
// The segment size must not exceed the maximum
aBufferSegmentSize = PR_MIN(aBufferMaxSize, aBufferSegmentSize);
nsresult rv = NS_NewPipe(getter_AddRefs(mPipeIn),
getter_AddRefs(mPipeOut),
aBufferSegmentSize,
aBufferMaxSize,
PR_TRUE, PR_TRUE);
if (NS_FAILED(rv)) return rv;
SetReceiver(aProvider);
return SetEventQueue(aEventQ);
}

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

@ -0,0 +1,37 @@
#ifndef nsStreamProviderProxy_h__
#define nsStreamProviderProxy_h__
#include "nsStreamObserverProxy.h"
#include "nsIStreamProvider.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
class nsStreamProviderProxy : public nsStreamProxyBase
, public nsIStreamProviderProxy
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMPROVIDER
NS_DECL_NSISTREAMPROVIDERPROXY
nsStreamProviderProxy();
virtual ~nsStreamProviderProxy();
nsIStreamProvider *GetProvider()
{
return NS_STATIC_CAST(nsIStreamProvider *, GetReceiver());
}
void SetProviderStatus(nsresult status)
{
mProviderStatus = status;
}
protected:
nsCOMPtr<nsIInputStream> mPipeIn;
nsCOMPtr<nsIOutputStream> mPipeOut;
nsresult mProviderStatus;
};
#endif /* !nsStreamProviderProxy_h__ */

0
netwerk/build/MANIFEST Normal file
Просмотреть файл

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

@ -32,6 +32,7 @@ IS_COMPONENT = 1
REQUIRES = xpcom nkcache pref js mime dbm util jar locale intl
CPPSRCS = nsNetModule.cpp
EXPORTS = nsNetCID.h
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/libneckobase_s.$(LIB_SUFFIX) \

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

@ -28,6 +28,10 @@ DLL=.\$(OBJDIR)\$(DLLNAME).dll
LCFLAGS = -DWIN32_LEAN_AND_MEAN -D_IMPL_NS_NET
EXPORTS = \
nsNetCID.h \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsNetModule.obj \
$(NULL)

102
netwerk/build/nsNetCID.h Normal file
Просмотреть файл

@ -0,0 +1,102 @@
#ifndef nsNetCID_h__
#define nsNetCID_h__
//
// nsStreamObserverProxy
//
#define NS_STREAMOBSERVERPROXY_CLASSNAME \
"Stream Observer Proxy"
#define NS_STREAMOBSERVERPROXY_CONTRACTID \
"@mozilla.org/network/stream-observer-proxy;1"
#define NS_STREAMOBSERVERPROXY_CID \
{ /* 51fa28c7-74c0-4b85-9c46-d03faa7b696b */ \
0x51fa28c7, \
0x74c0, \
0x4b85, \
{0x9c, 0x46, 0xd0, 0x3f, 0xaa, 0x7b, 0x69, 0x6b} \
}
//
// nsStreamListenerProxy
//
#define NS_STREAMLISTENERPROXY_CLASSNAME \
"Stream Listener Proxy"
#define NS_STREAMLISTENERPROXY_CONTRACTID \
"@mozilla.org/network/stream-listener-proxy;1"
#define NS_STREAMLISTENERPROXY_CID \
{ /* 96c48f15-aa8a-4da7-a9d5-e842bd76f015 */ \
0x96c48f15, \
0xaa8a, \
0x4da7, \
{0xa9, 0xd5, 0xe8, 0x42, 0xbd, 0x76, 0xf0, 0x15} \
}
//
// nsStreamProviderProxy
//
#define NS_STREAMPROVIDERPROXY_CLASSNAME \
"Stream Provider Proxy"
#define NS_STREAMPROVIDERPROXY_CONTRACTID \
"@mozilla.org/network/stream-provider-proxy;1"
#define NS_STREAMPROVIDERPROXY_CID \
{ /* ae964fcf-9c27-40f7-9bbd-78894bfc1f31 */ \
0xae964fcf, \
0x9c27, \
0x40f7, \
{0x9b, 0xbd, 0x78, 0x89, 0x4b, 0xfc, 0x1f, 0x31} \
}
//
// nsSimpleStreamListener
//
#define NS_SIMPLESTREAMLISTENER_CLASSNAME \
"Simple Stream Listener"
#define NS_SIMPLESTREAMLISTENER_CONTRACTID \
"@mozilla.org/network/simple-stream-listener;1"
#define NS_SIMPLESTREAMLISTENER_CID \
{ /* fb8cbf4e-4701-4ba1-b1d6-5388e041fb67 */ \
0xfb8cbf4e, \
0x4701, \
0x4ba1, \
{0xb1, 0xd6, 0x53, 0x88, 0xe0, 0x41, 0xfb, 0x67} \
}
//
// nsSimpleStreamProvider
//
#define NS_SIMPLESTREAMPROVIDER_CLASSNAME \
"Simple Stream Provider"
#define NS_SIMPLESTREAMPROVIDER_CONTRACTID \
"@mozilla.org/network/simple-stream-provider;1"
#define NS_SIMPLESTREAMPROVIDER_CID \
{ /* f9f6a519-4efb-4f36-af40-2a5ec3992710 */ \
0xf9f6a519, \
0x4efb, \
0x4f36, \
{0xaf, 0x40, 0x2a, 0x5e, 0xc3, 0x99, 0x27, 0x10} \
}
//
// nsAsyncStreamObserver
//
#define NS_ASYNCSTREAMOBSERVER_CID \
{ /* fcc7c380-91b3-11d3-8cd9-0060b0fc14a3 */ \
0xfcc7c380, \
0x91b3, \
0x11d3, \
{0x8c, 0xd9, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
}
//
// nsAsyncStreamListener
//
#define NS_ASYNCSTREAMLISTENER_CID \
{ /* 60047bb2-91c0-11d3-8cd9-0060b0fc14a3 */ \
0x60047bb2, \
0x91c0, \
0x11d3, \
{0x8c, 0xd9, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
}
#endif /* !nsNetCID_h__ */

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

@ -42,12 +42,14 @@
#include "nsStreamLoader.h"
#include "nsDownloader.h"
#include "nsAsyncStreamListener.h"
#include "nsSyncStreamListener.h"
//#include "nsSyncStreamListener.h"
#include "nsFileStreams.h"
#include "nsBufferedStreams.h"
#include "nsProtocolProxyService.h"
#include "nsSOCKSSocketProvider.h"
#include "nsNetCID.h"
///////////////////////////////////////////////////////////////////////////////
#include "nsStreamConverterService.h"
@ -74,7 +76,21 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCacheManager, Init)
#include "nsXMLMIMEDataSource.h"
#include "nsMIMEInfoImpl.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMIMEInfoImpl);
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMIMEInfoImpl)
///////////////////////////////////////////////////////////////////////////////
#include "nsStreamObserverProxy.h"
#include "nsStreamListenerProxy.h"
#include "nsStreamProviderProxy.h"
#include "nsSimpleStreamListener.h"
#include "nsSimpleStreamProvider.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStreamObserverProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStreamListenerProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStreamProviderProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSimpleStreamListener)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSimpleStreamProvider)
///////////////////////////////////////////////////////////////////////////////
@ -400,6 +416,26 @@ static nsModuleComponentInfo gNetModuleInfo[] = {
NS_DOWNLOADER_CID,
"@mozilla.org/network/downloader;1",
nsDownloader::Create },
{ NS_STREAMOBSERVERPROXY_CLASSNAME,
NS_STREAMOBSERVERPROXY_CID,
NS_STREAMOBSERVERPROXY_CONTRACTID,
nsStreamObserverProxyConstructor },
{ NS_STREAMLISTENERPROXY_CLASSNAME,
NS_STREAMLISTENERPROXY_CID,
NS_STREAMLISTENERPROXY_CONTRACTID,
nsStreamListenerProxyConstructor },
{ NS_STREAMPROVIDERPROXY_CLASSNAME,
NS_STREAMPROVIDERPROXY_CID,
NS_STREAMPROVIDERPROXY_CONTRACTID,
nsStreamProviderProxyConstructor },
{ NS_SIMPLESTREAMLISTENER_CLASSNAME,
NS_SIMPLESTREAMLISTENER_CID,
NS_SIMPLESTREAMLISTENER_CONTRACTID,
nsSimpleStreamListenerConstructor },
{ NS_SIMPLESTREAMPROVIDER_CLASSNAME,
NS_SIMPLESTREAMPROVIDER_CID,
NS_SIMPLESTREAMPROVIDER_CONTRACTID,
nsSimpleStreamProviderConstructor },
{ "Async Stream Observer",
NS_ASYNCSTREAMOBSERVER_CID,
"@mozilla.org/network/async-stream-observer;1",
@ -408,10 +444,12 @@ static nsModuleComponentInfo gNetModuleInfo[] = {
NS_ASYNCSTREAMLISTENER_CID,
"@mozilla.org/network/async-stream-listener;1",
nsAsyncStreamListener::Create },
/*
{ "Sync Stream Listener",
NS_SYNCSTREAMLISTENER_CID,
"@mozilla.org/network/sync-stream-listener;1",
nsSyncStreamListener::Create },
*/
{ "Load Group",
NS_LOADGROUP_CID,
"@mozilla.org/network/load-group;1",

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

@ -434,8 +434,7 @@ nsDiskCacheRecordChannel::AsyncRead(nsIStreamListener *aListener,
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsDiskCacheRecordChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{

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

@ -525,14 +525,15 @@ nsMemCacheChannel::AsyncRead(nsIStreamListener *aListener, nsISupports *aContext
mAsyncReadStream = asyncReadStreamAdaptor;
rv = asyncReadStreamAdaptor->AsyncRead(aListener, aContext);
if (NS_FAILED(rv))
delete asyncReadStreamAdaptor;
if (NS_FAILED(rv)) {
mAsyncReadStream = nsnull;
NS_RELEASE(asyncReadStreamAdaptor);
}
return rv;
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer, nsISupports *ctxt)
nsMemCacheChannel::AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt)
{
// Not required to be implemented
NS_NOTREACHED("nsMemCacheChannel::AsyncWrite");

3
netwerk/cache/mgr/nsCacheEntryChannel.cpp поставляемый
Просмотреть файл

@ -203,8 +203,7 @@ nsCacheEntryChannel::AsyncRead(nsIStreamListener *aListener, nsISupports *aConte
// No async writes allowed to the cache yet
NS_IMETHODIMP
nsCacheEntryChannel::AsyncWrite(nsIInputStream *aFromStream,
nsIStreamObserver *aObserver,
nsCacheEntryChannel::AsyncWrite(nsIStreamProvider *aProvider,
nsISupports *aContext)
{
NS_NOTREACHED("nsCacheEntryChannel::AsyncWrite");

3
netwerk/cache/mgr/nsCacheEntryChannel.h поставляемый
Просмотреть файл

@ -59,8 +59,7 @@ public:
NS_IMETHOD OpenOutputStream(nsIOutputStream* *aOutputStream);
NS_IMETHOD OpenInputStream(nsIInputStream* *aInputStream);
NS_IMETHOD AsyncRead(nsIStreamListener *aListener, nsISupports *aContext);
NS_IMETHOD AsyncWrite(nsIInputStream *aFromStream,
nsIStreamObserver *aObserver, nsISupports *aContext);
NS_IMETHOD AsyncWrite(nsIStreamProvider *aProvider, nsISupports *aContext);
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes);
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes);
NS_IMETHOD GetLoadGroup(nsILoadGroup* *aLoadGroup);

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

@ -357,8 +357,7 @@ nsDataChannel::AsyncRead(nsIStreamListener *aListener, nsISupports *ctxt)
}
NS_IMETHODIMP
nsDataChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsDataChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{
// you can't write to a data url

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

@ -202,8 +202,7 @@ nsDateTimeChannel::AsyncRead(nsIStreamListener *aListener,
}
NS_IMETHODIMP
nsDateTimeChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsDateTimeChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{
NS_NOTREACHED("nsDateTimeChannel::AsyncWrite");

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

@ -353,8 +353,7 @@ nsFileChannel::AsyncRead(nsIStreamListener *listener,
}
NS_IMETHODIMP
nsFileChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsFileChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{
nsresult rv;
@ -392,7 +391,7 @@ nsFileChannel::AsyncWrite(nsIInputStream *fromStream,
rv = EnsureTransport();
if (NS_FAILED(rv)) goto done;
rv = mFileTransport->AsyncWrite(fromStream, observer, ctxt);
rv = mFileTransport->AsyncWrite(provider, ctxt);
done:
if (NS_FAILED(rv)) {

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

@ -32,6 +32,7 @@
#include "nsMimeTypes.h"
#include "nsIStreamConverterService.h"
#include "nsITXTToHTMLConv.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
@ -250,8 +251,7 @@ nsFingerChannel::AsyncRead(nsIStreamListener *aListener, nsISupports *ctxt)
}
NS_IMETHODIMP
nsFingerChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsFingerChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{
NS_NOTREACHED("nsFingerChannel::AsyncWrite");
@ -540,7 +540,7 @@ nsFingerChannel::SendRequest(nsIChannel* aChannel) {
rv = aChannel->SetTransferCount(requestBuffer.Length());
if (NS_FAILED(rv)) return rv;
rv = aChannel->AsyncWrite(charstream, this, 0);
rv = NS_AsyncWriteFromStream(aChannel, charstream, this, nsnull);
return rv;
}

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

@ -293,13 +293,12 @@ nsFTPChannel::AsyncRead(nsIStreamListener *listener, nsISupports *ctxt)
}
NS_IMETHODIMP
nsFTPChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsFTPChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{
nsresult rv = NS_OK;
mObserver = observer;
mObserver = provider;
mUserContext = ctxt;
if (mProxyChannel) {
@ -307,9 +306,11 @@ nsFTPChannel::AsyncWrite(nsIInputStream *fromStream,
if (NS_FAILED(rv)) return rv;
rv = mProxyChannel->SetTransferCount(mAmount);
if (NS_FAILED(rv)) return rv;
return mProxyChannel->AsyncWrite(fromStream, observer, ctxt);
return mProxyChannel->AsyncWrite(provider, ctxt);
}
return NS_ERROR_NOT_IMPLEMENTED;
#if 0
NS_ASSERTION(mAmount > 0, "FTP requires stream len info");
if (mAmount < 1) return NS_ERROR_NOT_INITIALIZED;
@ -334,6 +335,7 @@ nsFTPChannel::AsyncWrite(nsIInputStream *fromStream,
if (NS_FAILED(rv)) return rv;
}
return mFTPState->Connect();
#endif
}
NS_IMETHODIMP

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

@ -1328,7 +1328,7 @@ nsFtpState::S_stor() {
mFireCallbacks = PR_FALSE; // observer callbacks will be handled by the transport.
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("(%x) writing on Data Transport\n", this));
return mDPipe->AsyncWrite(mWriteStream, mObserver, mObserverContext);
return NS_AsyncWriteFromStream(mDPipe, mWriteStream, mObserver, mObserverContext);
}
FTP_STATE

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

@ -25,6 +25,7 @@
#include "prlog.h"
#include "nsIPipe.h"
#include "nsIInputStream.h"
#include "nsNetUtil.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo* gFTPLog;
@ -102,7 +103,7 @@ nsFtpControlConnection::Connect()
// to indicate between the read and the write transport. We will be passing the a non-null
// context for the write, and a null context for the read.
rv = mCPipe->AsyncWrite(inStream, NS_STATIC_CAST(nsIStreamObserver*, this), NS_STATIC_CAST(nsISupports*, this));
rv = NS_AsyncWriteFromStream(mCPipe, inStream, NS_STATIC_CAST(nsIStreamObserver*, this), NS_STATIC_CAST(nsISupports*, this));
if (NS_FAILED(rv)) return rv;
// get the ball rolling by reading on the control socket.

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

@ -344,10 +344,12 @@ nsHTTPChannel::AsyncRead(nsIStreamListener *listener, nsISupports *aContext)
}
NS_IMETHODIMP
nsHTTPChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsHTTPChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{
NS_NOTREACHED("nsHTTPChannel::AsyncWrite");
return NS_ERROR_NOT_IMPLEMENTED;
#if 0
nsresult rv = NS_OK;
// parameter validation
@ -365,6 +367,7 @@ nsHTTPChannel::AsyncWrite(nsIInputStream *fromStream,
Open();
return rv;
#endif
}
NS_IMETHODIMP

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

@ -43,6 +43,7 @@
#include "nsISocketTransport.h"
#include "nsISSLSocketControl.h"
#include "plstr.h"
#include "nsNetUtil.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo* gHTTPLog;
@ -732,7 +733,7 @@ nsHTTPPipelinedRequest::WriteRequest(nsIInputStream* iRequestStream)
}
mOnStopDone = PR_FALSE;
rv = mTransport->AsyncWrite(stream, this,(nsISupports*)(nsIRequest*)req->mConnection);
rv = NS_AsyncWriteFromStream(mTransport, stream, this, (nsISupports*)(nsIRequest*)req->mConnection);
NS_RELEASE(req);
return rv;
@ -782,7 +783,7 @@ nsHTTPPipelinedRequest::OnStopRequest(nsIChannel* channel, nsISupports* i_Contex
("nsHTTPRequest [this=%x]. "
"Writing PUT/POST data to the server.\n", this));
rv = mTransport->AsyncWrite(mInputStream, this,
rv = NS_AsyncWriteFromStream(mTransport, mInputStream, this,
(nsISupports*)(nsIRequest*)req->mConnection);
/* the mInputStream is released below... */

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

@ -648,7 +648,8 @@ nsHTTPServerListener::OnStartRequest(nsIChannel* channel, nsISupports* i_pContex
mChunkHeaderCtx.SetEOF(PR_FALSE) ;
nsHTTPRequest * req;
mPipelinedRequest->GetCurrentRequest(&req) ;
if (mPipelinedRequest)
mPipelinedRequest->GetCurrentRequest(&req) ;
if (req)
{
@ -851,6 +852,14 @@ nsresult nsHTTPServerListener::FireSingleOnData(nsIStreamListener *aListener,
return rv;
}
struct nsWriteLineInfo
{
nsCString &buf;
PRBool haveLF;
nsWriteLineInfo(nsCString &b) : buf(b), haveLF(0) {}
};
static NS_METHOD
nsWriteLineToString(nsIInputStream* in,
void* closure,
@ -859,29 +868,29 @@ nsWriteLineToString(nsIInputStream* in,
PRUint32 count,
PRUint32 *writeCount)
{
nsCString* str = (nsCString*)closure;
nsWriteLineInfo *info = (nsWriteLineInfo *) closure;
*writeCount = 0;
if (info->haveLF)
// Stop reading
return NS_BASE_STREAM_WOULD_BLOCK;
else
{
char c = 0;
const char *buf = fromRawSegment;
const char *p = fromRawSegment;
for (; count>0; --count) {
c = *buf++;
c = *p++;
(*writeCount)++;
if (c == LF) {
info->haveLF = PR_TRUE;
break;
}
}
str->Append(fromRawSegment, *writeCount);
//
// If the entire segment has been read, and no LF has been found,
// then return OK to continue reading the next segment (if there
// is one). Else, return WOULD_BLOCK to cause ReadSegments to exit
// and allow us to parse this header.
//
return (c != LF) ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
info->buf.Append(fromRawSegment, *writeCount);
// Successfully read something
return NS_OK;
}
}
nsresult nsHTTPServerListener::ParseStatusLine(nsIInputStream* in,
PRUint32 aLength,
@ -901,8 +910,9 @@ nsresult nsHTTPServerListener::ParseStatusLine(nsIInputStream* in,
return NS_ERROR_FAILURE;
}
nsWriteLineInfo info(mHeaderBuffer);
rv = in->ReadSegments(nsWriteLineToString,
(void*) &mHeaderBuffer,
(void*) &info,
aLength,
&actualBytesRead) ;
if (NS_FAILED(rv)) return rv;
@ -987,8 +997,9 @@ nsresult nsHTTPServerListener::ParseHTTPHeader(nsIInputStream* in,
PRInt32 newlineOffset = 0;
do {
// Append the buffer into the header string...
nsWriteLineInfo info(mHeaderBuffer);
rv = in->ReadSegments(nsWriteLineToString,
(void*) &mHeaderBuffer,
(void*) &info,
totalBytesToRead,
&actualBytesRead);
if (NS_FAILED(rv)) return rv;

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

@ -392,8 +392,7 @@ nsJARChannel::AsyncReadJARElement()
}
NS_IMETHODIMP
nsJARChannel::AsyncWrite(nsIInputStream* fromStream,
nsIStreamObserver* observer,
nsJARChannel::AsyncWrite(nsIStreamProvider* provider,
nsISupports* ctxt)
{
NS_NOTREACHED("nsJARChannel::AsyncWrite");

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

@ -92,7 +92,7 @@ NS_IMPL_ISUPPORTS5(nsResChannel,
nsIChannel,
nsIRequest,
nsIStreamListener,
nsIStreamObserver)
nsIStreamProvider)
NS_METHOD
nsResChannel::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
@ -428,8 +428,7 @@ nsResChannel::AsyncRead(nsIStreamListener *listener, nsISupports *ctxt)
}
NS_IMETHODIMP
nsResChannel::AsyncWrite(nsIInputStream *fromStream,
nsIStreamObserver *observer,
nsResChannel::AsyncWrite(nsIStreamProvider *provider,
nsISupports *ctxt)
{
nsresult rv;
@ -459,16 +458,15 @@ nsResChannel::AsyncWrite(nsIInputStream *fromStream,
}
NS_ASSERTION(mState == ASYNC_READ, "wrong state");
mFromStream = fromStream;
mUserContext = ctxt;
mUserObserver = observer;
mUserObserver = provider;
do {
rv = EnsureNextResolvedChannel();
if (NS_FAILED(rv)) break;
if (mResolvedChannel)
rv = mResolvedChannel->AsyncWrite(fromStream, this, nsnull);
rv = mResolvedChannel->AsyncWrite(this, nsnull);
// Later, this AsyncWrite will call back our OnStopRequest
// method. The action resumes there...
} while (NS_FAILED(rv));
@ -704,7 +702,7 @@ nsResChannel::OnStopRequest(nsIChannel* transportChannel, nsISupports* context,
case ASYNC_READ:
return AsyncRead(GetUserListener(), mUserContext);
case ASYNC_WRITE:
return AsyncWrite(mFromStream, mUserObserver, mUserContext);
return AsyncWrite(GetUserProvider(), mUserContext);
default:
break;
}
@ -725,10 +723,9 @@ nsResChannel::EndRequest(nsresult aStatus, const PRUnichar* aStatusArg)
}
#endif
// Release the reference to the consumer stream listener...
mUserObserver = null_nsCOMPtr();
mUserContext = null_nsCOMPtr();
mResolvedChannel = null_nsCOMPtr();
mFromStream = null_nsCOMPtr();
mUserObserver = 0;
mUserContext = 0;
mResolvedChannel = 0;
return rv;
}
@ -745,4 +742,16 @@ nsResChannel::OnDataAvailable(nsIChannel* transportChannel, nsISupports* context
aSourceOffset, aLength);
}
NS_IMETHODIMP
nsResChannel::OnDataWritable(nsIChannel* transportChannel, nsISupports* context,
nsIOutputStream *aOStream, PRUint32 aOffset, PRUint32 aLength)
{
#ifdef DEBUG
NS_ASSERTION(mInitiator == PR_CurrentThread(),
"wrong thread calling this routine");
#endif
return GetUserProvider()->OnDataWritable(this, mUserContext, aOStream,
aOffset, aLength);
}
////////////////////////////////////////////////////////////////////////////////

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

@ -25,6 +25,7 @@
#include "nsIResChannel.h"
#include "nsIStreamListener.h"
#include "nsIStreamProvider.h"
#include "nsIResProtocolHandler.h"
#include "nsIURI.h"
#include "nsIInterfaceRequestor.h"
@ -38,7 +39,8 @@
#endif
class nsResChannel : public nsIResChannel,
public nsIStreamListener
public nsIStreamListener,
public nsIStreamProvider
{
public:
NS_DECL_ISUPPORTS
@ -47,6 +49,7 @@ public:
NS_DECL_NSIRESCHANNEL
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSISTREAMPROVIDER
nsResChannel();
virtual ~nsResChannel();
@ -90,6 +93,15 @@ protected:
return listener;
}
nsIStreamProvider* GetUserProvider() {
// this method doesn't addref the provider
NS_ASSERTION(mState == ASYNC_WRITE, "wrong state");
// this cast is safe because we set mUserObserver in AsyncWrite
nsIStreamObserver* obs = mUserObserver;
nsIStreamProvider* provider = NS_STATIC_CAST(nsIStreamProvider*, obs);
return provider;
}
nsresult EnsureNextResolvedChannel();
nsresult EndRequest(nsresult aStatus, const PRUnichar* aStatusArg);
@ -107,7 +119,6 @@ protected:
Substitutions mSubstitutions;
nsCOMPtr<nsIStreamObserver> mUserObserver;
nsCOMPtr<nsISupports> mUserContext;
nsCOMPtr<nsIInputStream> mFromStream;
PRUint32 mStartPosition;
PRInt32 mCount;
PRUint32 mBufferSegmentSize;

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

@ -29,6 +29,8 @@ include $(DEPTH)/config/autoconf.mk
MODULE = test_necko
REQUIRES = xpcom necko timer cookie layout widget dom
SHARED_LIBRARY_LIBS = $(DIST)/lib/libmozdbm_s.$(LIB_SUFFIX)
CPPSRCS = \
TestSocketIO.cpp \
TestSocketInput.cpp \
@ -37,9 +39,11 @@ CPPSRCS = \
TestProtocols.cpp \
urltest.cpp \
TestFileInput2.cpp \
TestFileTransport.cpp \
TestRes.cpp \
TestCallbacks.cpp \
TestSyncHTTP.cpp \
TestDBMAccess.cpp \
$(NULL)
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
@ -59,6 +63,7 @@ LIBS = \
$(XPCOM_LIBS) \
$(LOST_SYM_LIBS) \
$(NSPR_LIBS) \
$(SHARED_LIBRARY_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -31,6 +31,19 @@
#include "nsIStreamListener.h"
#include "nsIEventQueueService.h"
#include "nsIEventQueue.h"
#include "nsNetUtil.h"
#include "prlog.h"
////////////////////////////////////////////////////////////////////////////////
#if defined(PR_LOGGING)
static PRLogModuleInfo *gTestFileTransportLog = nsnull;
#define PRINTF(args) PR_LOG(gTestFileTransportLog, PR_LOG_ALWAYS, args)
#else
#define PRINTF(args)
#endif
////////////////////////////////////////////////////////////////////////////////
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
@ -46,13 +59,13 @@ public:
NS_DECL_ISUPPORTS
NS_IMETHOD OnStartRequest(nsIChannel *channel, nsISupports *ctxt) {
printf("starting\n");
PRINTF(("starting\n"));
return NS_OK;
}
NS_IMETHOD OnStopRequest(nsIChannel *channel, nsISupports *ctxt,
nsresult aStatus, const PRUnichar* aStatusArg) {
printf("ending status=%0x total=%d\n", aStatus, mTotal);
PRINTF(("ending status=%0x total=%d\n", aStatus, mTotal));
if (--mStopCount == 0)
gDone = PR_TRUE;
return NS_OK;
@ -61,9 +74,9 @@ public:
NS_IMETHOD OnDataAvailable(nsIChannel *channel, nsISupports *ctxt,
nsIInputStream *inStr, PRUint32 sourceOffset,
PRUint32 count) {
printf("receiving %d bytes\n", count);
PRINTF(("receiving %d bytes\n", count));
char buf[256];
PRUint32 writeCount;
PRUint32 writeCount, givenCount=count;
nsresult rv;
while (count > 0) {
PRUint32 amt = PR_MIN(count, 256);
@ -71,12 +84,15 @@ public:
rv = inStr->Read(buf, amt, &readCount);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(readCount != 0, "premature EOF");
nsresult rv = mOut->Write(buf, readCount, &writeCount);
rv = mOut->Write(buf, readCount, &writeCount);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(writeCount == readCount, "failed to write all the data");
count -= readCount;
mTotal += readCount;
}
PRINTF(("done reading data [read %u bytes]\n", givenCount - count));
//PRINTF("sleeping for 100 ticks\n");FLUSH();
//PR_Sleep(100);
return NS_OK;
}
@ -124,6 +140,8 @@ TestAsyncRead(const char* fileName, PRUint32 offset, PRInt32 length)
{
nsresult rv;
PRINTF(("TestAsyncRead\n"));
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
@ -151,7 +169,7 @@ TestAsyncRead(const char* fileName, PRUint32 offset, PRInt32 length)
while (!gDone) {
PLEvent* event;
rv = gEventQ->GetEvent(&event);
rv = gEventQ->WaitForEvent(&event);
if (NS_FAILED(rv)) return rv;
rv = gEventQ->HandleEvent(event);
if (NS_FAILED(rv)) return rv;
@ -169,6 +187,8 @@ TestAsyncWrite(const char* fileName, PRUint32 offset, PRInt32 length)
{
nsresult rv;
PRINTF(("TestAsyncWrite\n"));
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
@ -202,12 +222,12 @@ TestAsyncWrite(const char* fileName, PRUint32 offset, PRInt32 length)
if (NS_FAILED(rv)) return rv;
rv = fileTrans->SetTransferCount(length);
if (NS_FAILED(rv)) return rv;
rv = fileTrans->AsyncWrite(inStr, listener, nsnull);
rv = NS_AsyncWriteFromStream(fileTrans, inStr, listener, nsnull);
if (NS_FAILED(rv)) return rv;
while (!gDone) {
PLEvent* event;
rv = gEventQ->GetEvent(&event);
rv = gEventQ->WaitForEvent(&event);
if (NS_FAILED(rv)) return rv;
rv = gEventQ->HandleEvent(event);
if (NS_FAILED(rv)) return rv;
@ -233,15 +253,15 @@ public:
PRInt32 length;
rv = channel->GetContentLength(&length);
if (NS_FAILED(rv)) return rv;
printf("stream opened: content type = %s, length = %d\n",
contentType, length);
PRINTF(("stream opened: content type = %s, length = %d\n",
contentType, length));
nsCRT::free(contentType);
return NS_OK;
}
NS_IMETHOD OnStopRequest(nsIChannel *channel, nsISupports *ctxt,
nsresult aStatus, const PRUnichar* aStatusArg) {
printf("stream closed: status %x\n", aStatus);
PRINTF(("stream closed: status %x\n", aStatus));
return NS_OK;
}
@ -265,6 +285,10 @@ main(int argc, char* argv[])
{
nsresult rv;
#if defined(PR_LOGGING)
gTestFileTransportLog = PR_NewLogModule("TestFileTransport");
#endif
if (argc < 2) {
printf("usage: %s <file-to-read>\n", argv[0]);
return -1;

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

@ -651,7 +651,7 @@ main(int argc, char* argv[])
/* Mac stuff is missing here! */
#else
PLEvent *gEvent;
rv = gEventQ->GetEvent(&gEvent);
rv = gEventQ->WaitForEvent(&gEvent);
rv = gEventQ->HandleEvent(gEvent);
#endif /* XP_UNIX */
#endif /* !WIN32 */

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

@ -20,6 +20,7 @@
* Contributor(s):
*/
#include <stdio.h>
#include <signal.h>
#ifdef WIN32
#include <windows.h>
@ -34,13 +35,19 @@
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h"
#include "nsIChannel.h"
#include "nsIStreamObserver.h"
#include "nsIStreamProvider.h"
#include "nsIStreamListener.h"
#include "nsIPipe.h"
#include "nsIOutputStream.h"
#include "nsIInputStream.h"
#include "nsCRT.h"
#include "nsCOMPtr.h"
#include "nsIByteArrayInputStream.h"
#if defined(PR_LOGGING)
static PRLogModuleInfo *gTestSocketIOLog;
#endif
#define LOG(args) PR_LOG(gTestSocketIOLog, PR_LOG_DEBUG, args)
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
@ -50,250 +57,310 @@ static PRTime gElapsedTime;
static int gKeepRunning = 1;
static nsIEventQueue* gEventQ = nsnull;
class InputTestConsumer : public nsIStreamListener
//
//----------------------------------------------------------------------------
// Test Listener
//----------------------------------------------------------------------------
//
class TestListener : public nsIStreamListener
{
public:
InputTestConsumer();
virtual ~InputTestConsumer();
TestListener() { NS_INIT_ISUPPORTS(); }
virtual ~TestListener() {}
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
};
InputTestConsumer::InputTestConsumer()
{
NS_INIT_REFCNT();
}
InputTestConsumer::~InputTestConsumer()
{
}
NS_IMPL_ADDREF(InputTestConsumer);
NS_IMPL_RELEASE(InputTestConsumer);
NS_IMPL_QUERY_INTERFACE2(InputTestConsumer,
NS_IMPL_ISUPPORTS2(TestListener,
nsIStreamObserver,
nsIStreamListener);
NS_IMETHODIMP
InputTestConsumer::OnStartRequest(nsIChannel* channel, nsISupports* context)
TestListener::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
printf("\n+++ InputTestConsumer::OnStartRequest +++\n");
LOG(("TestListener::OnStartRequest\n"));
return NS_OK;
}
NS_IMETHODIMP
InputTestConsumer::OnDataAvailable(nsIChannel* channel,
TestListener::OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength)
{
LOG(("TestListener::OnDataAvailable [offset=%u length=%u]\n",
aSourceOffset, aLength));
char buf[1025];
PRUint32 amt;
do {
while (1) {
aIStream->Read(buf, 1024, &amt);
if (amt == 0) break;
if (amt == 0)
break;
buf[amt] = '\0';
puts(buf);
} while (amt != 0);
}
return NS_OK;
}
NS_IMETHODIMP
InputTestConsumer::OnStopRequest(nsIChannel* channel, nsISupports* context,
TestListener::OnStopRequest(nsIChannel* channel, nsISupports* context,
nsresult aStatus, const PRUnichar* aStatusArg)
{
LOG(("TestListener::OnStopRequest [aStatus=%x]\n", aStatus));
gKeepRunning = 0;
printf("\n+++ InputTestConsumer::OnStopRequest (status = %x) +++\n", aStatus);
return NS_OK;
}
//
//----------------------------------------------------------------------------
// Test Provider
//----------------------------------------------------------------------------
//
class TestWriteObserver : public nsIStreamObserver
class TestProvider : public nsIStreamProvider
{
public:
TestWriteObserver(nsIChannel* aChannel);
virtual ~TestWriteObserver();
TestProvider(char *data);
virtual ~TestProvider();
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMPROVIDER
protected:
nsIChannel* mTransport;
nsCOMPtr<nsIByteArrayInputStream> mData;
};
NS_IMPL_ISUPPORTS2(TestProvider,
nsIStreamProvider,
nsIStreamObserver)
TestWriteObserver::TestWriteObserver(nsIChannel* aChannel)
TestProvider::TestProvider(char *data)
{
NS_INIT_REFCNT();
mTransport = aChannel;
NS_ADDREF(mTransport);
NS_INIT_ISUPPORTS();
NS_NewByteArrayInputStream(getter_AddRefs(mData), data, strlen(data));
LOG(("Constructing TestProvider [this=%x]\n", this));
}
TestWriteObserver::~TestWriteObserver()
TestProvider::~TestProvider()
{
NS_RELEASE(mTransport);
LOG(("Destroying TestProvider [this=%x]\n", this));
}
NS_IMPL_ISUPPORTS(TestWriteObserver,NS_GET_IID(nsIStreamObserver));
NS_IMETHODIMP
TestWriteObserver::OnStartRequest(nsIChannel* channel, nsISupports* context)
TestProvider::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
printf("\n+++ TestWriteObserver::OnStartRequest +++\n");
LOG(("TestProvider::OnStartRequest [this=%x]\n", this));
return NS_OK;
}
NS_IMETHODIMP
TestWriteObserver::OnStopRequest(nsIChannel* channel, nsISupports* context,
TestProvider::OnStopRequest(nsIChannel* channel, nsISupports* context,
nsresult aStatus, const PRUnichar* aStatusArg)
{
printf("\n+++ TestWriteObserver::OnStopRequest (status = %x) +++\n", aStatus);
LOG(("TestProvider::OnStopRequest [status=%x]\n", aStatus));
if (NS_SUCCEEDED(aStatus)) {
mTransport->AsyncRead(nsnull, new InputTestConsumer);
} else {
nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(new TestListener());
if (NS_SUCCEEDED(aStatus))
channel->AsyncRead(listener, nsnull);
else
gKeepRunning = 0;
}
return NS_OK;
}
nsresult NS_AutoregisterComponents()
NS_IMETHODIMP
TestProvider::OnDataWritable(nsIChannel *channel, nsISupports *context,
nsIOutputStream *output, PRUint32 offset, PRUint32 count)
{
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup, NULL /* default */);
LOG(("TestProvider::OnDataWritable [offset=%u, count=%u]\n", offset, count));
PRUint32 writeCount;
nsresult rv = output->WriteFrom(mData, count, &writeCount);
// Zero bytes written on success indicates EOF
if (NS_SUCCEEDED(rv) && (writeCount == 0))
return NS_BASE_STREAM_CLOSED;
return rv;
}
//
//----------------------------------------------------------------------------
// Synchronous IO
//----------------------------------------------------------------------------
//
nsresult
WriteRequest(nsIOutputStream *os, const char *request)
{
PRUint32 n;
return os->Write(request, strlen(request), &n);
}
nsresult
ReadResponse(nsIInputStream *is)
{
PRUint32 bytesRead;
char buf[2048];
do {
is->Read(buf, sizeof(buf), &bytesRead);
if (bytesRead > 0)
fwrite(buf, 1, bytesRead, stdout);
} while (bytesRead > 0);
return NS_OK;
}
//
//----------------------------------------------------------------------------
// Startup...
//----------------------------------------------------------------------------
//
void
sighandler(int sig)
{
LOG(("got signal: %d\n", sig));
NS_BREAK();
}
void
usage(char **argv)
{
printf("usage: %s [-sync] <host> <path>\n", argv[0]);
exit(1);
}
int
main(int argc, char* argv[])
{
nsresult rv;
if (argc < 3) {
printf("usage: %s <host> <path>\n", argv[0]);
return -1;
}
signal(SIGSEGV, sighandler);
char* hostName = argv[1];
char* fileName = argv[2];
int port = 80;
gTestSocketIOLog = PR_NewLogModule("TestSocketIO");
rv = NS_AutoregisterComponents();
if (argc < 3)
usage(argv);
if (NS_FAILED(rv)) return rv;
PRIntn i=0;
PRBool sync = PR_FALSE;
if (nsCRT::strcasecmp(argv[1], "-sync") == 0) {
if (argc < 4)
usage(argv);
sync = PR_TRUE;
i = 1;
}
char *hostName = argv[1+i];
char *fileName = argv[2+i];
int port = 80;
// Create the Event Queue for this thread...
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv)) {
NS_WARNING("failed to create: event queue service!");
return rv;
}
rv = eventQService->CreateThreadEventQueue();
if (NS_FAILED(rv)) return rv;
rv = eventQService->CreateMonitoredThreadEventQueue();
if (NS_FAILED(rv)) {
NS_WARNING("failed to create: thread event queue!");
return rv;
}
eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
// Create the Socket transport service...
NS_WITH_SERVICE(nsISocketTransportService, sts, kSocketTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
// Create a stream for the data being written to the server...
nsIInputStream* stream;
PRUint32 bytesWritten;
nsCOMPtr<nsIOutputStream> out;
rv = NS_NewPipe(&stream, getter_AddRefs(out), 1024, 4096);
if (NS_FAILED(rv)) return rv;
char *buffer = PR_smprintf("GET %s HTML/1.0%s%s", fileName, CRLF, CRLF);
out->Write(buffer, strlen(buffer), &bytesWritten);
printf("\n+++ Request is: %s\n", buffer);
// Create the socket transport...
nsIChannel* transport;
rv = sts->CreateTransport(hostName, port, nsnull, -1, 0, 0, &transport);
// This stuff is used to test the output stream
#if 0
nsIOutputStream* outStr = nsnull;
rv = transport->OpenOutputStream(&outStr);
if (NS_SUCCEEDED(rv)) {
PRUint32 bytes;
rv = outStr->Write("test", 4, &bytes);
if (NS_FAILED(rv)) return rv;
}
rv = outStr->Close();
#else
if (NS_SUCCEEDED(rv)) {
TestWriteObserver* observer = new TestWriteObserver(transport);
gElapsedTime = PR_Now();
rv = transport->SetTransferCount(bytesWritten);
if (NS_SUCCEEDED(rv)) {
rv = transport->AsyncWrite(stream, nsnull, observer);
if (NS_FAILED(rv)) {
NS_WARNING("failed to create: socket transport service!");
return rv;
}
NS_RELEASE(transport);
}
#endif
char *buffer = PR_smprintf("GET %s HTTP/1.1" CRLF
"host: %s" CRLF
"user-agent: Mozilla/5.0 (X11; N; Linux 2.2.16-22smp i686; en-US; m18) Gecko/20001220" CRLF
"accept: */*" CRLF
"accept-language: en" CRLF
"accept-encoding: gzip,deflate,compress,identity" CRLF
"keep-alive: 300" CRLF
"connection: keep-alive" CRLF
CRLF,
fileName, hostName);
LOG(("Request [\n%s]\n", buffer));
if (NS_FAILED(rv)) return rv;
// Create the socket transport...
nsCOMPtr<nsIChannel> transport;
rv = sts->CreateTransport(hostName, port, nsnull, -1, 0, 0, getter_AddRefs(transport));
if (NS_FAILED(rv)) {
NS_WARNING("failed to create: socket transport!");
return rv;
}
gElapsedTime = PR_Now();
if (!sync) {
rv = transport->AsyncWrite(new TestProvider(buffer), nsnull);
if (NS_FAILED(rv)) {
NS_WARNING("failed calling: AsyncWrite!");
return rv;
}
// Enter the message pump to allow the URL load to proceed.
while ( gKeepRunning ) {
#ifdef WIN32
MSG msg;
if (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
} else
gKeepRunning = FALSE;
}
#else
#ifdef XP_MAC
/* Mac stuff is missing here! */
#else
#ifdef XP_OS2
QMSG qmsg;
if (WinGetMsg(0, &qmsg, 0, 0, 0))
WinDispatchMsg(0, &qmsg);
else
gKeepRunning = FALSE;
#else
PLEvent *gEvent;
rv = gEventQ->GetEvent(&gEvent);
rv = gEventQ->WaitForEvent(&gEvent);
rv = gEventQ->HandleEvent(gEvent);
#endif
#endif
#endif
}
}
else {
// synchronous write
{
nsCOMPtr<nsIOutputStream> os;
rv = transport->OpenOutputStream(getter_AddRefs(os));
if (NS_FAILED(rv)) return rv;
rv = WriteRequest(os, buffer);
if (NS_FAILED(rv)) return rv;
}
// synchronous read
{
nsCOMPtr<nsIInputStream> is;
rv = transport->OpenInputStream(getter_AddRefs(is));
if (NS_FAILED(rv)) return rv;
rv = ReadResponse(is);
if (NS_FAILED(rv)) return rv;
}
}
PRTime endTime;
endTime = PR_Now();
printf("Elapsed time: %d\n", (PRInt32)(endTime/1000UL-gElapsedTime/1000UL));
LOG(("Elapsed time: %d\n", (PRInt32)(endTime/1000UL - gElapsedTime/1000UL)));
sts->Shutdown();
return 0;
}

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

@ -49,6 +49,7 @@
#include "nsIInterfaceRequestor.h"
#include "nsIProgressEventSink.h"
#include "nsCRT.h"
#include "nsNetUtil.h"
#if defined(XP_MAC)
#include "macstdlibextras.h"
@ -431,7 +432,7 @@ nsresult TestConnection::WriteBuffer(void)
if (NS_SUCCEEDED(rv)) {
rv = mTransport->SetTransferCount(bytesWritten);
if (NS_SUCCEEDED(rv)) {
rv = mTransport->AsyncWrite(mStream, /* mOutputObserver */ nsnull, mTransport);
rv = NS_AsyncWriteFromStream(mTransport, mStream, nsnull, mTransport);
}
}
// Wait for the write to complete...

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

@ -271,7 +271,7 @@ nsCachedChromeChannel::AsyncRead(nsIStreamListener *listener, nsISupports *ctxt)
}
NS_IMETHODIMP
nsCachedChromeChannel::AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt)
nsCachedChromeChannel::AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;

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

@ -349,7 +349,7 @@ public:
NS_IMETHOD OpenOutputStream(nsIOutputStream **_retval) { *_retval = nsnull; return NS_OK; }
NS_IMETHOD AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncRead(nsIStreamListener *listener, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD AsyncWrite(nsIStreamProvider *provider, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes) { *aLoadAttributes = nsIChannel::LOAD_NORMAL; return NS_OK; }
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes) { return NS_OK; }
NS_IMETHOD GetContentType(char * *aContentType) { *aContentType = nsnull; return NS_OK; }

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

@ -403,6 +403,10 @@ nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK)
goto done;
NS_ASSERTION(writeCount <= readBufferLen, "writer returned bad writeCount");
#ifdef DEBUG
if (writeCount > 0 && rv == NS_BASE_STREAM_WOULD_BLOCK)
NS_WARNING("Invalid writer implementation: cannot write data and return WOULD_BLOCK");
#endif
readBuffer += writeCount;
readBufferLen -= writeCount;
*readCount += writeCount;
@ -432,6 +436,15 @@ nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
goto done;
}
}
else if (pipe->mReadCursor == pipe->mWriteCursor) {
if (mObserver) {
mon.Exit(); // XXXbe avoid deadlock better
rv = mObserver->OnEmpty(this);
mon.Enter();
if (NS_FAILED(rv))
goto done;
}
}
}
done:

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

@ -152,6 +152,8 @@ public:
PRUint32 count;
PRUint32 total = 0;
while (PR_TRUE) {
//if (gTrace)
// printf("calling Read\n");
rv = mIn->Read(buf, 100, &count);
if (NS_FAILED(rv)) {
printf("read failed\n");
@ -231,7 +233,9 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
if (gTrace)
printf("wrote %d bytes: %s\n", writeCount, buf);
PR_smprintf_free(buf);
//printf("calling Flush\n");
out->Flush();
//printf("calling WaitForReceipt\n");
PRUint32 received = receiver->WaitForReceipt();
NS_ASSERTION(received == writeCount, "received wrong amount");
}
@ -292,7 +296,7 @@ TestPipeObserver()
printf("TestPipeObserver: OnWrite and OnFull should be called once, OnEmpty should be called twice.\n");
nsIInputStream* in;
nsIOutputStream* out;
rv = NS_NewPipe(&in, &out, 20, 20, PR_TRUE, PR_TRUE);
rv = NS_NewPipe(&in, &out, 18, 36, PR_TRUE, PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = in->SetObserver(obs);
@ -302,27 +306,55 @@ TestPipeObserver()
char buf[] = "puirt a beul: a style of Gaelic vocal music intended for dancing.";
PRUint32 cnt;
// this should print OnWrite message:
printf("> should see OnWrite message:\n");
rv = out->Write(buf, 20, &cnt);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(cnt == 20, "Write failed");
// this should print OnFull message:
rv = out->Write(buf + 20, 1, &cnt);
if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) return rv;
NS_ASSERTION(cnt == 0 && rv == NS_BASE_STREAM_WOULD_BLOCK, "Write failed");
char buf2[20];
rv = in->Read(buf2, 20, &cnt);
printf("> should see OnWrite message followed by OnFull message:\n");
rv = out->Write(buf + 20, 20, &cnt);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(cnt == 20, "Read failed");
NS_ASSERTION(nsCRT::strncmp(buf, buf2, 20) == 0, "Read wrong stuff");
NS_ASSERTION(cnt == 16, "Write failed");
// this should print OnEmpty message:
rv = in->Read(buf2, 1, &cnt);
rv = in->Available(&cnt);
if (NS_FAILED(rv)) return rv;
printf("available = %u\n", cnt);
NS_ASSERTION(cnt == 36, "Available failed");
char buf2[40];
printf("> should see OnEmpty message:\n");
rv = in->Read(buf2, 40, &cnt);
if (NS_FAILED(rv)) return rv;
printf("cnt = %u\n", cnt);
NS_ASSERTION(cnt == 36, "Read failed");
NS_ASSERTION(nsCRT::strncmp(buf, buf2, 36) == 0, "Read wrong stuff");
rv = in->Available(&cnt);
if (NS_FAILED(rv)) return rv;
printf("available = %u\n", cnt);
NS_ASSERTION(cnt == 0, "Available failed");
printf("> should see OnEmpty message:\n");
rv = in->Read(buf2, 2, &cnt);
if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) return rv;
NS_ASSERTION(cnt == 0 && rv == NS_BASE_STREAM_WOULD_BLOCK, "Read failed");
printf("> should see OnWrite message:\n");
rv = out->Write(buf, 20, &cnt);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(cnt == 20, "Write failed");
rv = in->Available(&cnt);
if (NS_FAILED(rv)) return rv;
printf("available = %u\n", cnt);
NS_ASSERTION(cnt == 20, "Available failed");
printf("> should see OnEmpty message:\n");
rv = in->Read(buf2, 20, &cnt);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(cnt == 20, "Read failed");
printf("> should see OnClose message:\n");
NS_RELEASE(obs);
NS_RELEASE(in);
NS_RELEASE(out);

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

@ -202,7 +202,7 @@ nsStreamXferOp::Start( void ) {
// hand the output channel our input stream. it will take care
// of reading data from the stream and writing it to disk.
rv = mOutputChannel->AsyncWrite(inStream, NS_STATIC_CAST(nsIStreamObserver*,this), nsnull);
rv = NS_AsyncWriteFromStream(mOutputChannel, inStream, NS_STATIC_CAST(nsIStreamObserver*,this), nsnull);
if ( NS_FAILED( rv ) ) {
this->OnError( kOpAsyncWrite, rv );
}