comparison tango/tango/net/SocketConduit.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
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
12
13 *******************************************************************************/
14
15 module tango.net.SocketConduit;
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.
27
28 SocketConduit data-transfer is typically performed in conjunction with
29 an IBuffer, but can happily be handled directly using void array where
30 preferred
31
32 *******************************************************************************/
33
34 class SocketConduit : Conduit
35 {
36 private timeval tv;
37 private SocketSet ss;
38 package Socket socket_;
39 private bool timeout;
40
41 // freelist support
42 private SocketConduit next;
43 private bool fromList;
44 private static SocketConduit freelist;
45
46 /***********************************************************************
47
48 Create a streaming Internet Socket
49
50 ***********************************************************************/
51
52 this ()
53 {
54 this (SocketType.STREAM, ProtocolType.TCP);
55 }
56
57 /***********************************************************************
58
59 Create an Internet Socket. Used by subclasses and by
60 ServerSocket; the latter via method allocate() below
61
62 ***********************************************************************/
63
64 protected this (SocketType type, ProtocolType protocol, bool create=true)
65 {
66 socket_ = new Socket (AddressFamily.INET, type, protocol, create);
67 }
68
69 /***********************************************************************
70
71 Return the name of this device
72
73 ***********************************************************************/
74
75 override char[] toString()
76 {
77 return socket.toString;
78 }
79
80 /***********************************************************************
81
82 Return the socket wrapper
83
84 ***********************************************************************/
85
86 Socket socket ()
87 {
88 return socket_;
89 }
90
91 /***********************************************************************
92
93 Return a preferred size for buffering conduit I/O
94
95 ***********************************************************************/
96
97 override uint bufferSize ()
98 {
99 return 1024 * 8;
100 }
101
102 /***********************************************************************
103
104 Models a handle-oriented device.
105
106 TODO: figure out how to avoid exposing this in the general
107 case
108
109 ***********************************************************************/
110
111 override Handle fileHandle ()
112 {
113 return cast(Handle) socket_.fileHandle;
114 }
115
116 /***********************************************************************
117
118 Set the read timeout to the specified interval. Set a
119 value of zero to disable timeout support.
120
121 ***********************************************************************/
122
123 SocketConduit setTimeout (TimeSpan interval)
124 {
125 tv = Socket.toTimeval (interval);
126 return this;
127 }
128
129 /***********************************************************************
130
131 Did the last operation result in a timeout?
132
133 ***********************************************************************/
134
135 bool hadTimeout ()
136 {
137 return timeout;
138 }
139
140 /***********************************************************************
141
142 Is this socket still alive?
143
144 ***********************************************************************/
145
146 override bool isAlive ()
147 {
148 return socket_.isAlive;
149 }
150
151 /***********************************************************************
152
153 Connect to the provided endpoint
154
155 ***********************************************************************/
156
157 SocketConduit connect (Address addr)
158 {
159 socket_.connect (addr);
160 return this;
161 }
162
163 /***********************************************************************
164
165 Bind the socket. This is typically used to configure a
166 listening socket (such as a server or multicast socket).
167 The address given should describe a local adapter, or
168 specify the port alone (ADDR_ANY) to have the OS assign
169 a local adapter address.
170
171 ***********************************************************************/
172
173 SocketConduit bind (Address address)
174 {
175 socket_.bind (address);
176 return this;
177 }
178
179 /***********************************************************************
180
181 Inform other end of a connected socket that we're no longer
182 available. In general, this should be invoked before close()
183 is invoked
184
185 The shutdown function shuts down the connection of the socket:
186
187 - stops receiving data for this socket. If further data
188 arrives, it is rejected.
189
190 - stops trying to transmit data from this socket. Also
191 discards any data waiting to be sent. Stop looking for
192 acknowledgement of data already sent; don't retransmit
193 if any data is lost.
194
195 ***********************************************************************/
196
197 SocketConduit shutdown ()
198 {
199 socket_.shutdown (SocketShutdown.BOTH);
200 return this;
201 }
202
203 /***********************************************************************
204
205 Read content from socket. This is implemented as a callback
206 from the reader() method so we can expose the timout support
207 to subclasses
208
209 ***********************************************************************/
210
211 protected uint socketReader (void[] dst)
212 {
213 return socket_.receive (dst);
214 }
215
216 /***********************************************************************
217
218 Release this SocketConduit
219
220 Note that one should always disconnect a SocketConduit
221 under normal conditions, and generally invoke shutdown
222 on all connected sockets beforehand
223
224 ***********************************************************************/
225
226 override void detach ()
227 {
228 socket_.detach;
229
230 // deallocate if this came from the free-list,
231 // otherwise just wait for the GC to handle it
232 if (fromList)
233 deallocate (this);
234 }
235
236 /***********************************************************************
237
238 Callback routine to read content from the socket. Note
239 that the operation may timeout if method setTimeout()
240 has been invoked with a non-zero value.
241
242 Returns the number of bytes read from the socket, or
243 IConduit.Eof where there's no more content available
244
245 Note that a timeout is equivalent to Eof. Isolating
246 a timeout condition can be achieved via hadTimeout()
247
248 Note also that a zero return value is not legitimate;
249 such a value indicates Eof
250
251 ***********************************************************************/
252
253 override uint read (void[] dst)
254 {
255 // ensure just one read at a time
256 synchronized (this)
257 {
258 // reset timeout; we assume there's no thread contention
259 timeout = false;
260
261 // did user disable timeout checks?
262 if (tv.tv_usec | tv.tv_sec)
263 {
264 // nope: ensure we have a SocketSet
265 if (ss is null)
266 ss = new SocketSet (1);
267
268 ss.reset ();
269 ss.add (socket_);
270
271 // wait until data is available, or a timeout occurs
272 auto copy = tv;
273 int i = socket_.select (ss, null, null, &copy);
274
275 if (i <= 0)
276 {
277 if (i is 0)
278 timeout = true;
279 return Eof;
280 }
281 }
282
283 // invoke the actual read op
284 int count = socketReader (dst);
285 if (count <= 0)
286 count = Eof;
287 return count;
288 }
289 }
290
291 /***********************************************************************
292
293 Callback routine to write the provided content to the
294 socket. This will stall until the socket responds in
295 some manner. Returns the number of bytes sent to the
296 output, or IConduit.Eof if the socket cannot write.
297
298 ***********************************************************************/
299
300 override uint write (void[] src)
301 {
302 int count = socket_.send (src);
303 if (count <= 0)
304 count = Eof;
305 return count;
306 }
307
308 /***********************************************************************
309
310 Allocate a SocketConduit from a list rather than creating
311 a new one. Note that the socket itself is not opened; only
312 the wrappers. This is because the socket is often assigned
313 directly via accept()
314
315 ***********************************************************************/
316
317 package static synchronized SocketConduit allocate ()
318 {
319 SocketConduit s;
320
321 if (freelist)
322 {
323 s = freelist;
324 freelist = s.next;
325 }
326 else
327 {
328 s = new SocketConduit (SocketType.STREAM, ProtocolType.TCP, false);
329 s.fromList = true;
330 }
331 return s;
332 }
333
334 /***********************************************************************
335
336 Return this SocketConduit to the free-list
337
338 ***********************************************************************/
339
340 private static synchronized void deallocate (SocketConduit s)
341 {
342 s.next = freelist;
343 freelist = s;
344 }
345 }
346