Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
suuft (valeriy) committed Feb 19, 2023
0 parents commit 2586a0e
Show file tree
Hide file tree
Showing 17 changed files with 404 additions and 0 deletions.
40 changes: 40 additions & 0 deletions .github/DEPEND.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## | `Shadowsocks (Outline VPN) api wrapper`
Here is how to add this sdk depending on your project.
### | `Gradle`:
If you use Gradle with Groovy, then here is an example of adding dependencies:
```groovy
repositories {
// other repositories
maven {
name = "clojars.org"
url = uri("https://repo.clojars.org")
}
}
dependencies {
// other depend
implementation 'works.naifu:shadowsocks-java-wrapper:1.0.0'
}
```

### | `Maven`:

Repository:

```xml
<repository>
<id>clojars.org</id>
<url>https://repo.clojars.org</url>
</repository>
```

Depend:

```xml

<dependency>
<groupId>works.naifu</groupId>
<artifactId>shadowsocks-java-wrapper</artifactId>
<version>1.0.0</version>
</dependency>
```
2 changes: 2 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github: suuft
custom: https://www.buymeacoffee.com/suuft
17 changes: 17 additions & 0 deletions .github/USAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## | `Shadowsocks (Outline VPN) api wrapper`
*You can found full example-code in:* [LINK](https://github.com/suuft/shadowsocks-java-wrapper/blob/master/src/test/java/net/suuft/shadowsocks)

First initialize the instance of ShadowSocks Wrapper:
```java
ShadowsocksWrapper shadowsocks = ShadowsocksFactory
.createWrapper(API_URL);
```

Cool! Now you can work with the outline api, for example, create a key, and output a link to the console:

```java
int newKeyId = shadowsocks.generateKey().id;
System.out.println("new key: " + newKeyId);
```

Okay, just check it out.
7 changes: 7 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Copyright 2023 suuft (aka: Juhani Layne, Valeriy Shushpanov)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## | `Shadowsocks (Outline VPN) api wrapper`
Library for working with ShadowSocks remote servers (Outline VPN API) in Java.
### | `Links`:
* [Add as Depend](https://github.com/suuft/shadowsocks-java-wrapper/blob/master/.github/DEPEND.md)
* [Usage Example](https://github.com/suuft/shadowsocks-java-wrapper/blob/master/.github/USAGE.md)
43 changes: 43 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
plugins {
id 'java'
id 'maven-publish'
}

group 'works.naifu'
version '1.0.0'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
mavenCentral()
maven {
name = "clojars.org"
url = uri("https://repo.clojars.org")
}
}

dependencies {
compileOnly 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'
implementation 'com.google.code.gson:gson:2.8.7'
}

publishing {
repositories {
maven {
name = "clojars"
url = uri("https://clojars.org/repo")
credentials {
username = clojarsUserName
password = clojarsDeployToken
}
}

}
publications {
gpr(MavenPublication) {
from(components.java)
}
}
}
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
rootProject.name = 'shadowsocks-java-wrapper'

13 changes: 13 additions & 0 deletions src/main/java/net/suuft/shadowsocks/ShadowsocksFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package net.suuft.shadowsocks;

import lombok.NonNull;
import lombok.experimental.UtilityClass;
import net.suuft.shadowsocks.implementation.RealShadowsocksWrapper;

@UtilityClass
public class ShadowsocksFactory {

public ShadowsocksWrapper createWrapper(@NonNull String apiAddress) {
return new RealShadowsocksWrapper(apiAddress);
}
}
21 changes: 21 additions & 0 deletions src/main/java/net/suuft/shadowsocks/ShadowsocksWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.suuft.shadowsocks;

import net.suuft.shadowsocks.model.OutlineKey;
import net.suuft.shadowsocks.model.OutlineKeyList;
import net.suuft.shadowsocks.model.OutlineServer;

/**
* Shadowsocks Java Wrapper written by suuft developer.
* Distributed by MIT License.
*/
public interface ShadowsocksWrapper {

OutlineKeyList getKeys();

OutlineKey generateKey();

boolean removeKey(int keyIdentifier);

OutlineServer getServerInformation();

}
21 changes: 21 additions & 0 deletions src/main/java/net/suuft/shadowsocks/gson/GsonUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.suuft.shadowsocks.gson;

import com.google.gson.Gson;
import lombok.Getter;
import lombok.experimental.UtilityClass;

@UtilityClass
public class GsonUtil {

@Getter
private final Gson gson = new Gson();

public String parseJson(Object object) {
return gson.toJson(object);
}

public <T> T unparseJson(String json, Class<T> clazz) {
return gson.fromJson(json, clazz);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package net.suuft.shadowsocks.implementation;

import lombok.AllArgsConstructor;
import lombok.NonNull;
import net.suuft.shadowsocks.ShadowsocksWrapper;
import net.suuft.shadowsocks.implementation.model.Response;
import net.suuft.shadowsocks.model.OutlineKey;
import net.suuft.shadowsocks.model.OutlineKeyList;
import net.suuft.shadowsocks.model.OutlineServer;

import javax.net.ssl.*;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Scanner;

import static net.suuft.shadowsocks.gson.GsonUtil.unparseJson;

/**
* Shadowsocks Java Wrapper written by suuft developer.
* Distributed by MIT License.
*/
@AllArgsConstructor
public class RealShadowsocksWrapper implements ShadowsocksWrapper {

private String apiAddress;

@Override
public OutlineKeyList getKeys() {
return unparseJson(getResponse("/access-keys", "GET", null).responseString, OutlineKeyList.class);
}

@Override
public OutlineKey generateKey() {
return unparseJson(getResponse("/access-keys", "POST", null).responseString, OutlineKey.class);
}

@Override
public boolean removeKey(int keyIdentifier) {
return getResponse("/access-keys/" + keyIdentifier, "DELETE", null).responseCode == 204;
}


@Override
public OutlineServer getServerInformation() {
return unparseJson(getResponse("/server", "GET", null).responseString, OutlineServer.class);
}

private Response getResponse(@NonNull String requestAddress, @NonNull String method, String writableJson) {
try {
URL url = new URL(apiAddress + requestAddress);

HttpsURLConnection httpConn = (HttpsURLConnection) url.openConnection();

httpConn.setRequestMethod(method);
removeSSLVerifier(httpConn);

if (writableJson != null) {
httpConn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
writer.write(writableJson);
writer.flush();
writer.close();
httpConn.getOutputStream().close();
}

InputStream responseStream = httpConn.getResponseCode() / 100 == 2
? httpConn.getInputStream()
: httpConn.getErrorStream();
Scanner s = new Scanner(responseStream).useDelimiter("\\A");
String response = s.hasNext() ? s.next() : "";

return new Response(httpConn.getResponseCode(), response);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

private void removeSSLVerifier(@NonNull HttpsURLConnection connection) {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}

@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}

@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
}
};

SSLContext sc = null;
try {
sc = SSLContext.getInstance("SSL");
} catch (NoSuchAlgorithmException e) {
System.out.println(e.getMessage());
}
try {
sc.init(null, trustAllCerts, new java.security.SecureRandom());
} catch (KeyManagementException e) {
System.out.println(e.getMessage());
}
connection.setSSLSocketFactory(sc.getSocketFactory());

HostnameVerifier validHosts = new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
};

connection.setHostnameVerifier(validHosts);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.suuft.shadowsocks.implementation.model;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.experimental.FieldDefaults;

/**
* Shadowsocks Java Wrapper written by suuft developer.
* Distributed by MIT License.
*/
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PUBLIC)
public class Response {
int responseCode;
String responseString;
}
15 changes: 15 additions & 0 deletions src/main/java/net/suuft/shadowsocks/model/LimitModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package net.suuft.shadowsocks.model;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.experimental.FieldDefaults;

/**
* Shadowsocks Java Wrapper written by suuft developer.
* Distributed by MIT License.
*/
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PUBLIC)
public class LimitModel {
long bytes;
}
21 changes: 21 additions & 0 deletions src/main/java/net/suuft/shadowsocks/model/OutlineKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.suuft.shadowsocks.model;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.experimental.FieldDefaults;

/**
* Shadowsocks Java Wrapper written by suuft developer.
* Distributed by MIT License.
*/
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PUBLIC)
public class OutlineKey {
int id;
String name;
String password;
int port;
String method;
String accessUrl;
// int used_bytes;
}
17 changes: 17 additions & 0 deletions src/main/java/net/suuft/shadowsocks/model/OutlineKeyList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package net.suuft.shadowsocks.model;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.experimental.FieldDefaults;

import java.util.List;

/**
* Shadowsocks Java Wrapper written by suuft developer.
* Distributed by MIT License.
*/
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PUBLIC)
public class OutlineKeyList {
List<OutlineKey> accessKeys;
}
Loading

0 comments on commit 2586a0e

Please sign in to comment.