public static void Main(string[] args) { Console.WriteLine("Starting..."); X509Certificate2 serverCertificate = new X509Certificate2("certificate.pfx"); // Any valid certificate with private key will work fine. TcpListener listener = new TcpListener(IPAddress.Any, 4567); TcpClient client = new TcpClient(); listener.Start(); Task clientConnectTask = client.ConnectAsync(IPAddress.Loopback, 4567); Task<TcpClient> listenerAcceptTask = listener.AcceptTcpClientAsync(); Task.WaitAll(clientConnectTask, listenerAcceptTask); TcpClient server = listenerAcceptTask.Result; SslStream clientStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null, EncryptionPolicy.RequireEncryption); SslStream serverStream = new SslStream(server.GetStream(), false, null, null, EncryptionPolicy.RequireEncryption); Task clientAuthenticationTask = clientStream.AuthenticateAsClientAsync(serverCertificate.GetNameInfo(X509NameType.SimpleName, false), null, SslProtocols.Tls12, false); Task serverAuthenticationTask = serverStream.AuthenticateAsServerAsync(serverCertificate, false, SslProtocols.Tls12, false); Task.WaitAll(clientAuthenticationTask, serverAuthenticationTask); byte[] readBuffer = new byte[256]; Task<int> readTask = clientStream.ReadAsync(readBuffer, 0, readBuffer.Length); // Create a pending ReadAsync, which will wait for data that will never come (for testing purposes). byte[] writeBuffer = new byte[256]; Task writeTask = clientStream.WriteAsync(writeBuffer, 0, writeBuffer.Length); // The main thread actually blocks here (not asychronously waits) on .NET Core making this call. bool result = Task.WaitAll(new Task[1] { writeTask }, 5000); // This code won't even be reached on .NET Core. Works fine on .NET Framework. if (result) { Console.WriteLine("WriteAsync completed successfully while ReadAsync was pending... nothing locked up."); } else { Console.WriteLine("WriteAsync failed to complete after 5 seconds."); } }
private async Task StartClientToServerComms() { string host = "10.1.1.84"; int port = 58846; Console.WriteLine("[Relay] Connecting to {0}:{1}", host, port); using (var nextTcpClient = new TcpClient()) { await nextTcpClient.ConnectAsync(host, port); Console.WriteLine("[Relay] Connected to server"); byte[] clientBuffer = new byte[4096]; using (var clientToServerNetworkStream = new SslStream(nextTcpClient.GetStream(), true, (sender, certificate, chain, errors) => { return true; })) { clientToServerNetworkStream.AuthenticateAsClient(host); while (true) { var clientBytes = await clientToServerNetworkStream.ReadAsync(clientBuffer, 0, clientBuffer.Length); if (clientBytes > 0) { Console.WriteLine("Client sent {0}", DelugeRPC.DelugeProtocol.DecompressAndDecode(clientBuffer).Dump()); await clientToServerNetworkStream.WriteAsync(clientBuffer, 0, clientBuffer.Length); } } } } }
public async Task CertificatePassedToHttpContext() { RemoteCertificateValidationCallback validationCallback = (sender, cert, chain, sslPolicyErrors) => true; try { #if DNX451 ServicePointManager.ServerCertificateValidationCallback += validationCallback; #endif var serverAddress = "https://*****:*****@"TestResources/testCert.pfx", "testPassword"), ClientCertificateMode = ClientCertificateMode.RequireCertificate, ClientCertificateValidation = (certificate, chain, sslPolicyErrors) => true }, new NoOpConnectionFilter()) }; RequestDelegate app = context => { var tlsFeature = context.Features.Get<ITlsConnectionFeature>(); Assert.NotNull(tlsFeature); Assert.NotNull(tlsFeature.ClientCertificate); Assert.NotNull(context.Connection.ClientCertificate); return context.Response.WriteAsync("hello world"); }; using (var server = new TestServer(app, serviceContext, serverAddress)) { // SslStream is used to ensure the certificate is actually passed to the server // HttpClient might not send the certificate because it is invalid or it doesn't match any // of the certificate authorities sent by the server in the SSL handshake. using (var client = new TcpClient()) { await client.ConnectAsync("127.0.0.1", 54321); SslStream stream = new SslStream(client.GetStream(), false, (sender, certificate, chain, errors) => true, (sender, host, certificates, certificate, issuers) => new X509Certificate2(@"TestResources/testCert.pfx", "testPassword")); await stream.AuthenticateAsClientAsync("localhost"); var request = Encoding.UTF8.GetBytes("GET / HTTP/1.0\r\n\r\n"); await stream.WriteAsync(request, 0, request.Length); var reader = new StreamReader(stream); var line = await reader.ReadLineAsync(); Assert.Equal("HTTP/1.0 200 OK", line); } } } finally { #if DNX451 ServicePointManager.ServerCertificateValidationCallback -= validationCallback; #endif } }
// Handle new connection private async Task HandleConnectionAsync(TcpClient tcpClient) { await Task.Yield(); // continue asynchronously on another threads using (var networkStream = new SslStream(tcpClient.GetStream())) { var configItems = new object[] { new object[] {"listen_ports", new object[] {"31337", "1337"}}, new object[] {"dht", true}, new object[] {"info_sent", 0.0}, new object[] {"lsd", true}, new object[] {"max_download_speed", -1.0}, new object[] {"send_info", false}, new object[] {"natpmp", true}, new object[] {"move_completed_path", "C:\\Users\\Adam\\Downloads"}, new object[] {"peer_tos", "0x00"}, new object[] {"enc_in_policy", 1}, new object[] {"queue_new_to_top", false}, new object[] {"ignore_limits_on_local_network", true}, new object[] {"rate_limit_ip_overhead", true}, new object[] {"daemon_port", 58846}, new object[] {"torrentfiles_location", "C:\\Users\\Adam\\Downloads"}, new object[] {"max_active_limit", 8}, new object[] {"geoip_db_location", "/usr/share/GeoIP/GeoIP.dat"}, new object[] {"upnp", true}, new object[] {"utpex", true}, new object[] {"max_active_downloading", 3}, new object[] {"max_active_seeding", 5}, new object[] {"allow_remote", true}, new object[] {"enabled_plugins", new object[0]}, new object[] {"max_half_open_connections", 8}, new object[] {"download_location", "C:\\Users\\Adam\\Downloads"}, new object[] {"compact_allocation", false}, new object[] {"max_upload_speed", -1.0}, new object[] {"plugins_location", "C:\\Users\\Adam\\AppData\\Roaming\\deluge\\plugins"}, new object[] {"max_connections_global", 200}, new object[] {"enc_prefer_rc4", true}, new object[] {"cache_expiry", 60}, new object[] {"stop_seed_at_ratio", false}, new object[] {"stop_seed_ratio", 2.0}, new object[] {"max_download_speed_per_torrent", -1}, new object[] {"prioritize_first_last_pieces", false}, new object[] {"max_upload_speed_per_torrent", -1}, new object[] {"auto_managed", true}, new object[] {"enc_level", 2}, new object[] {"copy_torrent_file", false}, new object[] {"max_connections_per_second", 20}, new object[] {"dont_count_slow_torrents", false}, new object[] {"add_paused", false}, new object[] {"random_outgoing_ports", true}, new object[] {"max_upload_slots_per_torrent", -1}, new object[] {"new_release_check", true}, new object[] {"enc_out_policy", 1}, new object[] {"seed_time_ratio_limit", 7.0}, new object[] {"remove_seed_at_ratio", false}, new object[] {"autoadd_location", "C:\\Users\\Adam\\Downloads"}, new object[] {"max_upload_slots_global", 4}, new object[] {"seed_time_limit", 180}, new object[] {"cache_size", 512}, new object[] {"share_ratio_limit", 2.0}, new object[] {"random_port", true}, new object[] {"listen_interface", ""}, new object[] { "max_connections_per_torrent", -1}, new object[] {"move_completed", false} }; await networkStream.AuthenticateAsServerAsync(X509Certificate2.CreateFromCertFile(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "deluge.pfx"))); var buffer = new byte[4096]; var byteCount = await networkStream.ReadAsync(buffer, 0, buffer.Length); var bufferObject = DelugeRPC.DelugeProtocol.DecompressAndDecode(buffer); var id = (((bufferObject) as object[])[0] as object[])[0]; var response = DelugeRPC.DelugeProtocol.CompressAndEncode(new object[] { 1, id, 10 }); //var serverResponseBytes = Encoding.UTF8.GetBytes("Hello from server"); await networkStream.WriteAsync(response, 0, response.Length); //Console.WriteLine("[Server] Response has been written"); while (true) { byteCount = await networkStream.ReadAsync(buffer, 0, buffer.Length); if (byteCount > 0) { var handled = false; var temp = DelugeRPC.DelugeProtocol.DecompressAndDecode(buffer); var tempMessage = new RPCMessage(temp as object[]); Console.WriteLine(tempMessage.ID); if (tempMessage.Command == "daemon.info") { response = DelugeRPC.DelugeProtocol.CompressAndEncode(new object[] {1, tempMessage.ID, "6.6.6"}); handled = true; networkStream.WriteAsync(response, 0, response.Length); } if (tempMessage.Command == "core.get_filter_tree") { var filter = new object[] { 1, tempMessage.ID, new object[] { new object[] {"state", new object[] {new object[] {"All", 0}}}, new object[] {"tracker_host", new object[] {new object[] {"All", 0}}} } }; response = DelugeRPC.DelugeProtocol.CompressAndEncode(filter); handled = true; networkStream.WriteAsync(response, 0, response.Length); } if (tempMessage.Command == "core.get_free_space" || tempMessage.Command == "core.get_num_connections") { DelugeRPC.DelugeProtocol.CompressAndEncode(new object[] {1, tempMessage.ID, new object[] {0}}); handled = true; networkStream.WriteAsync(response, 0, response.Length); } /* Unimplemented command { ID: 2, Command: core.get_config_value, Parameters: [ max_download_speed ], NamedParameters: {} } lol Unimplemented command { ID: 3, Command: core.get_config_value, Parameters: [ max_upload_speed ], NamedParameters: {} } */ if (tempMessage.Command == "core.get_config_value") { var inner = configItems.ToList(); Console.WriteLine("Asking for config {0}", tempMessage.Parameters[0]); var config = new object[] { 1, tempMessage.ID, inner.First(x=> ((object[]) x)[0].ToString() == tempMessage.Parameters[0].ToString()) }; response = DelugeRPC.DelugeProtocol.CompressAndEncode(config); handled = true; networkStream.WriteAsync(response, 0, response.Length); } if (tempMessage.Command == "core.get_config_values") { var inner = configItems.ToList(); Console.WriteLine("Asking for config {0}", tempMessage.Parameters.Dump()); var selected = (from p in ((object[])(tempMessage.Parameters[0])) join i in inner on p equals ((object[]) i)[0] select i).ToArray(); var unmatched = ((object[]) tempMessage.Parameters[0]).Where(t => !selected.Any(s =>((object[])s)[0].ToString() == t.ToString())); Console.WriteLine("Missing values: {0}",unmatched.Dump()); var config = new object[] { 1, tempMessage.ID, selected }; response = DelugeRPC.DelugeProtocol.CompressAndEncode(config); handled = true; networkStream.WriteAsync(response, 0, response.Length); } /* Unimplemented command { ID: 5, Command: core.get_session_status, Parameters: [ [ payload_upload_rate, payload_download_rate ] ], NamedParameters: {} } */ if (tempMessage.Command == "core.get_session_status") { var responseList = new List<object>(); foreach (KeyValuePair<object, object> item in tempMessage.NamedParameters) { responseList.Add(new object[] {1337}); } var filter = new object[] { 1, tempMessage.ID, responseList.ToArray() }; response = DelugeRPC.DelugeProtocol.CompressAndEncode(filter); handled = true; networkStream.WriteAsync(response, 0, response.Length); } if (tempMessage.Command == "core.get_config") { //var firstPass = LoadCannedResponse("Responses\\core.get_config.json"); //JsonSerializer<Dictionary<string, string>> secondPassSerializer = // new JsonSerializer<Dictionary<string, string>>(); ////horrible horrible 3am hack to get *some* kind of config response working //var secondPass = // secondPassSerializer.DeserializeFromString(firstPass.ReturnValues[0].ToString()); //foreach (var item in secondPass) //{ // var firstHalf = item.Key.Split(':'); // var secondHalf = item.Value.Split(':'); // if (!item.Key.Contains("]")) // { // configItems.Add(new[] {firstHalf[0], firstHalf.Length > 1 ? firstHalf[1] : null}); // } // if (!item.Value.Contains("]")) // { // configItems.Add(new[] {secondHalf[0], secondHalf.Length > 1 ? secondHalf[1] : null}); // } //} //var values = cannned.ReturnValues[0].ToString().Split(','); var responseObject = new object[] { 1, tempMessage.ID, configItems }; Console.WriteLine("Loaded {0} config items", configItems.Length); response = DelugeRPC.DelugeProtocol.CompressAndEncode(responseObject); handled = true; networkStream.WriteAsync(response, 0, response.Length); } if (tempMessage.Command == "daemon.set_event_interest") { Console.WriteLine("Faking interest in the client"); var responseObject = new object[] { 1, tempMessage.ID, true }; response = DelugeRPC.DelugeProtocol.CompressAndEncode(responseObject); handled = true; networkStream.WriteAsync(response, 0, response.Length); } if (!handled) { Console.WriteLine("Canned response {0} not found!", tempMessage.Command); tempMessage.PrintDump(); } } } /* Unimplemented command { ID: 2, Command: core.get_config, Parameters: [], NamedParameters: {} } */ /* lol Unimplemented command { ID: 6, Command: core.get_enabled_plugins, Parameters: [], NamedParameters: {} } lol Unimplemented command { ID: 7, Command: core.get_torrents_status, Parameters: [ { }, [ ], True ], NamedParameters: {} } lol Unimplemented command { ID: 8, Command: core.get_config_values, Parameters: [ [ compact_allocation, max_connections_per_torrent, max_upload_slots_per_torrent, max_upload_speed_per_torrent, max_download_speed_per_torrent, prioritize_first_last_pieces, download_location, add_paused, move_completed, move_completed_path ] ], NamedParameters: {} } lol */ /* var responseObject = new object[] { 1, tempMessage.ID, responseArray.ReturnValues.ToArray() }; response = DelugeRPC.DelugeProtocol.CompressAndEncode(responseObject); networkStream.WriteAsync(response, 0, response.Length); */ } }
// Handle new connection private async Task HandleConnectionAsync(TcpClient tcpClient) { await Task.Yield(); // continue asynchronously on another threads using (var clientNetworkStream = new SslStream(tcpClient.GetStream())) { var clientBuffer = new byte[4096]; var serverBuffer = new byte[4096]; clientNetworkStream.AuthenticateAsServer(X509Certificate2.CreateFromCertFile( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "deluge.pfx"))); Console.WriteLine("[Relay] Set up SSL session with client"); while (true) { var serverBytes = await clientNetworkStream.ReadAsync(serverBuffer, 0, serverBuffer.Length); if (serverBytes > 0) { Console.WriteLine("Server replied {0}", DelugeRPC.DelugeProtocol.DecompressAndDecode(serverBuffer).Dump()); await clientNetworkStream.WriteAsync(serverBuffer, 0, serverBuffer.Length); } } } }