1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is Mozilla.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2002
19 * the Initial Developer. All Rights Reserved.
22 * Darin Fisher <darin@netscape.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef nsSocketTransport2_h__
39 #define nsSocketTransport2_h__
42 #define ENABLE_SOCKET_TRACING
45 #include "nsSocketTransportService2.h"
50 #include "nsISocketTransport.h"
51 #include "nsIInterfaceRequestor.h"
52 #include "nsIAsyncInputStream.h"
53 #include "nsIAsyncOutputStream.h"
54 #include "nsIDNSListener.h"
55 #include "nsIDNSRecord.h"
56 #include "nsICancelable.h"
57 #include "nsIClassInfo.h"
59 class nsSocketTransport
;
61 //-----------------------------------------------------------------------------
63 // after this short interval, we will return to PR_Poll
64 #define NS_SOCKET_CONNECT_TIMEOUT PR_MillisecondsToInterval(20)
66 //-----------------------------------------------------------------------------
68 class nsSocketInputStream
: public nsIAsyncInputStream
71 NS_DECL_ISUPPORTS_INHERITED
72 NS_DECL_NSIINPUTSTREAM
73 NS_DECL_NSIASYNCINPUTSTREAM
75 nsSocketInputStream(nsSocketTransport
*);
76 virtual ~nsSocketInputStream();
78 PRBool
IsReferenced() { return mReaderRefCnt
> 0; }
79 nsresult
Condition() { return mCondition
; }
80 PRUint64
ByteCount() { return mByteCount
; }
82 // called by the socket transport on the socket thread...
83 void OnSocketReady(nsresult condition
);
86 nsSocketTransport
*mTransport
;
87 nsrefcnt mReaderRefCnt
;
89 // access to these is protected by mTransport->mLock
91 nsCOMPtr
<nsIInputStreamCallback
> mCallback
;
92 PRUint32 mCallbackFlags
;
96 //-----------------------------------------------------------------------------
98 class nsSocketOutputStream
: public nsIAsyncOutputStream
101 NS_DECL_ISUPPORTS_INHERITED
102 NS_DECL_NSIOUTPUTSTREAM
103 NS_DECL_NSIASYNCOUTPUTSTREAM
105 nsSocketOutputStream(nsSocketTransport
*);
106 virtual ~nsSocketOutputStream();
108 PRBool
IsReferenced() { return mWriterRefCnt
> 0; }
109 nsresult
Condition() { return mCondition
; }
110 PRUint64
ByteCount() { return mByteCount
; }
112 // called by the socket transport on the socket thread...
113 void OnSocketReady(nsresult condition
);
116 static NS_METHOD
WriteFromSegments(nsIInputStream
*, void *,
117 const char *, PRUint32 offset
,
118 PRUint32 count
, PRUint32
*countRead
);
120 nsSocketTransport
*mTransport
;
121 nsrefcnt mWriterRefCnt
;
123 // access to these is protected by mTransport->mLock
125 nsCOMPtr
<nsIOutputStreamCallback
> mCallback
;
126 PRUint32 mCallbackFlags
;
130 //-----------------------------------------------------------------------------
132 class nsSocketTransport
: public nsASocketHandler
133 , public nsISocketTransport
134 , public nsIDNSListener
135 , public nsIClassInfo
140 NS_DECL_NSISOCKETTRANSPORT
141 NS_DECL_NSIDNSLISTENER
146 // this method instructs the socket transport to open a socket of the
147 // given type(s) to the given host or proxy.
148 nsresult
Init(const char **socketTypes
, PRUint32 typeCount
,
149 const nsACString
&host
, PRUint16 port
,
150 nsIProxyInfo
*proxyInfo
);
152 // this method instructs the socket transport to use an already connected
153 // socket with the given address.
154 nsresult
InitWithConnectedSocket(PRFileDesc
*socketFD
,
155 const PRNetAddr
*addr
);
157 // nsASocketHandler methods:
158 void OnSocketReady(PRFileDesc
*, PRInt16 outFlags
);
159 void OnSocketDetached(PRFileDesc
*);
161 // called when a socket event is handled
162 void OnSocketEvent(PRUint32 type
, nsresult status
, nsISupports
*param
);
166 virtual ~nsSocketTransport();
173 MSG_DNS_LOOKUP_COMPLETE
,
174 MSG_RETRY_INIT_SOCKET
,
181 nsresult
PostEvent(PRUint32 type
, nsresult status
= NS_OK
, nsISupports
*param
= nsnull
);
191 //-------------------------------------------------------------------------
192 // these members are "set" at initialization time and are never modified
193 // afterwards. this allows them to be safely accessed from any thread.
194 //-------------------------------------------------------------------------
200 nsCString mProxyHost
;
203 PRPackedBool mProxyTransparent
;
204 PRPackedBool mProxyTransparentResolvesHost
;
206 PRUint16
SocketPort() { return (!mProxyHost
.IsEmpty() && !mProxyTransparent
) ? mProxyPort
: mPort
; }
207 const nsCString
&SocketHost() { return (!mProxyHost
.IsEmpty() && !mProxyTransparent
) ? mProxyHost
: mHost
; }
209 //-------------------------------------------------------------------------
210 // members accessible only on the socket transport thread:
211 // (the exception being initialization/shutdown time)
212 //-------------------------------------------------------------------------
214 // socket state vars:
215 PRUint32 mState
; // STATE_??? flags
216 PRPackedBool mAttached
;
217 PRPackedBool mInputClosed
;
218 PRPackedBool mOutputClosed
;
220 // this flag is used to determine if the results of a host lookup arrive
221 // recursively or not. this flag is not protected by any lock.
222 PRPackedBool mResolving
;
224 nsCOMPtr
<nsICancelable
> mDNSRequest
;
225 nsCOMPtr
<nsIDNSRecord
> mDNSRecord
;
228 // socket methods (these can only be called on the socket thread):
230 void SendStatus(nsresult status
);
231 nsresult
ResolveHost();
232 nsresult
BuildSocket(PRFileDesc
*&, PRBool
&, PRBool
&);
233 nsresult
InitiateSocket();
234 PRBool
RecoverFromError();
236 void OnMsgInputPending()
238 if (mState
== STATE_TRANSFERRING
)
239 mPollFlags
|= (PR_POLL_READ
| PR_POLL_EXCEPT
);
241 void OnMsgOutputPending()
243 if (mState
== STATE_TRANSFERRING
)
244 mPollFlags
|= (PR_POLL_WRITE
| PR_POLL_EXCEPT
);
246 void OnMsgInputClosed(nsresult reason
);
247 void OnMsgOutputClosed(nsresult reason
);
249 // called when the socket is connected
250 void OnSocketConnected();
252 //-------------------------------------------------------------------------
253 // socket input/output objects. these may be accessed on any thread with
254 // the exception of some specific methods (XXX).
256 PRLock
*mLock
; // protects members in this section
258 nsrefcnt mFDref
; // mFD is closed when mFDref goes to zero.
259 PRBool mFDconnected
; // mFD is available to consumer when TRUE.
261 nsCOMPtr
<nsIInterfaceRequestor
> mCallbacks
;
262 nsCOMPtr
<nsITransportEventSink
> mEventSink
;
263 nsCOMPtr
<nsISupports
> mSecInfo
;
265 nsSocketInputStream mInput
;
266 nsSocketOutputStream mOutput
;
268 friend class nsSocketInputStream
;
269 friend class nsSocketOutputStream
;
271 // socket timeouts are not protected by any lock.
272 PRUint16 mTimeouts
[2];
275 // mFD access methods: called with mLock held.
277 PRFileDesc
*GetFD_Locked();
278 void ReleaseFD_Locked(PRFileDesc
*fd
);
281 // stream state changes (called outside mLock):
283 void OnInputClosed(nsresult reason
)
285 // no need to post an event if called on the socket thread
286 if (PR_GetCurrentThread() == gSocketThread
)
287 OnMsgInputClosed(reason
);
289 PostEvent(MSG_INPUT_CLOSED
, reason
);
291 void OnInputPending()
293 // no need to post an event if called on the socket thread
294 if (PR_GetCurrentThread() == gSocketThread
)
297 PostEvent(MSG_INPUT_PENDING
);
299 void OnOutputClosed(nsresult reason
)
301 // no need to post an event if called on the socket thread
302 if (PR_GetCurrentThread() == gSocketThread
)
303 OnMsgOutputClosed(reason
); // XXX need to not be inside lock!
305 PostEvent(MSG_OUTPUT_CLOSED
, reason
);
307 void OnOutputPending()
309 // no need to post an event if called on the socket thread
310 if (PR_GetCurrentThread() == gSocketThread
)
311 OnMsgOutputPending();
313 PostEvent(MSG_OUTPUT_PENDING
);
316 #ifdef ENABLE_SOCKET_TRACING
317 void TraceInBuf(const char *buf
, PRInt32 n
);
318 void TraceOutBuf(const char *buf
, PRInt32 n
);
322 #endif // !nsSocketTransport_h__