Mono.Zeroconf – Diff between revs 1 and 2

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 1 Rev 2
1 // 1 //
2 // ServiceBrowser.cs 2 // ServiceBrowser.cs
3 // 3 //
4 // Authors: 4 // Authors:
5 // Aaron Bockover <abockover@novell.com> 5 // Aaron Bockover <abockover@novell.com>
6 // 6 //
7 // Copyright (C) 2006-2007 Novell, Inc (http://www.novell.com) 7 // Copyright (C) 2006-2007 Novell, Inc (http://www.novell.com)
8 // 8 //
9 // Permission is hereby granted, free of charge, to any person obtaining 9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the 10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including 11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish, 12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to 13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to 14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions: 15 // the following conditions:
16 // 16 //
17 // The above copyright notice and this permission notice shall be 17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software. 18 // included in all copies or substantial portions of the Software.
19 // 19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 // 27 //
28   28  
29 using System; 29 using System;
30 using System.Collections; 30 using System.Collections;
31 using System.Collections.Generic; 31 using System.Collections.Generic;
32 using System.Threading; 32 using System.Threading;
33   33  
34 namespace Mono.Zeroconf.Providers.Bonjour 34 namespace Mono.Zeroconf.Providers.Bonjour
35 { 35 {
36 public class ServiceBrowseEventArgs : Mono.Zeroconf.ServiceBrowseEventArgs 36 public class ServiceBrowseEventArgs : Mono.Zeroconf.ServiceBrowseEventArgs
37 { 37 {
38 private bool more_coming; 38 private bool more_coming;
39 39
40 public ServiceBrowseEventArgs(BrowseService service, bool moreComing) : base(service) 40 public ServiceBrowseEventArgs(BrowseService service, bool moreComing) : base(service)
41 { 41 {
42 this.more_coming = moreComing; 42 this.more_coming = moreComing;
43 } 43 }
44 44
45 public bool MoreComing { 45 public bool MoreComing {
46 get { return more_coming; } 46 get { return more_coming; }
47 } 47 }
48 } 48 }
49 49
50 public class ServiceBrowser : IServiceBrowser, IDisposable 50 public class ServiceBrowser : IServiceBrowser, IDisposable
51 { 51 {
52 private uint interface_index; 52 private uint interface_index;
53 private AddressProtocol address_protocol; 53 private AddressProtocol address_protocol;
54 private string regtype; 54 private string regtype;
55 private string domain; 55 private string domain;
56 56
57 private ServiceRef sd_ref = ServiceRef.Zero; 57 private ServiceRef sd_ref = ServiceRef.Zero;
58 private Dictionary<string, IResolvableService> service_table = new Dictionary<string, IResolvableService> (); 58 private Dictionary<string, IResolvableService> service_table = new Dictionary<string, IResolvableService> ();
59 59
60 private Native.DNSServiceBrowseReply browse_reply_handler; 60 private Native.DNSServiceBrowseReply browse_reply_handler;
61 61
62 private Thread thread; 62 private Thread thread;
63 63
64 public event ServiceBrowseEventHandler ServiceAdded; 64 public event ServiceBrowseEventHandler ServiceAdded;
65 public event ServiceBrowseEventHandler ServiceRemoved; 65 public event ServiceBrowseEventHandler ServiceRemoved;
66 66
67 public ServiceBrowser() 67 public ServiceBrowser()
68 { 68 {
69 browse_reply_handler = new Native.DNSServiceBrowseReply(OnBrowseReply); 69 browse_reply_handler = new Native.DNSServiceBrowseReply(OnBrowseReply);
70 } 70 }
71 71
72 public void Browse (uint interfaceIndex, AddressProtocol addressProtocol, string regtype, string domain) 72 public void Browse (uint interfaceIndex, AddressProtocol addressProtocol, string regtype, string domain)
73 { 73 {
74 Configure(interfaceIndex, addressProtocol, regtype, domain); 74 Configure(interfaceIndex, addressProtocol, regtype, domain);
75 StartAsync(); 75 StartAsync();
76 } 76 }
77   77  
78 public void Configure(uint interfaceIndex, AddressProtocol addressProtocol, string regtype, string domain) 78 public void Configure(uint interfaceIndex, AddressProtocol addressProtocol, string regtype, string domain)
79 { 79 {
80 this.interface_index = interfaceIndex; 80 this.interface_index = interfaceIndex;
81 this.address_protocol = addressProtocol; 81 this.address_protocol = addressProtocol;
82 this.regtype = regtype; 82 this.regtype = regtype;
83 this.domain = domain; 83 this.domain = domain;
84 84
85 if(regtype == null) { 85 if(regtype == null) {
86 throw new ArgumentNullException("regtype"); 86 throw new ArgumentNullException("regtype");
87 } 87 }
88 } 88 }
89 89
90 private void Start(bool @async) 90 private void Start(bool @async)
91 { 91 {
92 if(thread != null) { 92 if(thread != null) {
93 throw new InvalidOperationException("ServiceBrowser is already started"); 93 throw new InvalidOperationException("ServiceBrowser is already started");
94 } 94 }
95 95
96 if(@async) { 96 if(@async) {
97 thread = new Thread(new ThreadStart(ThreadedStart)); 97 thread = new Thread(new ThreadStart(ThreadedStart));
98 thread.IsBackground = true; 98 thread.IsBackground = true;
99 thread.Start(); 99 thread.Start();
100 } else { 100 } else {
101 ProcessStart(); 101 ProcessStart();
102 } 102 }
103 } 103 }
104 104
105 public void Start() 105 public void Start()
106 { 106 {
107 Start(false); 107 Start(false);
108 } 108 }
109 109
110 public void StartAsync() 110 public void StartAsync()
111 { 111 {
112 Start(true); 112 Start(true);
113 } 113 }
114 114
115 private void ThreadedStart() 115 private void ThreadedStart()
116 { 116 {
117 try { 117 try {
118 ProcessStart(); 118 ProcessStart();
119 } catch(ThreadAbortException) { 119 } catch(ThreadAbortException) {
120 Thread.ResetAbort(); 120 Thread.ResetAbort();
121 } 121 }
122 122
123 thread = null; 123 thread = null;
124 } 124 }
125   125  
126 private void ProcessStart() 126 private void ProcessStart()
127 { 127 {
128 ServiceError error = Native.DNSServiceBrowse(out sd_ref, ServiceFlags.Default, 128 ServiceError error = Native.DNSServiceBrowse(out sd_ref, ServiceFlags.Default,
129 interface_index, regtype, domain, browse_reply_handler, IntPtr.Zero); 129 interface_index, regtype, domain, browse_reply_handler, IntPtr.Zero);
130   130  
131 if(error != ServiceError.NoError) { 131 if(error != ServiceError.NoError) {
132 throw new ServiceErrorException(error); 132 throw new ServiceErrorException(error);
133 } 133 }
134   134  
135 sd_ref.Process(); 135 sd_ref.Process();
136 } 136 }
137 137
138 public void Stop() 138 public void Stop()
139 { 139 {
140 if(sd_ref != ServiceRef.Zero) { 140 if(sd_ref != ServiceRef.Zero) {
141 sd_ref.Deallocate(); 141 sd_ref.Deallocate();
142 sd_ref = ServiceRef.Zero; 142 sd_ref = ServiceRef.Zero;
143 } 143 }
144 144
145 if(thread != null) { 145 if(thread != null) {
146 thread.Abort(); 146 thread.Abort();
147 thread = null; 147 thread = null;
148 } 148 }
149 } 149 }
150 150
151 public void Dispose() 151 public void Dispose()
152 { 152 {
153 Stop(); 153 Stop();
154 } 154 }
155 155
156 public IEnumerator<IResolvableService> GetEnumerator () 156 public IEnumerator<IResolvableService> GetEnumerator ()
157 { 157 {
158 lock (this) { 158 lock (this) {
159 foreach (IResolvableService service in service_table.Values) { 159 foreach (IResolvableService service in service_table.Values) {
160 yield return service; 160 yield return service;
161 } 161 }
162 } 162 }
163 } 163 }
164 164
165 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () 165 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
166 { 166 {
167 return GetEnumerator (); 167 return GetEnumerator ();
168 } 168 }
169 169
170 private void OnBrowseReply(ServiceRef sdRef, ServiceFlags flags, uint interfaceIndex, ServiceError errorCode, 170 private void OnBrowseReply(ServiceRef sdRef, ServiceFlags flags, uint interfaceIndex, ServiceError errorCode,
171 string serviceName, string regtype, string replyDomain, IntPtr context) 171 IntPtr serviceName, string regtype, string replyDomain, IntPtr context)
-   172 {
172 { 173 string name = Native.Utf8toString(serviceName);
173 BrowseService service = new BrowseService(); 174 BrowseService service = new BrowseService();
174 service.Flags = flags; 175 service.Flags = flags;
175 service.Name = serviceName; 176 service.Name = name;
176 service.RegType = regtype; 177 service.RegType = regtype;
177 service.ReplyDomain = replyDomain; 178 service.ReplyDomain = replyDomain;
178 service.InterfaceIndex = interfaceIndex; 179 service.InterfaceIndex = interfaceIndex;
179 service.AddressProtocol = address_protocol; 180 service.AddressProtocol = address_protocol;
180 181
181 ServiceBrowseEventArgs args = new ServiceBrowseEventArgs( 182 ServiceBrowseEventArgs args = new ServiceBrowseEventArgs(
182 service, (flags & ServiceFlags.MoreComing) != 0); 183 service, (flags & ServiceFlags.MoreComing) != 0);
183 184
184 if((flags & ServiceFlags.Add) != 0) { 185 if((flags & ServiceFlags.Add) != 0) {
185 lock (service_table) { 186 lock (service_table) {
186 if (service_table.ContainsKey (serviceName)) { 187 if (service_table.ContainsKey (name)) {
187 service_table[serviceName] = service; 188 service_table[name] = service;
188 } else { 189 } else {
189 service_table.Add (serviceName, service); 190 service_table.Add(name, service);
190 } 191 }
191 } 192 }
192 193
193 ServiceBrowseEventHandler handler = ServiceAdded; 194 ServiceBrowseEventHandler handler = ServiceAdded;
194 if(handler != null) { 195 if(handler != null) {
195 handler(this, args); 196 handler(this, args);
196 } 197 }
197 } else { 198 } else {
198 lock (service_table) { 199 lock (service_table) {
199 if (service_table.ContainsKey (serviceName)) { 200 if (service_table.ContainsKey (name)) {
200 service_table.Remove (serviceName); 201 service_table.Remove (name);
201 } 202 }
202 } 203 }
203 204
204 ServiceBrowseEventHandler handler = ServiceRemoved; 205 ServiceBrowseEventHandler handler = ServiceRemoved;
205 if(handler != null) { 206 if(handler != null) {
206 handler(this, args); 207 handler(this, args);
207 } 208 }
208 } 209 }
209 } 210 }
210 } 211 }
211 } 212 }
212   213