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")
|