public static void ConnectToSession(this ApplicationCanvas that, ConnectToSessionVariation variation = ConnectToSessionVariation.Flash)
        {
            var nc = new NetConnection();

            var connected = false;

            Action<string> RaiseMessage =
                x =>
                {
                    that.About.Text = x + Environment.NewLine + that.About.Text;
                };

            Action<string> PostMessage =
                message =>
                {

                    RaiseMessage("drop: " + message);
                };

            #region AtNotifyBuildRocket
            that.AtNotifyBuildRocket +=
                (x, y) =>
                {
                    XElement BuildRocket = new DoubleVector2
                    {
                        X = x,
                        Y = y
                    };

                    PostMessage(
                        new XElement("Updates",
                            new XElement("BuildRocket", BuildRocket)
                       ).ToString()
                    );
                };
            #endregion


            #region AtNotifyVisualizeTouch
            that.AtNotifyVisualizeTouch +=
                 (x, y) =>
                 {
                     XElement VisualizeTouch = new DoubleVector2
                    {
                        X = x,
                        Y = y
                    };

                     PostMessage(
                         new XElement("Updates",
                             new XElement("VisualizeTouch", VisualizeTouch)
                        ).ToString()
                     );
                 };
            #endregion


            nc.netStatus +=
                e =>
                {
                    // http://stackoverflow.com/questions/10683595/cant-receive-netgroup-events

                    RaiseMessage("nc.netStatus: " + e.info.code);


                    if (e.info.code == "NetGroup.Connect.Success")
                    {
                        connected = true;
                        RaiseMessage("connected");
                        return;
                    }

                    if (e.info.code == "NetConnection.Connect.Success")
                    {
                        // http://kafkaris.com/blog/2011/04/03/local-peer-to-peer-communication-in-as3-with-rtmfp/
                        // http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/GroupSpecifier.html

                        var groupspec = new GroupSpecifier("goo");
                        groupspec.postingEnabled = true;
                        groupspec.routingEnabled = true;

                        // // Necessary to multicast over a NetStream. 
                        groupspec.multicastEnabled = true;

                        // // Must be enabled for LAN peer discovery to work 
                        groupspec.ipMulticastMemberUpdatesEnabled = true;

                        // http://help.adobe.com/en_US/flashmediaserver/ssaslr/WS486834a3d4bc74a45ce7a7ac126f44d8a30-8000.html
                        //groupspec.addIPMulticastAddress("225.225.0.1:30303");


                        // // Multicast address over which to exchange peer discovery. 
                        groupspec.addIPMulticastAddress("224.0.0.255:30000");


                        // Specify minimum GroupSpec version (FMS 4.5.2/Flash Player 11.5) 
                        groupspec.minGroupspecVersion = 2;

                        var group = new NetGroup(
                            nc,
                            groupspec.groupspecWithAuthorizations()
                            //groupspec.groupspecWithoutAuthorizations()
                        );

                        // http://stackoverflow.com/questions/10206097/netstream-send-not-working-with-netgroup-in-rtmfp

                        PostMessage =
                            message =>
                            {
                                if (connected)
                                {

                                    RaiseMessage("write: " + new { message.Length });
                                    //RaiseMessage("write: " + message);

                                    group.post(message);
                                }
                                else
                                {
                                    //RaiseMessage("skip: " + message);
                                }
                            };

                        //AtPostMessage += PostMessage;

                        group.netStatus +=
                            g =>
                            {

                                if (g.info.code == "NetGroup.Posting.Notify")
                                {
                                    // Type Coercion failed: cannot convert Object@60b6cb9 to LANMulticast_Components_MySprite1__f__AnonymousType0_1_33554444.

                                    var source = (string)g.info.message;

                                    RaiseMessage("group.netStatus: " + new { g.info.code, source });


                                    //Console.WriteLine("source: " + source);

                                    var xml = XElement.Parse(source);

                                    xml.Elements().Where(k => k.Name.LocalName == "BuildRocket").Elements().WithEach(
                                        ksource =>
                                        {
                                            //Console.WriteLine("BuildRocket: " + ksource);

                                            DoubleVector2 k = ksource;

                                            that.NotifyBuildRocket(k.X, k.Y);
                                        }
                                    );

                                    xml.Elements().Where(k => k.Name.LocalName == "VisualizeTouch").Elements().WithEach(
                                        ksource =>
                                        {
                                            //Console.WriteLine("VisualizeTouch: " + ksource);

                                            DoubleVector2 k = ksource;

                                            that.NotifyVisualizeTouch(k.X, k.Y);
                                        }
                                    );

                                    return;
                                }

                                RaiseMessage("group.netStatus: " + g.info.code);

                            };

                        return;
                    }
                };


            // X:\jsc.svn\examples\actionscript\FlashStratusDemo\FlashStratusDemo\ActionScript\OrcasFlashApplication.cs
            nc.connect("rtmfp:");
        }
        public static void InitializeConnection(
            this KeySample key, bool WriteMode = true, bool ReadMode = false,
            TextField text = null,

            Action<Action<string>> yield_PostMessage = null,
            Action<XElement> yield_Notify = null
            )
        {
            //var that = new { About };

            var nc = new NetConnection();

            var connected = false;

            Action<string> RaiseMessage =
                x =>
                {
                    if (text != null)
                    {
                        //text.text = x + Environment.NewLine + text.text;
                        text.text = x;
                    }
                };

            Action<string> PostMessage =
                message =>
                {

                    RaiseMessage("drop: " + message);
                };


            if (WriteMode)
            {
                var sync = new ScriptCoreLib.ActionScript.flash.utils.Timer(1000 / 60);
                var syncid = 0;

                var was = -1;

                sync.timer += delegate
                {
                    if (key.value == was)
                        if (was == 0)
                            return;

                    syncid++;

                    PostMessage(
                        new XElement("sync",
                           new XElement("KeySample",
                               new XAttribute("value", "" + key.value),
                               new XAttribute("forcex", "" + key.forcex),
                               new XAttribute("forcey", "" + key.forcey),
                               new XAttribute("syncid", "" + syncid)
                          )

                        ).ToString()
                       );

                    was = key.value;
                };

                sync.start();
            }

            //that.AtNotifyVisualizeTouch +=
            //     (x, y) =>
            //     {
            //         XElement VisualizeTouch = new DoubleVector2
            //         {
            //             X = x,
            //             Y = y
            //         };

            //         PostMessage(
            //             new XElement("Updates",
            //                 new XElement("VisualizeTouch", VisualizeTouch)
            //            ).ToString()
            //         );
            //     };


            nc.netStatus +=
                e =>
                {
                    RaiseMessage("nc.netStatus: " + e.info.code);


                    if (e.info.code == "NetGroup.Connect.Success")
                    {
                        connected = true;
                        RaiseMessage("connected, looking for long range coms... (7 to 30sec delay) might need to reset android wifi, pc wifi or wifi router itself!");
                        return;
                    }

                    if (e.info.code == "NetConnection.Connect.Success")
                    {
                        RaiseMessage("looking for long range coms... looking for permission...");


                        var groupspec = new GroupSpecifier("myGroup/groupOne");
                        groupspec.postingEnabled = true;
                        groupspec.ipMulticastMemberUpdatesEnabled = true;
                        groupspec.addIPMulticastAddress("225.225.0.1:30303");

                        var group = new NetGroup(nc, groupspec.groupspecWithAuthorizations());


                        PostMessage =
                            message =>
                            {
                                if (connected)
                                {

                                    RaiseMessage("write: " + message);

                                    group.post(message);
                                }
                                else
                                {
                                    RaiseMessage("skip: " + message);
                                }
                            };

                        if (yield_PostMessage != null)
                            yield_PostMessage(PostMessage);

                        //if (WriteMode)
                        //{
                        //    PostMessage(
                        //          new XElement("KeySample",
                        //              new XAttribute("value", "" + key.value)
                        //         ).ToString()
                        //      );
                        //}
                        //AtPostMessage += PostMessage;

                        group.netStatus +=
                            g =>
                            {

                                if (g.info.code == "NetGroup.Posting.Notify")
                                {
                                    // Type Coercion failed: cannot convert Object@60b6cb9 to LANMulticast_Components_MySprite1__f__AnonymousType0_1_33554444.

                                    var source = (string)g.info.message;

                                    //Console.WriteLine("source: " + source);
                                    RaiseMessage("source: " + source);

                                    var xml = XElement.Parse(source);

                                    //xml.Elements().Where(k => k.Name.LocalName == "BuildRocket").Elements().WithEach(
                                    //    ksource =>
                                    //    {
                                    //        //Console.WriteLine("BuildRocket: " + ksource);

                                    //        DoubleVector2 k = ksource;

                                    //        that.NotifyBuildRocket(k.X, k.Y);
                                    //    }
                                    //);

                                    if (yield_Notify != null)
                                    {
                                        yield_Notify(xml);
                                    }

                                    if (ReadMode)
                                    {
                                        //xml.Elements().Where(k => k.Name.LocalName == "KeySample").WithEach(
                                        xml.Elements("KeySample").WithEach(
                                            ksource =>
                                            {
                                                var value = int.Parse(ksource.Attribute("value").Value);
                                                var forcex = double.Parse(ksource.Attribute("forcex").Value);
                                                var forcey = double.Parse(ksource.Attribute("forcey").Value);

                                                //RaiseMessage("value: " + value);

                                                key.value = value;
                                                key.forcex = forcex;
                                                key.forcey = forcey;

                                                //Console.WriteLine("VisualizeTouch: " + ksource);
                                                //new XElement("value", "" + k.value)

                                                //DoubleVector2 k = ksource;

                                                //that.NotifyVisualizeTouch(k.X, k.Y);
                                            }
                                        );
                                    }

                                    return;
                                }

                                RaiseMessage("group.netStatus: " + g.info.code);

                            };

                        return;
                    }
                };

            nc.connect("rtmfp:");
        }
        //C:\util\flex_sdk_4.6\frameworks\flex-config.xml(47): Error: unable to open 'libs/player/11.1/playerglobal.swc'


        // http://www.adobe.com/devnet/flashplayer/articles/rtmfp_stratus_app_03.html

        // see this video:
        // http://tv.adobe.com/#vi+f15384v1056

        /// <summary>
        /// Default constructor
        /// </summary>
        public FlashStratusDemo()
        {

            var t = new TextField
            {
                multiline = true,
                text = "powered by jsc",
                background = true,
                x = 0,
                y = 0,
                width = 400,
                alwaysShowSelection = true,
            }.AttachTo(this);

            var c = new NetConnection();



            Func<NetStatusEvent, string> get_Code =
                e =>
                {
                    var info = new DynamicContainer { Subject = e.info };
                    var code = (string)info["code"];

                    return code;
                };


            c.netStatus +=
                status =>
                {
                    // http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/events/NetStatusEvent.html#info


                    t.appendText("\nc.netStatus: " + get_Code(status));

                    if (get_Code(status) == "NetConnection.Connect.Success")
                    {
                        t.appendText("\n" + c.nearID);

                        #region we could be a client

                        var q = new TextField
                        {
                            background = true,
                            x = 0,
                            y = 200,
                            width = 400,
                            alwaysShowSelection = true,
                            text = "enter id here",
                            type = TextFieldType.INPUT
                        }.AttachTo(this);


                        q.change +=
                            delegate
                            {
                                if (q.text.Length != c.nearID.Length)
                                    return;

                                if (q.text == c.nearID)
                                    return;

                                t.appendText("\ntarget set");
                                q.Orphanize();

                                var r = new NetStream(c, q.text);

                                r.netStatus +=
                                    r_status =>
                                    {

                                        t.appendText("\nr.netStatus: " + get_Code(r_status));
                                    };

                                r.client = new DynamicDelegatesContainer
									{
										{"handler1", 
											(string x) =>
											{
												t.appendText("\nhandler1: " + x);
												t.setSelection( t.length, t.length);
											}
										}
									}.Subject;

                                r.play("stream1");
                            };
                        #endregion

                        // yay! we are online
                        var s = new NetStream(c, NetStream.DIRECT_CONNECTIONS);

                        s.client = new DynamicDelegatesContainer
						{
							{"onPeerConnect", 
								(NetStream x) =>
								{
									
									t.appendText("\nonPeerConnect: " + x.farID);
									t.setSelection( t.length, t.length);

									q.Orphanize();

									return true;
								}
							}
						}.Subject;

                        s.netStatus +=
                            s_status =>
                            {

                                t.appendText("\ns.netStatus: " + get_Code(s_status));
                            };









                        s.publish("stream1");

                        #region broadcast the data
                        var counter = 0;

                        5000.AtInterval(
                            delegate
                            {
                                counter++;

                                s.send("handler1", "counter = " + counter);
                            }
                        );
                        #endregion

                    }
                };




            // "Developer Key" means any license key, activation code, or similar 
            // installation, access or usage control codes, including serial numbers 
            // and electronic certificates digitally signed by Adobe, designed to 
            // uniquely identify your Developer Program and link it to you 
            // the Developer.

            // Attention: You cannot use this key in your applications.
            //c.connect("rtmfp://stratus.adobe.com/3f37a156abb67621000856d1-08d2970f1b43/");
            c.connect("rtmfp://stratus.adobe.com/3f37a156abb67621000856d1-08d2970f1b43");

            // X:\jsc.svn\examples\actionscript\MultitouchExample\MultitouchFingerTools.FlashLAN\ApplicationCanvas.Session.cs
        }
        public MySprite1()
        {
            var nc = new NetConnection();
            nc.asyncError +=
                e =>
                {
                    RaiseMessage("nc.asyncError: " + e.errorID);
                };

            nc.ioError +=
               e =>
               {
                   RaiseMessage("nc.ioError: " + e.errorID);
               };

            nc.securityError +=
           e =>
           {
               RaiseMessage("nc.securityError: " + e.errorID);
           };

            nc.netStatus +=
                e =>
                {
                    RaiseMessage("nc.netStatus: " + e.info.code);


                    if (e.info.code == "NetGroup.Connect.Success")
                    {
                        connected = true;
                        RaiseMessage("connected");
                        return;
                    }

                    if (e.info.code == "NetConnection.Connect.Success")
                    {
                        // http://forums.adobe.com/message/2774620
                        // Click on the 'Administration' tab and Enable UPnP if it is disabled.

                        // http://book.zi5.me/books/read/2473/295
                        // this does not simply work anymore???

                        var groupspec = new GroupSpecifier("myGroup/groupOne");
                        //groupspec.multicastEnabled = true;
                        groupspec.addIPMulticastAddress("239.254.254.1:30000");
                        groupspec.ipMulticastMemberUpdatesEnabled = true;
                        groupspec.postingEnabled = true;
                        //groupspec.serverChannelEnabled = true;


                        //groupspec.addIPMulticastAddress("225.225.0.1:30303");

                        var group = new NetGroup(nc, groupspec.groupspecWithAuthorizations());
                        //var group = new NetGroup(nc, groupspec.groupspecWithoutAuthorizations());


                        group.deactivate +=
                            ee =>
                            {
                                RaiseMessage("group.deactivate");
                            };

                        Action<string> PostMessage =
                            message =>
                            {
                                if (connected)
                                {

                                    RaiseMessage("write: " + message);

                                    group.post(message);
                                    group.sendToAllNeighbors(message);

                                }
                                else
                                {
                                    RaiseMessage("skip: " + message);
                                }
                            };

                        AtPostMessage += PostMessage;

                        group.netStatus +=
                            g =>
                            {
                                RaiseMessage("group.netStatus: " + g.info.code);

                                if (g.info.code == "NetGroup.Posting.Notify")
                                {
                                    // Type Coercion failed: cannot convert Object@60b6cb9 to LANMulticast_Components_MySprite1__f__AnonymousType0_1_33554444.

                                    var k = (string)g.info.message;

                                    RaiseMessage("read: " + k);
                                }
                            };


                        return;
                    }
                };

            // http://stackoverflow.com/questions/5332762/rtmfp-and-firewalls-routers
            nc.connect("rtmfp:");

        }