Mercurial > projects > dreactor
view dreactor/protocol/RawTcp.d @ 6:287ba7de97c4
more housekeeping
author | rick@minifunk |
---|---|
date | Tue, 08 Jul 2008 12:23:26 -0400 |
parents | f875a1f278b8 |
children | 60cf25102fb2 |
line wrap: on
line source
module dreactor.protocol.RawTcp; import tango.io.Conduit; import tango.io.selector.model.ISelector; import tango.net.Socket; import tango.util.collection.CircularSeq; import tango.util.log.Log; import tango.util.log.Config; import dreactor.transport.AsyncSocketConduit; import dreactor.core.Vat; import dreactor.core.Dispatcher; /****************************************************************************** Basic TCP server or client routines for sending raw data. ******************************************************************************/ class RawTCPListener { public Logger log; this(Dispatcher mgr, Vat sel, IPv4Address addr) { manager = mgr; mgr.events(Event.Read); mgr.setOutgoingHandler(&Handlers.onSend); mgr.setIncomingHandler(&Handlers.onReceive); mgr.setConnectHandler(&accept); mgr.listen(addr); sel.addConnection(mgr); vat = sel; log = Log.lookup("dreactor.protocol.RawTcpServer"); log.info("log initialized"); children = new CircularSeq!(Dispatcher); } int accept(Conduit cond, RegisterD reg) { AsyncSocketConduit newcond = new AsyncSocketConduit; (cast(AsyncSocketConduit)cond).socket().accept(newcond.socket); Dispatcher h = Dispatcher.New(newcond, manager); h.events(Event.Read); vat.addConnection(h); children.append(h); log.info("accepted new connection"); return 0; } int broadcast(char[] outbuf) { foreach(Dispatcher h; children) { if (h.appendOutBuffer(outbuf)) { h.addEvent(Event.Write); vat.addConnection(h); } } return 0; } void close() { } private Dispatcher manager; Vat vat; CircularSeq!(Dispatcher) children; } class RawTCPClient { public Logger log; this(Dispatcher mgr, Vat sel, Event evts = Event.Read) { manager = mgr; manager.events(evts); connected = false; mgr.setOutgoingHandler(&Handlers.onSend); mgr.setIncomingHandler(&Handlers.onReceive); vat = sel; log = Log.lookup("dreactor.protocol.RawTcpClient"); } int connect(IPv4Address addr) { (cast(AsyncSocketConduit) manager.transport()).connect(addr); vat.addConnection(manager); connected = true; log.info("connected to {}", addr); return 0; } /************************************************************************** send User-called function to send data to the counterpart at the other end of the connection. This sets up the connection manager to send data as the socket becomes free. **************************************************************************/ int send(char[] outbuf, IPv4Address addr = null) { if (!connected) { log.info("send: not connected, connecting"); if (addr !is null) { if (0 > connect(addr)) { log.error("send: unable to connect"); return -1; } } } if (manager.appendOutBuffer(outbuf)) { manager.addEvent(Event.Write); if (!vat.addConnection(manager)) { log.error("unable to register mgr"); } } return 0; } private Dispatcher manager; Vat vat; bool connected; } /****************************************************************************** Default Event handlers common to both listener/clients ******************************************************************************/ class Handlers { /************************************************************************** onSend OutgoingHandlerD To be registered as the response to socket writable event. Sends data, returns amount sent. Unregisters Handler for sending if there is no more data left to send. ***************************************************************************/ public static int onSend(Dispatcher h) { Logger log = Log.lookup("Handlers.onSend"); log.info("top of onSend"); char[] outbuf = h.nextBuffer(); if (outbuf !is null) { int sent = h.transport.write(outbuf); if (sent > 0) { if (! h.addOffset(sent)) { h.remEvent(Event.Write); return REREGISTER; } } else if (sent == AsyncSocketConduit.Eof) { log.error("Select said socket was writable, but sent 0 bytes"); } else { log.error("Socket send return ERR"); } return REMAIN; } else { h.remEvent(Event.Write); return REREGISTER; } } /************************************************************************** receive IncomingHandlerD Default incoming data handler. Should be replaced with something useful. **************************************************************************/ public static int onReceive(Dispatcher h) { Logger log = Log.lookup("Handlers.onReceive"); char inbuf[8192]; int amt; if((amt = h.transport.read(inbuf)) > 0) log.info("Received {} byte Buffer: {}", amt, inbuf[0 .. amt]); else log.error("Received no data, err = {}", amt); return REMAIN; } }