diff --git a/scripts/ping.ps1 b/scripts/ping.ps1 deleted file mode 100644 index 20c762410a..0000000000 --- a/scripts/ping.ps1 +++ /dev/null @@ -1,172 +0,0 @@ -<# - -.SYNOPSIS -This script runs quicping locally. - -.PARAMETER Config - Specifies the build configuration to use. - -.PARAMETER Arch - The CPU architecture to use. - -.PARAMETER Tls - The TLS library use. - -.PARAMETER KeepOutputOnSuccess - Don't discard console output or logs on success. - -.PARAMETER GenerateXmlResults - Generates an xml Test report for the run. - -.PARAMETER Debugger - Attaches the debugger to the process. - -.PARAMETER InitialBreak - Debugger starts broken into the process to allow setting breakpoints, etc. - -.PARAMETER LogProfile - The name of the profile to use for log collection. - -.PARAMETER Target - A target to connect to. - -.PARAMETER Listen - An address to listen on or * for wildcard. - -.PARAMETER Port - A UDP port to connect to. - -.PARAMETER Thumbprint - The hash or thumbprint of the certificate to use. - -.PARAMETER UnidirectionalStreams - The number of unidirectional streams to open. - -.PARAMETER PeerUnidirectionalStreams - The number of unidirectional streams the peer is allowed to open. - -#> - -param ( - [Parameter(Mandatory = $false)] - [ValidateSet("Debug", "Release")] - [string]$Config = "Debug", - - [Parameter(Mandatory = $false)] - [ValidateSet("x86", "x64", "arm", "arm64")] - [string]$Arch = "x64", - - [Parameter(Mandatory = $false)] - [ValidateSet("schannel", "openssl")] - [string]$Tls = "", - - [Parameter(Mandatory = $false)] - [switch]$KeepOutputOnSuccess = $false, - - [Parameter(Mandatory = $false)] - [switch]$GenerateXmlResults = $false, - - [Parameter(Mandatory = $false)] - [switch]$Debugger = $false, - - [Parameter(Mandatory = $false)] - [switch]$InitialBreak = $false, - - [Parameter(Mandatory = $false)] - [ValidateSet("None", "Basic.Light", "Basic.Verbose", "Full.Light", "Full.Verbose", "SpinQuic.Light")] - [string]$LogProfile = "None", - - [Parameter(Mandatory = $false)] - [string]$Target = "", - - [Parameter(Mandatory = $false)] - [string]$Listen = "", - - [Parameter(Mandatory = $false)] - [UInt16]$Port = 0, - - [Parameter(Mandatory = $false)] - [string]$Thumbprint = "", - - [Parameter(Mandatory = $false)] - [uint]$UnidirectionalStreams = 0, - - [Parameter(Mandatory = $false)] - [uint]$PeerUnidirectionalStreams = 0 -) - -Set-StrictMode -Version 'Latest' -$PSDefaultParameterValues['*:ErrorAction'] = 'Stop' - -# Default TLS based on current platform. -if ("" -eq $Tls) { - if ($IsWindows) { - $Tls = "schannel" - } else { - $Tls = "openssl" - } -} - -# Root directory of the project. -$RootDir = Split-Path $PSScriptRoot -Parent - -# Path to the run-executable Powershell script. -$RunExecutable = Join-Path $RootDir "scripts/run-executable.ps1" - -# Path to the quicping exectuable. -$QuicPing = $null -if ($IsWindows) { - $QuicPing = Join-Path $RootDir "\artifacts\bin\windows\$($Arch)_$($Config)_$($Tls)\quicping.exe" -} else { - $QuicPing = Join-Path $RootDir "/artifacts/bin/linux/$($Arch)_$($Config)_$($Tls)/quicping" -} - -# Make sure the build is present. -if (!(Test-Path $QuicPing)) { - Write-Error "Build does not exist!`n `nRun the following to generate it:`n `n $(Join-Path $RootDir "scripts" "build.ps1") -Config $Config -Arch $Arch -Tls $Tls`n" -} - -# Build up all the arguments to pass to the Powershell script. -$Arguments = "-Path $($QuicPing) -ShowOutput" -if ($KeepOutputOnSuccess) { - $Arguments += " -KeepOutputOnSuccess" -} -if ($GenerateXmlResults) { - $Arguments += " -GenerateXmlResults" -} -if ($Debugger) { - $Arguments += " -Debugger" -} -if ($InitialBreak) { - $Arguments += " -InitialBreak" -} -if ("None" -ne $LogProfile) { - $Arguments += " -LogProfile $($LogProfile)" -} - -$ExtraArgs = "" -if ($Target -ne "") { - $ExtraArgs += " -target:$Target" -} -if ($Listen -ne "") { - $ExtraArgs += " -listen:$Listen" -} -if ($Port -ne 0) { - $ExtraArgs += " -port:$Port" -} -if ($Thumbprint -ne "") { - $ExtraArgs += " -thumbprint:$Thumbprint" -} -if ($UnidirectionalStreams -ne 0) { - $ExtraArgs += " -uni:$UnidirectionalStreams" -} -if ($PeerUnidirectionalStreams -ne 0) { - $ExtraArgs += " -peer_uni:$PeerUnidirectionalStreams" -} - -if ($ExtraArgs -ne "") { - $Arguments += " -Arguments `"$ExtraArgs`"" -} - -# Run the script. -Invoke-Expression ($RunExecutable + " " + $Arguments) diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index b7cd438181..f0219790f6 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -20,7 +20,6 @@ add_subdirectory(interopserver) add_subdirectory(ip/client) add_subdirectory(ip/server) add_subdirectory(pcp) -add_subdirectory(ping) add_subdirectory(post) add_subdirectory(reach) add_subdirectory(sample) diff --git a/src/tools/ping/CMakeLists.txt b/src/tools/ping/CMakeLists.txt deleted file mode 100644 index ea9da425e5..0000000000 --- a/src/tools/ping/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -set(SOURCES - Client.cpp - PingConnection.cpp - PingStream.cpp - QuicPing.cpp - Server.cpp -) - -add_quic_tool(quicping ${SOURCES}) diff --git a/src/tools/ping/Client.cpp b/src/tools/ping/Client.cpp deleted file mode 100644 index 7d0895aa86..0000000000 --- a/src/tools/ping/Client.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - -Abstract: - - QUIC PING Client Implementation. Supports connecting to a remote QUIC - endpoint and sending a variable length payload of semi-random data. It - then waits for the remote to acknowledge the data via closing the stream. - The remote may or may not echo the payload. - ---*/ - -#include "QuicPing.h" - -struct QuicConfigurationPtr { - HQUIC Handle {nullptr}; - ~QuicConfigurationPtr() { MsQuic->ConfigurationClose(Handle); } -}; - -void QuicPingClientRun() -{ - PingTracker Tracker; - bool Timeout = true; - { - QUIC_SETTINGS Settings{0}; - Settings.IdleTimeoutMs = PingConfig.IdleTimeout; - Settings.IsSet.IdleTimeoutMs = TRUE; - Settings.DisconnectTimeoutMs = PingConfig.DisconnectTimeout; - Settings.IsSet.DisconnectTimeoutMs = TRUE; - Settings.DatagramReceiveEnabled = TRUE; - Settings.IsSet.DatagramReceiveEnabled = TRUE; - if (!PingConfig.UseSendBuffer) { - Settings.SendBufferingEnabled = FALSE; - Settings.IsSet.SendBufferingEnabled = TRUE; - } - if (!PingConfig.UsePacing) { - Settings.PacingEnabled = FALSE; - Settings.IsSet.PacingEnabled = TRUE; - } - if (PingConfig.MaxBytesPerKey != UINT64_MAX) { - Settings.MaxBytesPerKey = PingConfig.MaxBytesPerKey; - Settings.IsSet.MaxBytesPerKey = TRUE; - } - if (PingConfig.PeerBidirStreamCount != 0) { - Settings.PeerBidiStreamCount = PingConfig.PeerBidirStreamCount; - Settings.IsSet.PeerBidiStreamCount = TRUE; - } - if (PingConfig.PeerUnidirStreamCount != 0) { - Settings.PeerUnidiStreamCount = PingConfig.PeerUnidirStreamCount; - Settings.IsSet.PeerUnidiStreamCount = TRUE; - } - - QuicConfigurationPtr ClientConfiguration; - if (QUIC_FAILED( - MsQuic->ConfigurationOpen( - Registration, - &PingConfig.ALPN, - 1, - &Settings, - sizeof(Settings), - nullptr, - &ClientConfiguration.Handle))) { - printf("MsQuic->ConfigurationOpen failed!\n"); - return; - } - - QUIC_CREDENTIAL_CONFIG CredConfig; - CxPlatZeroMemory(&CredConfig, sizeof(CredConfig)); - CredConfig.Type = QUIC_CREDENTIAL_TYPE_NONE; - CredConfig.Flags = QUIC_CREDENTIAL_FLAG_CLIENT | QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION; - if (QUIC_FAILED( - MsQuic->ConfigurationLoadCredential( - ClientConfiguration.Handle, - &CredConfig))) { - printf("MsQuic->ConfigurationLoadCredential failed!\n"); - return; - } - - auto Connections = new PingConnection*[PingConfig.ConnectionCount]; - for (uint32_t i = 0; i < PingConfig.ConnectionCount; i++) { - Connections[i] = - new PingConnection( - &Tracker, - PingConfig.ConnectionCount == 1); - if (!Connections[i]) { - printf("Failed to open a connection!\n"); - return; - } - - if (!Connections[i]->Initialize(false)) { - return; - } - } - - Tracker.Start(); - - // - // Start connecting to the remote server. - // - for (uint32_t i = 0; i < PingConfig.ConnectionCount; i++) { - Connections[i]->Connect(ClientConfiguration.Handle); - } - - delete[] Connections; - - if (Tracker.Wait(PingConfig.Client.WaitTimeout)) { - printf("Cancelling remaining connections.\n"); - MsQuic->RegistrationShutdown(Registration, QUIC_CONNECTION_SHUTDOWN_FLAG_NONE, 0); - Timeout = false; // Connections didn't hit idle timeout. They were cancelled. - } - } - - if (PingConfig.ConnectionCount > 1 && - (Tracker.BytesSent != 0 || Tracker.BytesReceived != 0)) { - uint64_t ElapsedMicroseconds = Tracker.CompleteTime - Tracker.StartTime; - if (Timeout) { - ElapsedMicroseconds -= DEFAULT_IDLE_TIMEOUT * 1000; - } - - uint32_t SendRate = (uint32_t)((Tracker.BytesSent * 1000 * 1000 * 8) / (1000 * ElapsedMicroseconds)); - uint32_t RecvRate = (uint32_t)((Tracker.BytesReceived * 1000 * 1000 * 8) / (1000 * ElapsedMicroseconds)); - - printf("Total rate after %u.%u ms. (TX %llu bytes @ %u kbps | RX %llu bytes @ %u kbps).\n", - (uint32_t)(ElapsedMicroseconds / 1000), - (uint32_t)(ElapsedMicroseconds % 1000), - (unsigned long long)Tracker.BytesSent, SendRate, - (unsigned long long)Tracker.BytesReceived, RecvRate); - } -} diff --git a/src/tools/ping/PingConnection.cpp b/src/tools/ping/PingConnection.cpp deleted file mode 100644 index 3392324c42..0000000000 --- a/src/tools/ping/PingConnection.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - -Abstract: - - QUIC PING Connection Implementation. - ---*/ - -#include "QuicPing.h" - -PingConnection::PingConnection( - _In_ PingTracker* Tracker, - _In_ bool DumpResumption - ) : - Tracker(Tracker), QuicConnection(nullptr), DumpResumption(DumpResumption), - IsServer(false), ConnectedSuccessfully(false), TimedOut(false), - BytesSent(0), BytesReceived(0), DatagramLength(0), DatagramsSent(0), - DatagramsAcked(0), DatagramsLost(0), DatagramsCancelled(0), - DatagramsReceived(0), DatagramsJitterTotal(0), DatagramLastTime(0) { - - if (QUIC_FAILED( - MsQuic->ConnectionOpen( - Registration, - QuicCallbackHandler, - this, - &QuicConnection))) { - printf("Failed to open connection!\n"); - } -} - -PingConnection::PingConnection( - _In_ PingTracker* Tracker, - _In_ HQUIC Connection - ) : - Tracker(Tracker), QuicConnection(Connection), DumpResumption(false), - ConnectedSuccessfully(false), TimedOut(false), BytesSent(0), - BytesReceived(0), DatagramLength(0), DatagramsSent(0), DatagramsAcked(0), - DatagramsLost(0), DatagramsCancelled(0), DatagramsReceived(0), - DatagramsJitterTotal(0), DatagramLastTime(0) { - - StartTime = CxPlatTimeUs64(); - MsQuic->SetCallbackHandler(Connection, (void*)QuicCallbackHandler, this); -} - -PingConnection::~PingConnection() { - if (QuicConnection != nullptr) { - MsQuic->ConnectionClose(QuicConnection); - } -} - -bool -PingConnection::Initialize( - bool isServer - ) -{ - this->IsServer = isServer; - - if (!IsServer) { - /*if (PingConfig.Client.ResumeToken && - !SetResumptionState( - MsQuic, - QuicConnection, - PingConfig.Client.ResumeToken)) { - printf("Failed to set the resumption token!\n"); - return false; - }*/ - QUIC_SETTINGS Settings = { 0 }; - Settings.IsSet.DesiredVersionsList = TRUE; - Settings.DesiredVersionsList = &PingConfig.Client.Version; - Settings.DesiredVersionsListLength = 1; - - if (PingConfig.Client.Version && - QUIC_FAILED( - MsQuic->SetParam( - QuicConnection, - QUIC_PARAM_LEVEL_CONNECTION, - QUIC_PARAM_CONN_SETTINGS, - sizeof(Settings), - &Settings))) { - printf("Failed to set the version!\n"); - return false; - } - } - - if (IsServer || !PingConfig.UseEncryption) { - BOOLEAN value = TRUE; - if (QUIC_FAILED( - MsQuic->SetParam( - QuicConnection, - QUIC_PARAM_LEVEL_CONNECTION, - QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION, - sizeof(value), - &value)) && - !IsServer) { - printf("MsQuic->SetParam (CONN_DISABLE_1RTT_ENCRYPTION) failed!\n"); - } - } - - for (uint64_t i = 0; i < PingConfig.LocalBidirStreamCount; i++) { - auto Stream = new PingStream(this, BidiSendMode); - if (!Stream || !Stream->Start()) { - delete Stream; - return false; - } - } - for (uint64_t i = 0; i < PingConfig.LocalUnidirStreamCount; i++) { - auto Stream = new PingStream(this, UniSendMode); - if (!Stream || !Stream->Start()) { - delete Stream; - return false; - } - } - - while (DatagramsSent < PingConfig.LocalDatagramCount) { - auto SendRequest = new PingSendRequest(); - SendRequest->SetLength(DatagramLength); - if (!QueueDatagram(SendRequest)) { - delete SendRequest; - return false; - } - } - - return true; -} - -bool -PingConnection::QueueDatagram( - PingSendRequest* SendRequest - ) -{ - BytesSent += SendRequest->QuicBuffer.Length; - DatagramsSent++; - - return - QUIC_SUCCEEDED( - MsQuic->DatagramSend( - QuicConnection, - &SendRequest->QuicBuffer, - 1, - SendRequest->Flags, - SendRequest)); -} - -bool -PingConnection::Connect(_In_ HQUIC ClientConfiguration) { - if (QuicAddrGetFamily(&PingConfig.LocalIpAddr) != QUIC_ADDRESS_FAMILY_UNSPEC) { - MsQuic->SetParam( - QuicConnection, - QUIC_PARAM_LEVEL_CONNECTION, - QUIC_PARAM_CONN_LOCAL_ADDRESS, - sizeof(PingConfig.LocalIpAddr), - &PingConfig.LocalIpAddr); - } - - if (PingConfig.Client.UseExplicitRemoteAddr) { - MsQuic->SetParam( - QuicConnection, - QUIC_PARAM_LEVEL_CONNECTION, - QUIC_PARAM_CONN_REMOTE_ADDRESS, - sizeof(PingConfig.Client.RemoteIpAddr), - &PingConfig.Client.RemoteIpAddr); - } - - Tracker->AddItem(); - StartTime = CxPlatTimeUs64(); - if (QUIC_FAILED( - MsQuic->ConnectionStart( - QuicConnection, - ClientConfiguration, - QuicAddrGetFamily(&PingConfig.Client.RemoteIpAddr), - PingConfig.Client.Target, - QuicAddrGetPort(&PingConfig.Client.RemoteIpAddr)))) { - Tracker->CompleteItem(0, 0); - return false; - } - - return true; -} - -void -PingConnection::OnPingStreamShutdownComplete( - _In_ PingStream *Stream - ) { - - BytesSent += Stream->BytesCompleted; - BytesReceived += Stream->BytesReceived; -} - -void -PingConnection::ProcessEvent( - _Inout_ QUIC_CONNECTION_EVENT* Event - ) { - switch (Event->Type) { - case QUIC_CONNECTION_EVENT_CONNECTED: { - ConnectedSuccessfully = true; - ConnectTime = CxPlatTimeUs64(); - - uint64_t ElapsedMicroseconds = ConnectTime - StartTime; - - printf("[%p] Connected in %u.%03u milliseconds.\n", - QuicConnection, - (uint32_t)(ElapsedMicroseconds / 1000), - (uint32_t)(ElapsedMicroseconds % 1000)); - - if (this->IsServer) { - if (QUIC_FAILED( - MsQuic->ConnectionSendResumptionTicket(QuicConnection, QUIC_SEND_RESUMPTION_FLAG_FINAL, 0, nullptr))) { - printf("[%p] Failed to send 0-RTT resumption ticket!\n", QuicConnection); - } - } - break; - } - - case QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_TRANSPORT: { - if (!ConnectedSuccessfully) { - ConnectTime = CxPlatTimeUs64(); - - uint64_t ElapsedMicroseconds = ConnectTime - StartTime; - - printf("[%p] Failed to connect: %s (0x%x) in %u.%03u milliseconds.\n", - QuicConnection, - QuicStatusToString(Event->SHUTDOWN_INITIATED_BY_TRANSPORT.Status), - Event->SHUTDOWN_INITIATED_BY_TRANSPORT.Status, - (uint32_t)(ElapsedMicroseconds / 1000), - (uint32_t)(ElapsedMicroseconds % 1000)); - } else { - if (Event->SHUTDOWN_INITIATED_BY_TRANSPORT.Status != QUIC_STATUS_SUCCESS && - Event->SHUTDOWN_INITIATED_BY_TRANSPORT.Status != QUIC_STATUS_CONNECTION_IDLE) { - printf("[%p] Closed with error: %s (0x%x).\n", - QuicConnection, - QuicStatusToString(Event->SHUTDOWN_INITIATED_BY_TRANSPORT.Status), - Event->SHUTDOWN_INITIATED_BY_TRANSPORT.Status); - } else if (Event->SHUTDOWN_INITIATED_BY_TRANSPORT.Status == QUIC_STATUS_CONNECTION_IDLE) { - TimedOut = true; - } - } - break; - } - - case QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_PEER: { - if (!ConnectedSuccessfully) { - ConnectTime = CxPlatTimeUs64(); - - uint64_t ElapsedMicroseconds = ConnectTime - StartTime; - - printf("[%p] Failed to connect: 0x%llx in %u.%03u milliseconds.\n", - QuicConnection, - (unsigned long long)Event->SHUTDOWN_INITIATED_BY_PEER.ErrorCode, - (uint32_t)(ElapsedMicroseconds / 1000), - (uint32_t)(ElapsedMicroseconds % 1000)); - } else { - printf("[%p] App Closed with error: 0x%llx.\n", - QuicConnection, - (unsigned long long)Event->SHUTDOWN_INITIATED_BY_PEER.ErrorCode); - } - break; - } - - case QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE: { - CompleteTime = CxPlatTimeUs64(); - - if (ConnectedSuccessfully && !Event->SHUTDOWN_COMPLETE.PeerAcknowledgedShutdown) { - printf("[%p] Shutdown timed out.\n", QuicConnection); - } - - if (BytesSent != 0 || BytesReceived != 0) { - uint64_t ElapsedMicroseconds = CompleteTime - StartTime; - if (TimedOut) { - ElapsedMicroseconds -= DEFAULT_IDLE_TIMEOUT * 1000; - } - - uint32_t SendRate = (uint32_t)((BytesSent * 1000 * 1000 * 8) / (1000 * ElapsedMicroseconds)); - uint32_t RecvRate = (uint32_t)((BytesReceived * 1000 * 1000 * 8) / (1000 * ElapsedMicroseconds)); - - printf("[%p] Total rate after %u.%03u ms. (TX %llu bytes @ %u kbps | RX %llu bytes @ %u kbps).\n", - QuicConnection, - (uint32_t)(ElapsedMicroseconds / 1000), - (uint32_t)(ElapsedMicroseconds % 1000), - (unsigned long long)BytesSent, SendRate, - (unsigned long long)BytesReceived, RecvRate); - - if (DatagramsReceived != 0) { - uint64_t Jitter = DatagramsJitterTotal / (DatagramsReceived - 1); - printf("[%p] Datagrams: %llu recv | %u.%03u ms jitter\n", - QuicConnection, - (unsigned long long)DatagramsReceived, - (uint32_t)(Jitter / 1000), - (uint32_t)(Jitter % 1000)); - } else if (DatagramsSent != 0) { - printf("[%p] Datagrams: %llu sent | %llu acked | %llu lost | %llu cancelled\n", - QuicConnection, - (unsigned long long)DatagramsSent, - (unsigned long long)DatagramsAcked, - (unsigned long long)DatagramsLost, - (unsigned long long)DatagramsCancelled); - } - } - - if (Tracker != nullptr) { - Tracker->CompleteItem(BytesSent, BytesReceived); - } - - if (DumpResumption && ConnectedSuccessfully) { - uint8_t SerializedResumptionState[2048]; - uint32_t SerializedResumptionStateLength = sizeof(SerializedResumptionState); - if (QUIC_SUCCEEDED( - MsQuic->GetParam( - QuicConnection, - QUIC_PARAM_LEVEL_CONNECTION, - QUIC_PARAM_CONN_RESUMPTION_TICKET, - &SerializedResumptionStateLength, - SerializedResumptionState))) { - printf("[%p] Resumption state (%u bytes):\n", QuicConnection, SerializedResumptionStateLength); - for (uint32_t i = 0; i < SerializedResumptionStateLength; i++) { - printf("%.2X", (uint8_t)SerializedResumptionState[i]); - } - printf("\n"); - } - } - - if (PingConfig.PrintStats) { - QUIC_STATISTICS Stats; - uint32_t StatsLength = sizeof(Stats); - MsQuic->GetParam( - QuicConnection, - QUIC_PARAM_LEVEL_CONNECTION, - QUIC_PARAM_CONN_STATISTICS, - &StatsLength, - &Stats); - printf("[%p] Transport Statistics:\n", QuicConnection); - printf("[%p] Correlation Id: %llu\n", QuicConnection, (unsigned long long)Stats.CorrelationId); - printf("[%p] RTT: %u us (min:%u max:%u)\n", QuicConnection, Stats.Rtt, Stats.MinRtt, Stats.MaxRtt); - printf("[%p] Send:\n", QuicConnection); - printf("[%p] PMTU: %hu bytes\n", QuicConnection, Stats.Send.PathMtu); - printf("[%p] Total Packets: %llu\n", QuicConnection, (unsigned long long)Stats.Send.TotalPackets); - printf("[%p] Lost Packets: %llu\n", QuicConnection, (unsigned long long)(Stats.Send.SuspectedLostPackets - Stats.Send.SpuriousLostPackets)); - printf("[%p] Spurious Packets: %llu\n", QuicConnection, (unsigned long long)Stats.Send.SpuriousLostPackets); - printf("[%p] Total Bytes: %llu\n", QuicConnection, (unsigned long long)Stats.Send.TotalBytes); - printf("[%p] Stream Bytes: %llu\n", QuicConnection, (unsigned long long)Stats.Send.TotalStreamBytes); - printf("[%p] Congestion Events: %u\n", QuicConnection, Stats.Send.CongestionCount); - printf("[%p] Pers Congestion Events: %u\n", QuicConnection, Stats.Send.PersistentCongestionCount); - printf("[%p] Recv:\n", QuicConnection); - printf("[%p] Total Packets: %llu\n", QuicConnection, (unsigned long long)Stats.Recv.TotalPackets); - printf("[%p] Reordered Packets: %llu\n", QuicConnection, (unsigned long long)Stats.Recv.ReorderedPackets); - printf("[%p] Dropped Packets: %llu\n", QuicConnection, (unsigned long long)Stats.Recv.DroppedPackets); - printf("[%p] Decryption Failures: %llu\n", QuicConnection, (unsigned long long)Stats.Recv.DecryptionFailures); - printf("[%p] Total Bytes: %llu\n", QuicConnection, (unsigned long long)Stats.Recv.TotalBytes); - printf("[%p] Stream Bytes: %llu\n", QuicConnection, (unsigned long long)Stats.Recv.TotalStreamBytes); - printf("[%p] Misc:\n", QuicConnection); - printf("[%p] Key Updates: %u\n", QuicConnection, Stats.Misc.KeyUpdateCount); - } - - delete this; - break; - } - - case QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED: { - new PingStream( - this, - Event->PEER_STREAM_STARTED.Stream, - (Event->PEER_STREAM_STARTED.Flags & QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL) ? UniRecvMode : BidiEchoMode); - break; - } - - case QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED: { - DatagramLength = - min(PingConfig.DatagramMaxLength, Event->DATAGRAM_STATE_CHANGED.MaxSendLength); - //printf("[%p] New Datagram Length = %hu\n", QuicConnection, DatagramLength); - break; - } - - case QUIC_CONNECTION_EVENT_DATAGRAM_RECEIVED: { - BytesReceived += Event->DATAGRAM_RECEIVED.Buffer->Length; - DatagramsReceived++; - uint64_t RecvTime = CxPlatTimeUs64(); - if (DatagramLastTime != 0) { - DatagramsJitterTotal += RecvTime - DatagramLastTime; - } - DatagramLastTime = RecvTime; - break; - } - - case QUIC_CONNECTION_EVENT_DATAGRAM_SEND_STATE_CHANGED: { - auto SendRequest = (PingSendRequest*)Event->DATAGRAM_SEND_STATE_CHANGED.ClientContext; - Event->DATAGRAM_SEND_STATE_CHANGED.ClientContext = nullptr; - - switch (Event->DATAGRAM_SEND_STATE_CHANGED.State) { - case QUIC_DATAGRAM_SEND_SENT: - if (DatagramsSent != PingConfig.LocalDatagramCount) { - SendRequest->SetLength(DatagramLength); - if (!QueueDatagram(SendRequest)) { - SendRequest = nullptr; - } - } - break; - case QUIC_DATAGRAM_SEND_LOST_DISCARDED: - DatagramsLost++; - break; - case QUIC_DATAGRAM_SEND_ACKNOWLEDGED: - case QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS: - DatagramsAcked++; - break; - case QUIC_DATAGRAM_SEND_CANCELED: - DatagramsCancelled++; - break; - default: - break; - } - - delete SendRequest; - break; - } - - default: - break; - } -} - -QUIC_STATUS -QUIC_API -PingConnection::QuicCallbackHandler( - _In_ HQUIC /* Connection */, - _In_opt_ void* Context, - _Inout_ QUIC_CONNECTION_EVENT* Event - ) { - PingConnection *pThis = (PingConnection*)Context; - pThis->ProcessEvent(Event); - return QUIC_STATUS_SUCCESS; -} diff --git a/src/tools/ping/PingConnection.h b/src/tools/ping/PingConnection.h deleted file mode 100644 index 73b78536d3..0000000000 --- a/src/tools/ping/PingConnection.h +++ /dev/null @@ -1,167 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - -Abstract: - - QUIC Ping Connection declaration. Defines the functions and variables used - in the PingConnection class. - ---*/ - -struct PingTracker { - - long RefCount; - - uint64_t BytesSent; - uint64_t BytesReceived; - - uint64_t StartTime; - uint64_t CompleteTime; - - CXPLAT_EVENT Done; - - PingTracker() : - RefCount(1), BytesSent(0), BytesReceived(0), StartTime(0), CompleteTime(0) { - CxPlatEventInitialize(&Done, FALSE, FALSE); - } - - ~PingTracker() { - CxPlatEventUninitialize(Done); - } - - void - Start() { - StartTime = CxPlatTimeUs64(); - } - - bool - Wait( - uint32_t Milliseconds - ) { - if (InterlockedDecrement(&RefCount) == 0) { - CompleteTime = CxPlatTimeUs64(); - return true; - } else { - return !CxPlatEventWaitWithTimeout(Done, Milliseconds); - } - } - - void - WaitForever( - ) { - if (InterlockedDecrement(&RefCount) == 0) { - CompleteTime = CxPlatTimeUs64(); - return; - } else { - CxPlatEventWaitForever(Done); - } - } - - void - AddItem() { - InterlockedIncrement(&RefCount); - } - - void - CompleteItem( - uint64_t Sent, - uint64_t Received - ) { - InterlockedExchangeAdd64((int64_t*)&BytesSent, (int64_t)Sent); - InterlockedExchangeAdd64((int64_t*)&BytesReceived, (int64_t)Received); - if (InterlockedDecrement(&RefCount) == 0) { - CompleteTime = CxPlatTimeUs64(); - CxPlatEventSet(Done); - } - } -}; - -struct PingConnection { - - PingTracker* Tracker; - HQUIC QuicConnection; - bool DumpResumption; - bool IsServer; - - uint64_t StartTime; - uint64_t ConnectTime; - uint64_t CompleteTime; - bool ConnectedSuccessfully; - bool TimedOut; - - uint64_t BytesSent; - uint64_t BytesReceived; - - uint16_t DatagramLength; - - uint64_t DatagramsSent; - uint64_t DatagramsAcked; - uint64_t DatagramsLost; - uint64_t DatagramsCancelled; - - uint64_t DatagramsReceived; - uint64_t DatagramsJitterTotal; - uint64_t DatagramLastTime; - - // - // Constructor for creating a new connection. - // - PingConnection( - _In_ PingTracker* Tracker, - _In_ bool DumpResumption - ); - - // - // Constructor for incoming connection with tracker. - // - PingConnection( - _In_ PingTracker* Tracker, - _In_ HQUIC Connection - ); - - // - // Destructor. Closes the associated connection. - // - ~PingConnection(); - - // - // Initializes all the QUIC parameters on the connection. - // - bool Initialize(bool IsServer); - - // - // Starts the connection handshake to the server. - // - bool Connect(_In_ HQUIC ClientConfiguration); - - // - // Called by the child stream when it's done cleaning up. - // - void - OnPingStreamShutdownComplete( - _In_ PingStream *Stream - ); - -private: - - bool - QueueDatagram( - PingSendRequest* SendRequest - ); - - void - ProcessEvent( - _Inout_ QUIC_CONNECTION_EVENT* Event - ); - - static - QUIC_STATUS - QUIC_API - QuicCallbackHandler( - _In_ HQUIC Connection, - _In_opt_ void* Context, - _Inout_ QUIC_CONNECTION_EVENT* Event - ); -}; diff --git a/src/tools/ping/PingStream.cpp b/src/tools/ping/PingStream.cpp deleted file mode 100644 index 4f0b793384..0000000000 --- a/src/tools/ping/PingStream.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - -Abstract: - - QUIC PING Client Implementation. Supports connecting to a remote QUIC - endpoint and sending a variable length payload of semi-random data. It - then waits for the remote to acknowledge the data via closing the stream. - The remote may or may not echo the payload. - ---*/ - -#include "QuicPing.h" - -uint8_t* QuicPingRawIoBuffer = nullptr; - -PingStream::PingStream( - _In_ PingConnection *connection, - _In_ PingStreamMode mode - ) : - Connection(connection), QuicStream(nullptr), - Mode(mode), Aborted(false), - BytesSent(0), BytesCompleted(0), BytesReceived(0) { -} - -// -// Constructor for incoming stream. -// -PingStream::PingStream( - _In_ PingConnection *connection, - _In_ HQUIC stream, - _In_ PingStreamMode mode - ) : - Connection(connection), QuicStream(stream), - Mode(mode), Aborted(false), - BytesSent(0), BytesCompleted(0), BytesReceived(0) { - StartTime = CxPlatTimeUs64(); - MsQuic->SetCallbackHandler(QuicStream, (void*)QuicCallbackHandler, this); - - printf("[%p][%llu] Opened.\n", Connection->QuicConnection, (unsigned long long)GetStreamID(MsQuic, QuicStream)); -} - -PingStream::~PingStream() { - if (QuicStream) { - MsQuic->StreamClose(QuicStream); - } -} - -bool -PingStream::Start( - ) { - StartTime = CxPlatTimeUs64(); - QUIC_STREAM_OPEN_FLAGS OpenFlags = QUIC_STREAM_OPEN_FLAG_NONE; - if (Mode == UniSendMode) { - OpenFlags = QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL; - } - if (QUIC_SUCCEEDED(MsQuic->StreamOpen(Connection->QuicConnection, OpenFlags, QuicCallbackHandler, this, &QuicStream)) && - QUIC_SUCCEEDED(MsQuic->StreamStart(QuicStream, QUIC_STREAM_START_FLAG_NONE))) { - printf("[%p][%llu] Opened.\n", Connection->QuicConnection, (unsigned long long)GetStreamID(MsQuic, QuicStream)); - return StartSend(); - } else { - return false; - } -} - -bool -PingStream::QueueSendRequest( - PingSendRequest* SendRequest - ) -{ - return - QUIC_SUCCEEDED( - MsQuic->StreamSend( - QuicStream, - &SendRequest->QuicBuffer, - 1, - SendRequest->Flags, - SendRequest)); -} - -bool -PingStream::StartSend( - ) { - if (PingConfig.StreamPayloadLength == 0) { - MsQuic->StreamShutdown(QuicStream, QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL, 0); - return true; - } - - uint32_t SendRequestsCount = 0; - while (BytesSent < PingConfig.StreamPayloadLength && SendRequestsCount < PingConfig.IoCount) { - auto SendRequest = new PingSendRequest(); - SendRequest->SetLength(PingConfig.StreamPayloadLength - BytesSent); - BytesSent += SendRequest->QuicBuffer.Length; - SendRequestsCount++; - if (!QueueSendRequest(SendRequest)) { - delete SendRequest; - return false; - } - } - - return true; -} - -void -PingStream::ProcessEvent( - _Inout_ QUIC_STREAM_EVENT* Event - ) { - switch (Event->Type) { - case QUIC_STREAM_EVENT_RECEIVE: - BytesReceived += Event->RECEIVE.TotalBufferLength; - if (Mode == BidiEchoMode) { - for (uint32_t i = 0; i < Event->RECEIVE.BufferCount; ++i) { - const QUIC_BUFFER* Buffer = &Event->RECEIVE.Buffers[i]; - auto SendRequest = new PingSendRequest(Buffer->Buffer, Buffer->Length); - BytesSent += Buffer->Length; - - if (!QueueSendRequest(SendRequest)) { - delete SendRequest; - MsQuic->StreamShutdown( - QuicStream, - QUIC_STREAM_SHUTDOWN_FLAG_ABORT_SEND, - 1); - break; - } - } - } - break; - - case QUIC_STREAM_EVENT_SEND_COMPLETE: { - auto SendRequest = (PingSendRequest*)Event->SEND_COMPLETE.ClientContext; - if (!Event->SEND_COMPLETE.Canceled) { - BytesCompleted += SendRequest->QuicBuffer.Length; - if (Mode == BidiSendMode || Mode == UniSendMode) { - // - // In Bidi or Uni Send mode, we continue to send data until we - // have sent the correct number of bytes. - // - auto BytesLeftToSend = PingConfig.StreamPayloadLength - BytesSent; - if (BytesLeftToSend != 0) { - SendRequest->SetLength(BytesLeftToSend); - BytesSent += SendRequest->QuicBuffer.Length; - if (QueueSendRequest(SendRequest)) { - SendRequest = nullptr; - } - } - } - } - delete SendRequest; - break; - } - - case QUIC_STREAM_EVENT_PEER_SEND_SHUTDOWN: - if (Mode == BidiEchoMode) { - // - // In Bidi Echo mode, we shutdown our send path once the remote - // shutdowns their send path. - // - MsQuic->StreamShutdown( - QuicStream, - QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL, - 0); - } - break; - - case QUIC_STREAM_EVENT_PEER_SEND_ABORTED: - case QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED: - Aborted = true; - MsQuic->StreamShutdown( - QuicStream, - QUIC_STREAM_SHUTDOWN_FLAG_ABORT_SEND | QUIC_STREAM_SHUTDOWN_FLAG_ABORT_RECEIVE, - 0); - break; - - case QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE: { - CompleteTime = CxPlatTimeUs64(); - - bool Completed = false; - switch (Mode) { - case UniSendMode: - Completed = BytesCompleted == PingConfig.StreamPayloadLength; - break; - case UniRecvMode: - Completed = true; - break; - case BidiSendMode: - Completed = - BytesCompleted == PingConfig.StreamPayloadLength && - BytesReceived == PingConfig.StreamPayloadLength; - break; - case BidiEchoMode: - Completed = BytesCompleted == BytesReceived; - break; - } - - Completed &= !Aborted; - - uint64_t ElapsedMicroseconds = CompleteTime - StartTime; - - if (BytesCompleted != 0 || BytesReceived != 0) { - - uint32_t SendRate = (uint32_t)((BytesCompleted * 1000 * 1000 * 8) / (1000 * ElapsedMicroseconds)); - uint32_t RecvRate = (uint32_t)((BytesReceived * 1000 * 1000 * 8) / (1000 * ElapsedMicroseconds)); - - printf("[%p][%llu] Closed [%s] after %u.%u ms. (TX %llu bytes @ %u kbps | RX %llu bytes @ %u kbps).\n", - Connection->QuicConnection, (unsigned long long)GetStreamID(MsQuic, QuicStream), - Completed ? "Complete" : "Cancel", - (uint32_t)(ElapsedMicroseconds / 1000), - (uint32_t)(ElapsedMicroseconds % 1000), - (unsigned long long)BytesCompleted, SendRate, - (unsigned long long)BytesReceived, RecvRate); - - } else { - printf("[%p][%llu] Closed [%s] after %u.%u ms.\n", - Connection->QuicConnection, (unsigned long long)GetStreamID(MsQuic, QuicStream), - Completed ? "Complete" : "Cancel", - (uint32_t)(ElapsedMicroseconds / 1000), - (uint32_t)(ElapsedMicroseconds % 1000)); - } - - Connection->OnPingStreamShutdownComplete(this); - - delete this; - break; - } - - default: - break; - } -} - -QUIC_STATUS -QUIC_API -PingStream::QuicCallbackHandler( - _In_ HQUIC /* Stream */, - _In_opt_ void* Context, - _Inout_ QUIC_STREAM_EVENT* Event - ) { - PingStream *pThis = (PingStream*)Context; - pThis->ProcessEvent(Event); - return QUIC_STATUS_SUCCESS; -} diff --git a/src/tools/ping/PingStream.h b/src/tools/ping/PingStream.h deleted file mode 100644 index fe4e5352d9..0000000000 --- a/src/tools/ping/PingStream.h +++ /dev/null @@ -1,87 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - -Abstract: - - QUIC Ping Stream declaration. Definites the functions and variables used - in the PingStream class. - ---*/ - -struct PingConnection; - -enum PingStreamMode { - UniSendMode, - UniRecvMode, - BidiSendMode, - BidiEchoMode -}; - -struct PingStream { - - PingConnection *Connection; - HQUIC QuicStream; - PingStreamMode Mode; - bool Aborted; - - uint64_t StartTime; - uint64_t CompleteTime; - - uint64_t BytesSent; - uint64_t BytesCompleted; - uint64_t BytesReceived; - - // - // Constructor for creating a new stream. - // - PingStream( - _In_ PingConnection *connection, - _In_ PingStreamMode mode - ); - - // - // Constructor for incoming stream. - // - PingStream( - _In_ PingConnection *connection, - _In_ HQUIC stream, - _In_ PingStreamMode modes - ); - - // - // Destructor. Closes the associated stream. - // - ~PingStream(); - - // - // Creates the underlying stream and starts sending. - // - bool - Start(); - -private: - - bool - QueueSendRequest( - PingSendRequest* SendRequest - ); - - bool - StartSend(); - - void - ProcessEvent( - _Inout_ QUIC_STREAM_EVENT* Event - ); - - static - QUIC_STATUS - QUIC_API - QuicCallbackHandler( - _In_ HQUIC Stream, - _In_opt_ void* Context, - _Inout_ QUIC_STREAM_EVENT* Event - ); -}; diff --git a/src/tools/ping/QuicPing.cpp b/src/tools/ping/QuicPing.cpp deleted file mode 100644 index 83c0df7c5e..0000000000 --- a/src/tools/ping/QuicPing.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - -Abstract: - - QUIC PING Server/Client tool. - ---*/ - -#include "QuicPing.h" - -const QUIC_API_TABLE* MsQuic; -HQUIC Registration; -HQUIC Configuration; -QUIC_PING_CONFIG PingConfig; - -void -PrintUsage() -{ - printf("quicping is a tool for sending and receiving data between a client and" - " server via the QUIC networking protocol.\n"); - - printf("\n quicping.exe [options]\n"); - - printf("\nServer options:\n"); - printf( - " -listen: The local IP address to listen on, or * for all IP addresses.\n" - " -thumbprint: The hash or thumbprint of the certificate to use.\n" - " -cert_store: The certificate store to search for the thumbprint in.\n" - " -machine_cert:<0/1> Use the machine, or current user's, certificate store. (def:0)\n"); - - printf("\nClient options:\n"); - printf( - " -target: The remote hostname or IP address to connect to.\n" - " -ip:<0/4/6> A hint for the resolving the hostname to an IP address. (def:0)\n" - " -remote: A remote IP address to connect to.\n" - " -bind: A local IP address to bind to.\n" - " -ver: The initial QUIC version number to use.\n" - " -resume: Resumption bytes for 0-RTT.\n" - " -connections:<####> The number of connections to create. (def:%u)\n" - " -wait:<####> The time the app waits for completion. (def:%u ms)\n", - DEFAULT_CLIENT_CONNECTION_COUNT, - DEFAULT_WAIT_TIMEOUT); - - printf("\nCommon options:\n"); - printf( -#if _WIN32 - " -comp:<####> The compartment ID to run in.\n" - " -core:<####> The CPU core to use for the main thread.\n" -#endif - " -alpn: The ALPN to use. (def:%s)\n" - " -port:<####> The UDP port of the server. (def:%u)\n" - " -encrypt:<0/1> Enables/disables encryption. (def:%u)\n" - " -sendbuf:<0/1> Whether to use send buffering. (def:%u)\n" - " -pacing:<0/1> Enables/disables pacing. (def:%u)\n" - " -stats:<0/1> Enables/disables printing statistics. (def:%u)\n" - " -exec:<0/1/2/3> The execution profile to use. (def:%u)\n" - " -uni:<####> The number of unidirectional streams to open locally. (def:0)\n" - " -bidi:<####> The number of bidirectional streams to open locally. (def:0)\n" - " -peer_uni:<####> The number of unidirectional streams for the peer to open. (def:0)\n" - " -peer_bidi:<####> The number of bidirectional streams for the peer to open. (def:0)\n" - " -length:<####> The length of streams opened locally. (def:0)\n" - " -iosize:<####> The size of each send request queued. (buffered def:%u) (nonbuffered def:%u)\n" - " -iocount:<####> The number of outstanding send requests to queue per stream. (buffered def:%u) (nonbuffered def:%u)\n" - " -datagrams:<####> The number of datagrams to open locally. (def:0)\n" - " -dlength:<####> The max length of each datagram. (def:%u)\n" - " -timeout:<####> Disconnect timeout for connection. (def:%u ms)\n" - " -idle:<####> Idle timeout for connection. (def:%u ms)\n" - " -key_bytes:<####> The number of bytes encrypted per key.\n" - " -selfsign:<0/1> Use self signed test certificates.\n", - DEFAULT_ALPN, - DEFAULT_PORT, - DEFAULT_USE_ENCRYPTION, - DEFAULT_USE_SEND_BUF, - DEFAULT_USE_PACING, - DEFAULT_PRINT_STATISTICS, - DEFAULT_EXECUTION_PROFILE, - DEFAULT_SEND_IO_SIZE_BUFFERED, DEFAULT_SEND_IO_SIZE_NONBUFFERED, - DEFAULT_SEND_COUNT_BUFFERED, DEFAULT_SEND_COUNT_NONBUFFERED, - DEFAULT_DATAGRAM_MAX_LENGTH, - DEFAULT_DISCONNECT_TIMEOUT, - DEFAULT_IDLE_TIMEOUT); - - printf("\nServer Examples:\n"); - printf(" quicping.exe -listen:* -thumbprint:175342733b39d81c997817296c9b691172ca6b6e -bidi:10\n"); - printf(" quicping.exe -listen:2001:4898:d8:34:b912:426d:1c88:5859 -thumbprint:175342733b39d81c997817296c9b691172ca6b6e\n"); - - printf("\nClient Examples:\n"); - printf(" quicping.exe -target:localhost -port:443 -ip:6 -uni:0\n"); - printf(" quicping.exe -target:localhost -connections:12 -uni:2 -length:100000\n"); -} - -void -ParseCommonCommands( - _In_ int argc, - _In_reads_(argc) _Null_terminated_ char* argv[] - ) -{ -#if _WIN32 - uint16_t compartmentid; - if (TryGetValue(argc, argv, "comp", &compartmentid)) { - NETIO_STATUS status; - if (!NETIO_SUCCESS(status = SetCurrentThreadCompartmentId(compartmentid))) { - printf("Failed to set compartment ID = %d: 0x%x\n", compartmentid, status); - return; - } else { - printf("Running in Compartment %d\n", compartmentid); - } - } - - uint8_t cpuCore; - if (TryGetValue(argc, argv, "core", &cpuCore)) { - SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR)(1ull << cpuCore)); - } -#endif - - const char* alpn = DEFAULT_ALPN; - TryGetValue(argc, argv, "alpn", &alpn); - PingConfig.ALPN.Buffer = (uint8_t*)alpn; - PingConfig.ALPN.Length = (uint32_t)strlen(alpn); - - uint16_t port = DEFAULT_PORT; - TryGetValue(argc, argv, "port", &port); - if (PingConfig.ServerMode) { - QuicAddrSetPort(&PingConfig.LocalIpAddr, port); - } else { - QuicAddrSetPort(&PingConfig.Client.RemoteIpAddr, port); - } - - uint16_t useEncryption = DEFAULT_USE_ENCRYPTION; - TryGetValue(argc, argv, "encrypt", &useEncryption); - PingConfig.UseEncryption = useEncryption != 0; - - uint16_t useSendBuffer = DEFAULT_USE_SEND_BUF; - TryGetValue(argc, argv, "sendbuf", &useSendBuffer); - PingConfig.UseSendBuffer = useSendBuffer != 0; - - uint16_t usePacing = DEFAULT_USE_PACING; - TryGetValue(argc, argv, "pacing", &usePacing); - PingConfig.UsePacing = usePacing != 0; - - uint16_t printStats = DEFAULT_PRINT_STATISTICS; - TryGetValue(argc, argv, "stats", &printStats); - PingConfig.PrintStats = printStats != 0; - - uint64_t uniStreams = 0; - TryGetValue(argc, argv, "uni", &uniStreams); - PingConfig.LocalUnidirStreamCount = uniStreams; - - uint64_t bidiStreams = 0; - TryGetValue(argc, argv, "bidi", &bidiStreams); - PingConfig.LocalBidirStreamCount = bidiStreams; - - uint16_t peerUniStreams = 0; - TryGetValue(argc, argv, "peer_uni", &peerUniStreams); - PingConfig.PeerUnidirStreamCount = peerUniStreams; - - uint16_t peerBidiStreams = 0; - TryGetValue(argc, argv, "peer_bidi", &peerBidiStreams); - PingConfig.PeerBidirStreamCount = peerBidiStreams; - - uint64_t streamLength = 0; - TryGetValue(argc, argv, "length", &streamLength); - PingConfig.StreamPayloadLength = streamLength; - - uint32_t ioSize = PingConfig.UseSendBuffer ? DEFAULT_SEND_IO_SIZE_BUFFERED : DEFAULT_SEND_IO_SIZE_NONBUFFERED; - TryGetValue(argc, argv, "iosize", &ioSize); - PingConfig.IoSize = ioSize; - - uint32_t ioCount = PingConfig.UseSendBuffer ? DEFAULT_SEND_COUNT_BUFFERED : DEFAULT_SEND_COUNT_NONBUFFERED; - TryGetValue(argc, argv, "iocount", &ioCount); - PingConfig.IoCount = ioCount; - - uint64_t datagrams = 0; - TryGetValue(argc, argv, "datagrams", &datagrams); - PingConfig.LocalDatagramCount = datagrams; - - uint16_t datagramMaxLength = DEFAULT_DATAGRAM_MAX_LENGTH; - TryGetValue(argc, argv, "dlength", &datagramMaxLength); - PingConfig.DatagramMaxLength = datagramMaxLength; - - uint32_t disconnectTimeout = DEFAULT_DISCONNECT_TIMEOUT; - TryGetValue(argc, argv, "timeout", &disconnectTimeout); - PingConfig.DisconnectTimeout = disconnectTimeout; - - uint64_t idleTimeout = DEFAULT_IDLE_TIMEOUT; - TryGetValue(argc, argv, "idle", &idleTimeout); - PingConfig.IdleTimeout = idleTimeout; - - PingConfig.MaxBytesPerKey = UINT64_MAX; - TryGetValue(argc, argv, "key_bytes", &PingConfig.MaxBytesPerKey); - - uint32_t connections = PingConfig.ConnectionCount; - TryGetValue(argc, argv, "connections", &connections); - PingConfig.ConnectionCount = connections; - - // - // Initialize internal memory structures based on the configuration. - // - - QuicPingRawIoBuffer = new uint8_t[PingConfig.IoSize]; -} - -void -ParseServerCommand( - _In_ int argc, - _In_reads_(argc) _Null_terminated_ char* argv[] - ) -{ - PingConfig.ServerMode = true; - - const char* localAddress = nullptr; - if (!TryGetValue(argc, argv, "listen", &localAddress)) { - printf("Must specify -listen for server mode\n"); - return; - } - if (!ConvertArgToAddress(localAddress, 0, &PingConfig.LocalIpAddr)) { - printf("Failed to decode IP address: '%s'!\nMust be *, a IPv4 or a IPv6 address.\n", localAddress); - return; - } - - PingConfig.ConnectionCount = 0; - ParseCommonCommands(argc, argv); - - QUIC_SETTINGS Settings{0}; - Settings.PeerBidiStreamCount = PingConfig.PeerBidirStreamCount; - Settings.IsSet.PeerBidiStreamCount = TRUE; - Settings.PeerUnidiStreamCount = PingConfig.PeerUnidirStreamCount; - Settings.IsSet.PeerUnidiStreamCount = TRUE; - Settings.DisconnectTimeoutMs = PingConfig.DisconnectTimeout; - Settings.IsSet.DisconnectTimeoutMs = TRUE; - Settings.IdleTimeoutMs = PingConfig.IdleTimeout; - Settings.IsSet.IdleTimeoutMs = TRUE; - Settings.DatagramReceiveEnabled = TRUE; - Settings.IsSet.DatagramReceiveEnabled = TRUE; - if (!PingConfig.UseSendBuffer) { - Settings.SendBufferingEnabled = FALSE; - Settings.IsSet.SendBufferingEnabled = TRUE; - } - if (!PingConfig.UsePacing) { - Settings.PacingEnabled = FALSE; - Settings.IsSet.PacingEnabled = TRUE; - } - if (PingConfig.MaxBytesPerKey != UINT64_MAX) { - Settings.MaxBytesPerKey = PingConfig.MaxBytesPerKey; - Settings.IsSet.MaxBytesPerKey = TRUE; - } - Settings.ServerResumptionLevel = QUIC_SERVER_RESUME_ONLY; - Settings.IsSet.ServerResumptionLevel = TRUE; - - Configuration = - GetServerConfigurationFromArgs( - argc, - argv, - MsQuic, - Registration, - &PingConfig.ALPN, - 1, - &Settings, - sizeof(Settings)); - if (!Configuration) { - printf("Failed to load configuration from args.\n"); - return; - } - - QuicPingServerRun(); - - FreeServerConfiguration(MsQuic, Configuration); -} - -void -ParseClientCommand( - _In_ int argc, - _In_reads_(argc) _Null_terminated_ char* argv[] - ) -{ - PingConfig.ServerMode = false; - - TryGetValue(argc, argv, "target", &PingConfig.Client.Target); - - uint16_t ip; - if (TryGetValue(argc, argv, "ip", &ip)) { - switch (ip) { - case 4: QuicAddrSetFamily(&PingConfig.Client.RemoteIpAddr, QUIC_ADDRESS_FAMILY_INET); break; - case 6: QuicAddrSetFamily(&PingConfig.Client.RemoteIpAddr, QUIC_ADDRESS_FAMILY_INET6); break; - } - } - - const char* remoteAddress; - if (TryGetValue(argc, argv, "remote", &remoteAddress)) { - PingConfig.Client.UseExplicitRemoteAddr = true; - if (!ConvertArgToAddress(remoteAddress, 0, &PingConfig.Client.RemoteIpAddr)) { - printf("Failed to decode IP address: '%s'!\nMust be *, a IPv4 or a IPv6 address.\n", remoteAddress); - return; - } - } - - const char* localAddress; - if (TryGetValue(argc, argv, "bind", &localAddress)) { - if (!ConvertArgToAddress(localAddress, 0, &PingConfig.LocalIpAddr)) { - printf("Failed to decode IP address: '%s'!\nMust be *, a IPv4 or a IPv6 address.\n", localAddress); - return; - } - } - - uint32_t version = 0; - TryGetValue(argc, argv, "ver", &version); - PingConfig.Client.Version = version; - - TryGetValue(argc, argv, "resume", &PingConfig.Client.ResumeToken); - - uint32_t waitTimeout = DEFAULT_WAIT_TIMEOUT; - TryGetValue(argc, argv, "wait", &waitTimeout); - PingConfig.Client.WaitTimeout = waitTimeout; - - PingConfig.ConnectionCount = DEFAULT_CLIENT_CONNECTION_COUNT; - ParseCommonCommands(argc, argv); - QuicPingClientRun(); -} - -int -QUIC_MAIN_EXPORT -main( - _In_ int argc, - _In_reads_(argc) _Null_terminated_ char* argv[] - ) -{ - int ErrorCode = -1; - uint16_t execProfile = DEFAULT_EXECUTION_PROFILE; - QUIC_REGISTRATION_CONFIG RegConfig = { "quicping", DEFAULT_EXECUTION_PROFILE }; - - CxPlatSystemLoad(); - CxPlatInitialize(); - - if (argc < 2) { - PrintUsage(); - goto Error; - } - - if (QUIC_FAILED(MsQuicOpen(&MsQuic))) { - printf("MsQuicOpen failed!\n"); - goto Error; - } - - TryGetValue(argc, argv, "exec", &execProfile); - RegConfig.ExecutionProfile = (QUIC_EXECUTION_PROFILE)execProfile; - - if (QUIC_FAILED(MsQuic->RegistrationOpen(&RegConfig, &Registration))) { - printf("RegistrationOpen failed!\n"); - MsQuicClose(MsQuic); - goto Error; - } - - // - // Parse input to see if we are a client or server - // - if (GetValue(argc, argv, "listen")) { - ParseServerCommand(argc, argv); - } else if (GetValue(argc, argv, "target")) { - ParseClientCommand(argc, argv); - } else { - printf("Invalid usage!\n\n"); - PrintUsage(); - } - - ErrorCode = 0; - delete [] QuicPingRawIoBuffer; - MsQuic->RegistrationClose(Registration); - MsQuicClose(MsQuic); - -Error: - - CxPlatUninitialize(); - CxPlatSystemUnload(); - - return ErrorCode; -} diff --git a/src/tools/ping/QuicPing.h b/src/tools/ping/QuicPing.h deleted file mode 100644 index 1a3fdaf6e9..0000000000 --- a/src/tools/ping/QuicPing.h +++ /dev/null @@ -1,207 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - ---*/ - -#pragma once - -#define _CRT_SECURE_NO_WARNINGS 1 -#define QUIC_TEST_APIS 1 // Needed for self signed cert API -#define QUIC_API_ENABLE_INSECURE_FEATURES 1 // Needed for disabling 1-RTT encryption -#include - -// -// QUIC API Function Table. -// -extern const QUIC_API_TABLE* MsQuic; - -// -// Registration context. -// -extern HQUIC Registration; - -// -// Configuration for server. -// -extern HQUIC Configuration; - -// -// Raw byte buffer for sending. -// -extern uint8_t* QuicPingRawIoBuffer; - -// -// The protocol name used for QuicPing -// -#define DEFAULT_ALPN "ping" - -// -// The default port used for connecting with QuicPing. -// -#define DEFAULT_PORT 433 - -// -// QuicPing defaults to using encryption. -// -#define DEFAULT_USE_ENCRYPTION 1 - -// -// QuicPing defaults to using send buffering. -// -#define DEFAULT_USE_SEND_BUF 1 - -// -// QuicPing defaults to using send pacing. -// -#define DEFAULT_USE_PACING 1 - -// -// QuicPing defaults not printing connection statistics. -// -#define DEFAULT_PRINT_STATISTICS 0 - -// -// QuicPing defaults to the low latency profile. -// -#define DEFAULT_EXECUTION_PROFILE QUIC_EXECUTION_PROFILE_LOW_LATENCY - -// -// The default connection count count. -// -#define DEFAULT_CLIENT_CONNECTION_COUNT 1 - -// -// The default size of a single send IO, and how many to keep outstanding, -// when buffered sends are disabled. -// -#define DEFAULT_SEND_IO_SIZE_NONBUFFERED 0x100000 -#define DEFAULT_SEND_COUNT_NONBUFFERED 8 - -// -// The default size of a single send IO, and how many to keep outstanding, -// when buffered sends are enabled. -// -#define DEFAULT_SEND_IO_SIZE_BUFFERED 0x10000 -#define DEFAULT_SEND_COUNT_BUFFERED 1 - -// -// The default payload length of datagrams. -// -#define DEFAULT_DATAGRAM_MAX_LENGTH UINT16_MAX // Use connection max - -// -// The disconnect timeout (in milliseconds) used. -// -#define DEFAULT_DISCONNECT_TIMEOUT (10 * 1000) - -// -// The idle timeout (in milliseconds) used. -// -#define DEFAULT_IDLE_TIMEOUT 1000 - -// -// The amount of time (in milliseconds) the app will wait for completion. -// -#define DEFAULT_WAIT_TIMEOUT (60 * 60 * 1000) - -typedef struct QUIC_PING_CONFIG { - - bool ServerMode : 1; - bool UseEncryption : 1; - bool UseSendBuffer : 1; - bool UsePacing : 1; - bool PrintStats : 1; - - QUIC_BUFFER ALPN; - QUIC_ADDR LocalIpAddr; - - uint32_t DisconnectTimeout; // Milliseconds - uint64_t IdleTimeout; // Milliseconds - - uint64_t LocalUnidirStreamCount; // Total - uint64_t LocalBidirStreamCount; // Total - uint64_t LocalDatagramCount; // Total - uint16_t PeerUnidirStreamCount; // Max simultaneous - uint16_t PeerBidirStreamCount; // Max simultaneous - - uint64_t MaxBytesPerKey; // Max bytes per key - - uint64_t StreamPayloadLength; - uint16_t DatagramMaxLength; - - uint32_t IoSize; - uint32_t IoCount; - - uint32_t ConnectionCount; - - struct { - bool UseExplicitRemoteAddr : 1; - const char* Target; // SNI - QUIC_ADDR RemoteIpAddr; - uint32_t Version; // QUIC protocol version - const char* ResumeToken; - uint32_t WaitTimeout; // Milliseconds - } Client; - -} QUIC_PING_CONFIG; - -extern QUIC_PING_CONFIG PingConfig; - -struct PingSendRequest { - - QUIC_SEND_FLAGS Flags; - QUIC_BUFFER QuicBuffer; - bool DeleteBufferOnDestruction; - - PingSendRequest( - ) { - DeleteBufferOnDestruction = false; - Flags = QUIC_SEND_FLAG_ALLOW_0_RTT; - QuicBuffer.Buffer = QuicPingRawIoBuffer; - QuicBuffer.Length = 0; - } - - PingSendRequest( - const uint8_t * buffer, - uint32_t bufferSize - ) { - DeleteBufferOnDestruction = true; - Flags = QUIC_SEND_FLAG_NONE; - QuicBuffer.Buffer = new uint8_t[bufferSize]; - QuicBuffer.Length = bufferSize; - if (buffer) { - memcpy((uint8_t*)QuicBuffer.Buffer, buffer, bufferSize); - } - } - - void SetLength(uint64_t BytesLeftToSend) { - if (BytesLeftToSend > PingConfig.IoSize) { - QuicBuffer.Length = PingConfig.IoSize; - } else { - Flags |= QUIC_SEND_FLAG_FIN; - QuicBuffer.Length = (uint32_t)BytesLeftToSend; - } - } - - ~PingSendRequest( - ) { - if (DeleteBufferOnDestruction) { - delete[] QuicBuffer.Buffer; - } - } -}; - -// -// Starts the server at the local address and waits for clients until a key is pressed. -// -void QuicPingServerRun(); - -// -// Connects the client to the remote host. -// -void QuicPingClientRun(); - -#include "PingStream.h" -#include "PingConnection.h" diff --git a/src/tools/ping/Server.cpp b/src/tools/ping/Server.cpp deleted file mode 100644 index 7866dae1e3..0000000000 --- a/src/tools/ping/Server.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - -Abstract: - - QUIC PING Server Implementation. - ---*/ - -#include "QuicPing.h" - -struct PingServer { - - HQUIC QuicListener; - - PingTracker Tracker; - - PingServer() : QuicListener(nullptr) { } - - ~PingServer() { - if (QuicListener) { - MsQuic->ListenerClose(QuicListener); - } - } - - bool Start() { - if (QUIC_FAILED( - MsQuic->ListenerOpen( - Registration, - QuicCallbackHandler, - this, - &QuicListener))) { - printf("MsQuic->ListenerOpen failed!\n"); - return false; - } - if (QUIC_FAILED( - MsQuic->ListenerStart( - QuicListener, - &PingConfig.ALPN, - 1, - &PingConfig.LocalIpAddr))) { - printf("MsQuic->ListenerStart failed!\n"); - } - return true; - } - - void - ProcessEvent( - _Inout_ QUIC_LISTENER_EVENT* Event - ) { - switch (Event->Type) { - case QUIC_LISTENER_EVENT_NEW_CONNECTION: { - auto Connection = new PingConnection(&Tracker, Event->NEW_CONNECTION.Connection); - if (Connection != NULL) { - QUIC_STATUS Status = - MsQuic->ConnectionSetConfiguration( - Event->NEW_CONNECTION.Connection, - Configuration); - if (QUIC_FAILED(Status)) { - delete Connection; - } - if (!Connection->Initialize(true)) { - delete Connection; - } - } - break; - } - } - } - - static - QUIC_STATUS - QUIC_API - QuicCallbackHandler( - _In_ HQUIC /* Listener */, - _In_opt_ void* Context, - _In_ QUIC_LISTENER_EVENT* Event - ) { - PingServer *pThis = (PingServer*)Context; - pThis->ProcessEvent(Event); - return QUIC_STATUS_SUCCESS; - } -}; - -void QuicPingServerRun() -{ - { - PingServer Server; - if (!Server.Start()) { - printf("Failed to start the listener!\n"); - return; - } - - if (PingConfig.ConnectionCount > 0) { - for (uint32_t i = 0; i < PingConfig.ConnectionCount; i++) { - Server.Tracker.AddItem(); - } - Server.Tracker.Start(); - printf("Ready For Connections!\n\n"); - // - // An explicit flush is needed in order to be detected in real time by the test runner - // - fflush(stdout); - Server.Tracker.WaitForever(); - } else { - printf("Press Enter to exit.\n\n"); - getchar(); - } - } - - MsQuic->RegistrationShutdown(Registration, QUIC_CONNECTION_SHUTDOWN_FLAG_NONE, 0); -} diff --git a/src/tools/ping/readme.md b/src/tools/ping/readme.md deleted file mode 100644 index ce41aa4c3c..0000000000 --- a/src/tools/ping/readme.md +++ /dev/null @@ -1,164 +0,0 @@ -Quic Ping -======================== - -The following details how to use quicping to exercise QUIC. quicping allows for -creating either a client or server that can send and/or receive random streams -of data of variable length. - -Common Configuration ------------------------- - -There are a number parameters that are common ot both client and server. - -**OPTIONAL PARAMETERS** - - alpn The TLS application layer protocol negotiation to use. - [default: ping] - - port The UDP port to listen on (server) or connect to (client). - [default: 4433] - - encrypt Enable/disable encryption for the QUIC connection. If encryption - is disabled, then only quicping servers that also have - encryption disabled will allow the client to connect. - [default: 1] - - sendbuf Enable/disable send buffering logic when sending on a stream. - [default: 1] - - pacing Enable/disable pacing for the QUIC connection(s). - [default: 1] - - stats Enable/disable printing of statistics after a connection ends. - [default: 0] - - uni The number of unidirectional streams to open. - [default: 0] - - bidi The number of bidirectional streams to open. - [default: 0] - - peer_uni The number of unidirectional streams to allow the peer to open. - [default: 0] - - peer_bidi The number of bidirectional streams to allow the peer to open. - [default: 0] - - length The number of bytes to send per stream. - [default: 0] - - iosize The size of each send request queued. - [buffered default: 0x10000] - [nonbuffered default: 0x100000] - - iocount The number of outstanding send requests to queue per stream. - [buffered default: 1] - [nonbuffered default: 8] - - timeout The disconnect timeout to use. Units of milliseconds. - [default: 10000] - - idle The idle timeout to use. Units of milliseconds. - [default: 1000] - - key_bytes The number of bytes encrypted per key. - -Server Configuration ------------------------- - - quicping.exe -listen:127.0.0.1 -port:443 -thumbprint:175342733b39d81c997817296c9b691172ca6b6e - -When running quicping.exe as a server, there are a number of configuration -parameters that are important to note: - -**REQUIRED PARAMETERS** - - listen The local IP (v4 or v6) address the server will be listening on. - - thumbprint The hash or thumbprint of the certificate (in current user's MY - store) to use. - -**EXAMPLE CONFIGURATIONS** - -The following example configures quicping to listen on the local IP and UDP -port 127.0.0.1:443. It allows the client to open up to 100 bidirectional -streams and if the client allows it, the server will open up to 100 -unidirectional streams. - - quicping.exe -listen:127.0.0.1 -port:443 -thumbprint:175342733b39d81c997817296c9b691172ca6b6e - -The following example configures quicping to listen on the localhost IP -address with the default port of 4433. It also disables encryption so only -clients that also disable encryption will be able to connect. - - quicping.exe -listen:127.0.0.1 -encrypt:0 -thumbprint:175342733b39d81c997817296c9b691172ca6b6e - -**SERVER CERTIFICATE** - -The following Powershell command can be used to create self-signed certificates: - - New-SelfSignedCertificate -DnsName -FriendlyName MsQuic-Test -KeyUsageProperty Sign -KeyUsage DigitalSignature -CertStoreLocation cert:\CurrentUser\My -HashAlgorithm SHA256 -Provider "Microsoft Software Key Storage Provider" - -Client Configuration ------------------------- - - quicping.exe -target:localhost -ip:4 -port:443 -uni:0 - -When running quicping.exe as a client, there are a number of configuration -parameters that are important to note: - -**REQUIRED PARAMETERS** - - target The hostname or IP address of the target machine to connect to. - -**OPTIONAL PARAMETERS** - - ip The hint to use for resolving a hostname via DNS to either an - IPv4 (4) or IPv6 (6) address. A value of 0 indicates - unspecified. - [default: 0] - - remote A remote IP address to connect to. - [default: N/A] - - bind The local IP address to bind to before starting the connection - to the target machine. - [default: N/A] - - ver The initial version to set when connecting. - [default: N/A] - - connections The number of parallel connections to open. - [default: 1] - - resume A 0-RTT resumption ticket to use for the connection. The ticket - is from a previous connection attempt, and should be written to - the console if it was successful. - [default: N/A] - -**EXAMPLE CONFIGURATIONS** - -The following example configures the client to attempt to the IPv4 localhost -address of the local machine (127.0.0.1) on port 443. It will not open any -unidirectional or bidirectional streams to the server, nor will it allow for -the server to open any back to the client. After successfully connecting it -will exit. - - quicping.exe -target:localhost -ip:4 -port:443 - -The following example configures the client to attempt to a test Microsoft -server running quicping as a server. It opens two unidirectional streams and -sends 1 MB on each of them. - - quicping.exe -target:quic.westus.cloudapp.azure.com -port:4433 -uni:2 -length:1000000 - -Example Output: - - [75212a5493c6b5db][2] Opened. - [75212a5493c6b5db][6] Opened. - [75212a5493c6b5db] Connected in 117.731 milliseconds. - [75212a5493c6b5db][6] Closed [Complete] after 268.246 ms. (TX 1000000 bytes @ 29124 kbps | RX 0 bytes @ 0 kbps). - [75212a5493c6b5db][2] Closed [Complete] after 283.97 ms. (TX 1000000 bytes @ 27596 kbps | RX 0 bytes @ 0 kbps). - Total Rate for all Connections & Streams: 56720 kbps. - [75212a5493c6b5db] Resumption ticket (106 bytes): - 42007BBE3E070D5555487B5DBDAC6C7B426F2B950B3D6972F5FE83FA254F881D2106BC583C2D08A6C3C6AD1E75E09F009BC1BB50DE939C420F9C259E1E83CAB6162F827C03041303002062EE266CD55AE46383F1679294D8263109620EBC12B5D048D15422031D3AFAB7