comparison dreactor/core/ConnectionHandler.d @ 0:7a315154bf5e

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