2005-04-21 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / UnixListener.cs
1 //
2 // UnixListener.cs
3 //
4 // Authors:
5 //      Joe Shaw (joeshaw@novell.com)
6 //
7 // Copyright (C) 2004-2005 Novell, Inc.
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a
12 // copy of this software and associated documentation files (the "Software"),
13 // to deal in the Software without restriction, including without limitation
14 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 // and/or sell copies of the Software, and to permit persons to whom the
16 // Software is furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 // DEALINGS IN THE SOFTWARE.
28 //
29
30
31 using System;
32 using System.Net;
33 using System.Net.Sockets;
34 using System.IO;
35
36 namespace Mono.Unix {
37
38         public class UnixListener : IDisposable {
39                 bool disposed;
40                 bool listening;
41                 Socket server;
42                 EndPoint savedEP;
43  
44                 void Init (UnixEndPoint ep)
45                 {
46                         Cleanup (ep);
47                         listening = false;
48                         string filename = ep.Filename;
49                         if (File.Exists (filename)) {
50                                 Socket conn = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
51                                 try {
52                                         conn.Connect (ep);
53                                         conn.Close ();
54                                         throw new InvalidOperationException ("There's already a server listening on " + filename);
55                                 } catch (SocketException se) {
56                                 }
57                                 File.Delete (filename);
58                         }
59
60                         server = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
61                         server.Bind (ep);
62                         savedEP = server.LocalEndPoint;
63                 }
64         
65                 public UnixListener (string path)
66                 {
67                         if (!Directory.Exists (Path.GetDirectoryName (path)))
68                                 Directory.CreateDirectory (Path.GetDirectoryName (path));
69             
70                         Init (new UnixEndPoint (path));
71                 }
72
73                 public UnixListener (UnixEndPoint localEndPoint)
74                 {
75                         if (localEndPoint == null)
76                                 throw new ArgumentNullException ("localendPoint");
77
78                         Init (localEndPoint);
79                 }
80         
81                 public EndPoint LocalEndpoint {
82                         get { return savedEP; }
83                 }
84         
85                 protected Socket Server {
86                         get { return server; }
87                 }
88         
89                 public Socket AcceptSocket ()
90                 {
91                         CheckDisposed ();
92                         if (!listening)
93                                 throw new InvalidOperationException ("Socket is not listening");
94
95                         return server.Accept ();
96                 }
97         
98                 public UnixClient AcceptUnixClient ()
99                 {
100                         CheckDisposed ();
101                         if (!listening)
102                                 throw new InvalidOperationException ("Socket is not listening");
103
104                         return new UnixClient (AcceptSocket ());
105                 }
106         
107                 ~UnixListener ()
108                 {
109                         Dispose (false);
110                 }
111     
112                 public bool Pending ()
113                 {
114                         CheckDisposed ();
115                         if (!listening)
116                                 throw new InvalidOperationException ("Socket is not listening");
117
118                         return server.Poll (1000, SelectMode.SelectRead);
119                 }
120         
121                 public void Start ()
122                 {
123                         Start (5);
124                 }
125         
126                 public void Start (int backlog)
127                 {
128                         CheckDisposed ();
129                         if (listening)
130                                 return;
131
132                         server.Listen (backlog);
133                         listening = true;
134                 }
135
136                 public void Stop ()
137                 {
138                         CheckDisposed ();
139                         Dispose (true);
140                 }
141
142                 public void Dispose ()
143                 {
144                         Dispose (true);
145                         GC.SuppressFinalize (this);
146                 }
147
148                 protected void Dispose (bool disposing)
149                 {
150                         if (disposed)
151                                 return;
152
153                         if (disposing) {
154                                 if (server != null)
155                                         server.Close ();
156
157                                 server = null;
158                         }
159
160                         disposed = true;
161                 }
162         
163                 void CheckDisposed ()
164                 {
165                         if (disposed)
166                                 throw new ObjectDisposedException (GetType().FullName);
167                 }        
168
169                 static void Cleanup (UnixEndPoint ep)
170                 {
171                         string path = ((UnixEndPoint) ep).Filename;
172                         if (File.Exists (path))
173                                 File.Delete (path);
174                 }
175         }
176
177 }