Mercurial > projects > dreactor
view dreactor/core/ConnectionHandler.d @ 2:d3374d553986
updates
author | rick@minifunk |
---|---|
date | Thu, 12 Jun 2008 23:12:17 -0400 |
parents | 7a315154bf5e |
children | e3dbc9208822 |
line wrap: on
line source
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 listener = false) { transport = trans; ibuf_len = 0; obuf_len = 0; i_offset = 0; o_offset = 0; } /********************************************************************** 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 .. $]; } /************************************************************************** listen Enable listening on the socket attached to this connectionhandler **************************************************************************/ int listen(IPv4Address addr) { transport.bind().listen(); state = listening; setConnectionHandler() } /************************************************************************** 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; } }