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