1 /*******************************************************************************
2 
3         copyright:      Copyright (c) 2009 Tango. All rights reserved
4 
5         license:        BSD style: $(LICENSE)
6 
7         version:        Nov 2009: Initial release
8 
9         author:         Lukas Pinkowski, Kris
10 
11 *******************************************************************************/
12 
13 module tango.net.device.LocalSocket;
14 
15 private import tango.net.device.Socket;
16 private import tango.net.device.Berkeley;
17 
18 /*******************************************************************************
19 
20 
21 *******************************************************************************/
22 
23 version (Windows)
24 {
25         pragma(msg, "not yet available for windows");
26 }
27 
28 /*******************************************************************************
29 
30         A wrapper around the Berkeley API to implement the IConduit 
31         abstraction and add stream-specific functionality.
32 
33 *******************************************************************************/
34 
35 class LocalSocket : Socket
36 {
37         /***********************************************************************
38         
39                 Create a streaming local socket
40 
41         ***********************************************************************/
42 
43         private this ()
44         {
45                 super (AddressFamily.UNIX, SocketType.STREAM, ProtocolType.IP);
46         }
47 
48         /***********************************************************************
49         
50                 Create a streaming local socket
51 
52         ***********************************************************************/
53 
54         this (const(char)[] path)
55         {
56                 this (new LocalAddress (path));
57         }
58 
59         /***********************************************************************
60         
61                 Create a streaming local socket
62 
63         ***********************************************************************/
64 
65         this (LocalAddress addr)
66         {       
67                 this();
68                 super.connect (addr);
69         }
70 
71         /***********************************************************************
72 
73                 Return the name of this device
74 
75         ***********************************************************************/
76 
77         override immutable(char)[] toString()
78         {
79                 return "<localsocket>";
80         }
81 }
82 
83 /*******************************************************************************
84 
85 
86 *******************************************************************************/
87 
88 class LocalServerSocket : LocalSocket
89 {      
90         /***********************************************************************
91 
92         ***********************************************************************/
93 
94         this (const(char)[] path, int backlog=32, bool reuse=false)
95         {
96                 auto addr = new LocalAddress (path);
97                 native.addressReuse(reuse).bind(addr).listen(backlog);
98         }
99 
100         /***********************************************************************
101 
102                 Return the name of this device
103 
104         ***********************************************************************/
105 
106         override immutable(char)[] toString()
107         {
108                 return "<localaccept>";
109         }
110 
111         /***********************************************************************
112 
113         ***********************************************************************/
114 
115         Socket accept (Socket recipient = null)
116         {
117                 if (recipient is null)
118                     recipient = new LocalSocket;
119 
120                 native.accept (*recipient.native);
121                 recipient.timeout = timeout;
122                 return recipient;
123         }
124 }
125 
126 /*******************************************************************************
127 
128 *******************************************************************************/
129 
130 class LocalAddress : Address
131 {
132         align(1) struct sockaddr_un
133         {
134                 ushort sun_family = AddressFamily.UNIX;
135                 char[108] sun_path;
136         }
137                         
138         protected
139         {
140                 sockaddr_un sun;
141                 const(char)[] _path;
142                 size_t _pathLength;
143         }
144 
145         /***********************************************************************
146 
147             -path- path to a unix domain socket (which is a filename)
148 
149         ***********************************************************************/
150 
151         this (const(char)[] path)
152         {
153                 assert (path.length < 108);
154                 
155                 sun.sun_path [0 .. path.length] = path[];
156                 sun.sun_path [path.length .. $] = 0;
157                 
158                 _pathLength = path.length;
159                 _path = sun.sun_path [0 .. path.length];
160         }
161 
162         /***********************************************************************
163 
164         ***********************************************************************/
165 
166         @property override final sockaddr* name () 
167         { 
168                 return cast(sockaddr*) &sun; 
169         }
170         
171         /***********************************************************************
172 
173         ***********************************************************************/
174 
175         @property override final const int nameLen ()
176         { 
177                 return cast(int)(_pathLength + ushort.sizeof);
178         }
179         
180         /***********************************************************************
181 
182         ***********************************************************************/
183 
184         @property override final AddressFamily addressFamily () 
185         { 
186                 return AddressFamily.UNIX; 
187         }
188         
189         /***********************************************************************
190 
191         ***********************************************************************/
192 
193         final override string toString ()
194         {
195                 if (isAbstract)
196                     return "unix:abstract=" ~ _path[1..$].idup;
197                 else
198                    return "unix:path=" ~ _path.idup;
199         }
200         
201         /***********************************************************************
202 
203         ***********************************************************************/
204 
205         @property final const const(char)[] path ()
206         {
207                 return _path;
208         }
209         
210         /***********************************************************************
211 
212         ***********************************************************************/
213 
214         @property final const bool isAbstract ()
215         {
216                 return _path[0] == 0;
217         }
218 }
219 
220 /******************************************************************************
221 
222 ******************************************************************************/
223 
224 debug (LocalSocket)
225 {
226         import tango.io.Stdout;
227 
228         void main()
229         {
230                 auto y = new LocalSocket ("foo");
231                 auto x = new LocalServerSocket ("foo");   
232         }
233 }