public GamePlayer(ServerHost context, Socket socket, int bufferSize) { this.mContext = context; this.Socket = socket; mBufferSize = bufferSize; mMaxBufferSize = bufferSize * 2; mLocalBuffer = new byte[mMaxBufferSize]; //<! For now, allow max buffer storage be 2x size of max buffer ConnectResponse msg = new ConnectResponse{ success = true }; DispatchMessage(msg); // Temporary JoinGameSession(); }
protected virtual void Client_FailedToConnectToServer(ConnectResponse response) { UnityMainThreadDispatcher.Instance().Enqueue(() => { SetLeftScreenViewController(null, ViewController.AnimationType.None); }); }
private void OnConnect(ConnectResponse connectResponse) { }
/// ----------------------------------------------------------------------------- /// <summary> /// Test du protocole /// </summary> /// <typeparam name="TP">Le type de protocole</typeparam> /// <typeparam name="TC">Le type de canal</typeparam> /// <param name="port">le port de base</param> /// ----------------------------------------------------------------------------- private void TestProtocol <TP, TC>(int port) where TP : GenericProtocol where TC : IChannel { BdtServer server; BdtClient client; EchoServer echo; GatewayServer gw; Initialize <TP>(port, out server, out client, out echo, out gw); foreach (IChannel channel in ChannelServices.RegisteredChannels) { Assert.IsInstanceOfType(channel, typeof(TC)); Assert.IsTrue(channel.ChannelName == client.ClientConfig.ServiceName || channel.ChannelName == client.ClientConfig.ServiceName + ".Client"); } ConnectResponse conr = client.Tunnel.Connect(new ConnectRequest(client.Sid, "localhost", port + GatewayOffset)); Assert.IsTrue(conr.Connected); Assert.IsTrue(conr.Success); int totalread = 0; for (int datalength = 0; datalength < 4096; datalength = (datalength == 0) ? 1 : datalength * 2) { var buffer = new byte[datalength]; var outbuffer = new byte[datalength]; var readcount = 0; var rnd = new Random(); rnd.NextBytes(buffer); var wrir = client.Tunnel.Write(new WriteRequest(client.Sid, conr.Cid, buffer)); Assert.IsTrue(wrir.Connected); Assert.IsTrue(wrir.Success); while (readcount < datalength) { var rear = client.Tunnel.Read(new ConnectionContextRequest(client.Sid, conr.Cid)); Assert.IsTrue(rear.Connected); Assert.IsTrue(rear.Success); if (!rear.DataAvailable) { continue; } Array.Copy(rear.Data, 0, outbuffer, readcount, rear.Data.Length); readcount += rear.Data.Length; } Assert.AreEqual(datalength, readcount); for (var i = 0; i < datalength; i++) { Assert.AreEqual(buffer[i], outbuffer[i], "Offset " + i); } totalread += readcount; } // Test Monitor method var monr = client.Tunnel.Monitor(new SessionContextRequest(client.Sid)); Assert.IsTrue(monr.Success); Assert.AreEqual(1, monr.Sessions.Length); Assert.IsTrue(monr.Sessions[0].Admin); Assert.AreEqual(client.Sid.ToString("x"), monr.Sessions[0].Sid); Assert.AreEqual(2, monr.Sessions[0].Connections.Length); var connections = (from c in monr.Sessions[0].Connections orderby c.Port select c).ToArray(); var hostname = Dns.GetHostEntry(connections[0].Address).HostName; Assert.AreEqual(hostname, connections[0].Host); Assert.AreEqual("127.0.0.1", connections[0].Address); Assert.AreEqual(port + EchoOffset, connections[0].Port); Assert.AreEqual(totalread, connections[0].ReadCount); Assert.AreEqual(totalread, connections[0].WriteCount); Assert.AreEqual(hostname, connections[1].Host); Assert.AreEqual("127.0.0.1", connections[1].Address); Assert.AreEqual(port + GatewayOffset, connections[1].Port); Assert.AreEqual(totalread, connections[1].ReadCount); Assert.AreEqual(totalread, connections[1].WriteCount); Assert.AreEqual(conr.Cid.ToString("x"), connections[1].Cid); // Test Disconnect method var disr = client.Tunnel.Disconnect(new ConnectionContextRequest(client.Sid, conr.Cid)); Assert.IsFalse(disr.Connected); Assert.IsTrue(disr.Success); TestKill(client, port); TestBadValues(client, port); Finalize(ref server, ref client, ref echo, ref gw); }
public ConnectResponse Connect() { ConnectResponse connectResponse = new ConnectResponse(); try { Connect(out connectResponse.ErrorInfo); if (base.IsConnected) { if (isRs485) { RS485Item[] rS485Items = RS485Items; foreach (RS485Item rS485Item in rS485Items) { MsgRfidStatusQuery msgRfidStatusQuery = new MsgRfidStatusQuery(); if (rS485Item.Send(msgRfidStatusQuery)) { rS485Item.UhfBand = msgRfidStatusQuery.ReceivedMessage.UhfBand; } Msg6CTagFieldConfig msg6CTagFieldConfig = new Msg6CTagFieldConfig(); if (rS485Item.Send(msg6CTagFieldConfig)) { rS485Item.isEnableAntenna = msg6CTagFieldConfig.ReceivedMessage.IsEnableAntenna; rS485Item.isEnableRSSI = msg6CTagFieldConfig.ReceivedMessage.IsEnableRSSI; } MsgReaderVersionQuery msgReaderVersionQuery = new MsgReaderVersionQuery(); if (rS485Item.Send(msgReaderVersionQuery)) { rS485Item.modelNumber = msgReaderVersionQuery.ReceivedMessage.ModelNumber; } } } else if (!(base.CommPort is UdpPort)) { MsgRfidStatusQuery msgRfidStatusQuery2 = new MsgRfidStatusQuery(); if (Send(msgRfidStatusQuery2)) { UhfBand = msgRfidStatusQuery2.ReceivedMessage.UhfBand; } Msg6CTagFieldConfig msg6CTagFieldConfig2 = new Msg6CTagFieldConfig(); if (Send(msg6CTagFieldConfig2)) { isEnableAntenna = msg6CTagFieldConfig2.ReceivedMessage.IsEnableAntenna; isEnableRSSI = msg6CTagFieldConfig2.ReceivedMessage.IsEnableRSSI; } MsgReaderVersionQuery msgReaderVersionQuery2 = new MsgReaderVersionQuery(); if (Send(msgReaderVersionQuery2)) { modelNumber = msgReaderVersionQuery2.ReceivedMessage.ModelNumber; } } } } catch (Exception ex) { connectResponse.ErrorInfo = new ErrInfo("FF01", ex.Message); Log.Error(ex.Message); } connectResponse.IsSucessed = base.IsConnected; return(connectResponse); }
private void ProcessFirstResponse(ConnectResponse response) { var isMasterResponse = response.IsMasterResult.Response; // first response has to match replica set name in settings (if any) var replicaSetName = isMasterResponse["setName"].AsString; if (_server.Settings.ReplicaSetName != null && replicaSetName != _server.Settings.ReplicaSetName) { var message = string.Format( "Server at address '{0}' is a member of replica set '{1}' and not '{2}'.", response.ServerInstance.Address, replicaSetName, _server.Settings.ReplicaSetName); throw new MongoConnectionException(message); } _server.ReplicaSetName = replicaSetName; // find all valid addresses var validAddresses = new HashSet<MongoServerAddress>(); if (isMasterResponse.Contains("hosts")) { foreach (string address in isMasterResponse["hosts"].AsBsonArray) { validAddresses.Add(MongoServerAddress.Parse(address)); } } if (isMasterResponse.Contains("passives")) { foreach (string address in isMasterResponse["passives"].AsBsonArray) { validAddresses.Add(MongoServerAddress.Parse(address)); } } if (isMasterResponse.Contains("arbiters")) { foreach (string address in isMasterResponse["arbiters"].AsBsonArray) { validAddresses.Add(MongoServerAddress.Parse(address)); } } // remove server instances created from the seed list that turn out to be invalid var invalidInstances = _server.Instances.Where(i => !validAddresses.Contains(i.Address)).ToArray(); // force evaluation foreach (var invalidInstance in invalidInstances) { _server.RemoveInstance(invalidInstance); } // add any server instances that were missing from the seed list foreach (var address in validAddresses) { if (!_server.Instances.Any(i => i.Address == address)) { var missingInstance = new MongoServerInstance(_server, address); _server.AddInstance(missingInstance); QueueConnect(missingInstance); } } }
// private methods // note: this method will run on a thread from the ThreadPool private void ConnectWorkItem(object argsObject) { var args = (ConnectArgs)argsObject; var serverInstance = args.ServerInstance; var response = new ConnectResponse { ServerInstance = serverInstance }; try { serverInstance.Connect(true); // slaveOk response.IsMasterResult = serverInstance.IsMasterResult; } catch (Exception ex) { response.Exception = ex; } args.ResponseQueue.Enqueue(response); }
private void ProcessResponse( ConnectResponse response ) { responses.Add(response); if (response.ServerInstance.ConnectException != null) { return; } try { if (!response.IsMasterResult.Response.Contains("setName")) { var message = string.Format("Server at address '{0}' does not have a replica set name.", response.ServerInstance.Address); throw new MongoConnectionException(message); } if (!response.IsMasterResult.Response.Contains("hosts")) { var message = string.Format("Server at address '{0}' does not have a hosts list.", response.ServerInstance.Address); throw new MongoConnectionException(message); } if (firstResponseHasBeenProcessed) { ProcessAdditionalResponse(response); } else { ProcessFirstResponse(response); firstResponseHasBeenProcessed = true; // remains false if ProcessFirstResponse throws an exception } } catch (Exception ex) { response.ServerInstance.ConnectException = ex; try { response.ServerInstance.Disconnect(); } catch { } // ignore exceptions } }
/// <summary> /// This is called when client is aware of proxy /// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy /// </summary> /// <param name="endPoint"></param> /// <param name="tcpClient"></param> /// <returns></returns> private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient) { var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); try { string connectHostname = null; ConnectRequest connectRequest = null; //Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request) if (await HttpHelper.IsConnectMethod(clientStream) == 1) { //read the first line HTTP command string httpCmd = await clientStreamReader.ReadLineAsync(); if (string.IsNullOrEmpty(httpCmd)) { return; } Request.ParseRequestLine(httpCmd, out string _, out string httpUrl, out var version); var httpRemoteUri = new Uri("http://" + httpUrl); connectHostname = httpRemoteUri.Host; //filter out excluded host names bool excluded = false; if (endPoint.BeforeTunnelConnect != null) { excluded = await endPoint.BeforeTunnelConnect(connectHostname); } connectRequest = new ConnectRequest { RequestUri = httpRemoteUri, OriginalUrl = httpUrl, HttpVersion = version, }; await HeaderParser.ReadHeaders(clientStreamReader, connectRequest.Headers); var connectArgs = new TunnelConnectSessionEventArgs(BufferSize, endPoint, connectRequest, ExceptionFunc); connectArgs.ProxyClient.TcpClient = tcpClient; connectArgs.ProxyClient.ClientStream = clientStream; await endPoint.InvokeTunnectConnectRequest(this, connectArgs, ExceptionFunc); if (await CheckAuthorization(clientStreamWriter, connectArgs) == false) { await endPoint.InvokeTunnectConnectResponse(this, connectArgs, ExceptionFunc); return; } //write back successfull CONNECT response var response = ConnectResponse.CreateSuccessfullConnectResponse(version); response.Headers.FixProxyHeaders(); connectArgs.WebSession.Response = response; await clientStreamWriter.WriteResponseAsync(response); var clientHelloInfo = await SslTools.PeekClientHello(clientStream); bool isClientHello = clientHelloInfo != null; if (isClientHello) { connectRequest.ClientHelloInfo = clientHelloInfo; } await endPoint.InvokeTunnectConnectResponse(this, connectArgs, ExceptionFunc, isClientHello); if (!excluded && isClientHello) { connectRequest.RequestUri = new Uri("https://" + httpUrl); SslStream sslStream = null; try { sslStream = new SslStream(clientStream); string certName = HttpHelper.GetWildCardDomainName(connectHostname); var certificate = endPoint.GenericCertificate ?? await CertificateManager.CreateCertificateAsync(certName); //Successfully managed to authenticate the client using the fake certificate await sslStream.AuthenticateAsServerAsync(certificate, false, SupportedSslProtocols, false); //HTTPS server created - we can now decrypt the client's traffic clientStream = new CustomBufferedStream(sslStream, BufferSize); clientStreamReader.Dispose(); clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); } catch { sslStream?.Dispose(); return; } if (await HttpHelper.IsConnectMethod(clientStream) == -1) { // It can be for example some Google (Cloude Messaging for Chrome) magic excluded = true; } } //Hostname is excluded or it is not an HTTPS connect if (excluded || !isClientHello) { //create new connection using (var connection = await GetServerConnection(connectArgs, true)) { if (isClientHello) { int available = clientStream.Available; if (available > 0) { //send the buffered data var data = BufferPool.GetBuffer(BufferSize); try { // clientStream.Available sbould be at most BufferSize because it is using the same buffer size await clientStream.ReadAsync(data, 0, available); await connection.StreamWriter.WriteAsync(data, 0, available, true); } finally { BufferPool.ReturnBuffer(data); } } var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream); ((ConnectResponse)connectArgs.WebSession.Response).ServerHelloInfo = serverHelloInfo; } await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, ExceptionFunc); } return; } } //Now create the request await HandleHttpSessionRequest(tcpClient, clientStream, clientStreamReader, clientStreamWriter, connectHostname, endPoint, connectRequest); } catch (ProxyHttpException e) { ExceptionFunc(e); } catch (IOException e) { ExceptionFunc(new Exception("Connection was aborted", e)); } catch (SocketException e) { ExceptionFunc(new Exception("Could not connect", e)); } catch (Exception e) { ExceptionFunc(new Exception("Error occured in whilst handling the client", e)); } finally { clientStreamReader.Dispose(); clientStream.Dispose(); } }
/// <summary> /// This is called when client is aware of proxy /// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy /// </summary> /// <param name="endPoint"></param> /// <param name="tcpClient"></param> /// <returns></returns> private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient) { bool disposed = false; var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); Uri httpRemoteUri; try { //read the first line HTTP command string httpCmd = await clientStreamReader.ReadLineAsync(); if (string.IsNullOrEmpty(httpCmd)) { return; } string httpMethod; string httpUrl; Version version; Request.ParseRequestLine(httpCmd, out httpMethod, out httpUrl, out version); httpRemoteUri = httpMethod == "CONNECT" ? new Uri("http://" + httpUrl) : new Uri(httpUrl); //filter out excluded host names bool excluded = false; if (endPoint.ExcludedHttpsHostNameRegex != null) { excluded = endPoint.ExcludedHttpsHostNameRegexList.Any(x => x.IsMatch(httpRemoteUri.Host)); } if (endPoint.IncludedHttpsHostNameRegex != null) { excluded = !endPoint.IncludedHttpsHostNameRegexList.Any(x => x.IsMatch(httpRemoteUri.Host)); } ConnectRequest connectRequest = null; //Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request) if (httpMethod == "CONNECT") { connectRequest = new ConnectRequest { RequestUri = httpRemoteUri, OriginalUrl = httpUrl, HttpVersion = version, }; await HeaderParser.ReadHeaders(clientStreamReader, connectRequest.Headers); var connectArgs = new TunnelConnectSessionEventArgs(BufferSize, endPoint, connectRequest); connectArgs.ProxyClient.TcpClient = tcpClient; connectArgs.ProxyClient.ClientStream = clientStream; if (TunnelConnectRequest != null) { await TunnelConnectRequest.InvokeParallelAsync(this, connectArgs, ExceptionFunc); } if (!excluded && await CheckAuthorization(clientStreamWriter, connectArgs) == false) { if (TunnelConnectResponse != null) { await TunnelConnectResponse.InvokeParallelAsync(this, connectArgs, ExceptionFunc); } return; } //write back successfull CONNECT response connectArgs.WebSession.Response = ConnectResponse.CreateSuccessfullConnectResponse(version); await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response); var clientHelloInfo = await SslTools.PeekClientHello(clientStream); bool isClientHello = clientHelloInfo != null; if (isClientHello) { connectRequest.ClientHelloInfo = clientHelloInfo; } if (TunnelConnectResponse != null) { connectArgs.IsHttpsConnect = isClientHello; await TunnelConnectResponse.InvokeParallelAsync(this, connectArgs, ExceptionFunc); } if (!excluded && isClientHello) { httpRemoteUri = new Uri("https://" + httpUrl); connectRequest.RequestUri = httpRemoteUri; SslStream sslStream = null; try { sslStream = new SslStream(clientStream); string certName = HttpHelper.GetWildCardDomainName(httpRemoteUri.Host); var certificate = endPoint.GenericCertificate ?? CertificateManager.CreateCertificate(certName, false); //Successfully managed to authenticate the client using the fake certificate await sslStream.AuthenticateAsServerAsync(certificate, false, SupportedSslProtocols, false); //HTTPS server created - we can now decrypt the client's traffic clientStream = new CustomBufferedStream(sslStream, BufferSize); clientStreamReader.Dispose(); clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); } catch { sslStream?.Dispose(); return; } //Now read the actual HTTPS request line httpCmd = await clientStreamReader.ReadLineAsync(); } //Hostname is excluded or it is not an HTTPS connect else { //create new connection using (var connection = await GetServerConnection(connectArgs, true)) { try { if (isClientHello) { if (clientStream.Available > 0) { //send the buffered data var data = new byte[clientStream.Available]; await clientStream.ReadAsync(data, 0, data.Length); await connection.Stream.WriteAsync(data, 0, data.Length); await connection.Stream.FlushAsync(); } var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream); ((ConnectResponse)connectArgs.WebSession.Response).ServerHelloInfo = serverHelloInfo; } await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }); } finally { UpdateServerConnectionCount(false); } } return; } } //Now create the request disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter, httpRemoteUri.Scheme == UriSchemeHttps?httpRemoteUri.Host : null, endPoint, connectRequest); } catch (Exception e) { ExceptionFunc(new Exception("Error whilst authorizing request", e)); } finally { if (!disposed) { Dispose(clientStream, clientStreamReader, clientStreamWriter, null); } } }
/// <summary> /// This is called when client is aware of proxy /// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy /// </summary> /// <param name="endPoint">The explicit endpoint.</param> /// <param name="clientConnection">The client connection.</param> /// <returns>The task.</returns> internal async Task handleClient(ExplicitProxyEndPoint endPoint, RequestStateBase state) { TcpClientConnection clientConnection = state.ClientConnection; var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool); Task <TcpServerConnection>?prefetchConnectionTask = null; bool closeServerConnection = false; bool calledRequestHandler = false; SslStream?sslStream = null; try { TunnelConnectSessionEventArgs?connectArgs = null; var method = await HttpHelper.GetMethod(clientStream, BufferPool, cancellationToken); if (clientStream.IsClosed) { return; } // Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request) if (method == KnownMethod.Connect) { // read the first line HTTP command var requestLine = await clientStream.ReadRequestLine(cancellationToken); if (requestLine.IsEmpty()) { return; } var connectRequest = new ConnectRequest(requestLine.RequestUri) { RequestUriString8 = requestLine.RequestUri, HttpVersion = requestLine.Version }; await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken); connectArgs = new TunnelConnectSessionEventArgs(state, endPoint, connectRequest, clientConnection, clientStream, cancellationTokenSource); clientStream.DataRead += (o, args) => connectArgs.OnDataSent(args.Buffer, args.Offset, args.Count); clientStream.DataWrite += (o, args) => connectArgs.OnDataReceived(args.Buffer, args.Offset, args.Count); await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc); // filter out excluded host names bool decryptSsl = endPoint.DecryptSsl && connectArgs.DecryptSsl; bool sendRawData = !decryptSsl; if (connectArgs.DenyConnect) { if (connectArgs.HttpClient.Response.StatusCode == 0) { connectArgs.HttpClient.Response = new Response { HttpVersion = HttpHeader.Version11, StatusCode = (int)HttpStatusCode.Forbidden, StatusDescription = "Forbidden" }; } // send the response await clientStream.WriteResponseAsync(connectArgs.HttpClient.Response, cancellationToken); return; } if (await checkAuthorization(connectArgs) == false) { await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc); // send the response await clientStream.WriteResponseAsync(connectArgs.HttpClient.Response, cancellationToken); return; } // write back successful CONNECT response var response = ConnectResponse.CreateSuccessfulConnectResponse(requestLine.Version); // Set ContentLength explicitly to properly handle HTTP 1.0 response.ContentLength = 0; response.Headers.FixProxyHeaders(); connectArgs.HttpClient.Response = response; await clientStream.WriteResponseAsync(response, cancellationToken); var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken); if (clientStream.IsClosed) { return; } bool isClientHello = clientHelloInfo != null; if (clientHelloInfo != null) { connectRequest.TunnelType = TunnelType.Https; connectRequest.ClientHelloInfo = clientHelloInfo; } await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc, isClientHello); if (decryptSsl && clientHelloInfo != null) { connectRequest.IsHttps = true; // todo: move this line to the previous "if" clientStream.Connection.SslProtocol = clientHelloInfo.SslProtocol; bool http2Supported = false; if (EnableHttp2) { var alpn = clientHelloInfo.GetAlpn(); if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2)) { // test server HTTP/2 support try { // todo: this is a hack, because Titanium does not support HTTP protocol changing currently var connection = await tcpConnectionFactory.GetServerConnection(state, true, SslExtensions.Http2ProtocolAsList, true, cancellationToken); http2Supported = connection.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2; // release connection back to pool instead of closing when connection pool is enabled. await tcpConnectionFactory.Release(connection, true); } catch (Exception) { // ignore } } } if (EnableTcpServerConnectionPrefetch) { IPAddress[]? ipAddresses = null; try { // make sure the host can be resolved before creating the prefetch task ipAddresses = await Dns.GetHostAddressesAsync(connectArgs.HttpClient.Request.RequestUri.Host); } catch (SocketException) { } if (ipAddresses != null && ipAddresses.Length > 0) { // don't pass cancellation token here // it could cause floating server connections when client exits prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(state, true, null, false, CancellationToken.None); } } string connectHostname = requestLine.RequestUri.GetString(); int idx = connectHostname.IndexOf(":"); if (idx >= 0) { connectHostname = connectHostname.Substring(0, idx); } X509Certificate2?certificate = null; try { sslStream = new SslStream(clientStream, false); string certName = HttpHelper.GetWildCardDomainName(connectHostname); certificate = endPoint.GenericCertificate ?? await CertificateManager.CreateServerCertificate(certName); // Successfully managed to authenticate the client using the fake certificate var options = new SslServerAuthenticationOptions(); if (EnableHttp2 && http2Supported) { options.ApplicationProtocols = clientHelloInfo.GetAlpn(); if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0) { options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList; } } options.ServerCertificate = certificate; options.ClientCertificateRequired = false; options.EnabledSslProtocols = SupportedSslProtocols; options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck; await sslStream.AuthenticateAsServerAsync(options, cancellationToken); #if NETSTANDARD2_1 clientStream.Connection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; #endif // HTTPS server created - we can now decrypt the client's traffic clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool); sslStream = null; // clientStream was created, no need to keep SSL stream reference clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count); clientStream.DataWrite += (o, args) => connectArgs.OnDecryptedDataReceived(args.Buffer, args.Offset, args.Count); } catch (Exception e) { var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false); throw new ProxyConnectException( $"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs); } method = await HttpHelper.GetMethod(clientStream, BufferPool, cancellationToken); if (clientStream.IsClosed) { return; } if (method == KnownMethod.Invalid) { sendRawData = true; await tcpConnectionFactory.Release(prefetchConnectionTask, true); prefetchConnectionTask = null; } } else if (clientHelloInfo == null) { method = await HttpHelper.GetMethod(clientStream, BufferPool, cancellationToken); if (clientStream.IsClosed) { return; } } if (cancellationTokenSource.IsCancellationRequested) { throw new Exception("Session was terminated by user."); } if (method == KnownMethod.Invalid) { sendRawData = true; } // Hostname is excluded or it is not an HTTPS connect if (sendRawData) { // create new connection to server. // If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then // this connection should not be HTTPS. var connection = await tcpConnectionFactory.GetServerConnection(state, true, SslExtensions.Http2ProtocolAsList, true, cancellationToken); try { if (isClientHello) { int available = clientStream.Available; if (available > 0) { // send the buffered data var data = BufferPool.GetBuffer(); try { // clientStream.Available should be at most BufferSize because it is using the same buffer size int read = await clientStream.ReadAsync(data, 0, available, cancellationToken); if (read != available) { throw new Exception("Internal error."); } await connection.Stream.WriteAsync(data, 0, available, true, cancellationToken); } finally { BufferPool.ReturnBuffer(data); } } var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream, BufferPool, cancellationToken); ((ConnectResponse)connectArgs.HttpClient.Response).ServerHelloInfo = serverHelloInfo; } if (!clientStream.IsClosed && !connection.Stream.IsClosed) { await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool, null, null, connectArgs.CancellationTokenSource, ExceptionFunc); } } finally { await tcpConnectionFactory.Release(connection, true); } return; } } if (connectArgs != null && method == KnownMethod.Pri) { // todo string?httpCmd = await clientStream.ReadLineAsync(cancellationToken); if (httpCmd == "PRI * HTTP/2.0") { connectArgs.HttpClient.ConnectRequest !.TunnelType = TunnelType.Http2; // HTTP/2 Connection Preface string?line = await clientStream.ReadLineAsync(cancellationToken); if (line != string.Empty) { throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received"); } line = await clientStream.ReadLineAsync(cancellationToken); if (line != "SM") { throw new Exception($"HTTP/2 Protocol violation. 'SM' expected, '{line}' received"); } line = await clientStream.ReadLineAsync(cancellationToken); if (line != string.Empty) { throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received"); } var connection = await tcpConnectionFactory.GetServerConnection(state, true, SslExtensions.Http2ProtocolAsList, true, cancellationToken); try { #if NETSTANDARD2_1 var connectionPreface = new ReadOnlyMemory <byte>(Http2Helper.ConnectionPreface); await connection.Stream.WriteAsync(connectionPreface, cancellationToken); await Http2Helper.SendHttp2(clientStream, connection.Stream, () => new SessionEventArgs(state, endPoint, clientStream, connectArgs?.HttpClient.ConnectRequest, cancellationTokenSource) { UserData = connectArgs?.UserData }, async args => { await onBeforeRequest(args); }, async args => { await onBeforeResponse(args); }, connectArgs.CancellationTokenSource, clientStream.Connection.Id, ExceptionFunc); #endif } finally { await tcpConnectionFactory.Release(connection, true); } } } calledRequestHandler = true; // Now create the request await handleHttpSessionRequest(endPoint, state, clientStream, cancellationTokenSource, connectArgs, prefetchConnectionTask); } catch (ProxyException e) { closeServerConnection = true; onException(clientStream, e); } catch (IOException e) { closeServerConnection = true; onException(clientStream, new Exception("Connection was aborted", e)); } catch (SocketException e) { closeServerConnection = true; onException(clientStream, new Exception("Could not connect", e)); } catch (Exception e) { closeServerConnection = true; onException(clientStream, new Exception("Error occured in whilst handling the client", e)); } finally { if (!calledRequestHandler) { await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection); } sslStream?.Dispose(); clientStream.Dispose(); } }
private void ReadConnectResult(byte[] content) { using (var reader = new EndianBinaryReader(EndianBitConverter.Big, new MemoryStream(content), Encoding.UTF8)) { BinaryInputArchive bbia = BinaryInputArchive.GetArchive(reader); ConnectResponse conRsp = new ConnectResponse(); conRsp.Deserialize(bbia, "connect"); negotiatedSessionTimeout = conRsp.TimeOut; if (negotiatedSessionTimeout <= 0) { zooKeeper.State = ZooKeeper.States.CLOSED; conn.consumer.QueueEvent(new WatchedEvent(KeeperState.Expired, EventType.None, null)); throw new SessionExpiredException(new StringBuilder().AppendFormat("Unable to reconnect to ZooKeeper service, session 0x{0:X} has expired", conn.SessionId).ToString()); } conn.readTimeout = new TimeSpan(0, 0, 0, 0, negotiatedSessionTimeout * 2 / 3); // commented...we haven't need this information yet... //conn.connectTimeout = new TimeSpan(0, 0, 0, negotiatedSessionTimeout / conn.serverAddrs.Count); conn.SessionId = conRsp.SessionId; conn.SessionPassword = conRsp.Passwd; zooKeeper.State = ZooKeeper.States.CONNECTED; #if !NET_CORE LOG.InfoFormat("Session establishment complete on server {0:X}, negotiated timeout = {1}", conn.SessionId, negotiatedSessionTimeout); #endif conn.consumer.QueueEvent(new WatchedEvent(KeeperState.SyncConnected, EventType.None, null)); } }
public override void CallServerMethod(uint token, uint methodId, CodedInputStream stream) { switch (methodId) { case 1: { ConnectRequest request = ConnectRequest.Parser.ParseFrom(stream); ConnectResponse response = new ConnectResponse(); BattlenetRpcErrorCode status = HandleConnect(request, response); Log.outDebug(LogFilter.ServiceProtobuf, "{0} Client called server method ConnectionService.Connect(bgs.protocol.connection.v1.ConnectRequest: {1}) returned bgs.protocol.connection.v1.ConnectResponse: {2} status: {3}.", GetCallerInfo(), request.ToString(), response.ToString(), status); if (status == 0) { SendResponse(token, response); } else { SendResponse(token, status); } break; } case 2: { BindRequest request = new BindRequest(); request.MergeFrom(stream); BindResponse response = new BindResponse(); BattlenetRpcErrorCode status = HandleBind(request, response); Log.outDebug(LogFilter.ServiceProtobuf, "{0} Client called server method ConnectionService.Bind(bgs.protocol.connection.v1.BindRequest: {1}) returned bgs.protocol.connection.v1.BindResponse: {2} status: {3}.", GetCallerInfo(), request.ToString(), response.ToString(), status); if (status == 0) { SendResponse(token, response); } else { SendResponse(token, status); } break; } case 3: { EchoRequest request = new EchoRequest(); request.MergeFrom(stream); EchoResponse response = new EchoResponse(); BattlenetRpcErrorCode status = HandleEcho(request, response); Log.outDebug(LogFilter.ServiceProtobuf, "{0} Client called server method ConnectionService.Echo(bgs.protocol.connection.v1.EchoRequest: {1}) returned bgs.protocol.connection.v1.EchoResponse: {2} status: {3}.", GetCallerInfo(), request.ToString(), response.ToString(), status); if (status == 0) { SendResponse(token, response); } else { SendResponse(token, status); } break; } case 4: { DisconnectNotification request = DisconnectNotification.Parser.ParseFrom(stream); BattlenetRpcErrorCode status = HandleForceDisconnect(request); Log.outDebug(LogFilter.ServiceProtobuf, "{0} Client called server method ConnectionService.ForceDisconnect(bgs.protocol.connection.v1.DisconnectNotification: {1}) status: {2}.", GetCallerInfo(), request.ToString(), status); if (status != 0) { SendResponse(token, status); } break; } case 5: { NoData request = NoData.Parser.ParseFrom(stream); BattlenetRpcErrorCode status = HandleKeepAlive(request); Log.outDebug(LogFilter.ServiceProtobuf, "{0} Client called server method ConnectionService.KeepAlive(bgs.protocol.NoData: {1}) status: {2}.", GetCallerInfo(), request.ToString(), status); if (status != 0) { SendResponse(token, status); } break; } case 6: { EncryptRequest request = EncryptRequest.Parser.ParseFrom(stream); NoData response = new NoData(); BattlenetRpcErrorCode status = HandleEncrypt(request, response); Log.outDebug(LogFilter.ServiceProtobuf, "{0} Client called server method ConnectionService.Encrypt(bgs.protocol.connection.v1.EncryptRequest: {1}) returned bgs.protocol.NoData: {2} status: {3}.", GetCallerInfo(), request.ToString(), response.ToString(), status); if (status == 0) { SendResponse(token, response); } else { SendResponse(token, status); } break; } case 7: { DisconnectRequest request = DisconnectRequest.Parser.ParseFrom(stream); BattlenetRpcErrorCode status = HandleRequestDisconnect(request); Log.outDebug(LogFilter.ServiceProtobuf, "{0} Client called server method ConnectionService.RequestDisconnect(bgs.protocol.connection.v1.DisconnectRequest: {1}) status: {2}.", GetCallerInfo(), request.ToString(), status); if (status != 0) { SendResponse(token, status); } break; } default: Log.outError(LogFilter.ServiceProtobuf, "Bad method id {0}.", methodId); SendResponse(token, BattlenetRpcErrorCode.RpcInvalidMethod); break; } }
public void Handle(ConnectResponse message) { OnConnect?.Invoke(message); }
internal Connection(string stanClusterID, string clientID, StanOptions options) { this.clientID = clientID; connID = Google.Protobuf.ByteString.CopyFrom(System.Text.Encoding.UTF8.GetBytes(pubNUID.Next)); opts = (options != null) ? new StanOptions(options) : new StanOptions(); if (opts.natsConn == null) { ncOwned = true; try { var nopts = ConnectionFactory.GetDefaultOptions(); nopts.MaxReconnect = Options.ReconnectForever; nopts.Url = opts.NatsURL; // TODO: disable buffering. nc = new ConnectionFactory().CreateConnection(nopts); } catch (Exception ex) { throw new StanConnectionException(ex); } } else { nc = opts.natsConn; ncOwned = false; } // Prepare a subscription on ping responses, even if we are not // going to need it, so that if that fails, it fails before initiating // a connection. pingSubscription = nc.SubscribeAsync(newInbox(), processPingResponse); // create a heartbeat inbox string hbInbox = newInbox(); hbSubscription = nc.SubscribeAsync(hbInbox, processHeartBeat); string discoverSubject = opts.discoverPrefix + "." + stanClusterID; // The streaming server expects seconds, but can handle millis // millis are denoted by negative numbers. int pi; if (opts.PingInterval < 1000) { pi = opts.pingInterval * -1; } else { pi = opts.pingInterval / 1000; } ConnectRequest req = new ConnectRequest { ClientID = clientID, HeartbeatInbox = hbInbox, ConnID = (Google.Protobuf.ByteString)connID, Protocol = StanConsts.protocolOne, PingMaxOut = opts.PingMaxOutstanding, PingInterval = pi }; Msg cr; try { cr = nc.Request(discoverSubject, ProtocolSerializer.marshal(req), opts.ConnectTimeout); } catch (NATSTimeoutException) { protoUnsubscribe(); throw new StanConnectRequestTimeoutException( string.Format("No response from a streaming server with a cluster ID of '{0}'", stanClusterID)); } ConnectResponse response = new ConnectResponse(); try { ProtocolSerializer.unmarshal(cr.Data, response); } catch (Exception e) { protoUnsubscribe(); throw new StanConnectRequestException(e); } if (!string.IsNullOrEmpty(response.Error)) { protoUnsubscribe(); throw new StanConnectRequestException(response.Error); } // capture cluster configuration endpoints to publish and subscribe/unsubscribe pubPrefix = response.PubPrefix; subRequests = response.SubRequests; unsubRequests = response.UnsubRequests; subCloseRequests = response.SubCloseRequests; closeRequests = response.CloseRequests; // setup the Ack subscription ackSubject = StanConsts.DefaultACKPrefix + "." + newGUID(); ackSubscription = nc.SubscribeAsync(ackSubject, processAck); // TODO: hardcode or options? ackSubscription.SetPendingLimits(1024 * 1024, 32 * 1024 * 1024); pubAckMap = new BlockingDictionary <string, PublishAck>(opts.maxPubAcksInflight); // TODO - check out sub map and chans bool unsubPing = true; // Do this with servers which are at least at protcolOne. if (response.Protocol >= StanConsts.protocolOne) { // Note that in the future server may override client ping // interval value sent in ConnectRequest, so use the // value in ConnectResponse to decide if we send PINGs // and at what interval. // In tests, the interval could be negative to indicate // milliseconds. if (response.PingInterval != 0) { unsubPing = false; // These will be immutable pingRequests = response.PingRequests; pingInbox = pingSubscription.Subject; // negative values returned from the server are ms if (response.PingInterval < 0) { pingInterval = response.PingInterval * -1; } else { // if positive, the result is in seconds, but // in the .NET clients we always use millis. pingInterval = response.PingInterval * 1000; } pingMaxOut = response.PingMaxOut; pingBytes = ProtocolSerializer.createPing(connID); pingTimer = new Timer(pingServer, null, pingInterval, Timeout.Infinite); } } if (unsubPing) { pingSubscription.Unsubscribe(); pingSubscription = null; } }
/// <summary> /// This is called when client is aware of proxy /// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy /// </summary> /// <param name="endPoint">The explicit endpoint.</param> /// <param name="clientConnection">The client connection.</param> /// <returns>The task.</returns> private async Task handleClient(ExplicitProxyEndPoint endPoint, TcpClientConnection clientConnection) { var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize); Task <TcpServerConnection> prefetchConnectionTask = null; bool closeServerConnection = false; bool calledRequestHandler = false; SslStream sslStream = null; try { string connectHostname = null; TunnelConnectSessionEventArgs connectArgs = null; // Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request) if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1) { // read the first line HTTP command string httpCmd = await clientStream.ReadLineAsync(cancellationToken); if (string.IsNullOrEmpty(httpCmd)) { return; } Request.ParseRequestLine(httpCmd, out string _, out string httpUrl, out var version); var httpRemoteUri = new Uri("http://" + httpUrl); connectHostname = httpRemoteUri.Host; var connectRequest = new ConnectRequest { RequestUri = httpRemoteUri, OriginalUrl = httpUrl, HttpVersion = version }; await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken); connectArgs = new TunnelConnectSessionEventArgs(this, endPoint, connectRequest, cancellationTokenSource); connectArgs.ProxyClient.Connection = clientConnection; connectArgs.ProxyClient.ClientStream = clientStream; await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc); // filter out excluded host names bool decryptSsl = endPoint.DecryptSsl && connectArgs.DecryptSsl; if (connectArgs.DenyConnect) { if (connectArgs.HttpClient.Response.StatusCode == 0) { connectArgs.HttpClient.Response = new Response { HttpVersion = HttpHeader.Version11, StatusCode = (int)HttpStatusCode.Forbidden, StatusDescription = "Forbidden" }; } // send the response await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response, cancellationToken : cancellationToken); return; } if (await checkAuthorization(connectArgs) == false) { await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc); // send the response await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response, cancellationToken : cancellationToken); return; } // write back successful CONNECT response var response = ConnectResponse.CreateSuccessfulConnectResponse(version); // Set ContentLength explicitly to properly handle HTTP 1.0 response.ContentLength = 0; response.Headers.FixProxyHeaders(); connectArgs.HttpClient.Response = response; await clientStreamWriter.WriteResponseAsync(response, cancellationToken : cancellationToken); var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken); bool isClientHello = clientHelloInfo != null; if (isClientHello) { connectRequest.TunnelType = TunnelType.Https; connectRequest.ClientHelloInfo = clientHelloInfo; } await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc, isClientHello); if (decryptSsl && isClientHello) { connectRequest.RequestUri = new Uri("https://" + httpUrl); bool http2Supported = false; var alpn = clientHelloInfo.GetAlpn(); if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2)) { // test server HTTP/2 support try { // todo: this is a hack, because Titanium does not support HTTP protocol changing currently var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs, isConnect : true, applicationProtocols : SslExtensions.Http2ProtocolAsList, noCache : true, cancellationToken : cancellationToken); http2Supported = connection.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2; //release connection back to pool instead of closing when connection pool is enabled. await tcpConnectionFactory.Release(connection, true); } catch (Exception) { // ignore } } if (EnableTcpServerConnectionPrefetch) { IPAddress[] ipAddresses = null; try { //make sure the host can be resolved before creating the prefetch task ipAddresses = await Dns.GetHostAddressesAsync(connectArgs.HttpClient.Request.RequestUri.Host); } catch (SocketException) { } if (ipAddresses != null && ipAddresses.Length > 0) { //don't pass cancellation token here //it could cause floating server connections when client exits prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(this, connectArgs, isConnect: true, applicationProtocols: null, noCache: false, cancellationToken: CancellationToken.None); } } X509Certificate2 certificate = null; try { sslStream = new MySslStream(clientStream, false); string certName = HttpHelper.GetWildCardDomainName(connectHostname); certificate = endPoint.GenericCertificate ?? await CertificateManager.CreateServerCertificate(certName); // Successfully managed to authenticate the client using the fake certificate var options = new SslServerAuthenticationOptions(); if (EnableHttp2 && http2Supported) { options.ApplicationProtocols = clientHelloInfo.GetAlpn(); if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0) { options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList; } } options.ServerCertificate = certificate; options.ClientCertificateRequired = false; options.EnabledSslProtocols = SupportedSslProtocols; options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck; await sslStream.AuthenticateAsServerAsync(options, cancellationToken); #if NETCOREAPP2_1 clientConnection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; #endif // HTTPS server created - we can now decrypt the client's traffic clientStream = new CustomBufferedStream(new StreamWrapper(sslStream), BufferPool, BufferSize); clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize); } catch (Exception e) { var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false); throw new ProxyConnectException( $"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs); } if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == -1) { decryptSsl = false; } if (!decryptSsl) { await tcpConnectionFactory.Release(prefetchConnectionTask, true); prefetchConnectionTask = null; } } if (cancellationTokenSource.IsCancellationRequested) { throw new Exception("Session was terminated by user."); } // Hostname is excluded or it is not an HTTPS connect if (!decryptSsl || !isClientHello) { if (!isClientHello) { connectRequest.TunnelType = TunnelType.Websocket; } // create new connection to server. // If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then // this connection should not be HTTPS. var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs, isConnect : true, applicationProtocols : SslExtensions.Http2ProtocolAsList, noCache : true, cancellationToken : cancellationToken); try { if (isClientHello) { int available = clientStream.Available; if (available > 0) { // send the buffered data var data = BufferPool.GetBuffer(BufferSize); try { // clientStream.Available should be at most BufferSize because it is using the same buffer size await clientStream.ReadAsync(data, 0, available, cancellationToken); await connection.StreamWriter.WriteAsync(data, 0, available, true, cancellationToken); } finally { BufferPool.ReturnBuffer(data); } } var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream, BufferPool, cancellationToken); ((ConnectResponse)connectArgs.HttpClient.Response).ServerHelloInfo = serverHelloInfo; } if (!clientStream.IsClosed && !connection.Stream.IsClosed) { await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool, BufferSize, (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, connectArgs.CancellationTokenSource, ExceptionFunc); } } finally { await tcpConnectionFactory.Release(connection, true); } return; } } if (connectArgs != null && await HttpHelper.IsPriMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1) { // todo string httpCmd = await clientStream.ReadLineAsync(cancellationToken); if (httpCmd == "PRI * HTTP/2.0") { connectArgs.HttpClient.ConnectRequest.TunnelType = TunnelType.Http2; // HTTP/2 Connection Preface string line = await clientStream.ReadLineAsync(cancellationToken); if (line != string.Empty) { throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received"); } line = await clientStream.ReadLineAsync(cancellationToken); if (line != "SM") { throw new Exception($"HTTP/2 Protocol violation. 'SM' expected, '{line}' received"); } line = await clientStream.ReadLineAsync(cancellationToken); if (line != string.Empty) { throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received"); } var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs, isConnect : true, applicationProtocols : SslExtensions.Http2ProtocolAsList, noCache : true, cancellationToken : cancellationToken); try { await connection.StreamWriter.WriteLineAsync("PRI * HTTP/2.0", cancellationToken); await connection.StreamWriter.WriteLineAsync(cancellationToken); await connection.StreamWriter.WriteLineAsync("SM", cancellationToken); await connection.StreamWriter.WriteLineAsync(cancellationToken); #if NETCOREAPP2_1 await Http2Helper.SendHttp2(clientStream, connection.Stream, BufferSize, (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, () => new SessionEventArgs(this, endPoint, cancellationTokenSource) { ProxyClient = { Connection = clientConnection }, HttpClient = { ConnectRequest = connectArgs?.HttpClient.ConnectRequest }, UserData = connectArgs?.UserData }, async args => { await invokeBeforeRequest(args); }, async args => { await invokeBeforeResponse(args); }, connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc); #endif } finally { await tcpConnectionFactory.Release(connection, true); } } } calledRequestHandler = true; // Now create the request await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, cancellationTokenSource, connectHostname, connectArgs, prefetchConnectionTask); } catch (ProxyException e) { closeServerConnection = true; onException(clientStream, e); } catch (IOException e) { closeServerConnection = true; onException(clientStream, new Exception("Connection was aborted", e)); } catch (SocketException e) { closeServerConnection = true; onException(clientStream, new Exception("Could not connect", e)); } catch (Exception e) { closeServerConnection = true; onException(clientStream, new Exception("Error occured in whilst handling the client", e)); } finally { if (!calledRequestHandler) { await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection); } sslStream?.Dispose(); clientStream.Dispose(); if (!cancellationTokenSource.IsCancellationRequested) { cancellationTokenSource.Cancel(); } } }
public void Answer(Reject reject, B1Protocol b1, B2Protocol b2, B3Protocol b3) { Debug.Assert(_status == ConnectionStatus.D_ConnectPending); if (_connectIndication == null || _status != ConnectionStatus.D_ConnectPending) { throw new NotSupportedException("Connection is not in the right state."); } ConnectResponse response = new ConnectResponse(_connectIndication); _connectIndication = null; response.Reject = reject; response.BPtotocol.B1 = b1; response.BPtotocol.B2 = b2; response.BPtotocol.B3 = b3; _application.SendMessage(response); }
// note: this method will run on a thread from the ThreadPool private void ConnectWorkItem( object argsObject ) { var args = (ConnectArgs) argsObject; var serverInstance = args.ServerInstance; var response = new ConnectResponse { ServerInstance = serverInstance }; try { serverInstance.Connect(true); // slaveOk response.IsMasterResult = serverInstance.IsMasterResult; } catch { // exception is already stored in serverInstance.ConnectException and will be handled later } args.ResponseQueue.Enqueue(response); }
public void Handle(ConnectResponse message) { Console.WriteLine("Connected!"); Console.WriteLine(message.Message); }
private void ProcessAdditionalResponse(ConnectResponse response) { // additional responses have to be for the same replica set name as the first response var replicaSetName = response.IsMasterResult.Response["setName"].AsString; if (replicaSetName != _server.ReplicaSetName) { var message = string.Format( "Server at address '{0}' is a member of replica set '{1}' and not '{2}'.", response.ServerInstance.Address, replicaSetName, _server.ReplicaSetName); throw new MongoConnectionException(message); } }
internal Connection(string stanClusterID, string clientID, StanOptions options) { this.clientID = clientID; if (options != null) { opts = new StanOptions(options); } else { opts = new StanOptions(); } if (opts.natsConn == null) { ncOwned = true; try { nc = new ConnectionFactory().CreateConnection(opts.NatsURL); } catch (Exception ex) { throw new StanConnectionException(ex); } } else { nc = opts.natsConn; ncOwned = false; } // create a heartbeat inbox string hbInbox = newInbox(); hbSubscription = nc.SubscribeAsync(hbInbox, processHeartBeat); string discoverSubject = opts.discoverPrefix + "." + stanClusterID; ConnectRequest req = new ConnectRequest(); req.ClientID = this.clientID; req.HeartbeatInbox = hbInbox; Msg cr; try { cr = nc.Request(discoverSubject, ProtocolSerializer.marshal(req), opts.ConnectTimeout); } catch (NATSTimeoutException) { throw new StanConnectRequestTimeoutException(); } ConnectResponse response = new ConnectResponse(); try { ProtocolSerializer.unmarshal(cr.Data, response); } catch (Exception e) { throw new StanConnectRequestException(e); } if (!string.IsNullOrEmpty(response.Error)) { throw new StanConnectRequestException(response.Error); } // capture cluster configuration endpoints to publish and subscribe/unsubscribe pubPrefix = response.PubPrefix; subRequests = response.SubRequests; unsubRequests = response.UnsubRequests; subCloseRequests = response.SubCloseRequests; closeRequests = response.CloseRequests; // setup the Ack subscription ackSubject = StanConsts.DefaultACKPrefix + "." + newGUID(); ackSubscription = nc.SubscribeAsync(ackSubject, processAck); // TODO: hardcode or options? ackSubscription.SetPendingLimits(1024 * 1024, 32 * 1024 * 1024); pubAckMap = new BlockingDictionary <string, PublishAck>(opts.maxPubAcksInflight); }
private void ProcessResponse(ConnectResponse response) { _responses.Add(response); // don't process response if it threw an exception if (response.Exception != null) { return; } // don't process response if Disconnect was called before the response was received if (_server.State == MongoServerState.Disconnected || _server.State == MongoServerState.Disconnecting) { return; } // don't process response if it was for a previous connection attempt if (_connectionAttempt != _server.ConnectionAttempt) { return; } try { if (!response.IsMasterResult.Response.Contains("setName")) { var message = string.Format("Server at address '{0}' does not have a replica set name.", response.ServerInstance.Address); throw new MongoConnectionException(message); } if (!response.IsMasterResult.Response.Contains("hosts")) { var message = string.Format("Server at address '{0}' does not have a hosts list.", response.ServerInstance.Address); throw new MongoConnectionException(message); } if (_firstResponseHasBeenProcessed) { ProcessAdditionalResponse(response); } else { ProcessFirstResponse(response); _firstResponseHasBeenProcessed = true; // remains false if ProcessFirstResponse throws an exception } } catch (Exception ex) { response.ServerInstance.ConnectException = ex; try { response.ServerInstance.Disconnect(); } catch { } // ignore exceptions } }
public void ReceivedData(UdpReceiveResult res, UdpClient client) { var receivedData = res.Buffer; var endPointAddress = res.RemoteEndPoint.Address; var addressString = endPointAddress.ToString(); if (receivedData.Length > 12) { var action = Unpack.UInt32(receivedData, 8); //connect,announce,scrape switch (action) { case 0: var connectRequest = new ConnectRequest(receivedData); Console.WriteLine("[Connect] from " + addressString + ":" + res.RemoteEndPoint.Port); var connectResponse = new ConnectResponse(0, connectRequest.TransactionID, (long)13376969); SendDataAsync(client, connectResponse.Data, res.RemoteEndPoint); break; case 1: var announceRequest = new AnnounceRequest(receivedData); Console.WriteLine("[Announce] from " + addressString + ":" + announceRequest.Port + ", " + (TorrentEvent)announceRequest.TorrentEvent); var peer = new TorrentPeer(addressString, announceRequest.Port); if ((TorrentEvent)announceRequest.TorrentEvent != TorrentEvent.Stopped) { RedisBacking.AddPeer(peer, announceRequest.InfoHash); } else { RedisBacking.RemovePeer(peer, announceRequest.InfoHash); } var peers = RedisBacking.GetPeers(announceRequest.InfoHash); var torrentInfo = RedisBacking.ScrapeHashes(new List <byte[]>() { announceRequest.InfoHash }); var announceResponse = new AnnounceResponse(announceRequest.TransactionID, AnnounceInterval, torrentInfo.First().Leechers, torrentInfo.First().Seeders, peers); SendDataAsync(client, announceResponse.Data, res.RemoteEndPoint); break; case 2: var scrapeRequest = new ScrapeRequest(receivedData); Console.WriteLine(string.Format("[Scrape] from {0} for {1} torrents", addressString, scrapeRequest.InfoHashes.Count)); var scrapedTorrents = RedisBacking.ScrapeHashes(scrapeRequest.InfoHashes); var scrapeResponse = new ScrapeResponse(scrapeRequest.TransactionID, scrapedTorrents); SendDataAsync(client, scrapeResponse.Data, res.RemoteEndPoint); break; default: Console.WriteLine(Encoding.UTF8.GetString(receivedData)); break; } } else { Console.WriteLine(Encoding.UTF8.GetString(receivedData)); } }