public virtual async void connect(string address, SessionRequestListener networkListener, IDictionary <string, string> extraHeaders, string cookies, Proxy proxy, long timeout) { Uri uri = LsUtils.uri(address); string host = uri.Host; int port = LsUtils.port(uri); bool secure = LsUtils.isSSL(uri); try { string host4Netty = System.Net.Dns.GetHostAddresses(host)[0].ToString(); NettyFullAddress remoteAddress = new NettyFullAddress(secure, host4Netty, port, host, proxy); ExtendedNettyFullAddress extendedRemoteAddress = new ExtendedNettyFullAddress(remoteAddress, extraHeaders, cookies); WebSocketChannelPool wsPool = (WebSocketChannelPool)wsPoolManager.get(extendedRemoteAddress); IChannel ch = await wsPool.AcquireNewOr(timeout); if (ch != null) { if (ch.Active) { this.channel = new MyChannel(ch, wsPool, networkListener); WebSocketChannelHandler chHandler = new WebSocketChannelHandler(networkListener, channel); PipelineUtils.populateWSPipeline(ch, chHandler); networkListener.onOpen(); } else { log.Error("WebSocket handshake error, "); networkListener.onBroken(); } } else { log.Error("WebSocket handshake error, channel unexpectedly null"); networkListener.onBroken(); } } catch (Exception e) { log.Error("WebSocket handshake error: " + e.Message); networkListener.onBroken(); } }
/// <summary> /// Upgrade the channel to WebSocket. /// </summary> private void upgrade(ExtendedNettyFullAddress address) { /* * ========================================= Note ================================================= * Operations on the channel must happen in the thread associated with the channel. * Otherwise subtle bugs can appear. * For example the method WebSocketClientHandshaker.finishHandshake can return before * the method WebSocketClientHandshaker.handshake returns leaving the channel pipeline in a mess. * ================================================================================================ */ chnl.EventLoop.Execute(() => { /* * If the eventLoop is overloaded, when this task is executed the channel can be broken * (for example because the server has closed it). * So the first thing to do is to check if the channel is healthy. */ if (chnl.Active) { /* set cookies and extra headers */ string cookies = address.Cookies; IDictionary <string, string> extraHeaders = address.ExtraHeaders; DefaultHttpHeaders customHeaders = new DefaultHttpHeaders(); if (extraHeaders != null) { foreach (KeyValuePair <string, string> entry in extraHeaders) { customHeaders.Add(new AsciiString(entry.Key), entry.Value); } } if (!string.ReferenceEquals(cookies, null) && cookies.Length > 0) { customHeaders.Set(HttpHeaderNames.Cookie, cookies); } /* build url */ NettyFullAddress remoteAddress = address.Address; string scheme = remoteAddress.Secure ? "wss" : "ws"; string host = remoteAddress.Host; string url; int port = remoteAddress.Port; if (host.Equals("::1")) { url = scheme + "://localhost:" + port + "/lightstreamer"; } else { url = scheme + "://" + host + ":" + port + "/lightstreamer"; } Uri uri = LsUtils.uri(url); string subprotocol = Constants.TLCP_VERSION + ".lightstreamer.com"; /* build pipeline */ WebSocketHandshakeHandler wsHandshakeHandler = new WebSocketHandshakeHandler(uri, subprotocol, customHeaders, this); PipelineUtils.populateWSPipelineForHandshake(chnl, wsHandshakeHandler); /* WS handshake */ futureTask = wsHandshakeHandler.handshake(chnl); } else { futureTask = Task.Factory.StartNew(() => Thread.Sleep(2)); } }); return; }