Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

AbstractServer.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file AbstractServer.d
00004         
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032         
00033         @version        Initial version, April 2004      
00034         @author         Kris
00035 
00036 
00037 *******************************************************************************/
00038 
00039 module mango.utils.AbstractServer;
00040 
00041 private import  mango.log.Logger;
00042 
00043 private import  mango.io.Exception,
00044                 mango.io.ServerSocket,
00045                 mango.io.SocketConduit;
00046 
00047 private import  mango.format.Int;
00048 
00049 private import  mango.io.model.IConduit;
00050 
00051 private import  mango.utils.ServerThread;
00052 
00053 private import  mango.utils.model.IServer;
00054 
00055 
00056 /******************************************************************************
00057 
00058         Exposes the foundation of a multi-threaded Socket server. This is 
00059         subclassed by  mango.http.server.HttpServer, which itself would
00060         likely be subclassed by a SecureHttpServer. 
00061 
00062 ******************************************************************************/
00063 
00064 class AbstractServer : IServer
00065 {
00066         private InternetAddress bind;
00067         private int             threads;
00068         private int             backlog;
00069         private ServerSocket    socket;
00070         private ILogger         logger;
00071 
00072         /**********************************************************************
00073 
00074                 Setup this server with the requisite attributes. The number
00075                 of threads specified dictate exactly that. You might have 
00076                 anything between 1 thread and several hundred, dependent
00077                 upon the underlying O/S and hardware.
00078 
00079                 Parameter 'backlog' specifies the max number of"simultaneous" 
00080                 connection requests to be handled by an underlying socket 
00081                 implementation.
00082 
00083         **********************************************************************/
00084 
00085         this (InternetAddress bind, int threads, int backlog, ILogger logger = null)
00086         in {
00087            assert (bind);
00088            assert (backlog >= 0);
00089            assert (threads > 0 && threads < 1025);
00090            }
00091         body
00092         {
00093                 this.bind = bind;
00094                 this.threads = threads;
00095                 this.backlog = backlog;
00096 
00097                 // save our logger for later reference
00098                 if (logger is null)
00099                     logger = Logger.getLogger ("mango.utils.AbstractServer");
00100                 this.logger = logger;
00101 
00102         }
00103 
00104         /**********************************************************************
00105 
00106                 Concrete server must expose a name 
00107 
00108         **********************************************************************/
00109 
00110         protected abstract char[] toString();
00111 
00112         /**********************************************************************
00113 
00114                 Concrete server must expose a ServerSocket factory
00115 
00116         **********************************************************************/
00117 
00118         protected abstract ServerSocket createSocket (InternetAddress bind, int backlog);
00119 
00120         /**********************************************************************
00121 
00122                 Concrete server must expose a ServerThread factory
00123 
00124         **********************************************************************/
00125 
00126         protected abstract ServerThread createThread (ServerSocket socket);
00127 
00128         /**********************************************************************
00129 
00130                 Concrete server must expose a service handler
00131 
00132         **********************************************************************/
00133 
00134         abstract void service (ServerThread thread, IConduit conduit);
00135 
00136         /**********************************************************************
00137 
00138                 Provide support for figuring out the remote address
00139 
00140         **********************************************************************/
00141 
00142         char[] getRemoteAddress (IConduit conduit)
00143         {
00144                 SocketConduit socket = cast(SocketConduit) conduit;
00145                 InternetAddress addr = cast(InternetAddress) socket.remoteAddress();
00146 
00147                 if (addr)
00148                     return addr.toAddrString();
00149                 return "127.0.0.1";
00150         }
00151 
00152         /**********************************************************************
00153 
00154                 Provide support for figuring out the remote host. Not
00155                 currently implemented.
00156                 
00157         **********************************************************************/
00158 
00159         char[] getRemoteHost (IConduit conduit)
00160         {
00161                 return null;
00162         }
00163 
00164         /**********************************************************************
00165 
00166                 Return the local port we're attached to
00167 
00168         **********************************************************************/
00169 
00170         int getPort ()
00171         {
00172                 InternetAddress addr = cast(InternetAddress) socket.localAddress();
00173                 return addr.port();
00174         }
00175 
00176         /**********************************************************************
00177 
00178                 Return the local address we're attached to
00179 
00180         **********************************************************************/
00181 
00182         char[] getHost ()
00183         {
00184                 InternetAddress addr = cast(InternetAddress) socket.localAddress();
00185                 return addr.toAddrString();
00186         }
00187 
00188         /**********************************************************************
00189 
00190                 Return the logger associated with this server
00191 
00192         **********************************************************************/
00193 
00194         ILogger getLogger ()
00195         {
00196                 return logger;
00197         }
00198 
00199         /**********************************************************************
00200 
00201                 Start this server
00202 
00203         **********************************************************************/
00204 
00205         void start ()
00206         {
00207                 // have the subclass create a ServerSocket for us 
00208                 socket = createSocket (bind, backlog);
00209                 
00210                 // instantiate and start all threads
00211                 for (int i=threads; --i >= 0;)
00212                      createThread (socket).start();
00213 
00214                 char[] info = "Server "~toString()~" started on "~
00215                                socket.localAddress().toString()~
00216                                " with "~Int.format(threads)~" accept threads, "~
00217                                Int.format(backlog)~" backlogs";
00218 
00219                 // indicate what's going on 
00220                 logger.info (info);
00221         }
00222 }

Generated on Fri May 27 18:11:55 2005 for Mango by  doxygen 1.4.0