Back to index

lightning-sunbird  0.9+nobinonly
nsSocketTransportService2.h
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
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2002
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Darin Fisher <darin@netscape.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef nsSocketTransportService2_h__
00039 #define nsSocketTransportService2_h__
00040 
00041 #include "nsPISocketTransportService.h"
00042 #include "nsIEventTarget.h"
00043 #include "nsIRunnable.h"
00044 #include "nsIThread.h"
00045 #include "nsCOMPtr.h"
00046 #include "pldhash.h"
00047 #include "prinrval.h"
00048 #include "prlog.h"
00049 #include "prio.h"
00050 
00051 //-----------------------------------------------------------------------------
00052 
00053 #if defined(PR_LOGGING)
00054 //
00055 // set NSPR_LOG_MODULES=nsSocketTransport:5
00056 //
00057 extern PRLogModuleInfo *gSocketTransportLog;
00058 #endif
00059 #define LOG(args)     PR_LOG(gSocketTransportLog, PR_LOG_DEBUG, args)
00060 #define LOG_ENABLED() PR_LOG_TEST(gSocketTransportLog, PR_LOG_DEBUG)
00061 
00062 //-----------------------------------------------------------------------------
00063 
00064 #define NS_SOCKET_MAX_COUNT    50
00065 #define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT
00066 
00067 //-----------------------------------------------------------------------------
00068 // socket handler: methods are only called on the socket thread.
00069 
00070 class nsASocketHandler : public nsISupports
00071 {
00072 public:
00073     nsASocketHandler()
00074         : mCondition(NS_OK)
00075         , mPollFlags(0)
00076         , mPollTimeout(PR_UINT16_MAX)
00077         {}
00078 
00079     //
00080     // this condition variable will be checked to determine if the socket
00081     // handler should be detached.  it must only be accessed on the socket
00082     // thread.
00083     //
00084     nsresult mCondition;
00085 
00086     //
00087     // these flags can only be modified on the socket transport thread.
00088     // the socket transport service will check these flags before calling
00089     // PR_Poll.
00090     //
00091     PRUint16 mPollFlags;
00092 
00093     //
00094     // this value specifies the maximum amount of time in seconds that may be
00095     // spent waiting for activity on this socket.  if this timeout is reached,
00096     // then OnSocketReady will be called with outFlags = -1.
00097     //
00098     // the default value for this member is PR_UINT16_MAX, which disables the
00099     // timeout error checking.  (i.e., a timeout value of PR_UINT16_MAX is
00100     // never reached.)
00101     //
00102     PRUint16 mPollTimeout;
00103 
00104     //
00105     // called to service a socket
00106     // 
00107     // params:
00108     //   socketRef - socket identifier
00109     //   fd        - socket file descriptor
00110     //   outFlags  - value of PR_PollDesc::out_flags after PR_Poll returns
00111     //               or -1 if a timeout occured
00112     //
00113     virtual void OnSocketReady(PRFileDesc *fd, PRInt16 outFlags) = 0;
00114 
00115     //
00116     // called when a socket is no longer under the control of the socket
00117     // transport service.  the socket handler may close the socket at this
00118     // point.  after this call returns, the handler will no longer be owned
00119     // by the socket transport service.
00120     //
00121     virtual void OnSocketDetached(PRFileDesc *fd) = 0;
00122 };
00123 
00124 //-----------------------------------------------------------------------------
00125 
00126 class nsSocketTransportService : public nsPISocketTransportService
00127                                , public nsIEventTarget
00128                                , public nsIRunnable
00129 {
00130 public:
00131     NS_DECL_ISUPPORTS
00132     NS_DECL_NSPISOCKETTRANSPORTSERVICE
00133     NS_DECL_NSISOCKETTRANSPORTSERVICE
00134     NS_DECL_NSIEVENTTARGET
00135     NS_DECL_NSIRUNNABLE
00136 
00137     nsSocketTransportService();
00138 
00139     //
00140     // the number of sockets that can be attached at any given time is
00141     // limited.  this is done because some operating systems (e.g., Win9x)
00142     // limit the number of sockets that can be created by an application.
00143     // AttachSocket will fail if the limit is exceeded.  consumers should
00144     // call CanAttachSocket and check the result before creating a socket.
00145     //
00146     PRBool CanAttachSocket() { return mActiveCount + mIdleCount < NS_SOCKET_MAX_COUNT; }
00147 
00148     //
00149     // if the number of sockets is at the limit, then consumers can be notified
00150     // when the number of sockets becomes less than the limit.  the notification
00151     // is asynchronous, delivered via the given PLEvent instance on the socket
00152     // transport thread.
00153     //
00154     nsresult NotifyWhenCanAttachSocket(PLEvent *);
00155 
00156     //
00157     // add a new socket to the list of controlled sockets.  returns a socket
00158     // reference for the newly attached socket that can be used with other
00159     // methods to control the socket.
00160     //
00161     // NOTE: this function may only be called from an event dispatch on the
00162     //       socket thread.
00163     //
00164     nsresult AttachSocket(PRFileDesc *fd, nsASocketHandler *);
00165 
00166 protected:
00167 
00168     virtual ~nsSocketTransportService();
00169 
00170 private:
00171 
00172     //-------------------------------------------------------------------------
00173     // misc (any thread)
00174     //-------------------------------------------------------------------------
00175 
00176     PRBool      mInitialized;
00177     nsIThread  *mThread;
00178     PRFileDesc *mThreadEvent;
00179                             // protected by mEventQLock.  mThreadEvent may
00180                             // change if the old pollable event is broken.
00181                             // only the socket thread may change mThreadEvent;
00182                             // it needs to lock mEventQLock only when it
00183                             // changes mThreadEvent.  other threads don't
00184                             // change mThreadEvent; they need to lock
00185                             // mEventQLock whenever they access mThreadEvent.
00186 
00187     // pref to control autodial code
00188     PRBool      mAutodialEnabled;
00189 
00190     //-------------------------------------------------------------------------
00191     // misc (socket thread only)
00192     //-------------------------------------------------------------------------
00193     // indicates whether we are currently in the process of shutting down
00194     PRBool      mShuttingDown;
00195 
00196     //-------------------------------------------------------------------------
00197     // event queue (any thread)
00198     //-------------------------------------------------------------------------
00199 
00200     PRCList  mEventQ; // list of PLEvent objects
00201     PRLock  *mEventQLock;
00202 
00203     //-------------------------------------------------------------------------
00204     // socket lists (socket thread only)
00205     //
00206     // only "active" sockets are on the poll list.  the active list is kept
00207     // in sync with the poll list such that:
00208     //
00209     //   mActiveList[k].mFD == mPollList[k+1].fd
00210     //
00211     // where k=0,1,2,...
00212     //-------------------------------------------------------------------------
00213 
00214     struct SocketContext
00215     {
00216         PRFileDesc       *mFD;
00217         nsASocketHandler *mHandler;
00218         PRUint16          mElapsedTime;  // time elapsed w/o activity
00219     };
00220 
00221     SocketContext mActiveList [ NS_SOCKET_MAX_COUNT ];
00222     SocketContext mIdleList   [ NS_SOCKET_MAX_COUNT ];
00223 
00224     PRUint32 mActiveCount;
00225     PRUint32 mIdleCount;
00226 
00227     nsresult DetachSocket(SocketContext *);
00228     nsresult AddToIdleList(SocketContext *);
00229     nsresult AddToPollList(SocketContext *);
00230     void RemoveFromIdleList(SocketContext *);
00231     void RemoveFromPollList(SocketContext *);
00232     void MoveToIdleList(SocketContext *sock);
00233     void MoveToPollList(SocketContext *sock);
00234     
00235     // returns PR_FALSE to stop processing the main loop
00236     PRBool ServiceEventQ();
00237 
00238     //-------------------------------------------------------------------------
00239     // poll list (socket thread only)
00240     //
00241     // first element of the poll list is mThreadEvent (or null if the pollable
00242     // event cannot be created).
00243     //-------------------------------------------------------------------------
00244 
00245     PRPollDesc mPollList[ NS_SOCKET_MAX_COUNT + 1 ];
00246 
00247     PRIntervalTime PollTimeout();            // computes ideal poll timeout
00248     PRInt32        Poll(PRUint32 *interval); // calls PR_Poll.  the out param
00249                                              // interval indicates the poll
00250                                              // duration in seconds.
00251 
00252     //-------------------------------------------------------------------------
00253     // pending socket queue - see NotifyWhenCanAttachSocket
00254     //-------------------------------------------------------------------------
00255 
00256     PRCList mPendingSocketQ; // list of PLEvent objects
00257 };
00258 
00259 extern nsSocketTransportService *gSocketTransportService;
00260 extern PRThread                 *gSocketThread;
00261 
00262 #endif // !nsSocketTransportService_h__