view dreactor/transport/AsyncSocketConduit.d @ 13:8c9b1276f623 default tip

bug fixes
author rick@minifunk
date Sat, 20 Sep 2008 18:33:11 -0400
parents d6a3cfe7c3de
children
line wrap: on
line source

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

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

license:        BSD style: $(LICENSE)

version:        Mar 2004 : Initial release
version:        Jan 2005 : RedShodan patch for timeout query
version:        Dec 2006 : Outback release

author:         Kris, modified by Rick Richardson (May 2008)

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

module dreactor.transport.AsyncSocketConduit;

private import  tango.time.Time;

public  import  tango.io.device.Conduit;

private import  tango.net.Socket;

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

  A wrapper around the bare Socket to implement the IConduit abstraction
  and add socket-specific functionality specifically for multiplexing via 
  poll and the ilk.

  AsyncSocketConduit data-transfer is typically performed in conjunction with
  an IBuffer, but can happily be handled directly using void array where
  preferred

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

class AsyncSocketConduit : Conduit
{
    package Socket socket_;

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

      Create a streaming Internet Socket

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

    this ()
    {
        this (SocketType.STREAM, ProtocolType.TCP);
    }

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

        Create an Internet Socket. Used by subclasses and by
        ServerSocket; the latter via method allocate() below

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

    protected this (SocketType type, ProtocolType protocol, bool create=true)
    {
        socket_ = new Socket (AddressFamily.INET, type, protocol, create);
        socket_.blocking(false);
    }

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

     Return the name of this device

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

    override char[] toString()
    {
       return socket.toString;
    }

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

     Return the socket wrapper

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

    Socket socket ()
    {
       return socket_;
    }

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

     Return a preferred size for buffering conduit I/O

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

    override uint bufferSize ()
    {
       return 1024 * 8;
    }

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

     Models a handle-oriented device.

    TODO: figure out how to avoid exposing this in the general
    case

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

    Handle fileHandle ()
    {
       return cast(Handle) socket_.fileHandle;
    }

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

     Is this socket still alive?

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

    override bool isAlive ()
    {
       return socket_.isAlive;
    }

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

     Connect to the provided endpoint

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

    AsyncSocketConduit connect (Address addr)
    {
       socket_.connect (addr);
       return this;
    }

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

     Bind the socket. This is typically used to configure a
     listening socket (such as a server or multicast socket).
     The address given should describe a local adapter, or
     specify the port alone (ADDR_ANY) to have the OS assign
     a local adapter address.

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

    AsyncSocketConduit bind (Address address)
    {
       socket_.bind (address);
       return this;
    }

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

        Enable the socket for listening

    **************************************************************************/
    AsyncSocketConduit listen(int backlog = 255)
    {
        socket_.listen(backlog);
        return this;
    }

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

     Inform other end of a connected socket that we're no longer
     available. In general, this should be invoked before close()
     is invoked

     The shutdown function shuts down the connection of the socket: 

     -   stops receiving data for this socket. If further data 
     arrives, it is rejected.

     -   stops trying to transmit data from this socket. Also
     discards any data waiting to be sent. Stop looking for 
     acknowledgement of data already sent; don't retransmit 
     if any data is lost.

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

    AsyncSocketConduit shutdown ()
    {
       socket_.shutdown (SocketShutdown.BOTH);
       return this;
    }

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

     Release this AsyncSocketConduit

     Note that one should always disconnect a AsyncSocketConduit 
     under normal conditions, and generally invoke shutdown 
     on all connected sockets beforehand

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

    override void detach ()
    {
       socket_.detach;
    }

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

     Read content from the socket. 

     Returns the number of bytes read from the socket, or
     IConduit.Eof where there's no more content available
     
     Return IConduit.Eof if there is an error with the socket.

    ***********************************************************************/
    override uint read (void[] dst)
    {
       // invoke the actual read op
       return socket_.receive(dst);
    }


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

     Callback routine to write the provided content to the
     socket. 
    ***********************************************************************/

    override uint write (void[] src)
    {
       return socket_.send (src);
    }
}