comparison dreactor/protocol/RawTcp.d @ 4:f8b01c9f7114

adding basic protocols
author rick@minifunk
date Tue, 08 Jul 2008 11:22:39 -0400
parents
children f875a1f278b8
comparison
equal deleted inserted replaced
3:e3dbc9208822 4:f8b01c9f7114
1 module dreactor.protocol.RawTcp;
2
3 import tango.io.Conduit;
4 import tango.io.selector.model.ISelector;
5 import tango.net.Socket;
6 import tango.util.collection.CircularSeq;
7 import tango.util.log.Log;
8 import tango.util.log.Config;
9
10 import dreactor.transport.AsyncSocketConduit;
11 import dreactor.core.SelectLoop;
12 import dreactor.core.ConnectionHandler;
13
14 /******************************************************************************
15
16 Basic TCP server or client routines for sending raw data.
17
18 ******************************************************************************/
19 class RawTCPListener
20 {
21 public
22 Logger log;
23 this(ConnectionHandler mgr, SelectLoop sel, IPv4Address addr)
24 {
25 manager = mgr;
26 mgr.events(Event.Read);
27 mgr.setOutgoingHandler(&Handlers.onSend);
28 mgr.setIncomingHandler(&Handlers.onReceive);
29 mgr.setConnectHandler(&accept);
30 mgr.listen(addr);
31
32 sel.addConnection(mgr);
33 select = sel;
34 log = Log.lookup("dreactor.protocol.RawTcpServer");
35 log.info("log initialized");
36 children = new CircularSeq!(ConnectionHandler);
37 }
38
39 int accept(Conduit cond, RegisterD reg)
40 {
41 AsyncSocketConduit newcond = new AsyncSocketConduit;
42 (cast(AsyncSocketConduit)cond).socket().accept(newcond.socket);
43 ConnectionHandler h = ConnectionHandler.New(newcond, manager);
44 h.events(Event.Read);
45 select.addConnection(h);
46 children.append(h);
47 log.info("accepted new connection");
48 return 0;
49 }
50
51 int broadcast(char[] outbuf)
52 {
53 foreach(ConnectionHandler h; children)
54 {
55 if (h.appendOutBuffer(outbuf))
56 {
57 h.addEvent(Event.Write);
58 select.addConnection(h);
59 }
60 }
61 return 0;
62 }
63
64 void close()
65 {
66
67 }
68
69 private
70 ConnectionHandler manager;
71 SelectLoop select;
72 CircularSeq!(ConnectionHandler) children;
73 }
74
75 class RawTCPClient
76 {
77 public
78 Logger log;
79 this(ConnectionHandler mgr, SelectLoop sel, Event evts = Event.Read)
80 {
81 manager = mgr;
82 manager.events(evts);
83 connected = false;
84 mgr.setOutgoingHandler(&Handlers.onSend);
85 mgr.setIncomingHandler(&Handlers.onReceive);
86 select = sel;
87 log = Log.lookup("dreactor.protocol.RawTcpClient");
88 }
89
90 int connect(IPv4Address addr)
91 {
92 (cast(AsyncSocketConduit) manager.transport()).connect(addr);
93 select.addConnection(manager);
94 connected = true;
95 log.info("connected to {}", addr);
96 return 0;
97 }
98
99 /**************************************************************************
100
101 send
102 User-called function to send data to the counterpart at the other
103 end of the connection. This sets up the connection manager to send
104 data as the socket becomes free.
105
106 **************************************************************************/
107 int send(char[] outbuf, IPv4Address addr = null)
108 {
109 log.info("sending buffer: {}", outbuf);
110 if (!connected)
111 {
112 log.info("not connected, connecting");
113 if (addr !is null)
114 {
115 if (0 > connect(addr))
116 {
117 log.error("unable to connect");
118 return -1;
119 }
120 }
121 }
122 if (manager.appendOutBuffer(outbuf))
123 {
124 manager.addEvent(Event.Write);
125 if (!select.addConnection(manager))
126 {
127 log.error("unable to register mgr");
128 }
129 }
130 return 0;
131 }
132
133 private
134 ConnectionHandler manager;
135 SelectLoop select;
136 bool connected;
137 }
138
139
140 /******************************************************************************
141
142 Default Event handlers common to both listener/clients
143
144 ******************************************************************************/
145 class Handlers
146 {
147 /**************************************************************************
148
149 onSend
150 OutgoingHandlerD
151 To be registered as the response to socket writable event.
152 Sends data, returns amount sent. Unregisters Handler for sending
153 if there is no more data left to send.
154
155 ***************************************************************************/
156 public static int onSend(ConnectionHandler h)
157 {
158 Logger log = Log.lookup("Handlers.onSend");
159
160 log.info("top of onSend");
161 char[] outbuf = h.nextBuffer();
162 if (outbuf !is null)
163 {
164 int sent = h.transport.write(outbuf);
165 if (sent > 0)
166 {
167 if (! h.addOffset(sent))
168 {
169 h.remEvent(Event.Write);
170 return REREGISTER;
171 }
172 }
173 else if (sent == AsyncSocketConduit.Eof)
174 {
175 log.error("Select said socket was writable, but sent 0 bytes");
176 }
177 else
178 {
179 log.error("Socket send return ERR");
180 }
181 return REMAIN;
182 }
183 else
184 {
185 h.remEvent(Event.Write);
186 return REREGISTER;
187 }
188 }
189 /**************************************************************************
190
191 receive
192 IncomingHandlerD
193 Default incoming data handler. Should be replaced with something useful.
194
195 **************************************************************************/
196 public static int onReceive(ConnectionHandler h)
197 {
198 Logger log = Log.lookup("Handlers.onReceive");
199
200 char inbuf[8192];
201 int amt;
202 if((amt = h.transport.read(inbuf)) > 0)
203 log.info("Received Buffer: {}", inbuf[0 .. amt]);
204 else
205 log.error("Received no data, err = {}", amt);
206
207 return REMAIN;
208 }
209 }