Back to index

lightning-sunbird  0.9+nobinonly
nsSyncStreamListener.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla.
00015  *
00016  * The Initial Developer of the Original Code is IBM Corporation.
00017  * Portions created by IBM Corporation are Copyright (C) 2003
00018  * IBM Corporation. All Rights Reserved.
00019  *
00020  * Contributor(s):
00021  *   IBM Corp.
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "nsSyncStreamListener.h"
00038 #include "nsIPipe.h"
00039 #include "nsEventQueueUtils.h"
00040 #include "nsNetSegmentUtils.h"
00041 
00042 nsresult
00043 nsSyncStreamListener::Init()
00044 {
00045     return NS_NewPipe(getter_AddRefs(mPipeIn),
00046                       getter_AddRefs(mPipeOut),
00047                       NET_DEFAULT_SEGMENT_SIZE,
00048                       PR_UINT32_MAX, // no size limit
00049                       PR_FALSE,
00050                       PR_FALSE);
00051 }
00052 
00053 nsresult
00054 nsSyncStreamListener::WaitForData()
00055 {
00056     nsresult rv;
00057 
00058     if (!mEventQ) {
00059         rv = NS_GetCurrentEventQ(getter_AddRefs(mEventQ));
00060         if (NS_FAILED(rv)) return rv;
00061     }
00062 
00063     mKeepWaiting = PR_TRUE;
00064 
00065     PLEvent *ev;
00066     while (mKeepWaiting) {
00067         rv = mEventQ->WaitForEvent(&ev);
00068         if (NS_FAILED(rv)) return rv;
00069 
00070         rv = mEventQ->HandleEvent(ev);
00071         if (NS_FAILED(rv)) return rv;
00072     }
00073 
00074     return NS_OK;
00075 }
00076 
00077 //-----------------------------------------------------------------------------
00078 // nsSyncStreamListener::nsISupports
00079 //-----------------------------------------------------------------------------
00080 
00081 NS_IMPL_ISUPPORTS4(nsSyncStreamListener,
00082                    nsIStreamListener,
00083                    nsIRequestObserver,
00084                    nsIInputStream,
00085                    nsISyncStreamListener)
00086 
00087 //-----------------------------------------------------------------------------
00088 // nsSyncStreamListener::nsISyncStreamListener
00089 //-----------------------------------------------------------------------------
00090 
00091 NS_IMETHODIMP
00092 nsSyncStreamListener::GetInputStream(nsIInputStream **result)
00093 {
00094     NS_ADDREF(*result = this);
00095     return NS_OK;
00096 }
00097 
00098 //-----------------------------------------------------------------------------
00099 // nsSyncStreamListener::nsIStreamListener
00100 //-----------------------------------------------------------------------------
00101 
00102 NS_IMETHODIMP
00103 nsSyncStreamListener::OnStartRequest(nsIRequest  *request,
00104                                      nsISupports *context)
00105 {
00106     return NS_OK;
00107 }
00108 
00109 NS_IMETHODIMP
00110 nsSyncStreamListener::OnDataAvailable(nsIRequest     *request,
00111                                       nsISupports    *context,
00112                                       nsIInputStream *stream,
00113                                       PRUint32        offset,
00114                                       PRUint32        count)
00115 {
00116     PRUint32 bytesWritten;
00117 
00118     nsresult rv = mPipeOut->WriteFrom(stream, count, &bytesWritten);
00119 
00120     // if we get an error, then return failure.  this will cause the
00121     // channel to be canceled, and as a result our OnStopRequest method
00122     // will be called immediately.  because of this we do not need to
00123     // set mStatus or mKeepWaiting here.
00124     if (NS_FAILED(rv))
00125         return rv;
00126 
00127     // we expect that all data will be written to the pipe because
00128     // the pipe was created to have "infinite" room.
00129     NS_ASSERTION(bytesWritten == count, "did not write all data"); 
00130 
00131     mKeepWaiting = PR_FALSE; // unblock Read
00132     return NS_OK;
00133 }
00134 
00135 NS_IMETHODIMP
00136 nsSyncStreamListener::OnStopRequest(nsIRequest  *request,
00137                                     nsISupports *context,
00138                                     nsresult     status)
00139 {
00140     mStatus = status;
00141     mKeepWaiting = PR_FALSE; // unblock Read
00142     mDone = PR_TRUE;
00143     return NS_OK;
00144 }
00145 
00146 //-----------------------------------------------------------------------------
00147 // nsSyncStreamListener::nsIInputStream
00148 //-----------------------------------------------------------------------------
00149 
00150 NS_IMETHODIMP
00151 nsSyncStreamListener::Close()
00152 {
00153     mStatus = NS_BASE_STREAM_CLOSED;
00154     mDone = PR_TRUE;
00155     // XXX shouldn't we cancel the nsIRequest at this point?
00156     return NS_OK;
00157 }
00158 
00159 NS_IMETHODIMP
00160 nsSyncStreamListener::Available(PRUint32 *result)
00161 {
00162     if (NS_FAILED(mStatus))
00163         return mStatus;
00164 
00165     mStatus = mPipeIn->Available(result);
00166     if (NS_SUCCEEDED(mStatus) && (*result == 0) && !mDone) {
00167         mStatus = WaitForData();
00168         if (NS_SUCCEEDED(mStatus))
00169             mStatus = mPipeIn->Available(result);
00170     }
00171     return mStatus;
00172 }
00173 
00174 NS_IMETHODIMP
00175 nsSyncStreamListener::Read(char     *buf,
00176                            PRUint32  bufLen,
00177                            PRUint32 *result)
00178 {
00179     PRUint32 avail;
00180     if (NS_FAILED(Available(&avail)))
00181         return mStatus;
00182 
00183     avail = PR_MIN(avail, bufLen);
00184     mStatus = mPipeIn->Read(buf, avail, result);
00185     return mStatus;
00186 }
00187 
00188 NS_IMETHODIMP
00189 nsSyncStreamListener::ReadSegments(nsWriteSegmentFun  writer,
00190                                    void              *closure,
00191                                    PRUint32           count,
00192                                    PRUint32          *result)
00193 {
00194     PRUint32 avail;
00195     if (NS_FAILED(Available(&avail)))
00196         return mStatus;
00197 
00198     avail = PR_MIN(avail, count);
00199     mStatus = mPipeIn->ReadSegments(writer, closure, avail, result);
00200     return mStatus;
00201 }
00202 
00203 NS_IMETHODIMP
00204 nsSyncStreamListener::IsNonBlocking(PRBool *result)
00205 {
00206     *result = PR_FALSE;
00207     return NS_OK;
00208 }