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