Mercurial > projects > dreactor
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 |