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 **************************************************************************/
|
|
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
|