Blob


1 package com.omarpolo.gemini;
3 import javax.net.ssl.*;
4 import java.io.*;
5 import java.net.*;
6 import java.security.KeyManagementException;
7 import java.security.NoSuchAlgorithmException;
8 import java.security.SecureRandom;
9 import java.security.cert.X509Certificate;
10 import java.util.Collections;
11 import java.util.NoSuchElementException;
12 import java.util.Scanner;
14 public class Request implements AutoCloseable {
16 private final BufferedReader in;
17 private final PrintWriter out;
18 private final SSLSocket sock;
20 private final int code;
21 private final String meta;
23 public static class DummyManager extends X509ExtendedTrustManager {
25 @Override
26 public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) {
27 }
29 @Override
30 public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) {
31 }
33 @Override
34 public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) {
35 }
37 @Override
38 public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) {
39 }
41 @Override
42 public void checkClientTrusted(X509Certificate[] chain, String authType) {
43 }
45 @Override
46 public void checkServerTrusted(X509Certificate[] chain, String authType) {
47 }
49 @Override
50 public X509Certificate[] getAcceptedIssuers() {
51 return null;
52 }
53 }
55 public static class MalformedResponse extends Exception {}
57 public Request(String uri) throws IOException, MalformedResponse, URISyntaxException {
58 this(new URI(uri));
59 }
61 public Request(URL url) throws IOException, MalformedResponse {
62 this(url.getHost(), url.getPort(), url.toString());
63 }
65 public Request(URI uri) throws IOException, MalformedResponse {
66 this(uri.getHost(), uri.getPort(), uri.toString());
67 }
69 public Request(String host, int port, URL req) throws IOException, MalformedResponse {
70 this(host, port, req.toString());
71 }
73 public Request(String host, int port, URI req) throws IOException, MalformedResponse {
74 this(host, port, req.toString());
75 }
77 public Request(String host, int port, String req) throws IOException, MalformedResponse {
78 if (port == -1) {
79 port = 1965;
80 }
82 sock = connect(host, port);
84 var outStream = sock.getOutputStream();
85 out = new PrintWriter(
86 new BufferedWriter(new OutputStreamWriter(outStream)));
88 out.print(req);
89 out.print("\r\n");
90 out.flush();
92 var inStream = sock.getInputStream();
93 in = new BufferedReader(new InputStreamReader(inStream));
95 var reply = in.readLine();
97 if (reply.length() > 1027) {
98 throw new MalformedResponse();
99 }
101 var s = new Scanner(new StringReader(reply));
102 try {
103 code = s.nextInt();
104 s.skip(" ");
105 meta = s.nextLine();
106 } catch (NoSuchElementException e) {
107 throw new MalformedResponse();
111 private SSLSocket connect(String host, int port) throws IOException {
112 try {
113 var params = new SSLParameters();
114 params.setServerNames(Collections.singletonList(new SNIHostName(host)));
116 var ctx = SSLContext.getInstance("TLS");
117 ctx.init(null, new DummyManager[]{new DummyManager()}, new SecureRandom());
118 var factory = (SSLSocketFactory) ctx.getSocketFactory();
120 var socket = (SSLSocket) factory.createSocket(host, port);
121 socket.setSSLParameters(params);
122 socket.startHandshake();
123 return socket;
124 } catch (NoSuchAlgorithmException | KeyManagementException e) {
125 throw new RuntimeException("Unexpected failure", e);
129 public int getCode() {
130 return code;
133 public String getMeta() {
134 return meta;
137 public BufferedReader body() {
138 return in;
141 public void close() throws IOException {
142 in.close();
143 out.close();
144 sock.close();