From 201a39a56bc8e3572356451fcad9526e6234a0b2 Mon Sep 17 00:00:00 2001 From: Alexander Lehmann Date: Sun, 6 Aug 2023 15:28:14 +0200 Subject: [PATCH] first version, gemini-socks5 proxy --- .editorconfig | 11 + .gitignore | 188 ++++++++++++++++++ README.adoc | 32 +++ pom.xml | 137 +++++++++++++ .../gemini/gemini_proxy/MainVerticle.java | 102 ++++++++++ .../gemini/gemini_proxy/TestMainVerticle.java | 23 +++ 6 files changed, 493 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 README.adoc create mode 100644 pom.xml create mode 100644 src/main/java/cx/lehmann/gemini/gemini_proxy/MainVerticle.java create mode 100644 src/test/java/cx/lehmann/gemini/gemini_proxy/TestMainVerticle.java diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3003493 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# EditorConfig is awesome: https://EditorConfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +end_of_line = lf +insert_final_newline = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4cb41e9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,188 @@ +### Vert.x ### +.vertx/ + +### Eclipse ### + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +### Intellij+iml ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-buildTool-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-buildTool.properties +fabric.properties + +### Intellij+iml Patch ### +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +### macOS ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Maven ### +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties + +# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) +!/.mvn/wrapper/maven-wrapper.jar + +### Gradle ### +.gradle +/buildTool/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +### NetBeans ### +nbproject/private/ +buildTool/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +.classpath +.project diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..4c4af45 --- /dev/null +++ b/README.adoc @@ -0,0 +1,32 @@ += Gemini + +image:https://img.shields.io/badge/vert.x-4.4.1-purple.svg[link="https://vertx.io"] + +This application was generated using http://start.vertx.io + +== Building + +To launch your tests: +``` +./mvnw clean test +``` + +To package your application: +``` +./mvnw clean package +``` + +To run your application: +``` +./mvnw clean compile exec:java +``` + +== Help + +* https://vertx.io/docs/[Vert.x Documentation] +* https://stackoverflow.com/questions/tagged/vert.x?sort=newest&pageSize=15[Vert.x Stack Overflow] +* https://groups.google.com/forum/?fromgroups#!forum/vertx[Vert.x User Group] +* https://discord.gg/6ry7aqPWXy[Vert.x Discord] +* https://gitter.im/eclipse-vertx/vertx-users[Vert.x Gitter] + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..d7bce5d --- /dev/null +++ b/pom.xml @@ -0,0 +1,137 @@ + + + 4.0.0 + + cx.lehmann.gemini + gemini-proxy + 1.0.0-SNAPSHOT + + + UTF-8 + + 3.8.1 + 3.2.4 + 2.22.2 + 3.0.0 + + 4.4.4 + 5.9.1 + + cx.lehmann.gemini.gemini_proxy.MainVerticle + io.vertx.core.Launcher + + + + + + io.vertx + vertx-stack-depchain + ${vertx.version} + pom + import + + + + + + + io.vertx + vertx-core + + + + io.vertx + vertx-junit5 + test + + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + + org.slf4j + slf4j-api + 2.0.7 + + + + org.slf4j + slf4j-simple + 2.0.7 + runtime + + + + javax.xml.bind + jaxb-api + 2.4.0-b180830.0359 + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 11 + + + + maven-shade-plugin + ${maven-shade-plugin.version} + + + package + + shade + + + + + + ${launcher.class} + ${main.verticle} + + + + + ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar + + + + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + org.codehaus.mojo + exec-maven-plugin + ${exec-maven-plugin.version} + + io.vertx.core.Launcher + + run + ${main.verticle} + + + + + + + + diff --git a/src/main/java/cx/lehmann/gemini/gemini_proxy/MainVerticle.java b/src/main/java/cx/lehmann/gemini/gemini_proxy/MainVerticle.java new file mode 100644 index 0000000..bd0b671 --- /dev/null +++ b/src/main/java/cx/lehmann/gemini/gemini_proxy/MainVerticle.java @@ -0,0 +1,102 @@ +package cx.lehmann.gemini.gemini_proxy; + +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Promise; +import io.vertx.core.net.NetClient; +import io.vertx.core.net.NetClientOptions; +import io.vertx.core.net.NetServerOptions; +import io.vertx.core.net.NetSocket; +import io.vertx.core.net.PemKeyCertOptions; +import io.vertx.core.net.ProxyOptions; +import io.vertx.core.net.ProxyType; +import io.vertx.core.streams.Pump; + +public class MainVerticle extends AbstractVerticle { + + private final static Logger log = LoggerFactory.getLogger(MainVerticle.class); + + @Override + public void start(Promise startPromise) throws Exception { + NetServerOptions serverOptions=new NetServerOptions(); + NetClientOptions clientOptions=new NetClientOptions(); + + ProxyOptions proxyOptions=new ProxyOptions(); + proxyOptions.setHost("localhost") + .setPort(9150) + .setType(ProxyType.SOCKS5); + + clientOptions.setProxyOptions(proxyOptions) + .setTrustAll(true) + .setSsl(true); + + NetClient client=vertx.createNetClient(clientOptions); + + vertx.exceptionHandler(ex -> {ex.printStackTrace();}); + + String certPath="c:/temp/cert.pem"; +// String certPath="/home/lehmann/gemini-chat/cert.pem"; + + serverOptions.setPemKeyCertOptions(new PemKeyCertOptions() + .setCertPath(certPath) + .setKeyPath(certPath)) + .setSsl(true); + + vertx.createNetServer(serverOptions).connectHandler(conn -> { + conn.handler(event -> { + System.out.println(new Date().toString()+" accepted connection:"+conn.remoteAddress()); + String line=event.toString("UTF-8"); + if(!line.endsWith("\r\n")) { + conn.write("40 format error\r\n"); + conn.close(); + } else { + String url=line.substring(0, line.length()-2); + + if(!url.startsWith("gemini://")) { + conn.write("40 format error\r\n"); + conn.close(); + } + else { + String url1=url.substring(9); + log.info("url:{}",url1); + int firstSlash=url1.indexOf('/'); + String hostname=url1.substring(0,firstSlash); + String path=url1.substring(firstSlash); + client.connect(1965, hostname, res -> { + if(res.succeeded()) { + NetSocket clientConn = res.result(); + clientConn.write(url+"\r\n"); + Pump pump=Pump.pump(clientConn, conn).start(); + clientConn.closeHandler(v -> { + pump.stop(); + conn.close(); + }); + conn.closeHandler(v -> { + pump.stop(); + clientConn.close(); + }); + } else { + log.info("connection failed", res.cause()); + conn.write("40 connection error"+res.cause().getMessage()+"\r\n"); + conn.close(); + } + }); + } + } + } + ); + }).listen(1965, server -> { + if (server.succeeded()) { + startPromise.complete(); + System.out.println("Gemini proxy started on port 1965 at "+new Date().toString()); + } else { + server.cause().printStackTrace(); + startPromise.fail(server.cause()); + } + }); + } +} diff --git a/src/test/java/cx/lehmann/gemini/gemini_proxy/TestMainVerticle.java b/src/test/java/cx/lehmann/gemini/gemini_proxy/TestMainVerticle.java new file mode 100644 index 0000000..55b8a31 --- /dev/null +++ b/src/test/java/cx/lehmann/gemini/gemini_proxy/TestMainVerticle.java @@ -0,0 +1,23 @@ +package cx.lehmann.gemini.gemini_proxy; + +//import io.vertx.core.Vertx; +//import io.vertx.junit5.VertxExtension; +//import io.vertx.junit5.VertxTestContext; +//import org.junit.jupiter.api.BeforeEach; +//import org.junit.jupiter.api.Test; +//import org.junit.jupiter.api.extension.ExtendWith; + +//@ExtendWith(VertxExtension.class) +public class TestMainVerticle { + +// @BeforeEach +// void deploy_verticle(Vertx vertx, VertxTestContext testContext) { +// vertx.deployVerticle(new MainVerticle(), testContext.succeeding(id -> testContext.completeNow())); +// } +// +// @Test +// void verticle_deployed(Vertx vertx, VertxTestContext testContext) throws Throwable { +// vertx.setTimer(10000000, l -> +// testContext.completeNow()); +// } +}