From 6386804f93ee272fcff73459a9cfe0b847101609 Mon Sep 17 00:00:00 2001 From: Federico Lucifredi Date: Tue, 19 Dec 2006 19:11:45 +0000 Subject: Branching for wide-area publishing work git-svn-id: file:///home/lennart/svn/public/avahi/branches/federico@1344 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- trunk/avahi-sharp/Client.cs | 385 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 385 insertions(+) create mode 100644 trunk/avahi-sharp/Client.cs (limited to 'trunk/avahi-sharp/Client.cs') diff --git a/trunk/avahi-sharp/Client.cs b/trunk/avahi-sharp/Client.cs new file mode 100644 index 0000000..02763d4 --- /dev/null +++ b/trunk/avahi-sharp/Client.cs @@ -0,0 +1,385 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + + +using System; +using System.Threading; +using System.Collections; +using System.Runtime.InteropServices; +using Mono.Unix; +using Mono.Unix.Native; + +using Stdlib = Mono.Unix.Native.Stdlib; + +namespace Avahi +{ + internal enum ResolverEvent { + Found, + Failure + } + + internal enum BrowserEvent { + Added, + Removed, + CacheExhausted, + AllForNow, + Failure + } + + internal delegate int PollCallback (IntPtr ufds, uint nfds, int timeout); + internal delegate void ClientCallback (IntPtr client, ClientState state, IntPtr userData); + + public delegate void ClientStateHandler (object o, ClientStateArgs state); + + public class ClientStateArgs : EventArgs + { + private ClientState state; + private ErrorCode error; + + public ClientState State + { + get { return state; } + } + + public ErrorCode Error + { + get { return error; } + } + + public ClientStateArgs (ClientState state, ErrorCode error) + { + this.state = state; + this.error = error; + } + } + + public enum Protocol { + Unspecified = -1, + IPv4 = 0, + IPv6 = 1 + } + + internal enum ServerState { + Invalid, + Registering, + Running, + Collision + } + + public enum ClientState { + Registering = ServerState.Registering, + Running = ServerState.Running, + Collision = ServerState.Collision, + Failure = 100, + Connecting = 101 + } + + [Flags] + public enum LookupFlags { + None = 0, + UseWideArea = 1, + UseMulticast = 2, + NoTxt = 4, + NoAddress = 8 + } + + [Flags] + public enum LookupResultFlags { + None = 0, + Cached = 1, + WideArea = 2, + Multicast = 4, + Local = 8, + OurOwn = 16, + } + + [Flags] + public enum ClientFlags { + None = 0, + IgnoreUserConfig = 1, + NoFail = 2 + } + + public class Client : IDisposable + { + private IntPtr handle; + private ClientCallback cb; + private PollCallback pollcb; + private IntPtr spoll; + + private Thread thread; + + [DllImport ("avahi-client")] + private static extern IntPtr avahi_client_new (IntPtr poll, ClientFlags flags, ClientCallback handler, + IntPtr userData, out int error); + + [DllImport ("avahi-client")] + private static extern void avahi_client_free (IntPtr handle); + + [DllImport ("avahi-client")] + private static extern IntPtr avahi_client_get_version_string (IntPtr handle); + + [DllImport ("avahi-client")] + private static extern IntPtr avahi_client_get_host_name (IntPtr handle); + + [DllImport ("avahi-client")] + private static extern IntPtr avahi_client_get_domain_name (IntPtr handle); + + [DllImport ("avahi-client")] + private static extern IntPtr avahi_client_get_host_name_fqdn (IntPtr handle); + + [DllImport ("avahi-client")] + private static extern ClientState avahi_client_get_state (IntPtr handle); + + [DllImport ("avahi-client")] + private static extern int avahi_client_errno (IntPtr handle); + + [DllImport ("avahi-common")] + private static extern IntPtr avahi_simple_poll_new (); + + [DllImport ("avahi-common")] + private static extern IntPtr avahi_simple_poll_get (IntPtr spoll); + + [DllImport ("avahi-common")] + private static extern void avahi_simple_poll_free (IntPtr spoll); + + [DllImport ("avahi-common")] + private static extern int avahi_simple_poll_loop (IntPtr spoll); + + [DllImport ("avahi-common")] + private static extern void avahi_simple_poll_set_func (IntPtr spoll, PollCallback cb); + + [DllImport ("avahi-common")] + private static extern void avahi_simple_poll_quit (IntPtr spoll); + + [DllImport ("avahi-client")] + private static extern uint avahi_client_get_local_service_cookie (IntPtr client); + + [DllImport ("avahi-common")] + private static extern int avahi_service_name_join (IntPtr buf, int len, byte[] name, byte[] type, + byte[] domain); + + [DllImport ("avahi-common")] + private static extern int avahi_service_name_split (byte[] service, IntPtr name, int name_len, + IntPtr type, int type_len, + IntPtr domain, int domain_len); + + + [DllImport ("libc")] + private static extern int poll(IntPtr ufds, uint nfds, int timeout); + + public event ClientStateHandler StateChanged; + + internal IntPtr Handle + { + get { return handle; } + } + + public string Version + { + get { + lock (this) { + return Utility.PtrToString (avahi_client_get_version_string (handle)); + } + } + } + + public string HostName + { + get { + lock (this) { + return Utility.PtrToString (avahi_client_get_host_name (handle)); + } + } + } + + public string DomainName + { + get { + lock (this) { + return Utility.PtrToString (avahi_client_get_domain_name (handle)); + } + } + } + + public string HostNameFqdn + { + get { + lock (this) { + return Utility.PtrToString (avahi_client_get_host_name_fqdn (handle)); + } + } + } + + public ClientState State + { + get { + lock (this) { + return (ClientState) avahi_client_get_state (handle); + } + } + } + + public uint LocalServiceCookie + { + get { + lock (this) { + return avahi_client_get_local_service_cookie (handle); + } + } + } + + internal ErrorCode LastError + { + get { + lock (this) { + return (ErrorCode) avahi_client_errno (handle); + } + } + } + + public Client (ClientFlags flags) + { + spoll = avahi_simple_poll_new (); + + pollcb = OnPollCallback; + avahi_simple_poll_set_func (spoll, pollcb); + IntPtr poll = avahi_simple_poll_get (spoll); + cb = OnClientCallback; + + int error; + handle = avahi_client_new (poll, flags, cb, IntPtr.Zero, out error); + if (error != 0) + throw new ClientException (error); + + thread = new Thread (PollLoop); + thread.IsBackground = true; + thread.Start (); + } + + public Client () : this (ClientFlags.None) { + } + + ~Client () + { + Dispose (); + } + + public void Dispose () + { + if (handle != IntPtr.Zero) { + lock (this) { + avahi_client_free (handle); + handle = IntPtr.Zero; + + avahi_simple_poll_quit (spoll); + Monitor.Wait (this); + + avahi_simple_poll_free (spoll); + } + } + } + + public static string JoinServiceName (string name, string type, string domain) + { + int len = 4 * (name.Length + type.Length + domain.Length) + 4; + IntPtr buf = Stdlib.malloc ((ulong) len); + + int ret = avahi_service_name_join (buf, len, + Utility.StringToBytes (name), + Utility.StringToBytes (type), + Utility.StringToBytes (domain)); + + if (ret < 0) { + Utility.Free (buf); + return null; // FIXME, should throw exception + } + + string service = Utility.PtrToString (buf); + Utility.Free (buf); + + return service; + } + + public static void SplitServiceName (string service, out string name, out string type, out string domain) + { + int len = 1024; + + IntPtr namePtr = Stdlib.malloc ((ulong) len); + IntPtr typePtr = Stdlib.malloc ((ulong) len); + IntPtr domainPtr = Stdlib.malloc ((ulong) len); + + int ret = avahi_service_name_split (Utility.StringToBytes (service), namePtr, len, typePtr, len, + domainPtr, len); + + if (ret < 0) { + Utility.Free (namePtr); + Utility.Free (typePtr); + Utility.Free (domainPtr); + + name = null; + type = null; + domain = null; + return; + } + + name = Utility.PtrToString (namePtr); + type = Utility.PtrToString (typePtr); + domain = Utility.PtrToString (domainPtr); + + Utility.Free (namePtr); + Utility.Free (typePtr); + Utility.Free (domainPtr); + } + + internal void ThrowError () + { + ErrorCode error = LastError; + + if (error != ErrorCode.Ok) + throw new ClientException (error); + } + + private void OnClientCallback (IntPtr client, ClientState state, IntPtr userData) + { + if (StateChanged != null) + StateChanged (this, new ClientStateArgs (state, LastError)); + } + + private int OnPollCallback (IntPtr ufds, uint nfds, int timeout) { + Monitor.Exit (this); + int result = poll (ufds, nfds, timeout); + Monitor.Enter (this); + return result; + } + + private void PollLoop () { + try { + lock (this) { + avahi_simple_poll_loop (spoll); + Monitor.Pulse (this); + } + } catch (Exception e) { + Console.Error.WriteLine ("Error in avahi-sharp event loop: " + e); + } + } + } +} -- cgit