0
|
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
|