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