comparison dreactor/transport/AsyncSocketConduit.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 /*******************************************************************************
2
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved
4
5 license: BSD style: $(LICENSE)
6
7 version: Mar 2004 : Initial release
8 version: Jan 2005 : RedShodan patch for timeout query
9 version: Dec 2006 : Outback release
10
11 author: Kris, modified by Rick Richardson (May 2008)
12
13 *******************************************************************************/
14
15 module dreactor.transport.AsyncSocketConduit;
16
17 private import tango.time.Time;
18
19 public import tango.io.Conduit;
20
21 private import tango.net.Socket;
22
23 /*******************************************************************************
24
25 A wrapper around the bare Socket to implement the IConduit abstraction
26 and add socket-specific functionality specifically for multiplexing via
27 poll and the ilk.
28
29 AsyncSocketConduit data-transfer is typically performed in conjunction with
30 an IBuffer, but can happily be handled directly using void array where
31 preferred
32
33 *******************************************************************************/
34
35 class AsyncSocketConduit : Conduit
36 {
37 package Socket socket_;
38
39 /***********************************************************************
40
41 Create a streaming Internet Socket
42
43 ***********************************************************************/
44 /* overriding the enum from the IConduit interface */
45 enum : uint
46 {
47 Eof = uint.max, /// the End-of-Flow identifer
48 Err = uint.max -1 // some error ocurred, Should disconnect
49 }
50
51 this ()
52 {
53 this (SocketType.STREAM, ProtocolType.TCP);
54 }
55
56 /***********************************************************************
57
58 Create an Internet Socket. Used by subclasses and by
59 ServerSocket; the latter via method allocate() below
60
61 ***********************************************************************/
62
63 protected this (SocketType type, ProtocolType protocol, bool create=true)
64 {
65 socket_ = new Socket (AddressFamily.INET, type, protocol, create);
66 }
67
68 /***********************************************************************
69
70 Return the name of this device
71
72 ***********************************************************************/
73
74 override char[] toString()
75 {
76 return socket.toString;
77 }
78
79 /***********************************************************************
80
81 Return the socket wrapper
82
83 ***********************************************************************/
84
85 Socket socket ()
86 {
87 return socket_;
88 }
89
90 /***********************************************************************
91
92 Return a preferred size for buffering conduit I/O
93
94 ***********************************************************************/
95
96 override uint bufferSize ()
97 {
98 return 1024 * 8;
99 }
100
101 /***********************************************************************
102
103 Models a handle-oriented device.
104
105 TODO: figure out how to avoid exposing this in the general
106 case
107
108 ***********************************************************************/
109
110 override Handle fileHandle ()
111 {
112 return cast(Handle) socket_.fileHandle;
113 }
114
115 /***********************************************************************
116
117 Is this socket still alive?
118
119 ***********************************************************************/
120
121 override bool isAlive ()
122 {
123 return socket_.isAlive;
124 }
125
126 /***********************************************************************
127
128 Connect to the provided endpoint
129
130 ***********************************************************************/
131
132 AsyncSocketConduit connect (Address addr)
133 {
134 socket_.connect (addr);
135 return this;
136 }
137
138 /***********************************************************************
139
140 Bind the socket. This is typically used to configure a
141 listening socket (such as a server or multicast socket).
142 The address given should describe a local adapter, or
143 specify the port alone (ADDR_ANY) to have the OS assign
144 a local adapter address.
145
146 ***********************************************************************/
147
148 AsyncSocketConduit bind (Address address)
149 {
150 socket_.bind (address);
151 return this;
152 }
153
154 /***********************************************************************
155
156 Inform other end of a connected socket that we're no longer
157 available. In general, this should be invoked before close()
158 is invoked
159
160 The shutdown function shuts down the connection of the socket:
161
162 - stops receiving data for this socket. If further data
163 arrives, it is rejected.
164
165 - stops trying to transmit data from this socket. Also
166 discards any data waiting to be sent. Stop looking for
167 acknowledgement of data already sent; don't retransmit
168 if any data is lost.
169
170 ***********************************************************************/
171
172 AsyncSocketConduit shutdown ()
173 {
174 socket_.shutdown (SocketShutdown.BOTH);
175 return this;
176 }
177
178 /***********************************************************************
179
180 Release this AsyncSocketConduit
181
182 Note that one should always disconnect a AsyncSocketConduit
183 under normal conditions, and generally invoke shutdown
184 on all connected sockets beforehand
185
186 ***********************************************************************/
187
188 override void detach ()
189 {
190 socket_.detach;
191
192 // deallocate if this came from the free-list,
193 // otherwise just wait for the GC to handle it
194 if (fromList)
195 deallocate (this);
196 }
197
198 /***********************************************************************
199
200 Read content from the socket.
201
202 Returns the number of bytes read from the socket, or
203 IConduit.Eof where there's no more content available
204
205 Note that a timeout is equivalent to Eof. Isolating
206 a timeout condition can be achieved via hadTimeout()
207
208 Note also that a zero return value is not legitimate;
209 such a value indicates Eof
210
211 ***********************************************************************/
212
213 override uint read (void[] dst)
214 {
215 return read (dst, (void[] dst){return socket_.receive(dst);});
216 }
217
218 /***********************************************************************
219
220 Callback routine to write the provided content to the
221 socket. This will stall until the socket responds in
222 some manner. Returns the number of bytes sent to the
223 output, or IConduit.Eof if the socket cannot write.
224
225 ***********************************************************************/
226
227 override uint write (void[] src)
228 {
229 int count = socket_.send (src);
230 if (count == 0)
231 count = Eof;
232 else if (count < 0)
233 count = Err;
234 return count;
235 }
236
237 /***********************************************************************
238
239 Internal routine to handle socket read under a timeout.
240 Note that this is synchronized, in order to serialize
241 socket access
242
243 ***********************************************************************/
244
245 package final uint read (void[] dst, int delegate(void[]) dg)
246 {
247 // invoke the actual read op
248 int count = dg (dst);
249 if (count == 0)
250 return Eof;
251 else if (count < 0)
252 return Err;
253
254 return count;
255 }
256
257 }
258