├── .gitattributes ├── .gitignore ├── LICENSE.txt ├── README.md └── source ├── TentaclePing.sln ├── TentaclePing ├── Program.cs └── TentaclePing.csproj └── TentaclePong ├── Program.cs └── TentaclePong.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # ========================= 18 | # Operating System Files 19 | # ========================= 20 | 21 | # OSX 22 | # ========================= 23 | 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must end with two \r 29 | Icon 30 | 31 | 32 | # Thumbnails 33 | ._* 34 | 35 | # Files that might appear on external disk 36 | .Spotlight-V100 37 | .Trashes 38 | 39 | # Directories potentially created on remote AFP share 40 | .AppleDB 41 | .AppleDesktop 42 | Network Trash Folder 43 | Temporary Items 44 | .apdisk 45 | ## Ignore Visual Studio temporary files, build results, and 46 | ## files generated by popular Visual Studio add-ons. 47 | 48 | # User-specific files 49 | *.suo 50 | *.user 51 | *.userosscache 52 | *.sln.docstates 53 | 54 | # Build results 55 | [Dd]ebug/ 56 | [Dd]ebugPublic/ 57 | [Rr]elease/ 58 | [Rr]eleases/ 59 | x64/ 60 | x86/ 61 | build/ 62 | bld/ 63 | [Bb]in/ 64 | [Oo]bj/ 65 | 66 | # Roslyn cache directories 67 | *.ide/ 68 | 69 | # MSTest test Results 70 | [Tt]est[Rr]esult*/ 71 | [Bb]uild[Ll]og.* 72 | 73 | #NUNIT 74 | *.VisualState.xml 75 | TestResult.xml 76 | 77 | # Build Results of an ATL Project 78 | [Dd]ebugPS/ 79 | [Rr]eleasePS/ 80 | dlldata.c 81 | 82 | *_i.c 83 | *_p.c 84 | *_i.h 85 | *.ilk 86 | *.meta 87 | *.obj 88 | *.pch 89 | *.pdb 90 | *.pgc 91 | *.pgd 92 | *.rsp 93 | *.sbr 94 | *.tlb 95 | *.tli 96 | *.tlh 97 | *.tmp 98 | *.tmp_proj 99 | *.log 100 | *.vspscc 101 | *.vssscc 102 | .builds 103 | *.pidb 104 | *.svclog 105 | *.scc 106 | 107 | # Chutzpah Test files 108 | _Chutzpah* 109 | 110 | # Visual C++ cache files 111 | ipch/ 112 | *.aps 113 | *.ncb 114 | *.opensdf 115 | *.sdf 116 | *.cachefile 117 | 118 | # Visual Studio profiler 119 | *.psess 120 | *.vsp 121 | *.vspx 122 | 123 | # TFS 2012 Local Workspace 124 | $tf/ 125 | 126 | # Guidance Automation Toolkit 127 | *.gpState 128 | 129 | # ReSharper is a .NET coding add-in 130 | _ReSharper*/ 131 | *.[Rr]e[Ss]harper 132 | *.DotSettings.user 133 | 134 | # JustCode is a .NET coding addin-in 135 | .JustCode 136 | 137 | # TeamCity is a build add-in 138 | _TeamCity* 139 | 140 | # DotCover is a Code Coverage Tool 141 | *.dotCover 142 | 143 | # NCrunch 144 | _NCrunch_* 145 | .*crunch*.local.xml 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # TODO: Comment the next line if you want to checkin your web deploy settings 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # NuGet Packages 179 | *.nupkg 180 | # The packages folder can be ignored because of Package Restore 181 | **/packages/* 182 | # except build/, which is used as an MSBuild target. 183 | !**/packages/build/ 184 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 185 | #!**/packages/repositories.config 186 | 187 | # Windows Azure Build Output 188 | csx/ 189 | *.build.csdef 190 | 191 | # Windows Store app package directory 192 | AppPackages/ 193 | 194 | # Others 195 | sql/ 196 | *.Cache 197 | ClientBin/ 198 | [Ss]tyle[Cc]op.* 199 | ~$* 200 | *~ 201 | *.dbmdl 202 | *.dbproj.schemaview 203 | *.pfx 204 | *.publishsettings 205 | node_modules/ 206 | 207 | # RIA/Silverlight projects 208 | Generated_Code/ 209 | 210 | # Backup & report files from converting an old project file 211 | # to a newer Visual Studio version. Backup files are not needed, 212 | # because we have git ;-) 213 | _UpgradeReport_Files/ 214 | Backup*/ 215 | UpgradeLog*.XML 216 | UpgradeLog*.htm 217 | 218 | # SQL Server files 219 | *.mdf 220 | *.ldf 221 | 222 | # Business Intelligence projects 223 | *.rdl.data 224 | *.bim.layout 225 | *.bim_*.settings 226 | 227 | # Microsoft Fakes 228 | FakesAssemblies/ 229 | *.lock 230 | *.ide 231 | *.ide-shm 232 | *.ide-wal 233 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Octopus Deploy and contributors. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TentaclePing is a command line tool that helps to diagnose troubled connections between an Octopus server and a listening Tentacle. 2 | 3 | [Download](https://github.com/OctopusDeploy/TentaclePing/releases) 4 | 5 | ## TentaclePing 6 | 7 | Unlike regular Ping, TentaclePing makes an SSL connection to the Tentacle service, meaning it will only work if the Tentacle service is running and responding. 8 | 9 | The command takes four arguments: 10 | 11 | TentaclePing [] [] [] [ {None|Ssl2|Ssl3|Tls|Tls11|Tls12|Default}] 12 | 13 | Examples: 14 | 15 | TentaclePing.exe MyServer # Uses default port (10933) 16 | TentaclePing.exe 10.0.0.1 10934 # Explicit port 17 | TentaclePing.exe 10.0.0.1 10933 0 2 Tls12 # Specified IP address, port, data size, chunk size, and SSL Protocol 18 | 19 | If you are experiencing slow deployments or package uploads with Octopus, you can use TentaclePing to determine whether there is a connectivity problem: 20 | 21 | 1. Download TentaclePing.zip and extract it on your Octopus server 22 | 2. Open a command prompt, and run TentaclePing as shown above 23 | 3. Let it run for a few hours. If it encounters failures, it will log them and count the number of failures 24 | 4. Send the results to the Octopus Deploy team 25 | 26 | ## TentaclePong 27 | 28 | Normally, TentaclePing is pointed at a listening Tentacle or Octopus Server polling endpoint. If you have run TentaclePing and determinied that you have issues with connections being dropped, the next step is to determine whether the problem is with the Tentacle/Octopus server, or just a network issue. TentaclePong is the server equivalent for TentaclePing, listening on a port and waiting for requests from TentaclePing. 29 | 30 | Usage: 31 | 32 | TentaclePong 10945 # On server 1, listen on a port 33 | TentaclePing YourServer 10945 # Server 2 will ping server 1 34 | TentaclePing YourServer 10945 100 # Server 2 will send 100Mb of data using default chunk size (2Mb) to server 1 35 | TentaclePing YourServer 10945 100 10 # Server 2 will send 100Mb of data using a chunk size of 10Mb to server 1 36 | 37 | 38 | If TentaclePing reports problems when pointed at a listening Tentacle/Octopus server, but there are no problems with TentaclePong, then the issue is most likely a bug or resource utilization problem on the Tentacle/Octopus server (e.g., high CPU usage, limited memory, etc.). 39 | 40 | However, if the connection problems persist with TentaclePong, then the problem is most likely down to a network issue. Unfortunately there's really not much the Octopus team can do to help with that. 41 | 42 | ## Capturing output 43 | 44 | If you don't plan to watch TentaclePing run, you may want to pipe the results to a text file: 45 | 46 | TentaclePing.exe MyServer 10933 > Output.txt 47 | 48 | This file can then easily be sent to the Octopus support team (support@octopusdeploy.com) for analysis. 49 | -------------------------------------------------------------------------------- /source/TentaclePing.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30110.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TentaclePing", "TentaclePing\TentaclePing.csproj", "{AC19705A-89FF-4520-A07C-06E00EB16A4E}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TentaclePong", "TentaclePong\TentaclePong.csproj", "{8073FE72-9C13-4D4D-B070-659E9727C9D3}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {AC19705A-89FF-4520-A07C-06E00EB16A4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {AC19705A-89FF-4520-A07C-06E00EB16A4E}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {AC19705A-89FF-4520-A07C-06E00EB16A4E}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {AC19705A-89FF-4520-A07C-06E00EB16A4E}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {8073FE72-9C13-4D4D-B070-659E9727C9D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {8073FE72-9C13-4D4D-B070-659E9727C9D3}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {8073FE72-9C13-4D4D-B070-659E9727C9D3}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {8073FE72-9C13-4D4D-B070-659E9727C9D3}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /source/TentaclePing/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Net.Security; 5 | using System.Net.Sockets; 6 | using System.Security.Authentication; 7 | using System.Security.Cryptography.X509Certificates; 8 | using System.Threading; 9 | 10 | namespace TentaclePing 11 | { 12 | static class Program 13 | { 14 | private static readonly TimeSpan sendReceiveTimeout = TimeSpan.FromMinutes(30); 15 | private static int chunkSizeInBytes; 16 | 17 | static int Main(string[] args) 18 | { 19 | if (args.Length >= 1 && args.Length <= 5) 20 | { 21 | var hostname = args[0]; 22 | var port = 10933; 23 | if (args.Length >= 2) 24 | { 25 | port = int.Parse(args[1]); 26 | } 27 | var dataSize = 0; 28 | if (args.Length >= 3) 29 | { 30 | dataSize = int.Parse(args[2]); 31 | } 32 | var chunkSize = 2; 33 | if (args.Length >= 4) 34 | { 35 | chunkSize = int.Parse(args[3]); 36 | } 37 | var sslProtocol = SslProtocols.Tls; 38 | if (args.Length == 5) 39 | { 40 | if (Enum.TryParse(args[4], out var parsedSslProtocol)) 41 | { 42 | sslProtocol = parsedSslProtocol; 43 | } 44 | } 45 | 46 | Console.WriteLine($"Using SSL Protocol: {sslProtocol}"); 47 | Console.WriteLine("Pinging " + hostname + " on port " + port + (dataSize == 0 ? "" : ", sending " + dataSize + "Mb of data in " + chunkSize + "Mb chunks")); 48 | chunkSizeInBytes = 1024*1024*chunkSize; 49 | return ExecutePing(hostname, port, dataSize, sslProtocol); 50 | } 51 | PrintUsage(); 52 | return 1; 53 | } 54 | 55 | private static void PrintUsage() 56 | { 57 | Console.WriteLine("TentaclePing.exe [] [] []"); 58 | } 59 | 60 | private static int ExecutePing(string hostname, int port, int dataSize, SslProtocols sslProtocol) 61 | { 62 | var failCount = 0; 63 | var successCount = 0; 64 | while (true) 65 | { 66 | var attempts = successCount + failCount; 67 | if (attempts > 0 && attempts % 10 == 0) 68 | { 69 | Console.ForegroundColor = ConsoleColor.Green; 70 | Console.Write("{0:n0}", successCount); 71 | Console.ResetColor(); 72 | Console.Write(" successful connections, "); 73 | Console.ForegroundColor = failCount == 0 ? ConsoleColor.White : ConsoleColor.Red; 74 | Console.Write("{0:n0}", failCount); 75 | Console.ResetColor(); 76 | Console.WriteLine(" failed connections. Hit Ctrl+C to quit any time."); 77 | } 78 | 79 | var start = Stopwatch.StartNew(); 80 | var connected = false; 81 | var sslEstablished = false; 82 | 83 | try 84 | { 85 | Console.ForegroundColor = ConsoleColor.Gray; 86 | Console.Write($"{DateTime.UtcNow:s} "); 87 | Console.Write("Connect: "); 88 | Console.ResetColor(); 89 | 90 | var bytesRead = 0; 91 | 92 | if (dataSize > 0) 93 | { 94 | var dataToBeSent = 1024*1024*dataSize; 95 | 96 | while (dataToBeSent > 0) 97 | { 98 | var data = new string('A', (dataToBeSent < chunkSizeInBytes ? dataToBeSent : chunkSizeInBytes)); 99 | SendRequest(hostname, port, sslProtocol, out bytesRead, out connected, out sslEstablished, data); 100 | dataToBeSent -= data.Length; 101 | } 102 | } 103 | else 104 | { 105 | SendRequest(hostname, port, sslProtocol, out bytesRead, out connected, out sslEstablished); 106 | } 107 | 108 | Console.ForegroundColor = ConsoleColor.Green; 109 | Console.WriteLine("Success! {0:n0}ms, {1:n0} bytes read", start.ElapsedMilliseconds, bytesRead); 110 | Console.ResetColor(); 111 | successCount++; 112 | } 113 | catch (Exception ex) 114 | { 115 | Console.ForegroundColor = ConsoleColor.Red; 116 | Console.WriteLine("Failed! {0:n0}ms; connected: {1}; SSL: {2}", start.ElapsedMilliseconds, connected, sslEstablished); 117 | Console.ResetColor(); 118 | Console.WriteLine(ex); 119 | failCount++; 120 | } 121 | 122 | Thread.Sleep(500); 123 | } 124 | } 125 | 126 | private static void SendRequest(string hostname, int port, SslProtocols sslProtocol, out int bytesRead, out bool connected, out bool sslEstablished, string data = null) 127 | { 128 | using (var client = new TcpClient()) 129 | { 130 | client.SendTimeout = (int) sendReceiveTimeout.TotalMilliseconds; 131 | client.ReceiveTimeout = (int) sendReceiveTimeout.TotalMilliseconds; 132 | client.Connect(hostname, port); 133 | 134 | using (var stream = client.GetStream()) 135 | { 136 | connected = true; 137 | 138 | using (var ssl = new SslStream(stream, false, CertificateValidator, LocalCertificateSelection)) 139 | { 140 | sslEstablished = true; 141 | 142 | ssl.AuthenticateAsClient(hostname, null, sslProtocol, false); 143 | 144 | var writer = new StreamWriter(ssl); 145 | writer.WriteLine("GET / HTTP/1.1"); 146 | writer.WriteLine("Host: " + hostname); 147 | writer.WriteLine(data); 148 | writer.WriteLine(); 149 | writer.Flush(); 150 | using (var reader = new StreamReader(ssl)) 151 | { 152 | bytesRead = reader.ReadToEnd().Length; 153 | } 154 | } 155 | } 156 | } 157 | } 158 | 159 | private static X509Certificate LocalCertificateSelection(object sender, string targethost, X509CertificateCollection localcertificates, X509Certificate remotecertificate, string[] acceptableissuers) 160 | { 161 | return null; 162 | } 163 | 164 | private static bool CertificateValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors) 165 | { 166 | return true; 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /source/TentaclePing/TentaclePing.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Tentacle ping - a tool to test connections with Octopus Tentacle. 4 | en-US 5 | 1.2.0 6 | Octopus Deploy 7 | TentaclePing 8 | TentaclePing 9 | false 10 | true 11 | netcoreapp3.1 12 | EXE 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /source/TentaclePong/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Net.Security; 6 | using System.Net.Sockets; 7 | using System.Security.Authentication; 8 | using System.Security.Cryptography.X509Certificates; 9 | 10 | namespace TentaclePong 11 | { 12 | class Program 13 | { 14 | static readonly X509Certificate2 serverCertificate = new X509Certificate2(Convert.FromBase64String("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"), (string)null); 15 | private static bool isStopped; 16 | private static TcpListener listener; 17 | private static string response = new string('A', 1024 * 10); 18 | 19 | static int Main(string[] args) 20 | { 21 | if (args.Length == 1) 22 | { 23 | var port = int.Parse(args[0]); 24 | 25 | Console.WriteLine("Listening on port " + port); 26 | 27 | return RunServer(port); 28 | } 29 | PrintUsage(); 30 | return 1; 31 | } 32 | 33 | private static void PrintUsage() 34 | { 35 | Console.WriteLine("TentaclePong.exe "); 36 | } 37 | 38 | private static int RunServer(int port) 39 | { 40 | listener = new TcpListener(new IPEndPoint(IPAddress.Any, port)); 41 | listener.Start(); 42 | 43 | Accept(); 44 | 45 | Console.WriteLine("Listening, hit to exit..."); 46 | Console.ReadLine(); 47 | isStopped = true; 48 | 49 | return 0; 50 | } 51 | 52 | static void Accept() 53 | { 54 | if (isStopped) 55 | { 56 | listener.Stop(); 57 | return; 58 | } 59 | 60 | listener.BeginAcceptTcpClient(r => 61 | { 62 | try 63 | { 64 | // Just a nicety - race still makes ObjectDisposedException possible 65 | if (isStopped) 66 | return; 67 | 68 | TcpClient client; 69 | try 70 | { 71 | client = listener.EndAcceptTcpClient(r); 72 | } 73 | finally 74 | { 75 | Accept(); 76 | } 77 | 78 | Console.WriteLine($"{DateTime.UtcNow:s} Accepted TCP client " + client.Client.RemoteEndPoint); 79 | ExecuteRequest(client); 80 | } 81 | catch (Exception ex) 82 | { 83 | Console.WriteLine("TCP client error: " + ex); 84 | } 85 | }, null); 86 | } 87 | 88 | static void ExecuteRequest(TcpClient client) 89 | { 90 | RemoteCertificateValidationCallback validate = (sender, clientCertificate, chain, sslPolicyErrors) => 91 | { 92 | return true; 93 | }; 94 | 95 | try 96 | { 97 | using (var stream = client.GetStream()) 98 | using (var ssl = new SslStream(stream, false, validate)) 99 | { 100 | // We don't actually validate the client, accepting anything; validation 101 | // status is reflected in validClientThumprint != null. 102 | ssl.AuthenticateAsServer(serverCertificate, true, SslProtocols.Tls, false); 103 | 104 | var reader = new StreamReader(ssl); 105 | 106 | string line; 107 | int bytesRead = 0; 108 | while (!string.IsNullOrEmpty((line = reader.ReadLine()))) 109 | { 110 | bytesRead += line.Length; 111 | } 112 | Console.WriteLine(bytesRead + " bytes read"); 113 | 114 | var writer = new StreamWriter(ssl); 115 | writer.WriteLine("HTTP/1.0 200 OK"); 116 | writer.WriteLine("Content-Length: " + response.Length); 117 | writer.WriteLine(); 118 | writer.WriteLine(response); 119 | writer.Flush(); 120 | ssl.Flush(); 121 | } 122 | } 123 | catch (AuthenticationException ex) 124 | { 125 | Console.WriteLine("Client failed authentication: " + ex); 126 | } 127 | catch (Exception ex) 128 | { 129 | Console.WriteLine("Unhandled error when processing request from client: " + ex); 130 | } 131 | finally 132 | { 133 | client.Close(); 134 | } 135 | } 136 | 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /source/TentaclePong/TentaclePong.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Tentacle Pong - a tool to test connections with Octopus Server. 4 | en-US 5 | 1.2.0 6 | Octopus Deploy 7 | TentaclePong 8 | TentaclePong 9 | false 10 | true 11 | netcoreapp3.1 12 | EXE 13 | 14 | 15 | 16 | 17 | --------------------------------------------------------------------------------