]> git.saurik.com Git - apple/mdnsresponder.git/blob - Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs
75bbc93005319f05057b6e20c7d6d591b1607a70
[apple/mdnsresponder.git] / Clients / DNSServiceBrowser.NET / DNSServiceBrowser.cs
1 /*
2 * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22
23 Change History (most recent first):
24
25 $Log: DNSServiceBrowser.cs,v $
26 Revision 1.5 2004/09/21 16:26:58 shersche
27 Check to make sure browse list selected item is not null before resolving
28 Submitted by: prepin@gmail.com
29
30 Revision 1.4 2004/09/13 19:38:17 shersche
31 Changed code to reflect namespace and type changes to dnssd.NET library
32
33 Revision 1.3 2004/09/11 00:38:14 shersche
34 DNSService APIs now assume port in host format. Check for null text record in resolve callback.
35
36 Revision 1.2 2004/07/22 23:15:25 shersche
37 Fix service names for teleport, tftp, and bootps
38
39 Revision 1.1 2004/07/19 07:54:24 shersche
40 Initial revision
41
42
43
44 */
45
46 using System;
47 using System.Drawing;
48 using System.Collections;
49 using System.ComponentModel;
50 using System.Windows.Forms;
51 using System.Data;
52 using System.Text;
53 using Apple.DNSSD;
54
55 namespace DNSServiceBrowser_NET
56 {
57 /// <summary>
58 /// Summary description for Form1.
59 /// </summary>
60 public class Form1 : System.Windows.Forms.Form
61 {
62 private System.Windows.Forms.ComboBox typeBox;
63 private System.Windows.Forms.ListBox browseList;
64 private ServiceRef browser = null;
65 private ServiceRef resolver = null;
66 /// <summary>
67 /// Required designer variable.
68 /// </summary>
69 private System.ComponentModel.Container components = null;
70
71
72 //
73 // These delegates are invoked as a result of DNSService
74 // operation.
75 //
76 delegate void AddServiceCallback(BrowseData data);
77 delegate void RemoveServiceCallback(BrowseData data);
78 delegate void ResolveServiceCallback(ResolveData data);
79
80 AddServiceCallback addServiceCallback;
81 RemoveServiceCallback removeServiceCallback;
82 private System.Windows.Forms.Label label1;
83 private System.Windows.Forms.Label label2;
84 private System.Windows.Forms.Label label3;
85 private System.Windows.Forms.Label label4;
86 private System.Windows.Forms.TextBox nameField;
87 private System.Windows.Forms.TextBox typeField;
88 private System.Windows.Forms.TextBox domainField;
89 private System.Windows.Forms.TextBox hostField;
90 private System.Windows.Forms.TextBox portField;
91 private System.Windows.Forms.Label label5;
92 private System.Windows.Forms.ListBox serviceTextField;
93 ResolveServiceCallback resolveServiceCallback;
94
95 public Form1()
96 {
97 //
98 // Required for Windows Form Designer support
99 //
100 InitializeComponent();
101
102 addServiceCallback = new AddServiceCallback(OnAddService);
103 removeServiceCallback = new RemoveServiceCallback(OnRemoveService);
104 resolveServiceCallback = new ResolveServiceCallback(OnResolveService);
105
106 this.Load += new System.EventHandler(this.Form1_Load);
107 }
108
109 private void Form1_Load(object sender, EventArgs e)
110 {
111 typeBox.SelectedItem = "_spike._tcp";
112 }
113
114 /// <summary>
115 /// Clean up any resources being used.
116 /// </summary>
117 protected override void Dispose( bool disposing )
118 {
119 if( disposing )
120 {
121 if (components != null)
122 {
123 components.Dispose();
124 }
125
126 if (browser != null)
127 {
128 browser.Dispose();
129 }
130 }
131 base.Dispose( disposing );
132 }
133
134 #region Windows Form Designer generated code
135 /// <summary>
136 /// Required method for Designer support - do not modify
137 /// the contents of this method with the code editor.
138 /// </summary>
139 private void InitializeComponent()
140 {
141 this.browseList = new System.Windows.Forms.ListBox();
142 this.typeBox = new System.Windows.Forms.ComboBox();
143 this.label1 = new System.Windows.Forms.Label();
144 this.label2 = new System.Windows.Forms.Label();
145 this.label3 = new System.Windows.Forms.Label();
146 this.label4 = new System.Windows.Forms.Label();
147 this.nameField = new System.Windows.Forms.TextBox();
148 this.typeField = new System.Windows.Forms.TextBox();
149 this.domainField = new System.Windows.Forms.TextBox();
150 this.hostField = new System.Windows.Forms.TextBox();
151 this.portField = new System.Windows.Forms.TextBox();
152 this.label5 = new System.Windows.Forms.Label();
153 this.serviceTextField = new System.Windows.Forms.ListBox();
154 this.SuspendLayout();
155 //
156 // browseList
157 //
158 this.browseList.Location = new System.Drawing.Point(8, 48);
159 this.browseList.Name = "browseList";
160 this.browseList.Size = new System.Drawing.Size(488, 147);
161 this.browseList.TabIndex = 0;
162 this.browseList.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
163 //
164 // typeBox
165 //
166 this.typeBox.Items.AddRange(new object[]
167 {
168 "_accessone._tcp",
169 "_accountedge._tcp",
170 "_actionitems._tcp",
171 "_addressbook._tcp",
172 "_aecoretech._tcp",
173 "_afpovertcp._tcp",
174 "_airport._tcp",
175 "_animolmd._tcp",
176 "_animobserver._tcp",
177 "_apple-sasl._tcp",
178 "_aquamon._tcp",
179 "_async._tcp",
180 "_auth._tcp",
181 "_beep._tcp",
182 "_bfagent._tcp",
183 "_bootps._udp",
184 "_bousg._tcp",
185 "_bsqdea._tcp",
186 "_cheat._tcp",
187 "_chess._tcp",
188 "_clipboard._tcp",
189 "_collection._tcp",
190 "_contactserver._tcp",
191 "_cvspserver._tcp",
192 "_cytv._tcp",
193 "_daap._tcp",
194 "_difi._tcp",
195 "_distcc._tcp",
196 "_dossier._tcp",
197 "_dpap._tcp",
198 "_earphoria._tcp",
199 "_ebms._tcp",
200 "_ebreg._tcp",
201 "_ecbyesfsgksc._tcp",
202 "_eheap._tcp",
203 "_embrace._tcp",
204 "_eppc._tcp",
205 "_eventserver._tcp",
206 "_exec._tcp",
207 "_facespan._tcp",
208 "_faxstfx._tcp",
209 "_fish._tcp",
210 "_fjork._tcp",
211 "_fmpro-internal._tcp",
212 "_ftp._tcp",
213 "_ftpcroco._tcp",
214 "_gbs-smp._tcp",
215 "_gbs-stp._tcp",
216 "_grillezvous._tcp",
217 "_h323._tcp",
218 "_http._tcp",
219 "_hotwayd._tcp",
220 "_hydra._tcp",
221 "_ica-networking._tcp",
222 "_ichalkboard._tcp",
223 "_ichat._tcp",
224 "_iconquer._tcp",
225 "_ifolder._tcp",
226 "_ilynx._tcp",
227 "_imap._tcp",
228 "_imidi._tcp",
229 "_ipbroadcaster._tcp",
230 "_ipp._tcp",
231 "_isparx._tcp",
232 "_ispq-vc._tcp",
233 "_ishare._tcp",
234 "_isticky._tcp",
235 "_istorm._tcp",
236 "_iwork._tcp",
237 "_lan2p._tcp",
238 "_ldap._tcp",
239 "_liaison._tcp",
240 "_login._tcp",
241 "_lontalk._tcp",
242 "_lonworks._tcp",
243 "_macfoh-remote._tcp",
244 "_macminder._tcp",
245 "_moneyworks._tcp",
246 "_mp3sushi._tcp",
247 "_mttp._tcp",
248 "_ncbroadcast._tcp",
249 "_ncdirect._tcp",
250 "_ncsyncserver._tcp",
251 "_net-assistant._tcp",
252 "_newton-dock._tcp",
253 "_nfs._udp",
254 "_nssocketport._tcp",
255 "_odabsharing._tcp",
256 "_omni-bookmark._tcp",
257 "_openbase._tcp",
258 "_p2pchat._udp",
259 "_pdl-datastream._tcp",
260 "_poch._tcp",
261 "_pop3._tcp",
262 "_postgresql._tcp",
263 "_presence._tcp",
264 "_printer._tcp",
265 "_ptp._tcp",
266 "_quinn._tcp",
267 "_raop._tcp",
268 "_rce._tcp",
269 "_realplayfavs._tcp",
270 "_rendezvouspong._tcp",
271 "_riousbprint._tcp",
272 "_rfb._tcp",
273 "_rtsp._tcp",
274 "_safarimenu._tcp",
275 "_sallingclicker._tcp",
276 "_scone._tcp",
277 "_sdsharing._tcp",
278 "_see._tcp",
279 "_seeCard._tcp",
280 "_serendipd._tcp",
281 "_servermgr._tcp",
282 "_shell._tcp",
283 "_shout._tcp",
284 "_shoutcast._tcp",
285 "_soap._tcp",
286 "_spike._tcp",
287 "_spincrisis._tcp",
288 "_spl-itunes._tcp",
289 "_spr-itunes._tcp",
290 "_ssh._tcp",
291 "_ssscreenshare._tcp",
292 "_strateges._tcp",
293 "_sge-exec._tcp",
294 "_sge-qmaster._tcp",
295 "_stickynotes._tcp",
296 "_sxqdea._tcp",
297 "_sybase-tds._tcp",
298 "_teamlist._tcp",
299 "_teleport._udp",
300 "_telnet._tcp",
301 "_tftp._udp",
302 "_ticonnectmgr._tcp",
303 "_tinavigator._tcp",
304 "_tryst._tcp",
305 "_upnp._tcp",
306 "_utest._tcp",
307 "_vue4rendercow._tcp",
308 "_webdav._tcp",
309 "_whamb._tcp",
310 "_wired._tcp",
311 "_workstation._tcp",
312 "_wormhole._tcp",
313 "_workgroup._tcp",
314 "_ws._tcp",
315 "_xserveraid._tcp",
316 "_xsync._tcp",
317 "_xtshapro._tcp"
318 });
319
320 this.typeBox.Location = new System.Drawing.Point(8, 16);
321 this.typeBox.Name = "typeBox";
322 this.typeBox.Size = new System.Drawing.Size(192, 21);
323 this.typeBox.Sorted = true;
324 this.typeBox.TabIndex = 3;
325 this.typeBox.SelectedIndexChanged += new System.EventHandler(this.typeBox_SelectedIndexChanged);
326 //
327 // label1
328 //
329 this.label1.Location = new System.Drawing.Point(8, 208);
330 this.label1.Name = "label1";
331 this.label1.Size = new System.Drawing.Size(48, 16);
332 this.label1.TabIndex = 4;
333 this.label1.Text = "Name:";
334 this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
335 //
336 // label2
337 //
338 this.label2.Location = new System.Drawing.Point(8, 240);
339 this.label2.Name = "label2";
340 this.label2.Size = new System.Drawing.Size(48, 16);
341 this.label2.TabIndex = 5;
342 this.label2.Text = "Type:";
343 this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
344 //
345 // label3
346 //
347 this.label3.Location = new System.Drawing.Point(8, 272);
348 this.label3.Name = "label3";
349 this.label3.Size = new System.Drawing.Size(48, 16);
350 this.label3.TabIndex = 6;
351 this.label3.Text = "Domain:";
352 this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
353 //
354 // label4
355 //
356 this.label4.Location = new System.Drawing.Point(8, 304);
357 this.label4.Name = "label4";
358 this.label4.Size = new System.Drawing.Size(48, 16);
359 this.label4.TabIndex = 7;
360 this.label4.Text = "Host:";
361 this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
362 //
363 // nameField
364 //
365 this.nameField.Location = new System.Drawing.Point(56, 208);
366 this.nameField.Name = "nameField";
367 this.nameField.ReadOnly = true;
368 this.nameField.Size = new System.Drawing.Size(168, 20);
369 this.nameField.TabIndex = 8;
370 this.nameField.Text = "";
371 //
372 // typeField
373 //
374 this.typeField.Location = new System.Drawing.Point(56, 240);
375 this.typeField.Name = "typeField";
376 this.typeField.ReadOnly = true;
377 this.typeField.Size = new System.Drawing.Size(168, 20);
378 this.typeField.TabIndex = 9;
379 this.typeField.Text = "";
380 //
381 // domainField
382 //
383 this.domainField.Location = new System.Drawing.Point(56, 272);
384 this.domainField.Name = "domainField";
385 this.domainField.ReadOnly = true;
386 this.domainField.Size = new System.Drawing.Size(168, 20);
387 this.domainField.TabIndex = 10;
388 this.domainField.Text = "";
389 //
390 // hostField
391 //
392 this.hostField.Location = new System.Drawing.Point(56, 304);
393 this.hostField.Name = "hostField";
394 this.hostField.ReadOnly = true;
395 this.hostField.Size = new System.Drawing.Size(168, 20);
396 this.hostField.TabIndex = 11;
397 this.hostField.Text = "";
398
399 //
400 // portField
401 //
402 this.portField.Location = new System.Drawing.Point(56, 336);
403 this.portField.Name = "portField";
404 this.portField.ReadOnly = true;
405 this.portField.Size = new System.Drawing.Size(168, 20);
406 this.portField.TabIndex = 12;
407 this.portField.Text = "";
408 //
409 // label5
410 //
411 this.label5.Location = new System.Drawing.Point(8, 336);
412 this.label5.Name = "label5";
413 this.label5.Size = new System.Drawing.Size(48, 16);
414 this.label5.TabIndex = 14;
415 this.label5.Text = "Port:";
416 this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
417 //
418 // serviceTextField
419 //
420 this.serviceTextField.HorizontalScrollbar = true;
421 this.serviceTextField.Location = new System.Drawing.Point(264, 208);
422 this.serviceTextField.Name = "serviceTextField";
423 this.serviceTextField.Size = new System.Drawing.Size(232, 147);
424 this.serviceTextField.TabIndex = 16;
425 //
426 // Form1
427 //
428 this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
429 this.ClientSize = new System.Drawing.Size(512, 365);
430 this.Controls.AddRange(new System.Windows.Forms.Control[] {
431 this.serviceTextField,
432 this.label5,
433 this.portField,
434 this.hostField,
435 this.domainField,
436 this.typeField,
437 this.nameField,
438 this.label4,
439 this.label3,
440 this.label2,
441 this.label1,
442 this.typeBox,
443 this.browseList});
444 this.Name = "Form1";
445 this.Text = "DNSServices Browser";
446 this.ResumeLayout(false);
447
448 }
449 #endregion
450
451 /// <summary>
452 /// The main entry point for the application.
453 /// </summary>
454 [STAThread]
455 static void Main()
456 {
457 Application.Run(new Form1());
458 }
459 //
460 // BrowseData
461 //
462 // This class is used to store data associated
463 // with a DNSService.Browse() operation
464 //
465 public class BrowseData
466 {
467 public int InterfaceIndex;
468 public String Name;
469 public String Type;
470 public String Domain;
471
472 public override String
473 ToString()
474 {
475 return Name;
476 }
477
478 public override bool
479 Equals(object other)
480 {
481 bool result = false;
482
483 if (other != null)
484 {
485 if ((object) this == other)
486 {
487 result = true;
488 }
489 else if (other is BrowseData)
490 {
491 BrowseData otherBrowseData = (BrowseData) other;
492
493 result = (this.Name == otherBrowseData.Name);
494 }
495 }
496
497 return result;
498 }
499
500 public override int
501 GetHashCode()
502 {
503 return Name.GetHashCode();
504 }
505 };
506
507
508 //
509 // ResolveData
510 //
511 // This class is used to store data associated
512 // with a DNSService.Resolve() operation
513 //
514 public class ResolveData
515 {
516 public int InterfaceIndex;
517 public String FullName;
518 public String HostName;
519 public int Port;
520 public Byte[] TxtRecord;
521
522 public override String
523 ToString()
524 {
525 return FullName;
526 }
527 };
528
529 //
530 // Populate()
531 //
532 // Populate this form with data associated with a
533 // DNSService.Resolve() call
534 //
535 public void
536 Populate(BrowseData browseData, ResolveData resolveData)
537 {
538 nameField.Text = browseData.Name;
539 typeField.Text = browseData.Type;
540 domainField.Text = browseData.Domain;
541 hostField.Text = resolveData.HostName;
542 portField.Text = resolveData.Port.ToString();
543
544 serviceTextField.Items.Clear();
545
546 if (resolveData.TxtRecord != null)
547 {
548 for (int idx = 0; idx < TextRecord.GetCount(resolveData.TxtRecord); idx++)
549 {
550 String key;
551 Byte[] bytes;
552
553 bytes = TextRecord.GetItemAtIndex(resolveData.TxtRecord, idx, out key);
554
555 if (key.Length > 0)
556 {
557 String val = "";
558
559 if (bytes != null)
560 {
561 val = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
562 }
563
564 serviceTextField.Items.Add(key + "=" + val);
565 }
566 }
567 }
568 }
569
570 //
571 // called when the type field changes
572 //
573 private void typeBox_SelectedIndexChanged(object sender, System.EventArgs e)
574 {
575 browseList.Items.Clear();
576
577 if (browser != null)
578 {
579 browser.Dispose();
580 }
581
582 nameField.Text = "";
583 typeField.Text = "";
584 domainField.Text = "";
585 hostField.Text = "";
586 portField.Text = "";
587 serviceTextField.Items.Clear();
588
589 try
590 {
591 browser = DNSService.Browse(0, 0, typeBox.SelectedItem.ToString(), null, new DNSService.BrowseReply(OnBrowseReply));
592 }
593 catch
594 {
595 MessageBox.Show("Browse Failed", "Error");
596 Application.Exit();
597 }
598 }
599
600 private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
601 {
602 if (resolver != null)
603 {
604 resolver.Dispose();
605 }
606
607 if (browseList.SelectedItem != null)
608 {
609 try
610 {
611 BrowseData data = (BrowseData) browseList.SelectedItem;
612
613 resolver = DNSService.Resolve(0, 0, data.Name, data.Type, data.Domain, new DNSService.ResolveReply(OnResolveReply));
614 }
615 catch
616 {
617 MessageBox.Show("Resolve Failed", "Error");
618 Application.Exit();
619 }
620 }
621 }
622
623 //
624 // OnAddService
625 //
626 // This method is "Invoked" by OnBrowseReply. This call
627 // executes in the context of the main thread
628 //
629 private void OnAddService
630 (
631 BrowseData data
632 )
633 {
634 browseList.Items.Add(data);
635 browseList.Invalidate();
636 }
637
638 //
639 // OnRemoveService
640 //
641 // This method is "Invoked" by OnBrowseReply. This call
642 // executes in the context of the main thread
643 //
644 private void OnRemoveService
645 (
646 BrowseData data
647 )
648 {
649 browseList.Items.Remove(data);
650 browseList.Invalidate();
651 }
652
653 //
654 // OnResolveService
655 //
656 // This method is "Invoked" by OnResolveReply. This call
657 // executes in the context of the main thread
658 //
659 private void OnResolveService
660 (
661 ResolveData data
662 )
663 {
664 resolver.Dispose();
665 resolver = null;
666
667 Populate((BrowseData) browseList.SelectedItem, data);
668 }
669
670 //
671 // OnBrowseReply
672 //
673 // This call is invoked by the DNSService core. It is
674 // executed in the context of a worker thread, not the
675 // main (GUI) thread. We create a BrowseData object
676 // and invoked the appropriate method in the GUI thread
677 // so we can update the UI
678 //
679 private void OnBrowseReply
680 (
681 ServiceRef sdRef,
682 ServiceFlags flags,
683 int interfaceIndex,
684 ErrorCode errorCode,
685 String name,
686 String type,
687 String domain
688 )
689 {
690 if (errorCode == ErrorCode.NoError)
691 {
692 BrowseData data = new BrowseData();
693
694 data.InterfaceIndex = interfaceIndex;
695 data.Name = name;
696 data.Type = type;
697 data.Domain = domain;
698
699 if ((flags & ServiceFlags.Add) != 0)
700 {
701 Invoke(addServiceCallback, new Object[]{data});
702
703 }
704 else if ((flags == 0) || ((flags & ServiceFlags.MoreComing) != 0))
705 {
706 Invoke(removeServiceCallback, new Object[]{data});
707 }
708 }
709 else
710 {
711 MessageBox.Show("OnBrowseReply returned an error code: " + errorCode, "Error");
712 }
713 }
714
715 private void OnResolveReply
716 (
717 ServiceRef sdRef,
718 ServiceFlags flags,
719 int interfaceIndex,
720 ErrorCode errorCode,
721 String fullName,
722 String hostName,
723 int port,
724 Byte[] txtRecord
725 )
726 {
727 if (errorCode == ErrorCode.NoError)
728 {
729 ResolveData data = new ResolveData();
730
731 data.InterfaceIndex = interfaceIndex;
732 data.FullName = fullName;
733 data.HostName = hostName;
734 data.Port = port;
735 data.TxtRecord = txtRecord;
736
737 Invoke(resolveServiceCallback, new Object[]{data});
738 }
739 else
740 {
741 MessageBox.Show("OnResolveReply returned an error code: " + errorCode, "Error");
742 }
743 }
744 }
745 }