Skip to content

Commit e577596

Browse files
authored
Merge pull request #1687 from fl4via/backport-fixes_2.3.x
[UNDERTOW-2412 / 2445 / 2449 / 2446 / 2436 / 2422 / 2444 / 2448] Backport fixes to 2.3.x
2 parents 8fafa79 + 4fe95e7 commit e577596

File tree

10 files changed

+311
-102
lines changed

10 files changed

+311
-102
lines changed

.github/workflows/ci.yml

+7-7
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ jobs:
4040
shell: bash
4141
run: tar -czf maven-repo.tgz -C ~ .m2/repository
4242
- name: Persist Maven Repo
43-
uses: actions/upload-artifact@v1
43+
uses: actions/upload-artifact@v4
4444
with:
4545
name: maven-repo
4646
path: maven-repo.tgz
47-
- uses: actions/upload-artifact@v2
47+
- uses: actions/upload-artifact@v4
4848
if: failure()
4949
with:
5050
name: surefire-reports-build
@@ -59,7 +59,7 @@ jobs:
5959
fail-fast: false
6060
matrix:
6161
os: [ubuntu-latest, windows-latest, macos-latest]
62-
module: [core, servlet, websockets-jsr]
62+
module: [core]
6363
jdk: [11, 17, 21]
6464
openjdk_impl: [ temurin ]
6565
steps:
@@ -85,7 +85,7 @@ jobs:
8585
hostname || true
8686
- uses: actions/checkout@v2
8787
- name: Download Maven Repo
88-
uses: actions/download-artifact@v1
88+
uses: actions/download-artifact@v4
8989
with:
9090
name: maven-repo
9191
path: .
@@ -105,7 +105,7 @@ jobs:
105105
run: mvn -v
106106
- name: Run Tests
107107
run: mvn -U -B -fae test -Pproxy '-DfailIfNoTests=false' -pl ${{ matrix.module }}
108-
- uses: actions/upload-artifact@v2
108+
- uses: actions/upload-artifact@v4
109109
if: failure()
110110
with:
111111
name: surefire-reports-${{ matrix.jdk }}-${{ matrix.module }}-${{ matrix.os }}
@@ -138,7 +138,7 @@ jobs:
138138
hostname || true
139139
- uses: actions/checkout@v2
140140
- name: Download Maven Repo
141-
uses: actions/download-artifact@v1
141+
uses: actions/download-artifact@v4
142142
with:
143143
name: maven-repo
144144
path: .
@@ -157,7 +157,7 @@ jobs:
157157
run: mvn -v
158158
- name: Run Tests
159159
run: mvn -U -B -fae test ${{ matrix.proxy }} '-DfailIfNoTests=false' -pl ${{ matrix.module }} -Dtest.ipv6=true
160-
- uses: actions/upload-artifact@v2
160+
- uses: actions/upload-artifact@v4
161161
if: failure()
162162
with:
163163
name: surefire-reports-${{ matrix.jdk }}-ipv6-${{ matrix.module }}${{ matrix.proxy }}-${{ matrix.os }}

core/src/main/java/io/undertow/UndertowMessages.java

+3
Original file line numberDiff line numberDiff line change
@@ -647,4 +647,7 @@ public interface UndertowMessages {
647647
@Message(id = 208, value = "Failed to allocate resource")
648648
IOException failedToAllocateResource();
649649

650+
@Message(id = 209, value = "Protocol string was too large for the buffer. Either provide a smaller message or a bigger buffer. Protocol: %s")
651+
IllegalStateException protocolTooLargeForBuffer(String protocolString);
652+
650653
}

core/src/main/java/io/undertow/attribute/StoredResponse.java

+5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ private String extractCharset(HeaderMap headers) {
6666
if(contentType.startsWith("text/")) {
6767
return StandardCharsets.ISO_8859_1.displayName();
6868
}
69+
// json has no charset param: https://www.iana.org/assignments/media-types/application/json
70+
// the default is UTF-8: https://www.rfc-editor.org/rfc/rfc7158#section-8.1 & https://www.rfc-editor.org/rfc/rfc8259#section-8.1
71+
if(contentType.equals("application/json")) {
72+
return StandardCharsets.UTF_8.name();
73+
}
6974
return null;
7075
}
7176
return null;

core/src/main/java/io/undertow/protocols/http2/Http2Channel.java

+36-3
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,7 @@ private StreamHolder handleRstStream(int streamId, boolean receivedRst) {
12251225
resetStreamTracker.store(streamId, holder);
12261226
if(streamId % 2 == (isClient() ? 1 : 0)) {
12271227
sendConcurrentStreamsAtomicUpdater.getAndDecrement(this);
1228+
holder.sent = true;
12281229
} else {
12291230
receiveConcurrentStreamsAtomicUpdater.getAndDecrement(this);
12301231
}
@@ -1239,13 +1240,14 @@ private StreamHolder handleRstStream(int streamId, boolean receivedRst) {
12391240
//Server side originated, no input from client other than RST
12401241
//this can happen on page refresh when push happens, but client
12411242
//still has valid cache entry
1243+
//NOTE: this is specific case when its set.
12421244
holder.resetByPeer = receivedRst;
12431245
} else {
12441246
handleRstWindow();
12451247
}
12461248
}
12471249
} else if(receivedRst){
1248-
final StreamHolder resetStream = resetStreamTracker.find(streamId);
1250+
final StreamHolder resetStream = resetStreamTracker.find(streamId, true);
12491251
if(resetStream != null && resetStream.resetByPeer) {
12501252
//This means other side reset stream at some point.
12511253
//depending on peer or network latency our frames might be late and
@@ -1378,6 +1380,10 @@ private static final class StreamHolder {
13781380
* This flag is set only in case of short lived server push that was reset by remote end.
13791381
*/
13801382
boolean resetByPeer = false;
1383+
/**
1384+
* flag indicate whether our side originated. This is done for caching purposes, handlng differs.
1385+
*/
1386+
boolean sent = false;
13811387
Http2StreamSourceChannel sourceChannel;
13821388
Http2StreamSinkChannel sinkChannel;
13831389

@@ -1388,6 +1394,13 @@ private static final class StreamHolder {
13881394
StreamHolder(Http2StreamSinkChannel sinkChannel) {
13891395
this.sinkChannel = sinkChannel;
13901396
}
1397+
1398+
@Override
1399+
public String toString() {
1400+
return "StreamHolder [sourceClosed=" + sourceClosed + ", sinkClosed=" + sinkClosed + ", resetByPeer=" + resetByPeer
1401+
+ ", sent=" + sent + ", sourceChannel=" + sourceChannel + ", sinkChannel=" + sinkChannel + "]";
1402+
}
1403+
13911404
}
13921405

13931406
// cache that keeps track of streams until they can be evicted @see Http2Channel#RST_STREAM_EVICATION_TIME
@@ -1403,12 +1416,27 @@ private void store(int streamId, StreamHolder streamHolder) {
14031416
streamHolders.put(streamId, streamHolder);
14041417
entries.add(new StreamCacheEntry(streamId));
14051418
}
1406-
private StreamHolder find(int streamId) {
1419+
1420+
/**
1421+
* Method will return only sent
1422+
* @param streamId
1423+
* @return
1424+
*/
1425+
private StreamHolder find(final int streamId) {
1426+
return find(streamId, false);
1427+
}
1428+
1429+
private StreamHolder find(final int streamId, final boolean all) {
14071430
for (Iterator<StreamCacheEntry> iterator = entries.iterator(); iterator.hasNext();) {
14081431
StreamCacheEntry entry = iterator.next();
14091432
if (entry.shouldEvict()) {
14101433
iterator.remove();
14111434
StreamHolder holder = streamHolders.remove(entry.streamId);
1435+
if(!holder.sent || holder.resetByPeer) {
1436+
//if its not our end of chain, its just cached, so we only cache for purpose of
1437+
// handling eager RST
1438+
continue;
1439+
}
14121440
AbstractHttp2StreamSourceChannel receiver = holder.sourceChannel;
14131441
if(receiver != null) {
14141442
IoUtils.safeClose(receiver);
@@ -1422,7 +1450,12 @@ private StreamHolder find(int streamId) {
14221450
}
14231451
} else break;
14241452
}
1425-
return streamHolders.get(streamId);
1453+
final StreamHolder holder = streamHolders.get(streamId);
1454+
if(holder != null && (!all && !holder.sent)) {
1455+
return null;
1456+
} else {
1457+
return holder;
1458+
}
14261459
}
14271460

14281461
private Map<Integer, StreamHolder> getStreamHolders() {

0 commit comments

Comments
 (0)