1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.testsuite_jpms.main;
18
19 import io.netty.bootstrap.Bootstrap;
20 import io.netty.bootstrap.ServerBootstrap;
21 import io.netty.channel.Channel;
22 import io.netty.channel.ChannelHandler;
23 import io.netty.channel.ChannelHandlerContext;
24 import io.netty.channel.ChannelOption;
25 import io.netty.channel.EventLoopGroup;
26 import io.netty.channel.IoHandlerFactory;
27 import io.netty.channel.MultiThreadIoEventLoopGroup;
28 import io.netty.channel.epoll.EpollIoHandler;
29 import io.netty.channel.epoll.EpollServerSocketChannel;
30 import io.netty.channel.kqueue.KQueueIoHandler;
31 import io.netty.channel.kqueue.KQueueServerSocketChannel;
32 import io.netty.channel.nio.NioIoHandler;
33 import io.netty.channel.socket.ServerSocketChannel;
34 import io.netty.channel.socket.nio.NioDatagramChannel;
35 import io.netty.channel.socket.nio.NioServerSocketChannel;
36 import io.netty.channel.uring.IoUringIoHandler;
37 import io.netty.channel.uring.IoUringServerSocketChannel;
38 import io.netty.handler.codec.http3.Http3;
39 import io.netty.handler.codec.quic.InsecureQuicTokenHandler;
40 import io.netty.handler.codec.quic.QuicSslContext;
41 import io.netty.handler.codec.quic.QuicSslContextBuilder;
42 import io.netty.handler.logging.LogLevel;
43 import io.netty.handler.logging.LoggingHandler;
44 import io.netty.handler.ssl.IdentityCipherSuiteFilter;
45 import io.netty.handler.ssl.SslContext;
46 import io.netty.handler.ssl.SslHandler;
47 import io.netty.handler.ssl.SslProvider;
48 import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
49 import io.netty.pkitesting.CertificateBuilder;
50 import io.netty.pkitesting.X509Bundle;
51
52 import java.net.InetSocketAddress;
53 import java.util.concurrent.TimeUnit;
54 import java.util.stream.Collectors;
55
56 import static io.netty.handler.ssl.SslContextBuilder.forServer;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public final class HttpHelloWorldServer {
79
80 private HttpHelloWorldServer() {
81 }
82
83 public static void main(String[] args) throws Exception {
84
85 String transport = "nio";
86 boolean ssl = false;
87 SslProvider sslProvider = SslProvider.JDK;
88 boolean http3 = false;
89
90 Integer port = null;
91 for (int i = 0; i < args.length; i++) {
92 if (args[i].equals("--help")) {
93 System.out.println("usage: [options]");
94 System.out.println("--ssl");
95 System.out.println("--ssl-provider [ JDK | OPENSSL ]");
96 System.out.println("--port <port>");
97 System.out.println("--transport [ nio | kqueue | epoll | io_uring ]");
98 System.out.println("--http3");
99 System.exit(0);
100 }
101 if (args[i].equals("--ssl")) {
102 ssl = true;
103 }
104 if (args[i].equals("--ssl-provider")) {
105 if (i < args.length - 1) {
106 sslProvider = SslProvider.valueOf(args[++i]);
107 } else {
108 System.exit(1);
109 }
110 }
111 if (args[i].equals("--port")) {
112 if (i < args.length - 1) {
113 port = Integer.parseInt(args[++i]);
114 } else {
115 System.exit(1);
116 }
117 }
118 if (args[i].equals("--transport")) {
119 if (i < args.length - 1) {
120 transport = args[++i];
121 } else {
122 System.exit(1);
123 }
124 }
125 if (args[i].equals("--http3")) {
126 http3 = true;
127 }
128 }
129
130 if (port == null) {
131 port = ssl ? 8443 : 8080;
132 }
133
134 IoHandlerFactory ioHandlerFactory;
135 Class<? extends ServerSocketChannel> serverSocketChannelFactory;
136 switch (transport) {
137 case "nio":
138 ioHandlerFactory = NioIoHandler.newFactory();
139 serverSocketChannelFactory = NioServerSocketChannel.class;
140 break;
141 case "kqueue":
142 ioHandlerFactory = KQueueIoHandler.newFactory();
143 serverSocketChannelFactory = KQueueServerSocketChannel.class;
144 break;
145 case "epoll":
146 ioHandlerFactory = EpollIoHandler.newFactory();
147 serverSocketChannelFactory = EpollServerSocketChannel.class;
148 break;
149 case "io_uring":
150 ioHandlerFactory = IoUringIoHandler.newFactory();
151 serverSocketChannelFactory = IoUringServerSocketChannel.class;
152 break;
153 default:
154 System.exit(1);
155 return;
156 }
157
158 X509Bundle cert = new CertificateBuilder()
159 .subject("cn=localhost")
160 .setIsCertificateAuthority(true)
161 .buildSelfSigned();
162
163
164 EventLoopGroup group = new MultiThreadIoEventLoopGroup(ioHandlerFactory);
165 try {
166 Channel ch;
167 if (http3) {
168 QuicSslContext quicCslContext = QuicSslContextBuilder.forServer(cert.toKeyManagerFactory(), null)
169 .applicationProtocols(Http3.supportedApplicationProtocols()).build();
170 ChannelHandler codec = Http3.newQuicServerCodecBuilder()
171 .sslContext(quicCslContext)
172 .maxIdleTimeout(5000, TimeUnit.MILLISECONDS)
173 .initialMaxData(10000000)
174 .initialMaxStreamDataBidirectionalLocal(1000000)
175 .initialMaxStreamDataBidirectionalRemote(1000000)
176 .initialMaxStreamsBidirectional(100)
177 .tokenHandler(InsecureQuicTokenHandler.INSTANCE)
178 .handler(new Http3HelloWorldServerInitializer())
179 .build();
180
181 Bootstrap bs = new Bootstrap();
182 ch = bs.group(group)
183 .channel(NioDatagramChannel.class)
184 .handler(codec)
185 .bind(new InetSocketAddress(port)).sync().channel();
186 } else {
187 SslContext sslContext;
188 if (ssl) {
189 sslContext = forServer(cert.toKeyManagerFactory())
190 .sslProvider(sslProvider)
191 .protocols("TLSv1.2")
192 .trustManager(InsecureTrustManagerFactory.INSTANCE)
193 .ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
194 .sessionCacheSize(0)
195 .sessionTimeout(0)
196 .build();
197 } else {
198 sslContext = null;
199 }
200 ServerBootstrap b = new ServerBootstrap();
201 b.option(ChannelOption.SO_BACKLOG, 1024);
202 b.group(group)
203 .channel(serverSocketChannelFactory)
204 .handler(new LoggingHandler(LogLevel.INFO))
205 .childHandler(new HttpHelloWorldServerInitializer(sslContext));
206
207 ch = b.bind(port).sync().channel();
208 }
209
210 System.err.println("Open your web browser and navigate to " +
211 ((ssl || http3)? "https" : "http") + "://127.0.0.1:" + port + '/');
212
213 ch.closeFuture().sync();
214 } finally {
215 group.shutdownGracefully();
216 }
217 }
218
219 static String content(ChannelHandlerContext ctx) {
220 String modulesInfo = ModuleLayer.boot().modules().stream()
221 .map(module -> "- " + module.getName() + " " +
222 (module.getDescriptor().isAutomatic() ? "(automatic)" : ""))
223 .collect(Collectors.joining("\r\n", "Boot layer:\r\n", "\r\n"));
224
225 String channelType = ctx.channel().getClass().getName();
226
227 String sslEngineInfo = "";
228 SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
229 if (sslHandler != null) {
230 sslEngineInfo = "SSL Engine: " + sslHandler.engine().getClass().getName() + "\r\n";
231 }
232
233 return "Hello World\r\n" +
234 "Transport: " + channelType + "\r\n" +
235 sslEngineInfo +
236 modulesInfo;
237 }
238 }