1 : /* vim:set ts=4 sw=4 sts=4 ci et: */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2002
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Darin Fisher <darin@netscape.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef nsSocketTransportService2_h__
40 : #define nsSocketTransportService2_h__
41 :
42 : #include "nsPISocketTransportService.h"
43 : #include "nsIThreadInternal.h"
44 : #include "nsThreadUtils.h"
45 : #include "nsEventQueue.h"
46 : #include "nsCOMPtr.h"
47 : #include "pldhash.h"
48 : #include "prinrval.h"
49 : #include "prlog.h"
50 : #include "prinit.h"
51 : #include "prio.h"
52 : #include "nsASocketHandler.h"
53 : #include "nsIObserver.h"
54 : #include "mozilla/Mutex.h"
55 :
56 : //-----------------------------------------------------------------------------
57 :
58 : #if defined(PR_LOGGING)
59 : //
60 : // set NSPR_LOG_MODULES=nsSocketTransport:5
61 : //
62 : extern PRLogModuleInfo *gSocketTransportLog;
63 : #endif
64 : #define SOCKET_LOG(args) PR_LOG(gSocketTransportLog, PR_LOG_DEBUG, args)
65 : #define SOCKET_LOG_ENABLED() PR_LOG_TEST(gSocketTransportLog, PR_LOG_DEBUG)
66 :
67 : //-----------------------------------------------------------------------------
68 :
69 : #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT
70 :
71 : //-----------------------------------------------------------------------------
72 :
73 : class nsSocketTransportService : public nsPISocketTransportService
74 : , public nsIEventTarget
75 : , public nsIThreadObserver
76 : , public nsIRunnable
77 : , public nsIObserver
78 : {
79 : typedef mozilla::Mutex Mutex;
80 :
81 : public:
82 : NS_DECL_ISUPPORTS
83 : NS_DECL_NSPISOCKETTRANSPORTSERVICE
84 : NS_DECL_NSISOCKETTRANSPORTSERVICE
85 : NS_DECL_NSIEVENTTARGET
86 : NS_DECL_NSITHREADOBSERVER
87 : NS_DECL_NSIRUNNABLE
88 : NS_DECL_NSIOBSERVER
89 :
90 : nsSocketTransportService();
91 :
92 : // Max Socket count may need to get initialized/used by nsHttpHandler
93 : // before this class is initialized.
94 : static PRUint32 gMaxCount;
95 : static PRCallOnceType gMaxCountInitOnce;
96 : static PRStatus DiscoverMaxCount();
97 :
98 : //
99 : // the number of sockets that can be attached at any given time is
100 : // limited. this is done because some operating systems (e.g., Win9x)
101 : // limit the number of sockets that can be created by an application.
102 : // AttachSocket will fail if the limit is exceeded. consumers should
103 : // call CanAttachSocket and check the result before creating a socket.
104 : //
105 12592 : bool CanAttachSocket() {
106 12592 : return mActiveCount + mIdleCount < gMaxCount;
107 : }
108 :
109 : protected:
110 :
111 : virtual ~nsSocketTransportService();
112 :
113 : private:
114 :
115 : //-------------------------------------------------------------------------
116 : // misc (any thread)
117 : //-------------------------------------------------------------------------
118 :
119 : nsCOMPtr<nsIThread> mThread; // protected by mLock
120 : PRFileDesc *mThreadEvent;
121 : // protected by mLock. mThreadEvent may change
122 : // if the old pollable event is broken. only
123 : // the socket thread may change mThreadEvent;
124 : // it needs to lock mLock only when it changes
125 : // mThreadEvent. other threads don't change
126 : // mThreadEvent; they need to lock mLock
127 : // whenever they access mThreadEvent.
128 : bool mAutodialEnabled;
129 : // pref to control autodial code
130 :
131 : // Returns mThread, protecting the get-and-addref with mLock
132 : already_AddRefed<nsIThread> GetThreadSafely();
133 :
134 : //-------------------------------------------------------------------------
135 : // initialization and shutdown (any thread)
136 : //-------------------------------------------------------------------------
137 :
138 : Mutex mLock;
139 : bool mInitialized;
140 : bool mShuttingDown;
141 : // indicates whether we are currently in the
142 : // process of shutting down
143 :
144 : //-------------------------------------------------------------------------
145 : // socket lists (socket thread only)
146 : //
147 : // only "active" sockets are on the poll list. the active list is kept
148 : // in sync with the poll list such that:
149 : //
150 : // mActiveList[k].mFD == mPollList[k+1].fd
151 : //
152 : // where k=0,1,2,...
153 : //-------------------------------------------------------------------------
154 :
155 : struct SocketContext
156 : {
157 : PRFileDesc *mFD;
158 : nsASocketHandler *mHandler;
159 : PRUint16 mElapsedTime; // time elapsed w/o activity
160 : };
161 :
162 : SocketContext *mActiveList; /* mListSize entries */
163 : SocketContext *mIdleList; /* mListSize entries */
164 :
165 : PRUint32 mActiveListSize;
166 : PRUint32 mIdleListSize;
167 : PRUint32 mActiveCount;
168 : PRUint32 mIdleCount;
169 :
170 : nsresult DetachSocket(SocketContext *, SocketContext *);
171 : nsresult AddToIdleList(SocketContext *);
172 : nsresult AddToPollList(SocketContext *);
173 : void RemoveFromIdleList(SocketContext *);
174 : void RemoveFromPollList(SocketContext *);
175 : void MoveToIdleList(SocketContext *sock);
176 : void MoveToPollList(SocketContext *sock);
177 :
178 : bool GrowActiveList();
179 : bool GrowIdleList();
180 : void InitMaxCount();
181 :
182 : //-------------------------------------------------------------------------
183 : // poll list (socket thread only)
184 : //
185 : // first element of the poll list is mThreadEvent (or null if the pollable
186 : // event cannot be created).
187 : //-------------------------------------------------------------------------
188 :
189 : PRPollDesc *mPollList; /* mListSize + 1 entries */
190 :
191 : PRIntervalTime PollTimeout(); // computes ideal poll timeout
192 : nsresult DoPollIteration(bool wait);
193 : // perfoms a single poll iteration
194 : PRInt32 Poll(bool wait, PRUint32 *interval);
195 : // calls PR_Poll. the out param
196 : // interval indicates the poll
197 : // duration in seconds.
198 :
199 : //-------------------------------------------------------------------------
200 : // pending socket queue - see NotifyWhenCanAttachSocket
201 : //-------------------------------------------------------------------------
202 :
203 : nsEventQueue mPendingSocketQ; // queue of nsIRunnable objects
204 :
205 : // Preference Monitor for SendBufferSize
206 : nsresult UpdatePrefs();
207 : PRInt32 mSendBufferSize;
208 :
209 : // Socket thread only for dynamically adjusting max socket size
210 : #if defined(XP_WIN)
211 : void ProbeMaxCount();
212 : #endif
213 : bool mProbedMaxCount;
214 : };
215 :
216 : extern nsSocketTransportService *gSocketTransportService;
217 : extern PRThread *gSocketThread;
218 :
219 : #endif // !nsSocketTransportService_h__
|