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
;
205 PRUint32 mConnectionFlags
;
207 PRUint16
SocketPort() { return (!mProxyHost
.IsEmpty() && !mProxyTransparent
) ? mProxyPort
: mPort
; }
208 const nsCString
&SocketHost() { return (!mProxyHost
.IsEmpty() && !mProxyTransparent
) ? mProxyHost
: mHost
; }
210 //-------------------------------------------------------------------------
211 // members accessible only on the socket transport thread:
212 // (the exception being initialization/shutdown time)
213 //-------------------------------------------------------------------------
215 // socket state vars:
216 PRUint32 mState
; // STATE_??? flags
217 PRPackedBool mAttached
;
218 PRPackedBool mInputClosed
;
219 PRPackedBool mOutputClosed
;
221 // this flag is used to determine if the results of a host lookup arrive
222 // recursively or not. this flag is not protected by any lock.
223 PRPackedBool mResolving
;
225 nsCOMPtr
<nsICancelable
> mDNSRequest
;
226 nsCOMPtr
<nsIDNSRecord
> mDNSRecord
;
229 // socket methods (these can only be called on the socket thread):
231 void SendStatus(nsresult status
);
232 nsresult
ResolveHost();
233 nsresult
BuildSocket(PRFileDesc
*&, PRBool
&, PRBool
&);
234 nsresult
InitiateSocket();
235 PRBool
RecoverFromError();
237 void OnMsgInputPending()
239 if (mState
== STATE_TRANSFERRING
)
240 mPollFlags
|= (PR_POLL_READ
| PR_POLL_EXCEPT
);
242 void OnMsgOutputPending()
244 if (mState
== STATE_TRANSFERRING
)
245 mPollFlags
|= (PR_POLL_WRITE
| PR_POLL_EXCEPT
);
247 void OnMsgInputClosed(nsresult reason
);
248 void OnMsgOutputClosed(nsresult reason
);
250 // called when the socket is connected
251 void OnSocketConnected();
253 //-------------------------------------------------------------------------
254 // socket input/output objects. these may be accessed on any thread with
255 // the exception of some specific methods (XXX).
257 PRLock
*mLock
; // protects members in this section
259 nsrefcnt mFDref
; // mFD is closed when mFDref goes to zero.
260 PRBool mFDconnected
; // mFD is available to consumer when TRUE.
262 nsCOMPtr
<nsIInterfaceRequestor
> mCallbacks
;
263 nsCOMPtr
<nsITransportEventSink
> mEventSink
;
264 nsCOMPtr
<nsISupports
> mSecInfo
;
266 nsSocketInputStream mInput
;
267 nsSocketOutputStream mOutput
;
269 friend class nsSocketInputStream
;
270 friend class nsSocketOutputStream
;
272 // socket timeouts are not protected by any lock.
273 PRUint16 mTimeouts
[2];
276 // mFD access methods: called with mLock held.
278 PRFileDesc
*GetFD_Locked();
279 void ReleaseFD_Locked(PRFileDesc
*fd
);
282 // stream state changes (called outside mLock):
284 void OnInputClosed(nsresult reason
)
286 // no need to post an event if called on the socket thread
287 if (PR_GetCurrentThread() == gSocketThread
)
288 OnMsgInputClosed(reason
);
290 PostEvent(MSG_INPUT_CLOSED
, reason
);
292 void OnInputPending()
294 // no need to post an event if called on the socket thread
295 if (PR_GetCurrentThread() == gSocketThread
)
298 PostEvent(MSG_INPUT_PENDING
);
300 void OnOutputClosed(nsresult reason
)
302 // no need to post an event if called on the socket thread
303 if (PR_GetCurrentThread() == gSocketThread
)
304 OnMsgOutputClosed(reason
); // XXX need to not be inside lock!
306 PostEvent(MSG_OUTPUT_CLOSED
, reason
);
308 void OnOutputPending()
310 // no need to post an event if called on the socket thread
311 if (PR_GetCurrentThread() == gSocketThread
)
312 OnMsgOutputPending();
314 PostEvent(MSG_OUTPUT_PENDING
);
317 #ifdef ENABLE_SOCKET_TRACING
318 void TraceInBuf(const char *buf
, PRInt32 n
);
319 void TraceOutBuf(const char *buf
, PRInt32 n
);
323 #endif // !nsSocketTransport_h__