diff --git a/pom.xml b/pom.xml
index b3a15d5..ab29cb7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,10 +58,6 @@
${junit-jupiter.version}
test
-
- io.netty
- netty-tcnative-boringssl-static
-
org.slf4j
diff --git a/src/main/java/cx/lehmann/gemini/gemini/MainVerticle.java b/src/main/java/cx/lehmann/gemini/gemini/MainVerticle.java
index 87dc1a9..97b2fc9 100644
--- a/src/main/java/cx/lehmann/gemini/gemini/MainVerticle.java
+++ b/src/main/java/cx/lehmann/gemini/gemini/MainVerticle.java
@@ -41,18 +41,18 @@ public class MainVerticle extends AbstractVerticle {
List clients=new ArrayList<>();
-// X509TrustManager tm=new MyTrustManager();
-
+ // X509TrustManager tm=new MyTrustManager();
+
@Override
public void start(Promise startPromise) throws Exception {
NetServerOptions options=new NetServerOptions();
vertx.exceptionHandler(ex -> {ex.printStackTrace();});
-
+
// String certPath="c:/temp/cert.pem";
String certPath="/home/lehmann/gemini-chat/cert.pem";
-
-// TrustOptions trustOptions=new MyTrustOptions(vertx);
+
+ // TrustOptions trustOptions=new MyTrustOptions(vertx);
TrustManagerFactory trustMgrFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keystore=KeyStore.getInstance("JKS");
@@ -61,26 +61,26 @@ public class MainVerticle extends AbstractVerticle {
TrustManager tms[] = trustMgrFactory.getTrustManagers();
TrustManager tm=tms[0];
-
+
TrustManager trustManager = new MyTrustManager(tm);
options.setPemKeyCertOptions(new PemKeyCertOptions()
.setCertPath(certPath)
.setKeyPath(certPath))
.setSsl(true)
-// .setTrustOptions(trustOptions)
- .setTrustOptions(TrustOptions.wrap(trustManager))
+ // .setTrustOptions(trustOptions)
+ .setTrustOptions(TrustOptions.wrap(trustManager))
-// .setOpenSslEngineOptions(new OpenSSLEngineOptions())
+ // .setOpenSslEngineOptions(new OpenSSLEngineOptions())
.setClientAuth(ClientAuth.REQUEST)
- ;
+ ;
+
+ // SSLContext sc = SSLContext.getInstance("SSL");
+ // sc.init(null, new X509TrustManager[] { tm }, null);
+ // HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
-// SSLContext sc = SSLContext.getInstance("SSL");
-// sc.init(null, new X509TrustManager[] { tm }, null);
-// HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
-
vertx.createNetServer(options).connectHandler(conn -> {
conn.handler(event -> {
- System.out.println(new Date().toString()+"accepted connection:"+conn.remoteAddress());
+ System.out.println(new Date().toString()+" accepted connection:"+conn.remoteAddress());
String url=event.toString("UTF-8");
if(!url.endsWith("\r\n")) {
conn.write("40 format error\r\n");
@@ -89,17 +89,34 @@ public class MainVerticle extends AbstractVerticle {
url=url.substring(0, url.length()-2);
System.out.println("url:"+url);
String path=url.substring(9);
- if(path.indexOf('/')>=0) {
- path=path.substring(path.indexOf('/'));
- } else {
- path="";
- }
+ if(path.indexOf('/')>=0) {
+ path=path.substring(path.indexOf('/'));
+ } else {
+ path="";
+ }
System.out.println("path:"+path);
- if(path.equals("")) {
- conn.write("30 gemini://gemini.lehmann.cx:11965/\r\n");
- conn.close();
- }
- else if(path.startsWith("/post")) {
+ if(path.equals("")) {
+ conn.write("30 gemini://gemini.lehmann.cx:11965/\r\n");
+ conn.close();
+ }
+ else if(path.equals("/")) {
+ conn.write("20 text/gemini\r\n");
+ conn.write("# a very simple chat server\n");
+ conn.write("the chat page loads indefintely (until the connection breaks at least)\n");
+ conn.write("and shows chat messages sent by other users\n");
+ conn.write("messages can be sent via the /post url and use the client certificate to authenticate\n");
+ conn.write("currently the sha256 hash of the client cert is used as user-id\n");
+ conn.write("\n");
+ conn.write("the source code for the server is at\n");
+ conn.write("=> https://tildegit.org/alexlehm/vertx-gemini-server\n");
+ conn.write("the author of this chat is reachable via\n");
+ conn.write("=> gemini://gemini.lehmann.cx/\n");
+ conn.write("\n");
+ conn.write("click on the link to get started\n");
+ conn.write("=> /chat\n");
+ conn.close();
+ }
+ else if(path.startsWith("/post")) {
System.out.println("post");
try {
List certs = conn.peerCertificates();
@@ -115,55 +132,66 @@ public class MainVerticle extends AbstractVerticle {
conn.write("message was sent\n");
conn.write("=> /post post another message\n");
- String decodedMessage;
- try {
- decodedMessage=URLDecoder.decode(message, "utf-8");
- }
- catch(UnsupportedEncodingException ex) {
- decodedMessage="error";
- }
+ String decodedMessage;
+ try {
+ decodedMessage=URLDecoder.decode(message, "utf-8");
+ }
+ catch(UnsupportedEncodingException ex) {
+ decodedMessage="error";
+ }
- String quotedMessage=decodedMessage.replace("\n", "\n ");
+ String quotedMessage=decodedMessage.replace("\n", "\n ");
- for (NetSocket socket:clients) {
+ for (NetSocket socket:clients) {
socket.write(clientHash+":"+quotedMessage+"\n");
}
}
} catch (SSLPeerUnverifiedException | CertificateEncodingException | NoSuchAlgorithmException ex) {
-// ex.printStackTrace();
+ // ex.printStackTrace();
conn.write("60 cert required\r\n");
}
conn.close();
} else {
System.out.println("conn2");
+ for (NetSocket socket:clients) {
+ socket.write("one client connected. count is "+(clients.size()+1)+"\n");
+ }
clients.add(conn);
conn.write("20 text/gemini\r\n");
conn.write("to post messages, go to\n");
conn.write("=> post post page\n");
conn.write("preferably in a new window\n");
+ conn.write("currently "+clients.size()+" reading clients are connected\n");
conn.write("chat start\n");
+ conn.closeHandler(v -> {
+ System.out.println("a client closed");
+ clients.remove(conn);
+ for (NetSocket socket:clients) {
+ socket.write("one client disconnected. count is "+clients.size()+"\n");
+ }
+ });
}
}
}
- );
- }).listen(11965, server -> {
- if (server.succeeded()) {
- startPromise.complete();
- System.out.println("Gemini server started on port 11965 at "+new Date().toString());
- } else {
- server.cause().printStackTrace();
- startPromise.fail(server.cause());
- }
- });
- }
+ );
+ }).listen(11965, server -> {
+ if (server.succeeded()) {
+ startPromise.complete();
+ System.out.println("Gemini server started on port 11965 at "+new Date().toString());
+ } else {
+ server.cause().printStackTrace();
+ startPromise.fail(server.cause());
+ }
+ });
+ }
- private static String getThumbprint(X509Certificate cert)
- throws NoSuchAlgorithmException, CertificateEncodingException {
- MessageDigest md = MessageDigest.getInstance("SHA-256");
- byte[] der = cert.getEncoded();
- md.update(der);
- byte[] digest = md.digest();
- String digestHex = DatatypeConverter.printHexBinary(digest);
- return digestHex.toLowerCase();
- }
+ private static String getThumbprint(X509Certificate cert)
+ throws NoSuchAlgorithmException, CertificateEncodingException {
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ byte[] der = cert.getEncoded();
+ md.update(der);
+ byte[] digest = md.digest();
+ String digestHex = DatatypeConverter.printHexBinary(digest);
+ return digestHex.toLowerCase();
+ }
}
diff --git a/src/main/java/cx/lehmann/gemini/gemini/MyTrustManager.java b/src/main/java/cx/lehmann/gemini/gemini/MyTrustManager.java
new file mode 100644
index 0000000..d1094ce
--- /dev/null
+++ b/src/main/java/cx/lehmann/gemini/gemini/MyTrustManager.java
@@ -0,0 +1,56 @@
+/**
+ *
+ */
+package cx.lehmann.gemini.gemini;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * @author Alexander Lehmann
+ *
+ */
+public class MyTrustManager implements X509TrustManager {
+
+// private final Logger LOGGER=LoggerFactory.getLogger(this.getClass());
+
+ final X509TrustManager tm;
+
+ /**
+ * @param tm
+ */
+ public MyTrustManager(TrustManager tm) {
+ this.tm=(X509TrustManager)tm;
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+// LOGGER.info("checkClientTrusted");
+ System.out.println("checkClientTrusted");
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+// LOGGER.info("checkServerTrusted");
+ System.out.println("checkServerTrusted");
+ }
+
+// X509Certificate certs[]= {};
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+// LOGGER.info("getAcceptedIssuers");
+ System.out.println("getAcceptedIssuers");
+
+// Exception ex=new Exception();
+
+// ex.printStackTrace();
+
+ return tm.getAcceptedIssuers();
+ }
+
+
+}