OCT 1. 初始化代码仓库
|
@ -0,0 +1,15 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
|
@ -0,0 +1,3 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
|
@ -0,0 +1,117 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
|
@ -0,0 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxProjectSettings">
|
||||
<option name="commitMessageIssueKeyValidationOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
<option name="commitMessageValidationEnabledOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="GRADLE" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="jbr-17" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,10 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
|
@ -0,0 +1,9 @@
|
|||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,48 @@
|
|||
plugins {
|
||||
id("com.android.application")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.sccproxy"
|
||||
compileSdk = 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.example.sccproxy"
|
||||
minSdk = 24
|
||||
targetSdk = 33
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path = file("src/main/cpp/CMakeLists.txt")
|
||||
version = "3.22.1"
|
||||
}
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("com.google.android.material:material:1.8.0")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,26 @@
|
|||
package com.example.sccproxy;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("com.example.sccproxy", appContext.getPackageName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Sccproxy"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,40 @@
|
|||
# For more information about using CMake with Android Studio, read the
|
||||
# documentation: https://d.android.com/studio/projects/add-native-code.html.
|
||||
# For more examples on how to use CMake, see https://github.com/android/ndk-samples.
|
||||
|
||||
# Sets the minimum CMake version required for this project.
|
||||
cmake_minimum_required(VERSION 3.22.1)
|
||||
|
||||
# Declares the project name. The project name can be accessed via ${ PROJECT_NAME},
|
||||
# Since this is the top level CMakeLists.txt, the project name is also accessible
|
||||
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
|
||||
# build script scope).
|
||||
project("sccproxy")
|
||||
|
||||
INCLUDE_DIRECTORIES(include ./)
|
||||
FILE(GLOB C_HEADS ./include/*.h ./cJSON/cJSON.h)
|
||||
|
||||
# Creates and names a library, sets it as either STATIC
|
||||
# or SHARED, and provides the relative paths to its source code.
|
||||
# You can define multiple libraries, and CMake builds them for you.
|
||||
# Gradle automatically packages shared libraries with your APK.
|
||||
#
|
||||
# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define
|
||||
# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME}
|
||||
# is preferred for the same purpose.
|
||||
#
|
||||
# In order to load a library into your app from Java/Kotlin, you must call
|
||||
# System.loadLibrary() and pass the name of the library defined here;
|
||||
# for GameActivity/NativeActivity derived applications, the same library name must be
|
||||
# used in the AndroidManifest.xml file.
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED
|
||||
# List C/C++ source files with relative paths to this CMakeLists.txt.
|
||||
native-lib.cpp srcs/ipcalc.cpp srcs/scc-service.cpp srcs/tunnel-proxy.cpp cJSON/cJSON.c ${C_HEADS})
|
||||
|
||||
# Specifies libraries CMake should link to your target library. You
|
||||
# can link libraries from various origins, such as libraries defined in this
|
||||
# build script, prebuilt third-party libraries, or Android system libraries.
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
# List libraries link to the target library
|
||||
android
|
||||
log)
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef cJSON__h
|
||||
#define cJSON__h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
|
||||
#define __WINDOWS__
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
||||
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
|
||||
|
||||
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
|
||||
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
|
||||
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
|
||||
|
||||
For *nix builds that support visibility attribute, you can define similar behavior by
|
||||
|
||||
setting default visibility to hidden by adding
|
||||
-fvisibility=hidden (for gcc)
|
||||
or
|
||||
-xldscope=hidden (for sun cc)
|
||||
to CFLAGS
|
||||
|
||||
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
|
||||
|
||||
*/
|
||||
|
||||
#define CJSON_CDECL __cdecl
|
||||
#define CJSON_STDCALL __stdcall
|
||||
|
||||
/* export symbols by default, this is necessary for copy pasting the C and header file */
|
||||
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
|
||||
#define CJSON_EXPORT_SYMBOLS
|
||||
#endif
|
||||
|
||||
#if defined(CJSON_HIDE_SYMBOLS)
|
||||
#define CJSON_PUBLIC(type) type CJSON_STDCALL
|
||||
#elif defined(CJSON_EXPORT_SYMBOLS)
|
||||
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
|
||||
#elif defined(CJSON_IMPORT_SYMBOLS)
|
||||
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
|
||||
#endif
|
||||
#else /* !__WINDOWS__ */
|
||||
#define CJSON_CDECL
|
||||
#define CJSON_STDCALL
|
||||
|
||||
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
|
||||
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
|
||||
#else
|
||||
#define CJSON_PUBLIC(type) type
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* project version */
|
||||
#define CJSON_VERSION_MAJOR 1
|
||||
#define CJSON_VERSION_MINOR 7
|
||||
#define CJSON_VERSION_PATCH 16
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* cJSON Types: */
|
||||
#define cJSON_Invalid (0)
|
||||
#define cJSON_False (1 << 0)
|
||||
#define cJSON_True (1 << 1)
|
||||
#define cJSON_NULL (1 << 2)
|
||||
#define cJSON_Number (1 << 3)
|
||||
#define cJSON_String (1 << 4)
|
||||
#define cJSON_Array (1 << 5)
|
||||
#define cJSON_Object (1 << 6)
|
||||
#define cJSON_Raw (1 << 7) /* raw json */
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
#define cJSON_StringIsConst 512
|
||||
|
||||
/* The cJSON structure: */
|
||||
typedef struct cJSON
|
||||
{
|
||||
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||
struct cJSON *next;
|
||||
struct cJSON *prev;
|
||||
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||
struct cJSON *child;
|
||||
|
||||
/* The type of the item, as above. */
|
||||
int type;
|
||||
|
||||
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
|
||||
char *valuestring;
|
||||
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
|
||||
int valueint;
|
||||
/* The item's number, if type==cJSON_Number */
|
||||
double valuedouble;
|
||||
|
||||
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||
char *string;
|
||||
} cJSON;
|
||||
|
||||
typedef struct cJSON_Hooks
|
||||
{
|
||||
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
|
||||
void *(CJSON_CDECL *malloc_fn)(size_t sz);
|
||||
void (CJSON_CDECL *free_fn)(void *ptr);
|
||||
} cJSON_Hooks;
|
||||
|
||||
typedef int cJSON_bool;
|
||||
|
||||
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
|
||||
* This is to prevent stack overflows. */
|
||||
#ifndef CJSON_NESTING_LIMIT
|
||||
#define CJSON_NESTING_LIMIT 1000
|
||||
#endif
|
||||
|
||||
/* returns the version of cJSON as a string */
|
||||
CJSON_PUBLIC(const char*) cJSON_Version(void);
|
||||
|
||||
/* Supply malloc, realloc and free functions to cJSON */
|
||||
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||
|
||||
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
|
||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
|
||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
|
||||
|
||||
/* Render a cJSON entity to text for transfer/storage. */
|
||||
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
|
||||
/* Render a cJSON entity to text for transfer/storage without any formatting. */
|
||||
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
|
||||
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
|
||||
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
|
||||
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
|
||||
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
|
||||
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
|
||||
|
||||
/* Check item type and return its value */
|
||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
|
||||
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
|
||||
|
||||
/* These functions check the type of an item */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
|
||||
|
||||
/* These calls create a cJSON item of the appropriate type. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
|
||||
/* raw json */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
|
||||
|
||||
/* Create a string where valuestring references a string so
|
||||
* it will not be freed by cJSON_Delete */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
|
||||
/* Create an object/array that only references it's elements so
|
||||
* they will not be freed by cJSON_Delete */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
|
||||
|
||||
/* These utilities create an Array of count items.
|
||||
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
|
||||
|
||||
/* Append item to the specified array/object. */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
|
||||
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
|
||||
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
|
||||
* writing to `item->string` */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
|
||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||
|
||||
/* Remove/Detach items from Arrays/Objects. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
|
||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||
* The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
|
||||
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
|
||||
|
||||
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
|
||||
* The input pointer json cannot point to a read-only address area, such as a string constant,
|
||||
* but should point to a readable and writable address area. */
|
||||
CJSON_PUBLIC(void) cJSON_Minify(char *json);
|
||||
|
||||
/* Helper functions for creating and adding items to an object at the same time.
|
||||
* They return the added item or NULL on failure. */
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
|
||||
|
||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
|
||||
/* helper for the cJSON_SetNumberValue macro */
|
||||
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
|
||||
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
|
||||
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
|
||||
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
|
||||
|
||||
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
|
||||
#define cJSON_SetBoolValue(object, boolValue) ( \
|
||||
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
|
||||
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
|
||||
cJSON_Invalid\
|
||||
)
|
||||
|
||||
/* Macro for iterating over an array or object */
|
||||
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
|
||||
|
||||
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
|
||||
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
|
||||
CJSON_PUBLIC(void) cJSON_free(void *object);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Nikos Mavrogiannopoulos <nmav@redhat.com>
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "sccproxy.h"
|
||||
|
||||
/**
|
||||
* @brief IPv4 网络信息
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int prefix; ///< 网络前缀
|
||||
char hostip[MAX_IPV4_LEN]; ///< IP 地址
|
||||
char ip[MAX_IPV4_LEN]; ///< IP 地址
|
||||
char network[MAX_IPV4_LEN]; ///< 网络地址
|
||||
char broadcast[MAX_IPV4_LEN]; ///< 网络广播地址
|
||||
char netmask[MAX_IPV4_LEN]; ///< 网络子网掩码
|
||||
char hosts[64]; ///< number of hosts in text
|
||||
char hostmin[MAX_IPV4_LEN]; ///< 最小网络主机 IP
|
||||
char hostmax[MAX_IPV4_LEN]; ///< 最大网络主机 IP
|
||||
} IP_INFO, *PIP_INFO;
|
||||
|
||||
/**
|
||||
* @brief 计算 IPv4 网络信息
|
||||
* @param[in] pIpStr IPv4 地址
|
||||
* @param[in] pNetmask IPv4子网掩码
|
||||
* @param[out] pInfo 计算结果
|
||||
* @return 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_UN_SUPPORT 不支持的格式转换
|
||||
* - -ERR_MALLOC_MEMORY 分配内存失败
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
int get_ipv4_info_from_cidr(const char *pIpStr, const char *pNetmask, PIP_INFO pInfo);
|
||||
/**
|
||||
* @brief 计算 IPv4 网络信息
|
||||
* @param[in] pIpStr IPv4 网络信息 '/' 分割,支持CIDR以及子网掩码 example: 192.168.1.32/24, 192.168.1.32/255.255.255.0
|
||||
* @param[out] pInfo 计算结果
|
||||
* @return 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_UN_SUPPORT 不支持的格式转换
|
||||
* - -ERR_MALLOC_MEMORY 分配内存失败
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
int get_ipv4_info_from_netmask(const char *pIpStr, PIP_INFO pInfo);
|
||||
|
||||
/**
|
||||
* @brief 根据 IP/域名/主机名 获取 IP 地址
|
||||
* @param[in] host 域名/主机名
|
||||
* @param[out] pInfo 计算结果
|
||||
* @return 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_UN_SUPPORT 不支持的格式转换
|
||||
* - -ERR_MALLOC_MEMORY 分配内存失败
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
int get_ipv4_info_from_hostname(const char *host, PIP_INFO pInfo);
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
//
|
||||
// Created by HuangXin on 2023/10/12.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define ANDROID_LOG(level, tag, format, args...) (__android_log_print(level, tag, "[%s(%d)] %s:" format, basename(__FILE__), __LINE__, __FUNCTION__, ##args))
|
|
@ -0,0 +1,83 @@
|
|||
//
|
||||
// Created by HuangXin on 2023/10/12.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#define MAX_PATH (256)
|
||||
|
||||
/**
|
||||
* @brief IP 字符串最大长度(支持IPv6)
|
||||
*/
|
||||
#define MAX_IPV4_LEN (48)
|
||||
|
||||
/**
|
||||
* @brief IP 字符串最小长度
|
||||
*/
|
||||
#define MIN_IPV4_LEN (7)
|
||||
|
||||
|
||||
/**
|
||||
* @brief SCG 服务 ID
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
WG_TUNNEL_SCG_ID = 3, ///< 隧道服务
|
||||
WG_CTRL_SCG_ID = 4 ///< 隧道控制服务
|
||||
} SCG_SVR_ID;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 初始化 SCG 代理服务
|
||||
* @param[in] pSCGIpAddr SCG 代理 IP/域名/主机名
|
||||
* @param[in] scgPort SCG 代理端口
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int init_scgproxy_service(const char *pSCGIpAddr, int scgPort);
|
||||
|
||||
/**
|
||||
* @brief 启动远程隧道服务端
|
||||
* @param[in] vmId 云电脑虚拟机 VMID
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int remote_tunnel_service_start(int vmId);
|
||||
|
||||
/**
|
||||
* @brief 停止远程隧道服务端
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int remote_tunnel_service_stop();
|
||||
|
||||
/**
|
||||
* @brief 设置远程隧道参数
|
||||
* @param[in] pCliPubKey 客户端公钥
|
||||
* @param[in] pCliNetwork 客户端共享网络地址
|
||||
* @param[in] pCliTunNetwork 客户端隧道网络地址
|
||||
* @param[out] pSvrNetwork 服务端返回的服务端隧道网络地址
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int remote_tunnel_set_params(const char *pCliPubKey, const char *pCliNetwork, const char *pCliTunNetwork, char *pSvrNetwork);
|
||||
|
||||
/**
|
||||
* @brief 获取 Wireguard 隧道 UDP 代理服务端口
|
||||
* @return 0:当前代理服务端口不可用, >0 UDP 代理服务端口
|
||||
*/
|
||||
unsigned short get_tunnel_proxy_port();
|
||||
|
||||
/**
|
||||
* @brief 停止 wireguard 隧道 UDP 代理服务
|
||||
*/
|
||||
void stop_wireguard_proxy_server();
|
||||
|
||||
/**
|
||||
* @brief 创建 wireguard 隧道 UDP 代理服务
|
||||
* @param[out] pPorxyPort 当前 UDP 代理服务使用的端口,代理 IP 地址固定为 127.0.0.1
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int create_wireguard_proxy_server(unsigned short *pPorxyPort);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,8 @@
|
|||
//
|
||||
// Created by HuangXin on 2023/10/13.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
int get_scg_cur_vmid();
|
||||
const char *get_scg_proxy_ipaddr();
|
||||
unsigned short get_scg_proxy_port();
|
|
@ -0,0 +1,75 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief SDK 常用错误码
|
||||
*/
|
||||
enum USER_ERRNO {
|
||||
ERR_SUCCESS = 0, ///< 成功
|
||||
ERR_INPUT_PARAMS, ///< 输入参数错误
|
||||
ERR_UN_SUPPORT, ///< 不支持的操作
|
||||
ERR_CALL_SHELL, ///< 调用Shell命令失败
|
||||
ERR_ITEM_EXISTS, ///< 该内容已经存在
|
||||
ERR_ITEM_UNEXISTS, ///< 该内容不存在
|
||||
ERR_SYS_INIT, ///< 系统中断
|
||||
ERR_SYS_CALL, ///< 系统调用
|
||||
ERR_LOAD_LIBRARY, ///< 加载系统库失败
|
||||
ERR_MAP_LIBRARY, ///< 加载系统库接口失败
|
||||
ERR_SYS_TIMEOUT, ///< 系统超时
|
||||
ERR_SYSTEM_UNINITIALIZE, ///< 系统未初始化
|
||||
ERR_CREATE_FILE, ///< 创建文件/目录失败
|
||||
ERR_OPEN_FILE, ///< 打开文件失败
|
||||
ERR_READ_FILE, ///< 读取文件失败
|
||||
ERR_WRITE_FILE, ///< 写入文件失败
|
||||
ERR_FILE_NOT_EXISTS, ///< 文件不存在
|
||||
ERR_FILE_LOCKED, ///< 文件被锁定
|
||||
ERR_GET_FILE_SIZE, ///< 获取文件大小失败
|
||||
ERR_FIND_FILE, ///< 查找文件失败
|
||||
ERR_COPY_FILE, ///< 复制文件失败
|
||||
ERR_OPEN_SCM, ///< 打开服务管理器设备失败
|
||||
ERR_OPEN_SERVICE, ///< 打开服务失败
|
||||
ERR_CREATE_SERVICE, ///< 创建服务失败
|
||||
ERR_START_SERVICE, ///< 启动服务失败
|
||||
ERR_STOP_SERVICE, ///< 停止服务失败
|
||||
ERR_DELETE_SERVICE, ///< 删除服务失败
|
||||
ERR_CONFIG_SERVICE, ///< 修改服务配置失败
|
||||
ERR_GET_SERVICESSTATUS, ///< 获取服务状态失败
|
||||
ERR_MALLOC_MEMORY, ///< 分配内存失败
|
||||
ERR_MMAP_MEMORY, ///< 共享内存失败
|
||||
ERR_MEMORY_STR, ///< 字符串操作失败
|
||||
ERR_CREATE_PROCESS, ///< 创建进程失败
|
||||
ERR_PROCESS_RETURN, ///< 进程调用返回失败
|
||||
ERR_CREATE_THREAD, ///< 创建线程失败
|
||||
ERR_CREATE_TIMER, ///< 创建定时器失败
|
||||
ERR_DELETE_TIMER, ///< 销毁定时器失败
|
||||
ERR_SOCKET_CREATE, ///< 创建 SOCKET 失败
|
||||
ERR_SOCKET_BIND, ///< 绑定 SOCKET 端口失败
|
||||
ERR_SOCKET_CONNECT, ///< 连接 TCP SOCKET 服务器失败
|
||||
ERR_SOCKET_LISTEN, ///< TCP SOCKET 服务监听失败
|
||||
ERR_SOCKET_BIND_PORT, ///< 绑定端口失败
|
||||
ERR_SOCKET_SET_OPT, ///< 设置 SOCKET 参数失败
|
||||
ERR_SOCKET_GET_OPT, ///< 读取 SOCKET 参数失败
|
||||
ERR_BCRYPT_OPEN = 100, ///< 创建加密算法失败
|
||||
ERR_BCRYPT_GETPROPERTY, ///< 获取加密算法属性失败
|
||||
ERR_BCRYPT_CREATEHASH, ///< 创建 Hash 算法失败
|
||||
ERR_BCRYPT_HASHDATA, ///< 计算 Hash 数据失败
|
||||
ERR_BCRYPT_FINISHHASH, ///< 计算 Hash 结果失败
|
||||
ERR_NET_UNCONNECT = 200, ///< 网络未连接
|
||||
ERR_NET_CATEGORY_MODE, ///< 网络工作模式
|
||||
ERR_NET_INTELNEL_ICS, ///< 共享 Intelnet 网络 ICS 共享失败
|
||||
ERR_NET_WIREGUARD_ICS, ///< 共享 WireGuard 网络 ICS 共享失败
|
||||
ERR_GET_IPFOWARDTBL = 300, ///< 获取系统 IP 转发表失败
|
||||
ERR_CREATE_COMMOBJECT = 400, ///< 创建 COM 对象失败
|
||||
ERR_CALL_COMMOBJECT, ///< 调用 COM 对象失败
|
||||
ERR_WMI_GET_COMMOBJECT, ///< 获取 WMI COM 对象失败
|
||||
ERR_WMI_CONN_SVR, ///< 连接到 WMI 失败
|
||||
ERR_WMI_SET_PROXY, ///< 设置 WMI 代理服务失败
|
||||
ERR_WMI_QUERY, ///< 执行 WMI SQL查询失败
|
||||
ERR_WMI_EXEC_METHOD, ///< 执行 WMI 函数失败
|
||||
ERR_COM_INITIALIZE, ///< 初始化COM失败
|
||||
ERR_JSON_CREATE = 500, ///< 创建 JSON 对象失败
|
||||
ERR_JSON_DECODE, ///< 从 JSON 反序列化对象失败
|
||||
ERR_HTTP_SERVER_RSP = 600, ///< HTTP 服务端返回错误
|
||||
ERR_HTTP_POST_DATA, ///< 发送 POST 请求失败
|
||||
ERR_NET_ADD_ROUTE, ///< 添加路由失败
|
||||
ERR_NET_REMOVE_ROUTE, ///< 删除路由失败
|
||||
};
|
|
@ -0,0 +1,140 @@
|
|||
#include <jni.h>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include "sccproxy.h"
|
||||
#include "log.h"
|
||||
#include "usrerr.h"
|
||||
|
||||
extern "C" JNIEXPORT jstring JNICALL
|
||||
Java_com_example_sccproxy_MainActivity_stringFromJNI(
|
||||
JNIEnv *env,
|
||||
jobject /* this */) {
|
||||
int ret;
|
||||
int vmId = 123;
|
||||
char svrTunnelNetwork[256];
|
||||
unsigned short tunnelProxyPort = 0;
|
||||
|
||||
std::string hello = "Hello from C++";
|
||||
//-----------------------------------------------------------------------
|
||||
// 系统初始化, 程序启动时调用一次
|
||||
//-----------------------------------------------------------------------
|
||||
// Init step 1. 初始化 SCG 代理服务
|
||||
ret = init_scgproxy_service("127.0.0.1", 10800);
|
||||
if (ret == ERR_SUCCESS) {
|
||||
ANDROID_LOG(ANDROID_LOG_INFO, "SCGPROXY", "init_scgproxy_service: SUCCESSED\n");
|
||||
} else {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "init_scgproxy_service error: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Init step 2. 初始化 SCG 代理服务
|
||||
// 初始化 wireguard 隧道代理服务,如果成功会返回代理端口, 程序启动时调用一次
|
||||
// 填入 Wiregurad 配置文件 Endpoint 参数为 Endpoint = 127.0.0.1:tunnelProxyPort
|
||||
ret = create_wireguard_proxy_server(&tunnelProxyPort);
|
||||
if (ret == ERR_SUCCESS) {
|
||||
ANDROID_LOG(ANDROID_LOG_INFO, "SCGPROXY", "create_wireguard_proxy_server: SUCCESSED, proxyPort = %d\n", tunnelProxyPort);
|
||||
} else {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "create_wireguard_proxy_server error: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// 隧道控制,每次启动/停止 SCC 服务时调用
|
||||
//-----------------------------------------------------------------------
|
||||
// SCC Service Step 1. 客户端获取隧道配置并连接到虚拟机后,首先要对虚拟机里面的隧道进行配置
|
||||
/**
|
||||
{
|
||||
"code": "00000",
|
||||
"data": {
|
||||
"cliHost": "10.10.10.1/24", // TODO Set to pCliTunNetwork(Step 1) & et to wireguard 配置文件 Address=/AllowedIPs= (Step 2)
|
||||
"cliPubKey": "fcosdnZe7PQjkjpFNNZUxv9Dtl36XubAj6d6cDU6R34=", // TODO Set to pCliPubKey(Step 1)
|
||||
"cliPriKey": "6PIYlZHVDzRbgvfWgeu27OfO0NeN8WrFBMAa56hIL0M=", // TODO Set to wireguard 配置文件 PrivateKey= (Step 2)
|
||||
"vmInfoList": [
|
||||
{
|
||||
"svrPubKey": "nssKUB0d+uRLiys/YzCqA0n8xhw6fuRgs2Q5asEAExc=", // TODO Set to wireguard 配置文件 PublicKey= (Step 2)
|
||||
"vmName": "ct-pool-95-1696922439711",
|
||||
"vmId": 827, // TODO Set to vmid (Step 3)
|
||||
"extVmId": "a3adc00b-d794-46b7-bb83-1951f3368cfb",
|
||||
"vmNetwork": "172.31.18.108/24",
|
||||
"scgIp": "112.17.28.220",
|
||||
"scgPort": 1080,
|
||||
"portMapIp": "112.17.28.221",
|
||||
"portMapPort": 2002
|
||||
}
|
||||
]
|
||||
},
|
||||
"message": "操作成功"
|
||||
}
|
||||
*/
|
||||
ret = remote_tunnel_set_params("fcosdnZe7PQjkjpFNNZUxv9Dtl36XubAj6d6cDU6R34=", "192.168.100.0/24", "10.10.10.0/24", svrTunnelNetwork);
|
||||
|
||||
if (ret == ERR_SUCCESS) {
|
||||
ANDROID_LOG(ANDROID_LOG_INFO, "SCGPROXY", "remote_tunnel_set_params: SUCCESSED, Server Tunnel Network: %s\n", svrTunnelNetwork);
|
||||
} else {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "remote_tunnel_set_params error: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// SCC Service Step 2. 创建本地 Wireguard 配置文件
|
||||
// TODO
|
||||
/**
|
||||
[Interface]
|
||||
PrivateKey = 6PIYlZHVDzRbgvfWgeu27OfO0NeN8WrFBMAa56hIL0M= // TODO from (step 1)
|
||||
Address = 10.10.10.1/24 // TODO from (step 1)
|
||||
|
||||
[Peer]
|
||||
PublicKey = nssKUB0d+uRLiys/YzCqA0n8xhw6fuRgs2Q5asEAExc= // TODO from (step 1)
|
||||
AllowedIPs = 10.10.10.0/24,172.31.18.0/24 // TODO from (Step 1 pCliTunNetwork and svrTunnelNetwork)
|
||||
Endpoint = 127.0.0.1:49301 // TODO Port from tunnelProxyPort (Init Step 2)
|
||||
PersistentKeepalive = 30 // TODO fixed or configure by user
|
||||
*/
|
||||
|
||||
// SCC Service Step 3. 启动虚拟机内服务端隧道
|
||||
ret = remote_tunnel_service_start(vmId);
|
||||
if (ret == ERR_SUCCESS) {
|
||||
ANDROID_LOG(ANDROID_LOG_INFO, "SCGPROXY", "remote_tunnel_service_start: SUCCESSED, Current Connect VMID: %d\n", vmId);
|
||||
} else {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "remote_tunnel_service_start error: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// SCC Service Step 4. 启动客户端本地 Wireguard 隧道
|
||||
// TODO
|
||||
|
||||
// SCC Service Step 5. 配置客户端 iptables 规则,启动 SCC 内网转发
|
||||
// TODO
|
||||
|
||||
// SCC Service Step 6. 端口虚拟机,停止服务端隧道
|
||||
ret = remote_tunnel_service_stop();
|
||||
if (ret == ERR_SUCCESS) {
|
||||
ANDROID_LOG(ANDROID_LOG_INFO, "SCGPROXY", "remote_tunnel_service_stop: SUCCESSED, Current Connect VMID: %d\n", vmId);
|
||||
} else {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "remote_tunnel_service_stop error: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// SCC Service Step 7. 删除客户端 iptables 规则, 停止 SCC 内网转发
|
||||
// TODO
|
||||
|
||||
// SCC Service Step 8. 停止本地 Wireguard 隧道
|
||||
// TODO
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// 资源清理,程序退出时调用
|
||||
//-----------------------------------------------------------------------
|
||||
// UnInit step 1. 停止虚拟机内隧道服务程序
|
||||
// remote_tunnel_service_stop
|
||||
|
||||
// UnInit step 2. 删除客户端 iptables 规则, 停止 SCC 内网转发
|
||||
// TODO
|
||||
|
||||
// UnInit step 3. 停止本地 Wireguard 隧道
|
||||
// TODO
|
||||
|
||||
// UnInit step 4. 停止客户端 Wireguard 隧道 UDP 代理服务
|
||||
stop_wireguard_proxy_server();
|
||||
|
||||
error:
|
||||
return env->NewStringUTF(hello.c_str());
|
||||
}
|
|
@ -0,0 +1,511 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "usrerr.h"
|
||||
#include "ipcalc.h"
|
||||
#include "log.h"
|
||||
|
||||
static const char *p2_table(unsigned pow) {
|
||||
static const char *pow2[] = {
|
||||
"1",
|
||||
"2",
|
||||
"4",
|
||||
"8",
|
||||
"16",
|
||||
"32",
|
||||
"64",
|
||||
"128",
|
||||
"256",
|
||||
"512",
|
||||
"1024",
|
||||
"2048",
|
||||
"4096",
|
||||
"8192",
|
||||
"16384",
|
||||
"32768",
|
||||
"65536",
|
||||
"131072",
|
||||
"262144",
|
||||
"524288",
|
||||
"1048576",
|
||||
"2097152",
|
||||
"4194304",
|
||||
"8388608",
|
||||
"16777216",
|
||||
"33554432",
|
||||
"67108864",
|
||||
"134217728",
|
||||
"268435456",
|
||||
"536870912",
|
||||
"1073741824",
|
||||
"2147483648",
|
||||
"4294967296",
|
||||
"8589934592",
|
||||
"17179869184",
|
||||
"34359738368",
|
||||
"68719476736",
|
||||
"137438953472",
|
||||
"274877906944",
|
||||
"549755813888",
|
||||
"1099511627776",
|
||||
"2199023255552",
|
||||
"4398046511104",
|
||||
"8796093022208",
|
||||
"17592186044416",
|
||||
"35184372088832",
|
||||
"70368744177664",
|
||||
"140737488355328",
|
||||
"281474976710656",
|
||||
"562949953421312",
|
||||
"1125899906842624",
|
||||
"2251799813685248",
|
||||
"4503599627370496",
|
||||
"9007199254740992",
|
||||
"18014398509481984",
|
||||
"36028797018963968",
|
||||
"72057594037927936",
|
||||
"144115188075855872",
|
||||
"288230376151711744",
|
||||
"576460752303423488",
|
||||
"1152921504606846976",
|
||||
"2305843009213693952",
|
||||
"4611686018427387904",
|
||||
"9223372036854775808",
|
||||
"18446744073709551616",
|
||||
"36893488147419103232",
|
||||
"73786976294838206464",
|
||||
"147573952589676412928",
|
||||
"295147905179352825856",
|
||||
"590295810358705651712",
|
||||
"1180591620717411303424",
|
||||
"2361183241434822606848",
|
||||
"4722366482869645213696",
|
||||
"9444732965739290427392",
|
||||
"18889465931478580854784",
|
||||
"37778931862957161709568",
|
||||
"75557863725914323419136",
|
||||
"151115727451828646838272",
|
||||
"302231454903657293676544",
|
||||
"604462909807314587353088",
|
||||
"1208925819614629174706176",
|
||||
"2417851639229258349412352",
|
||||
"4835703278458516698824704",
|
||||
"9671406556917033397649408",
|
||||
"19342813113834066795298816",
|
||||
"38685626227668133590597632",
|
||||
"77371252455336267181195264",
|
||||
"154742504910672534362390528",
|
||||
"309485009821345068724781056",
|
||||
"618970019642690137449562112",
|
||||
"1237940039285380274899124224",
|
||||
"2475880078570760549798248448",
|
||||
"4951760157141521099596496896",
|
||||
"9903520314283042199192993792",
|
||||
"19807040628566084398385987584",
|
||||
"39614081257132168796771975168",
|
||||
"79228162514264337593543950336",
|
||||
"158456325028528675187087900672",
|
||||
"316912650057057350374175801344",
|
||||
"633825300114114700748351602688",
|
||||
"1267650600228229401496703205376",
|
||||
"2535301200456458802993406410752",
|
||||
"5070602400912917605986812821504",
|
||||
"10141204801825835211973625643008",
|
||||
"20282409603651670423947251286016",
|
||||
"40564819207303340847894502572032",
|
||||
"81129638414606681695789005144064",
|
||||
"162259276829213363391578010288128",
|
||||
"324518553658426726783156020576256",
|
||||
"649037107316853453566312041152512",
|
||||
"1298074214633706907132624082305024",
|
||||
"2596148429267413814265248164610048",
|
||||
"5192296858534827628530496329220096",
|
||||
"10384593717069655257060992658440192",
|
||||
"20769187434139310514121985316880384",
|
||||
"41538374868278621028243970633760768",
|
||||
"83076749736557242056487941267521536",
|
||||
"166153499473114484112975882535043072",
|
||||
"332306998946228968225951765070086144",
|
||||
"664613997892457936451903530140172288",
|
||||
"1329227995784915872903807060280344576",
|
||||
"2658455991569831745807614120560689152",
|
||||
"5316911983139663491615228241121378304",
|
||||
"10633823966279326983230456482242756608",
|
||||
"21267647932558653966460912964485513216",
|
||||
"42535295865117307932921825928971026432",
|
||||
"85070591730234615865843651857942052864",
|
||||
"170141183460469231731687303715884105728",
|
||||
};
|
||||
if (pow <= 127) {
|
||||
return pow2[pow];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static int bit_count(unsigned int i) {
|
||||
int c = 0;
|
||||
unsigned int seen_one = 0;
|
||||
|
||||
while (i > 0) {
|
||||
if (i & 1) {
|
||||
seen_one = 1;
|
||||
c++;
|
||||
} else {
|
||||
if (seen_one) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
i >>= 1;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates a netmask from a specified number of bits
|
||||
* This function converts a prefix length to a netmask. As CIDR (classless
|
||||
* internet domain internet domain routing) has taken off, more an more IP
|
||||
* addresses are being specified in the format address/prefix
|
||||
* (i.e. 192.168.2.3/24, with a corresponding netmask 255.255.255.0). If you
|
||||
* need to see what netmask corresponds to the prefix part of the address, this
|
||||
* is the function. See also @ref mask2prefix.
|
||||
* @param prefix prefix is the number of bits to create a mask for.
|
||||
* @return a network mask, in network byte order.
|
||||
*/
|
||||
unsigned int prefix2mask(int prefix) {
|
||||
if (prefix) {
|
||||
return htonl(~((1 << (32 - prefix)) - 1));
|
||||
} else {
|
||||
return htonl(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief calculates the number of bits masked off by a netmask.
|
||||
* This function calculates the significant bits in an IP address as specified by
|
||||
* a netmask. See also @ref prefix2mask.
|
||||
* @param mask is the netmask, specified as an struct in_addr in network byte order.
|
||||
* @return the number of significant bits.
|
||||
*/
|
||||
static int mask2prefix(struct in_addr mask) {
|
||||
return bit_count(ntohl(mask.s_addr));
|
||||
}
|
||||
|
||||
static int ipv4_mask_to_int(const char *prefix) {
|
||||
int ret;
|
||||
struct in_addr in = {};
|
||||
|
||||
ret = inet_pton(AF_INET, prefix, &in);
|
||||
if (ret == 0)
|
||||
return -1;
|
||||
|
||||
return mask2prefix(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief calculate broadcast address given an IP address and a prefix length.
|
||||
* @param addr an IP address in network byte order.
|
||||
* @param prefix a prefix length.
|
||||
* @return the calculated broadcast address for the network, in network byte order.
|
||||
*/
|
||||
static struct in_addr calc_broadcast(struct in_addr addr, int prefix) {
|
||||
struct in_addr mask = {};
|
||||
struct in_addr broadcast = {};
|
||||
|
||||
mask.s_addr = prefix2mask(prefix);
|
||||
|
||||
memset(&broadcast, 0, sizeof(broadcast));
|
||||
broadcast.s_addr = (addr.s_addr & mask.s_addr) | ~mask.s_addr;
|
||||
return broadcast;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief calculates the network address for a specified address and prefix.
|
||||
* @param addr an IP address, in network byte order
|
||||
* @param prefix the network prefix
|
||||
* @return the base address of the network that addr is associated with, in
|
||||
* network byte order.
|
||||
*/
|
||||
static struct in_addr calc_network(struct in_addr addr, int prefix) {
|
||||
struct in_addr mask = {};
|
||||
struct in_addr network = {};
|
||||
|
||||
mask.s_addr = prefix2mask(prefix);
|
||||
|
||||
memset(&network, 0, sizeof(network));
|
||||
network.s_addr = addr.s_addr & mask.s_addr;
|
||||
return network;
|
||||
}
|
||||
|
||||
char *ipv4_prefix_to_hosts(char *hosts, unsigned hosts_size, unsigned prefix) {
|
||||
unsigned tmp;
|
||||
|
||||
if (prefix >= 31) {
|
||||
snprintf(hosts, hosts_size, "%s", p2_table(32 - prefix));
|
||||
} else {
|
||||
tmp = (1 << (32 - prefix)) - 2;
|
||||
snprintf(hosts, hosts_size, "%u", tmp);
|
||||
}
|
||||
return hosts;
|
||||
}
|
||||
|
||||
static int str_to_prefix(int *ipv6, const char *prefixStr) {
|
||||
int prefix;
|
||||
|
||||
if (!(*ipv6) && strchr(prefixStr, '.')) { /* prefix is 255.x.x.x */
|
||||
prefix = ipv4_mask_to_int(prefixStr);
|
||||
} else {
|
||||
prefix = strtol(prefixStr, nullptr, 10);
|
||||
}
|
||||
|
||||
if (prefix > 32 && !(*ipv6)) {
|
||||
*ipv6 = 1;
|
||||
}
|
||||
|
||||
if (prefix < 0 || (((*ipv6) && prefix > 128) || (!(*ipv6) && prefix > 32))) {
|
||||
return -1;
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
static int get_ipv4_info(const char *pIpStr, int prefix, PIP_INFO pInfo) {
|
||||
struct in_addr ip = {}, netmask = {}, network = {}, broadcast = {}, minhost = {}, maxhost = {};
|
||||
char namebuf[INET_ADDRSTRLEN + 1];
|
||||
char *ipStr = strdup(pIpStr);
|
||||
|
||||
memset(pInfo, 0, sizeof(*pInfo));
|
||||
|
||||
if (inet_pton(AF_INET, ipStr, &ip) <= 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Bad IPv4 address: %s\n", ipStr);
|
||||
free(ipStr);
|
||||
return -ERR_UN_SUPPORT;
|
||||
}
|
||||
|
||||
/* Handle CIDR entries such as 172/8 */
|
||||
if (prefix >= 0) {
|
||||
auto tmp = const_cast<char *>(ipStr);
|
||||
int i;
|
||||
|
||||
for (i = 3; i > 0; i--) {
|
||||
tmp = strchr(tmp, '.');
|
||||
if (!tmp) {
|
||||
break;
|
||||
} else {
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = nullptr;
|
||||
for (; i > 0; i--) {
|
||||
if (asprintf(&tmp, "%s.0", ipStr) == -1) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Memory allocation failure\n");
|
||||
free(ipStr);
|
||||
return -ERR_MALLOC_MEMORY;
|
||||
}
|
||||
ipStr = tmp;
|
||||
}
|
||||
} else { // assume good old days classful Internet
|
||||
prefix = 32;
|
||||
}
|
||||
|
||||
if (prefix > 32) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Bad IPv4 prefix: %d\n", prefix);
|
||||
free(ipStr);
|
||||
return -ERR_UN_SUPPORT;
|
||||
}
|
||||
|
||||
if (inet_ntop(AF_INET, &ip, namebuf, sizeof(namebuf)) == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Error calculating the IPv4 network\n");
|
||||
free(ipStr);
|
||||
return -ERR_UN_SUPPORT;
|
||||
}
|
||||
strncpy(pInfo->ip, namebuf, MAX_IPV4_LEN);
|
||||
|
||||
netmask.s_addr = prefix2mask(prefix);
|
||||
memset(namebuf, '\0', sizeof(namebuf));
|
||||
|
||||
if (inet_ntop(AF_INET, &netmask, namebuf, INET_ADDRSTRLEN) == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "inet_ntop error\n");
|
||||
free(ipStr);
|
||||
return -ERR_UN_SUPPORT;
|
||||
}
|
||||
strncpy(pInfo->netmask, namebuf, MAX_IPV4_LEN);
|
||||
|
||||
pInfo->prefix = prefix;
|
||||
|
||||
broadcast = calc_broadcast(ip, prefix);
|
||||
|
||||
memset(namebuf, '\0', sizeof(namebuf));
|
||||
if (inet_ntop(AF_INET, &broadcast, namebuf, INET_ADDRSTRLEN) == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "inet_ntop error\n");
|
||||
free(ipStr);
|
||||
return -ERR_UN_SUPPORT;
|
||||
}
|
||||
|
||||
strncpy(pInfo->broadcast, namebuf, MAX_IPV4_LEN);
|
||||
|
||||
network = calc_network(ip, prefix);
|
||||
|
||||
memset(namebuf, '\0', sizeof(namebuf));
|
||||
if (inet_ntop(AF_INET, &network, namebuf, INET_ADDRSTRLEN) == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "inet_ntop error\n");
|
||||
free(ipStr);
|
||||
return -ERR_UN_SUPPORT;
|
||||
}
|
||||
|
||||
strncpy(pInfo->network, namebuf, MAX_IPV4_LEN);
|
||||
|
||||
if (prefix < 32) {
|
||||
memcpy(&minhost, &network, sizeof(minhost));
|
||||
|
||||
if (prefix <= 30) {
|
||||
minhost.s_addr = htonl(ntohl(minhost.s_addr) | 1);
|
||||
}
|
||||
if (inet_ntop(AF_INET, &minhost, namebuf, INET_ADDRSTRLEN) == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "inet_ntop error\n");
|
||||
free(ipStr);
|
||||
return -ERR_UN_SUPPORT;
|
||||
}
|
||||
strncpy(pInfo->hostmin, namebuf, MAX_IPV4_LEN);
|
||||
|
||||
memcpy(&maxhost, &network, sizeof(minhost));
|
||||
maxhost.s_addr |= ~netmask.s_addr;
|
||||
if (prefix <= 30) {
|
||||
maxhost.s_addr = htonl(ntohl(maxhost.s_addr) - 1);
|
||||
}
|
||||
if (inet_ntop(AF_INET, &maxhost, namebuf, sizeof(namebuf)) == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Error calculating the IPv4 network\n");
|
||||
free(ipStr);
|
||||
return -ERR_UN_SUPPORT;
|
||||
}
|
||||
|
||||
strncpy(pInfo->hostmax, namebuf, MAX_IPV4_LEN);
|
||||
} else {
|
||||
strncpy(pInfo->hostmin, pInfo->network, MAX_IPV4_LEN);
|
||||
strncpy(pInfo->hostmax, pInfo->network, MAX_IPV4_LEN);
|
||||
}
|
||||
|
||||
ipv4_prefix_to_hosts(pInfo->hosts, sizeof(pInfo->hosts), prefix);
|
||||
|
||||
free(ipStr);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算 IPv4 网络信息
|
||||
* @param[in] pIpStr IPv4 网络信息 '/' 分割,支持CIDR以及子网掩码 example: 192.168.1.32/24, 192.168.1.32/255.255.255.0
|
||||
* @param[out] pInfo 计算结果
|
||||
* @return 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_UN_SUPPORT 不支持的格式转换
|
||||
* - -ERR_MALLOC_MEMORY 分配内存失败
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
int get_ipv4_info_from_cidr(const char *pIpStr, PIP_INFO pInfo) {
|
||||
int ret, prefix;
|
||||
char *prefixStr;
|
||||
int familyIPv6 = 0;
|
||||
char *ipStr = strdup(pIpStr);
|
||||
|
||||
if (pIpStr == nullptr || strlen(pIpStr) < MIN_IPV4_LEN || strlen(pIpStr) >= MAX_IPV4_LEN) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Input pIpStr format error: %s\n", pIpStr);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pInfo == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Input pInfo is NULL\n");
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (strchr(ipStr, '/') != nullptr) {
|
||||
prefixStr = static_cast<char *>(strchr(ipStr, '/'));
|
||||
*prefixStr = '\0'; /* fix up ipStr */
|
||||
prefixStr++;
|
||||
} else {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Input pIpStr isn't CIDR format: %s\n", pIpStr);
|
||||
free(ipStr);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (strchr(prefixStr, '.') != nullptr) {
|
||||
prefix = ipv4_mask_to_int(prefixStr);
|
||||
} else {
|
||||
prefix = str_to_prefix(&familyIPv6, prefixStr);
|
||||
}
|
||||
|
||||
ret = get_ipv4_info(ipStr, prefix, pInfo);
|
||||
|
||||
free(ipStr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算 IPv4 网络信息
|
||||
* @param[in] pIpStr IPv4 地址
|
||||
* @param[in] pNetmask IPv4子网掩码
|
||||
* @param[out] pInfo 计算结果
|
||||
* @return 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_UN_SUPPORT 不支持的格式转换
|
||||
* - -ERR_MALLOC_MEMORY 分配内存失败
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
int get_ipv4_info_from_netmask(const char *pIpStr, const char *pNetmask, PIP_INFO pInfo) {
|
||||
int prefix;
|
||||
|
||||
if (pIpStr == nullptr || strlen(pIpStr) < MIN_IPV4_LEN || strlen(pIpStr) >= MAX_IPV4_LEN) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Input pIpStr format error: %s\n", pIpStr);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pNetmask == nullptr || strlen(pNetmask) < MIN_IPV4_LEN || strlen(pNetmask) >= MAX_IPV4_LEN) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Input pNetmask format error: %s\n", pNetmask);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pInfo == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "IPCALC", "Input pInfo is NULL.\n");
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
prefix = ipv4_mask_to_int(pNetmask);
|
||||
return get_ipv4_info(pIpStr, prefix, pInfo);
|
||||
}
|
||||
|
||||
int get_ipv4_info_from_hostname(const char *host, PIP_INFO pInfo) {
|
||||
struct addrinfo *res, *rp;
|
||||
struct addrinfo hints = {};
|
||||
int err;
|
||||
static char ipname[64];
|
||||
void *addr;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
err = getaddrinfo(host, nullptr, &hints, &res);
|
||||
if (err != 0) {
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
for (rp = res; rp != nullptr; rp = rp->ai_next) {
|
||||
if (rp->ai_family == AF_INET) {
|
||||
addr = (&reinterpret_cast<sockaddr_in * >(rp->ai_addr)->sin_addr);
|
||||
} else {
|
||||
addr = (&reinterpret_cast<sockaddr_in6 * >(rp->ai_addr)->sin6_addr);
|
||||
}
|
||||
|
||||
if (inet_ntop(rp->ai_family, addr, ipname, sizeof(ipname)) != nullptr) {
|
||||
freeaddrinfo(res);
|
||||
strncpy(pInfo->hostip, ipname, MAX_IPV4_LEN);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
return ERR_ITEM_EXISTS;
|
||||
}
|
|
@ -0,0 +1,376 @@
|
|||
#include "usrerr.h"
|
||||
#include "httplib.h"
|
||||
#include "log.h"
|
||||
#include "sccproxy.h"
|
||||
#include "ipcalc.h"
|
||||
#include "scg-service.h"
|
||||
#include "../cJSON/cJSON.h"
|
||||
|
||||
#define SET_CLIENTCFG_PATH ("/tunnel/setconfig")
|
||||
#define SET_CLIENTSTART_TUNNEL ("/tunnel/start")
|
||||
|
||||
typedef struct {
|
||||
char scgProxyIpAddr[MAX_PATH];
|
||||
int scgProxyPort;
|
||||
int curConnVmId;
|
||||
int isEnable;
|
||||
httplib::Client *g_tunCtrlCtx;
|
||||
} SCGPROXY_CONFIG, *PSCGPROXY_CONFIG;
|
||||
|
||||
static SCGPROXY_CONFIG g_scgProxyCfg;
|
||||
|
||||
int get_scg_cur_vmid() {
|
||||
return g_scgProxyCfg.curConnVmId;
|
||||
}
|
||||
|
||||
const char *get_scg_proxy_ipaddr() {
|
||||
return g_scgProxyCfg.scgProxyIpAddr;
|
||||
}
|
||||
|
||||
unsigned short get_scg_proxy_port() {
|
||||
return static_cast<unsigned short>(g_scgProxyCfg.scgProxyPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化 SCG 代理服务
|
||||
* @param[in] pSCGIpAddr SCG 代理 IP/域名/主机名
|
||||
* @param[in] scgPort SCG 代理端口
|
||||
* @return 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int init_scgproxy_service(const char *pSCGIpAddr, int scgPort) {
|
||||
IP_INFO ipInfo;
|
||||
int ret;
|
||||
char scgProxyUrl[MAX_PATH * 4];
|
||||
|
||||
memset(&g_scgProxyCfg, 0, sizeof(SCGPROXY_CONFIG));
|
||||
|
||||
if (pSCGIpAddr == nullptr || strlen(pSCGIpAddr) == 0 || strlen(pSCGIpAddr) >= MAX_IPV4_LEN) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Input pSCGIpAddr params error: %s\n", pSCGIpAddr ? pSCGIpAddr : "NULL String");
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (scgPort <= 0 || scgPort > 65535) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Input scgPort params error: %d\n", scgPort);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
ANDROID_LOG(ANDROID_LOG_INFO, "SCGPROXY", "Enable SCG Proxy: %s:%d, Tunnel Control VMID = %d, Tunnel Data VMID = %d \n",
|
||||
pSCGIpAddr, scgPort, WG_CTRL_SCG_ID, WG_TUNNEL_SCG_ID);
|
||||
|
||||
if ((ret = get_ipv4_info_from_hostname(pSCGIpAddr, &ipInfo)) != ERR_SUCCESS) {
|
||||
ANDROID_LOG(ANDROID_LOG_WARN, "SCGPROXY", "get_ipv4_info_from_hostname error: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
strncpy(g_scgProxyCfg.scgProxyIpAddr, ipInfo.hostip, MAX_PATH);
|
||||
g_scgProxyCfg.scgProxyPort = scgPort;
|
||||
|
||||
memset(scgProxyUrl, 0, MAX_PATH * 4);
|
||||
snprintf(scgProxyUrl, MAX_PATH * 4 - 1, "http://%s:%d", g_scgProxyCfg.scgProxyIpAddr, g_scgProxyCfg.scgProxyPort);
|
||||
g_scgProxyCfg.g_tunCtrlCtx = new httplib::Client(scgProxyUrl);
|
||||
|
||||
if (g_scgProxyCfg.g_tunCtrlCtx == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_WARN, "SCGPROXY", "Create HTTP Proxy error: %s\n", scgProxyUrl);
|
||||
return -ERR_SYSTEM_UNINITIALIZE;
|
||||
} else {
|
||||
g_scgProxyCfg.g_tunCtrlCtx->set_connection_timeout(0, 1000000); // 1 second
|
||||
g_scgProxyCfg.g_tunCtrlCtx->set_read_timeout(5, 0); // 5 seconds
|
||||
g_scgProxyCfg.g_tunCtrlCtx->set_write_timeout(5, 0); // 5 seconds
|
||||
g_scgProxyCfg.g_tunCtrlCtx->set_keep_alive(true);
|
||||
g_scgProxyCfg.g_tunCtrlCtx->set_post_connect_cb([](socket_t sock) {
|
||||
int ret;
|
||||
unsigned char vmid[4];
|
||||
unsigned char *p;
|
||||
const unsigned int id = htonl(g_scgProxyCfg.curConnVmId);
|
||||
const auto svrId = static_cast<unsigned char>(WG_CTRL_SCG_ID);
|
||||
unsigned char scgProxy[] = {0x01, // VERSION
|
||||
0x09, // Length
|
||||
0xF0, // ++++++ INFO[0] TYPE
|
||||
0x04, // INFO[0] LENGTH
|
||||
0, // INFO[0] VMID[0]
|
||||
0, // INFO[0] VMID[1]
|
||||
0, // INFO[0] VMID[2]
|
||||
0, // INFO[0] VMID[3]
|
||||
0xF1, // INFO[1] TYPE
|
||||
0x01, // INFO[1] LENGTH
|
||||
svrId}; // ------ INFO[1] SCG Service ID
|
||||
|
||||
p = scgProxy;
|
||||
memcpy(vmid, &id, 4);
|
||||
scgProxy[4] = vmid[0];
|
||||
scgProxy[5] = vmid[1];
|
||||
scgProxy[6] = vmid[2];
|
||||
scgProxy[7] = vmid[3];
|
||||
|
||||
ret = send(sock, reinterpret_cast<const char *>(p), sizeof(scgProxy), 0);
|
||||
|
||||
if (ret != sizeof(scgProxy)) {
|
||||
ANDROID_LOG(ANDROID_LOG_WARN, "SCGPROXY", "Service Connected To SCG Server(vmid = %d, SCGAppId = %d) error: %d\n",
|
||||
g_scgProxyCfg.curConnVmId, WG_CTRL_SCG_ID, ret);
|
||||
}
|
||||
|
||||
ANDROID_LOG(ANDROID_LOG_DEBUG, "SCGPROXY", "Service Connected To SCG Server:vmid = %d, SCGAppId = %d: %d\n",
|
||||
g_scgProxyCfg.curConnVmId, WG_CTRL_SCG_ID, sock);
|
||||
});
|
||||
}
|
||||
|
||||
g_scgProxyCfg.isEnable = true;
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static int remote_tunnel_service_control(int vmId, bool start) {
|
||||
if (vmId < 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Input pSCGIpAddr params error: %d\n", vmId);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (!g_scgProxyCfg.isEnable) {
|
||||
ANDROID_LOG(ANDROID_LOG_WARN, "SCGPROXY", "SCG Proxy Service Uninit.\n");
|
||||
return -ERR_SYSTEM_UNINITIALIZE;
|
||||
}
|
||||
|
||||
if (g_scgProxyCfg.g_tunCtrlCtx == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_WARN, "SCGPROXY", "Server Control Service don't connected(g_tunnelHttpCtx is not initialize).");
|
||||
return -ERR_SYSTEM_UNINITIALIZE;
|
||||
} else {
|
||||
char *pJsonString;
|
||||
cJSON *pRoot;
|
||||
cJSON *pMsgContent;
|
||||
cJSON *rspCode;
|
||||
httplib::Result res;
|
||||
|
||||
g_scgProxyCfg.curConnVmId = vmId;
|
||||
|
||||
pRoot = cJSON_CreateObject();
|
||||
|
||||
if (pRoot == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Create JSON Error.\n");
|
||||
return -ERR_JSON_CREATE;
|
||||
}
|
||||
|
||||
cJSON_AddNumberToObject(pRoot, "ver", 1);
|
||||
cJSON_AddNumberToObject(pRoot, "cryptoType", 0);
|
||||
cJSON_AddNumberToObject(pRoot, "timeStamp", time(nullptr));
|
||||
|
||||
pMsgContent = cJSON_CreateObject();
|
||||
if (pMsgContent == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Create JSON Error.\n");
|
||||
cJSON_Delete(pRoot);
|
||||
return -ERR_JSON_CREATE;
|
||||
}
|
||||
|
||||
cJSON_AddItemToObject(pRoot, "msgContent", pMsgContent);
|
||||
cJSON_AddBoolToObject(pMsgContent, "isStart", start);
|
||||
|
||||
pJsonString = cJSON_PrintUnformatted(pRoot);
|
||||
cJSON_Delete(pRoot);
|
||||
|
||||
res = g_scgProxyCfg.g_tunCtrlCtx->Post(SET_CLIENTSTART_TUNNEL, pJsonString, "application/json");
|
||||
|
||||
if (res.error() != httplib::Error::Success) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "[%s]:Post Data %s error: %s\n", SET_CLIENTSTART_TUNNEL, pJsonString,
|
||||
httplib::to_string(res.error()).c_str());
|
||||
free(pJsonString);
|
||||
return -ERR_HTTP_POST_DATA;
|
||||
}
|
||||
|
||||
if (res->status != 200) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "[%s]:Post Data %s server return HTTP error: %d\n", SET_CLIENTSTART_TUNNEL,
|
||||
pJsonString,
|
||||
res->status);
|
||||
free(pJsonString);
|
||||
return -ERR_HTTP_SERVER_RSP;
|
||||
}
|
||||
|
||||
ANDROID_LOG(ANDROID_LOG_DEBUG, "SCGPROXY", "+++++ Http Request %s\n---- Http Response %s\n", pJsonString, res->body.c_str());
|
||||
|
||||
free(pJsonString);
|
||||
|
||||
if (strlen(res->body.c_str()) == 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Server response empty message.\n");
|
||||
return -ERR_READ_FILE;
|
||||
}
|
||||
|
||||
pRoot = cJSON_Parse(res->body.c_str());
|
||||
|
||||
if (pRoot == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Decode JSON %s Error.\n", res->body.c_str());
|
||||
return -ERR_JSON_DECODE;
|
||||
}
|
||||
|
||||
pMsgContent = cJSON_GetObjectItem(pRoot, "msgContent");
|
||||
|
||||
if (pMsgContent == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Decode(msgContent) JSON %s Error.\n", res->body.c_str());
|
||||
cJSON_Delete(pRoot);
|
||||
return -ERR_JSON_DECODE;
|
||||
}
|
||||
|
||||
rspCode = cJSON_GetObjectItem(pMsgContent, "errCode");
|
||||
|
||||
if (rspCode == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Decode(msgContent.rspCode) JSON %s Error.\n", res->body.c_str());
|
||||
cJSON_Delete(pRoot);
|
||||
return -ERR_JSON_DECODE;
|
||||
}
|
||||
|
||||
cJSON_Delete(pRoot);
|
||||
|
||||
return rspCode->valueint;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 停止远程隧道服务端
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int remote_tunnel_service_stop() {
|
||||
return remote_tunnel_service_control(g_scgProxyCfg.curConnVmId, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 启动远程隧道服务端
|
||||
* @param[in] vmId 云电脑虚拟机 VMID
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int remote_tunnel_service_start(int vmId) {
|
||||
return remote_tunnel_service_control(vmId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置远程隧道参数
|
||||
* @param[in] pCliPubKey 客户端公钥
|
||||
* @param[in] pCliNetwork 客户端共享网络地址
|
||||
* @param[in] pCliTunNetwork 客户端隧道网络地址
|
||||
* @param[out] pSvrNetwork 服务端返回的服务端隧道网络地址
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int remote_tunnel_set_params(const char *pCliPubKey, const char *pCliNetwork, const char *pCliTunNetwork, char *pSvrNetwork) {
|
||||
char *pJsonString;
|
||||
cJSON *pRoot;
|
||||
cJSON *pMsgContent;
|
||||
cJSON *pRspCode;
|
||||
cJSON *pSvrNet;
|
||||
httplib::Result res;
|
||||
|
||||
if (pCliPubKey == nullptr || strlen(pCliPubKey) == 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Input pCliPubKey params error: %s\n", pCliPubKey ? pCliPubKey : "NULL String");
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pCliNetwork == nullptr || strlen(pCliNetwork) == 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Input pCliNetwork params error: %s\n", pCliNetwork ? pCliNetwork : "NULL String");
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pCliTunNetwork == nullptr || strlen(pCliTunNetwork) == 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Input pCliTunNetwork params error: %s\n", pCliTunNetwork ? pCliTunNetwork : "NULL String");
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pSvrNetwork == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Input pSvrNetwork params is null\n");
|
||||
}
|
||||
|
||||
if (g_scgProxyCfg.curConnVmId <= 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Current Unconnect VM, vmid: %d\n", g_scgProxyCfg.curConnVmId);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (!g_scgProxyCfg.isEnable) {
|
||||
ANDROID_LOG(ANDROID_LOG_WARN, "SCGPROXY", "SCG Proxy Service Uninit.\n");
|
||||
return -ERR_SYSTEM_UNINITIALIZE;
|
||||
}
|
||||
|
||||
pRoot = cJSON_CreateObject();
|
||||
|
||||
if (pRoot == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Create JSON Error.\n");
|
||||
return -ERR_JSON_CREATE;
|
||||
}
|
||||
|
||||
cJSON_AddNumberToObject(pRoot, "ver", 1);
|
||||
cJSON_AddNumberToObject(pRoot, "cryptoType", 0);
|
||||
cJSON_AddNumberToObject(pRoot, "timeStamp", time(nullptr));
|
||||
|
||||
pMsgContent = cJSON_CreateObject();
|
||||
if (pMsgContent == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Create JSON Error.\n");
|
||||
cJSON_Delete(pRoot);
|
||||
return -ERR_JSON_CREATE;
|
||||
}
|
||||
|
||||
cJSON_AddItemToObject(pRoot, "msgContent", pMsgContent);
|
||||
cJSON_AddStringToObject(pMsgContent, "cliPublicKey", pCliPubKey);
|
||||
cJSON_AddStringToObject(pMsgContent, "pCliNetwork", pCliNetwork);
|
||||
cJSON_AddStringToObject(pMsgContent, "cliTunnelAddr", pCliTunNetwork);
|
||||
|
||||
pJsonString = cJSON_PrintUnformatted(pRoot);
|
||||
cJSON_Delete(pRoot);
|
||||
|
||||
res = g_scgProxyCfg.g_tunCtrlCtx->Post(SET_CLIENTCFG_PATH, pJsonString, "application/json");
|
||||
|
||||
if (res.error() != httplib::Error::Success) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "[%s]:Post Data %s error: %s\n", SET_CLIENTCFG_PATH, pJsonString,
|
||||
httplib::to_string(res.error()).c_str());
|
||||
free(pJsonString);
|
||||
return -ERR_HTTP_POST_DATA;
|
||||
}
|
||||
|
||||
if (res->status != 200) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "[%s]:Post Data %s server return HTTP error: %d\n", SET_CLIENTCFG_PATH,
|
||||
pJsonString,
|
||||
res->status);
|
||||
free(pJsonString);
|
||||
return -ERR_HTTP_SERVER_RSP;
|
||||
}
|
||||
|
||||
ANDROID_LOG(ANDROID_LOG_DEBUG, "SCGPROXY", "+++++ Http Request %s\n---- Http Response %s\n", pJsonString, res->body.c_str());
|
||||
free(pJsonString);
|
||||
|
||||
if (strlen(res->body.c_str()) == 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Server response empty message.\n");
|
||||
return -ERR_READ_FILE;
|
||||
}
|
||||
|
||||
pRoot = cJSON_Parse(res->body.c_str());
|
||||
|
||||
if (pRoot == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Decode JSON %s Error.\n", res->body.c_str());
|
||||
return -ERR_JSON_DECODE;
|
||||
}
|
||||
|
||||
pMsgContent = cJSON_GetObjectItem(pRoot, "msgContent");
|
||||
|
||||
if (pMsgContent == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Decode(msgContent) JSON %s Error.\n", res->body.c_str());
|
||||
cJSON_Delete(pRoot);
|
||||
return -ERR_JSON_DECODE;
|
||||
}
|
||||
|
||||
pRspCode = cJSON_GetObjectItem(pMsgContent, "errCode");
|
||||
|
||||
if (pRspCode == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Decode(msgContent.pRspCode) JSON %s Error.\n", res->body.c_str());
|
||||
cJSON_Delete(pRoot);
|
||||
return -ERR_JSON_DECODE;
|
||||
}
|
||||
|
||||
if (pRspCode->valueint != 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Server Response Error: %d\n", pRspCode->valueint);
|
||||
cJSON_Delete(pRoot);
|
||||
return -ERR_JSON_DECODE;
|
||||
}
|
||||
|
||||
pSvrNet = cJSON_GetObjectItem(pMsgContent, "svrNetwork");
|
||||
if (pSvrNet == nullptr) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Decode(msgContent.pSvrNet) JSON %s Error.\n", res->body.c_str());
|
||||
cJSON_Delete(pRoot);
|
||||
return -ERR_JSON_DECODE;
|
||||
}
|
||||
|
||||
strcpy(pSvrNetwork, pSvrNet->valuestring);
|
||||
cJSON_Delete(pRoot);
|
||||
return ERR_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <csignal>
|
||||
|
||||
#include "usrerr.h"
|
||||
#include "sccproxy.h"
|
||||
#include "scg-service.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) UNUSED_##x __attribute__((__unused__))
|
||||
#endif
|
||||
|
||||
#define SCG_UDP_HEAD_SIZE (11)
|
||||
#define SIG_CANCEL_SIGNAL SIGUSR1
|
||||
|
||||
typedef struct {
|
||||
unsigned short targetPort;
|
||||
unsigned short proxyPort;
|
||||
int udpProxySock;
|
||||
int scgGwSock;
|
||||
pthread_t hProxyTunnelThread;
|
||||
pthread_t hProxySCGThread;
|
||||
bool exitNow;
|
||||
} SCG_PROXY_INFO, *PSCG_PROXY_INFO;
|
||||
|
||||
static SCG_PROXY_INFO g_scgProxyInfo;
|
||||
|
||||
static int pthread_setcancelstate() {
|
||||
sigset_t newState, old;
|
||||
int ret;
|
||||
sigemptyset(&newState);
|
||||
sigaddset(&newState, SIG_CANCEL_SIGNAL);
|
||||
|
||||
ret = pthread_sigmask(SIG_BLOCK, &newState, &old);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Wireguard 隧道 UDP 代理服务端口
|
||||
* @return 0:当前代理服务端口不可用, >0 UDP 代理服务端口
|
||||
*/
|
||||
unsigned short get_tunnel_proxy_port() {
|
||||
return g_scgProxyInfo.proxyPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 停止 wireguard 隧道 UDP 代理服务
|
||||
*/
|
||||
void stop_wireguard_proxy_server() {
|
||||
PSCG_PROXY_INFO pProxy = &g_scgProxyInfo;
|
||||
pProxy->exitNow = true;
|
||||
|
||||
if (pProxy->hProxyTunnelThread) {
|
||||
pthread_kill(pProxy->hProxyTunnelThread, SIG_CANCEL_SIGNAL);
|
||||
ANDROID_LOG(ANDROID_LOG_INFO, "SCGPROXY", "Proxy Tunnel Thread finished(%ld)...... \n",
|
||||
pProxy->hProxyTunnelThread);
|
||||
pProxy->hProxyTunnelThread = 0;
|
||||
close(pProxy->udpProxySock);
|
||||
}
|
||||
|
||||
if (pProxy->hProxySCGThread) {
|
||||
pthread_kill(pProxy->hProxySCGThread, SIG_CANCEL_SIGNAL);
|
||||
ANDROID_LOG(ANDROID_LOG_INFO, "SCGPROXY", "Proxy SCG Thread finished(%ld)...... \n", pProxy->hProxySCGThread);
|
||||
pProxy->hProxySCGThread = 0;
|
||||
close(pProxy->scgGwSock);
|
||||
}
|
||||
}
|
||||
|
||||
static void *UDPProxvRemoteThread(void *lpParameter) {
|
||||
const auto pPeerSock = static_cast<sockaddr_in *>(lpParameter);
|
||||
PSCG_PROXY_INFO pProxy = &g_scgProxyInfo;
|
||||
|
||||
while (pPeerSock && !pProxy->exitNow) {
|
||||
sockaddr_in remoteWgAddr{};
|
||||
char ipAddr[MAX_IPV4_LEN];
|
||||
|
||||
int addrSize = sizeof(struct sockaddr);
|
||||
char recvBuf[1500];
|
||||
int iRecvBytes;
|
||||
|
||||
// 代理服务 In
|
||||
iRecvBytes = recvfrom(pProxy->scgGwSock,
|
||||
recvBuf,
|
||||
1500,
|
||||
0,
|
||||
reinterpret_cast<struct sockaddr *>(&remoteWgAddr),
|
||||
reinterpret_cast<socklen_t *>(&addrSize));
|
||||
|
||||
memset(ipAddr, 0, MAX_IPV4_LEN);
|
||||
inet_ntop(AF_INET, &remoteWgAddr.sin_addr.s_addr, ipAddr, MAX_IPV4_LEN);
|
||||
|
||||
if (iRecvBytes != -1) {
|
||||
int sendBytes = sendto(pProxy->udpProxySock,
|
||||
recvBuf,
|
||||
iRecvBytes,
|
||||
0,
|
||||
reinterpret_cast<struct sockaddr *>(pPeerSock),
|
||||
sizeof(struct sockaddr));
|
||||
if (sendBytes != iRecvBytes) {
|
||||
ANDROID_LOG(ANDROID_LOG_WARN, "SCGPROXY", "Porxy Send Data Error(%d): %d/%d\n", errno, sendBytes, iRecvBytes);
|
||||
}
|
||||
} else {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", ">>> Scoket In %d Recv %d bytes from %s:%d error %d\n", iRecvBytes,
|
||||
pProxy->scgGwSock,
|
||||
ipAddr,
|
||||
ntohs(remoteWgAddr.sin_port),
|
||||
errno);
|
||||
}
|
||||
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
pthread_detach(pthread_self());
|
||||
pthread_exit(nullptr);
|
||||
}
|
||||
|
||||
static void *UDPProxyRecvThread(void *UNUSED(lpParameter)) {
|
||||
bool isRemoteInit = false;
|
||||
sockaddr_in localWgAddr{};
|
||||
sockaddr_in scgAddr{};
|
||||
unsigned char recvBuf[1500 + SCG_UDP_HEAD_SIZE];
|
||||
PSCG_PROXY_INFO pProxy = &g_scgProxyInfo;
|
||||
char *pRecBuf = reinterpret_cast<char *>(&recvBuf[SCG_UDP_HEAD_SIZE]);
|
||||
|
||||
scgAddr.sin_family = AF_INET;
|
||||
scgAddr.sin_port = htons(get_scg_proxy_port());
|
||||
inet_pton(AF_INET, get_scg_proxy_ipaddr(), &scgAddr.sin_addr.s_addr);
|
||||
|
||||
// 构建 SCG UDP 包头
|
||||
recvBuf[0] = 0x01; // VERSION
|
||||
recvBuf[1] = 0x09; // Length
|
||||
recvBuf[2] = 0xF0; // ++++++ INFO[0] TYPE
|
||||
recvBuf[3] = 0x04; // INFO[0] LENGTH
|
||||
recvBuf[4] = 0; // INFO[0] VMID[0]
|
||||
recvBuf[5] = 0; // INFO[0] VMID[1]
|
||||
recvBuf[6] = 0; // INFO[0] VMID[2]
|
||||
recvBuf[7] = 0; // INFO[0] VMID[3]
|
||||
recvBuf[8] = 0xF1; // INFO[1] TYPE
|
||||
recvBuf[9] = 0x01; // INFO[1] LENGTH
|
||||
recvBuf[10] = WG_TUNNEL_SCG_ID; // ------ INFO[1] SCG Service ID
|
||||
|
||||
pProxy->exitNow = false;
|
||||
while (!pProxy->exitNow) {
|
||||
char ipAddr[MAX_IPV4_LEN];
|
||||
int addrSize = sizeof(struct sockaddr);
|
||||
int iRecvBytes;
|
||||
|
||||
// 代理服务 Out
|
||||
iRecvBytes = recvfrom(pProxy->udpProxySock,
|
||||
pRecBuf,
|
||||
1500,
|
||||
0,
|
||||
reinterpret_cast<struct sockaddr *>(&localWgAddr),
|
||||
reinterpret_cast<socklen_t *>(&addrSize));
|
||||
|
||||
inet_ntop(AF_INET, &localWgAddr.sin_addr.s_addr, ipAddr, MAX_IPV4_LEN);
|
||||
|
||||
if (iRecvBytes != -1) {
|
||||
int sendBytes;
|
||||
const unsigned int id = htonl(get_scg_cur_vmid());
|
||||
unsigned char vmid[4];
|
||||
memcpy(vmid, &id, 4);
|
||||
|
||||
if (!isRemoteInit) {
|
||||
int ret;
|
||||
isRemoteInit = true;
|
||||
|
||||
if ((ret = pthread_create(&pProxy->hProxySCGThread, nullptr, UDPProxvRemoteThread, &localWgAddr)) != 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Create Thread failed with error(%d): %d\n", errno, ret);
|
||||
close(pProxy->udpProxySock);
|
||||
close(pProxy->scgGwSock);
|
||||
pProxy->exitNow = true;
|
||||
pthread_detach(pthread_self());
|
||||
pthread_exit(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
recvBuf[4] = vmid[0]; // INFO[0] VMID[0]
|
||||
recvBuf[5] = vmid[1]; // INFO[0] VMID[1]
|
||||
recvBuf[6] = vmid[2]; // INFO[0] VMID[2]
|
||||
recvBuf[7] = vmid[3]; // INFO[0] VMID[3]
|
||||
|
||||
// 增加SCG包头数据长度
|
||||
iRecvBytes += 11;
|
||||
|
||||
sendBytes = sendto(pProxy->scgGwSock,
|
||||
reinterpret_cast<char *>(recvBuf),
|
||||
iRecvBytes,
|
||||
0,
|
||||
reinterpret_cast<struct sockaddr *>(&scgAddr),
|
||||
sizeof(struct sockaddr));
|
||||
|
||||
if (sendBytes != iRecvBytes) {
|
||||
ANDROID_LOG(ANDROID_LOG_WARN, "SCGPROXY", "Porxy Send Data Error(%d): %d/%d\n", errno, sendBytes, iRecvBytes);
|
||||
}
|
||||
}
|
||||
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
pthread_detach(pthread_self());
|
||||
pthread_exit(nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 创建 wireguard 隧道 UDP 代理服务
|
||||
* @param[out] pPorxyPort 当前 UDP 代理服务使用的端口,代理 IP 地址固定为 127.0.0.1
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
*/
|
||||
int create_wireguard_proxy_server(unsigned short *pPorxyPort) {
|
||||
int ret;
|
||||
int addrSize = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in server = {};
|
||||
struct sockaddr_in bindAddr = {};
|
||||
int sock;
|
||||
PSCG_PROXY_INFO pProxy = &g_scgProxyInfo;
|
||||
|
||||
pthread_setcancelstate();
|
||||
|
||||
memset(&g_scgProxyInfo, 0, sizeof(SCG_PROXY_INFO));
|
||||
|
||||
// 创建本地 SOCKET 代理服务器
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == -1) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Create UDP Socket failed with error: %d\n", errno);
|
||||
return -ERR_SOCKET_CREATE;
|
||||
}
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
server.sin_port = htons(0);
|
||||
|
||||
if (bind(sock, reinterpret_cast<struct sockaddr *>(&server), sizeof(struct sockaddr_in)) == -1) {
|
||||
close(sock);
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Bind local UDP Socket failed with error: %d\n", errno);
|
||||
return -ERR_SOCKET_BIND;
|
||||
}
|
||||
|
||||
if ((ret = getsockname(sock, reinterpret_cast<struct sockaddr *>(&bindAddr), reinterpret_cast<socklen_t *>(&addrSize))) != 0) {
|
||||
close(sock);
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Get UDP Socket bind port failed with error(%d): %d\n", errno, ret);
|
||||
return -ERR_SOCKET_BIND;
|
||||
}
|
||||
|
||||
// 保存 UDP 代理服务器信息
|
||||
pProxy->udpProxySock = sock;
|
||||
pProxy->proxyPort = ntohs(bindAddr.sin_port);
|
||||
|
||||
if (pPorxyPort) {
|
||||
*pPorxyPort = pProxy->proxyPort;
|
||||
}
|
||||
|
||||
ANDROID_LOG(ANDROID_LOG_DEBUG, "SCGPROXY", "Proxy Server socket {%d} bind {%d} port\n", sock, pProxy->proxyPort);
|
||||
|
||||
// 创建SCG SOCKET 连接客户端服务
|
||||
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock == -1) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Create UDP Socket failed with error: %d\n", errno);
|
||||
close(pProxy->udpProxySock);
|
||||
return -ERR_SOCKET_CREATE;
|
||||
}
|
||||
|
||||
pProxy->scgGwSock = sock;
|
||||
|
||||
// 创建代理服务发送线程
|
||||
if ((ret = pthread_create(&pProxy->hProxyTunnelThread, nullptr, UDPProxyRecvThread, nullptr)) != 0) {
|
||||
ANDROID_LOG(ANDROID_LOG_ERROR, "SCGPROXY", "Create Thread failed with error(%d) : %d\n", errno, ret);
|
||||
close(pProxy->udpProxySock);
|
||||
close(pProxy->scgGwSock);
|
||||
return -ERR_CREATE_THREAD;
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.example.sccproxy;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.example.sccproxy.databinding.ActivityMainBinding;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
// Used to load the 'sccproxy' library on application startup.
|
||||
static {
|
||||
System.loadLibrary("sccproxy");
|
||||
}
|
||||
|
||||
private ActivityMainBinding binding;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
// Example of a call to a native method
|
||||
TextView tv = binding.sampleText;
|
||||
tv.setText(stringFromJNI());
|
||||
}
|
||||
|
||||
/**
|
||||
* A native method that is implemented by the 'sccproxy' native library,
|
||||
* which is packaged with this application.
|
||||
*/
|
||||
public native String stringFromJNI();
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
|
@ -0,0 +1,30 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sample_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 982 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 7.6 KiB |
|
@ -0,0 +1,16 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.Sccproxy" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_200</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/black</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">sccproxy</string>
|
||||
</resources>
|
|
@ -0,0 +1,16 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.Sccproxy" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_500</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
|
@ -0,0 +1,17 @@
|
|||
package com.example.sccproxy;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id("com.android.application") version "8.1.2" apply false
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
|
@ -0,0 +1,6 @@
|
|||
#Thu Oct 12 09:37:52 CST 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
|
@ -0,0 +1,185 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
|
@ -0,0 +1,89 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
|
@ -0,0 +1,17 @@
|
|||
pluginManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "sccproxy"
|
||||
include(":app")
|