comparison dreactor/core/Dispatcher.d @ 6:287ba7de97c4

more housekeeping
author rick@minifunk
date Tue, 08 Jul 2008 12:23:26 -0400
parents dreactor/core/ConnectionHandler.d@f875a1f278b8
children 5412a1ff2e49
comparison
equal deleted inserted replaced
5:f875a1f278b8 6:287ba7de97c4
1 module dreactor.core.Dispatcher;
2
3 import tango.io.selector.model.ISelector;
4 import tango.util.collection.CircularSeq;
5 import tango.net.Socket;
6 public import tango.core.Exception;
7 import dreactor.transport.AsyncSocketConduit;
8
9 import tango.util.log.Log;
10 import tango.util.log.Config;
11
12 alias bool delegate(Dispatcher) RegisterD;
13
14 alias int delegate(Dispatcher) IncomingHandlerD;
15 alias int delegate(Dispatcher) OutgoingHandlerD;
16 alias int delegate(Dispatcher, RegisterD) ErrorHandlerD;
17 alias int delegate(Dispatcher) DisconnectHandlerD;
18 alias int delegate(Conduit, RegisterD) ConnectHandlerD;
19
20 alias int function(Dispatcher) IncomingHandlerF;
21 alias int function(Dispatcher) OutgoingHandlerF;
22 alias int function(Dispatcher, RegisterD) ErrorHandlerF;
23 alias int function(Dispatcher) DisconnectHandlerF;
24 alias int function(Conduit, RegisterD) ConnectHandlerF;
25
26
27 /******************************************************************************
28 Dispatcher object. To be used by the SelectLoop to manage callbacks
29 for events. It may also be used to buffer data inbetween requests.
30 These can be populated passed to a SelectLoop directly by the end user,
31 or may be managed by a chosen Protocol.
32 ******************************************************************************/
33 class Dispatcher
34 {
35 public
36 enum State { init, connected, listening, idle, closing };
37
38 /**************************************************************************
39
40 Standard Ctor, takes a transport_
41
42 **************************************************************************/
43 this (Conduit trans, bool listener = false)
44 {
45 transport_ = trans;
46 ibuf_len = 0;
47 i_offset = 0;
48 o_offset = 0;
49 out_buffers = new CircularSeq!(char[]);
50 log = Log.lookup("dreactor.core.Dispatcher");
51 }
52
53 /**********************************************************************
54
55 Setters for the handlers. These are set by the Protocols as well
56
57 **********************************************************************/
58
59 void setIncomingHandler(IncomingHandlerD hand)
60 {
61 inD = hand;
62 inF = null;
63 }
64
65 void setIncomingHandler(IncomingHandlerF hand)
66 {
67 inF = hand;
68 inD = null;
69 }
70
71 void setOutgoingHandler(OutgoingHandlerD hand)
72 {
73 outD = hand;
74 outF = null;
75 }
76
77 void setOutgoingHandler(OutgoingHandlerF hand)
78 {
79 outF = hand;
80 outD = null;
81 }
82
83 void setErrorHandler(ErrorHandlerD hand)
84 {
85 errD = hand;
86 errF = null;
87 }
88
89 void setErrorHandler(ErrorHandlerF hand)
90 {
91 errF = hand;
92 errD = null;
93 }
94
95 void setDisconnectHandler(DisconnectHandlerD hand)
96 {
97 disD = hand;
98 disF = null;
99 }
100
101 void setDisconnectHandler(DisconnectHandlerF hand)
102 {
103 disF = hand;
104 disD = null;
105 }
106
107 void setConnectHandler(ConnectHandlerD hand)
108 {
109 conD = hand;
110 conF = null;
111 }
112
113 void setConnectHandler(ConnectHandlerF hand)
114 {
115 conF = hand;
116 conD = null;
117 }
118
119 /**********************************************************************
120
121 Handlers to be called by the SelectLoop when events occur
122
123 **********************************************************************/
124 int handleIncoming()
125 {
126 if (inD !is null)
127 return inD(this);
128 else if (inF !is null)
129 return inF(this);
130 else
131 throw new Exception("no Incoming handler set");
132 }
133
134 int handleOutgoing()
135 {
136 if (outD !is null)
137 return outD(this);
138 else if (outF !is null)
139 return outF(this);
140 else
141 throw new Exception("no Outgoing handler set");
142 }
143
144 int handleError(RegisterD reg)
145 {
146 if (errD !is null)
147 return errD(this, reg);
148 else if (errF !is null)
149 return errF(this, reg);
150 }
151
152 int handleDisconnect()
153 {
154 if (disD !is null)
155 return disD(this);
156 else if (disF !is null)
157 return disF(this);
158 }
159
160 int handleConnection(Conduit cond, RegisterD reg )
161 {
162 if (conD !is null)
163 {
164 return conD(cond, reg);
165 }
166 else if (conF !is null)
167 {
168 return conF(cond, reg);
169 }
170 }
171
172 /**************************************************************************
173
174 Sending / Receiving helpers
175
176 **************************************************************************/
177
178 /**************************************************************************
179
180 appendOutBuffer
181
182 Adds an outgoing buffer to the list. This returns true if the list
183 was empty, indicating that the handler should be registered with the
184 SelectLoop. If it returns false, it was probably already registered.
185
186 **************************************************************************/
187 synchronized bool appendOutBuffer(char[] outbuf)
188 {
189 out_buffers.append(outbuf);
190 out_buffers_len++;
191 if (out_buffers_len == 1)
192 return true;
193 else
194 return false;
195 }
196
197 /**************************************************************************
198
199 addOffset
200 Use this function to update the offset position after a successful data
201 send. This not only manages the current offset, but will update the
202 out buffer chain if necessary.
203
204 Returns: false if there is nothing left to send, true if there is.
205
206 **************************************************************************/
207 synchronized bool addOffset(int off)
208 in
209 {
210 assert(out_buffers_len > 0);
211 }
212 body
213 {
214 char[] hd = out_buffers.head();
215 if ((off + o_offset) >= hd.length)
216 {
217 out_buffers.removeHead();
218 o_offset = 0;
219 out_buffers_len--;
220 return (out_buffers_len > 0);
221 }
222 else
223 o_offset += off;
224 return true;
225 }
226
227 /**************************************************************************
228
229 char[] nextBuffer
230
231 Returns a slice of the current outbound buffer, returns a char[] pointing
232 to null if there is no current outbound buffer
233
234 **************************************************************************/
235 synchronized char[] nextBuffer()
236 {
237 if (out_buffers_len < 1)
238 {
239 return null;
240 }
241
242 return out_buffers.head()[o_offset .. $];
243 }
244
245 /**************************************************************************
246
247 listen
248 Enable listening on the socket attached to this connectionhandler
249
250 **************************************************************************/
251 int listen(IPv4Address addr)
252 {
253 (cast(AsyncSocketConduit)transport_).bind(addr).listen();
254 state_ = State.listening;
255 return 0;
256 }
257
258 Conduit transport()
259 {
260 return transport_;
261 }
262 /**************************************************************************
263
264 Configuration functions
265
266 **************************************************************************/
267 Event events()
268 {
269 return events_;
270 }
271 void events(Event e)
272 {
273 events_ = e;
274 }
275 void addEvent(Event e)
276 {
277 events_ |= e;
278 }
279 void remEvent(Event e)
280 {
281 events_ &= ~e;
282 }
283
284 State getState() {return state_;}
285
286 /*
287 connection handlers are left out of this because
288 this method is used by the listener socket to pass
289 on its handlers to the accepted socket. An accepted
290 socket will generally do different things onConnection
291 */
292 void setHandlers(Dispatcher other)
293 {
294 inD = other.inD;
295 outD = other.outD;
296 errD = other.errD;
297 disD = other.disD;
298 inF = other.inF;
299 outF = other.outF;
300 errF = other.errF;
301 disF = other.disF;
302 }
303
304 /**************************************************************************
305
306 Freelist allocators and deallocators
307
308 **************************************************************************/
309 static synchronized Dispatcher New(Conduit tran, Dispatcher other = null)
310 {
311 Dispatcher hand;
312 if (freelist)
313 {
314 hand = freelist;
315 freelist = hand.next;
316 hand.transport_ = tran;
317 }
318 else
319 hand = new Dispatcher(tran);
320
321 if (!(other is null))
322 {
323 hand.setHandlers(other);
324 }
325 return hand;
326 }
327
328 static synchronized void Delete(Dispatcher hand)
329 {
330 hand.next = freelist;
331 freelist = hand.initialize();
332 }
333
334 private
335
336 char[] in_buffer;
337 CircularSeq!(char[]) out_buffers;
338 int out_buffers_len;
339 int ibuf_len;
340 int i_offset;
341 int o_offset;
342 Logger log;
343
344 package Conduit transport_;
345 State state_;
346 Event events_;
347 IncomingHandlerD inD;
348 OutgoingHandlerD outD;
349 ErrorHandlerD errD;
350 DisconnectHandlerD disD;
351 ConnectHandlerD conD;
352
353 IncomingHandlerF inF;
354 OutgoingHandlerF outF;
355 ErrorHandlerF errF;
356 DisconnectHandlerF disF;
357 ConnectHandlerF conF;
358
359 static Dispatcher freelist;
360 Dispatcher next;
361
362 /**************************************************************************
363 Copy ctor, creates a new Dispatcher using the settings
364 of an existing handler.
365 **************************************************************************/
366 Dispatcher initialize()
367 {
368 transport_ = null;
369 state_ = State.init;
370 ibuf_len = 0;
371 i_offset = 0;
372 o_offset = 0;
373 out_buffers.clear();
374 inD = null;
375 outD = null;
376 errD = null;
377 disD = null;
378 conD = null;
379 inF = null;
380 outF = null;
381 errF = null;
382 disF = null;
383 conF = null;
384 return this;
385 }
386 }
387