Mercurial > projects > dreactor
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; + } +} +