]> git.saurik.com Git - apple/mdnsresponder.git/blob - Clients/SimpleChat.NET/SimpleChat.cs
mDNSResponder-212.1.tar.gz
[apple/mdnsresponder.git] / Clients / SimpleChat.NET / SimpleChat.cs
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16
17 Change History (most recent first):
18
19 $Log: SimpleChat.cs,v $
20 Revision 1.7 2009/06/04 20:21:19 herscher
21 <rdar://problem/3948252> Update code to work with DNSSD COM component
22
23 Revision 1.6 2006/08/14 23:24:21 cheshire
24 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
25
26 Revision 1.5 2004/09/13 19:37:42 shersche
27 Change code to reflect namespace and type changes to dnssd.NET library
28
29 Revision 1.4 2004/09/11 05:42:56 shersche
30 don't reset SelectedIndex in OnRemove
31
32 Revision 1.3 2004/09/11 00:38:58 shersche
33 DNSService APIs now expect port in host format
34
35 Revision 1.2 2004/07/19 22:08:53 shersche
36 Fixed rdata->int conversion problem in QueryRecordReply
37
38 Revision 1.1 2004/07/19 07:57:08 shersche
39 Initial revision
40
41
42
43 */
44
45 using System;
46 using System.Drawing;
47 using System.Collections;
48 using System.ComponentModel;
49 using System.Windows.Forms;
50 using System.Net;
51 using System.Net.Sockets;
52 using System.Data;
53 using System.Text;
54 using Bonjour;
55
56 namespace SimpleChat.NET
57 {
58 /// <summary>
59 /// Summary description for Form1.
60 /// </summary>
61 ///
62
63 public class SimpleChat : System.Windows.Forms.Form
64 {
65 private System.Windows.Forms.ComboBox comboBox1;
66 private System.Windows.Forms.TextBox textBox2;
67 private System.Windows.Forms.Button button1;
68 private System.Windows.Forms.Label label1;
69 private Bonjour.DNSSDEventManager m_eventManager = null;
70 private Bonjour.DNSSDService m_service = null;
71 private Bonjour.DNSSDService m_registrar = null;
72 private Bonjour.DNSSDService m_browser = null;
73 private Bonjour.DNSSDService m_resolver = null;
74 private String m_name;
75 private Socket m_socket = null;
76 private const int BUFFER_SIZE = 1024;
77 public byte[] m_buffer = new byte[BUFFER_SIZE];
78 public bool m_complete = false;
79 public StringBuilder m_sb = new StringBuilder();
80 delegate void ReadMessageCallback(String data);
81 ReadMessageCallback m_readMessageCallback;
82 /// <summary>
83 /// Required designer variable.
84 /// </summary>
85 private System.ComponentModel.Container components = null;
86 private System.Windows.Forms.RichTextBox richTextBox1;
87
88 // ServiceRegistered
89 //
90 // Called by DNSServices core as a result of Register()
91 // call
92 //
93
94 public void
95 ServiceRegistered
96 (
97 DNSSDService service,
98 DNSSDFlags flags,
99 String name,
100 String regType,
101 String domain
102 )
103 {
104 m_name = name;
105
106 try
107 {
108 m_browser = m_service.Browse(0, 0, "_p2pchat._udp", null, m_eventManager);
109 }
110 catch
111 {
112 MessageBox.Show("Browse Failed", "Error");
113 Application.Exit();
114 }
115 }
116
117 //
118 // ServiceFound
119 //
120 // Called by DNSServices core as a result of a Browse call
121 //
122
123 public void
124 ServiceFound
125 (
126 DNSSDService sref,
127 DNSSDFlags flags,
128 uint ifIndex,
129 String serviceName,
130 String regType,
131 String domain
132 )
133 {
134 if (serviceName != m_name)
135 {
136 PeerData peer = new PeerData();
137
138 peer.InterfaceIndex = ifIndex;
139 peer.Name = serviceName;
140 peer.Type = regType;
141 peer.Domain = domain;
142 peer.Address = null;
143
144 comboBox1.Items.Add(peer);
145
146 if (comboBox1.Items.Count == 1)
147 {
148 comboBox1.SelectedIndex = 0;
149 }
150 }
151 }
152
153 //
154 // ServiceLost
155 //
156 // Called by DNSServices core as a result of a Browse call
157 //
158
159 public void
160 ServiceLost
161 (
162 DNSSDService sref,
163 DNSSDFlags flags,
164 uint ifIndex,
165 String serviceName,
166 String regType,
167 String domain
168 )
169 {
170 PeerData peer = new PeerData();
171
172 peer.InterfaceIndex = ifIndex;
173 peer.Name = serviceName;
174 peer.Type = regType;
175 peer.Domain = domain;
176 peer.Address = null;
177
178 comboBox1.Items.Remove(peer);
179 }
180
181 //
182 // ServiceResolved
183 //
184 // Called by DNSServices core as a result of DNSService.Resolve()
185 // call
186 //
187
188 public void
189 ServiceResolved
190 (
191 DNSSDService sref,
192 DNSSDFlags flags,
193 uint ifIndex,
194 String fullName,
195 String hostName,
196 ushort port,
197 TXTRecord txtRecord
198 )
199 {
200 m_resolver.Stop();
201 m_resolver = null;
202
203 PeerData peer = (PeerData)comboBox1.SelectedItem;
204
205 peer.Port = port;
206
207 try
208 {
209 m_resolver = m_service.QueryRecord(0, ifIndex, hostName, DNSSDRRType.kDNSSDType_A, DNSSDRRClass.kDNSSDClass_IN, m_eventManager );
210 }
211 catch
212 {
213 MessageBox.Show("QueryRecord Failed", "Error");
214 Application.Exit();
215 }
216 }
217
218 //
219 // QueryAnswered
220 //
221 // Called by DNSServices core as a result of DNSService.QueryRecord()
222 // call
223 //
224
225 public void
226 QueryAnswered
227 (
228 DNSSDService service,
229 DNSSDFlags flags,
230 uint ifIndex,
231 String fullName,
232 DNSSDRRType rrtype,
233 DNSSDRRClass rrclass,
234 Object rdata,
235 uint ttl
236 )
237 {
238 m_resolver.Stop();
239 m_resolver = null;
240
241 PeerData peer = (PeerData) comboBox1.SelectedItem;
242
243 uint bits = BitConverter.ToUInt32( (Byte[])rdata, 0);
244 System.Net.IPAddress address = new System.Net.IPAddress(bits);
245
246 peer.Address = address;
247 }
248
249 public void
250 OperationFailed
251 (
252 DNSSDService service,
253 DNSSDError error
254 )
255 {
256 MessageBox.Show("Operation returned an error code " + error, "Error");
257 }
258
259 //
260 // OnReadMessage
261 //
262 // Called when there is data to be read on a socket
263 //
264 // This is called (indirectly) from OnReadSocket()
265 //
266 private void
267 OnReadMessage
268 (
269 String msg
270 )
271 {
272 int rgb = 0;
273
274 for (int i = 0; i < msg.Length && msg[i] != ':'; i++)
275 {
276 rgb = rgb ^ ((int)msg[i] << (i % 3 + 2) * 8);
277 }
278
279 Color color = Color.FromArgb(rgb & 0x007F7FFF);
280 richTextBox1.SelectionColor = color;
281 richTextBox1.AppendText(msg + Environment.NewLine);
282 }
283
284 //
285 // OnReadSocket
286 //
287 // Called by the .NET core when there is data to be read on a socket
288 //
289 // This is called from a worker thread by the .NET core
290 //
291 private void
292 OnReadSocket
293 (
294 IAsyncResult ar
295 )
296 {
297 try
298 {
299 int read = m_socket.EndReceive(ar);
300
301 if (read > 0)
302 {
303 String msg = Encoding.UTF8.GetString(m_buffer, 0, read);
304 Invoke(m_readMessageCallback, new Object[]{msg});
305 }
306
307 m_socket.BeginReceive(m_buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(OnReadSocket), this);
308 }
309 catch
310 {
311 }
312 }
313
314
315 public SimpleChat()
316 {
317 //
318 // Required for Windows Form Designer support
319 //
320 InitializeComponent();
321
322 try
323 {
324 m_service = new DNSSDService();
325 }
326 catch
327 {
328 MessageBox.Show("Bonjour Service is not available", "Error");
329 Application.Exit();
330 }
331
332 m_eventManager = new DNSSDEventManager();
333 m_eventManager.ServiceRegistered += new _IDNSSDEvents_ServiceRegisteredEventHandler(this.ServiceRegistered);
334 m_eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
335 m_eventManager.ServiceLost += new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
336 m_eventManager.ServiceResolved += new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
337 m_eventManager.QueryRecordAnswered += new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);
338 m_eventManager.OperationFailed += new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
339
340 m_readMessageCallback = new ReadMessageCallback(OnReadMessage);
341
342 this.Load += new System.EventHandler(this.Form1_Load);
343
344 this.AcceptButton = button1;
345 }
346
347 /// <summary>
348 /// Clean up any resources being used.
349 /// </summary>
350 protected override void
351 Dispose( bool disposing )
352 {
353 if( disposing )
354 {
355 if (components != null)
356 {
357 components.Dispose();
358 }
359
360 if (m_registrar != null)
361 {
362 m_registrar.Stop();
363 }
364
365 if (m_browser != null)
366 {
367 m_browser.Stop();
368 }
369
370 if (m_resolver != null)
371 {
372 m_resolver.Stop();
373 }
374
375 m_eventManager.ServiceFound -= new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
376 m_eventManager.ServiceLost -= new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
377 m_eventManager.ServiceResolved -= new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
378 m_eventManager.QueryRecordAnswered -= new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);
379 m_eventManager.OperationFailed -= new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
380 }
381 base.Dispose( disposing );
382 }
383
384 #region Windows Form Designer generated code
385 /// <summary>
386 /// Required method for Designer support - do not modify
387 /// the contents of this method with the code editor.
388 /// </summary>
389 private void InitializeComponent()
390 {
391 this.comboBox1 = new System.Windows.Forms.ComboBox();
392 this.textBox2 = new System.Windows.Forms.TextBox();
393 this.button1 = new System.Windows.Forms.Button();
394 this.label1 = new System.Windows.Forms.Label();
395 this.richTextBox1 = new System.Windows.Forms.RichTextBox();
396 this.SuspendLayout();
397 //
398 // comboBox1
399 //
400 this.comboBox1.Anchor = ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
401 | System.Windows.Forms.AnchorStyles.Right);
402 this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
403 this.comboBox1.Location = new System.Drawing.Point(59, 208);
404 this.comboBox1.Name = "comboBox1";
405 this.comboBox1.Size = new System.Drawing.Size(224, 21);
406 this.comboBox1.Sorted = true;
407 this.comboBox1.TabIndex = 5;
408 this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
409 //
410 // textBox2
411 //
412 this.textBox2.Anchor = ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
413 | System.Windows.Forms.AnchorStyles.Right);
414 this.textBox2.Location = new System.Drawing.Point(8, 248);
415 this.textBox2.Name = "textBox2";
416 this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Horizontal;
417 this.textBox2.Size = new System.Drawing.Size(192, 20);
418 this.textBox2.TabIndex = 2;
419 this.textBox2.Text = "";
420 this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged);
421 //
422 // button1
423 //
424 this.button1.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right);
425 this.button1.Enabled = false;
426 this.button1.Location = new System.Drawing.Point(208, 248);
427 this.button1.Name = "button1";
428 this.button1.TabIndex = 3;
429 this.button1.Text = "Send";
430 this.button1.Click += new System.EventHandler(this.button1_Click);
431 //
432 // label1
433 //
434 this.label1.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left);
435 this.label1.Location = new System.Drawing.Point(8, 210);
436 this.label1.Name = "label1";
437 this.label1.Size = new System.Drawing.Size(48, 16);
438 this.label1.TabIndex = 4;
439 this.label1.Text = "Talk To:";
440 //
441 // richTextBox1
442 //
443 this.richTextBox1.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
444 | System.Windows.Forms.AnchorStyles.Left)
445 | System.Windows.Forms.AnchorStyles.Right);
446 this.richTextBox1.Location = new System.Drawing.Point(8, 8);
447 this.richTextBox1.Name = "richTextBox1";
448 this.richTextBox1.ReadOnly = true;
449 this.richTextBox1.Size = new System.Drawing.Size(272, 184);
450 this.richTextBox1.TabIndex = 1;
451 this.richTextBox1.Text = "";
452 //
453 // Form1
454 //
455 this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
456 this.ClientSize = new System.Drawing.Size(292, 273);
457 this.Controls.AddRange(new System.Windows.Forms.Control[] {
458 this.richTextBox1,
459 this.label1,
460 this.button1,
461 this.textBox2,
462 this.comboBox1});
463 this.Name = "Form1";
464 this.Text = "SimpleChat.NET";
465 this.ResumeLayout(false);
466
467 }
468 #endregion
469
470 private void Form1_Load(object sender, EventArgs e)
471 {
472 IPEndPoint localEP = new IPEndPoint(System.Net.IPAddress.Any, 0);
473
474 //
475 // create the socket and bind to INADDR_ANY
476 //
477 m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
478 m_socket.Bind(localEP);
479 localEP = (IPEndPoint) m_socket.LocalEndPoint;
480
481 //
482 // start asynchronous read
483 //
484 m_socket.BeginReceive(m_buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(this.OnReadSocket), this);
485
486 try
487 {
488 //
489 // start the register and browse operations
490 //
491 m_registrar = m_service.Register( 0, 0, System.Environment.UserName, "_p2pchat._udp", null, null, ( ushort ) localEP.Port, null, m_eventManager );
492 }
493 catch
494 {
495 MessageBox.Show("Bonjour service is not available", "Error");
496 Application.Exit();
497 }
498 }
499
500 /// <summary>
501 /// The main entry point for the application.
502 /// </summary>
503 [STAThread]
504 static void Main()
505 {
506 Application.Run(new SimpleChat());
507 }
508
509 //
510 // send the message to a peer
511 //
512 private void button1_Click(object sender, System.EventArgs e)
513 {
514 PeerData peer = (PeerData) comboBox1.SelectedItem;
515
516 String message = m_name + ": " + textBox2.Text;
517
518 Byte[] bytes = Encoding.UTF8.GetBytes(message);
519
520 IPEndPoint endPoint = new IPEndPoint( peer.Address, peer.Port );
521
522 m_socket.SendTo(bytes, endPoint);
523
524 richTextBox1.SelectionColor = Color.Black;
525
526 richTextBox1.AppendText(textBox2.Text + "\n");
527
528 textBox2.Text = "";
529 }
530
531 //
532 // called when typing in message box
533 //
534 private void textBox2_TextChanged(object sender, System.EventArgs e)
535 {
536 PeerData peer = (PeerData) comboBox1.SelectedItem;
537 button1.Enabled = ((peer.Address != null) && (textBox2.Text.Length > 0));
538 }
539
540 //
541 // called when peer target changes
542 //
543 /// <summary>
544 /// </summary>
545 /// <param name="sender"></param>
546 /// <param name="e"></param>
547 private void comboBox1_SelectedIndexChanged(object sender, System.EventArgs e)
548 {
549 PeerData peer = (PeerData) comboBox1.SelectedItem;
550
551 try
552 {
553 m_resolver = m_service.Resolve(0, peer.InterfaceIndex, peer.Name, peer.Type, peer.Domain, m_eventManager);
554 }
555 catch
556 {
557 MessageBox.Show("Unable to Resolve service", "Error");
558 Application.Exit();
559 }
560 }
561 }
562
563 //
564 // PeerData
565 //
566 // Holds onto the information associated with a peer on the network
567 //
568 public class PeerData
569 {
570 public uint InterfaceIndex;
571 public String Name;
572 public String Type;
573 public String Domain;
574 public IPAddress Address;
575 public int Port;
576
577 public override String
578 ToString()
579 {
580 return Name;
581 }
582
583 public override bool
584 Equals(object other)
585 {
586 bool result = false;
587
588 if (other != null)
589 {
590 if ((object)this == other)
591 {
592 result = true;
593 }
594 else if (other is PeerData)
595 {
596 PeerData otherPeerData = (PeerData)other;
597
598 result = (this.Name == otherPeerData.Name);
599 }
600 }
601
602 return result;
603 }
604
605 public override int
606 GetHashCode()
607 {
608 return Name.GetHashCode();
609 }
610 };
611 }