1/* $Id$ */
2
3/***
4  This file is part of avahi.
5
6  avahi is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Lesser General Public License as
8  published by the Free Software Foundation; either version 2.1 of the
9  License, or (at your option) any later version.
10
11  avahi is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14  Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with avahi; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  USA.
20***/
21
22using System;
23using System.Collections;
24using System.Runtime.InteropServices;
25using System.Text;
26
27namespace Avahi
28{
29    internal delegate void ServiceTypeBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
30                                                       IntPtr type, IntPtr domain, LookupResultFlags flags,
31                                                       IntPtr userdata);
32
33    public struct ServiceTypeInfo
34    {
35        public int NetworkInterface;
36        public Protocol Protocol;
37        public string Domain;
38        public string ServiceType;
39        public LookupResultFlags Flags;
40    }
41
42    public class ServiceTypeInfoArgs : EventArgs
43    {
44        private ServiceTypeInfo type;
45
46        public ServiceTypeInfo ServiceType
47        {
48            get { return type; }
49        }
50
51        public ServiceTypeInfoArgs (ServiceTypeInfo type)
52        {
53            this.type = type;
54        }
55    }
56
57    public delegate void ServiceTypeInfoHandler (object o, ServiceTypeInfoArgs args);
58
59    public class ServiceTypeBrowser : BrowserBase, IDisposable
60    {
61        private IntPtr handle;
62        private ArrayList infos = new ArrayList ();
63        private Client client;
64        private int iface;
65        private Protocol proto;
66        private string domain;
67        private LookupFlags flags;
68        private ServiceTypeBrowserCallback cb;
69
70        private ArrayList addListeners = new ArrayList ();
71        private ArrayList removeListeners = new ArrayList ();
72
73        [DllImport ("avahi-client")]
74        private static extern IntPtr avahi_service_type_browser_new (IntPtr client, int iface, int proto,
75                                                                     byte[] domain, LookupFlags flags,
76                                                                     ServiceTypeBrowserCallback cb,
77                                                                     IntPtr userdata);
78
79        [DllImport ("avahi-client")]
80        private static extern void avahi_service_type_browser_free (IntPtr handle);
81
82        public event ServiceTypeInfoHandler ServiceTypeAdded
83        {
84            add {
85                addListeners.Add (value);
86                Start ();
87            }
88            remove {
89                addListeners.Remove (value);
90                Stop (false);
91            }
92        }
93
94        public event ServiceTypeInfoHandler ServiceTypeRemoved
95        {
96            add {
97                removeListeners.Add (value);
98                Start ();
99            }
100            remove {
101                removeListeners.Remove (value);
102                Stop (false);
103            }
104        }
105
106        public ServiceTypeInfo[] ServiceTypes
107        {
108            get { return (ServiceTypeInfo[]) infos.ToArray (typeof (ServiceTypeInfo)); }
109        }
110
111        public ServiceTypeBrowser (Client client) : this (client, client.DomainName)
112        {
113        }
114
115        public ServiceTypeBrowser (Client client, string domain) : this (client, -1, Protocol.Unspecified,
116                                                                         domain, LookupFlags.None)
117        {
118        }
119
120        public ServiceTypeBrowser (Client client, int iface, Protocol proto, string domain, LookupFlags flags)
121        {
122            this.client = client;
123            this.iface = iface;
124            this.proto = proto;
125            this.domain = domain;
126            this.flags = flags;
127            cb = OnServiceTypeBrowserCallback;
128        }
129
130        ~ServiceTypeBrowser ()
131        {
132            Dispose ();
133        }
134
135        public void Dispose ()
136        {
137            Stop (true);
138        }
139
140        private void Start ()
141        {
142            if (client.Handle == IntPtr.Zero || handle != IntPtr.Zero ||
143                (addListeners.Count == 0 && removeListeners.Count == 0))
144                return;
145
146            lock (client) {
147                handle = avahi_service_type_browser_new (client.Handle, iface, (int) proto,
148                                                         Utility.StringToBytes (domain), flags,
149                                                         cb, IntPtr.Zero);
150
151                if (handle == IntPtr.Zero)
152                    client.ThrowError ();
153            }
154        }
155
156        private void Stop (bool force)
157        {
158            if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero &&
159                (force || (addListeners.Count == 0 && removeListeners.Count == 0))) {
160
161                lock (client) {
162                    avahi_service_type_browser_free (handle);
163                    handle = IntPtr.Zero;
164                }
165            }
166        }
167
168        private void OnServiceTypeBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
169                                                   IntPtr type, IntPtr domain, LookupResultFlags flags,
170                                                   IntPtr userdata)
171        {
172
173            ServiceTypeInfo info;
174            info.NetworkInterface = iface;
175            info.Protocol = proto;
176            info.Domain = Utility.PtrToString (domain);
177            info.ServiceType = Utility.PtrToString (type);
178            info.Flags = flags;
179
180            switch (bevent) {
181            case BrowserEvent.Added:
182                infos.Add (info);
183
184                foreach (ServiceTypeInfoHandler handler in addListeners)
185                    handler (this, new ServiceTypeInfoArgs (info));
186                break;
187            case BrowserEvent.Removed:
188                infos.Remove (info);
189
190                foreach (ServiceTypeInfoHandler handler in removeListeners)
191                    handler (this, new ServiceTypeInfoArgs (info));
192                break;
193            default:
194                EmitBrowserEvent (bevent);
195                break;
196            }
197        }
198    }
199}
200