Skip to content

Commit 630c5e1

Browse files
committed
Rewrote a lot of systems, added support for keep-alive
1 parent 7f9a792 commit 630c5e1

18 files changed

+743
-372
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package dev.latvian.apps.tinyserver;
2+
3+
import dev.latvian.apps.tinyserver.http.response.HTTPPayload;
4+
5+
import java.io.ByteArrayOutputStream;
6+
import java.io.IOException;
7+
import java.net.SocketTimeoutException;
8+
import java.nio.ByteBuffer;
9+
import java.nio.channels.ClosedChannelException;
10+
import java.nio.channels.SocketChannel;
11+
import java.nio.charset.StandardCharsets;
12+
import java.time.Instant;
13+
14+
public class HTTPConnection implements AutoCloseable, Runnable {
15+
public final HTTPServer<?> server;
16+
public final SocketChannel socketChannel;
17+
public final Instant createdTime;
18+
long lastActivity;
19+
private final ByteBuffer singleByte;
20+
21+
public HTTPConnection(HTTPServer<?> server, SocketChannel socketChannel, Instant createdTime) {
22+
this.server = server;
23+
this.socketChannel = socketChannel;
24+
this.createdTime = createdTime;
25+
this.singleByte = ByteBuffer.allocate(1);
26+
}
27+
28+
@Override
29+
public void run() {
30+
try {
31+
server.handleClient(this);
32+
} catch (Throwable ex) {
33+
error(ex);
34+
}
35+
}
36+
37+
@Override
38+
public void close() {
39+
try {
40+
socketChannel.shutdownInput();
41+
} catch (IOException ex) {
42+
error(ex);
43+
}
44+
45+
try {
46+
socketChannel.shutdownOutput();
47+
} catch (IOException ex) {
48+
error(ex);
49+
}
50+
51+
try {
52+
socketChannel.close();
53+
} catch (IOException ex) {
54+
error(ex);
55+
}
56+
57+
closed();
58+
}
59+
60+
public boolean isClosed() {
61+
return !socketChannel.isOpen();
62+
}
63+
64+
protected void beforeHandshake() {
65+
}
66+
67+
protected void closed() {
68+
}
69+
70+
protected void error(Throwable error) {
71+
if (!(error instanceof SocketTimeoutException || error instanceof ClosedChannelException)) {
72+
error.printStackTrace();
73+
}
74+
}
75+
76+
@Override
77+
public String toString() {
78+
return socketChannel.socket().getPort() + " @ " + HTTPPayload.DATE_TIME_FORMATTER.format(createdTime);
79+
}
80+
81+
public void readBytes(byte[] bytes) throws IOException {
82+
var buf = ByteBuffer.wrap(bytes);
83+
socketChannel.read(buf);
84+
buf.flip();
85+
buf.get(bytes);
86+
}
87+
88+
public byte readByte() throws IOException {
89+
singleByte.clear();
90+
socketChannel.read(singleByte);
91+
singleByte.flip();
92+
return singleByte.get();
93+
}
94+
95+
public short readShort() throws IOException {
96+
var buf = ByteBuffer.allocate(2);
97+
socketChannel.read(buf);
98+
buf.flip();
99+
return buf.getShort();
100+
}
101+
102+
public int readInt() throws IOException {
103+
var buf = ByteBuffer.allocate(4);
104+
socketChannel.read(buf);
105+
buf.flip();
106+
return buf.getInt();
107+
}
108+
109+
public long readLong() throws IOException {
110+
var buf = ByteBuffer.allocate(8);
111+
socketChannel.read(buf);
112+
buf.flip();
113+
return buf.getLong();
114+
}
115+
116+
public String readCRLF() throws IOException {
117+
var bytes = new ByteArrayOutputStream();
118+
119+
while (true) {
120+
int b = readByte();
121+
122+
if (b == '\r') {
123+
var r = readByte();
124+
125+
if (r == '\n') {
126+
break;
127+
} else {
128+
bytes.write('\r');
129+
bytes.write(r);
130+
}
131+
} else {
132+
bytes.write(b);
133+
}
134+
}
135+
136+
return bytes.toString(StandardCharsets.UTF_8);
137+
}
138+
}

0 commit comments

Comments
 (0)