diff dreactor/core/ConnectionHandler.d @ 0:7a315154bf5e

Initial commit
author rick@minifunk
date Sun, 08 Jun 2008 01:45:38 -0400
parents
children d3374d553986
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dreactor/core/ConnectionHandler.d	Sun Jun 08 01:45:38 2008 -0400
@@ -0,0 +1,362 @@
+module dreactor.core.ConnectionHandler;
+
+import tango.io.selector.model.ISelector;
+import tango.net.Socket.Address;
+import tango.util.collection.CircularSeq;
+
+import dreactor.transport.AsyncSocketConduit;
+
+alias bool delegate(ConnectionHandler) RegisterD;
+
+alias bool delegate(ConnectionHandler, RegisterD)   IncomingHandlerD;
+alias bool delegate(ConnectionHandler, RegisterD)   OutgoingHandlerD;
+alias int delegate(ConnectionHandler, RegisterD)    ErrorHandlerD;
+alias bool delegate(ConnectionHandler, RegisterD)   DisconnectHandlerD;
+alias int delegate(Conduit, RegisterD)              ConnectHandlerD;
+
+alias bool function(ConnectionHandler, RegisterD)   IncomingHandlerF;
+alias bool function(ConnectionHandler, RegisterD)   OutgoingHandlerF;
+alias int function(ConnectionHandler, RegisterD)    ErrorHandlerF;
+alias bool function(ConnectionHandler, RegisterD)   DisconnectHandlerF;
+alias int function(Conduit, RegisterD)              ConnectHandlerF;
+
+
+/******************************************************************************
+    ConnectionHandler object. To be used by the SelectLoop to manage callbacks 
+    for events. It may also be used to buffer data inbetween requests.
+    These can be populated passed to a SelectLoop directly by the end user, 
+    or may be managed by a chosen Protocol. 
+******************************************************************************/
+class ConnectionHandler()
+{
+ public 
+    enum { init, connected, listening, idle,  closing };
+  
+    /**************************************************************************
+
+        Standard Ctor, takes a transport
+
+    **************************************************************************/ 
+    this (Conduit trans, bool islistener = false)
+    {
+        state = State.init;
+        transport = trans;
+        ibuf_len = 0;
+        obuf_len = 0;
+        i_offset = 0;
+        o_offset = 0;
+        isListener = islistener;
+    }
+    
+      
+    /**********************************************************************
+    
+        Setters for the handlers. These are set by the Protocols as well 
+    
+    **********************************************************************/
+    
+    void setIncomingHandler(IncomingHandlerD hand)
+    {
+        inD = hand;
+        inF = null;
+    }
+
+    void setIncomingHandler(IncomingHandlerF hand)
+    {
+        inF = hand;
+        inD = null;
+    }
+
+    void setOutgoingHandler(OutgoingHandlerD hand)
+    {
+        outD = hand;
+        outF = null;
+    }
+
+    void setOutgoingHandler(OutgoingHandlerF hand)
+    {
+        outF = hand;
+        outD = null;
+    }
+
+    void setErrorHandler(ErrorHandlerD hand)
+    {
+        errD = hand;
+        errF = null;
+    }
+
+    void setErrorHandler(ErrorHandlerF hand)
+    {
+        errF = hand;
+        errD = null;
+    }
+
+    void setDisconnectHandler(DisconnectHandlerD hand)
+    {
+        disD = hand;
+        disF = null;
+    }
+
+    void setDisconnectHandler(DisconnectHandlerF hand)
+    {
+        disF = hand;
+        disD = null;
+    }
+
+    void setConnectHandler(ConnectHandlerD hand)
+    {
+        conD = hand;
+        conF = null;
+    }
+
+    void setConnectHandler(ConnectHandlerF hand)
+    {
+        conF = hand;
+        conD = null;
+    }
+
+    /**********************************************************************
+        
+        Handlers to be called by the SelectLoop when events occur
+    
+    **********************************************************************/
+    void handleIncoming(Conduit cond)
+    {
+        if (!inD is null)
+            return inD(cond);
+        else if (!inF is null)
+            return inF(cond);
+    }
+
+    void handleOutgoing(Conduit cond)
+    {
+        if (!outD is null)
+            return outD(cond);
+        else if (!outF is null)
+            return outF(cond);
+    }
+
+    int handleError(Conduit cond)
+    {
+        if (!errD is null)
+            return errD(cond);
+        else if (!errF is null)
+            return errF(cond);
+    }
+
+    int handleDisconnect(Conduit cond)
+    {
+        if (!disD is null)
+            return disD(addr);
+        else if (!disF is null)
+            return disF(addr);
+    }
+
+    int handleConnection(Address addr)
+    {
+        if (!conD is null)
+        {
+            return conD(addr);
+        }
+        else if (!conF is null)
+        {
+            return conF(addr);
+        }
+    }
+
+    /**************************************************************************
+
+        Sending / Receiving helpers
+
+    **************************************************************************/
+
+    /**************************************************************************
+    
+        appendOutBuffer
+
+        Adds an outgoing buffer to the list. This returns true if the list
+        was empty, indicating that the handler should be registered with the
+        SelectLoop. If it returns false, it was probably already registered.
+        
+    **************************************************************************/
+    synchronized void appendOutBuffer(char[] outbuf)
+    {
+        out_buffers.append(outbuf);
+        out_buffers_len++;
+        if (out_buffers_len == 1)
+            return true;
+        else
+            return false;
+    }
+   
+    /**************************************************************************
+
+        addOffset 
+        Use this function to update the offset position after a successful data
+        send. This not only manages the current offset, but will update the 
+        out buffer chain if necessary. 
+
+        Returns: false if there is nothing left to send, true if there is.
+
+    **************************************************************************/ 
+    synchronized bool addOffset(int off)
+    in
+    {
+        assert(out_buffers_len > 0);
+    }
+    body
+    {
+        char[] hd = out_buffers.head();
+        if ((off + o_offset) >= hd.length)
+        {
+            out_buffers.removeHead();
+            o_offset = 0;
+            out_buffers_len--;
+            return (out_buffers_len > 0);
+        }
+        else
+            o_offset += off;
+        return true;
+    }
+
+    /**************************************************************************
+
+        char[] nextBuffer
+
+        Returns a slice of the current outbound buffer, returns a char[] pointing
+        to null if there is no current outbound buffer
+
+    **************************************************************************/
+    synchronized char[] nextBuffer()
+    {
+        if (out_buffers_len < 1)
+        {
+            return null; 
+        }
+
+        return out_buffers.head()[o_offset .. $];
+    }
+    /**************************************************************************
+
+        Configuration functions
+
+    **************************************************************************/
+    Event events()
+    {
+        return events_;
+    }
+    void events(Event e)
+    {
+        events_ = e;
+    }
+    void addEvent(Event e)
+    {
+        events_ |= e;
+    }
+    void remEvent(Event e)
+    {
+        events_ &= ^e;
+    }
+
+    State getState() {return state;}
+    
+    /*
+       connection handlers are left out of this because 
+       this method is used by the listener socket to pass 
+       on its handlers to the accepted socket. An accepted
+       socket will generally do different things onConnection
+    */
+    void setHandlers(ConnectionHandler other)
+    {
+        inD  = other.inD; 
+        outD = other.outD;
+        errD = other.errD;
+        disD = other.disD;
+        inF  = other.inF;
+        outF = other.outF;
+        errF = other.errF;
+        disF = other.disF;
+    }
+
+    /**************************************************************************
+    
+        Freelist allocators and deallocators
+
+    **************************************************************************/
+    static synchronized ConnectionHandler New(Conduit tran, ConnectionHandler other = null)
+    {
+        ConnectionHandler hand;
+	    if (freelist)
+	    {   
+            hand = freelist;
+	        freelist = hand.next;
+            hand.transport = tran;
+	    }
+	    else
+	        hand = new ConnectionHandler(tran);
+
+        if (!other is null)
+        {
+            hand.setHandlers(other);
+        }
+	    return hand;
+    }
+
+    static synchronized void Delete(ConnectionHandler hand)
+    {   
+        hand.next = freelist;
+        freelist = hand.init();
+    } 
+
+private
+    
+    char[SZ] in_buffer;
+    CircularSeq!(char[]) out_buffers;
+    int ibuf_len;
+    int i_offset;
+    int o_offset;
+
+    package Conduit transport;
+    State state;
+    Event events; 
+    IncomingHandlerD    inD;
+    OutgoingHandlerD    outD;
+    ErrorHandlerD       errD;
+    DisconnectHandlerD  disD;
+    ConnectHandlerD     conD;
+
+    IncomingHandlerF    inF;
+    OutgoingHandlerF    outF;
+    ErrorHandlerF       errF;
+    DisconnectHandlerF  disF;
+    ConnectHandlerF     conF;
+    
+    static ConnectionHandler freelist;
+    ConnectionHandler next;
+
+    /**************************************************************************
+        Copy ctor, creates a new ConnectionHandler using the settings
+        of an existing handler. 
+    **************************************************************************/ 
+    void init()
+    {
+        transport = null;
+        state = State.init;
+        ibuf_len = 0;
+        obuf_len = 0;
+        i_offset = 0;
+        o_offset = 0;
+        out_buffer = null;
+        inD  = null;
+        outD = null;
+        errD = null;
+        disD = null;
+        conD = null;
+        inF  = null;
+        outF = null;
+        errF = null;
+        disF = null;
+        conF = null;
+    }
+}
+