/* -*- Mode: C; tab-width: 4 -*- * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Text; using Bonjour; namespace DNSServiceBrowser_NET { /// /// Summary description for Form1. /// public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.ComboBox typeBox; private System.Windows.Forms.ListBox browseList; private Bonjour.DNSSDEventManager eventManager = null; private Bonjour.DNSSDService service = null; private Bonjour.DNSSDService browser = null; private Bonjour.DNSSDService resolver = null; /// /// Required designer variable. /// private System.ComponentModel.Container components = null; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label4; private System.Windows.Forms.TextBox nameField; private System.Windows.Forms.TextBox typeField; private System.Windows.Forms.TextBox domainField; private System.Windows.Forms.TextBox hostField; private System.Windows.Forms.TextBox portField; private System.Windows.Forms.Label label5; private System.Windows.Forms.ListBox serviceTextField; public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); this.Load += new System.EventHandler(this.Form1_Load); // // Create the DNSSDEventManager. You can then associate event handlers // with the instance that will be invoked when the event occurs // // In this example, we're associating ServiceFound, ServiceLost, // ServiceResolved, and OperationFailed event handlers with the // event manager instance. // eventManager = new DNSSDEventManager(); eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound); eventManager.ServiceLost += new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost); eventManager.ServiceResolved += new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved); eventManager.OperationFailed += new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed); service = new DNSSDService(); } private void Form1_Load(object sender, EventArgs e) { typeBox.SelectedItem = "_http._tcp"; } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } // // Clean up // if (resolver != null) { resolver.Stop(); } if (browser != null) { browser.Stop(); } if (service != null) { service.Stop(); } eventManager.ServiceFound -= new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound); eventManager.ServiceLost -= new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost); eventManager.ServiceResolved -= new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved); eventManager.OperationFailed -= new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed); } base.Dispose( disposing ); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.browseList = new System.Windows.Forms.ListBox(); this.typeBox = new System.Windows.Forms.ComboBox(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label(); this.nameField = new System.Windows.Forms.TextBox(); this.typeField = new System.Windows.Forms.TextBox(); this.domainField = new System.Windows.Forms.TextBox(); this.hostField = new System.Windows.Forms.TextBox(); this.portField = new System.Windows.Forms.TextBox(); this.label5 = new System.Windows.Forms.Label(); this.serviceTextField = new System.Windows.Forms.ListBox(); this.SuspendLayout(); // // browseList // this.browseList.Location = new System.Drawing.Point(8, 48); this.browseList.Name = "browseList"; this.browseList.Size = new System.Drawing.Size(488, 147); this.browseList.TabIndex = 0; this.browseList.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); // // typeBox // this.typeBox.Items.AddRange(new object[] { "_accessone._tcp", "_accountedge._tcp", "_actionitems._tcp", "_addressbook._tcp", "_aecoretech._tcp", "_afpovertcp._tcp", "_airport._tcp", "_animolmd._tcp", "_animobserver._tcp", "_apple-sasl._tcp", "_aquamon._tcp", "_async._tcp", "_auth._tcp", "_beep._tcp", "_bfagent._tcp", "_bootps._udp", "_bousg._tcp", "_bsqdea._tcp", "_cheat._tcp", "_chess._tcp", "_clipboard._tcp", "_collection._tcp", "_contactserver._tcp", "_cvspserver._tcp", "_cytv._tcp", "_daap._tcp", "_difi._tcp", "_distcc._tcp", "_dossier._tcp", "_dpap._tcp", "_earphoria._tcp", "_ebms._tcp", "_ebreg._tcp", "_ecbyesfsgksc._tcp", "_eheap._tcp", "_embrace._tcp", "_eppc._tcp", "_eventserver._tcp", "_exec._tcp", "_facespan._tcp", "_faxstfx._tcp", "_fish._tcp", "_fjork._tcp", "_fmpro-internal._tcp", "_ftp._tcp", "_ftpcroco._tcp", "_gbs-smp._tcp", "_gbs-stp._tcp", "_grillezvous._tcp", "_h323._tcp", "_http._tcp", "_hotwayd._tcp", "_hydra._tcp", "_ica-networking._tcp", "_ichalkboard._tcp", "_ichat._tcp", "_iconquer._tcp", "_ifolder._tcp", "_ilynx._tcp", "_imap._tcp", "_imidi._tcp", "_ipbroadcaster._tcp", "_ipp._tcp", "_isparx._tcp", "_ispq-vc._tcp", "_ishare._tcp", "_isticky._tcp", "_istorm._tcp", "_iwork._tcp", "_lan2p._tcp", "_ldap._tcp", "_liaison._tcp", "_login._tcp", "_lontalk._tcp", "_lonworks._tcp", "_macfoh-remote._tcp", "_macminder._tcp", "_moneyworks._tcp", "_mp3sushi._tcp", "_mttp._tcp", "_ncbroadcast._tcp", "_ncdirect._tcp", "_ncsyncserver._tcp", "_net-assistant._tcp", "_newton-dock._tcp", "_nfs._udp", "_nssocketport._tcp", "_odabsharing._tcp", "_omni-bookmark._tcp", "_openbase._tcp", "_p2pchat._udp", "_pdl-datastream._tcp", "_poch._tcp", "_pop3._tcp", "_postgresql._tcp", "_presence._tcp", "_printer._tcp", "_ptp._tcp", "_quinn._tcp", "_raop._tcp", "_rce._tcp", "_realplayfavs._tcp", "_riousbprint._tcp", "_rfb._tcp", "_rtsp._tcp", "_safarimenu._tcp", "_sallingclicker._tcp", "_scone._tcp", "_sdsharing._tcp", "_see._tcp", "_seeCard._tcp", "_serendipd._tcp", "_servermgr._tcp", "_shell._tcp", "_shout._tcp", "_shoutcast._tcp", "_soap._tcp", "_spike._tcp", "_spincrisis._tcp", "_spl-itunes._tcp", "_spr-itunes._tcp", "_ssh._tcp", "_ssscreenshare._tcp", "_strateges._tcp", "_sge-exec._tcp", "_sge-qmaster._tcp", "_stickynotes._tcp", "_sxqdea._tcp", "_sybase-tds._tcp", "_teamlist._tcp", "_teleport._udp", "_telnet._tcp", "_tftp._udp", "_ticonnectmgr._tcp", "_tinavigator._tcp", "_tryst._tcp", "_upnp._tcp", "_utest._tcp", "_vue4rendercow._tcp", "_webdav._tcp", "_whamb._tcp", "_wired._tcp", "_workstation._tcp", "_wormhole._tcp", "_workgroup._tcp", "_ws._tcp", "_xserveraid._tcp", "_xsync._tcp", "_xtshapro._tcp" }); this.typeBox.Location = new System.Drawing.Point(8, 16); this.typeBox.Name = "typeBox"; this.typeBox.Size = new System.Drawing.Size(192, 21); this.typeBox.Sorted = true; this.typeBox.TabIndex = 3; this.typeBox.SelectedIndexChanged += new System.EventHandler(this.typeBox_SelectedIndexChanged); // // label1 // this.label1.Location = new System.Drawing.Point(8, 208); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(48, 16); this.label1.TabIndex = 4; this.label1.Text = "Name:"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label2 // this.label2.Location = new System.Drawing.Point(8, 240); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(48, 16); this.label2.TabIndex = 5; this.label2.Text = "Type:"; this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label3 // this.label3.Location = new System.Drawing.Point(8, 272); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(48, 16); this.label3.TabIndex = 6; this.label3.Text = "Domain:"; this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label4 // this.label4.Location = new System.Drawing.Point(8, 304); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(48, 16); this.label4.TabIndex = 7; this.label4.Text = "Host:"; this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // nameField // this.nameField.Location = new System.Drawing.Point(56, 208); this.nameField.Name = "nameField"; this.nameField.ReadOnly = true; this.nameField.Size = new System.Drawing.Size(168, 20); this.nameField.TabIndex = 8; this.nameField.Text = ""; // // typeField // this.typeField.Location = new System.Drawing.Point(56, 240); this.typeField.Name = "typeField"; this.typeField.ReadOnly = true; this.typeField.Size = new System.Drawing.Size(168, 20); this.typeField.TabIndex = 9; this.typeField.Text = ""; // // domainField // this.domainField.Location = new System.Drawing.Point(56, 272); this.domainField.Name = "domainField"; this.domainField.ReadOnly = true; this.domainField.Size = new System.Drawing.Size(168, 20); this.domainField.TabIndex = 10; this.domainField.Text = ""; // // hostField // this.hostField.Location = new System.Drawing.Point(56, 304); this.hostField.Name = "hostField"; this.hostField.ReadOnly = true; this.hostField.Size = new System.Drawing.Size(168, 20); this.hostField.TabIndex = 11; this.hostField.Text = ""; // // portField // this.portField.Location = new System.Drawing.Point(56, 336); this.portField.Name = "portField"; this.portField.ReadOnly = true; this.portField.Size = new System.Drawing.Size(168, 20); this.portField.TabIndex = 12; this.portField.Text = ""; // // label5 // this.label5.Location = new System.Drawing.Point(8, 336); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(48, 16); this.label5.TabIndex = 14; this.label5.Text = "Port:"; this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // serviceTextField // this.serviceTextField.HorizontalScrollbar = true; this.serviceTextField.Location = new System.Drawing.Point(264, 208); this.serviceTextField.Name = "serviceTextField"; this.serviceTextField.Size = new System.Drawing.Size(232, 147); this.serviceTextField.TabIndex = 16; // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(512, 365); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.serviceTextField, this.label5, this.portField, this.hostField, this.domainField, this.typeField, this.nameField, this.label4, this.label3, this.label2, this.label1, this.typeBox, this.browseList}); this.Name = "Form1"; this.Text = "DNSServices Browser"; this.ResumeLayout(false); } #endregion /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.Run(new Form1()); } // // BrowseData // // This class is used to store data associated // with a DNSService.Browse() operation // public class BrowseData { public uint InterfaceIndex; public String Name; public String Type; public String Domain; public int Refs; public override String ToString() { return Name; } public override bool Equals(object other) { bool result = false; if (other != null) { result = (this.Name == other.ToString()); } return result; } public override int GetHashCode() { return Name.GetHashCode(); } }; // // ResolveData // // This class is used to store data associated // with a DNSService.Resolve() operation // public class ResolveData { public uint InterfaceIndex; public String FullName; public String HostName; public int Port; public TXTRecord TxtRecord; public override String ToString() { return FullName; } }; // // Populate() // // Populate this form with data associated with a // DNSService.Resolve() call // public void Populate(BrowseData browseData, ResolveData resolveData) { nameField.Text = browseData.Name; typeField.Text = browseData.Type; domainField.Text = browseData.Domain; hostField.Text = resolveData.HostName; portField.Text = resolveData.Port.ToString(); serviceTextField.Items.Clear(); // // When we print the text record, we're going to assume that every value // is a string. // if (resolveData.TxtRecord != null) { for (uint idx = 0; idx < resolveData.TxtRecord.GetCount(); idx++) { String key; Byte[] bytes; key = resolveData.TxtRecord.GetKeyAtIndex(idx); bytes = (Byte[])resolveData.TxtRecord.GetValueAtIndex(idx); if (key.Length > 0) { String val = ""; if (bytes != null) { val = Encoding.ASCII.GetString(bytes, 0, bytes.Length); } serviceTextField.Items.Add(key + "=" + val); } } } } // // called when the type field changes // private void typeBox_SelectedIndexChanged(object sender, System.EventArgs e) { browseList.Items.Clear(); // // Stop the current browse operation // if (browser != null) { browser.Stop(); } nameField.Text = ""; typeField.Text = ""; domainField.Text = ""; hostField.Text = ""; portField.Text = ""; serviceTextField.Items.Clear(); try { // // Selecting a service type will start a new browse operation. // browser = service.Browse( 0, 0, typeBox.SelectedItem.ToString(), null, eventManager ); } catch { MessageBox.Show("Browse Failed", "Error"); Application.Exit(); } } private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e) { if (resolver != null) { resolver.Stop(); resolver = null; } if (browseList.SelectedItem != null) { try { BrowseData data = (BrowseData) browseList.SelectedItem; // // Clicking on a service instance results in starting a resolve operation // that will call us back with information about the service // resolver = service.Resolve(0, data.InterfaceIndex, data.Name, data.Type, data.Domain, eventManager); } catch { MessageBox.Show("Resolve Failed", "Error"); Application.Exit(); } } } // // ServiceFound // // This call is invoked by the DNSService core. We create // a BrowseData object and invoked the appropriate method // in the GUI thread so we can update the UI // public void ServiceFound ( DNSSDService sref, DNSSDFlags flags, uint ifIndex, String serviceName, String regType, String domain ) { int index = browseList.Items.IndexOf(serviceName); // // Check to see if we've seen this service before. If the machine has multiple // interfaces, we could potentially get called back multiple times for the // same service. Implementing a simple reference counting scheme will address // the problem of the same service showing up more than once in the browse list. // if (index == -1) { BrowseData data = new BrowseData(); data.InterfaceIndex = ifIndex; data.Name = serviceName; data.Type = regType; data.Domain = domain; data.Refs = 1; browseList.Items.Add(data); browseList.Invalidate(); } else { BrowseData data = (BrowseData) browseList.Items[index]; data.Refs++; } } public void ServiceLost ( DNSSDService sref, DNSSDFlags flags, uint ifIndex, String serviceName, String regType, String domain ) { int index = browseList.Items.IndexOf(serviceName); // // See above comment in ServiceFound about reference counting // if (index != -1) { BrowseData data = (BrowseData) browseList.Items[index]; data.Refs--; if (data.Refs == 0) { browseList.Items.Remove(data); browseList.Invalidate(); } } } public void ServiceResolved ( DNSSDService sref, DNSSDFlags flags, uint ifIndex, String fullName, String hostName, ushort port, TXTRecord txtRecord ) { ResolveData data = new ResolveData(); data.InterfaceIndex = ifIndex; data.FullName = fullName; data.HostName = hostName; data.Port = port; data.TxtRecord = txtRecord; // // Don't forget to stop the resolver. This eases the burden on the network // resolver.Stop(); resolver = null; Populate((BrowseData) browseList.SelectedItem, data); } public void OperationFailed ( DNSSDService sref, DNSSDError error ) { MessageBox.Show("Operation failed: error code: " + error, "Error"); } } }