diff --git a/bench/run.sh b/bench/run.sh index f72e8f4..c21dbfa 100644 --- a/bench/run.sh +++ b/bench/run.sh @@ -48,7 +48,7 @@ echo -e "\nTesting.." $JMETER -n -t bench/test.jmx -Jhost=127.0.0.1 -Jt=60 -Jc=10 -Jport=8080 -Jout=out/$1.csv echo -e "\n launch http2 bench" -h2load -v -c 10 -t 10 -m 10 -D 60 --warm-up-time=10 http://127.0.0.1:8080/test > out/$1.log +h2load -c 10 -t 10 -m 10 -D 60 --warm-up-time=10 http://127.0.0.1:8080/test > out/$1.log ${1}_stop sleep 10 diff --git a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Headers.java b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Headers.java index 8b19280..1a9e2d7 100644 --- a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Headers.java +++ b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Headers.java @@ -150,7 +150,7 @@ public static void writeInt(Buffers out, int p, int n, int v) throws Interrupted * @throws InterruptedException */ public void writeHeader(Buffers out, String name, String value) throws InterruptedException { - int o = 0; + int o = -1; for (int i = 0; i < TABLE.length; i++) { Entry e = TABLE[i]; if (e.name.equals(name)) { @@ -158,24 +158,24 @@ public void writeHeader(Buffers out, String name, String value) throws Interrupt writeInt(out, 0b10000000, 7, i + 1); return; } - if (o == 0) + if (o == -1) o = i; } } int i = TABLE.length; for (Entry e : dynamic) { - i++; if (e.name.equals(name)) { if (e.value.equals(value)) { writeInt(out, 0b10000000, 7, i + 1); return; } - if (o == 0) + if (o == -1) o = i; } + i++; } - writeInt(out, 0b01000000, 6, o < 0 ? 0 : o); + writeInt(out, 0b01000000, 6, o < 0 ? 0 : o + 1); if (o < 0) writeData(out, name); writeData(out, value); @@ -247,6 +247,8 @@ private static String readData(InputStream in) throws IOException { private static void writeData(Buffers out, String value) throws InterruptedException { byte[] bytes = value.getBytes(StandardCharsets.US_ASCII); + // TODO huffman + writeInt(out, 0, 7, bytes.length); out.write(bytes); } diff --git a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Processor.java b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Processor.java index b4f9ee0..d84e13c 100644 --- a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Processor.java +++ b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Processor.java @@ -154,7 +154,6 @@ private void readFrame(Buffers buf) throws InterruptedException { int type = b[3]; int flags = b[4]; int id = (b[5] & 0x7f) << 24 | (b[6] & 0xff) << 16 | (b[7] & 0xff) << 8 | (b[8] & 0xff); - logger.debug("{} {} {} {}", size, type, flags, id); if (wantContinuation && type != 9 || !wantContinuation && type == 9) { goaway(PROTOCOL_ERROR); @@ -168,6 +167,7 @@ private void readFrame(Buffers buf) throws InterruptedException { return; } + logger.debug("{}: read {}", this, b.getClass().getSimpleName()); r = b.build(this, size, flags, id, buf); } @@ -186,37 +186,37 @@ public void goaway(int err) throws InterruptedException { co.pendingWrite.write(f); co.flush(); } + logger.debug("{}: send GOAWAY {}", this, error(err)); } - @SuppressWarnings("resource") public void sendHeaders(int id, ServletResponseImpl res) throws InterruptedException { byte[] f = new byte[9]; Buffers out = new Buffers(); int type = 1; - synchronized (headers) { - headers.writeHeader(out, ":status", Integer.toString(res.getStatus())); - for (String n : res.getHeaderNames()) { - for (String v : res.getHeaders(n)) { - headers.writeHeader(out, n, v); - - if (out.length() >= frame) { - formatFrame(f, out.length(), type, 0, id); - type = 9; - synchronized (co) { - co.pendingWrite.write(f); - out.read(co.pendingWrite, frame, false); - co.flush(); + synchronized (co) { + synchronized (headers) { + headers.writeHeader(out, ":status", Integer.toString(res.getStatus())); + for (String n : res.getHeaderNames()) { + for (String v : res.getHeaders(n)) { + headers.writeHeader(out, n, v); + + if (out.length() >= frame) { + formatFrame(f, out.length(), type, 0, id); + type = 9; + synchronized (co) { + co.pendingWrite.write(f); + out.read(co.pendingWrite, frame, false); + co.flush(); + } } } } } - } - int flag = 0x4; - Http2ServletOutput sout = (Http2ServletOutput) res.getRawStream(); - if (sout == null || sout.isDone()) - flag |= 0x1; - formatFrame(f, out.length(), type, flag, id); - synchronized (co) { + int flag = 0x4; + Http2ServletOutput sout = (Http2ServletOutput) res.getRawStream(); + if (sout == null || sout.isDone()) + flag |= 0x1; + formatFrame(f, out.length(), type, flag, id); co.pendingWrite.write(f); out.read(co.pendingWrite, -1, false); co.flush(); diff --git a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Stream.java b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Stream.java index 7fff6d4..bfafae1 100644 --- a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Stream.java +++ b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/Http2Stream.java @@ -6,16 +6,12 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import jakarta.servlet.ServletInputStream; import unknow.server.servlet.HttpWorker; import unknow.server.servlet.impl.AbstractServletOutput; import unknow.server.servlet.utils.PathUtils; public class Http2Stream extends HttpWorker implements Http2FlowControl { - private static final Logger logger = LoggerFactory.getLogger(Http2Stream.class); private final int id; private final Http2Processor p; @@ -41,7 +37,6 @@ public Http2Stream(Http2Processor p, int id, int window) { } public final void addHeader(String name, String value) { - logger.debug("addHeader {}: {}", name, value); if (name.charAt(0) != ':') { req.addHeader(name, value); return; diff --git a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/frame/FrameGoAway.java b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/frame/FrameGoAway.java index 88f41d1..1bdb766 100644 --- a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/frame/FrameGoAway.java +++ b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/frame/FrameGoAway.java @@ -37,7 +37,7 @@ public FrameReader process(Buffers buf) throws InterruptedException { lastId = (b[0] & 0x7f) << 24 | (b[1] & 0xff) << 16 | (b[2] & 0xff) << 8 | (b[3] & 0xff); buf.read(b, 0, 4, false); - int err = (b[0] & 0x7f) << 24 | (b[1] & 0xff) << 16 | (b[2] & 0xff) << 8 | (b[3] & 0xff); + int err = (b[0] & 0xff) << 24 | (b[1] & 0xff) << 16 | (b[2] & 0xff) << 8 | (b[3] & 0xff); logger.info("goaway last: {} err: {}", lastId, Http2Processor.error(err)); size -= 8; p.closing = true; diff --git a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/frame/FrameSettings.java b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/frame/FrameSettings.java index 0c57758..aaf34f6 100644 --- a/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/frame/FrameSettings.java +++ b/unknow-server-servlet/src/main/java/unknow/server/servlet/http2/frame/FrameSettings.java @@ -1,14 +1,19 @@ package unknow.server.servlet.http2.frame; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import unknow.server.servlet.HttpConnection; import unknow.server.servlet.http2.Http2Processor; import unknow.server.util.io.Buffers; public class FrameSettings extends FrameReader { + private static final Logger logger = LoggerFactory.getLogger(FrameSettings.class); public static final FrameBuilder BUILDER = (p, size, flags, id, buf) -> { if ((flags & 0x1) == 1) { if (size != 0) p.goaway(Http2Processor.FRAME_SIZE_ERROR); + logger.trace("{}: settings ack", p); return null; } if (id != 0) { @@ -40,11 +45,13 @@ public final FrameReader process(Buffers buf) throws InterruptedException { switch (i) { case 1: + logger.trace("{}: SETTINGS_HEADER_TABLE_SIZE {}", p, v); synchronized (p.headers) { p.headers.setMax(v); } break; case 2: + logger.trace("{}: SETTINGS_ENABLE_PUSH {}", p, v); if (v < 0 || v > 1) { p.goaway(Http2Processor.PROTOCOL_ERROR); return null; @@ -52,12 +59,15 @@ public final FrameReader process(Buffers buf) throws InterruptedException { // allowPush = v == 1; break; case 3: + logger.trace("{}: SETTINGS_MAX_CONCURRENT_STREAMS {}", p, v); // concurrent = v; break; case 4: + logger.trace("{}: SETTINGS_INITIAL_WINDOW_SIZE {}", p, v); p.initialWindow = v; break; case 5: + logger.trace("{}: SETTINGS_MAX_FRAME_SIZE {}", p, v); if (v < 16384 || v > 16777215) { p.goaway(Http2Processor.PROTOCOL_ERROR); return null; @@ -65,6 +75,7 @@ public final FrameReader process(Buffers buf) throws InterruptedException { p.frame = v; break; case 6: + logger.trace("{}: SETTINGS_MAX_HEADER_LIST_SIZE {}", p, v); // headerList = v; break; default: