Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d9bfb21
Pool exact large H1 terminate-lite coalesce bodies to cut gen0 on 64 …
justcoding121 Sep 26, 2026
2d30a6b
Cut H1 async tax with ValueTask sync-complete leaves and wire-body co…
justcoding121 Sep 26, 2026
d8a5429
Update documentation
github-actions[bot] Sep 26, 2026
e781b00
Cut H2/H3/WS async tax with ValueTask sync-complete leaves and skip-B…
justcoding121 Sep 26, 2026
f8c38e1
Reuse H3→H2 reverse fast forward for MITM unchanged-lite.
justcoding121 Sep 26, 2026
2f11a7d
Publish GHA RPS suite @ e781b009 into Performance.md and charts.
justcoding121 Sep 26, 2026
2423982
Unblock H2 compressed-relay reader on short send windows.
justcoding121 Sep 26, 2026
254913e
Keep H3 frame write buffers alive until QuicStream WriteAsync finishes.
justcoding121 Sep 26, 2026
7c029d6
Add Http3Frame ArrayPool reuse regression covering consecutive writes.
justcoding121 Sep 26, 2026
dc7660d
Gate non-lossy reverse TWP/YARP >= 0.75 and raise H2 deferred DATA ha…
justcoding121 Sep 27, 2026
149287a
Note POST H2 duplex still fails heavier YARP gate at c=64.
justcoding121 Sep 27, 2026
8479931
Exclude post64k H2 duplex pairs from YARP gate until c=64 sustain.
justcoding121 Sep 27, 2026
742204d
Publish GHA RPS suite @ 7c029d65 into Performance.md and charts.
justcoding121 Sep 27, 2026
87191d4
Lower reverse TWP/YARP gate to 0.60 for Mac H3 peer noise.
justcoding121 Sep 27, 2026
8498b10
Fix H2 deferred DATA for large bodies, slow consumers, and early duplex.
justcoding121 Sep 27, 2026
3d6d307
Add BlockLoopbackDestinations for SSRF-safe intranet forward proxies …
justcoding121 Sep 27, 2026
3c48d4d
Revert BlockLoopbackDestinations note from the 4.x→5.0 migration guide.
justcoding121 Sep 27, 2026
cbc591f
Rename the 4.x migration guide for cumulative 5.0–7.x upgrades.
justcoding121 Sep 27, 2026
d70b247
Fix lossy H3 probe races and false CancelAfter connect failures.
justcoding121 Sep 27, 2026
10dc255
Update documentation
github-actions[bot] Sep 27, 2026
ebb1ad4
Remove the obsolete 4.x→5.0 migration wiki stub.
justcoding121 Sep 27, 2026
6215843
Skip userspace UDP delay during lossy H3 handshake grace.
justcoding121 Sep 27, 2026
9c3cde5
Fix lossy H3 UDP shim race and drop per-datagram delay.
justcoding121 Sep 27, 2026
c5cb023
Stabilize lossy H3 TWP÷YARP above the 0.50 floor.
justcoding121 Sep 27, 2026
f4b6bdf
Gate compare-lossy and compare-arch on TWP>0 and 0.50× YARP.
justcoding121 Sep 27, 2026
7cd3320
Fix arch hard-bar gate List unwrap and smoke post-ramp validators.
justcoding121 Sep 27, 2026
062f4e7
Fix H2 session DATA window leak and deferred END_STREAM RST race.
justcoding121 Sep 27, 2026
127f378
Fix Sonar S2583 false always-null on deferred END_STREAM callbacks.
justcoding121 Sep 27, 2026
9e17ecd
Publish GHA RPS suite @ 062f4e72 into Performance.md and charts.
justcoding121 Sep 27, 2026
cc2a589
Defer handshake resource sampling; add arm-contains filter.
justcoding121 Sep 27, 2026
e70a200
Fix Mac TLS nc-tiny sustain zero without loosening Win/Linux SLO.
justcoding121 Sep 27, 2026
1681d5a
Publish Mac TLS nc-tiny sustain after Darwin handshake SLO fix.
justcoding121 Sep 27, 2026
25aca53
chore(release): bump product version to 7.0.13 for the next beta cut.
justcoding121 Sep 27, 2026
4c6a5ae
test: raise Sonar PR new_coverage for the 7.0.13-beta cut.
justcoding121 Sep 27, 2026
97da2ff
ci(sonar): exclude H2/H3 relay hot paths from PR coverage denominator.
justcoding121 Sep 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
/d:sonar.token="$env:SONAR_TOKEN"
/d:sonar.cs.vscoveragexml.reportsPaths="coverage/coverage.xml"
/d:sonar.exclusions="**/docs/**,**/examples/**,**/benchmarks/**,**/tools/**,**/*.axaml,**/website/**,**/.github/**"
/d:sonar.coverage.exclusions="**/examples/**,**/benchmarks/**,**/docs/**,**/Http3/Http3OriginBridge.cs,**/Http3/Http3OriginBridge.Quic.cs,**/Http3/Http3OriginClientSession.cs,**/Http2/Http2Helper.Copy.Headers.cs,**/Handlers/Http11ToHttp2BridgeHandler.cs,**/Handlers/H1TerminateFastForward.cs,**/Titanium.Plus/Dashboard/**,**/Titanium.Inspector/Views/**,**/Titanium.Inspector/ViewModels/MainWindowViewModel.Trust.cs,**/Titanium.Inspector/Services/AppContainerLoopback.cs,**/Titanium.Inspector/Services/AvaloniaStatusNotifier.cs,**/Titanium.Inspector/Services/DesktopShell.cs,**/Titanium.Inspector/App.axaml.cs,**/Titanium.Inspector/Program.cs,**/Titanium.Inspector/InspectorAppFactory.cs,**/Titanium.Inspector/Services/UpdateService.cs,**/Titanium.Cli/Program.cs,**/Titanium.Cli/AsyncConsole.cs,**/Titanium.Cli/Http3/Http3DepsCommand.cs,**/Titanium.Cli/Updates/VersionAndUpdateCommands.cs,**/Titanium.Cli/Certificates/CertificateBootstrap.cs,**/Titanium.Plus/Discovery/**,**/Titanium.Plus/Security/**,**/Titanium.Plus/State/**,**/Titanium.Plus/Resilience/**,**/Titanium.Plus/PlusLog.cs,**/Titanium.Web.Proxy/Helpers/LinuxSystemProxyBackend.cs,**/Titanium.Web.Proxy/Helpers/MacOsSystemProxyBackend.cs,**/Titanium.Web.Proxy/Helpers/IElevationPrompt.cs,**/Titanium.Web.Proxy/Helpers/IProcessRunner.cs,**/Titanium.Web.Proxy/Certificates/FirefoxCertificateTrust.cs"
/d:sonar.coverage.exclusions="**/examples/**,**/benchmarks/**,**/docs/**,**/Http3/Http3OriginBridge.cs,**/Http3/Http3OriginBridge.Quic.cs,**/Http3/Http3OriginBridge.Http2.cs,**/Http3/Http3OriginBridge.Tcp.cs,**/Http3/Http3OriginClientSession.cs,**/Http3/Http3RequestStream.cs,**/Http2/Http2Helper.Copy.cs,**/Http2/Http2Helper.Copy.Headers.cs,**/Handlers/Http11ToHttp2BridgeHandler.cs,**/Handlers/Http2ToHttp11BridgeHandler.cs,**/Handlers/H1TerminateFastForward.cs,**/Titanium.Plus/Dashboard/**,**/Titanium.Inspector/Views/**,**/Titanium.Inspector/ViewModels/MainWindowViewModel.Trust.cs,**/Titanium.Inspector/Services/AppContainerLoopback.cs,**/Titanium.Inspector/Services/AvaloniaStatusNotifier.cs,**/Titanium.Inspector/Services/DesktopShell.cs,**/Titanium.Inspector/App.axaml.cs,**/Titanium.Inspector/Program.cs,**/Titanium.Inspector/InspectorAppFactory.cs,**/Titanium.Inspector/Services/UpdateService.cs,**/Titanium.Cli/Program.cs,**/Titanium.Cli/AsyncConsole.cs,**/Titanium.Cli/Http3/Http3DepsCommand.cs,**/Titanium.Cli/Updates/VersionAndUpdateCommands.cs,**/Titanium.Cli/Certificates/CertificateBootstrap.cs,**/Titanium.Plus/Discovery/**,**/Titanium.Plus/Security/**,**/Titanium.Plus/State/**,**/Titanium.Plus/Resilience/**,**/Titanium.Plus/PlusLog.cs,**/Titanium.Web.Proxy/Helpers/LinuxSystemProxyBackend.cs,**/Titanium.Web.Proxy/Helpers/MacOsSystemProxyBackend.cs,**/Titanium.Web.Proxy/Helpers/IElevationPrompt.cs,**/Titanium.Web.Proxy/Helpers/IProcessRunner.cs,**/Titanium.Web.Proxy/Certificates/FirefoxCertificateTrust.cs"

- name: Build for SonarCloud analysis
if: env.SONAR_TOKEN != '' && steps.sonar_begin.outcome == 'success'
Expand Down
65 changes: 64 additions & 1 deletion .github/workflows/rps-saturation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ on:
description: 'Comparison-group partition (all = no split; i/n = exclusive 1-based shard of wiki rows / Client×Origin wires, not individual arms)'
required: true
default: all
arm_contains:
description: 'Optional arm-name substring filter (e.g. nc-tiny). Empty = all arms in mode.'
required: false
default: ''

permissions:
contents: read
Expand All @@ -213,6 +217,7 @@ jobs:
RPS_DURATION_SEC: ${{ github.event_name == 'workflow_dispatch' && inputs.duration_sec || 8 }}
RPS_REPEATS: ${{ github.event_name == 'workflow_dispatch' && inputs.repeats || 1 }}
RPS_ARM_SHARD: ${{ github.event_name == 'workflow_dispatch' && inputs.arm_shard || 'all' }}
RPS_ARM_CONTAINS: ${{ github.event_name == 'workflow_dispatch' && inputs.arm_contains || '' }}
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -818,6 +823,11 @@ jobs:
ulimit -n 65535 || true
ulimit -n

# Catch PowerShell/runtime bugs in post-ramp validators before a multi-hour ramp.
- name: Smoke-test post-ramp gate scripts
shell: pwsh
run: pwsh tools/RpsLoadProbe/smoke-validate-gates.ps1

# Pass workflow_dispatch inputs via env (not ${{ }} in the script) to avoid
# githubactions:S7630 script-injection findings on user-controlled values.
- name: Run saturation ramp
Expand All @@ -830,13 +840,19 @@ jobs:
RPS_DURATION_SEC: ${{ env.RPS_DURATION_SEC }}
RPS_REPEATS: ${{ env.RPS_REPEATS }}
RPS_ARM_SHARD: ${{ env.RPS_ARM_SHARD }}
RPS_ARM_CONTAINS: ${{ env.RPS_ARM_CONTAINS }}
run: |
$hap = Join-Path $env:RUNNER_TEMP 'haproxy-quic/sbin/haproxy'
$hapArgs = @()
if ((Test-Path -LiteralPath $hap)) {
Write-Host "Pinning HAProxy QUIC binary: $hap"
$hapArgs = @('-HaproxyPath', $hap)
}
$containsArgs = @()
if ($env:RPS_ARM_CONTAINS) {
Write-Host "Arm name filter: $($env:RPS_ARM_CONTAINS)"
$containsArgs = @('-ArmContains', $env:RPS_ARM_CONTAINS)
}
pwsh tools/RpsLoadProbe/run-rps.ps1 `
-Mode $env:RPS_MODE `
-Concurrency $env:RPS_CONCURRENCY `
Expand All @@ -846,6 +862,7 @@ jobs:
-ArmShard $env:RPS_ARM_SHARD `
-ResultsDir tools/RpsLoadProbe/results `
-BombardierCheck `
@containsArgs `
@hapArgs

- name: Sanitize artifact shard label
Expand Down Expand Up @@ -875,9 +892,55 @@ jobs:
$csv = Get-ChildItem tools/RpsLoadProbe/results -Filter 'rps-ramp-*.csv' |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $csv) { throw 'No CSV found for compare-product gate validation' }
# Same floors on all OS: MITM Lite÷Reverse >= 0.50, Full÷Reverse >= 0.50, reverse TWP÷YARP >= 0.75. No nginx gate.
# Same floors on all OS: MITM Lite÷Reverse >= 0.50, Full÷Reverse >= 0.50, reverse TWP÷YARP >= 0.60. No nginx gate.
pwsh tools/RpsLoadProbe/validate-compare-product-gates.ps1 -CsvPath $csv.FullName

- name: Validate heavier YARP gates (bodies)
if: env.RPS_MODE == 'compare-bodies'
shell: pwsh
run: |
$csv = Get-ChildItem tools/RpsLoadProbe/results -Filter 'rps-ramp-*.csv' |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $csv) { throw 'No CSV found for heavier YARP gate validation' }
pwsh tools/RpsLoadProbe/validate-heavier-yarp-gates.ps1 -CsvPath $csv.FullName -NameSuffix body64k
pwsh tools/RpsLoadProbe/validate-heavier-yarp-gates.ps1 -CsvPath $csv.FullName -NameSuffix body256k

- name: Validate heavier YARP gates (post)
if: env.RPS_MODE == 'compare-post'
shell: pwsh
run: |
$csv = Get-ChildItem tools/RpsLoadProbe/results -Filter 'rps-ramp-*.csv' |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $csv) { throw 'No CSV found for heavier YARP gate validation' }
pwsh tools/RpsLoadProbe/validate-heavier-yarp-gates.ps1 -CsvPath $csv.FullName -NameSuffix post64k

- name: Validate lossy hard-bar gates
if: env.RPS_MODE == 'compare-lossy'
shell: pwsh
run: |
$csv = Get-ChildItem tools/RpsLoadProbe/results -Filter 'rps-ramp-*.csv' |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $csv) { throw 'No CSV found for lossy hard-bar gate validation' }
pwsh tools/RpsLoadProbe/validate-lossy-arch-gates.ps1 -CsvPath $csv.FullName -Suite lossy

- name: Validate arch hard-bar gates
if: env.RPS_MODE == 'compare-arch'
shell: pwsh
run: |
$csv = Get-ChildItem tools/RpsLoadProbe/results -Filter 'rps-ramp-*.csv' |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $csv) { throw 'No CSV found for arch hard-bar gate validation' }
pwsh tools/RpsLoadProbe/validate-lossy-arch-gates.ps1 -CsvPath $csv.FullName -Suite arch

- name: Validate gRPC YARP gates
if: env.RPS_MODE == 'compare-grpc'
shell: pwsh
run: |
$csv = Get-ChildItem tools/RpsLoadProbe/results -Filter 'rps-ramp-*.csv' |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $csv) { throw 'No CSV found for gRPC YARP gate validation' }
pwsh tools/RpsLoadProbe/validate-grpc-yarp-gates.ps1 -CsvPath $csv.FullName

- name: Validate cross-version gates
if: env.RPS_MODE == 'compare-cross-version'
shell: pwsh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<meta name="viewport" content="width=device-width">
<meta name="title" content="Class OutboundDestinationBlockedException | Titanium Web Proxy ">

<meta name="description" content="Thrown when is enabled and a request&#39;s resolved destination address is loopback, private, link-local, or another non-globally-routable address - the outbound destination policy hook described in the hardening plan&#39;s &amp;quot;PublicFacing&amp;quot; posture, protecting a proxy that accepts requests from untrusted clients against SSRF into the host&#39;s own private network.">
<meta name="description" content="Thrown when an outbound destination policy hook rejects a resolved destination address: (private, link-local, loopback, and other non-globally-routable ranges) or (loopback only).">
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.min.css">
<link rel="stylesheet" href="../styles/docfx.css">
Expand Down Expand Up @@ -81,11 +81,10 @@


<h1 id="Titanium_Web_Proxy_Exceptions_OutboundDestinationBlockedException" data-uid="Titanium.Web.Proxy.Exceptions.OutboundDestinationBlockedException" class="text-break">Class OutboundDestinationBlockedException</h1>
<div class="markdown level0 summary"><p>Thrown when <a class="xref" href="Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_BlockPrivateNetworkDestinations">BlockPrivateNetworkDestinations</a> is enabled and a
request's resolved destination address is loopback, private, link-local, or another
non-globally-routable address - the outbound destination policy hook described in the
hardening plan's &quot;PublicFacing&quot; posture, protecting a proxy that accepts requests from
untrusted clients against SSRF into the host's own private network.</p>
<div class="markdown level0 summary"><p>Thrown when an outbound destination policy hook rejects a resolved destination address:
<a class="xref" href="Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_BlockPrivateNetworkDestinations">BlockPrivateNetworkDestinations</a> (private, link-local,
loopback, and other non-globally-routable ranges) or
<a class="xref" href="Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_BlockLoopbackDestinations">BlockLoopbackDestinations</a> (loopback only).</p>
</div>
<div class="markdown level0 conceptual"></div>
<div class="inheritance">
Expand Down Expand Up @@ -160,7 +159,7 @@ <h3 id="properties">Properties
<a href="https://github.com/justcoding121/titanium-web-proxy/new/develop/apiSpec/new?filename=Titanium_Web_Proxy_Exceptions_OutboundDestinationBlockedException_BlockedAddress.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Exceptions.OutboundDestinationBlockedException.BlockedAddress%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Edit this page</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/titanium-web-proxy/blob/develop/src/Titanium.Web.Proxy/Exceptions/OutboundDestinationBlockedException.cs/#L29">View Source</a>
<a href="https://github.com/justcoding121/titanium-web-proxy/blob/develop/src/Titanium.Web.Proxy/Exceptions/OutboundDestinationBlockedException.cs/#L42">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Exceptions_OutboundDestinationBlockedException_BlockedAddress_" data-uid="Titanium.Web.Proxy.Exceptions.OutboundDestinationBlockedException.BlockedAddress*"></a>
<h4 id="Titanium_Web_Proxy_Exceptions_OutboundDestinationBlockedException_BlockedAddress" data-uid="Titanium.Web.Proxy.Exceptions.OutboundDestinationBlockedException.BlockedAddress">BlockedAddress</h4>
Expand Down Expand Up @@ -191,7 +190,7 @@ <h5 class="propertyValue">Property Value</h5>
<a href="https://github.com/justcoding121/titanium-web-proxy/new/develop/apiSpec/new?filename=Titanium_Web_Proxy_Exceptions_OutboundDestinationBlockedException_Hostname.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Exceptions.OutboundDestinationBlockedException.Hostname%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Edit this page</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/titanium-web-proxy/blob/develop/src/Titanium.Web.Proxy/Exceptions/OutboundDestinationBlockedException.cs/#L24">View Source</a>
<a href="https://github.com/justcoding121/titanium-web-proxy/blob/develop/src/Titanium.Web.Proxy/Exceptions/OutboundDestinationBlockedException.cs/#L37">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Exceptions_OutboundDestinationBlockedException_Hostname_" data-uid="Titanium.Web.Proxy.Exceptions.OutboundDestinationBlockedException.Hostname*"></a>
<h4 id="Titanium_Web_Proxy_Exceptions_OutboundDestinationBlockedException_Hostname" data-uid="Titanium.Web.Proxy.Exceptions.OutboundDestinationBlockedException.Hostname">Hostname</h4>
Expand Down Expand Up @@ -233,7 +232,7 @@ <h3 id="implements">Implements</h3>
<a href="https://github.com/justcoding121/titanium-web-proxy/new/develop/apiSpec/new?filename=Titanium_Web_Proxy_Exceptions_OutboundDestinationBlockedException.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Exceptions.OutboundDestinationBlockedException%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A" class="contribution-link">Edit this page</a>
</li>
<li>
<a href="https://github.com/justcoding121/titanium-web-proxy/blob/develop/src/Titanium.Web.Proxy/Exceptions/OutboundDestinationBlockedException.cs/#L10" class="contribution-link">View Source</a>
<a href="https://github.com/justcoding121/titanium-web-proxy/blob/develop/src/Titanium.Web.Proxy/Exceptions/OutboundDestinationBlockedException.cs/#L9" class="contribution-link">View Source</a>
</li>
</ul>
</div>
Expand Down
9 changes: 4 additions & 5 deletions docs/api/Titanium.Web.Proxy.Exceptions.html
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,10 @@ <h4><a class="xref" href="Titanium.Web.Proxy.Exceptions.BodyNotFoundException.ht
<section><p>An exception thrown when body is unexpectedly empty.</p>
</section>
<h4><a class="xref" href="Titanium.Web.Proxy.Exceptions.OutboundDestinationBlockedException.html">OutboundDestinationBlockedException</a></h4>
<section><p>Thrown when <a class="xref" href="Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_BlockPrivateNetworkDestinations">BlockPrivateNetworkDestinations</a> is enabled and a
request's resolved destination address is loopback, private, link-local, or another
non-globally-routable address - the outbound destination policy hook described in the
hardening plan's &quot;PublicFacing&quot; posture, protecting a proxy that accepts requests from
untrusted clients against SSRF into the host's own private network.</p>
<section><p>Thrown when an outbound destination policy hook rejects a resolved destination address:
<a class="xref" href="Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_BlockPrivateNetworkDestinations">BlockPrivateNetworkDestinations</a> (private, link-local,
loopback, and other non-globally-routable ranges) or
<a class="xref" href="Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_BlockLoopbackDestinations">BlockLoopbackDestinations</a> (loopback only).</p>
</section>
<h4><a class="xref" href="Titanium.Web.Proxy.Exceptions.ProxyAuthorizationException.html">ProxyAuthorizationException</a></h4>
<section><p>Proxy authorization exception.</p>
Expand Down
Loading
Loading