X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/blobdiff_plain/8e92c31c9a45a66732f5bc7afbc9f5596c17e91d..7f0064bd55e3fa98568d2c359429ff8a38b23a6c:/Clients/SimpleChat.NET/SimpleChat.cs
diff --git a/Clients/SimpleChat.NET/SimpleChat.cs b/Clients/SimpleChat.NET/SimpleChat.cs
new file mode 100755
index 0000000..fb841f2
--- /dev/null
+++ b/Clients/SimpleChat.NET/SimpleChat.cs
@@ -0,0 +1,757 @@
+/*
+ * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+
+ Change History (most recent first):
+
+$Log: SimpleChat.cs,v $
+Revision 1.5 2004/09/13 19:37:42 shersche
+Change code to reflect namespace and type changes to dnssd.NET library
+
+Revision 1.4 2004/09/11 05:42:56 shersche
+don't reset SelectedIndex in OnRemove
+
+Revision 1.3 2004/09/11 00:38:58 shersche
+DNSService APIs now expect port in host format
+
+Revision 1.2 2004/07/19 22:08:53 shersche
+Fixed rdata->int conversion problem in QueryRecordReply
+
+Revision 1.1 2004/07/19 07:57:08 shersche
+Initial revision
+
+
+
+*/
+
+using System;
+using System.Drawing;
+using System.Collections;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Net;
+using System.Net.Sockets;
+using System.Data;
+using System.Text;
+using Apple.DNSSD;
+
+namespace SimpleChat.NET
+{
+ ///
+ /// Summary description for Form1.
+ ///
+ ///
+
+ //
+ // PeerData
+ //
+ // Holds onto the information associated with a peer on the network
+ //
+ public class PeerData
+ {
+ public int InterfaceIndex;
+ public String Name;
+ public String Type;
+ public String Domain;
+ public IPAddress Address;
+ public int Port;
+
+ public override String
+ ToString()
+ {
+ return Name;
+ }
+
+ public override bool
+ Equals(object other)
+ {
+ bool result = false;
+
+ if (other != null)
+ {
+ if ((object) this == other)
+ {
+ result = true;
+ }
+ else if (other is PeerData)
+ {
+ PeerData otherPeerData = (PeerData) other;
+
+ result = (this.Name == otherPeerData.Name);
+ }
+ }
+
+ return result;
+ }
+
+ public override int
+ GetHashCode()
+ {
+ return Name.GetHashCode();
+ }
+ };
+
+ //
+ // ResolveData
+ //
+ // Holds onto the information associated with the resolution
+ // of a DNSService
+ //
+ public class ResolveData
+ {
+ public int InterfaceIndex;
+ public String FullName;
+ public String HostName;
+ public int Port;
+ public Byte[] TxtRecord;
+
+ public override String
+ ToString()
+ {
+ return FullName;
+ }
+ };
+
+
+ //
+ // SocketStateObject
+ //
+ // Holds onto the data associated with an asynchronous
+ // socket operation
+ //
+ class SocketStateObject
+ {
+ public const int BUFFER_SIZE = 1024;
+ private Socket m_socket;
+ public byte[] m_buffer;
+ public bool m_complete;
+ public StringBuilder m_sb = new StringBuilder();
+
+ public SocketStateObject(Socket socket)
+ {
+ m_buffer = new byte[BUFFER_SIZE];
+ m_complete = false;
+ m_socket = socket;
+ }
+
+ public Socket
+ WorkSocket
+ {
+ get
+ {
+ return m_socket;
+ }
+ }
+ }
+ public class Form1 : System.Windows.Forms.Form
+ {
+ private System.Windows.Forms.ComboBox comboBox1;
+ private System.Windows.Forms.TextBox textBox2;
+ private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.Label label1;
+ private ServiceRef registrar = null;
+ private ServiceRef browser = null;
+ private ServiceRef resolver = null;
+ private String myName;
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.Container components = null;
+
+ //
+ // These all of our callbacks. These are invoked in the context
+ // of the main (GUI) thread. The DNSService callbacks Invoke()
+ // them
+ delegate void RegisterServiceCallback(String name);
+ delegate void AddPeerCallback(PeerData data);
+ delegate void RemovePeerCallback(PeerData data);
+ delegate void ResolveServiceCallback(ResolveData data);
+ delegate void ResolveAddressCallback(System.Net.IPAddress address);
+ delegate void ReadMessageCallback(String data);
+
+ RegisterServiceCallback registerServiceCallback;
+ AddPeerCallback addPeerCallback;
+ RemovePeerCallback removePeerCallback;
+ ResolveServiceCallback resolveServiceCallback;
+ ResolveAddressCallback resolveAddressCallback;
+ ReadMessageCallback readMessageCallback;
+ private System.Windows.Forms.RichTextBox richTextBox1;
+
+ //
+ // The socket that we will be reading data from
+ //
+ Socket socket = null;
+
+ //
+ // OnRegisterService
+ //
+ // The name that we are passed might be different than the
+ // name we called Register with. So we hold onto this name
+ // rather than the name we Register with.
+ //
+ // This is called (indirectly) from OnRegisterReply().
+ //
+ private void
+ OnRegisterService
+ (
+ String name
+ )
+ {
+ myName = name;
+ }
+
+ //
+ // OnAddPeer
+ //
+ // Called when DNSServices detects a new P2P Chat peer has
+ // joined.
+ //
+ // This is called (indirectly) from OnBrowseReply()
+ //
+ private void
+ OnAddPeer
+ (
+ PeerData peer
+ )
+ {
+ comboBox1.Items.Add(peer);
+
+ if (comboBox1.Items.Count == 1)
+ {
+ comboBox1.SelectedIndex = 0;
+ }
+ }
+
+ //
+ // OnRemovePeer
+ //
+ // Called when DNSServices detects a P2P peer has left
+ // the network
+ //
+ // This is called (indirectly) from OnBrowseReply()
+ //
+ private void
+ OnRemovePeer
+ (
+ PeerData peer
+ )
+ {
+ comboBox1.Items.Remove(peer);
+ }
+
+ //
+ // OnResolveService
+ //
+ // Called when DNSServices has resolved a service.
+ //
+ // This is called (indirectly) from OnResolveService()
+ //
+ private void
+ OnResolveService
+ (
+ ResolveData data
+ )
+ {
+ resolver.Dispose();
+
+ PeerData peer = (PeerData) comboBox1.SelectedItem;
+
+ peer.Port = data.Port;
+
+ try
+ {
+ resolver = DNSService.QueryRecord(0, 0, data.HostName, /* ns_t_a */ 1, /* ns_t_c */ 1, new DNSService.QueryRecordReply(OnQueryRecordReply));
+ }
+ catch
+ {
+ MessageBox.Show("QueryRecord Failed", "Error");
+ Application.Exit();
+ }
+ }
+
+ //
+ // OnResolveAddress
+ //
+ // Called when DNSServices has finished a query operation
+ //
+ // This is called (indirectly) from OnQueryRecordReply()
+ //
+ private void
+ OnResolveAddress
+ (
+ System.Net.IPAddress address
+ )
+ {
+ resolver.Dispose();
+
+ PeerData peer = (PeerData) comboBox1.SelectedItem;
+
+ peer.Address = address;
+ }
+
+ //
+ // OnReadMessage
+ //
+ // Called when there is data to be read on a socket
+ //
+ // This is called (indirectly) from OnReadSocket()
+ //
+ private void
+ OnReadMessage
+ (
+ String msg
+ )
+ {
+ int rgb = 0;
+
+ for (int i = 0; i < msg.Length && msg[i] != ':'; i++)
+ {
+ rgb = rgb ^ ((int) msg[i] << (i % 3 + 2) * 8);
+ }
+
+ Color color = Color.FromArgb(rgb & 0x007F7FFF);
+
+ richTextBox1.SelectionColor = color;
+
+ richTextBox1.AppendText(msg + "\n");
+ }
+
+ //
+ // OnRegisterReply
+ //
+ // Called by DNSServices core as a result of DNSService.Register()
+ // call
+ //
+ // This is called from a worker thread by DNSService core.
+ //
+ private void
+ OnRegisterReply
+ (
+ ServiceRef sdRef,
+ ServiceFlags flags,
+ ErrorCode errorCode,
+ String name,
+ String regtype,
+ String domain)
+ {
+ if (errorCode == ErrorCode.NoError)
+ {
+ Invoke(registerServiceCallback, new Object[]{name});
+ }
+ else
+ {
+ MessageBox.Show("OnRegisterReply returned an error code " + errorCode, "Error");
+ }
+ }
+
+
+ //
+ // OnBrowseReply
+ //
+ // Called by DNSServices core as a result of DNSService.Browse()
+ // call
+ //
+ // This is called from a worker thread by DNSService core.
+ //
+ private void
+ OnBrowseReply
+ (
+ ServiceRef sdRef,
+ ServiceFlags flags,
+ int interfaceIndex,
+ ErrorCode errorCode,
+ String name,
+ String type,
+ String domain)
+ {
+ if (errorCode == ErrorCode.NoError)
+ {
+ PeerData peer = new PeerData();
+
+ peer.InterfaceIndex = interfaceIndex;
+ peer.Name = name;
+ peer.Type = type;
+ peer.Domain = domain;
+ peer.Address = null;
+
+ if ((flags & ServiceFlags.Add) != 0)
+ {
+ Invoke(addPeerCallback, new Object[]{peer});
+ }
+ else if ((flags == 0) || ((flags & ServiceFlags.MoreComing) != 0))
+ {
+ Invoke(removePeerCallback, new Object[]{peer});
+ }
+ }
+ else
+ {
+ MessageBox.Show("OnBrowseReply returned an error code " + errorCode, "Error");
+ }
+ }
+
+ //
+ // OnResolveReply
+ //
+ // Called by DNSServices core as a result of DNSService.Resolve()
+ // call
+ //
+ // This is called from a worker thread by DNSService core.
+ //
+ private void
+ OnResolveReply
+ (
+ ServiceRef sdRef,
+ ServiceFlags flags,
+ int interfaceIndex,
+ ErrorCode errorCode,
+ String fullName,
+ String hostName,
+ int port,
+ Byte[] txtRecord
+ )
+ {
+ if (errorCode == ErrorCode.NoError)
+ {
+ ResolveData data = new ResolveData();
+
+ data.InterfaceIndex = interfaceIndex;
+ data.FullName = fullName;
+ data.HostName = hostName;
+ data.Port = port;
+ data.TxtRecord = txtRecord;
+
+ Invoke(resolveServiceCallback, new Object[]{data});
+ }
+ else
+ {
+ MessageBox.Show("OnResolveReply returned an error code: " + errorCode, "Error");
+ }
+ }
+
+ //
+ // OnQueryRecordReply
+ //
+ // Called by DNSServices core as a result of DNSService.QueryRecord()
+ // call
+ //
+ // This is called from a worker thread by DNSService core.
+ //
+ private void
+ OnQueryRecordReply
+ (
+ ServiceRef sdRef,
+ ServiceFlags flags,
+ int interfaceIndex,
+ ErrorCode errorCode,
+ String fullName,
+ int rrtype,
+ int rrclass,
+ Byte[] rdata,
+ int ttl
+ )
+ {
+ if (errorCode == ErrorCode.NoError)
+ {
+ uint bits = BitConverter.ToUInt32(rdata, 0);
+ System.Net.IPAddress data = new System.Net.IPAddress(bits);
+
+ Invoke(resolveAddressCallback, new Object[]{data});
+ }
+ else
+ {
+ MessageBox.Show("OnQueryRecordReply returned an error code: " + errorCode, "Error");
+ }
+ }
+
+ //
+ // OnReadSocket
+ //
+ // Called by the .NET core when there is data to be read on a socket
+ //
+ // This is called from a worker thread by the .NET core
+ //
+ private void
+ OnReadSocket
+ (
+ IAsyncResult ar
+ )
+ {
+ SocketStateObject so = (SocketStateObject) ar.AsyncState;
+ Socket s = so.WorkSocket;
+
+ try
+ {
+ if (s == null)
+ {
+ return;
+ }
+
+ int read = s.EndReceive(ar);
+
+ if (read > 0)
+ {
+ String msg = Encoding.UTF8.GetString(so.m_buffer, 0, read);
+
+ Invoke(readMessageCallback, new Object[]{msg});
+ }
+
+ s.BeginReceive(so.m_buffer, 0, SocketStateObject.BUFFER_SIZE, 0, new AsyncCallback(OnReadSocket), so);
+ }
+ catch
+ {
+ }
+ }
+
+
+ public Form1()
+ {
+ //
+ // Required for Windows Form Designer support
+ //
+ InitializeComponent();
+
+ registerServiceCallback = new RegisterServiceCallback(OnRegisterService);
+ addPeerCallback = new AddPeerCallback(OnAddPeer);
+ removePeerCallback = new RemovePeerCallback(OnRemovePeer);
+ resolveServiceCallback = new ResolveServiceCallback(OnResolveService);
+ resolveAddressCallback = new ResolveAddressCallback(OnResolveAddress);
+ readMessageCallback = new ReadMessageCallback(OnReadMessage);
+
+ this.Load += new System.EventHandler(this.Form1_Load);
+
+ this.AcceptButton = button1;
+ }
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ protected override void
+ Dispose( bool disposing )
+ {
+ if( disposing )
+ {
+ if (components != null)
+ {
+ components.Dispose();
+ }
+
+ if (registrar != null)
+ {
+ registrar.Dispose();
+ }
+
+ if (browser != null)
+ {
+ browser.Dispose();
+ }
+ }
+ 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.comboBox1 = new System.Windows.Forms.ComboBox();
+ this.textBox2 = new System.Windows.Forms.TextBox();
+ this.button1 = new System.Windows.Forms.Button();
+ this.label1 = new System.Windows.Forms.Label();
+ this.richTextBox1 = new System.Windows.Forms.RichTextBox();
+ this.SuspendLayout();
+ //
+ // comboBox1
+ //
+ this.comboBox1.Anchor = ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right);
+ this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.comboBox1.Location = new System.Drawing.Point(59, 208);
+ this.comboBox1.Name = "comboBox1";
+ this.comboBox1.Size = new System.Drawing.Size(224, 21);
+ this.comboBox1.Sorted = true;
+ this.comboBox1.TabIndex = 5;
+ this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
+ //
+ // textBox2
+ //
+ this.textBox2.Anchor = ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right);
+ this.textBox2.Location = new System.Drawing.Point(8, 248);
+ this.textBox2.Name = "textBox2";
+ this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Horizontal;
+ this.textBox2.Size = new System.Drawing.Size(192, 20);
+ this.textBox2.TabIndex = 2;
+ this.textBox2.Text = "";
+ this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged);
+ //
+ // button1
+ //
+ this.button1.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right);
+ this.button1.Enabled = false;
+ this.button1.Location = new System.Drawing.Point(208, 248);
+ this.button1.Name = "button1";
+ this.button1.TabIndex = 3;
+ this.button1.Text = "Send";
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // label1
+ //
+ this.label1.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left);
+ this.label1.Location = new System.Drawing.Point(8, 210);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(48, 16);
+ this.label1.TabIndex = 4;
+ this.label1.Text = "Talk To:";
+ //
+ // richTextBox1
+ //
+ this.richTextBox1.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right);
+ this.richTextBox1.Location = new System.Drawing.Point(8, 8);
+ this.richTextBox1.Name = "richTextBox1";
+ this.richTextBox1.ReadOnly = true;
+ this.richTextBox1.Size = new System.Drawing.Size(272, 184);
+ this.richTextBox1.TabIndex = 1;
+ this.richTextBox1.Text = "";
+ //
+ // Form1
+ //
+ this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+ this.ClientSize = new System.Drawing.Size(292, 273);
+ this.Controls.AddRange(new System.Windows.Forms.Control[] {
+ this.richTextBox1,
+ this.label1,
+ this.button1,
+ this.textBox2,
+ this.comboBox1});
+ this.Name = "Form1";
+ this.Text = "SimpleChat.NET";
+ this.ResumeLayout(false);
+
+ }
+ #endregion
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ IPEndPoint localEP = new IPEndPoint(System.Net.IPAddress.Any, 0);
+
+ //
+ // create the socket and bind to INADDR_ANY
+ //
+ socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ socket.Bind(localEP);
+ localEP = (IPEndPoint) socket.LocalEndPoint;
+
+ //
+ // start asynchronous read
+ //
+ SocketStateObject so = new SocketStateObject(socket);
+ socket.BeginReceive(so.m_buffer, 0, SocketStateObject.BUFFER_SIZE, 0, new AsyncCallback(this.OnReadSocket), so);
+
+ try
+ {
+ //
+ // start the register and browse operations
+ //
+ registrar = DNSService.Register(0, 0, System.Environment.UserName, "_p2pchat._udp", null, null, localEP.Port, null, new DNSService.RegisterReply(OnRegisterReply));
+ browser = DNSService.Browse(0, 0, "_p2pchat._udp", null, new DNSService.BrowseReply(OnBrowseReply));
+ }
+ catch
+ {
+ MessageBox.Show("DNSServices Not Available", "Error");
+ Application.Exit();
+ }
+ }
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.Run(new Form1());
+ }
+
+ //
+ // send the message to a peer
+ //
+ private void button1_Click(object sender, System.EventArgs e)
+ {
+ PeerData peer = (PeerData) comboBox1.SelectedItem;
+
+ String message = myName + ": " + textBox2.Text;
+
+ Byte[] bytes = Encoding.UTF8.GetBytes(message);
+
+ UdpClient udpSocket = new UdpClient(peer.Address.ToString(), peer.Port);
+
+ udpSocket.Send(bytes, bytes.Length);
+
+ richTextBox1.SelectionColor = Color.Black;
+
+ richTextBox1.AppendText(textBox2.Text + "\n");
+
+ textBox2.Text = "";
+ }
+
+ //
+ // called when typing in message box
+ //
+ private void textBox2_TextChanged(object sender, System.EventArgs e)
+ {
+ PeerData peer = (PeerData) comboBox1.SelectedItem;
+
+ if ((peer.Address != null) && (textBox2.Text.Length > 0))
+ {
+ button1.Enabled = true;
+ }
+ else
+ {
+ button1.Enabled = false;
+ }
+ }
+
+ //
+ // called when peer target changes
+ //
+ ///
+ ///
+ ///
+ ///
+ private void comboBox1_SelectedIndexChanged(object sender, System.EventArgs e)
+ {
+ PeerData peer = (PeerData) comboBox1.SelectedItem;
+
+ try
+ {
+ resolver = DNSService.Resolve(0, 0, peer.Name, peer.Type, peer.Domain, new DNSService.ResolveReply(OnResolveReply));
+ }
+ catch
+ {
+ MessageBox.Show("Unable to Resolve service", "Error");
+ Application.Exit();
+ }
+ }
+ }
+}