BluetoothTesting.cs :  » Business-Application » 32feet.NET » ConsoleMenuTesting » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Business Application » 32feet.NET 
32feet.NET » ConsoleMenuTesting » BluetoothTesting.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using InTheHand.Net.Sockets;
using InTheHand.Net.Bluetooth;
using InTheHand.Net;
using System.Threading;
using System.Diagnostics;
using ConsoleSystem.ValueType; // Block the use of Console, must use "console".
using System.Reflection;
using InTheHand.Net.Bluetooth.AttributeIds;

namespace ConsoleMenuTesting{
    partial class BluetoothTesting
    {
        public MenuSystem console; //HACK public MenuSystem console;
        Stream peer;

        public BluetoothTesting()
        {
        }

        //----

        static WeakReferenceT<BluetoothClient> s_cli;

        class WeakReferenceT<T> : WeakReference
        {
            public WeakReferenceT(T target)
                : base(target)
            {
            }

            public new T Target
            {
                get { return (T)base.Target; }
                set { base.Target = value; }
            }
        }

        //--------

#if DEBUG
        [MenuItem]
        public void TestPause()
        {
            console.WriteLine("1111");
            console.WriteLine("2222");
            console.WriteLine("3333");
            console.WriteLine("4444");
            console.WriteLine("55555");
            console.WriteLine("Before Pause");
            console.Pause("Message");
            console.WriteLine("After Pause");
        }
#endif

#if !NETCF
        [MenuItem, SubMenu("Device Discovery")]
        public void DiscoDevicesAsync()
        {
            BluetoothComponent bco = new BluetoothComponent();
            bco.DiscoverDevicesComplete += _DiscoDevicesAsync_Callback;
            bco.DiscoverDevicesAsync(255, true, true, true, false, 99);
        }

        void _DiscoDevicesAsync_Callback(object sender, DiscoverDevicesEventArgs e)
        {
            Debug.Assert((int)e.UserState == 99);
            if (e.Cancelled) {
                console.WriteLine("DiscoDevicesAsync cancelled.");
            } else if (e.Error != null) {
                console.WriteLine("DiscoDevicesAsync error: {0}.", Exception_FirstLine(e.Error));
            } else {
                console.WriteLine("DiscoDevicesAsync found {0} devices.", e.Devices.Length);
            }
        }
#endif

        //--------

        BluetoothRadio m_factoryRadio;
        BluetoothPublicFactory m_factory;

        // TODO Should BluetoothPublicFactory have a Primary/AllRadios property?
        /// <summary>
        /// --can return null--
        /// </summary>
        /// <returns></returns>
        BluetoothRadio Get_BluetoothRadio()
        {
            if (m_factory == null)
                return BluetoothRadio.PrimaryRadio;
            BluetoothRadio radio = m_factoryRadio;
            //ClassOfDevice checkNonNull = radio.ClassOfDevice;
            return radio;
        }

        BluetoothDeviceInfo Create_BluetoothDeviceInfo(BluetoothAddress addr)
        {
            if (m_factory == null)
                return new BluetoothDeviceInfo(addr);
            return m_factory.CreateBluetoothDeviceInfo(addr);
        }

        BluetoothClient Create_BluetoothClient()
        {
            if (m_factory == null)
                return new BluetoothClient();
            return m_factory.CreateBluetoothClient();
        }

        BluetoothListener Create_BluetoothListener(Guid svc)
        {
            if (m_factory == null)
                return new BluetoothListener(svc);
            return m_factory.CreateBluetoothListener(svc);
        }

        BluetoothListener Create_BluetoothListener(Guid svc, ServiceRecord record)
        {
            if (m_factory == null)
                return new BluetoothListener(svc, record);
            return m_factory.CreateBluetoothListener(svc, record);
        }

        BluetoothListener Create_BluetoothListener(BluetoothEndPoint ep)
        {
            if (m_factory == null)
                return new BluetoothListener(ep);
            return m_factory.CreateBluetoothListener(ep);
        }

        ObexWebRequest Create_ObexWebRequest(Uri requestUri)
        {
            if (m_factory == null)
                return new ObexWebRequest(requestUri);
            return m_factory.CreateObexWebRequest(requestUri);
        }

        ObexListener Create_ObexListener_Bluetooth()
        {
            if (m_factory == null)
                return new ObexListener(ObexTransport.Bluetooth);
            return m_factory.CreateObexListener();
        }


        [MenuItem]
        public void SetStackFactory()
        {
            BluetoothRadio[] list = BluetoothRadio_GetAll__();
            if (list.Length == 0) {
                console.WriteLine("No radios found!");
                m_factory = null;
                m_factoryRadio = null;
            }
            int choice;
            do {
                choice = console.ReadInteger(string.Format("Which stack for factory (1-{0}), 0 for \"new\"-direct", list.Length));
            } while (choice < 0 || choice > list.Length);
            if (choice == 0) {
                m_factory = null;
                m_factoryRadio = null;
            } else {
                m_factoryRadio = list[choice - 1];
                m_factory = m_factoryRadio.StackFactory;
            }
        }


        //--------
        private string GetTime()
        {
            return Environment.TickCount.ToString();
        }

        void MiscCallback(IAsyncResult ar)
        {
            console.WriteLine("{1}: Callback called for \"{0}\"", ar.AsyncState, GetTime());
        }

        void EmptyCallback(IAsyncResult ar)
        {
            if (ar.CompletedSynchronously) {
            } else {
            }
        }

        bool VerifyConnectionWrite()
        {
            if (peer == null || !peer.CanWrite) {
                console.WriteLine("No connection!");
                return false;
            }
            return true;
        }

        bool VerifyConnectionRead()
        {
            if (peer == null || !peer.CanRead) {
                console.WriteLine("No connection!");
                return false;
            }
            return true;
        }

        //--------
        [MenuItem, SubMenu("Data")]
        public void PrintStreamState()
        {
            if (peer == null) {
                console.WriteLine("Stream is null.");
            } else {
                console.WriteLine("Stream has CanRead: {0}, CanWrite: {1}.",
                    peer.CanRead, peer.CanWrite);
            }
        }

        [MenuItem, SubMenu("Data")]
        public void CloseStream()
        {
            if (peer != null) {
                peer.Close();
                peer = null;
            }
        }

        [MenuItem, SubMenu("Data")]
        public void CloseStream_ButDontNullIt()
        {
            if (peer != null) {
                peer.Close();
            }
        }

        [MenuItem, SubMenu("Data")]
        public void NullStreamAndClient()
        {
            peer = null;
            s_cli = null;
        }

        [MenuItem, SubMenu("Data")]
        public void CloseClientIfExists()
        {
            if (s_cli != null) {
                BluetoothClient cli = s_cli.Target;
                if (cli != null) {
                    cli.Close();
                    s_cli = null;
                } else {
                    console.WriteLine("The reference has been GC'd.");
                }
            }
        }

        private BluetoothListener ListenInit()
        {
            Guid svcClass = BluetoothService.Wap;
            console.WriteLine("Default UUID : {0}", svcClass);
            Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID");
            if (inputGuid.HasValue)
                svcClass = inputGuid.Value;
            int? port = console.ReadOptionalInteger("Port number");
            bool auth = console.ReadYesNo("Authenticate", false);
            bool encpt = console.ReadYesNo("Encrypt", false);
            bool setPin1, setPin2;
            string passcode;
            BluetoothAddress pinAddr;
            PromptForSetPin(console, out setPin1, out setPin2, out passcode, out pinAddr);
            string svcName = console.ReadLine("Service Name (optional)");
            if (svcName != null && svcName.Length == 0)
                svcName = null;
            //
            BluetoothEndPoint lep;
            if (port == null)
                lep = new BluetoothEndPoint(BluetoothAddress.None, svcClass);
            else
                lep = new BluetoothEndPoint(BluetoothAddress.None, svcClass, port.Value);
            console.WriteLine("Going to listen on: {0}:{1}:{2}; auth: {3}, encrypt: {4}.", 
                lep.Address, lep.Service, lep.Port, auth, encpt);
            //
            BluetoothListener lsnr = Create_BluetoothListener(lep);
            if (svcName != null)
                lsnr.ServiceName = svcName;
            // Assume false by default, so if NotImpl fails only if user says true.
            if (auth)
                lsnr.Authenticate = true;
            if (encpt)
                lsnr.Encrypt = true;
            if (setPin1) {
                Debug.Assert(pinAddr == null, "pinAddr == null");
                //lsnr.SetPin(passcode);
                console.WriteLine("Soooorrrrry we don't support SetPin(String) on listener!!!!");
                throw new NotSupportedException("ConsoleMenuTesting");
            } else if (setPin2) {
                Debug.Assert(pinAddr != null, "pinAddr != null");
                lsnr.SetPin(pinAddr, passcode);
            }
            console.WriteLine("Starting Listener...");
            lsnr.Start();
            BluetoothEndPoint lepLsnr = (BluetoothEndPoint)lsnr.LocalEndPoint;
            console.WriteLine("Listening on endpoint: {0}", lepLsnr);
            return lsnr;
        }

        //[MenuItem, SubMenu("BtLsnr")]
        //public void ListenStartStopStart()
        //{
        //    Guid svcClass = BluetoothService.Wap;
        //    console.WriteLine("Default UUID : {0}", svcClass);
        //    Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID");
        //    if (inputGuid.HasValue)
        //        svcClass = inputGuid.Value;
        //    BluetoothListener lsnr = Create_BluetoothListener(svcClass);
        //    lsnr.Start();
        //    lsnr.Stop();
        //    lsnr.Start();
        //    //
        //    lsnr = null;
        //    GC.Collect();
        //    GC.Collect();
        //    GC.WaitForPendingFinalizers();
        //}

        [MenuItem, SubMenu("BtLsnr")]
        public void Listen()
        {
            BluetoothListener lsnr = ListenInit();
            BluetoothClient cli;
            bool startStopStartEtc = console.ReadYesNo("Start-Stop-Start-Stop-Start-Finalize", false);
            if (startStopStartEtc) {
                lsnr.Stop();
                lsnr.Start();
                console.WriteLine("Stopped and restarted.");
            }
            bool async = console.ReadYesNo("Async Accept", false);
            if (!async) {
                bool callPending = console.ReadYesNo("Loop on Pending()", false);
                if (callPending) {
                    int i = 0;
                    while (!lsnr.Pending()) {
                        console.WriteLine("Not Pending" + new string('.', (i + 3) % 3));
                        const int HalfSecond = 500;
                        Thread.Sleep(HalfSecond);
                        ++i;
                    }
                    console.WriteLine("Is Pending...");
                }
                //bool closeNow = console.ReadYesNo("Hit return to proceed to EndConnect.  Enter Y to call Close first.", false);
                console.WriteLine("calling Accept...");
                cli = lsnr.AcceptBluetoothClient();
            } else {
                console.WriteLine("Waiting for connection...");
                IAsyncResult ar = lsnr.BeginAcceptBluetoothClient(MiscCallback, "BeginAcceptBluetoothClient");
                console.WriteLine("(BeginAccept returned)");
#if !NETCF
                ManualResetEvent quit = console.NewManualResetEvent(false);
                int signalledIdx = WaitHandle.WaitAny(new WaitHandle[] { ar.AsyncWaitHandle, quit });
                if (signalledIdx == 1) {
                    // ?Do we want to test disposal or Finalization here?
                    // lsnr.Stop()
                    peer = null;
                    return;
                }
#endif
                cli = lsnr.EndAcceptBluetoothClient(ar);
            }
            //
            peer = cli.GetStream();
            console.WriteLine("Got connection from: '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint);
            console.Pause("Hit return to continue; and close listener");
            if (!startStopStartEtc) {
                lsnr.Stop();
            } else {
                lsnr.Stop();
                lsnr.Start();
                //
                bool x = console.ReadYesNo("Do Async Accept (before Finalization)", false);
                IAsyncResult arLast =null; 
                if (x) {
                    arLast = lsnr.BeginAcceptBluetoothClient(MiscCallback, "BeginAcceptBluetoothClient");
                    console.WriteLine("(BeginAccept returned)");
                }
                lsnr = null;
                GC.Collect();
                GC.Collect();
                GC.WaitForPendingFinalizers();
                console.WriteLine("Stopped, restarted, and Finalized.");
                if (arLast != null) {
                    console.WriteLine("arLastL: {0}", arLast.IsCompleted);
                    // Can't call EndAccept as no lsnr reference!
                }
            }
        }

        [MenuItem, SubMenu("BtLsnr")]
        public void ListenAndImmediatelyClose()
        {
            ListenAndImmediatelySendAndClose_(null);
        }

        [MenuItem, SubMenu("BtLsnr")]
        public void ListenAndImmediatelySendOneByteAndClose()
        {
            ListenAndImmediatelySendAndClose_(new byte[] { (byte)'a' });
        }

        void ListenAndImmediatelySendAndClose_(byte[] data)
        {
            BluetoothListener lsnr = ListenInit();
            console.WriteLine("Waiting for connection...");
            BluetoothClient cli = lsnr.AcceptBluetoothClient();
            console.WriteLine("Got connection from: {0}!", cli.RemoteMachineName);
            peer = cli.GetStream();
            if (data != null)
                peer.Write(data, 0, data.Length);
            peer.Close();
            peer = null;
            console.WriteLine("Got connection from ({2}and closed it!): '{0}' {1}",
                cli.RemoteMachineName, cli.RemoteEndPoint,
                (data != null ? "sent " : string.Empty));
            lsnr.Stop();
        }

        [MenuItem, SubMenu("Data")]
        public void SendOneByteAndImmediatelyClose()
        {
            if (!VerifyConnectionWrite())
                return;
            byte[] data = { (byte)'a' };
            peer.Write(data, 0, data.Length);
            peer.Close();
        }

        [MenuItem, SubMenu("BtLsnr")]
        public void ListenAcceptMultiple()
        {
            BluetoothListener lsnr = ListenInit();
            ManualResetEvent quit = console.NewManualResetEvent(false);
            ListenAcceptMultipleState state = new ListenAcceptMultipleState();
            state.lsnr = lsnr;
            state.quit = quit;
            bool keepOpen = console.ReadYesNo("Keep reference to all connections?", false);
            state.KeepAllConnections = keepOpen;
            lsnr.BeginAcceptBluetoothClient(ListenAcceptMultiple_Callback, state);
            console.Pause("Hit return to stop accepting");
            quit.Set();
            lsnr.Stop();
        }
        struct ListenAcceptMultipleState
        {
            public BluetoothListener lsnr;
            public ManualResetEvent quit;
            public int num;
            //
            bool storeAllConnections;
            public List<BluetoothClient> connList;

            public bool KeepAllConnections
            {
                get { return storeAllConnections; }
                set
                {
                    storeAllConnections = value;
                    if (storeAllConnections && connList == null) {
                        connList = new List<BluetoothClient>();
                    }
                }
            }
        }

        void ListenAcceptMultiple_Callback(IAsyncResult arCb)
        {
            ListenAcceptMultipleState state = (ListenAcceptMultipleState)arCb.AsyncState;
            BluetoothClient cli ;
            try {
                cli = state.lsnr.EndAcceptBluetoothClient(arCb);
                if (state.KeepAllConnections) {
                    state.connList.Add(cli);
                }
            } catch (ArgumentException ex) {
                console.WriteLine("Accept failed, due to quit?  Exiting.");
                console.WriteLine(ex);
                return;
            } catch (ObjectDisposedException ex) {
                console.WriteLine("Accept failed, due to quit?  Exiting.");
                console.WriteLine(ex);
                return;
            }
            Stream peer = cli.GetStream();
            console.WriteLine("At " + DateTime.Now.ToLongTimeString() + " got connection #" + (state.num + 1) + " from: '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint);
            ++state.num;
            if (!IsSet(state.quit))
                state.lsnr.BeginAcceptBluetoothClient(ListenAcceptMultiple_Callback, state);
        }


        [MenuItem]
        public void NewBtCli()
        {
            using (BluetoothClient cli = Create_BluetoothClient()) {
                console.ReadLine("BluetoothClient created.  Continue to dispose");
            }
        }

        [MenuItem]
        public void NewBtLsnr()
        {
            BluetoothListener lsnr = Create_BluetoothListener(BluetoothService.Wap);
            try {
                console.WriteLine("BluetoothListener created, now calling Start.");
                lsnr.Start();
                console.ReadLine("Started.  Continue to dispose");
            } finally {
                if (lsnr != null)
                    lsnr.Stop();
            }
        }


        [MenuItem, SubMenu("BtClient")]
        public void Connect()
        {
            BluetoothClient cli;
            Connect_(out cli);
            peer = cli.GetStream();
            s_cli = new WeakReferenceT<BluetoothClient>(cli);
        }

        [MenuItem, SubMenu("BtClient")]
        public void Connect_FromInquiryCallback()
        {
            BluetoothClient cliDd = Create_BluetoothClient();
                cliDd.BeginDiscoverDevices(255, true, true, true, false,
                    Connect_FromInquiryCallback_DdCallback, cliDd);
            console.WriteLine("Running async DiscoverDevices...");
        }

        void Connect_FromInquiryCallback_DdCallback(IAsyncResult ar)
        {
            console.WriteLine("DiscoverDevices completed...");
            BluetoothClient cliDd = (BluetoothClient)ar.AsyncState;
            cliDd.EndDiscoverDevices(ar);
            //
            BluetoothClient cli;
            Connect_(out cli);
            peer = cli.GetStream();
            s_cli = new WeakReferenceT<BluetoothClient>(cli);
        }

#if TEST_EARLY
        [MenuItem, SubMenu("BtClient")]
        public void Connect_GetStream2()
        {
            BluetoothClient cli;
            Connect_(out cli);
            peer = cli.GetStream2();
            s_cli = new WeakReferenceT<BluetoothClient>(cli);
        }
#endif

        [MenuItem, SubMenu("BtClient")]
        public void ConnectSuccessfullyAndImmediatelyClose()
        {
            ConnectSuccessfullyAndImmediatelySendAndClose_(null);
        }

        [MenuItem, SubMenu("BtClient")]
        public void ConnectSuccessfullyAndImmediatelySendOneByteAndClose()
        {
            ConnectSuccessfullyAndImmediatelySendAndClose_(new byte[] { (byte)'b' });
        }

        void ConnectSuccessfullyAndImmediatelySendAndClose_(byte[] data)
        {
            BluetoothClient cli;
            Connect_(out cli);
            peer = cli.GetStream();
            if (data != null)
                peer.Write(data, 0, data.Length);
            peer.Close();
            peer = null;
            s_cli = null;
        }

        [MenuItem, SubMenu("BtClient")]
        public void ConnectMultipleDevices()
        {
            int num = console.ReadInteger("How many connects?");
            bool oaat = console.ReadYesNo("Do one-at-a-time (e.g. Widcomm SDP sync)?", false);
            BluetoothAddress[] addrList = new BluetoothAddress[num];
            Guid[] svcClassList = new Guid[num];
            int?[] portList = new int?[num];
            BluetoothClient[] cliList = new BluetoothClient[num];
            IAsyncResult[] arList = new IAsyncResult[num];
            //
            for (int i = 0; i < num; ++i) {
                addrList[i] = console.ReadBluetoothAddress("Server #" + (i + 1) + "'s BluetoothAddress");
                svcClassList[i] = BluetoothService.Wap;
                console.WriteLine("Default UUID : {0}", svcClassList[i]);
                Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID");
                if (inputGuid.HasValue)
                    svcClassList[i] = inputGuid.Value;
                portList[i] = console.ReadOptionalInteger("Port number");
            }
            //
            IAsyncResult waitForLast = null;
            for (int i = 0; i < num; ++i) {
                if (waitForLast != null) {
                    console.Write("Waiting previous.  ");
                    bool signalled = waitForLast.AsyncWaitHandle.WaitOne(60 * 1000, false);
                    if (!signalled) {
                        throw new InvalidOperationException("Timed-out waiting for previous connect to complete.");
                    }
                }
                BluetoothEndPoint rep;
                if (portList[i] == null)
                    rep = new BluetoothEndPoint(addrList[i], svcClassList[i]);
                else
                    rep = new BluetoothEndPoint(addrList[i], svcClassList[i], portList[i].Value);
                console.WriteLine("{4}: Connecting #{3} to: {0}:{1}:{2} ...", rep.Address, rep.Service, rep.Port,
                    (i + 1), GetTime());
                //
                cliList[i] = Create_BluetoothClient();
                try {
                    arList[i] = cliList[i].BeginConnect(rep,
                        MiscCallback, "BeginConnect #" + (i + 1));
                    console.WriteLine("{0}: (BeginConnect returned)", GetTime());
                    if (oaat) {
                        waitForLast = arList[i];
                    }
                } catch (System.Net.Sockets.SocketException ex) {
                    console.WriteLine("{0}: BeginConnect failed: {1}", GetTime(), Exception_FirstLine(ex));
                }
            }//for
            //
            WaitAll(arList);
            console.WriteLine("All signalled");
            //
            for (int i = 0; i < cliList.Length; i++) {
                try {
                    cliList[i].EndConnect(arList[i]);
                } catch (Exception ex) {
                    console.WriteLine("Error for #{3}: ", (i + 1), Exception_FirstLine(ex));
                }
            }
            console.WriteLine("All completed");
        }

        private void WaitAll(IList<IAsyncResult> arList)
        {
            WaitHandle[] whList = GetWaitHandles(arList);
#if !NETCF
            bool signalled = WaitHandle.WaitAll(whList);
#else
            bool signalled = WaitHandle_WaitAll_Hack(whList);
#endif
            Debug.Assert(signalled, "Given infinite timeout, but returned NON-signalled!?!");
        }

        private WaitHandle[] GetWaitHandles(IList<IAsyncResult> arList)
        {
            Debug.Assert(arList != null, "ArgNullEx");
            List<WaitHandle> output = new List<WaitHandle>(arList.Count);
            for (int i = 0; i < arList.Count; ++i) {
                if (arList[i] != null)
                    output.Add(arList[i].AsyncWaitHandle);
            }
            return output.ToArray();
        }

#if NETCF
        bool WaitHandle_WaitAll_Hack(WaitHandle[] list)
        {
            bool sum = true;
            foreach (WaitHandle cur in list) {
                bool signalled = cur.WaitOne();
                Debug.Assert(signalled, "NOT signalled");
                sum = sum && signalled;
            }
            Debug.Assert(sum, "NOT signalled->sum");
            return sum;
        }
#endif

        void Connect_(out BluetoothClient cli)
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("Server's BluetoothAddress");
            Guid svcClass = BluetoothService.Wap;
            console.WriteLine("Default UUID : {0}", svcClass);
            Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID");
            if (inputGuid.HasValue)
                svcClass = inputGuid.Value;
            int? port = console.ReadOptionalInteger("Port number");
            bool auth = console.ReadYesNo("Authenticate", false);
            bool encpt = console.ReadYesNo("Encrypt", false);
            bool setPin1, setPin2;
            string passcode;
            BluetoothAddress pinAddr;
            PromptForSetPin(console, out setPin1, out setPin2, out passcode, out pinAddr);
            bool async = console.ReadYesNo("Async Connect?", false);
            bool asyncCallback = true;//not used but init anyway
            if (async) {
                asyncCallback = console.ReadYesNo("Async Callback?", true);
            }
            //
            BluetoothEndPoint rep;
            if (port == null)
                rep = new BluetoothEndPoint(addr, svcClass);
            else
                rep = new BluetoothEndPoint(addr, svcClass, port.Value);
            console.WriteLine("Connecting to: {0}:{1}:{2} ...", rep.Address, rep.Service, rep.Port);
            //
            cli = Create_BluetoothClient();
            // For Auth & Encrypt assume false by default, so if NotImpl fails only if user says true.
            if (auth)
                cli.Authenticate = true;
            if (encpt)
                cli.Encrypt = true;
            if (setPin1) {
                Debug.Assert(pinAddr == null, "pinAddr == null");
                cli.SetPin(passcode);
            } else if (setPin2) {
                Debug.Assert(pinAddr != null, "pinAddr != null");
                cli.SetPin(pinAddr, passcode);
            }
            if (async) {
                AsyncCallback cb = null;
                if (asyncCallback)
                    cb = MiscCallback;
                IAsyncResult ar = cli.BeginConnect(rep,
                    cb, "BeginConnect");
                console.WriteLine("(BeginConnect returned)");
#if NETCF // ReadYesNo will block the screen. :-(
                console.Pause("Paused after BeginConnect");
#endif
                bool closeNow = console.ReadYesNo("Hit return to proceed to EndConnect.  Enter Y to call Close first.", false);
                if (closeNow) {
                    cli.Close();
                }
                cli.EndConnect(ar);
            } else {
                cli.Connect(rep);
            }
            console.WriteLine("Connected to : '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint);
        }

        private void PromptForSetPin(MenuSystem console, out bool setPin1, out bool setPin2, 
            out string passcode, out BluetoothAddress pinAddr)
        {
            passcode = null;
            pinAddr = null;
            setPin1 = console.ReadYesNo("SetPin(string)", false);
            if (setPin1) {
                setPin2 = false;
            } else {
                setPin2 = console.ReadYesNo("SetPin(address,string)", false);
            }
            if (setPin1 || setPin2) {
                passcode = console.ReadLine("Passcode");
            }
            if (setPin2) {
                pinAddr = console.ReadBluetoothAddress("PIN address");
            }
        }

        [MenuItem, SubMenu("BtClient")]
        public void ConnectMultipleTimes()
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("Server's BluetoothAddress");
            Guid svcClass = BluetoothService.Wap;
            console.WriteLine("Default UUID : {0}", svcClass);
            Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID");
            if (inputGuid.HasValue)
                svcClass = inputGuid.Value;
            int? port = console.ReadOptionalInteger("Port number");
            //
            BluetoothEndPoint rep;
            if (port == null)
                rep = new BluetoothEndPoint(addr, svcClass);
            else
                rep = new BluetoothEndPoint(addr, svcClass, port.Value);
            console.WriteLine("Will connect to: {0}:{1}:{2} ...", rep.Address, rep.Service, rep.Port);
            //
            int count = console.ReadInteger("Connect how many times");
            int? delay = console.ReadOptionalInteger("Delay between each (ms)");
            //
            BluetoothClient cli = null;
            byte[] buf = { 0x61, 0x62, 0x63, 0x64 };
            for (int i = 0; i < count; ++i) {
                try {
                    if (delay.HasValue) {
                        Thread.Sleep(delay.Value);
                    }
                    console.Write("Connecting #" + (i + 1) + "...");
                    cli = Create_BluetoothClient();
                    cli.LingerState = new System.Net.Sockets.LingerOption(true, 10);
                    cli.Connect(rep);
                    console.WriteLine("Connected");
                    using (Stream peerA = cli.GetStream()) {
                        peerA.Write(buf, 0, buf.Length);
                    }
                } catch (Exception ex) {
                    console.Write("Failed: " + ex);
                    break;
                } finally {
                    if (cli != null) {
                        cli.Close();
                    }
                }
            }
        }

        [MenuItem, SubMenu("Data")]
        public void SendForever()
        {
            if (!VerifyConnectionWrite())
                return;
            int interSendPeriod = console.ReadInteger("Inter-send period in milliseconds");
            byte[] buf = Encoding.ASCII.GetBytes("____abcdefghijklmnopqrstuvwxyz");
            ManualResetEvent quit = console.NewManualResetEvent(false);
            Action<Stream> send = delegate(Stream peer2) {
                int num = 0;
                while (true) {
                    if (IsSet(quit))
                        break;
                    string numString = num.ToString("d4");
                    Debug.Assert(numString.Length == 4, "numString.Length: " + numString.Length);
                    unchecked {
                        buf[0] = (byte)numString[0];
                        buf[1] = (byte)numString[1];
                        buf[2] = (byte)numString[2];
                        buf[3] = (byte)numString[3];
                    }
                    peer2.Write(buf, 0, buf.Length);
                    console.Write(".");
                    if (IsSet(quit))
                        break;
                    Thread.Sleep(interSendPeriod);
                    ++num;
                }//while
            };
            IAsyncResult ar = DelegateExtension.BeginInvoke(send, peer, null, null);
            console.Pause("Hit return to stop sending");
            quit.Set();
            DelegateExtension.EndInvoke(send, ar);
        }

        [MenuItem, SubMenu("Data")]
        public void ZeroLengthSend()
        {
            if (peer == null)
                return;
            byte[] buf = new byte[2];
            peer.Write(buf, 0, 0);
            console.WriteLine("ZeroLengthSend");
        }

        [MenuItem, SubMenu("Data")]
        public void ZeroLengthRead()
        {
            if (peer == null)
                return;
            byte[] buf = new byte[2];
            IAsyncResult ar = null;
            bool doNormalReadFirst = console.ReadYesNo("Do normal async read first", false);
            if (doNormalReadFirst)
                ar = peer.BeginRead(buf, 0, 1, null, null);
            int readLen = peer.Read(buf, 0, 0);
            console.WriteLine("Did ZeroLengthRead, got length: {0}", readLen);
            if (ar != null) {
                int readLen0 = peer.EndRead(ar);
                console.WriteLine("The first read got {0} bytes.", readLen0);
            }
        }

        [MenuItem, SubMenu("Data")]
        public void SendOneAtATime()
        {
            if (!VerifyConnectionWrite())
                return;
            byte[] buf = Encoding.ASCII.GetBytes("____abcdefghijklmnopqrstuvwxyz");
            Action<Stream> send = delegate(Stream peer2) {
                int num = 0;
                while (true) {
                    string numString = num.ToString("d4");
                    Debug.Assert(numString.Length == 4, "numString.Length: " + numString.Length);
                    unchecked {
                        buf[0] = (byte)numString[0];
                        buf[1] = (byte)numString[1];
                        buf[2] = (byte)numString[2];
                        buf[3] = (byte)numString[3];
                    }
                    peer2.Write(buf, 0, buf.Length);
                    console.Write(".");
                    if (!console.ReadYesNo("Send another", true))
                        break;
                }//while
            };
            send.Invoke(peer);
        }

        private static bool IsSet(ManualResetEvent quit)
        {
            bool signalled = quit.WaitOne(0, false);
            return signalled;
        }

        [MenuItem, SubMenu("Data")]
        public void SendCrLf()
        {
            if (peer == null || !peer.CanWrite) {
                console.WriteLine("No connection!");
                return;
            }
            byte[] buf = Encoding.ASCII.GetBytes("\r\n");
            peer.Write(buf, 0, buf.Length);
        }


        [MenuItem, SubMenu("Data")]
        public void ReadForever()
        {
            if (!VerifyConnectionRead())
                return;
            byte[] buf = new byte[100];
            ManualResetEvent quit = console.NewManualResetEvent(false);
            Action<Stream> send = delegate(Stream peer2) {
                while (true) {
                    if (IsSet(quit))
                        break;
                    bool success = false;
                    try {
                        int readLen = peer2.Read(buf, 0, buf.Length);
                        console.Write(" len='{0}'", readLen);
                        success = true;
                        if (readLen == 0) {
                            console.WriteLine(" EoS.");
                            break;
                        }
                    } finally {
                        if (!success)
                            console.WriteLine("Error!");
                    }
                }//while
            };
            IAsyncResult ar = DelegateExtension.BeginInvoke(send, peer, null, null);
            console.Pause("Hit return to stop after next Read");
            quit.Set();
            DelegateExtension.EndInvoke(send, ar);
        }

        [MenuItem, SubMenu("Data")]
        public void ReadForeverAndReflect()
        {
            if (!VerifyConnectionRead())
                return;
            byte[] buf = new byte[100];
            byte[] rsp = new byte[100];
            ManualResetEvent quit = console.NewManualResetEvent(false);
            Action<Stream> send = delegate(Stream peer2) {
                while (true) {
                    if (IsSet(quit))
                        break;
                    int readLen = peer2.Read(buf, 0, buf.Length);
                    console.Write(" len='{0}'", readLen);
                    if (readLen == 0) {
                        console.WriteLine(" EoS.");
                        break;
                    }
                    SwapCase(buf, rsp, readLen);
                    peer2.Write(rsp, 0, readLen);
                }//while
            };
            IAsyncResult ar = DelegateExtension.BeginInvoke(send, peer, null, null);
            console.Pause("Hit return to stop after next Read");
            quit.Set();
            DelegateExtension.EndInvoke(send, ar);
        }

        private static void SwapCase(byte[] src, byte[] dst, int len)
        {
            for (int i = 0; i < len; ++i) {
                byte b = src[i];
                char ch = (char)b;
                char upper = char.ToUpper(ch, System.Globalization.CultureInfo.InvariantCulture);
                char lower = char.ToLower(ch, System.Globalization.CultureInfo.InvariantCulture);
                char upperBack = char.ToLower(ch, System.Globalization.CultureInfo.InvariantCulture);
                char lowerBack = char.ToUpper(ch, System.Globalization.CultureInfo.InvariantCulture);
                if (lowerBack != ch && upperBack != ch) {
                    // didn't round-trip, not a displayable(?) char, return as is.
                    dst[i] = (byte)ch;
                } else if (lower == ch && upper == ch) {
                    // didn't change, not a alphabetical char, return as is.
                    dst[i] = (byte)ch;
                } else if (lower == ch) { // Is lower case, so return as upper case
                    Debug.Assert(upper != ch, ((ushort)upper).ToString("X") + " != " + ((ushort)ch).ToString("X"));
                    dst[i] = (byte)upper;
                } else {
                    Debug.Assert(upper == ch);
                    Debug.Assert(lower != ch, ((ushort)upper).ToString("X") + " != " + ((ushort)ch).ToString("X"));
                    dst[i] = (byte)lower;
                }
            }//for
        }

        [MenuItem, SubMenu("Data")]
        public void SendObexPutInOnePacket()
        {
            if (!VerifyConnectionWrite())
                return;
            byte[] bufValid = {
                /*PutFinal*/0x82,  0,41,
                   /*Name*/0x01, 0,19, 0,(byte)'a', 0,(byte)'a', 0,(byte)'a', 
                        0,(byte)'.', 0,(byte)'t', 0,(byte)'x', 0,(byte)'t', 0,0,
                   /*EoB*/0x49, 0,19, 0,(byte)'a', 0,(byte)'a', 0,(byte)'a', 
                        0,(byte)'.', 0,(byte)'t', 0,(byte)'x', 0,(byte)'t', 0,0
            };
            byte[] bufTruncatedInFront = {
                /*PutFinal*/0x82,  0, // !!!!
            };
            byte[] bufTruncatedInRear = {
                /*PutFinal*/0x82,  0,41,
                   /*Name*/0x01, 0,19, 0,(byte)'a', // !!!!!
            };
            byte[] bufTruncateBeforeFinal = {
                /*Put-NON-Final*/0x02,  0,41,
                   /*Name*/0x01, 0,19, 0,(byte)'a', 0,(byte)'a', 0,(byte)'a', 
                        0,(byte)'.', 0,(byte)'t', 0,(byte)'x', 0,(byte)'t', 0,0,
                   /*Body*/0x48, 0,19, 0,(byte)'a', 0,(byte)'a', 0,(byte)'a', 
                        0,(byte)'.', 0,(byte)'t', 0,(byte)'x', 0,(byte)'t', 0,0
            };
            int? choice;
            while (true) {
                choice = console.ReadOptionalInteger(
                    "1. Complete (one packet), 2. Truncated in front, 3. Truncated in back, 4. Truncated before final packet");
                if (!choice.HasValue || (choice.Value >= 1 && choice.Value <= 4))
                    break;
                console.WriteLine("Invalid selection.");
            }
            byte[] buf;
            switch (choice) {
                case null:
                case 1:
                    buf = bufValid;
                    break;
                case 2:
                    buf = bufTruncatedInFront;
                    break;
                case 3:
                    buf = bufTruncatedInRear;
                    break;
                case 4:
                    buf = bufTruncateBeforeFinal;
                    break;
                default:
                    throw new ArgumentException("Invalid selection: " + choice);
            }
            peer.Write(buf, 0, buf.Length);
            peer.Flush(); // just in case
            console.ReadLine("Waiting before closing the connection");
            peer.Close();
        }

        //----
        [MenuItem, SubMenu("Device Discovery")]
        public void DiscoverAll()
        {
            BluetoothClient cli = Create_BluetoothClient();
            DateTime startTime = DateTime.Now;
            BluetoothDeviceInfo[] devices = cli.DiscoverDevices();
            DateTime endTime = DateTime.Now;
            DumpDeviceInfo(devices, startTime, endTime);
        }

        [MenuItem, SubMenu("Device Discovery")]
        public void DiscoverAllAsync()
        {
            BluetoothClient cli = Create_BluetoothClient();
            const int DefaultTimeout = 30;
            TimeSpan? timeout = console.ReadTimeSecondsOptional("Set InquiryLength (default " + DefaultTimeout + "secs)");
            if (timeout == null) {
                timeout = TimeSpan.FromSeconds(DefaultTimeout);
            }
            cli.InquiryLength = timeout.Value;
            EventHandler dlgt = delegate {
                DateTime startTime = DateTime.Now;
                DiscoState1 state = new DiscoState1(cli, startTime);
                IAsyncResult ar = cli.BeginDiscoverDevices(255,
                    true, true, true, false,
                    RestartDiscoCallback, state);
            };
#if NETCF
            bool fromUi = console.ReadYesNo("Start first discovery from UI thread?", false);
#else
            bool fromUi = false;
#endif
            if (fromUi) {
                console.UiInvoke(dlgt);
            } else {
                dlgt(null, null);
            }
            //
            console.Pause("Do continue when discovery has completed");
        }

        class DiscoState1
        {
            public readonly BluetoothClient cli;
            public readonly DateTime startTime;

            public DiscoState1(BluetoothClient cli, DateTime startTime)
            {
                this.cli = cli;
                this.startTime =startTime;
            }
        }

        void SimpleDiscoCallback(IAsyncResult ar)
        {
            DiscoState1 state = (DiscoState1)ar.AsyncState;
            try {
                BluetoothDeviceInfo[] devices = state.cli.EndDiscoverDevices(ar);
                DateTime endTime = DateTime.Now;
                DumpDeviceInfoBrief(devices, state.startTime, endTime);
            } catch (Exception ex) {
                console.WriteLine("Discovery failed with: " + ex);
            }
        }

        void RestartDiscoCallback(IAsyncResult ar)
        {
            SimpleDiscoCallback(ar);
            bool startAgainInCallback = console.ReadYesNo("Start discovery again from callback", false);
            if (startAgainInCallback) {
                DiscoState1 state0 = (DiscoState1)ar.AsyncState;
                DiscoState1 state = new DiscoState1(state0.cli, DateTime.Now);
                IAsyncResult ar2 = state.cli.BeginDiscoverDevices(255,
                    true, true, true, false,
                    SimpleDiscoCallback, state);
            }
        }

        [MenuItem, SubMenu("Device Discovery")]
        public void DiscoverRemembered()
        {
            BluetoothClient cli = Create_BluetoothClient();
            DateTime startTime = DateTime.Now;
            BluetoothDeviceInfo[] devices = cli.DiscoverDevices(255, false, true, false);
            DateTime endTime = DateTime.Now;
            DumpDeviceInfo(devices, startTime, endTime);
        }

        [MenuItem, SubMenu("Device Discovery")]
        public void DiscoverFlags()
        {
            DiscoverFlags_(false);
        }

        [MenuItem, SubMenu("Device Discovery")]
        void DiscoverFlagsAsync()
        {
            DiscoverFlags_(true);
        }

        private void GetDiscoveryFlags(MenuSystem console, out bool discoOnly, out bool auth, out bool rembd, out bool unk)
        {
            console.WriteLine("Discover which type of remote devices?");
            discoOnly = console.ReadYesNo("discoverableOnly", false);
            unk = console.ReadYesNo("Unknown", false);
            rembd = console.ReadYesNo("Remembered", false);
            auth = console.ReadYesNo("Authenticated", false);
        }

        public void DiscoverFlags_(bool async)
        {
            BluetoothClient cli = Create_BluetoothClient();
            bool discoOnly, auth, rembd, unk;
            GetDiscoveryFlags(console, out discoOnly, out auth, out rembd, out unk);
            BluetoothDeviceInfo[] devices;
            //
            TimeSpan? timeout = console.ReadTimeSecondsOptional("InquiryLength");
            if (timeout != null) {
                cli.InquiryLength = timeout.Value;
            }
            console.WriteLine("cli.InquiryLength is: {0}", cli.InquiryLength);
            //
            DateTime startTime = DateTime.Now;
            if (async) {
                IAsyncResult ar = cli.BeginDiscoverDevices(255, auth, rembd, unk, discoOnly,
                    MiscCallback, "BeginDiscoverDevices");
                console.WriteLine("(BeginDiscoverDevices returned)");
                devices = cli.EndDiscoverDevices(ar);
            } else {
                devices = cli.DiscoverDevices(255, auth, rembd, unk, discoOnly);
            }
            DateTime endTime = DateTime.Now;
            DumpDeviceInfo(devices, startTime, endTime);
            bool dispose = console.ReadYesNo("Dispose BtCli", false);
            if (dispose && cli != null) {
                cli.Dispose();
            }
        }

        [MenuItem, SubMenu("Device Discovery")]
        public void Discover_RunAllFlagCombinations()
        {
            BluetoothClient cli = Create_BluetoothClient();
            DateTime startTime = DateTime.Now;
            bool discoOnly, authenticated, remembered, unknown;
            int flagSource = 0;
            while (true) {
                authenticated = (flagSource & 1) != 0;
                remembered = (flagSource & 2) != 0;
                unknown = (flagSource & 4) != 0;
                discoOnly = (flagSource & 8) != 0;
                //
                BluetoothDeviceInfo[] devices = cli.DiscoverDevices(255, 
                    authenticated, remembered, unknown, discoOnly);
                console.WriteLine("Got {0} results", devices.Length);
                //
                if (authenticated && remembered && unknown && discoOnly)
                    break; // Have tested all cases of the original four flags.
                ++flagSource;
                Thread.Sleep(2000); // This sequence hangs on my W2k+Widcomm box -- does delaying help...?
            }//while
            //DateTime endTime = DateTime.Now;
            //DumpDeviceInfo(devices, startTime, endTime);
            console.WriteLine("All DiscoverDevices flag combinations run.");
        }

        const string vbCrLf = "\r\n";
        void DumpDeviceInfo(BluetoothDeviceInfo[] devices,
            DateTime startTime, DateTime endTime)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            DateTime localTime = startTime.ToLocalTime();
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                "Discovery process started at {0} UTC, {1} local, and ended at {2} UTC.",
                startTime, localTime, endTime);
            sb.Append(vbCrLf + vbCrLf);
            console.WriteLine(sb.ToString());
            foreach (BluetoothDeviceInfo curDevice in devices) {
                sb.Length = 0;
                DumpDeviceInfo(sb, curDevice);
                console.WriteLine(sb.ToString());
            }
        }

        void DumpDeviceInfoBrief(BluetoothDeviceInfo[] devices,
            DateTime startTime, DateTime endTime)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            DateTime localTime = startTime.ToLocalTime();
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                "Discovery process started at {0} UTC, {1} local, and ended at {2} UTC.",
                startTime, localTime, endTime);
            console.WriteLine(sb.ToString());
            foreach (BluetoothDeviceInfo curDevice in devices) {
                sb.Length = 0;
                DumpDeviceInfoBrief(sb, curDevice);
                console.WriteLine(sb.ToString());
            }
        }

        private static void DumpDeviceInfoBrief(StringBuilder sb, BluetoothDeviceInfo curDevice)
        {
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                "* {0}", curDevice.DeviceName);
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                ", Address: {0}", curDevice.DeviceAddress);
        }

        private static string DumpDeviceInfoBrief(BluetoothDeviceInfo curDevice)
        {
            System.Text.StringBuilder sb = new StringBuilder();
            DumpDeviceInfoBrief(sb, curDevice);
            return sb.ToString();
        }

        private static void DumpDeviceInfo(System.Text.StringBuilder sb, BluetoothDeviceInfo curDevice)
        {
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                "* {0}", curDevice.DeviceName);
            sb.Append(vbCrLf);
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                "Address: {0}", curDevice.DeviceAddress);
            sb.Append(vbCrLf);
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                "Remembered: {2}, Authenticated: {0}, Connected: {1}",
                curDevice.Authenticated, curDevice.Connected, curDevice.Remembered);
            sb.Append(vbCrLf);
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                "LastSeen: {0} ({2}), LastUsed: {1} ({3})",
                curDevice.LastSeen, curDevice.LastUsed,
                curDevice.LastSeen.Kind, curDevice.LastUsed.Kind);
            sb.Append(vbCrLf);
            DumpCodInfo(curDevice.ClassOfDevice, sb);
            Int32 rssi = curDevice.Rssi;
            if (rssi != Int32.MinValue) {
                sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                    "Rssi: {0} (0x{0:X})", rssi);
            } else {
                sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                    "Rssi: failed");
            }
            sb.Append(vbCrLf);
        }

        private static string DumpDeviceInfo(BluetoothDeviceInfo curDevice)
        {
            System.Text.StringBuilder sb = new StringBuilder();
            DumpDeviceInfo(sb, curDevice);
            return sb.ToString();
        }

        static void DumpCodInfo(ClassOfDevice cod, System.Text.StringBuilder sb)
        {
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                "CoD: (0x{0:X6})", cod.Value, cod);
            sb.Append(vbCrLf);
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                " Device:  {0} (0x{1:X2}) / {2} (0x{3:X4})", cod.MajorDevice, (int)cod.MajorDevice, cod.Device, (int)cod.Device);
            sb.Append(vbCrLf);
            sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                " Service: {0} (0x{1:X2})", cod.Service, (int)cod.Service);
            sb.Append(vbCrLf);
        }

        [MenuItem, SubMenu("Device Discovery")]
        public void DiscoveryUi()
        {
            bool discoOnly, auth, rembd, unk;
            GetDiscoveryFlags(console, out discoOnly, out auth, out rembd, out unk);
            InTheHand.Windows.Forms.SelectBluetoothDeviceDialog dlg = new InTheHand.Windows.Forms.SelectBluetoothDeviceDialog();
            dlg.ShowAuthenticated = auth;
            dlg.ShowRemembered = rembd;
            dlg.ShowUnknown = unk;
            System.Windows.Forms.DialogResult rslt = dlg.ShowDialog();
            console.WriteLine("DialogResult: {0}, Selected: {1}", rslt,
                dlg.SelectedDevice == null ? "(null)" : ("'" + dlg.SelectedDevice.DeviceName + "' " + dlg.SelectedDevice.DeviceAddress.ToString("C")));
        }


        //----
#if TEST_EARLY
        [MenuItem, SubMenu("SDP")]
        public void HackServiceDiscovery()
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("SDP server BluetoothAddress");
            try {
                BluetoothClient cli0 = new BluetoothClient();
                // Don't dispose this to check its Finalization.
                InTheHand.Net.Bluetooth.Widcomm.ISdpDiscoveryRecordsBuffer recs
                    = cli0.WidcommHack__GetServiceRecordsUnparsed(addr, BluetoothService.L2CapProtocol);
                console.WriteLine("recordCount: {0}", recs.RecordCount);
                //
                int[] ports = recs.Hack_GetPorts();
#if !NETCF
                string[] txtArr = Array.ConvertAll<int, string>(ports,
                    delegate(int cur) { return cur.ToString(); });
#else
                string[] txtArr = new string[ports.Length];
                for (int i = 0; i < ports.Length; ++i)
                    txtArr[i] = ports[i].ToString();
#endif
                string txt = string.Join(", ", txtArr);
                console.WriteLine("Ports: {0}", txt);
                //
                ServiceRecord[] recordArr = recs.GetServiceRecords();
                foreach (ServiceRecord cur in recordArr) {
                    console.WriteLine(
                        ServiceRecordUtilities.Dump(cur));
                }
            } catch (Exception ex) {
                console.WriteLine(ex);
            }
        }
#endif

        [MenuItem, SubMenu("SDP")]
        public void SdpQuery()
        {
            SdpQuery_();
        }

        void SdpQuery_()
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("SDP server BluetoothAddress");
            Guid? svcClass = console.ReadOptionalBluetoothUuid("Search UUID (default L2CAP->all)");
            if (svcClass == null) {
                svcClass = BluetoothService.L2CapProtocol;
            }
            bool async = console.ReadYesNo("Async Get", true);
            try {
                BluetoothDeviceInfo bdi = Create_BluetoothDeviceInfo(addr);
                ServiceRecord[] recordArr;
                if (async) {
                    console.WriteLine("Calling BeginGetServiceRecords({0})", (Guid)svcClass);
                    IAsyncResult ar = bdi.BeginGetServiceRecords((Guid)svcClass,
                            MiscCallback, "BeginGetServiceRecords");
                    console.WriteLine("BeginGetServiceRecords returned");
                    recordArr = bdi.EndGetServiceRecords(ar);
                } else {
                    console.WriteLine("Calling GetServiceRecords({0})", (Guid)svcClass);
                    recordArr = bdi.GetServiceRecords((Guid)svcClass);
                }
                //
                console.WriteLine("recordCount: {0}", recordArr.Length);
                int i = 1;
                foreach (ServiceRecord cur in recordArr) {
                    console.WriteLine("{0})", i);
                    console.WriteLine(
                        ServiceRecordUtilities.Dump(cur));
                    console.WriteLine("----");
                    ++i;
                }
            } catch (Exception ex) {
                console.WriteLine(ex);
            }
        }

        [MenuItem, SubMenu("SDP")]
        public void SdpCreateCustom()
        {
            ServiceRecord record = CreateAVariousRecord();
            BluetoothListener lsnr = Create_BluetoothListener(BluetoothService.HealthDeviceSink,
                record);
            lsnr.Start();
            console.Pause("Hit return to stop the server");
            lsnr.Stop();
        }

        private static ServiceRecord CreateAVariousRecord()
        {
            MyFunc<ElementType, ServiceAttributeId> createId = delegate(ElementType etX) {
                return (ServiceAttributeId)0x4000 + checked((byte)etX);
            };
            ServiceRecordBuilder bldr = new ServiceRecordBuilder();
            bldr.AddServiceClass(BluetoothService.HealthDevice);
            bldr.ServiceName = "alan";
            IList<ServiceAttribute> attrList = new List<ServiceAttribute>();
            ElementType et_;
#if SUPPORT_NIL
            et_ = ElementType.Nil;
            attrList.Add(new ServiceAttribute(createId(et_), new ServiceElement(et_, null)));
#endif
            et_ = ElementType.Boolean;
            attrList.Add(new ServiceAttribute(createId(et_), new ServiceElement(et_, true)));
            ElementType[] weee = {
                ElementType.UInt8,  ElementType.UInt16, ElementType.UInt32, ElementType.UInt64, //UInt128,
                ElementType.Int8,   ElementType.Int16,  ElementType.Int32,  ElementType.Int64,  //Int128,
            };
            foreach (ElementType et in weee) {
                attrList.Add(new ServiceAttribute(
                    createId(et),
                    ServiceElement.CreateNumericalServiceElement(et, (uint)et)));
            }
            et_ = ElementType.Uuid16;
            attrList.Add(new ServiceAttribute(createId(et_),
                new ServiceElement(et_, (UInt16)et_)));
            et_ = ElementType.Uuid32;
            attrList.Add(new ServiceAttribute(createId(et_),
                new ServiceElement(et_, (UInt32)et_)));
            et_ = ElementType.Uuid128;
            attrList.Add(new ServiceAttribute(createId(et_),
                new ServiceElement(et_, BluetoothService.CreateBluetoothUuid((int)et_))));
            bldr.AddCustomAttributes(attrList);
            bldr.AddCustomAttributes(ElementsAndVariableAndFixedInDeepTree1());
            ServiceRecord record = bldr.ServiceRecord;
            return record;
        }

        public const String RecordBytes_OneString_StringValue = "abcd\u00e9fgh\u012dj";
        public static IList<ServiceAttribute> ElementsAndVariableAndFixedInDeepTree1()
        {
            IList<ServiceAttribute> attrs = new List<ServiceAttribute>();
            //
            String str = RecordBytes_OneString_StringValue;
            ServiceElement itemStr1 = new ServiceElement(ElementType.TextString, str);
            ServiceElement itemStr2 = new ServiceElement(ElementType.TextString, str);
            //
            Uri uri = new Uri("http://example.com/foo.txt");
            ServiceElement itemUrl = new ServiceElement(ElementType.Url, uri);
            //
            ServiceElement itemF1 = new ServiceElement(ElementType.UInt16, (UInt16)0xfe12);
            ServiceElement itemF2 = new ServiceElement(ElementType.UInt16, (UInt16)0x1234);
            //
            IList<ServiceElement> leaves2 = new List<ServiceElement>();
            leaves2.Add(itemStr1);
            leaves2.Add(itemUrl);
            leaves2.Add(itemF1);
            ServiceElement e2 = new ServiceElement(ElementType.ElementSequence, leaves2);
            //
            ServiceElement e1 = new ServiceElement(ElementType.ElementSequence, e2);
            //
            IList<ServiceElement> leaves0 = new List<ServiceElement>();
            leaves0.Add(e1);
            leaves0.Add(itemStr2);
            leaves0.Add(itemF2);
            attrs.Add(
                new ServiceAttribute(0x0401, new ServiceElement(ElementType.ElementAlternative,
                        leaves0)));
            return attrs;
        }

        [MenuItem, SubMenu("SDP")]
        public void SdpCreateDeviceInfoRecord()
        {
            ServiceRecord record = CreateADeviceInfoRecord();
            BluetoothListener lsnr = Create_BluetoothListener(BluetoothService.HealthDeviceSink,
                record);
            lsnr.Start();
            console.Pause("Hit return to stop the server");
            lsnr.Stop();
        }

        private ServiceRecord CreateADeviceInfoRecord()
        {
            ServiceRecordBuilder bldr = new ServiceRecordBuilder();
            // Listener needs this. :-(
            bldr.ProtocolType = BluetoothProtocolDescriptorType.GeneralObex;
            bldr.AddServiceClass(BluetoothService.PnPInformation);
            bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.SpecificationId,
                ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 1)));
            bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.VendorId,
                ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 2)));
            bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.ProductId,
                ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 3)));
            bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.Version,
                ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 4)));
            bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.PrimaryRecord,
                new ServiceElement(ElementType.Boolean, true)));
            bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.VendorIdSource,
                ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 6)));
            return bldr.ServiceRecord;
        }

        delegate TResult MyFunc<T0, TResult>(T0 p0);
        delegate TResult MyFunc<T0, T1, TResult>(T0 p0, T1 p1);

        //----
        [MenuItem, SubMenu("Data")]
        public void SendLots()
        {
            if (!VerifyConnectionWrite())
                return;
            byte[] data = MakeLotsData();
            Lots_CheckTheTest(ref data);
            bool async = console.ReadYesNo("Async", true);
            if (async) {
                IAsyncResult ar = peer.BeginWrite(data, 0, data.Length, MiscCallback, "BeginWrite");
                console.WriteLine("Started writing (async), len: {0}.", data.Length);
                peer.EndWrite(ar);
            } else {
                peer.Write(data, 0, data.Length);
            }
            console.WriteLine("Finished writing.");
        }

        [MenuItem, SubMenu("Data")]
        public void SendLots_InSizedChunks()
        {
            if (!VerifyConnectionWrite())
                return;
            byte[] data = MakeLotsData();
            Lots_CheckTheTest(ref data);
            IList<byte[]> dataList = SplitIntoChunks(data, 999);
            bool async = console.ReadYesNo("Async", true);
            if (async) {
                List<IAsyncResult> arList = new List<IAsyncResult>(dataList.Count);
                int total = 0;
                foreach (byte[] cur in dataList) {
                    IAsyncResult ar = peer.BeginWrite(cur, 0, cur.Length, EmptyCallback, "BeginWrite");
                    total += cur.Length;
                    console.Write(".");
                    arList.Add(ar);
                }
                console.WriteLine("Did BeginWrite all chunks ({2}, async), len: {0} is {1}.", total, data.Length, arList.Count);
                foreach (IAsyncResult cur in arList) {
                    peer.EndWrite(cur);
                }
                console.WriteLine("Did EndWrite all chunks.");
            } else {
                foreach (byte[] chunk in dataList) {
                    console.WriteLine("chunk={0}", chunk.Length);
                    peer.Write(chunk, 0, chunk.Length);
                }
            }
            console.WriteLine("Finished writing.");
        }

        private void Lots_CheckTheTest(ref byte[] data)
        {
            bool testChecking1 = console.ReadYesNo("check the TEST, set one byte wrong", false);
            if (testChecking1) {
                data[1030000] ^= 255;
            }
            int hackOffset = 1040000;
            bool testChecking2 = console.ReadYesNo("check the TEST, add two bytes at " + hackOffset, false);
            if (testChecking2) {
                byte[] dataSlodged = new byte[data.Length + 2];
                Array.Copy(data, 0, dataSlodged, 0, hackOffset);
                Array.Copy(data, hackOffset, dataSlodged, 2 + hackOffset, data.Length - hackOffset);
                data = dataSlodged;
            }
        }

        private IList<byte[]> SplitIntoChunks(byte[] data, int chunkSize)
        {
            int offset = 0;
            List<byte[]> chunkList = new List<byte[]>(data.Length / chunkSize + 1);
            while (offset < data.Length) {
                int curSize = Math.Min(chunkSize, data.Length - offset);
                byte[] cur = new byte[curSize];
                Array.Copy(data, offset, cur, 0, cur.Length);
                offset += cur.Length;
                chunkList.Add(cur);
            }
            if (offset != data.Length)
                throw new InvalidOperationException("NOT offset==data.Length: " + offset + " vs " + data.Length);
            return chunkList;
        }

        private byte[] MakeLotsData()
        {
            byte[] data = new byte[1 * 1024 * 1024];
            bool useRandom = console.ReadYesNo("Random data", true);
            if (useRandom) {
                Random r = new Random(999);
                r.NextBytes(data);
            } else {
                for (int i = 0; i < data.Length; ++i) {
                    data[i] = unchecked((byte)i);
                    if (data[i] == 0) // Don't allow zeros, to se if that bug occurs.
                        data[i] = 255;
                }
            }
            return data;
        }

        [MenuItem, SubMenu("Data")]
        public void ReadLots()
        {
            if (!VerifyConnectionRead())
                return;
            byte[] expectedData = MakeLotsData();
            ReadLotsState state = new ReadLotsState(peer, expectedData);
            state.data = new byte[expectedData.Length + 20];
            ReadLotsStartNextRead(state);
            console.Pause("Hit return to stop");
            //lock (readLotsCurAr) {
            //    readLotsCurAr.
            //}
        }

        IAsyncResult readLotsCurAr;

        private void ReadLotsStartNextRead(ReadLotsState state)
        {
            if (state.numCompletedSynchronously > ReadLotsState.MaxCompletedSynchronously) {
                // (There's lots of pending data and thus) We've CompletedSynchronously
                // *many* times, so there's a danger of stack overflow 
                // (BeginRead->callback->BeginRead->callback->BeginRead->callback->...),
                // so start the next operation on a new thread.
                WaitCallback dlgt = delegate(object stateP) {
                    ReadLotsState state0 = (ReadLotsState)stateP;
                    state.numCompletedSynchronously = 0;
                    ReadLotsStartNextRead(state);
                };
                ThreadPool.QueueUserWorkItem(dlgt);
                return;
            }
            readLotsCurAr = state.peer.BeginRead(state.data, state.totalLen, state.data.Length - state.totalLen,
                ReadLotsReadCallBack, state);
            console.Write("-");
        }

        class ReadLotsState
        {
            public ReadLotsState(Stream peer, byte[] expectedData)
            {
                this.peer = peer;
                this.expectedData = expectedData;
            }

            public Stream peer;
            public byte[] data;
            public int totalLen;
            //
            public byte[] expectedData;
            //
            public int numCompletedSynchronously;
            public const int MaxCompletedSynchronously = 50;
        }

        void ReadLotsReadCallBack(IAsyncResult ar)
        {
            ReadLotsState state = (ReadLotsState)ar.AsyncState;
            int readLen ;
            try {
                readLen = state.peer.EndRead(ar);
            } catch (ObjectDisposedException) {
                console.WriteLine("Connection was closed during ReadLots.");
                console.WriteLine("???, hit return to continue.");
                return;
            }
            console.Write(">{1} ({0}) ", readLen, state.totalLen + readLen);
            ArraysEqual(state.expectedData, state.data, state.totalLen, readLen);
            state.totalLen += readLen;
            if (ar.CompletedSynchronously)
                ++state.numCompletedSynchronously;
            else
                state.numCompletedSynchronously = 0;
            if (state.totalLen == state.expectedData.Length) {
                console.WriteLine("got all!");
                return;
            }
            //
            if (readLen == 0) {
                console.WriteLine("EoF, hit return to continue.");
                return;
            }
            ReadLotsStartNextRead(state);
        }

        private void ArraysEqual(byte[] expected, byte[] actual, int offset, int count)
        {
            for (int i = 0; i < count; ++i) {
                if (offset + i >= expected.Length) {
                    console.WriteLine("!! ({0}+{1}=>) {2} >= {3}",offset , i, (offset + i), expected.Length);
                }
                if (offset + i >= actual.Length) {
                    console.WriteLine("!! ({0}+{1}=>) {2} >= {3}", offset, i, (offset + i), actual.Length);
                }
                if (expected[offset + i] != actual[offset + i]) {
                    console.WriteLine("wrong at {0}+{1}={2}", offset, i, offset + i);
                    break;
                }
            }
        }

        //----
        [MenuItem]
        public void BluetoothRadio_GetAll()
        {
            BluetoothRadio_GetAll__();
        }

        BluetoothRadio[] BluetoothRadio_GetAll__()
        {
            BluetoothRadio[] list = BluetoothRadio.AllRadios;
            if (list == null)
                console.WriteLine("AllRadios returned null!!!");
            else if (list.Length == 0)
                console.WriteLine("AllRadios returned empty list.");
            int i = 1;
            foreach (BluetoothRadio r in list) {
                console.WriteLine("{0})  {1}", i, DumpBluetoothRadio(r));
                ++i;
            }
            return list;
        }

        [MenuItem]
        public void BluetoothRadio_GetPrimary()
        {
            BluetoothRadio r = BluetoothRadio.PrimaryRadio;
            if (r == null)
                console.WriteLine("PrimaryRadio returned null.");
            else
                console.WriteLine(DumpBluetoothRadio(r));
        }

        private static string DumpBluetoothRadio(BluetoothRadio radio)
        {
            if (radio == null)
                throw new ArgumentNullException("radio");
            using (StringWriter wtr = new StringWriter()) {
                RadioMode mode = radio.Mode;
                // Warning: LocalAddress is null if the radio is powered-off.
                wtr.WriteLine("Radio, address: {0:C}", radio.LocalAddress);
                wtr.WriteLine("Mode: " + mode.ToString());
                wtr.WriteLine("Name: " + radio.Name
                    + ", LmpSubversion: " + radio.LmpSubversion);
                wtr.WriteLine("ClassOfDevice: " + radio.ClassOfDevice.ToString()
                    + ", device: " + radio.ClassOfDevice.Device.ToString()
                    + " / service: " + radio.ClassOfDevice.Service.ToString());
                wtr.WriteLine("Software: {0},  Hardware: {1}, status: {2}",
                    radio.SoftwareManufacturer, radio.Manufacturer, radio.HardwareStatus);
                wtr.WriteLine("Remote: '{0}'", radio.Remote);
                return wtr.ToString();
            }
        }


        //----
#if TEST_EARLY
        [MenuItem, SubMenu("BtLsnr")]
        public void WidcommHackListen()
        {
            BluetoothAddress addr = BluetoothAddress.None;
            //BluetoothAddress addr = console.ReadBluetoothAddress("Server's local BluetoothAddress");
            Guid svcClass = BluetoothService.WapClient;
            console.WriteLine("Default UUID : {0}", svcClass);
            Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID");
            if (inputGuid.HasValue)
                svcClass = inputGuid.Value;
            int? port = console.ReadOptionalInteger("Port number");
            //
            BluetoothEndPoint rep;
            if (port == null)
                rep = new BluetoothEndPoint(addr, svcClass);
            else
                rep = new BluetoothEndPoint(addr, svcClass, port.Value);
            console.WriteLine("Connecting to: {0}:{1}:{2}", rep.Address, rep.Service, rep.Port);
            //
            InTheHand.Net.Bluetooth.Widcomm.WidcommBluetoothListener lsnr
                = new InTheHand.Net.Bluetooth.Widcomm.WidcommBluetoothListener();
            lsnr.Construct(rep);
            lsnr.Start();
            BluetoothClient conn = lsnr.AcceptBluetoothClient();
            peer = conn.GetStream();
            s_cli = new WeakReferenceT<BluetoothClient>(conn);
        }
#endif

        [MenuItem, SubMenu("GC")]
        public void RunFinalizersAfterGc()
        {
            RunFinalizersAfterGc_();
        }

        public static void RunFinalizersAfterGc_()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        [MenuItem, SubMenu("GC")]
        public void RunGc()
        {
            RunGc_();
        }

        public static void RunGc_()
        {
            GC.Collect();
        }

        //----------
        [MenuItem, SubMenu("OBEX")]
        public void ObexWebRequest()
        {
            string addr = console.ReadLine("Address (IrDA / TCP/IP; hit return for BT)");
            if (addr.Length == 0) {
                BluetoothAddress addrB = console.ReadBluetoothAddress("Target Bluetooth device");
                addr = addrB.ToString();
            }
            int? contentLen = console.ReadOptionalInteger("How much content (default ~60 bytes)");
            if (contentLen == null)
                contentLen = 60;
            //NOT on NETCF!
            //  UriBuilder bldr = new UriBuilder();
            //  bldr.Scheme = "obex";
            //  bldr.Path = "/obexpush1.txt";
            //  bldr.Host = addr.ToString();
            Uri uri = new Uri(string.Format(System.Globalization.CultureInfo.InvariantCulture,
                "{0}://{1}{2}", 
                "obex", addr, "/obexpush1.txt"));
            ObexWebRequest req = Create_ObexWebRequest(uri);
            using (Stream content = req.GetRequestStream()) {
                // Using a StreamWriter to write text to the stream...
                using (TextWriter wtr = new StreamWriter(content)) {
                    int i=0;
                    while (content.Length < contentLen) {
                        ++i;
                        wtr.WriteLine("Hello World GetRequestStream {0}",
                            // Write the time to the first line
                            i == 1 ? DateTime.Now.ToString() : i.ToString());
                        wtr.Flush(); // push through to stream
                    }
                    // Set the Length header value
                    req.ContentLength = content.Length;
                }
            }
            console.WriteLine("Calling GetResponse with " + req.ContentLength + " bytes of content...");
            ObexWebResponse rsp = (ObexWebResponse)req.GetResponse();
            console.WriteLine("Response Code: {0} (0x{0:X})", rsp.StatusCode);
        }

        [MenuItem, SubMenu("OBEX")]
        public void ObexWebRequest_GET()
        {
            string addr = console.ReadLine("Address (IrDA / TCP/IP; hit return for BT)");
            if (addr.Length == 0) {
                BluetoothAddress addrB = console.ReadBluetoothAddress("Target Bluetooth device");
                addr = addrB.ToString();
            }
            string path = console.ReadLine("Path");
            Uri uri = new Uri(string.Format(System.Globalization.CultureInfo.InvariantCulture,
                "{0}://{1}/{2}",
                "obex-ftp", addr, path));
            console.WriteLine("Using URL: '{0}'", uri);
            ObexWebRequest req = new ObexWebRequest(uri);
            req.Method = "GET";
            ObexWebResponse rsp = (ObexWebResponse)req.GetResponse();
            console.WriteLine("Response Code: {0} (0x{0:X})", rsp.StatusCode);
            using (Stream rspData = rsp.GetResponseStream()) {
                StreamReader rdr = new StreamReader(rspData);
                console.WriteLine("data, first line: '{0}'", rdr.ReadLine());
            }
        }

        [MenuItem, SubMenu("OBEX")]
        public void ObexListener()
        {
            m_lsnrStop = false;
            Interlocked.Exchange(ref m_lsnrId, 0);
            ObexListener lstnr = null;
            ObexTransport? proto = null;
            while (lstnr == null) {
                int? i = console.ReadOptionalInteger("Which ObexListener transport: 1. Bluetooth, 2. IrDA, 3. TCP/IP");
                if (!i.HasValue || i.Value == 1) {
                    proto = ObexTransport.Bluetooth;
                    lstnr = Create_ObexListener_Bluetooth();
                } else {
                    while (!proto.HasValue) {
                        switch (i) {
                            case 2:
                                proto = ObexTransport.IrDA;
                                break;
                            case 3:
                                proto = ObexTransport.Tcp;
                                break;
                            default:
                                // (No Trace.Fail on NETCFv2)
                                Trace.Assert(false, "invalid input: " + i);
                                break;
                        }
                    }
                    lstnr = new ObexListener(proto.Value);
                }
            }
            console.WriteLine("Created {0} ObexListener.", proto);
            lstnr.Start();
            console.WriteLine("OBEX listening");
            int? count = console.ReadOptionalInteger("How many acceptors threads? (1 by default)");
            if (count == null) {
                count = 1;
            }
            console.WriteLine("Starting acceptor...");
            for (int i = 0; i < count; ++i) {
                ThreadPool.QueueUserWorkItem(ObexListener_Worker, lstnr);
            }
            try {
                console.Pause("Hit return to continue; and close listener");
            } finally {
                m_lsnrStop = true;
                lstnr.Stop();
            }
        }

        private volatile bool m_lsnrStop;
        private int m_lsnrId;

        void ObexListener_Worker(object state)
        {
            int id = Interlocked.Increment(ref m_lsnrId);
            while (true) {
                ObexListener lstnr = (ObexListener)state;
                if (m_lsnrStop || !lstnr.IsListening) {
                    break;
                }
                ObexListenerContext ctx = null;
                try {
                    ctx = lstnr.GetContext();
                    if (ctx == null) {
                        console.WriteLine("{0}: OBEX null context!", id);
                        continue;
                    }
                    console.WriteLine("{0}: OBEX accepted lContext", id);
                    ObexListenerRequest req = ctx.Request;
                    console.WriteLine("{0}: OBEX lRequest url: {1}", id, req.RawUrl);
                } catch (Exception ex) {
                    console.WriteLine("{0}: OBEX ctx/req fault: {1}", id, ex);
                }
                ctx = null;
            }//while
        }


        //--------
#if TEST_EARLY
        [MenuItem, SubMenu("Security etc")]
        public void SetPain()
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("Address");
            string passphrase = console.ReadLine("Passphrase");
            using (BluetoothClient cli = new BluetoothClient()) {
               InTheHand.Net.Bluetooth.Widcomm.BOND_RETURN_CODE ret = cli.WidcommHack__SetPinX(addr, passphrase);
               console.WriteLine("Bond returned: {0} = 0x{1:X}", ret, (int)ret);
           }
        }
#endif

        [MenuItem, SubMenu("Security etc")]
        public void PairRequest()
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("Address");
            string passphrase = console.ReadLine("Passphrase");
            if (string.IsNullOrEmpty(passphrase)) {
                bool makeNull = console.ReadYesNo("Do you want to use a null/Nothing passphrase", true);
                passphrase = makeNull ? null : string.Empty;
            }
            InTheHand.Net.Bluetooth.Factory.IBluetoothSecurity sec
                = Get_BluetoothRadio().StackFactory.BluetoothSecurity;
            bool ret = sec.PairRequest(addr, passphrase);
            console.WriteLine("PairRequest returned: {0}", ret);
        }

        [MenuItem, SubMenu("Security etc")]
        public void RemoveDevice()
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("Address");
            bool ret = BluetoothSecurity.RemoveDevice(addr);
            console.WriteLine("RemoveDevice returned: {0}", ret);
        }

        //--------
        [MenuItem, SubMenu("MultiStack")]
        public void ListenerOnStack1ClientOnStack2()
        {
            BluetoothRadio[] radios = BluetoothRadio_GetAll__();
            Debug.Assert(radios != null, "Should't return null!");
            if (radios.Length < 2) {
                console.WriteLine("Fewer that two radios were found ({0}).", radios.Length);
                return;
            }
            //
            ListenerOnStackAClientOnStackB(radios[0], radios[1]);
        }

        [MenuItem, SubMenu("MultiStack")]
        public void ListenerOnStack2ClientOnStack1()
        {
            BluetoothRadio[] radios = BluetoothRadio_GetAll__();
            Debug.Assert(radios != null, "Should't return null!");
            if (radios.Length < 2) {
                console.WriteLine("Fewer that two radios were found ({0}).", radios.Length);
                return;
            }
            //
            ListenerOnStackAClientOnStackB(radios[1], radios[0]);
        }

        public void ListenerOnStackAClientOnStackB(BluetoothRadio radioLsnr, BluetoothRadio radioCli)
        {
            BluetoothListener lsnr = radioLsnr.StackFactory.CreateBluetoothListener(BluetoothService.Wap);
            BluetoothClient conn = null;
            BluetoothClient cli = null;
            try {
                lsnr.Start();
#if APM_LSNR
            IAsyncResult arLsnr = lsnr.BeginAcceptBluetoothClient(MiscCallback, "ListenerOnStack1ClientOnStack2");
#else
                ManualResetEvent accepted = new ManualResetEvent(false);
                WaitCallback dlgt = delegate(object state) {
                    BluetoothListener lsnr_ = (BluetoothListener)state;
                    conn = lsnr_.AcceptBluetoothClient();
                    accepted.Set();
                };
                conn = null;
                ThreadPool.QueueUserWorkItem(dlgt, lsnr);
#endif
                BluetoothEndPoint lep = lsnr.LocalEndPoint;
                console.WriteLine("Listener active on SCN: {0}", lep.Port);
                //
                cli = radioCli.StackFactory.CreateBluetoothClient();
                BluetoothEndPoint rep = new BluetoothEndPoint(radioLsnr.LocalAddress, BluetoothService.Empty, lep.Port);
                console.WriteLine("Gonna connect to: {0}", rep);
                console.Pause("Release to connect!");
                cli.Connect(rep);
                console.WriteLine("Client Connected to : '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint);
                //
#if APM_LSNR
            console.WriteLine("Lsnr.Accept.IsCompleted: {0}", arLsnr.IsCompleted);
            conn = lsnr.EndAcceptBluetoothClient(arLsnr);
#else
                console.WriteLine("waiting for Lsnr.Accept completion event.");
                accepted.WaitOne();
                Debug.Assert(conn != null, "Should have veen set by thread!");
#endif
                console.WriteLine("All success");
                console.Pause("Release to exit (and close both)");
            } finally {
                if (lsnr != null)
                    lsnr.Stop();
                if (conn != null)
                    conn.Dispose();
                if (cli != null)
                    cli.Dispose();
            }
        }

        [MenuItem, SubMenu("MultiStack")]
        public void ObexWebRequestMultiAsync()
        {
            BluetoothRadio[] radios = BluetoothRadio_GetAll__();
            Debug.Assert(radios != null, "Should't return null!");
            if (radios.Length < 1) {
                console.WriteLine("No radios found.");
                return;
            }
            //
            List<BluetoothAddress> addrList = new List<BluetoothAddress>();
            for (int i = 0; i < radios.Length;++i ) {
                BluetoothAddress addr = console.ReadBluetoothAddress(
                    "Target device for radio #" + (i+1));
                addrList.Add(addr);
            }//for
            bool bigSend = console.ReadYesNo("Send big (1MB) or small?", false);
            byte[] bigBuf = null;
            if (bigSend) {
                bigBuf = new byte[1024 * 1024];
#if !NETCF
                Array.ForEach(bigBuf, delegate(byte cur) { cur = (byte)'a'; });
#endif
            }
            List<IAsyncResult> arList = new List<IAsyncResult>(addrList.Count);
            for (int i = 0; i < radios.Length; ++i) {
                BluetoothAddress addr = addrList[i];
                Uri uri = new Uri(string.Format(System.Globalization.CultureInfo.InvariantCulture,
                    "{0}://{1}{2}",
                    "obex", addr, "/obexpush1.txt"));
                BluetoothPublicFactory factory = radios[i].StackFactory;
                ObexWebRequest req = factory.CreateObexWebRequest(uri);
                using (Stream content = req.GetRequestStream()) {
                    // Using a StreamWriter to write text to the stream...
                    if (bigSend) {
                        content.Write(bigBuf, 0, bigBuf.Length);
                    } else {
                        using (TextWriter wtr = new StreamWriter(content)) {
                            wtr.WriteLine("Hello World GetRequestStream");
                            wtr.WriteLine("Hello World GetRequestStream 2");
                            wtr.Flush();
                            // Set the Length header value
                            req.ContentLength = content.Length;
                        }
                    }
                }
                IAsyncResult ar = req.BeginGetResponse(null, req);
                arList.Add(ar);
            }//for
            //
            console.WriteLine("Waiting for all requests to complete...");
            WaitAll(arList);
            console.WriteLine("All requests completed...");
            //
            for (int i = 0; i < radios.Length; ++i) {
                IAsyncResult cur = arList[i];
                ObexWebRequest req = (ObexWebRequest)cur.AsyncState;
                console.WriteLine("- - - #{1} - - -", null, (i + 1));
                try {
                    ObexWebResponse rsp = (ObexWebResponse)req.EndGetResponse(cur);
                    console.WriteLine("#{1}. Response Code: {0} (0x{0:X})", rsp.StatusCode, (i + 1));
                } catch (Exception ex) {
                    console.WriteLine("#{1}. Failed: {0}", ex, (i + 1));
                }
            }//for
        }

        //----
        [MenuItem, SubMenu("Data")]
        public void SetReadTimeout()
        {
            if (peer == null) {
                console.WriteLine("no connection");
                return;
            }
            console.WriteLine("ReadTimeout: {0}", peer.ReadTimeout);
            int? to = console.ReadOptionalInteger("New value");
            if (to.HasValue)
                peer.ReadTimeout = to.Value;
        }

        [MenuItem, SubMenu("Data")]
        public void SetWriteTimeout()
        {
            if (peer == null) {
                console.WriteLine("no connection");
                return;
            }
            console.WriteLine("WriteTimeout: {0}", peer.WriteTimeout);
            int? v = console.ReadOptionalInteger("New value");
            if (v.HasValue)
                peer.WriteTimeout = v.Value;
        }

        //----
        Stream _tcpConn;

        [MenuItem]
        public void TcpConnect()
        {
            string hostname = console.ReadLine("hostname");
            int port = console.ReadInteger("port");
            System.Net.Sockets.TcpClient cli = new System.Net.Sockets.TcpClient(hostname, port);
            _tcpConn = cli.GetStream();
        }

        [MenuItem]
        public void TcpClose()
        {
            if (_tcpConn != null) {
                _tcpConn.Close();
            }
            _tcpConn = null;
        }

        //----
        [MenuItem]
        public void GetDeviceInfo()
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("Device Address");
            BluetoothDeviceInfo device = Create_BluetoothDeviceInfo(addr);
            console.WriteLine(DumpDeviceInfo(device));
        }

        [MenuItem]
        public void SetServiceState()
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("Device Address");
            Guid? svcClass = console.ReadOptionalBluetoothUuid("Service Class (default SPP)");
            if (svcClass == null) svcClass = BluetoothService.SerialPort;
            bool state = console.ReadYesNo("Enable/Disable the service", true);
            BluetoothDeviceInfo device = Create_BluetoothDeviceInfo(addr);
            console.WriteLine(DumpDeviceInfoBrief(device));
            device.SetServiceState(svcClass.Value, state, true);
        }

        [MenuItem]
        public void WidcommIsPresentConnected()
        {
            BluetoothAddress addr = console.ReadBluetoothAddress("Device Address");
            InTheHand.Net.Bluetooth.Widcomm.RemoteDeviceState state
                = new InTheHand.Net.Bluetooth.Widcomm.WidcommPlaying().FindIfPresentOrConnected(addr);
            console.WriteLine("state: {0}", state);
        }

        //----
#if !NETCF
        [MenuItem]
        public void WmiSerialPorts()
        {
            const string Win32_SerialPort = "Win32_SerialPort";
#if false // Either work
            console.WriteLine("Running query...");
            System.Management.SelectQuery q = new System.Management.SelectQuery(Win32_SerialPort);
            System.Management.ManagementObjectSearcher s = new System.Management.ManagementObjectSearcher(q);
#else
            console.WriteLine("Running WMI query...");
            System.Management.ManagementObjectSearcher s = new System.Management.ManagementObjectSearcher(
                "SELECT DeviceID,PNPDeviceID FROM " + Win32_SerialPort);
#endif
            console.WriteLine("Getting results...");
            System.Management.ManagementObjectCollection list = s.Get();
            console.WriteLine("Enumerating results...");
            foreach (System.Management.ManagementBaseObject cur in list) {
                object id = cur.GetPropertyValue("DeviceID");
                object pnpId = cur.GetPropertyValue("PNPDeviceID");
                console.WriteLine("DeviceID:    {0} ", id);
                console.WriteLine("PNPDeviceID: {0} ", pnpId);
                console.WriteLine("");
            }//for
            //----
            console.WriteLine("SerialPort.GetPortNames...");
            string[] nameList = System.IO.Ports.SerialPort.GetPortNames();
            console.WriteLine("SerialPort.GetPortNames: {0}",
                string.Join(", ", nameList));
        }
#endif

        //----
        [MenuItem, SubMenu("SOCKETS")]
        public void TestsSocketsAndSockaddr()
        {
            Converter<bool, System.Net.Sockets.Socket> createSocket = delegate(bool unspecificProto) {
                System.Net.Sockets.Socket s0;
                if (unspecificProto)
                    s0 = new System.Net.Sockets.Socket(
                        AddressFamily32.Bluetooth, System.Net.Sockets.SocketType.Stream,
                        System.Net.Sockets.ProtocolType.Unspecified);
                else
                    s0 = new System.Net.Sockets.Socket(
                        AddressFamily32.Bluetooth, System.Net.Sockets.SocketType.Stream,
                        BluetoothProtocolType.RFComm);
                return s0;
            };
            BluetoothEndPoint ep;
            System.Net.Sockets.Socket s;
            //
            int step = 0;
            console.WriteLine("#{0}, gonna createSocket(false)", ++step);
            s = createSocket(false);
            ep = new BluetoothEndPoint(
                BluetoothAddress.None,
                BluetoothService.ObexFileTransfer);
            console.WriteLine("#{0}, gonna Bind", ++step);
            // Bind     None/FTP/None
            try {
                s.Bind(ep);
            } catch (Exception ex) {
                console.WriteLine(ex);
            }
            ep = new BluetoothEndPoint(
                BluetoothAddress.Parse("12345679abcd"),
                BluetoothService.ObexObjectPush);
            console.WriteLine("#{0}, gonna Connect", ++step);
            // Connect  Foo/OPP/None
            try {
                s.Connect(ep);
            } catch (Exception ex) {
                console.WriteLine(ex);
            }
            //
            console.WriteLine("#{0}, gonna createSocket(false)", ++step);
            s = createSocket(false);
            ep = new BluetoothEndPoint(
                BluetoothAddress.None,
                BluetoothService.ObexFileTransfer,
                unchecked((Int32)0xF2345678));
            console.WriteLine("#{0}, gonna Bind", ++step);
            // Bind     None/FTP/Bar
            try {
                s.Bind(ep);
            } catch (Exception ex) {
                console.WriteLine("Excepted failure");
                console.WriteLine(ex);
            }
            //
            ep = new BluetoothEndPoint(
                BluetoothAddress.None,
                BluetoothService.ObexFileTransfer,
                0x45);
            console.WriteLine("#{0}, gonna Bind", ++step);
            // Bind     None/FTP/Bar
            try {
                s.Bind(ep);
            } catch (Exception ex) {
                console.WriteLine(ex);
            }
            //
            ep = new BluetoothEndPoint(
                BluetoothAddress.Parse("12345679abcd"),
                BluetoothService.Fax, 0x45);
            console.WriteLine("#{0}, gonna Connect", ++step);
            // Connect  Foo/OPP/Bar
            try {
                s.Connect(ep);
            } catch (Exception ex) {
                console.WriteLine(ex);
            }
            //
            console.WriteLine("#{0}, gonna createSocket(true)", ++step);
            try {
                s = createSocket(true);
            } catch (System.Net.Sockets.SocketException ex) {
                const int WSAEPROTOTYPE = 10041;
#if NETCF
                if (ex.ErrorCode != WSAEPROTOTYPE)
                    throw;
#else
                if (ex.SocketErrorCode != System.Net.Sockets.SocketError.ProtocolType)
                    throw;
#endif
                Trace.Assert(ex.NativeErrorCode == WSAEPROTOTYPE);
                console.WriteLine("(Somewhat) expected failure; how to get 'Unspecified' behaviour supported?");
                console.WriteLine(ex);
            }
        }

        //--------
        [MenuItem]
        public void RSSI_repeated()
        {
            console.WriteLine("Stack: {0}", Get_BluetoothRadio().SoftwareManufacturer);
            BluetoothAddress addr = console.ReadBluetoothAddress("Address of device to read RSSI for");
            bool doSdp = console.ReadYesNo("Do concurrent repeated SDP Query", true);
            //
            _quitRepeatRssiing.Reset();
            try {
                ThreadPool.QueueUserWorkItem(RepeatRssiing_ReadRssi, addr);
                if (doSdp) { // Doing SDP queries to force forming a connection.
                    ThreadPool.QueueUserWorkItem(RepeatRssiing_DoSdp, addr);
                }
                console.WriteLine(null);
                console.Pause("Continue to stop RSSI-ing");
            } finally {
                _quitRepeatRssiing.Set();
            }
        }

        ManualResetEvent _quitRepeatRssiing = new ManualResetEvent(false);

        void RepeatRssiing_ReadRssi(object state)
        {
            BluetoothAddress addr = (BluetoothAddress)state;
            int delayMs = 1000;
            BluetoothDeviceInfo info = Create_BluetoothDeviceInfo(addr);
            int? lastRssi = null;
            while (!_quitRepeatRssiing.WaitOne(delayMs, false)) {
                int rssi = info.Rssi;
                console.Write("r");
                if (rssi != lastRssi) {
                    lastRssi = rssi;
                    console.WriteLine(null);
                    console.WriteLine("{0:T}: RSSI now: {1}", DateTime.Now, rssi);
                }
            }//while
        }

        void RepeatRssiing_DoSdp(object state)
        {
            Thread.Sleep(5000); // show rssi not available when not connected
            //
            BluetoothAddress addr = (BluetoothAddress)state;
            int delayMs = 1000;
            BluetoothDeviceInfo info = Create_BluetoothDeviceInfo(addr);
            while (!_quitRepeatRssiing.WaitOne(delayMs, false)) {
                ServiceRecord[] records = info.GetServiceRecords(BluetoothService.TcpProtocol);
                console.Write("s");
            }//while
        }

        //--------
        [MenuItem]
        public void RadioSetMode()
        {
            BluetoothRadio r = Get_BluetoothRadio();
            if (r == null) {
                console.WriteLine("No radio(?)");
                return;
            }
            console.WriteLine("Radio stack is: {0}", r.SoftwareManufacturer);
            int choice = console.ReadInteger("0. PowerOff, 1. Connectable, 2. Discoverable");
            RadioMode mode = (RadioMode)choice;
            bool doit = console.ReadYesNo("Set radio mode to: " + mode, true);
            if (doit) {
                r.Mode = mode;
            }
        }


        //--------
        [MenuItem, SubMenu("Data")]
        public void CloseLinger()
        {
            if (!VerifyConnectionWrite())
                return;
            BluetoothClient cli = s_cli.Target;
            if (cli == null) {
                console.WriteLine("No BtCli to set LingerState on!.");
                return;
            }
            cli.LingerState = new System.Net.Sockets.LingerOption(true, 30);
            // Write until buffers full
            List<IAsyncResult> arList = new List<IAsyncResult>();
            byte[] buf = new byte[16 * 1024];
            bool exitAfterNext = false;
            while (true) {
                IAsyncResult ar = peer.BeginWrite(buf, 0, buf.Length, MiscCallback, "BeginWrite");
                arList.Add(ar);
                console.Write(".");
                if (exitAfterNext)
                    break;
                if (!ar.IsCompleted) {
                    bool signalled = ar.AsyncWaitHandle.WaitOne(10000, false);
                    if (!signalled) {
                        exitAfterNext = true;
                    }
                }
            }//while
            console.WriteLine("Did BeginWrite until full ({0} times).", arList.Count);
            //
            console.WriteLine("Now going to Close.  Release receiver to not linger timeout.");
            console.Pause("Continue to Close");
            console.WriteLine("Closing at {0}", GetTime());
            DateTime startT = DateTime.UtcNow;
            try {
                peer.Close();
                string end = GetTime();
                console.WriteLine("Close exited cleanly at {0} after {1}.", end, DateTime.UtcNow - startT);
            } catch (Exception ex) { // We throw Exception currently!
                string end = GetTime();
                console.WriteLine("Close failed at {0} after {1} with: {2}", end, DateTime.UtcNow - startT, ex);
            }
            //
            int i = 0;
            console.Write("Write statuses (. or x, x=exception): ");
            foreach (IAsyncResult cur in arList) {
                if (!cur.IsCompleted) {
                    console.WriteLine("Write #{0} is not completed!", i + 1);
                }
                try {
                    peer.EndWrite(cur);
                    console.Write(".");
                } catch (IOException) {
                    console.Write("x");
                }
                ++i;
            }//for
            console.WriteLine(null);
            console.WriteLine("Finished.");
        }

        //--------
        [MenuItem]
        public void HackShutdownAll()
        {
            InTheHand.Net.Bluetooth.Factory.BluetoothFactory.HackShutdownAll();
            console.WriteLine("Done HackShutdownAll");
        }

        //--------
        private string ToStringQuotedOrNull<T>(T obj)
        {
            if (obj == null)
                return "(null)";
            else
                return obj.ToString();
        }

        string Exception_FirstLine(Exception ex)
        {
            using (StringReader rdr = new StringReader(ex.ToString())) {
                return rdr.ReadLine();
            }
        }

    }//class

}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.