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