예제 #1
0
 public void CreateUdpTest()
 {
     using (var options = NWProtocolOptions.CreateUdp()) {
         // we cannot test much more :(
         Assert.AreNotEqual(IntPtr.Zero, options.Handle);
     }
 }
        public void SetIPLocalAddressPreference()
        {
            TestRuntime.AssertXcodeVersion(11, 0);

            foreach (var ipOption in new [] { NWIPLocalAddressPreference.Default, NWIPLocalAddressPreference.Stable, NWIPLocalAddressPreference.Temporary })
            {
#if NET
                using (var options = new NWProtocolTlsOptions())
#else
                using (var options = NWProtocolOptions.CreateTls())
#endif
                    Assert.DoesNotThrow(() => options.IPLocalAddressPreference = ipOption, "Tls");
#if NET
                using (var options = new NWProtocolTcpOptions())
#else
                using (var options = NWProtocolOptions.CreateTcp())
#endif
                    Assert.DoesNotThrow(() => options.IPLocalAddressPreference = ipOption, "Tcp");
#if NET
                using (var options = new NWProtocolUdpOptions())
#else
                using (var options = NWProtocolOptions.CreateUdp())
#endif
                    Assert.DoesNotThrow(() => options.IPLocalAddressPreference = ipOption, "Udp");
            }
        }
예제 #3
0
    static NWConnection CreateOutboundConnection(string name, string port)
    {
        NWEndpoint endpoint;

        if (bonjour)
        {
            endpoint = NWEndpoint.CreateBonjourService(name, GetServiceType(), "local");
        }
        else
        {
            endpoint = NWEndpoint.Create(name, port);
        }

        Action <NWProtocolOptions> configureTls = SetupTls();
        NWParameters parameters;

        if (useUdp)
        {
            if (useTls)
            {
                parameters = NWParameters.CreateSecureUdp(configureTls: configureTls, configureUdp: null);
            }
            else
            {
                parameters = NWParameters.CreateUdp(configureUdp: null);
            }
        }
        else
        {
            if (useTls)
            {
                parameters = NWParameters.CreateSecureTcp(configureTls: configureTls, configureTcp: null);
            }
            else
            {
                parameters = NWParameters.CreateTcp(configureTcp: null);
            }
        }

        using (NWProtocolStack protocolStack = parameters.ProtocolStack){
            if (ipv4 || ipv6)
            {
                NWProtocolOptions ipOptions = protocolStack.InternetProtocol;
                ipOptions.IPSetVersion(ipv4 ? NWIPVersion.Version4 : NWIPVersion.Version6);
            }
        }

        if (localAddr != null || localPort != null)
        {
            using (NWEndpoint localEndpoint = NWEndpoint.Create(localAddr != null ? localAddr : "::", port == null ? "0" : port))
                parameters.LocalEndpoint = localEndpoint;
        }

        var connection = new NWConnection(endpoint, parameters);

        endpoint.Dispose();
        parameters.Dispose();
        return(connection);
    }
예제 #4
0
 public void CreateTlsTest()
 {
     using (var options = NWProtocolOptions.CreateTls()) {
         var sec = options.TlsProtocolOptions;
         // we cannot test much more :(
         Assert.AreNotEqual(IntPtr.Zero, options.Handle);
     }
 }
예제 #5
0
 public void SetUp()
 {
     using (var tcpOptions = NWProtocolOptions.CreateTcp())
         using (var tlsOptions = NWProtocolOptions.CreateTls())
             using (var parameters = NWParameters.CreateTcp()) {
                 parameters.ProtocolStack.PrependApplicationProtocol(tlsOptions);
                 parameters.ProtocolStack.PrependApplicationProtocol(tcpOptions);
                 parameters.IncludePeerToPeer = true;
                 listener = NWListener.Create("1234", parameters);
             }
 }
        public void CreateUdpTest()
        {
#if NET
            using (var options = new NWProtocolUdpOptions()) {
#else
            using (var options = NWProtocolOptions.CreateUdp()) {
#endif
                // we cannot test much more :(
                Assert.AreNotEqual(IntPtr.Zero, options.Handle);
            }
        }
        public void CreateTlsTest()
        {
#if NET
            using (var options = new NWProtocolTlsOptions()) {
                var sec = options.ProtocolOptions;
#else
            using (var options = NWProtocolOptions.CreateTls()) {
                var sec = options.TlsProtocolOptions;
#endif
                // we cannot test much more :(
                Assert.AreNotEqual(IntPtr.Zero, options.Handle);
            }
        }
 public void NewTlsOptions()
 {
     TestRuntime.AssertXcodeVersion(11, 0);
     using (var npo = NWProtocolOptions.CreateTls()) {
         var options = npo.TlsProtocolOptions;
         options.SetTlsMaxVersion(TlsProtocolVersion.Tls12);
         options.SetTlsMinVersion(TlsProtocolVersion.Tls10);
         options.AddTlsCipherSuite(TlsCipherSuite.Aes128GcmSha256);
         options.AddTlsCipherSuiteGroup(TlsCipherSuiteGroup.Legacy);
         using (var dd = DispatchData.FromByteBuffer(new byte [1])) {
             options.SetTlsPreSharedKeyIdentityHint(dd);
         }
     }
 }
        public void Equals()
        {
            TestRuntime.AssertXcodeVersion(11, 0);
            using (var npo = NWProtocolOptions.CreateTls()) {
                var options = npo.TlsProtocolOptions;

                Assert.True(SecProtocolOptions.Equals(null, null), "1");
                Assert.True(SecProtocolOptions.Equals(options, options), "2");
                Assert.False(SecProtocolOptions.Equals(null, options), "3");
                Assert.False(SecProtocolOptions.Equals(options, null), "4");

                Assert.True(options.Equals(options), "5");
                Assert.False(options.Equals(null), "6");
            }
        }
예제 #10
0
 public void TransportProtocolPropertyTest()
 {
     using (var options = stack.TransportProtocol)
     {
         Assert.IsNotNull(options, "Transport protocol should not be null.");
     }
     using (var options = NWProtocolOptions.CreateUdp())
     {
         stack.TransportProtocol = options;
         using (var copyOptions = stack.TransportProtocol)
         {
             copyOptions.IPSetUseMinimumMtu(true);                      // should not crash
         }
     }
 }
예제 #11
0
 // handler to iterate over the app protocols
 public void InterateProtocolsHandler(NWProtocolOptions o)
 {
     options.Add(o);
 }
예제 #12
0
        public void TestStateChangesHandler()
        {
            // In the test we are doing the following:
            //
            // 1. Start a browser. At this point, we have no listeners (unless someone is exposing it in the lab)
            // and therefore the browser cannot find any services/listeners.
            // 2. Start a listener that is using the same type/domain pair that the browser expects.
            // 3. Browser picks up the new listener, and sends an event (service found).
            // 4. Listener stops, and the service disappears.
            // 5. The browser is not yet canceled, so it picks up that the service/listener is not longer then and returns it.
            //
            // The test will block until the different events are set by the callbacks that are executed in a diff thread.

            bool      firstRun      = true;
            bool      eventsDone    = false;
            bool      listeningDone = false;
            Exception ex            = null;
            var       changesEvent  = new AutoResetEvent(false);
            var       browserReady  = new AutoResetEvent(false);
            var       finalEvent    = new AutoResetEvent(false);

            TestRuntime.RunAsync(DateTime.Now.AddSeconds(30), async() => {
                // start the browser, before the listener
                browser.SetStateChangesHandler((st, er) => {
                    Assert.IsNotNull(st, "State");
                    Assert.IsNull(er, "Error");
                    if (st == NWBrowserState.Ready)
                    {
                        browserReady.Set();
                    }
                });
                browser.SetChangesHandler((oldResult, newResult) => {
                    // first time, listener appears, so we do not have an old result, second time
                    // listener goes, so we do not have a new result
                    try {
                        if (firstRun)
                        {
                            Assert.IsNull(oldResult, "oldResult first run.");
                            Assert.IsNotNull(newResult, "newResult first run");
                            firstRun = false;
                        }
                        else
                        {
                            Assert.IsNotNull(oldResult, "oldResult first run.");
                            Assert.IsNull(newResult, "newResult first run");
                        }
                    } catch (Exception e) {
                        ex = e;
                    } finally {
                        changesEvent.Set();
                        eventsDone = true;
                    }
                });
                browser.Start();
                browserReady.WaitOne(30000);
                using (var advertiser = NWAdvertiseDescriptor.CreateBonjourService("MonoTouchFixtures.Network", type))
                    using (var tcpOptions = NWProtocolOptions.CreateTcp())
                        using (var tlsOptions = NWProtocolOptions.CreateTls())
                            using (var paramenters = NWParameters.CreateTcp()) {
                                paramenters.ProtocolStack.PrependApplicationProtocol(tlsOptions);
                                paramenters.ProtocolStack.PrependApplicationProtocol(tcpOptions);
                                paramenters.IncludePeerToPeer = true;
                                using (var listener = NWListener.Create("1234", paramenters)) {
                                    listener.SetQueue(DispatchQueue.CurrentQueue);
                                    listener.SetAdvertiseDescriptor(advertiser);
                                    // we need the connection handler, else we will get an exception
                                    listener.SetNewConnectionHandler((c) => { });
                                    listener.SetStateChangedHandler((s, e) => {
                                        if (e != null)
                                        {
                                            Console.WriteLine($"Got error {e.ErrorCode} {e.ErrorDomain} '{e.CFError.FailureReason}' {e.ToString ()}");
                                        }
                                    });
                                    listener.Start();
                                    changesEvent.WaitOne(30000);
                                    listener.Cancel();
                                    listeningDone = true;
                                    finalEvent.Set();
                                }
                            }
            }, () => eventsDone);

            finalEvent.WaitOne(30000);
            Assert.IsTrue(eventsDone);
            Assert.IsTrue(listeningDone);
            Assert.IsNull(ex, "Exception");
            browser.Cancel();
        }
예제 #13
0
        protected INativeObject GetINativeInstance(Type t)
        {
            var ctor = t.GetConstructor(Type.EmptyTypes);

            if ((ctor != null) && !ctor.IsAbstract)
            {
                return(ctor.Invoke(null) as INativeObject);
            }

            if (!NativeObjectInterfaceType.IsAssignableFrom(t))
            {
                throw new ArgumentException("t");
            }
            switch (t.Name)
            {
            case "CFAllocator":
                return(CFAllocator.SystemDefault);

            case "CFBundle":
                var bundles = CFBundle.GetAll();
                if (bundles.Length > 0)
                {
                    return(bundles [0]);
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Could not create the new instance for type {0}.", t.Name));
                }

            case "CFNotificationCenter":
                return(CFNotificationCenter.Darwin);

            case "CFReadStream":
            case "CFStream":
                CFReadStream  readStream;
                CFWriteStream writeStream;
                CFStream.CreatePairWithSocketToHost("www.google.com", 80, out readStream, out writeStream);
                return(readStream);

            case "CFWriteStream":
                CFStream.CreatePairWithSocketToHost("www.google.com", 80, out readStream, out writeStream);
                return(writeStream);

            case "CFUrl":
                return(CFUrl.FromFile("/etc"));

            case "CFPropertyList":
                return(CFPropertyList.FromData(NSData.FromString("<string>data</string>")).PropertyList);

            case "DispatchData":
                return(DispatchData.FromByteBuffer(new byte [] { 1, 2, 3, 4 }));

            case "AudioFile":
                var path = Path.GetFullPath("1.caf");
                var af   = AudioFile.Open(CFUrl.FromFile(path), AudioFilePermission.Read, AudioFileType.CAF);
                return(af);

            case "CFHTTPMessage":
                return(CFHTTPMessage.CreateEmpty(false));

            case "CFMutableString":
                return(new CFMutableString("xamarin"));

            case "CGBitmapContext":
                byte[] data = new byte [400];
                using (CGColorSpace space = CGColorSpace.CreateDeviceRGB()) {
                    return(new CGBitmapContext(data, 10, 10, 8, 40, space, CGBitmapFlags.PremultipliedLast));
                }

            case "CGContextPDF":
                var filename = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments) + "/t.pdf";
                using (var url = new NSUrl(filename))
                    return(new CGContextPDF(url));

            case "CGColorConversionInfo":
                var cci = new GColorConversionInfoTriple()
                {
                    Space     = CGColorSpace.CreateGenericRgb(),
                    Intent    = CGColorRenderingIntent.Default,
                    Transform = CGColorConversionInfoTransformType.ApplySpace
                };
                return(new CGColorConversionInfo((NSDictionary)null, cci, cci, cci));

            case "CGDataConsumer":
                using (NSMutableData destData = new NSMutableData()) {
                    return(new CGDataConsumer(destData));
                }

            case "CGDataProvider":
                filename = "xamarin1.png";
                return(new CGDataProvider(filename));

            case "CGFont":
                return(CGFont.CreateWithFontName("Courier New"));

            case "CGPattern":
                return(new CGPattern(
                           new RectangleF(0, 0, 16, 16),
                           CGAffineTransform.MakeIdentity(),
                           16, 16,
                           CGPatternTiling.NoDistortion,
                           true,
                           (cgc) => {}));

            case "CMBufferQueue":
                return(CMBufferQueue.CreateUnsorted(2));

            case "CTFont":
                CTFontDescriptorAttributes fda = new CTFontDescriptorAttributes()
                {
                    FamilyName = "Courier",
                    StyleName  = "Bold",
                    Size       = 16.0f
                };
                using (var fd = new CTFontDescriptor(fda))
                    return(new CTFont(fd, 10));

            case "CTFontCollection":
                return(new CTFontCollection(new CTFontCollectionOptions()));

            case "CTFontDescriptor":
                fda = new CTFontDescriptorAttributes();
                return(new CTFontDescriptor(fda));

            case "CTTextTab":
                return(new CTTextTab(CTTextAlignment.Left, 2));

            case "CTTypesetter":
                return(new CTTypesetter(new NSAttributedString("Hello, world",
                                                               new CTStringAttributes()
                {
                    ForegroundColorFromContext = true,
                    Font = new CTFont("ArialMT", 24)
                })));

            case "CTFrame":
                var framesetter = new CTFramesetter(new NSAttributedString("Hello, world",
                                                                           new CTStringAttributes()
                {
                    ForegroundColorFromContext = true,
                    Font = new CTFont("ArialMT", 24)
                }));
                var bPath = UIBezierPath.FromRect(new RectangleF(0, 0, 3, 3));
                return(framesetter.GetFrame(new NSRange(0, 0), bPath.CGPath, null));

            case "CTFramesetter":
                return(new CTFramesetter(new NSAttributedString("Hello, world",
                                                                new CTStringAttributes()
                {
                    ForegroundColorFromContext = true,
                    Font = new CTFont("ArialMT", 24)
                })));

            case "CTGlyphInfo":
                return(new CTGlyphInfo("Zapfino", new CTFont("ArialMT", 24), "Foo"));

            case "CTLine":
                return(new CTLine(new NSAttributedString("Hello, world",
                                                         new CTStringAttributes()
                {
                    ForegroundColorFromContext = true,
                    Font = new CTFont("ArialMT", 24)
                })));

            case "CGImageDestination":
                var storage = new NSMutableData();
                return(CGImageDestination.Create(new CGDataConsumer(storage), "public.png", 1));

            case "CGImageMetadataTag":
                using (NSString name = new NSString("tagName"))
                    using (var value = new NSString("value"))
                        return(new CGImageMetadataTag(CGImageMetadataTagNamespaces.Exif, CGImageMetadataTagPrefixes.Exif, name, CGImageMetadataType.Default, value));

            case "CGImageSource":
                filename = "xamarin1.png";
                return(CGImageSource.FromUrl(NSUrl.FromFilename(filename)));

            case "SecPolicy":
                return(SecPolicy.CreateSslPolicy(false, null));

            case "SecIdentity":
                using (var options = NSDictionary.FromObjectAndKey(new NSString("farscape"), SecImportExport.Passphrase)) {
                    NSDictionary[] array;
                    var            result = SecImportExport.ImportPkcs12(farscape_pfx, options, out array);
                    if (result != SecStatusCode.Success)
                    {
                        throw new InvalidOperationException(string.Format("Could not create the new instance for type {0} due to {1}.", t.Name, result));
                    }
                    return(new SecIdentity(array [0].LowlevelObjectForKey(SecImportExport.Identity.Handle)));
                }

            case "SecTrust":
                X509Certificate x = new X509Certificate(mail_google_com);
                using (var policy = SecPolicy.CreateSslPolicy(true, "mail.google.com"))
                    return(new SecTrust(x, policy));

            case "SslContext":
                return(new SslContext(SslProtocolSide.Client, SslConnectionType.Stream));

            case "UIFontFeature":
                return(new UIFontFeature(CTFontFeatureNumberSpacing.Selector.ProportionalNumbers));

            case "NetworkReachability":
                return(new NetworkReachability(IPAddress.Loopback, null));

            case "VTCompressionSession":
            case "VTSession":
                return(VTCompressionSession.Create(1024, 768, CMVideoCodecType.H264, (sourceFrame, status, flags, buffer) => { }, null, (CVPixelBufferAttributes)null));

            case "VTFrameSilo":
                return(VTFrameSilo.Create());

            case "VTMultiPassStorage":
                return(VTMultiPassStorage.Create());

            case "CFString":
                return(new CFString("test"));

            case "DispatchBlock":
                return(new DispatchBlock(() => { }));

            case "DispatchQueue":
                return(new DispatchQueue("com.example.subsystem.taskXYZ"));

            case "DispatchGroup":
                return(DispatchGroup.Create());

            case "CGColorSpace":
                return(CGColorSpace.CreateDeviceCmyk());

            case "CGGradient":
                CGColor[] cArray = { UIColor.Black.CGColor, UIColor.Clear.CGColor, UIColor.Blue.CGColor };
                return(new CGGradient(null, cArray));

            case "CGImage":
                filename = "xamarin1.png";
                using (var dp = new CGDataProvider(filename))
                    return(CGImage.FromPNG(dp, null, false, CGColorRenderingIntent.Default));

            case "CGColor":
                return(UIColor.Black.CGColor);

            case "CMClock":
                CMClockError ce;
                CMClock      clock = CMClock.CreateAudioClock(out ce);
                if (ce == CMClockError.None)
                {
                    return(clock);
                }
                throw new InvalidOperationException(string.Format("Could not create the new instance for type {0}.", t.Name));

            case "CMTimebase":
                clock = CMClock.CreateAudioClock(out ce);
                if (ce == CMClockError.None)
                {
                    return(new CMTimebase(clock));
                }
                throw new InvalidOperationException(string.Format("Could not create the new instance for type {0}.", t.Name));

            case "CVPixelBufferPool":
                return(new CVPixelBufferPool(
                           new CVPixelBufferPoolSettings(),
                           new CVPixelBufferAttributes(CVPixelFormatType.CV24RGB, 100, 50)
                           ));

            case "NWAdvertiseDescriptor":
                return(NWAdvertiseDescriptor.CreateBonjourService("sampleName" + DateTime.Now, "_nfs._tcp"));

            case "NWConnection": {
                var endpoint   = NWEndpoint.Create("www.microsoft.com", "https");
                var parameters = NWParameters.CreateTcp(configureTcp: null);
                return(new NWConnection(endpoint, parameters));
            }

            case "NWContentContext":
                return(new NWContentContext("contentContext" + DateTime.Now));

            case "NWEndpoint":
                return(NWEndpoint.Create("www.microsoft.com", "https"));

            case "NWListener":
                return(NWListener.Create(NWParameters.CreateTcp(configureTcp: null)));

            case "NWParameters":
                return(NWParameters.CreateTcp(configureTcp: null));

            case "NWProtocolDefinition":
                // Makes a new instance every time
                return(NWProtocolDefinition.TcpDefinition);

            case "NWProtocolOptions":
                return(NWProtocolOptions.CreateTcp());

            case "SecCertificate":
                using (var cdata = NSData.FromArray(mail_google_com))
                    return(new SecCertificate(cdata));

            case "SecCertificate2":
                using (var cdata = NSData.FromArray(mail_google_com))
                    return(new SecCertificate2(new SecCertificate(cdata)));

            case "SecTrust2":
                X509Certificate x2 = new X509Certificate(mail_google_com);
                using (var policy = SecPolicy.CreateSslPolicy(true, "mail.google.com"))
                    return(new SecTrust2(new SecTrust(x2, policy)));

            case "SecIdentity2":
                using (var options = NSDictionary.FromObjectAndKey(new NSString("farscape"), SecImportExport.Passphrase)) {
                    NSDictionary[] array;
                    var            result = SecImportExport.ImportPkcs12(farscape_pfx, options, out array);
                    if (result != SecStatusCode.Success)
                    {
                        throw new InvalidOperationException(string.Format("Could not create the new instance for type {0} due to {1}.", t.Name, result));
                    }
                    return(new SecIdentity2(new SecIdentity(array [0].LowlevelObjectForKey(SecImportExport.Identity.Handle))));
                }

            case "SecKey":
                SecKey private_key;
                SecKey public_key;
                using (var record = new SecRecord(SecKind.Key)) {
                    record.KeyType       = SecKeyType.RSA;
                    record.KeySizeInBits = 512;                     // it's not a performance test :)
                    SecKey.GenerateKeyPair(record.ToDictionary(), out public_key, out private_key);
                    return(private_key);
                }

            case "SecAccessControl":
                return(new SecAccessControl(SecAccessible.WhenPasscodeSetThisDeviceOnly));

            default:
                throw new InvalidOperationException(string.Format("Could not create the new instance for type {0}.", t.Name));
            }
        }
예제 #14
0
    static NWListener CreateAndStartListener(string host, string port)
    {
        Action <NWProtocolOptions> configureTls = SetupTls();
        NWParameters parameters;

        // Create the parameters, either TLS or no TLS, and with UDP or no UDP
        if (useUdp)
        {
            if (useTls)
            {
                parameters = NWParameters.CreateSecureUdp(configureTls: configureTls, configureUdp: null);
            }
            else
            {
                parameters = NWParameters.CreateUdp(configureUdp: null);
            }
        }
        else
        {
            if (useTls)
            {
                parameters = NWParameters.CreateSecureTcp(configureTls: configureTls, configureTcp: null);
            }
            else
            {
                parameters = NWParameters.CreateTcp(configureTcp: null);
            }
        }

        // If specified, set the IP version
        using (NWProtocolStack protocolStack = parameters.ProtocolStack){
            if (ipv4 || ipv6)
            {
                NWProtocolOptions ipOptions = protocolStack.InternetProtocol;
                ipOptions.IPSetVersion(ipv4 ? NWIPVersion.Version4 : NWIPVersion.Version6);
            }
        }

        // Bind to local address and port
        string address = bonjour ? null : host;

        if (address != null || port != null)
        {
            NWEndpoint localEndpoint = NWEndpoint.Create(address != null ? address : "::", port != null ? port : "0");
            Console.WriteLine("Getting {0} and {1}", address != null ? address : "::", port != null ? port : "0");
            parameters.LocalEndpoint = localEndpoint;
            Console.WriteLine("With port: " + localEndpoint.Port);
        }

        var listener = NWListener.Create(parameters);

        if (bonjour && host != null)
        {
            listener.SetAdvertiseDescriptor(NWAdvertiseDescriptor.CreateBonjourService(host, GetServiceType(), "local"));
            listener.SetAdvertisedEndpointChangedHandler((NWEndpoint advertisedEndpoint, bool added) => {
                if (verbose)
                {
                    var astr = added ? "added" : "removed";
                    warn($"Listener {astr} on {advertisedEndpoint.BonjourServiceName} on ({advertisedEndpoint.BonjourServiceName}.{GetServiceType()}.local");
                }
            });
        }

        listener.SetQueue(DispatchQueue.MainQueue);
        listener.SetStateChangedHandler((listenerState, error) => {
            var errno = (SslStatus)(error == null ? 0 : error.ErrorCode);
            switch (listenerState)
            {
            case NWListenerState.Waiting:
                if (verbose)
                {
                    warn($"Listener on port {listener.Port} udp={useUdp} waiting");
                }
                break;

            case NWListenerState.Failed:
                warn($"Listener on port {listener.Port} udp={useUdp} failed");
                break;

            case NWListenerState.Ready:
                if (verbose)
                {
                    warn($"Listener on port {listener.Port} udp={useUdp} ready");
                }
                break;

            case NWListenerState.Cancelled:
                listener = null;
                break;
            }
        });

        listener.SetNewConnectionHandler((connection) => {
            if (inboundConnection != null)
            {
                // We only support one connection at a time, so if we already
                // have one, reject the incoming connection.
                connection.Cancel();
            }
            else
            {
                if (verbose)
                {
                    warn($"New Connection on {connection.Handle} with {connection.Endpoint}");
                }
                // Accept the incoming connection and start sending  and receiving on it
                inboundConnection = connection;
                StartConnection(inboundConnection);
                StartSendReceiveLoop(inboundConnection);
            }
        });
        listener.Start();

        return(listener);
    }