view tango/tango/net/cluster/tina/util/AbstractServer.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
line wrap: on
line source

/*******************************************************************************

        copyright:      Copyright (c) 2004 Kris Bell. All rights reserved

        license:        BSD style: $(LICENSE)

        version:        Initial release: April 2004

        author:         Kris

*******************************************************************************/

module tango.net.cluster.tina.util.AbstractServer;

private   import  tango.net.Socket;

protected import  tango.util.log.Log;

protected import  tango.net.ServerSocket,
                  tango.net.SocketConduit;

protected import  tango.io.model.IConduit;

protected import  tango.text.convert.Sprint;

protected import  tango.net.cluster.tina.util.model.IServer;

/******************************************************************************

        Exposes the foundation of a multi-threaded Socket server. This is
        subclassed by  mango.net.http.server.HttpServer, which itself would
        likely be subclassed by a SecureHttpServer.

******************************************************************************/

class AbstractServer : IServer
{
        private InternetAddress bind;
        private ServerSocket    server;
        private Logger          logger;
        private Sprint!(char)   sprint;
        private uint            threads;
        private uint            backlog;

        /**********************************************************************

                Setup this server with the requisite attributes. The number
                of threads specified dictate exactly that. You might have
                anything between 1 thread and several hundred, dependent
                upon the underlying O/S and hardware.

                Parameter 'backlog' specifies the max number of"simultaneous"
                connection requests to be handled by an underlying socket
                implementation.

        **********************************************************************/

        this (InternetAddress bind, int threads, int backlog, Logger logger)
        in {
           assert (bind);
           assert (logger);
           assert (backlog >= 0);
           assert (threads > 0 && threads < 256);
           }
        body
        {
                this.bind = bind;
                this.logger = logger;
                this.threads = threads;
                this.backlog = backlog;
                this.sprint = new Sprint!(char);
        }

        /**********************************************************************

                Concrete server must expose a name

        **********************************************************************/

        protected abstract char[] toString();

        /**********************************************************************

                Concrete server must expose a ServerSocket factory

        **********************************************************************/

        protected abstract ServerSocket createSocket (InternetAddress bind, int backlog, bool reuse=false);

        /**********************************************************************

                Concrete server must expose a thread factory

        **********************************************************************/

        protected abstract void createThread (ServerSocket socket);

        /**********************************************************************

                Concrete server must expose a service handler

        **********************************************************************/

        abstract void service (IConduit conduit);

        /**********************************************************************

                Provide support for figuring out the remote address

        **********************************************************************/

        IPv4Address remoteAddress (IConduit conduit)
        {
                auto tmp = cast(SocketConduit) conduit;
                if (tmp)
                    return cast(IPv4Address) tmp.socket.remoteAddress;
                return null;
        }

        /**********************************************************************

                Provide support for figuring out the remote address

        **********************************************************************/

        IPv4Address localAddress ()
        {
                return cast(IPv4Address) server.socket.localAddress;
        }

        /**********************************************************************

                Provide support for figuring out the remote address

        **********************************************************************/

        char[] getRemoteAddress (IConduit conduit)
        {
                auto addr = remoteAddress (conduit);

                if (addr)
                    return addr.toAddrString;
                return "127.0.0.1";
        }

        /**********************************************************************

                Provide support for figuring out the remote host. Not
                currently implemented.

        **********************************************************************/

        char[] getRemoteHost (IConduit conduit)
        {
                return null;
        }

        /**********************************************************************

                Return the local port we're attached to

        **********************************************************************/

        int getPort ()
        {
                return localAddress.port;
        }

        /**********************************************************************

                Return the local address we're attached to

        **********************************************************************/

        char[] getHost ()
        {
                return localAddress.toAddrString;
        }

        /**********************************************************************

                Return the logger associated with this server

        **********************************************************************/

        Logger getLogger ()
        {
                return logger;
        }

        /**********************************************************************

                Start this server

        **********************************************************************/

        void start (bool reuse = false)
        {
                // have the subclass create a ServerSocket for us
                server = createSocket (bind, backlog, reuse);

                // instantiate and start all threads
                for (auto i=threads; i-- > 0;)
                     createThread (server);

                // indicate what's going on
                logger.info (sprint ("Server {} started on {} with {} accept threads and {} backlogs",
                                      this, localAddress, threads, backlog));
        }
}