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