mirror of https://github.com/LeOS-GSI/LeOS-Genesis
parent
dfec66447b
commit
2792fc6d62
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="deploymentTargetDropDown">
|
|
||||||
<targetSelectedWithDropDown>
|
|
||||||
<Target>
|
|
||||||
<type value="QUICK_BOOT_TARGET" />
|
|
||||||
<deviceKey>
|
|
||||||
<Key>
|
|
||||||
<type value="VIRTUAL_DEVICE_PATH" />
|
|
||||||
<value value="C:\Users\Dell\.android\avd\Pixel_2_API_Tiramisu.avd" />
|
|
||||||
</Key>
|
|
||||||
</deviceKey>
|
|
||||||
</Target>
|
|
||||||
</targetSelectedWithDropDown>
|
|
||||||
<timeTargetWasSelectedWithDropDown value="2022-03-29T19:14:13.074412300Z" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
|
@ -2,9 +2,7 @@ plugins {
|
||||||
id "com.jetbrains.python.envs" version "0.0.26"
|
id "com.jetbrains.python.envs" version "0.0.26"
|
||||||
}
|
}
|
||||||
|
|
||||||
ext.gleanExpireByVersion = 1
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: "org.mozilla.telemetry.glean-gradle-plugin"
|
|
||||||
apply from: 'variables.gradle'
|
apply from: 'variables.gradle'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
|
@ -30,10 +28,6 @@ android {
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
dexOptions {
|
|
||||||
preDexLibraries project.ext.preDexLibraries
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled project.ext.minifyEnabled
|
minifyEnabled project.ext.minifyEnabled
|
||||||
|
@ -74,79 +68,60 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
/* Android Support Repository dependencies */
|
|
||||||
|
/* File Support Dependencies */
|
||||||
|
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
implementation files('libs/httpclientandroidlib-1.2.1.jar')
|
||||||
|
|
||||||
|
/* Android Support Repository Dependencies */
|
||||||
|
|
||||||
/* Default Libraries */
|
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||||
|
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'
|
||||||
|
implementation 'com.google.android.material:material:1.5.0'
|
||||||
|
implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.6.10'
|
||||||
|
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10'
|
||||||
|
implementation 'org.apache.commons:commons-text:1.3'
|
||||||
|
implementation 'androidx.work:work-runtime-ktx:2.8.0-alpha01'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
|
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
|
||||||
|
implementation 'androidx.preference:preference-ktx:1.2.0'
|
||||||
|
implementation 'com.android.support:support-annotations:29.0.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
|
|
||||||
/* Firefox ABI Splits */
|
/* Firefox ABI Splits */
|
||||||
|
|
||||||
// implementation "androidx.compose.foundation:foundation:1.0.4"
|
implementation "androidx.compose.foundation:foundation:1.1.1"
|
||||||
// implementation "org.mozilla.components:browser-engine-gecko:100.0.20220327143103"
|
|
||||||
implementation "androidx.compose.foundation:foundation:1.0.4"
|
|
||||||
implementation "org.mozilla.components:browser-engine-gecko:100.0.20220327143103"
|
implementation "org.mozilla.components:browser-engine-gecko:100.0.20220327143103"
|
||||||
implementation "org.mozilla.components:service-glean:100.0.20220327143103"
|
|
||||||
implementation "org.mozilla.components:support-rusthttp:100.0.20220327143103"
|
implementation "org.mozilla.components:support-rusthttp:100.0.20220327143103"
|
||||||
implementation "org.mozilla.components:support-rustlog:100.0.20220327143103"
|
implementation "org.mozilla.components:support-rustlog:100.0.20220327143103"
|
||||||
|
|
||||||
implementation "org.mozilla.components:browser-icons:100.0.20220327143103"
|
implementation "org.mozilla.components:browser-icons:100.0.20220327143103"
|
||||||
implementation "org.mozilla.components:concept-fetch:100.0.20220327143103"
|
implementation "org.mozilla.components:concept-fetch:100.0.20220327143103"
|
||||||
implementation "org.mozilla.components:concept-base:100.0.20220327143103"
|
implementation "org.mozilla.components:concept-base:100.0.20220327143103"
|
||||||
implementation "org.mozilla.components:support-utils:100.0.20220327143103"
|
implementation "org.mozilla.components:support-utils:100.0.20220327143103"
|
||||||
|
|
||||||
|
/* Analytics */
|
||||||
|
|
||||||
/* Android Support Repository dependencies */
|
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
||||||
|
|
||||||
|
|
||||||
/* Default Libraries */
|
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
|
||||||
|
|
||||||
/* Firefox ABI Splits */
|
|
||||||
|
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
|
||||||
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
|
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
|
||||||
implementation 'androidx.preference:preference-ktx:1.2.0'
|
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
|
||||||
|
|
||||||
|
|
||||||
implementation 'com.flurry.android:analytics:13.1.0@aar'
|
implementation 'com.flurry.android:analytics:13.1.0@aar'
|
||||||
|
|
||||||
/* Ads Manager */
|
/* Ads Manager */
|
||||||
|
|
||||||
implementation 'com.android.support:support-annotations:29.0.0'
|
implementation 'com.facebook.android:audience-network-sdk:6.8.0'
|
||||||
implementation 'com.facebook.android:audience-network-sdk:6.6.0'
|
implementation 'com.applovin:applovin-sdk:11.3.1'
|
||||||
implementation 'com.mopub.mediation:facebookaudiencenetwork:6.6.0.0'
|
implementation 'com.applovin.mediation:facebook-adapter:6.8.0.12'
|
||||||
implementation 'com.applovin:applovin-sdk:+'
|
|
||||||
implementation 'com.applovin.mediation:facebook-adapter:+'
|
|
||||||
/* Crawler Service */
|
|
||||||
|
|
||||||
implementation 'org.jsoup:jsoup:1.13.1'
|
|
||||||
|
|
||||||
/* Orbot Service */
|
/* Orbot Service */
|
||||||
|
|
||||||
implementation project(path: ':orbotmanager')
|
implementation project(path: ':orbotmanager')
|
||||||
|
|
||||||
/* Helper Libraries */
|
/* Helper Libraries */
|
||||||
implementation 'androidx.work:work-runtime-ktx:2.7.0-alpha05'
|
|
||||||
implementation files('libs/httpclientandroidlib-1.2.1.jar')
|
|
||||||
implementation 'com.coolerfall:android-http-download-manager:1.6.3'
|
implementation 'com.coolerfall:android-http-download-manager:1.6.3'
|
||||||
implementation 'com.android.volley:volley:1.2.1'
|
implementation 'com.android.volley:volley:1.2.1'
|
||||||
implementation "net.zetetic:android-database-sqlcipher:4.4.3"
|
implementation "net.zetetic:android-database-sqlcipher:4.4.3"
|
||||||
implementation "androidx.sqlite:sqlite-ktx:2.2.0"
|
implementation "androidx.sqlite:sqlite-ktx:2.2.0"
|
||||||
implementation 'androidx.palette:palette-ktx:1.0.0'
|
implementation 'androidx.palette:palette-ktx:1.0.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
implementation 'org.jsoup:jsoup:1.13.1'
|
||||||
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'
|
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.31"
|
|
||||||
implementation 'org.apache.commons:commons-text:1.3'
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
{
|
|
||||||
"project_info": {
|
|
||||||
"project_number": "1026582312920",
|
|
||||||
"firebase_url": "https://genesis-5cc48.firebaseio.com",
|
|
||||||
"project_id": "genesis-5cc48",
|
|
||||||
"storage_bucket": "genesis-5cc48.appspot.com"
|
|
||||||
},
|
|
||||||
"client": [
|
|
||||||
{
|
|
||||||
"client_info": {
|
|
||||||
"mobilesdk_app_id": "1:1026582312920:android:056aacc3b6f0c3b3f164ad",
|
|
||||||
"android_client_info": {
|
|
||||||
"package_name": "com.darkweb.genesissearchengine.production"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "1026582312920-ciidt1n08e3fh9akdrn38ph6on2c7d95.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"api_key": [
|
|
||||||
{
|
|
||||||
"current_key": "AIza SyBMzD4SV_-2_2tG9E5a475k5OkwP9V-Naw"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"services": {
|
|
||||||
"appinvite_service": {
|
|
||||||
"other_platform_oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "1026582312920-ciidt1n08e3fh9akdrn38ph6on2c7d95.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"configuration_version": "1"
|
|
||||||
}
|
|
Binary file not shown.
|
@ -1,24 +0,0 @@
|
||||||
package com.example.myapplication
|
|
||||||
|
|
||||||
import android.support.test.InstrumentationRegistry
|
|
||||||
import android.support.test.runner.AndroidJUnit4
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
fun useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
val appContext = InstrumentationRegistry.getTargetContext()
|
|
||||||
assertEquals("com.example.myapplication", appContext.packageName)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,42 +27,25 @@
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
tools:targetApi="n">
|
tools:targetApi="n">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:name="com.hiddenservices.onionservices.appManager.advertManager.advertController"
|
android:name="com.hiddenservices.onionservices.appManager.advertManager.advertController"
|
||||||
android:exported="true" />
|
android:exported="true" />
|
||||||
|
|
||||||
<uses-library
|
|
||||||
android:name="org.apache.http.legacy"
|
|
||||||
android:required="false" />
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="applovin.sdk.key"
|
|
||||||
android:value="hGlhanpemGqPOKKAgaXvhyxwZaG9uD68csy1OadWTNhEgKvBWR7-7KSpyFr6nfZ4KMOuBBV5J49s2LLSg-SVxg" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.bookmarkManager.bookmarkSettings.bookmarkSettingController"
|
android:name="com.hiddenservices.onionservices.appManager.bookmarkManager.bookmarkSettings.bookmarkSettingController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name="com.widget.onionservices.widgetManager.widgetController"
|
|
||||||
android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.appwidget.provider"
|
|
||||||
android:resource="@xml/search_widget_manager_info" />
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.orbotManager.orbotController"
|
android:name="com.hiddenservices.onionservices.appManager.orbotManager.orbotController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" />
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.proxyStatusManager.proxyStatusController"
|
android:name="com.hiddenservices.onionservices.appManager.proxyStatusManager.proxyStatusController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" />
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.settingHomeManager.settingHomeController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.settingHomeManager.settingHomeController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
|
@ -70,71 +53,87 @@
|
||||||
android:label="@string/SETTING_HEADER"
|
android:label="@string/SETTING_HEADER"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.historyManager.historyController"
|
android:name="com.hiddenservices.onionservices.appManager.historyManager.historyController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.bookmarkManager.bookmarkHome.bookmarkController"
|
android:name="com.hiddenservices.onionservices.appManager.bookmarkManager.bookmarkHome.bookmarkController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.languageManager.languageController"
|
android:name="com.hiddenservices.onionservices.appManager.languageManager.languageController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:label="@string/SETTING_HEADER"
|
android:label="@string/SETTING_HEADER"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.helpManager.helpController"
|
android:name="com.hiddenservices.onionservices.appManager.helpManager.helpController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:label="@string/SETTING_HEADER"
|
android:label="@string/SETTING_HEADER"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.accessibilityManager.settingAccessibilityController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.accessibilityManager.settingAccessibilityController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:label="@string/SETTING_HEADER"
|
android:label="@string/SETTING_HEADER"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.clearManager.settingClearController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.clearManager.settingClearController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:label="@string/SETTING_HEADER"
|
android:label="@string/SETTING_HEADER"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.bridgeManager.bridgeController"
|
android:name="com.hiddenservices.onionservices.appManager.bridgeManager.bridgeController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.notificationManager.settingNotificationController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.notificationManager.settingNotificationController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.privacyManager.settingPrivacyController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.privacyManager.settingPrivacyController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.logManager.settingLogController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.logManager.settingLogController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.advanceManager.settingAdvanceController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.advanceManager.settingAdvanceController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.orbotLogManager.orbotLogController"
|
android:name="com.hiddenservices.onionservices.appManager.orbotLogManager.orbotLogController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.generalManager.settingGeneralController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.generalManager.settingGeneralController"
|
||||||
android:configChanges="uiMode"
|
android:configChanges="uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.searchEngineManager.settingSearchController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.searchEngineManager.settingSearchController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.settingManager.trackingManager.settingTrackingController"
|
android:name="com.hiddenservices.onionservices.appManager.settingManager.trackingManager.settingTrackingController"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.homeManager.homeController.homeController"
|
android:name="com.hiddenservices.onionservices.appManager.homeManager.homeController.homeController"
|
||||||
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize|locale|layoutDirection|smallestScreenSize|screenLayout"
|
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize|locale|layoutDirection|smallestScreenSize|screenLayout"
|
||||||
|
@ -153,6 +152,7 @@
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.homeManager.FakeLauncherActivity"
|
android:name="com.hiddenservices.onionservices.appManager.homeManager.FakeLauncherActivity"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
|
@ -164,6 +164,7 @@
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.hiddenservices.onionservices.appManager.externalCommandManager.externalShortcutController"
|
android:name="com.hiddenservices.onionservices.appManager.externalCommandManager.externalShortcutController"
|
||||||
android:launchMode="singleTop" />
|
android:launchMode="singleTop" />
|
||||||
|
@ -185,44 +186,61 @@
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity> <!-- Services & Settings -->
|
</activity>
|
||||||
|
|
||||||
|
<!-- Meta and Library & Settings -->
|
||||||
|
|
||||||
<uses-library
|
<uses-library
|
||||||
android:name="org.apache.http.legacy"
|
android:name="org.apache.http.legacy"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.fabric.ApiKey"
|
android:name="io.fabric.ApiKey"
|
||||||
android:value="be76c64dae2519d4ab8daaed88298da14c7c294f" /> <!-- Live Build -->
|
android:value="be76c64dae2519d4ab8daaed88298da14c7c294f" />
|
||||||
<!-- -->
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
android:name="applovin.sdk.key"
|
||||||
android:value="ca-app-pub-9270431839140630~7031430442" /> <!-- Development Build -->
|
android:value="hGlhanpemGqPOKKAgaXvhyxwZaG9uD68csy1OadWTNhEgKvBWR7-7KSpyFr6nfZ4KMOuBBV5J49s2LLSg-SVxg" />
|
||||||
<!--
|
|
||||||
<meta-data
|
<uses-library
|
||||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
android:name="org.apache.http.legacy"
|
||||||
android:value="ca-app-pub-6985886044951738~4177628900" />
|
android:required="false" />
|
||||||
-->
|
|
||||||
|
|
||||||
|
<!-- Services & Settings -->
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name="com.hiddenservices.onionservices.pluginManager.downloadPluginManager.downloadService"
|
android:name="com.hiddenservices.onionservices.pluginManager.downloadPluginManager.downloadService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="false"
|
||||||
android:stopWithTask="true" />
|
android:stopWithTask="true" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name="com.hiddenservices.onionservices.appManager.activityStateManager"
|
android:name="com.hiddenservices.onionservices.appManager.activityStateManager"
|
||||||
android:stopWithTask="true" />
|
android:stopWithTask="true" />
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name="org.orbotproject.android.service.OrbotService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false"
|
||||||
|
android:stopWithTask="true" />
|
||||||
|
|
||||||
|
<!-- Reciever & Settings -->
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name="com.hiddenservices.onionservices.pluginManager.notificationPluginManager.localEngagementManager"
|
android:name="com.hiddenservices.onionservices.pluginManager.notificationPluginManager.localEngagementManager"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:permission="TODO"
|
android:permission="TODO"
|
||||||
tools:ignore="ExportedReceiver" />
|
tools:ignore="ExportedReceiver" />
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name="com.hiddenservices.onionservices.pluginManager.pluginReciever.downloadNotificationReciever"
|
android:name="com.hiddenservices.onionservices.pluginManager.pluginReciever.downloadNotificationReciever"
|
||||||
android:exported="true">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="Download_Cancelled" />
|
<action android:name="Download_Cancelled" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name="org.orbotproject.android.service.StartTorReceiver"
|
android:name="org.orbotproject.android.service.StartTorReceiver"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -232,46 +250,61 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name="com.widget.onionservices.widgetManager.widgetController"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/search_widget_manager_info" />
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<!-- Providers & Settings -->
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="com.hiddenservices.onionservices.provider"
|
android:authorities="com.hiddenservices.onionservices.provider"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:grantUriPermissions="true">
|
android:grantUriPermissions="true"
|
||||||
|
tools:ignore="ExportedContentProvider">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/provider_paths" />
|
android:resource="@xml/provider_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="com.hiddenservices.onionservices.libs.providers.HSContentProvider"
|
android:name="com.hiddenservices.onionservices.libs.providers.HSContentProvider"
|
||||||
android:authorities="org.torproject.android.ui.hiddenservices.providers.genesishiddenservices"
|
android:authorities="org.torproject.android.ui.hiddenservices.providers.genesishiddenservices"
|
||||||
android:exported="true" />
|
android:exported="false" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="com.hiddenservices.onionservices.libs.providers.OnionServiceContentProvider"
|
android:name="com.hiddenservices.onionservices.libs.providers.OnionServiceContentProvider"
|
||||||
android:authorities="org.torproject.android.ui.v3onionservice.genesishiddenservices"
|
android:authorities="org.torproject.android.ui.v3onionservice.genesishiddenservices"
|
||||||
android:exported="true" />
|
android:exported="false" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="com.hiddenservices.onionservices.libs.providers.ClientAuthContentProviderGenesis"
|
android:name="com.hiddenservices.onionservices.libs.providers.ClientAuthContentProviderGenesis"
|
||||||
android:authorities="org.torproject.android.ui.v3onionservice.genesishiddenservices.clientauth"
|
android:authorities="org.torproject.android.ui.v3onionservice.genesishiddenservices.clientauth"
|
||||||
android:exported="true" />
|
android:exported="false" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="com.hiddenservices.onionservices.libs.providers.CookieContentProvider"
|
android:name="com.hiddenservices.onionservices.libs.providers.CookieContentProvider"
|
||||||
android:authorities="org.torproject.android.ui.hiddenservices.providers.genesishiddenservices.cookie"
|
android:authorities="org.torproject.android.ui.hiddenservices.providers.genesishiddenservices.cookie"
|
||||||
android:exported="true" />
|
android:exported="false" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.fileprovider"
|
android:authorities="${applicationId}.fileprovider"
|
||||||
android:exported="true"
|
android:exported="false"
|
||||||
android:grantUriPermissions="true">
|
android:grantUriPermissions="true">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/file_path" />
|
android:resource="@xml/file_path" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<service
|
|
||||||
android:name="org.orbotproject.android.service.OrbotService"
|
|
||||||
android:enabled="true"
|
|
||||||
android:exported="true"
|
|
||||||
android:stopWithTask="true" />
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -0,0 +1,56 @@
|
||||||
|
# Contents of /data/local/tmp/com.yourcompany.yourapp-geckoview-config.yaml
|
||||||
|
|
||||||
|
env:
|
||||||
|
MOZ_LOG: nsHttp:5
|
||||||
|
|
||||||
|
|
||||||
|
prefs:
|
||||||
|
network.proxy.type: 1
|
||||||
|
# network.proxy.socks: "127.0.0.1"
|
||||||
|
# network.proxy.socks_port: 9050
|
||||||
|
network.proxy.socks_version: 5
|
||||||
|
network.proxy.socks_remote_dns: true
|
||||||
|
permissions.default.image: 1
|
||||||
|
browser.display.show_image_placeholders: true
|
||||||
|
browser.cache.disk.enable: false
|
||||||
|
browser.cache.memory.enable: true
|
||||||
|
browser.cache.disk.capacity: 0
|
||||||
|
privacy.resistFingerprinting: true
|
||||||
|
privacy.donottrackheader.enabled: false
|
||||||
|
privacy.donottrackheader.value: 1
|
||||||
|
network.http.sendRefererHeader: 0
|
||||||
|
security.checkloaduri: false
|
||||||
|
security.mixed_content.block_active_content: false
|
||||||
|
security.mixed_content.block_display_content: false
|
||||||
|
media.peerconnection.enabled: false //webrtc disabled
|
||||||
|
browser.cache.disk_cache_ssl: true
|
||||||
|
signon.formlessCapture.enabled: true
|
||||||
|
signon.storeWhenAutocompleteOff: true
|
||||||
|
dom.event.contextmenu.enabled: true
|
||||||
|
layout.css.visited_links_enabled: true
|
||||||
|
security.ssl3.ecdhe_rsa_aes_128_sha: true
|
||||||
|
security.ssl3.ecdhe_ecdsa_aes_128_sha: true
|
||||||
|
security.ssl3.dhe_rsa_aes_128_sha: true
|
||||||
|
security.ssl3.rsa_des_ede3_sha: true
|
||||||
|
security.ssl3.dhe_rsa_aes_256_sha: true
|
||||||
|
browser.safebrowsing.blockedURIs.enabled: false
|
||||||
|
media.gmp-provider.enabled: false
|
||||||
|
browser.send_pings.require_same_host: false
|
||||||
|
webgl.disabled: false
|
||||||
|
pdfjs.enableWebGL: false
|
||||||
|
browser.safebrowsing.malware.enabled: false
|
||||||
|
security.csp.experimentalEnabled: false
|
||||||
|
network.http.referer.spoofSource: false
|
||||||
|
security.OCSP.require: false
|
||||||
|
security.ssl.require_safe_negotiation: false
|
||||||
|
privacy.clearOnShutdown.cache: true
|
||||||
|
privacy.clearOnShutdown.downloads: true
|
||||||
|
privacy.clearOnShutdown.formdata: true
|
||||||
|
privacy.clearOnShutdown.history: true
|
||||||
|
privacy.clearOnShutdown.offlineApps: true
|
||||||
|
privacy.clearOnShutdown.passwords: true
|
||||||
|
privacy.clearOnShutdown.sessions: true
|
||||||
|
privacy.clearOnShutdown.siteSettings: true
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ import static org.mozilla.geckoview.StorageController.ClearFlags.PERMISSIONS;
|
||||||
import static org.mozilla.geckoview.StorageController.ClearFlags.SITE_DATA;
|
import static org.mozilla.geckoview.StorageController.ClearFlags.SITE_DATA;
|
||||||
import static org.mozilla.geckoview.StorageController.ClearFlags.SITE_SETTINGS;
|
import static org.mozilla.geckoview.StorageController.ClearFlags.SITE_SETTINGS;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
//import org.mozilla.gecko.PrefsHelper;
|
|
||||||
import org.mozilla.geckoview.ContentBlocking;
|
import org.mozilla.geckoview.ContentBlocking;
|
||||||
import org.mozilla.geckoview.GeckoRuntime;
|
import org.mozilla.geckoview.GeckoRuntime;
|
||||||
import org.mozilla.geckoview.GeckoRuntimeSettings;
|
import org.mozilla.geckoview.GeckoRuntimeSettings;
|
||||||
|
@ -64,25 +63,32 @@ public class geckoClients
|
||||||
{
|
{
|
||||||
this.event = event;
|
this.event = event;
|
||||||
mSessionID = helperMethod.createRandomID();
|
mSessionID = helperMethod.createRandomID();
|
||||||
initRuntimeSettings(context);
|
//initRuntimeSettings(context);
|
||||||
|
|
||||||
if(!isForced && geckoView.getSession()!=null && geckoView.getSession().isOpen()){
|
if(!isForced && geckoView.getSession()!=null && geckoView.getSession().isOpen()){
|
||||||
mSession = (geckoSession) geckoView.getSession();
|
mSession = (geckoSession) geckoView.getSession();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(geckoView.getSession()!=null){
|
if(geckoView.getSession()!=null){
|
||||||
geckoView.releaseSession();
|
//geckoView.releaseSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
mSession = new geckoSession(new geckoViewClientCallback(),mSessionID,context, geckoView);
|
mSession = new geckoSession(new geckoViewClientCallback(),mSessionID,context, geckoView);
|
||||||
mSession.open(mRuntime);
|
//mSession.open(mRuntime);
|
||||||
mSession.getSettings().setUseTrackingProtection(status.sStatusDoNotTrack);
|
mSession.getSettings().setUseTrackingProtection(status.sStatusDoNotTrack);
|
||||||
mSession.getSettings().setFullAccessibilityTree(true);
|
mSession.getSettings().setFullAccessibilityTree(true);
|
||||||
mSession.getSettings().setUserAgentMode(USER_AGENT_MODE_MOBILE);
|
mSession.getSettings().setUserAgentMode(USER_AGENT_MODE_MOBILE);
|
||||||
mSession.getSettings().setAllowJavascript(status.sSettingJavaStatus);
|
mSession.getSettings().setAllowJavascript(status.sSettingJavaStatus);
|
||||||
geckoView.setSession(mSession);
|
//geckoView.setSession(mSession);
|
||||||
}
|
}
|
||||||
mSession.onSetInitializeFromStartup();
|
mSession.onSetInitializeFromStartup();
|
||||||
|
//onUpdateFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postInitRuntime(GeckoView geckoView, AppCompatActivity context){
|
||||||
|
initRuntimeSettings(context);
|
||||||
|
mSession.open(mRuntime);
|
||||||
|
geckoView.setSession(mSession);
|
||||||
onUpdateFont();
|
onUpdateFont();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +180,19 @@ public class geckoClients
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String mYAML = helperMethod.readFromFile(cacheFile.getPath());
|
||||||
|
mYAML = mYAML.replace("# network.proxy.socks: \"127.0.0.1\"","network.proxy.socks: \"127.0.0.1\"");
|
||||||
|
mYAML = mYAML.replace("# network.proxy.socks_port: 9050","network.proxy.socks_port: 9050");
|
||||||
|
mYAML = mYAML.replace("network.proxy.socks: \"127.0.0.1\"","network.proxy.socks: \"127.0.0.1\"");
|
||||||
|
|
||||||
|
StringBuilder buf = new StringBuilder(mYAML);
|
||||||
|
int portIndex = mYAML.indexOf("network.proxy.socks_port");
|
||||||
|
int breakIndex = mYAML.indexOf("\n",portIndex);
|
||||||
|
mYAML = buf.replace(portIndex, breakIndex,"network.proxy.socks_port: "+ orbotLocalConstants.mSOCKSPort).toString();
|
||||||
|
helperMethod.writeToFile(cacheFile.getPath(), mYAML);
|
||||||
|
|
||||||
|
|
||||||
return cacheFile.getAbsolutePath();
|
return cacheFile.getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,15 +281,6 @@ public class geckoClients
|
||||||
}
|
}
|
||||||
mSettings.build();
|
mSettings.build();
|
||||||
|
|
||||||
/*PrefsHelper.setPref("browser.cache.disk.enable",true);
|
|
||||||
PrefsHelper.setPref("browser.cache.memory.enable",true);
|
|
||||||
PrefsHelper.setPref("browser.cache.disk.capacity",1000);
|
|
||||||
PrefsHelper.setPref(keys.PROXY_TYPE, 1);
|
|
||||||
PrefsHelper.setPref(keys.PROXY_SOCKS,"127.0.0.1");
|
|
||||||
PrefsHelper.setPref(keys.PROXY_SOCKS_PORT, orbotLocalConstants.mSOCKSPort);
|
|
||||||
PrefsHelper.setPref(keys.PROXY_SOCKS_VERSION,5);
|
|
||||||
PrefsHelper.setPref(keys.PROXY_SOCKS_REMOTE_DNS,true);*/
|
|
||||||
|
|
||||||
mRuntime = GeckoRuntime.create(context, mSettings.build());
|
mRuntime = GeckoRuntime.create(context, mSettings.build());
|
||||||
mRuntime.getSettings().setRemoteDebuggingEnabled(true);
|
mRuntime.getSettings().setRemoteDebuggingEnabled(true);
|
||||||
installExtension();
|
installExtension();
|
||||||
|
@ -312,7 +322,7 @@ public class geckoClients
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("WrongConstant")
|
@SuppressLint("WrongConstant")
|
||||||
public void updateSetting(NestedGeckoView mNestedGeckoView, AppCompatActivity pcontext){
|
public void updateSetting(NestedGeckoView mNestedGeckoView,AppCompatActivity pcontext){
|
||||||
GeckoRuntimeSettings.Builder mSettings = new GeckoRuntimeSettings.Builder();
|
GeckoRuntimeSettings.Builder mSettings = new GeckoRuntimeSettings.Builder();
|
||||||
if(status.sShowImages == 2){
|
if(status.sShowImages == 2){
|
||||||
mSettings.configFilePath(getAssetsCacheFile(pcontext, "geckoview-config-noimage.yaml"));
|
mSettings.configFilePath(getAssetsCacheFile(pcontext, "geckoview-config-noimage.yaml"));
|
||||||
|
@ -320,7 +330,7 @@ public class geckoClients
|
||||||
mSettings.configFilePath(getAssetsCacheFile(pcontext, "geckoview-config.yaml"));
|
mSettings.configFilePath(getAssetsCacheFile(pcontext, "geckoview-config.yaml"));
|
||||||
}
|
}
|
||||||
mSettings.build();
|
mSettings.build();
|
||||||
|
mRuntime.getSettings().setRemoteDebuggingEnabled(true);
|
||||||
mRuntime.getSettings().setRemoteDebuggingEnabled(true);
|
mRuntime.getSettings().setRemoteDebuggingEnabled(true);
|
||||||
|
|
||||||
mRuntime.getSettings().setWebFontsEnabled(status.sShowWebFonts);
|
mRuntime.getSettings().setWebFontsEnabled(status.sShowWebFonts);
|
||||||
|
|
|
@ -28,9 +28,7 @@ class geckoDownloadManager
|
||||||
}
|
}
|
||||||
|
|
||||||
void downloadFile(WebResponse response, geckoSession session, AppCompatActivity context, eventObserver.eventListener event) {
|
void downloadFile(WebResponse response, geckoSession session, AppCompatActivity context, eventObserver.eventListener event) {
|
||||||
session
|
session.getUserAgent().accept(userAgent -> downloadFile(response, userAgent,context,session,event),
|
||||||
.getUserAgent()
|
|
||||||
.accept(userAgent -> downloadFile(response, userAgent,context,session,event),
|
|
||||||
exception -> {
|
exception -> {
|
||||||
throw new IllegalStateException("Could not get UserAgent string.");
|
throw new IllegalStateException("Could not get UserAgent string.");
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,7 +30,6 @@ import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
import com.hiddenservices.onionservices.constants.constants;
|
import com.hiddenservices.onionservices.constants.constants;
|
||||||
import com.hiddenservices.onionservices.constants.enums;
|
import com.hiddenservices.onionservices.constants.enums;
|
||||||
import com.hiddenservices.onionservices.constants.keys;
|
|
||||||
import com.hiddenservices.onionservices.constants.status;
|
import com.hiddenservices.onionservices.constants.status;
|
||||||
import com.hiddenservices.onionservices.constants.strings;
|
import com.hiddenservices.onionservices.constants.strings;
|
||||||
import com.hiddenservices.onionservices.dataManager.dataEnums;
|
import com.hiddenservices.onionservices.dataManager.dataEnums;
|
||||||
|
@ -388,13 +387,12 @@ geckoSession extends GeckoSession implements MediaSession.Delegate,GeckoSession.
|
||||||
PrefsHelper.setPref(keys.PROXY_SOCKS_REMOTE_DNS,true);*/
|
PrefsHelper.setPref(keys.PROXY_SOCKS_REMOTE_DNS,true);*/
|
||||||
|
|
||||||
if(mIsLoaded){
|
if(mIsLoaded){
|
||||||
if(!var2.equals("about:blank") && helperMethod.getHost(var2).endsWith(".onion")){
|
if(!mCurrentURL.equals("about:config") && !var2.equals("about:blank") && helperMethod.getHost(var2).endsWith(".onion")){
|
||||||
var2 = var2.replace("www.","");
|
var2 = var2.replace("www.","");
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentURL = var2;
|
mCurrentURL = var2;
|
||||||
|
if(!mCurrentURL.equals("about:config") && !mCurrentURL.equals("about:blank")){
|
||||||
if(!mCurrentURL.equals("about:blank")){
|
|
||||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, m_current_url_id, mTheme, this), enums.etype.ON_UPDATE_SEARCH_BAR);
|
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, m_current_url_id, mTheme, this), enums.etype.ON_UPDATE_SEARCH_BAR);
|
||||||
mContext.get().runOnUiThread(() -> event.invokeObserver(Arrays.asList(5,mSessionID), enums.etype.progress_update));
|
mContext.get().runOnUiThread(() -> event.invokeObserver(Arrays.asList(5,mSessionID), enums.etype.progress_update));
|
||||||
}
|
}
|
||||||
|
@ -404,7 +402,7 @@ geckoSession extends GeckoSession implements MediaSession.Delegate,GeckoSession.
|
||||||
mThemeChanged = false;
|
mThemeChanged = false;
|
||||||
}
|
}
|
||||||
isPageLoading = true;
|
isPageLoading = true;
|
||||||
if(!mCurrentURL.equals("about:blank") && !mCurrentTitle.equals("loading")){
|
if(!mCurrentURL.equals("about:config") && !mCurrentURL.equals("about:blank") && !mCurrentTitle.equals("loading")){
|
||||||
mProgress = 5;
|
mProgress = 5;
|
||||||
mContext.get().runOnUiThread(() -> event.invokeObserver(Arrays.asList(5,mSessionID), enums.etype.progress_update));
|
mContext.get().runOnUiThread(() -> event.invokeObserver(Arrays.asList(5,mSessionID), enums.etype.progress_update));
|
||||||
mThemeChanged = false;
|
mThemeChanged = false;
|
||||||
|
@ -500,7 +498,7 @@ geckoSession extends GeckoSession implements MediaSession.Delegate,GeckoSession.
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onProgressStart(){
|
public void onProgressStart(){
|
||||||
if(!getCurrentURL().equals("about:blank") && !getCurrentURL().contains("trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion") && !wasPreviousErrorPage() && !getCurrentURL().startsWith(CONST_GENESIS_URL_CACHED) && !getCurrentURL().startsWith(CONST_GENESIS_URL_CACHED_DARK) && !getCurrentURL().startsWith(CONST_GENESIS_HELP_URL_CACHE) && !getCurrentURL().startsWith(CONST_GENESIS_HELP_URL_CACHE_DARK)){
|
if(!getCurrentURL().equals("about:config") && !getCurrentURL().equals("about:blank") && !getCurrentURL().contains("trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion") && !wasPreviousErrorPage() && !getCurrentURL().startsWith(CONST_GENESIS_URL_CACHED) && !getCurrentURL().startsWith(CONST_GENESIS_URL_CACHED_DARK) && !getCurrentURL().startsWith(CONST_GENESIS_HELP_URL_CACHE) && !getCurrentURL().startsWith(CONST_GENESIS_HELP_URL_CACHE_DARK)){
|
||||||
mContext.get().runOnUiThread(() -> event.invokeObserver(Arrays.asList(5,mSessionID), enums.etype.progress_update));
|
mContext.get().runOnUiThread(() -> event.invokeObserver(Arrays.asList(5,mSessionID), enums.etype.progress_update));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -682,7 +680,7 @@ geckoSession extends GeckoSession implements MediaSession.Delegate,GeckoSession.
|
||||||
|
|
||||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, m_current_url_id, mTheme, this), enums.etype.ON_UPDATE_SEARCH_BAR);
|
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, m_current_url_id, mTheme, this), enums.etype.ON_UPDATE_SEARCH_BAR);
|
||||||
|
|
||||||
if(!mCurrentURL.contains("trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion")){
|
if(!m_url.equals("about:config") && !mCurrentURL.contains("trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion")){
|
||||||
mProgress = 5;
|
mProgress = 5;
|
||||||
onProgressStart();
|
onProgressStart();
|
||||||
}
|
}
|
||||||
|
@ -786,11 +784,6 @@ geckoSession extends GeckoSession implements MediaSession.Delegate,GeckoSession.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
|
||||||
public void onExternalResponse(@NonNull GeckoSession session, @NonNull GeckoSession.WebResponseInfo response){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public void onFirstContentfulPaint(@NonNull GeckoSession var1) {
|
public void onFirstContentfulPaint(@NonNull GeckoSession var1) {
|
||||||
|
|
||||||
|
@ -981,7 +974,7 @@ geckoSession extends GeckoSession implements MediaSession.Delegate,GeckoSession.
|
||||||
{
|
{
|
||||||
if(mDownloadManager.getDownloadURL()!=null && mDownloadManager.getDownloadFile()!=null){
|
if(mDownloadManager.getDownloadURL()!=null && mDownloadManager.getDownloadFile()!=null){
|
||||||
if(!createAndSaveFileFromBase64Url(mDownloadManager.getDownloadURL().toString())){
|
if(!createAndSaveFileFromBase64Url(mDownloadManager.getDownloadURL().toString())){
|
||||||
pluginController.getInstance().onDownloadInvoke(Arrays.asList(mDownloadManager.getDownloadURL()+"__"+mDownloadManager.getDownloadFile(), Environment.DIRECTORY_DOWNLOADS), pluginEnums.eDownloadManager.M_START_SERVICE);
|
pluginController.getInstance().onDownloadInvoke(Arrays.asList(mDownloadManager.getDownloadURL(), mDownloadManager.getDownloadFile()), pluginEnums.eDownloadManager.M_WEB_DOWNLOAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -990,7 +983,7 @@ geckoSession extends GeckoSession implements MediaSession.Delegate,GeckoSession.
|
||||||
{
|
{
|
||||||
if(downloadURL!=null && downloadFile!=null){
|
if(downloadURL!=null && downloadFile!=null){
|
||||||
if(!createAndSaveFileFromBase64Url(downloadURL.toString())){
|
if(!createAndSaveFileFromBase64Url(downloadURL.toString())){
|
||||||
pluginController.getInstance().onDownloadInvoke(Arrays.asList(downloadURL + "__" + downloadFile, Environment.DIRECTORY_DOWNLOADS), pluginEnums.eDownloadManager.M_START_SERVICE);
|
pluginController.getInstance().onDownloadInvoke(Arrays.asList(downloadURL, downloadFile), pluginEnums.eDownloadManager.M_WEB_DOWNLOAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1038,7 +1031,7 @@ geckoSession extends GeckoSession implements MediaSession.Delegate,GeckoSession.
|
||||||
String filename;
|
String filename;
|
||||||
|
|
||||||
if(url.startsWith("blob")){
|
if(url.startsWith("blob")){
|
||||||
loadUri((String) pluginController.getInstance().onDownloadInvoke(Collections.singletonList(url), pluginEnums.eDownloadManager.M_DOWNLOAD_BLOB));
|
loadUri((String) pluginController.getInstance().onDownloadInvoke(Collections.singletonList(url), pluginEnums.eDownloadManager.M_BLOB_DOWNLOAD_REQUEST));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -619,7 +619,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
||||||
|
|
||||||
public void initRuntimeSettings()
|
public void initRuntimeSettings()
|
||||||
{
|
{
|
||||||
mGeckoClient.updateSetting(mGeckoView, homeController.this);
|
mGeckoClient.updateSetting(mGeckoView, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onReDrawGeckoview(){
|
public void onReDrawGeckoview(){
|
||||||
|
@ -1894,7 +1894,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
||||||
{
|
{
|
||||||
pluginController.getInstance().onOrbotInvoke(Collections.singletonList(status.mThemeApplying), pluginEnums.eOrbotManager.M_DESTROY);
|
pluginController.getInstance().onOrbotInvoke(Collections.singletonList(status.mThemeApplying), pluginEnums.eOrbotManager.M_DESTROY);
|
||||||
|
|
||||||
finishAffinity();
|
finishAndRemoveTask();
|
||||||
overridePendingTransition(R.anim.popup_scale_in, R.anim.popup_scale_out);
|
overridePendingTransition(R.anim.popup_scale_in, R.anim.popup_scale_out);
|
||||||
activityContextManager.getInstance().getHomeController().onResetData();
|
activityContextManager.getInstance().getHomeController().onResetData();
|
||||||
mGeckoClient.onClearAll();
|
mGeckoClient.onClearAll();
|
||||||
|
@ -2127,6 +2127,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
||||||
{
|
{
|
||||||
initTabCountForced();
|
initTabCountForced();
|
||||||
}
|
}
|
||||||
|
else if(e_type.equals(enums.etype.M_INIT_RUNTIME_SETTINGS)){
|
||||||
|
mGeckoClient.postInitRuntime(mGeckoView, homeController.this);
|
||||||
|
}
|
||||||
else if(e_type.equals(enums.etype.M_IS_ERROR_PAGE))
|
else if(e_type.equals(enums.etype.M_IS_ERROR_PAGE))
|
||||||
{
|
{
|
||||||
if(mGeckoClient==null || mGeckoClient.getSession()==null){
|
if(mGeckoClient==null || mGeckoClient.getSession()==null){
|
||||||
|
|
|
@ -43,6 +43,7 @@ import androidx.fragment.app.FragmentContainerView;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.applovin.mediation.ads.MaxAdView;
|
import com.applovin.mediation.ads.MaxAdView;
|
||||||
|
import com.hiddenservices.onionservices.appManager.activityContextManager;
|
||||||
import com.hiddenservices.onionservices.constants.*;
|
import com.hiddenservices.onionservices.constants.*;
|
||||||
import com.hiddenservices.onionservices.dataManager.dataController;
|
import com.hiddenservices.onionservices.dataManager.dataController;
|
||||||
import com.hiddenservices.onionservices.dataManager.dataEnums;
|
import com.hiddenservices.onionservices.dataManager.dataEnums;
|
||||||
|
@ -610,7 +611,7 @@ class homeViewController
|
||||||
protected Void doInBackground(Void...arg0) {
|
protected Void doInBackground(Void...arg0) {
|
||||||
AppCompatActivity temp_context = mContext;
|
AppCompatActivity temp_context = mContext;
|
||||||
int mCounter = 0;
|
int mCounter = 0;
|
||||||
while (!orbotLocalConstants.mIsTorInitialized || !orbotLocalConstants.mNetworkState){
|
while (orbotLocalConstants.mSOCKSPort==-1 && (!orbotLocalConstants.mIsTorInitialized || !orbotLocalConstants.mNetworkState)){
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
boolean mFastConnect = status.sSettingIsAppStarted || !status.sRestoreTabs && status.sAppInstalled && status.sSettingDefaultSearchEngine.equals(constants.CONST_BACKEND_GENESIS_URL) && !status.sBridgeStatus && status.sExternalWebsite.equals(strings.GENERIC_EMPTY_STR);
|
boolean mFastConnect = status.sSettingIsAppStarted || !status.sRestoreTabs && status.sAppInstalled && status.sSettingDefaultSearchEngine.equals(constants.CONST_BACKEND_GENESIS_URL) && !status.sBridgeStatus && status.sExternalWebsite.equals(strings.GENERIC_EMPTY_STR);
|
||||||
|
@ -620,7 +621,9 @@ class homeViewController
|
||||||
orbotLocalConstants.mTorLogsStatus = "Starting Genesis | Please Wait ...";
|
orbotLocalConstants.mTorLogsStatus = "Starting Genesis | Please Wait ...";
|
||||||
mEvent.invokeObserver(Collections.singletonList(status.sSettingDefaultSearchEngine), enums.etype.recheck_orbot);
|
mEvent.invokeObserver(Collections.singletonList(status.sSettingDefaultSearchEngine), enums.etype.recheck_orbot);
|
||||||
startPostTask(messages.MESSAGE_UPDATE_LOADING_TEXT);
|
startPostTask(messages.MESSAGE_UPDATE_LOADING_TEXT);
|
||||||
break;
|
if (orbotLocalConstants.mSOCKSPort!=-1){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
orbotLocalConstants.mTorLogsStatus = "No internet connection";
|
orbotLocalConstants.mTorLogsStatus = "No internet connection";
|
||||||
startPostTask(messages.MESSAGE_UPDATE_LOADING_TEXT);
|
startPostTask(messages.MESSAGE_UPDATE_LOADING_TEXT);
|
||||||
|
@ -628,7 +631,7 @@ class homeViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(500);
|
sleep(500);
|
||||||
if(mCounter>20){
|
if(mCounter>20 && orbotLocalConstants.mSOCKSPort!=-1){
|
||||||
break;
|
break;
|
||||||
}else {
|
}else {
|
||||||
mCounter+=1;
|
mCounter+=1;
|
||||||
|
@ -648,6 +651,10 @@ class homeViewController
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mContext.runOnUiThread(() -> {
|
||||||
|
mEvent.invokeObserver(null, enums.etype.M_INIT_RUNTIME_SETTINGS);
|
||||||
|
});
|
||||||
|
|
||||||
if(!status.sSettingIsAppStarted){
|
if(!status.sSettingIsAppStarted){
|
||||||
mContext.runOnUiThread(() -> {
|
mContext.runOnUiThread(() -> {
|
||||||
onDisableSplashScreen();
|
onDisableSplashScreen();
|
||||||
|
@ -1637,6 +1644,12 @@ class homeViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status.sFullScreenBrowsing){
|
if(status.sFullScreenBrowsing){
|
||||||
|
int orientation = mContext.getResources().getConfiguration().orientation;
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||||
|
mWebviewContainer.setPadding(0,0,0,helperMethod.pxFromDp(60 + 60));
|
||||||
|
} else {
|
||||||
|
mWebviewContainer.setPadding(0,0,0,helperMethod.pxFromDp(110));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(mAdvertLoaded!=null && (boolean)mAdvertLoaded){
|
if(mAdvertLoaded!=null && (boolean)mAdvertLoaded){
|
||||||
|
|
|
@ -12,7 +12,7 @@ public class constants
|
||||||
public static final String CONST_PRIVACY_POLICY_URL = "http://trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion/privacy";
|
public static final String CONST_PRIVACY_POLICY_URL = "http://trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion/privacy";
|
||||||
public static final String CONST_REPORT_URL = "http://trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion/report?url=";
|
public static final String CONST_REPORT_URL = "http://trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion/report?url=";
|
||||||
public static final String CONST_SITEMAP = "http://trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion/create";
|
public static final String CONST_SITEMAP = "http://trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion/create";
|
||||||
public static final String CONST_PACKAGE_NAME = "com.darkweb.genesissearchengine.production";
|
public static final String CONST_PACKAGE_NAME = "com.hiddenservices.onionservices";
|
||||||
public static final String CONST_GENESIS_ONION = "genesis.onion";
|
public static final String CONST_GENESIS_ONION = "genesis.onion";
|
||||||
public static final String CONST_GENESIS_ONION_V2 = "trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion";
|
public static final String CONST_GENESIS_ONION_V2 = "trcip42ymcgvv5hsa7nxpwdnott46ebomnn5pm5lovg5hpszyo4n35yd.onion";
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ public class enums
|
||||||
on_verify_selected_url_menu,FINDER_RESULT_CALLBACK,M_ADMOB_BANNER_RECHECK,M_OPEN_SESSION,M_DOWNLOAD_FAILURE, M_ADVERT_LOADED,
|
on_verify_selected_url_menu,FINDER_RESULT_CALLBACK,M_ADMOB_BANNER_RECHECK,M_OPEN_SESSION,M_DOWNLOAD_FAILURE, M_ADVERT_LOADED,
|
||||||
welcome, reload,download_folder, M_UPDATE_THEME,M_ON_BANNER_UPDATE, M_LOAD_HOMEPAGE_GENESIS,M_INIT_TAB_COUNT_FORCED,M_SPLASH_DISABLE,M_NEW_LINK_IN_NEW_TAB, M_NEW_LINK_IN_NEW_TAB_LOAD,M_RESET_SUGGESTION,
|
welcome, reload,download_folder, M_UPDATE_THEME,M_ON_BANNER_UPDATE, M_LOAD_HOMEPAGE_GENESIS,M_INIT_TAB_COUNT_FORCED,M_SPLASH_DISABLE,M_NEW_LINK_IN_NEW_TAB, M_NEW_LINK_IN_NEW_TAB_LOAD,M_RESET_SUGGESTION,
|
||||||
url_triggered, url_triggered_new_tab,url_clear,fetch_favicon,M_OPEN_BOOKMARK_SETTING, M_COPY_URL,url_clear_at,remove_from_database,is_empty,M_HOME_PAGE,M_PRELOAD_URL,ON_KEYBOARD_CLOSE,M_CLOSE_TAB, M_CLOSE_TAB_BACK,
|
url_triggered, url_triggered_new_tab,url_clear,fetch_favicon,M_OPEN_BOOKMARK_SETTING, M_COPY_URL,url_clear_at,remove_from_database,is_empty,M_HOME_PAGE,M_PRELOAD_URL,ON_KEYBOARD_CLOSE,M_CLOSE_TAB, M_CLOSE_TAB_BACK,
|
||||||
on_close_sesson,on_long_press, on_full_screen,on_handle_external_intent,on_update_suggestion_url,progress_update,progress_update_forced, ON_EXPAND_TOP_BAR,recheck_orbot,on_url_load,on_playstore_load,back_list_empty,start_proxy, ON_UPDATE_THEME, M_NEW_IDENTITY,M_INDEX_WEBSITE, M_NEW_IDENTITY_MESSAGED, M_INITIALIZE_TAB_SINGLE, M_HOME_BUTTON_PRESSED, M_INITIALIZE_TAB_LINK,on_request_completed, on_update_history,on_update_suggestion,M_WELCOME_MESSAGE,ON_FIRST_PAINT, ON_INVOKE_PARSER, ON_LOAD_TAB_ON_RESUME, ON_SESSION_REINIT,on_page_loaded,on_load_error, M_ORBOT_LOADING,download_file_popup,on_init_ads, M_GET_CURRENT_URL,search_update, open_new_tab,open_new_tab_instant
|
on_close_sesson,on_long_press, on_full_screen,on_handle_external_intent,on_update_suggestion_url,progress_update,progress_update_forced, ON_EXPAND_TOP_BAR,recheck_orbot,on_url_load,on_playstore_load,back_list_empty,start_proxy, ON_UPDATE_THEME, M_NEW_IDENTITY,M_INDEX_WEBSITE, M_INIT_RUNTIME_SETTINGS, M_NEW_IDENTITY_MESSAGED, M_INITIALIZE_TAB_SINGLE, M_HOME_BUTTON_PRESSED, M_INITIALIZE_TAB_LINK,on_request_completed, on_update_history,on_update_suggestion,M_WELCOME_MESSAGE,ON_FIRST_PAINT, ON_INVOKE_PARSER, ON_LOAD_TAB_ON_RESUME, ON_SESSION_REINIT,on_page_loaded,on_load_error, M_ORBOT_LOADING,download_file_popup,on_init_ads, M_GET_CURRENT_URL,search_update, open_new_tab,open_new_tab_instant
|
||||||
}
|
}
|
||||||
|
|
||||||
/*General Enums*/
|
/*General Enums*/
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.DownloadManager;
|
import android.app.DownloadManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
|
@ -60,18 +61,27 @@ import com.hiddenservices.onionservices.constants.strings;
|
||||||
import com.hiddenservices.onionservices.pluginManager.pluginController;
|
import com.hiddenservices.onionservices.pluginManager.pluginController;
|
||||||
import com.example.myapplication.R;
|
import com.example.myapplication.R;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
@ -98,6 +108,33 @@ public class helperMethod
|
||||||
{
|
{
|
||||||
/*Helper Methods General*/
|
/*Helper Methods General*/
|
||||||
|
|
||||||
|
public static String getFileSizeBadge(long size) {
|
||||||
|
if (size <= 0)
|
||||||
|
return "0";
|
||||||
|
|
||||||
|
final String[] units = new String[] { "B Downloaded", "KB ⇣", "MB ⇣", "GB ⇣", "TB ⇣" };
|
||||||
|
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
|
||||||
|
|
||||||
|
return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint({"UnspecifiedImmutableFlag", "LaunchActivityFromNotification"})
|
||||||
|
public static PendingIntent onCreateActionIntent(Context pContext, Class<?> pBroadcastReciever, int pNotificationID, String pTitle, int pCommandID){
|
||||||
|
PendingIntent pendingIntent;
|
||||||
|
Intent pendingIntentTrigger = new Intent(pContext, pBroadcastReciever);
|
||||||
|
pendingIntentTrigger.setAction(pTitle);
|
||||||
|
pendingIntentTrigger.putExtra("N_ID", pNotificationID);
|
||||||
|
pendingIntentTrigger.putExtra("N_COMMAND", pCommandID);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
pendingIntent = PendingIntent.getBroadcast(pContext, pNotificationID, pendingIntentTrigger, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
|
}else{
|
||||||
|
pendingIntent = PendingIntent.getBroadcast(pContext, pNotificationID, pendingIntentTrigger, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pendingIntent;
|
||||||
|
}
|
||||||
|
|
||||||
public static int getResId(String resName, Class<?> c) {
|
public static int getResId(String resName, Class<?> c) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -129,6 +166,8 @@ public class helperMethod
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
|
public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(data);
|
ByteArrayInputStream in = new ByteArrayInputStream(data);
|
||||||
ObjectInputStream is = new ObjectInputStream(in);
|
ObjectInputStream is = new ObjectInputStream(in);
|
||||||
|
@ -192,8 +231,36 @@ public class helperMethod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void writeToFile(String pFilePath, String content){
|
||||||
|
Writer writer;
|
||||||
|
try {
|
||||||
|
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pFilePath), StandardCharsets.UTF_8));
|
||||||
|
writer.write(content);
|
||||||
|
writer.close();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readFromFile(String pFilePath){
|
||||||
|
File file = new File(pFilePath);
|
||||||
|
StringBuilder text = new StringBuilder();
|
||||||
|
try {
|
||||||
|
BufferedReader br = new BufferedReader(new FileReader(file));
|
||||||
|
String line;
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
text.append(line);
|
||||||
|
text.append('\n');
|
||||||
|
}
|
||||||
|
br.close();
|
||||||
|
return text.toString();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String completeURL(String pURL){
|
public static String completeURL(String pURL){
|
||||||
if(pURL.equals("about:blank")){
|
if(pURL.equals("about:blank") || pURL.equals("about:config")){
|
||||||
return pURL;
|
return pURL;
|
||||||
}
|
}
|
||||||
URL weburl;
|
URL weburl;
|
||||||
|
@ -237,7 +304,7 @@ public class helperMethod
|
||||||
return UUID.randomUUID().toString();
|
return UUID.randomUUID().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int createNotificationID(){
|
public static int createUniqueNotificationID(){
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
int id = Integer.parseInt(new SimpleDateFormat("ddHHmmss", Locale.US).format(now));
|
int id = Integer.parseInt(new SimpleDateFormat("ddHHmmss", Locale.US).format(now));
|
||||||
return id;
|
return id;
|
||||||
|
@ -835,7 +902,7 @@ public class helperMethod
|
||||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
|
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Uri uri = FileProvider.getUriForFile(context, "com.hiddenservices.genesissearchengine.production.provider", url);
|
Uri uri = FileProvider.getUriForFile(context, "com.hiddenservices.onionservices.provider", url);
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse(url.toString()));
|
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse(url.toString()));
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
@ -846,7 +913,7 @@ public class helperMethod
|
||||||
}
|
}
|
||||||
} else{
|
} else{
|
||||||
try {
|
try {
|
||||||
Uri uri = FileProvider.getUriForFile(context, "com.hiddenservices.genesissearchengine.production.provider", url);
|
Uri uri = FileProvider.getUriForFile(context, "com.hiddenservices.onionservices.provider", url);
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse(url.toString()));
|
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse(url.toString()));
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|
|
@ -12,20 +12,20 @@ import com.hiddenservices.onionservices.eventObserver;
|
||||||
import com.hiddenservices.onionservices.pluginManager.pluginEnums;
|
import com.hiddenservices.onionservices.pluginManager.pluginEnums;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import static com.hiddenservices.onionservices.pluginManager.pluginEnums.eAdManagerCallbacks.M_ON_AD_LOAD;
|
import static com.hiddenservices.onionservices.pluginManager.pluginEnums.eAdManagerCallbacks.M_ON_AD_LOAD;
|
||||||
public class mopubManager implements MaxAdViewAdListener
|
public class appLovinManager implements MaxAdViewAdListener
|
||||||
{
|
{
|
||||||
/*Private Variables */
|
/*Private Variables */
|
||||||
|
|
||||||
private eventObserver.eventListener mEvent;
|
private eventObserver.eventListener mEvent;
|
||||||
private WeakReference<MaxAdView> mBannerAds;
|
private WeakReference<MaxAdView> mBannerAds;
|
||||||
private int mRequestCount = 0;
|
|
||||||
|
|
||||||
|
private int mRequestCount = 0;
|
||||||
private boolean bannerAdsLoaded = false;
|
private boolean bannerAdsLoaded = false;
|
||||||
private boolean bannerAdRequested = false;
|
private boolean bannerAdRequested = false;
|
||||||
|
|
||||||
/*Initializations*/
|
/*Initializations*/
|
||||||
|
|
||||||
public mopubManager(eventObserver.eventListener pEvent, MaxAdView pBannerAds, Context pContext) {
|
public appLovinManager(eventObserver.eventListener pEvent, MaxAdView pBannerAds, Context pContext) {
|
||||||
this.mEvent = pEvent;
|
this.mEvent = pEvent;
|
||||||
this.mBannerAds = new WeakReference(pBannerAds);
|
this.mBannerAds = new WeakReference(pBannerAds);
|
||||||
initializeBannerAds(pContext);
|
initializeBannerAds(pContext);
|
||||||
|
@ -33,10 +33,8 @@ public class mopubManager implements MaxAdViewAdListener
|
||||||
|
|
||||||
private void initializeBannerAds(Context pContext){
|
private void initializeBannerAds(Context pContext){
|
||||||
AdSettings.setDataProcessingOptions( new String[] {} );
|
AdSettings.setDataProcessingOptions( new String[] {} );
|
||||||
|
|
||||||
AppLovinSdk.getInstance( pContext ).setMediationProvider( "max" );
|
AppLovinSdk.getInstance( pContext ).setMediationProvider( "max" );
|
||||||
AppLovinSdk.initializeSdk( pContext, configuration -> {
|
AppLovinSdk.initializeSdk( pContext, configuration -> {});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Local Helper Methods*/
|
/*Local Helper Methods*/
|
||||||
|
@ -53,19 +51,7 @@ public class mopubManager implements MaxAdViewAdListener
|
||||||
return bannerAdsLoaded;
|
return bannerAdsLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*External Triggers*/
|
/* Overriden Methods */
|
||||||
|
|
||||||
public Object onTrigger(pluginEnums.eAdManager pEventType) {
|
|
||||||
if(pEventType.equals(pluginEnums.eAdManager.M_INITIALIZE_BANNER_ADS))
|
|
||||||
{
|
|
||||||
// loadAds();
|
|
||||||
}
|
|
||||||
else if(pEventType.equals(pluginEnums.eAdManager.M_IS_ADVERT_LOADED))
|
|
||||||
{
|
|
||||||
return isAdvertLoaded();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAdExpanded(MaxAd ad) {
|
public void onAdExpanded(MaxAd ad) {
|
||||||
|
@ -115,5 +101,20 @@ public class mopubManager implements MaxAdViewAdListener
|
||||||
public void onAdDisplayFailed(MaxAd ad, MaxError error) {
|
public void onAdDisplayFailed(MaxAd ad, MaxError error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*External Triggers*/
|
||||||
|
|
||||||
|
public Object onTrigger(pluginEnums.eAdManager pEventType) {
|
||||||
|
if(pEventType.equals(pluginEnums.eAdManager.M_INITIALIZE_BANNER_ADS))
|
||||||
|
{
|
||||||
|
loadAds();
|
||||||
|
}
|
||||||
|
else if(pEventType.equals(pluginEnums.eAdManager.M_IS_ADVERT_LOADED))
|
||||||
|
{
|
||||||
|
return isAdvertLoaded();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
package com.hiddenservices.onionservices.pluginManager.adPluginManager;
|
|
||||||
|
|
||||||
import static com.hiddenservices.onionservices.pluginManager.pluginEnums.eAdManagerCallbacks.M_ON_AD_CLICK;
|
|
||||||
import static com.hiddenservices.onionservices.pluginManager.pluginEnums.eAdManagerCallbacks.M_ON_AD_LOAD;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import com.hiddenservices.onionservices.eventObserver;
|
|
||||||
import com.hiddenservices.onionservices.pluginManager.pluginEnums;
|
|
||||||
import com.facebook.ads.*;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
public class facebookAdsManager implements AdListener {
|
|
||||||
|
|
||||||
/*Private Variables */
|
|
||||||
|
|
||||||
private eventObserver.eventListener mEvent;
|
|
||||||
private WeakReference<LinearLayout> mBannerAds;
|
|
||||||
private AdView adView;
|
|
||||||
|
|
||||||
private boolean bannerAdsLoaded = false;
|
|
||||||
|
|
||||||
/*Initializations*/
|
|
||||||
|
|
||||||
public facebookAdsManager(eventObserver.eventListener pEvent, LinearLayout pBannerAds, AppCompatActivity pContext) {
|
|
||||||
this.mEvent = pEvent;
|
|
||||||
this.mBannerAds = new WeakReference(pBannerAds);
|
|
||||||
loadAds(pContext, pBannerAds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Local Overrides*/
|
|
||||||
@Override
|
|
||||||
public void onError(Ad ad, AdError adError) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAdLoaded(Ad ad) {
|
|
||||||
bannerAdsLoaded = true;
|
|
||||||
mEvent.invokeObserver(null, M_ON_AD_LOAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAdClicked(Ad ad) {
|
|
||||||
mEvent.invokeObserver(null, M_ON_AD_CLICK);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoggingImpression(Ad ad) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*Local Helper Methods*/
|
|
||||||
|
|
||||||
private void loadAds(AppCompatActivity pContext, LinearLayout pLinearLayout){
|
|
||||||
AudienceNetworkAds.initialize(pContext);
|
|
||||||
adView = new AdView(pContext, "IMG_16_9_APP_INSTALL#YOUR_PLACEMENT_ID", AdSize.BANNER_HEIGHT_50);
|
|
||||||
pLinearLayout.addView(adView);
|
|
||||||
adView.loadAd(adView.buildLoadAdConfig().withAdListener(this).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean isAdvertLoaded(){
|
|
||||||
return bannerAdsLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onDestroy(){
|
|
||||||
adView.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*External Triggers*/
|
|
||||||
|
|
||||||
public Object onTrigger(pluginEnums.eAdManager pEventType) {
|
|
||||||
if(pEventType.equals(pluginEnums.eAdManager.M_INITIALIZE_BANNER_ADS))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if(pEventType.equals(pluginEnums.eAdManager.M_IS_ADVERT_LOADED))
|
|
||||||
{
|
|
||||||
return isAdvertLoaded();
|
|
||||||
}
|
|
||||||
else if(pEventType.equals(pluginEnums.eAdManager.M_DESTROY))
|
|
||||||
{
|
|
||||||
onDestroy();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,16 +16,17 @@ import java.util.Date;
|
||||||
|
|
||||||
public class blobDownloader {
|
public class blobDownloader {
|
||||||
|
|
||||||
private Context context;
|
private Context mContext;
|
||||||
private NotificationManager nm;
|
private NotificationManager mNotificationManager;
|
||||||
public blobDownloader(Context context) {
|
public blobDownloader(Context context) {
|
||||||
this.context = context;
|
this.mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void getBase64FromBlobData(String base64Data) throws IOException {
|
public void getBase64FromBlobData(String base64Data) throws IOException {
|
||||||
convertBase64StringToPdfAndStoreIt(base64Data);
|
convertBase64StringToPdfAndStoreIt(base64Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getBase64StringFromBlobUrl(String blobUrl){
|
public static String getBase64StringFromBlobUrl(String blobUrl){
|
||||||
if(blobUrl.startsWith("blob")){
|
if(blobUrl.startsWith("blob")){
|
||||||
return "javascript: var xhr = new XMLHttpRequest();" +
|
return "javascript: var xhr = new XMLHttpRequest();" +
|
||||||
|
@ -60,18 +61,18 @@ public class blobDownloader {
|
||||||
os.flush();
|
os.flush();
|
||||||
|
|
||||||
if(dwldsPath.exists()) {
|
if(dwldsPath.exists()) {
|
||||||
NotificationCompat.Builder b = new NotificationCompat.Builder(context, "MY_DL")
|
NotificationCompat.Builder b = new NotificationCompat.Builder(mContext, "MY_DL")
|
||||||
.setDefaults(NotificationCompat.DEFAULT_ALL)
|
.setDefaults(NotificationCompat.DEFAULT_ALL)
|
||||||
.setWhen(System.currentTimeMillis())
|
.setWhen(System.currentTimeMillis())
|
||||||
.setSmallIcon(R.xml.ic_download)
|
.setSmallIcon(R.xml.ic_download)
|
||||||
.setContentTitle("MY TITLE")
|
.setContentTitle("IMAGE_TITLE")
|
||||||
.setContentText("MY TEXT CONTENT");
|
.setContentText("IMAGE_CONTENT");
|
||||||
nm = (NotificationManager) this.context.getSystemService(Context.NOTIFICATION_SERVICE);
|
mNotificationManager = (NotificationManager) this.mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
if(nm != null) {
|
if(mNotificationManager != null) {
|
||||||
nm.notify(notificationId, b.build());
|
mNotificationManager.notify(notificationId, b.build());
|
||||||
Handler h = new Handler();
|
Handler h = new Handler();
|
||||||
long delayInMilliseconds = 5000;
|
long delayInMilliseconds = 5000;
|
||||||
h.postDelayed(() -> nm.cancel(notificationId), delayInMilliseconds);
|
h.postDelayed(() -> mNotificationManager.cancel(notificationId), delayInMilliseconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,11 @@ package com.hiddenservices.onionservices.pluginManager.downloadPluginManager;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
import com.hiddenservices.onionservices.constants.status;
|
|
||||||
import com.hiddenservices.onionservices.eventObserver;
|
import com.hiddenservices.onionservices.eventObserver;
|
||||||
import com.hiddenservices.onionservices.helperManager.helperMethod;
|
import com.hiddenservices.onionservices.helperManager.helperMethod;
|
||||||
import com.hiddenservices.onionservices.pluginManager.pluginEnums;
|
import com.hiddenservices.onionservices.pluginManager.pluginEnums;
|
||||||
import com.hiddenservices.onionservices.pluginManager.pluginReciever.downloadNotificationReciever;
|
import com.hiddenservices.onionservices.pluginManager.pluginReciever.downloadNotificationReciever;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -32,82 +28,62 @@ public class downloadManager
|
||||||
public downloadManager(WeakReference<AppCompatActivity> pAppContext, eventObserver.eventListener pEvent){
|
public downloadManager(WeakReference<AppCompatActivity> pAppContext, eventObserver.eventListener pEvent){
|
||||||
this.mAppContext = pAppContext;
|
this.mAppContext = pAppContext;
|
||||||
this.mEvent = pEvent;
|
this.mEvent = pEvent;
|
||||||
|
|
||||||
initialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize()
|
private void onStartDownload(String pPath, String pFile) {
|
||||||
{
|
int mNotificationID = helperMethod.createUniqueNotificationID();
|
||||||
|
downloadReciever mFileDownloader = (downloadReciever)new downloadReciever(mAppContext.get(),pPath, pFile, mNotificationID, mEvent, downloadNotificationReciever.class).execute(pPath);
|
||||||
|
mDownloads.put(mNotificationID,mFileDownloader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startDownload(String pPath,String pFile) {
|
private void onCancelDownload(int pID) {
|
||||||
int mID = helperMethod.createNotificationID();
|
|
||||||
downloadReciever mFileDownloader = (downloadReciever)new downloadReciever(mAppContext.get().getApplicationContext(),pPath, pFile, mID, mEvent, downloadNotificationReciever.class).execute(pPath);
|
|
||||||
mDownloads.put(mID,mFileDownloader);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelDownload(int pID) {
|
|
||||||
if(mDownloads!=null && mDownloads.containsKey(pID)){
|
if(mDownloads!=null && mDownloads.containsKey(pID)){
|
||||||
downloadReciever mReciever = mDownloads.get(pID);
|
downloadReciever mReciever = mDownloads.get(pID);
|
||||||
if(mReciever!=null){
|
if(mReciever!=null){
|
||||||
mDownloads.get(pID).onCancel();
|
mDownloads.get(pID).onCancel();
|
||||||
}else {
|
}else {
|
||||||
try {
|
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
if(!status.sSettingIsAppRunning){
|
notificationManager.cancelAll();
|
||||||
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
notificationManager.cancelAll();
|
|
||||||
}
|
|
||||||
}catch (Exception ignored){}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSwipeDownload(int pID) {
|
private void onDownloadURLRequest(int pID) {
|
||||||
if(mDownloads!=null && mDownloads.get(pID)!=null){
|
|
||||||
mDownloads.get(pID).onCancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onTriggerDownload(int pID) {
|
|
||||||
if(mDownloads!=null && mDownloads.get(pID)!=null){
|
if(mDownloads!=null && mDownloads.get(pID)!=null){
|
||||||
mDownloads.get(pID).onTrigger();
|
mDownloads.get(pID).onTrigger();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onStartSercvice(String mURL, String mPath){
|
private void onDownloadWebRequest(String mURL, String mPath){
|
||||||
mAppContext.get().startService(downloadService.getDownloadService(mAppContext.get().getApplicationContext(), mURL + "__" + mPath, Environment.DIRECTORY_DOWNLOADS));
|
mAppContext.get().startService(downloadService.getDownloadService(mAppContext.get().getApplicationContext(), mURL, mPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String downloadBlob(String pURL){
|
private String onDownloadBlobFile(String pURL){
|
||||||
return blobDownloader.getBase64StringFromBlobUrl(pURL);
|
return blobDownloader.getBase64StringFromBlobUrl(pURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* External Triggers */
|
/* External Triggers */
|
||||||
|
|
||||||
public Object onTrigger(List<Object> pData, pluginEnums.eDownloadManager pEventType) {
|
public Object onTrigger(List<Object> pData, pluginEnums.eDownloadManager pEventType) {
|
||||||
if(pEventType.equals(pluginEnums.eDownloadManager.M_DOWNLOAD_FILE))
|
if(pEventType.equals(pluginEnums.eDownloadManager.M_START_DOWNLOAD))
|
||||||
{
|
{
|
||||||
startDownload((String) pData.get(0),(String)pData.get(1));
|
onStartDownload((String) pData.get(0),(String)pData.get(1));
|
||||||
}
|
}
|
||||||
else if(pEventType.equals(pluginEnums.eDownloadManager.M_CANCEL))
|
else if(pEventType.equals(pluginEnums.eDownloadManager.M_CANCEL_DOWNLOAD))
|
||||||
{
|
{
|
||||||
cancelDownload((int) pData.get(0));
|
onCancelDownload((int) pData.get(0));
|
||||||
}
|
}
|
||||||
else if(pEventType.equals(pluginEnums.eDownloadManager.M_TRIGGER))
|
else if(pEventType.equals(pluginEnums.eDownloadManager.M_URL_DOWNLOAD_REQUEST))
|
||||||
{
|
{
|
||||||
onTriggerDownload((int) pData.get(0));
|
onDownloadURLRequest((int) pData.get(0));
|
||||||
}
|
}
|
||||||
else if(pEventType.equals(pluginEnums.eDownloadManager.M_START_SERVICE))
|
else if(pEventType.equals(pluginEnums.eDownloadManager.M_WEB_DOWNLOAD_REQUEST))
|
||||||
{
|
{
|
||||||
onStartSercvice((String) pData.get(0), (String) pData.get(1));
|
onDownloadWebRequest(pData.get(0).toString(), (String) pData.get(1));
|
||||||
}
|
}
|
||||||
else if(pEventType.equals(pluginEnums.eDownloadManager.M_DOWNLOAD_BLOB))
|
else if(pEventType.equals(pluginEnums.eDownloadManager.M_BLOB_DOWNLOAD_REQUEST))
|
||||||
{
|
{
|
||||||
return downloadBlob((String) pData.get(0));
|
return onDownloadBlobFile((String) pData.get(0));
|
||||||
}
|
|
||||||
else if(pEventType.equals(pluginEnums.eDownloadManager.M_SWIPE))
|
|
||||||
{
|
|
||||||
onSwipeDownload((int) pData.get(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import android.app.PendingIntent;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
@ -18,10 +17,8 @@ import android.os.Environment;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
|
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
|
|
||||||
import com.hiddenservices.onionservices.appManager.activityContextManager;
|
import com.hiddenservices.onionservices.appManager.activityContextManager;
|
||||||
import com.hiddenservices.onionservices.constants.status;
|
import com.hiddenservices.onionservices.constants.status;
|
||||||
import com.hiddenservices.onionservices.eventObserver;
|
import com.hiddenservices.onionservices.eventObserver;
|
||||||
|
@ -29,20 +26,19 @@ import com.hiddenservices.onionservices.helperManager.helperMethod;
|
||||||
import com.hiddenservices.onionservices.libs.netcipher.client.StrongHttpsClient;
|
import com.hiddenservices.onionservices.libs.netcipher.client.StrongHttpsClient;
|
||||||
import com.example.myapplication.R;
|
import com.example.myapplication.R;
|
||||||
import org.orbotproject.android.service.wrapper.orbotLocalConstants;
|
import org.orbotproject.android.service.wrapper.orbotLocalConstants;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import ch.boye.httpclientandroidlib.HttpResponse;
|
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||||
import ch.boye.httpclientandroidlib.client.methods.HttpGet;
|
import ch.boye.httpclientandroidlib.client.methods.HttpGet;
|
||||||
|
|
||||||
|
@ -52,70 +48,67 @@ import static java.lang.Thread.sleep;
|
||||||
|
|
||||||
public class downloadReciever extends AsyncTask<String, Integer, String> {
|
public class downloadReciever extends AsyncTask<String, Integer, String> {
|
||||||
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
|
||||||
private Context context;
|
|
||||||
private NotificationManager mNotifyManager;
|
|
||||||
private NotificationCompat.Builder build;
|
|
||||||
private OutputStream output;
|
|
||||||
private InputStream mStream;
|
|
||||||
private Boolean mIsCanceled = false;
|
|
||||||
|
|
||||||
private String PROXY_ADDRESS = "localhost";
|
private WeakReference<Context> mContext;
|
||||||
|
|
||||||
private int mID;
|
|
||||||
private String mFileName;
|
|
||||||
private float mDownloadByte;
|
|
||||||
private String mURL;
|
|
||||||
private eventObserver.eventListener mEvent;
|
private eventObserver.eventListener mEvent;
|
||||||
|
|
||||||
|
private NotificationManager mNotifyManager;
|
||||||
|
private NotificationCompat.Builder mNotificationBuilder;
|
||||||
private Class<?> mBroadcastReciever;
|
private Class<?> mBroadcastReciever;
|
||||||
|
|
||||||
public downloadReciever(Context pContext, String pURL, String pFileName, int pID, eventObserver.eventListener pEvent, Class<?> pBroadcastReciever) {
|
private int mNotificationID;
|
||||||
this.context = pContext;
|
private float mDownloadByte;
|
||||||
|
private String mURL;
|
||||||
|
private String mFileName;
|
||||||
|
private Boolean mIsCanceled = false;
|
||||||
|
|
||||||
|
public downloadReciever(Context pContext, String pURL, String pFileName, int pNotificationID, eventObserver.eventListener pEvent, Class<?> pBroadcastReciever) {
|
||||||
|
this.mContext = new WeakReference(pContext);
|
||||||
|
this.mEvent = pEvent;
|
||||||
|
|
||||||
this.mFileName = pFileName;
|
this.mFileName = pFileName;
|
||||||
this.mURL = pURL;
|
this.mURL = pURL;
|
||||||
this.mID = pID;
|
this.mNotificationID = pNotificationID;
|
||||||
this.mEvent = pEvent;
|
|
||||||
this.mBroadcastReciever = pBroadcastReciever;
|
this.mBroadcastReciever = pBroadcastReciever;
|
||||||
|
|
||||||
|
|
||||||
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
|
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
|
||||||
StrictMode.setThreadPolicy(policy);
|
StrictMode.setThreadPolicy(policy);
|
||||||
|
|
||||||
mFileName = pFileName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnspecifiedImmutableFlag")
|
||||||
protected void onPreExecute() {
|
protected void onPreExecute() {
|
||||||
super.onPreExecute();
|
super.onPreExecute();
|
||||||
|
|
||||||
Intent snoozeIntent = new Intent(context, mBroadcastReciever);
|
/* Create Pending Intent */
|
||||||
snoozeIntent.setAction("Download_Cancelled");
|
|
||||||
snoozeIntent.putExtra("N_ID", mID);
|
|
||||||
snoozeIntent.putExtra("N_COMMAND", 0);
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, mID, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
|
|
||||||
mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
PendingIntent pendingIntentCancel = helperMethod.onCreateActionIntent(mContext.get(), mBroadcastReciever, mNotificationID, "Download_Cancelled",0);
|
||||||
build = new NotificationCompat.Builder(context);
|
|
||||||
|
/* Create Notification */
|
||||||
|
|
||||||
if(mFileName.length()>30){
|
if(mFileName.length()>30){
|
||||||
mFileName = "..." + mFileName.substring(mFileName.length()-30);
|
mFileName = "..." + mFileName.substring(mFileName.length()-30);
|
||||||
}
|
}
|
||||||
build.setContentTitle(mFileName)
|
|
||||||
|
mNotifyManager = (NotificationManager) mContext.get().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
mNotificationBuilder = new NotificationCompat.Builder(mContext.get());
|
||||||
|
mNotificationBuilder.setContentTitle(mFileName)
|
||||||
.setContentText("starting...")
|
.setContentText("starting...")
|
||||||
.setChannelId(mID + "")
|
.setChannelId(mNotificationID + "")
|
||||||
.setAutoCancel(false)
|
.setAutoCancel(false)
|
||||||
.setDefaults(0)
|
.setDefaults(0)
|
||||||
.setColor(Color.parseColor("#84989f"))
|
.setColor(Color.parseColor("#84989f"))
|
||||||
.setCategory(Notification.CATEGORY_SERVICE)
|
.setCategory(Notification.CATEGORY_SERVICE)
|
||||||
.setPriority(Notification.PRIORITY_DEFAULT)
|
.setPriority(Notification.PRIORITY_DEFAULT)
|
||||||
.addAction(R.drawable.ic_download, "Cancel",pendingIntent)
|
.addAction(R.drawable.ic_download, "Cancel",pendingIntentCancel)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
.setDeleteIntent(pendingIntent)
|
.setDeleteIntent(pendingIntentCancel)
|
||||||
.setOngoing(false);
|
.setOngoing(false);
|
||||||
|
|
||||||
|
/* Notification Channel for Latest Androids */
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
NotificationChannel channel = new NotificationChannel(mID + "",
|
NotificationChannel channel = new NotificationChannel(mNotificationID + "", "Social Media Downloader", NotificationManager.IMPORTANCE_HIGH);
|
||||||
"Social Media Downloader",
|
|
||||||
NotificationManager.IMPORTANCE_HIGH);
|
|
||||||
channel.setDescription("no sound");
|
channel.setDescription("no sound");
|
||||||
channel.setSound(null, null);
|
channel.setSound(null, null);
|
||||||
channel.enableLights(false);
|
channel.enableLights(false);
|
||||||
|
@ -123,100 +116,45 @@ public class downloadReciever extends AsyncTask<String, Integer, String> {
|
||||||
channel.enableVibration(false);
|
channel.enableVibration(false);
|
||||||
mNotifyManager.createNotificationChannel(channel);
|
mNotifyManager.createNotificationChannel(channel);
|
||||||
}
|
}
|
||||||
build.setProgress(100, 0, false);
|
mNotificationBuilder.setProgress(100, 0, false);
|
||||||
mNotifyManager.notify(mID, build.build());
|
mNotifyManager.notify(mNotificationID, mNotificationBuilder.build());
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFileSize(long size) {
|
|
||||||
if (size <= 0)
|
|
||||||
return "0";
|
|
||||||
|
|
||||||
final String[] units = new String[] { "B Downloaded", "KB ⇣", "MB ⇣", "GB ⇣", "TB ⇣" };
|
|
||||||
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
|
|
||||||
|
|
||||||
return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String doInBackground(String... f_url) {
|
protected String doInBackground(String... f_url) {
|
||||||
int count;
|
|
||||||
int mRequestCode = 0;
|
int mRequestCode = 0;
|
||||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
OutputStream mOutputStream;
|
||||||
try {
|
InputStream mInputStream;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
String fURL = f_url[0];
|
String fURL = f_url[0];
|
||||||
URL url = new URL(fURL);
|
URL url = new URL(fURL);
|
||||||
HttpURLConnection conection;
|
HttpURLConnection conection;
|
||||||
Proxy proxy;
|
Proxy proxy;
|
||||||
if(helperMethod.getDomainName(f_url[0]).contains(".onion")){
|
if(helperMethod.getDomainName(fURL).contains(".onion")){
|
||||||
proxy = new Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved(PROXY_ADDRESS, orbotLocalConstants.mSOCKSPort));
|
proxy = new Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved("localhost", orbotLocalConstants.mSOCKSPort));
|
||||||
conection = (HttpURLConnection) url.openConnection(proxy);
|
conection = (HttpURLConnection) url.openConnection(proxy);
|
||||||
}else {
|
}else {
|
||||||
Proxy mProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", orbotLocalConstants.mHTTPPort));
|
Proxy mProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", orbotLocalConstants.mHTTPPort));
|
||||||
URLConnection mURLConnection = new URI(f_url[0]).toURL().openConnection(mProxy);
|
URLConnection mURLConnection = new URI(fURL).toURL().openConnection(mProxy);
|
||||||
conection = (HttpURLConnection) mURLConnection;
|
conection = (HttpURLConnection) mURLConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
conection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0");
|
conection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0");
|
||||||
conection.setRequestProperty("Accept","*/*");
|
conection.setRequestProperty("Accept","*/*");
|
||||||
|
|
||||||
conection.connect();
|
conection.connect();
|
||||||
int lenghtOfFile = conection.getContentLength();
|
|
||||||
mRequestCode = conection.getResponseCode();
|
mRequestCode = conection.getResponseCode();
|
||||||
mStream = conection.getInputStream();
|
mInputStream = conection.getInputStream();
|
||||||
// Output stream
|
mOutputStream = new FileOutputStream(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()+"/"+mFileName);
|
||||||
output = new FileOutputStream(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()+"/"+mFileName));
|
int lenghtOfFile = conection.getContentLength();
|
||||||
byte[] data = new byte[100000];
|
|
||||||
|
|
||||||
long total = 0;
|
readStream(mInputStream, mOutputStream, lenghtOfFile);
|
||||||
|
}else {
|
||||||
while ((count = mStream.read(data)) != -1) {
|
|
||||||
if(!status.sSettingIsAppRunning){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
total += count;
|
|
||||||
int cur = (int) ((total * 100) / lenghtOfFile);
|
|
||||||
if(lenghtOfFile<0){
|
|
||||||
cur = (int)total;
|
|
||||||
mDownloadByte = cur * -1;
|
|
||||||
}else {
|
|
||||||
mDownloadByte = cur;
|
|
||||||
}
|
|
||||||
publishProgress(Math.min(cur, 100));
|
|
||||||
if (Math.min(cur, 100) > 98) {
|
|
||||||
sleep(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.write(data, 0, count);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
build.setContentText("saving file");
|
|
||||||
build.setSmallIcon(android.R.drawable.stat_sys_download);
|
|
||||||
mNotifyManager.notify(mID, build.build());
|
|
||||||
|
|
||||||
output.flush();
|
|
||||||
output.close();
|
|
||||||
mStream.close();
|
|
||||||
|
|
||||||
} catch (Exception ex) {
|
|
||||||
if(mRequestCode!=200){
|
|
||||||
String mRequestCodeResponse = String.valueOf(mRequestCode);
|
|
||||||
if(mRequestCodeResponse == null || mRequestCodeResponse.equals("0")){
|
|
||||||
mRequestCodeResponse = "\"Unknown\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mEvent.invokeObserver(Collections.singletonList("Request Error | " + mRequestCodeResponse), M_DOWNLOAD_FAILURE);
|
|
||||||
onCancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
try {
|
|
||||||
String ALLOWED_URI_CHARS = "@#&=*+-_.,:!?()/~'%";
|
String ALLOWED_URI_CHARS = "@#&=*+-_.,:!?()/~'%";
|
||||||
String urlEncoded = Uri.encode(f_url[0], ALLOWED_URI_CHARS);
|
String urlEncoded = Uri.encode(f_url[0], ALLOWED_URI_CHARS);
|
||||||
|
StrongHttpsClient httpclient = new StrongHttpsClient(mContext.get());
|
||||||
StrongHttpsClient httpclient = new StrongHttpsClient(context);
|
|
||||||
|
|
||||||
if(helperMethod.getDomainName(f_url[0]).contains(".onion")){
|
if(helperMethod.getDomainName(f_url[0]).contains(".onion")){
|
||||||
httpclient.useProxy(true, "SOCKS", "127.0.0.1", orbotLocalConstants.mSOCKSPort);
|
httpclient.useProxy(true, "SOCKS", "127.0.0.1", orbotLocalConstants.mSOCKSPort);
|
||||||
|
@ -226,120 +164,68 @@ public class downloadReciever extends AsyncTask<String, Integer, String> {
|
||||||
|
|
||||||
HttpGet httpget = new HttpGet(urlEncoded);
|
HttpGet httpget = new HttpGet(urlEncoded);
|
||||||
HttpResponse response = httpclient.execute(httpget);
|
HttpResponse response = httpclient.execute(httpget);
|
||||||
|
mInputStream = response.getEntity().getContent();
|
||||||
|
|
||||||
InputStream mStream = response.getEntity().getContent();
|
|
||||||
|
|
||||||
mRequestCode = response.getStatusLine().getStatusCode();
|
mRequestCode = response.getStatusLine().getStatusCode();
|
||||||
output = new FileOutputStream(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()+"/"+mFileName));
|
mOutputStream = new FileOutputStream(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()+"/"+mFileName);
|
||||||
byte[] data = new byte[100000];
|
|
||||||
|
|
||||||
long total = 0;
|
|
||||||
|
|
||||||
float lenghtOfFile = response.getEntity().getContentLength();
|
float lenghtOfFile = response.getEntity().getContentLength();
|
||||||
int read;
|
readStream(mInputStream, mOutputStream, lenghtOfFile);
|
||||||
while ((read = mStream.read(data)) != -1) {
|
|
||||||
if(!status.sSettingIsAppRunning){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
total += read;
|
|
||||||
int cur = (int) ((total * 100) / response.getEntity().getContentLength());
|
|
||||||
mDownloadByte = cur;
|
|
||||||
if(lenghtOfFile<0){
|
|
||||||
cur = (int)total;
|
|
||||||
mDownloadByte = total * -1;
|
|
||||||
}else {
|
|
||||||
mDownloadByte = cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
publishProgress(Math.min(cur, 100));
|
|
||||||
if (Math.min(cur, 100) > 98) {
|
|
||||||
sleep(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.write(data, 0, read);
|
|
||||||
}
|
|
||||||
|
|
||||||
build.setContentText("saving file");
|
|
||||||
build.setSmallIcon(android.R.drawable.stat_sys_download);
|
|
||||||
mNotifyManager.notify(mID, build.build());
|
|
||||||
|
|
||||||
output.flush();
|
|
||||||
output.close();
|
|
||||||
mStream.close();
|
|
||||||
}catch (Exception ex){
|
|
||||||
String mRequestCodeResponse = String.valueOf(mRequestCode);
|
|
||||||
if(mRequestCodeResponse == null || mRequestCodeResponse.equals("0")){
|
|
||||||
mRequestCodeResponse = "\"Unknown\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
mEvent.invokeObserver(Collections.singletonList("Request Error | " + mRequestCodeResponse), M_DOWNLOAD_FAILURE);
|
|
||||||
onCancel();
|
|
||||||
}
|
}
|
||||||
|
}catch (Exception ex){
|
||||||
|
if(mRequestCode!=200 && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
|
||||||
|
onBackgroundException(mRequestCode);
|
||||||
|
}
|
||||||
|
else if(android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
|
||||||
|
onBackgroundException(mRequestCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onProgressUpdate(Integer... progress) {
|
@SuppressLint({"UnspecifiedImmutableFlag", "LaunchActivityFromNotification"})
|
||||||
int mPercentage = (int)(mDownloadByte);
|
|
||||||
if(mPercentage<0){
|
|
||||||
build.setProgress(100, progress[0], true);
|
|
||||||
build.setContentText(getFileSize(mPercentage * -1));
|
|
||||||
}else {
|
|
||||||
build.setProgress(100, progress[0], false);
|
|
||||||
build.setContentText(mPercentage+"%");
|
|
||||||
}
|
|
||||||
mNotifyManager.notify(mID, build.build());
|
|
||||||
super.onProgressUpdate(progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(String file_url) {
|
protected void onPostExecute(String file_url) {
|
||||||
Intent snoozeIntentPost = new Intent(context, mBroadcastReciever);
|
|
||||||
snoozeIntentPost.setAction("Download_Open");
|
|
||||||
snoozeIntentPost.putExtra("N_ID", mID);
|
|
||||||
snoozeIntentPost.putExtra("N_COMMAND", 1);
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, mID, snoozeIntentPost, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
|
|
||||||
Intent snoozeIntentPost1 = new Intent(context, mBroadcastReciever);
|
/* Create Pending Intent */
|
||||||
snoozeIntentPost1.setAction("Download_Cancelled");
|
|
||||||
snoozeIntentPost1.putExtra("N_ID", mID);
|
|
||||||
snoozeIntentPost1.putExtra("N_COMMAND", 2);
|
|
||||||
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, mID, snoozeIntentPost1, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
|
|
||||||
build.addAction(0, null, null);
|
PendingIntent pendingIntentOpen = helperMethod.onCreateActionIntent(mContext.get(), mBroadcastReciever, mNotificationID, "Download_Open",1);
|
||||||
build.setContentIntent(pendingIntent);
|
PendingIntent pendingIntentCancel = helperMethod.onCreateActionIntent(mContext.get(), mBroadcastReciever, mNotificationID, "Download_Cancelled",2);
|
||||||
build.setContentText("Download complete");
|
|
||||||
build.setSmallIcon(R.drawable.ic_download_complete);
|
|
||||||
build.setColor(Color.parseColor("#84989f"));
|
|
||||||
build.setProgress(0, 0, false);
|
|
||||||
build.setAutoCancel(true);
|
|
||||||
build.setOngoing(false);
|
|
||||||
build.addAction(android.R.drawable.stat_sys_download, "Open",pendingIntent);
|
|
||||||
build.addAction(R.drawable.ic_download, "Cancel",pendingIntent1);
|
|
||||||
build.setOngoing(false);
|
|
||||||
build.setPriority(Notification.PRIORITY_LOW);
|
|
||||||
mNotifyManager.notify(mID, build.build());
|
|
||||||
|
|
||||||
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
/* Create Notification */
|
||||||
|
|
||||||
|
mNotificationBuilder.addAction(0, null, null);
|
||||||
|
mNotificationBuilder.setContentIntent(pendingIntentOpen);
|
||||||
|
mNotificationBuilder.setContentText("Download complete");
|
||||||
|
mNotificationBuilder.setSmallIcon(R.drawable.ic_download_complete);
|
||||||
|
mNotificationBuilder.setColor(Color.parseColor("#84989f"));
|
||||||
|
mNotificationBuilder.setProgress(0, 0, false);
|
||||||
|
mNotificationBuilder.setAutoCancel(true);
|
||||||
|
mNotificationBuilder.setOngoing(false);
|
||||||
|
mNotificationBuilder.addAction(android.R.drawable.stat_sys_download, "Open",pendingIntentOpen);
|
||||||
|
mNotificationBuilder.addAction(R.drawable.ic_download, "Cancel",pendingIntentCancel);
|
||||||
|
mNotificationBuilder.setOngoing(false);
|
||||||
|
mNotificationBuilder.setPriority(Notification.PRIORITY_LOW);
|
||||||
|
mNotifyManager.notify(mNotificationID, mNotificationBuilder.build());
|
||||||
|
|
||||||
|
DownloadManager dm = (DownloadManager) mContext.get().getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
String mPath = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + File.separator + mFileName).replace("File//","content://");
|
String mPath = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + File.separator + mFileName).replace("File//","content://");
|
||||||
File mFile = new File(mPath);
|
File mFile = new File(mPath);
|
||||||
|
|
||||||
|
/* Create Dwonload Complete Destination */
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
Uri uri = FileProvider.getUriForFile(context, "com.hiddenservices.genesissearchengine.production.provider", mFile);
|
Uri uri = FileProvider.getUriForFile(mContext.get(), "com.hiddenservices.onionservices.provider", mFile);
|
||||||
|
|
||||||
ContentValues contentValues = new ContentValues();
|
ContentValues contentValues = new ContentValues();
|
||||||
contentValues.put(MediaStore.Downloads.TITLE, mFileName);
|
contentValues.put(MediaStore.Downloads.TITLE, mFileName);
|
||||||
contentValues.put(MediaStore.Downloads.DISPLAY_NAME, mFileName);
|
contentValues.put(MediaStore.Downloads.DISPLAY_NAME, mFileName);
|
||||||
contentValues.put(MediaStore.Downloads.SIZE, mDownloadByte);
|
contentValues.put(MediaStore.Downloads.SIZE, mDownloadByte);
|
||||||
contentValues.put(MediaStore.Downloads.MIME_TYPE, helperMethod.getMimeType(uri.toString(), context));
|
contentValues.put(MediaStore.Downloads.MIME_TYPE, helperMethod.getMimeType(uri.toString(), mContext.get()));
|
||||||
contentValues.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + File.separator + mFileName + "_" + helperMethod.createRandomID().substring(0,5));
|
contentValues.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + File.separator + mFileName + "_" + helperMethod.createRandomID().substring(0,5));
|
||||||
ContentResolver database = context.getContentResolver();
|
ContentResolver database = mContext.get().getContentResolver();
|
||||||
database.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues);
|
database.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues);
|
||||||
} else {
|
} else {
|
||||||
Uri uri = FileProvider.getUriForFile(context, "com.hiddenservices.genesissearchengine.production.provider", mFile);
|
Uri uri = FileProvider.getUriForFile(mContext.get(), "com.hiddenservices.onionservices.provider", mFile);
|
||||||
String mime = helperMethod.getMimeType(uri.toString(), context);
|
String mime = helperMethod.getMimeType(uri.toString(), mContext.get());
|
||||||
if(mime!=null){
|
if(mime!=null){
|
||||||
dm.addCompletedDownload(mFileName, mURL, false, mime, mFile.getAbsolutePath(), mFile.length(), false);
|
dm.addCompletedDownload(mFileName, mURL, false, mime, mFile.getAbsolutePath(), mFile.length(), false);
|
||||||
}
|
}
|
||||||
|
@ -347,20 +233,85 @@ public class downloadReciever extends AsyncTask<String, Integer, String> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* UI TRIGGERS*/
|
||||||
|
|
||||||
|
protected void onProgressUpdate(Integer... progress) {
|
||||||
|
int mPercentage = (int)(mDownloadByte);
|
||||||
|
if(mPercentage<0){
|
||||||
|
mNotificationBuilder.setProgress(100, progress[0], true);
|
||||||
|
mNotificationBuilder.setContentText(helperMethod.getFileSizeBadge(mPercentage * -1));
|
||||||
|
}else {
|
||||||
|
mNotificationBuilder.setProgress(100, progress[0], false);
|
||||||
|
mNotificationBuilder.setContentText(mPercentage+"%");
|
||||||
|
}
|
||||||
|
mNotifyManager.notify(mNotificationID, mNotificationBuilder.build());
|
||||||
|
super.onProgressUpdate(progress);
|
||||||
|
}
|
||||||
|
|
||||||
public void onCancel(){
|
public void onCancel(){
|
||||||
mIsCanceled = true;
|
mIsCanceled = true;
|
||||||
mNotifyManager.cancel(mID);
|
mNotifyManager.cancel(mNotificationID);
|
||||||
cancel(true);
|
cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onTrigger(){
|
public void onTrigger(){
|
||||||
if(!mIsCanceled){
|
if(!mIsCanceled){
|
||||||
mNotifyManager.cancel(mID);
|
mNotifyManager.cancel(mNotificationID);
|
||||||
String mPath = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + File.separator + mFileName).replace("File//","content://");
|
String mPath = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + File.separator + mFileName).replace("File//","content://");
|
||||||
File mFile = new File(mPath);
|
File mFile = new File(mPath);
|
||||||
|
|
||||||
new Handler().postDelayed(() -> helperMethod.openFile(mFile, activityContextManager.getInstance().getHomeController()), 500);
|
new Handler().postDelayed(() -> helperMethod.openFile(mFile, activityContextManager.getInstance().getHomeController()), 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper Methods*/
|
||||||
|
|
||||||
|
private boolean readStream(InputStream pInputStream,OutputStream pOutputStream, float pLengthOfFile) throws IOException, InterruptedException {
|
||||||
|
|
||||||
|
byte[] mData = new byte[100000];
|
||||||
|
long mTotalReadCount = 0;
|
||||||
|
int mCurrentReadCount;
|
||||||
|
|
||||||
|
while ((mCurrentReadCount = pInputStream.read(mData)) != -1) {
|
||||||
|
if(!status.sSettingIsAppRunning){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mTotalReadCount += mCurrentReadCount;
|
||||||
|
int cur = (int) ((mTotalReadCount * 100) / pLengthOfFile);
|
||||||
|
mDownloadByte = cur;
|
||||||
|
if(pLengthOfFile<0){
|
||||||
|
cur = (int)mTotalReadCount;
|
||||||
|
mDownloadByte = mTotalReadCount * -1;
|
||||||
|
}else {
|
||||||
|
mDownloadByte = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
publishProgress(Math.min(cur, 100));
|
||||||
|
if (Math.min(cur, 100) > 98) {
|
||||||
|
sleep(500);
|
||||||
|
}
|
||||||
|
pOutputStream.write(mData, 0, mCurrentReadCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
mNotificationBuilder.setContentText("saving file");
|
||||||
|
mNotificationBuilder.setSmallIcon(android.R.drawable.stat_sys_download);
|
||||||
|
mNotifyManager.notify(mNotificationID, mNotificationBuilder.build());
|
||||||
|
|
||||||
|
pOutputStream.flush();
|
||||||
|
pOutputStream.close();
|
||||||
|
pInputStream.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onBackgroundException(int pRequestCode){
|
||||||
|
String mRequestCodeResponse = String.valueOf(pRequestCode);
|
||||||
|
if(mRequestCodeResponse == null || mRequestCodeResponse.equals("0")){
|
||||||
|
mRequestCodeResponse = "\"Unknown\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
String finalMRequestCodeResponse = mRequestCodeResponse;
|
||||||
|
activityContextManager.getInstance().getHomeController().runOnUiThread(() -> mEvent.invokeObserver(Collections.singletonList("Request Error | " + finalMRequestCodeResponse), M_DOWNLOAD_FAILURE));
|
||||||
|
onCancel();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,42 +1,32 @@
|
||||||
package com.hiddenservices.onionservices.pluginManager.downloadPluginManager;
|
package com.hiddenservices.onionservices.pluginManager.downloadPluginManager;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.IntentService;
|
import android.app.IntentService;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.hiddenservices.onionservices.pluginManager.pluginController;
|
import com.hiddenservices.onionservices.pluginManager.pluginController;
|
||||||
import com.hiddenservices.onionservices.pluginManager.pluginEnums;
|
import com.hiddenservices.onionservices.pluginManager.pluginEnums;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class downloadService extends IntentService
|
public class downloadService extends IntentService
|
||||||
{
|
{
|
||||||
private static final String DOWNLOAD_PATH = "com.spartons.androiddownloadmanager_DownloadSongService_Download_path";
|
|
||||||
private static final String DESTINATION_PATH = "com.spartons.androiddownloadmanager_DownloadSongService_Destination_path";
|
|
||||||
|
|
||||||
public downloadService() {
|
public downloadService() {
|
||||||
super("DownloadSongService");
|
super("DOWNLOAD_SERVICE");
|
||||||
}
|
}
|
||||||
@SuppressLint("StaticFieldLeak")
|
|
||||||
static Context context;
|
|
||||||
|
|
||||||
public static Intent getDownloadService(final @NonNull Context callingClassContext, final @NonNull String downloadPath, final @NonNull String destinationPath) {
|
public static Intent getDownloadService(final @NonNull Context callingClassContext, final @NonNull String downloadPath, final @NonNull String destinationPath) {
|
||||||
downloadService.context = callingClassContext;
|
Intent mIntent = new Intent(callingClassContext, downloadService.class);
|
||||||
return new Intent(callingClassContext, downloadService.class)
|
mIntent.putExtra("DOWNLOAD_PATH", downloadPath);
|
||||||
.putExtra(DOWNLOAD_PATH, downloadPath)
|
mIntent.putExtra("DESTINATION_PATH", destinationPath);
|
||||||
.putExtra(DESTINATION_PATH, destinationPath);
|
return mIntent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onHandleIntent(@Nullable Intent intent) {
|
protected void onHandleIntent(@Nullable Intent intent) {
|
||||||
String downloadPath = intent.getStringExtra(DOWNLOAD_PATH);
|
String mDownloadPath = intent.getStringExtra("DOWNLOAD_PATH");
|
||||||
startDownload(downloadPath);
|
String mDestinationPath = intent.getStringExtra("DESTINATION_PATH");
|
||||||
}
|
|
||||||
private void startDownload(String downloadPath) {
|
pluginController.getInstance().onDownloadInvoke(Arrays.asList(mDownloadPath, mDestinationPath), pluginEnums.eDownloadManager.M_START_DOWNLOAD);
|
||||||
String []fn = (downloadPath+"__"+"as").split("__");
|
|
||||||
pluginController.getInstance().onDownloadInvoke(Arrays.asList(fn[0],fn[1]), pluginEnums.eDownloadManager.M_DOWNLOAD_FILE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -368,8 +368,9 @@ public class messageManager implements View.OnClickListener, DialogInterface.OnD
|
||||||
LinearLayout mPopupURLLongPressCurrentTab = mDialog.findViewById(R.id.pPopupURLLongPressCurrentTab);
|
LinearLayout mPopupURLLongPressCurrentTab = mDialog.findViewById(R.id.pPopupURLLongPressCurrentTab);
|
||||||
LinearLayout mPopupURLLongPressClipboard = mDialog.findViewById(R.id.pPopupURLLongPressClipboard);
|
LinearLayout mPopupURLLongPressClipboard = mDialog.findViewById(R.id.pPopupURLLongPressClipboard);
|
||||||
Button mPopupURLLongPressDismiss = mDialog.findViewById(R.id.pPopupURLLongPressDismiss);
|
Button mPopupURLLongPressDismiss = mDialog.findViewById(R.id.pPopupURLLongPressDismiss);
|
||||||
|
String mText = title + mData.get(0);
|
||||||
|
|
||||||
mPopupURLLongPressHeader.setText((title + mData.get(0)));
|
mPopupURLLongPressHeader.setText(mText);
|
||||||
mEvent.invokeObserver(Arrays.asList(mPopupURLLongPressImage, helperMethod.getDomainName(mData.get(0).toString())), enums.etype.fetch_favicon);
|
mEvent.invokeObserver(Arrays.asList(mPopupURLLongPressImage, helperMethod.getDomainName(mData.get(0).toString())), enums.etype.fetch_favicon);
|
||||||
|
|
||||||
mDialog.setOnDismissListener(this);
|
mDialog.setOnDismissListener(this);
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class orbotManager
|
||||||
this.mAppContext = new WeakReference(pAppContext);
|
this.mAppContext = new WeakReference(pAppContext);
|
||||||
this.mLogManger = new orbotLogManager();
|
this.mLogManger = new orbotLogManager();
|
||||||
|
|
||||||
onInitNotificationStatus(pNotificationStatus);
|
orbotLocalConstants.mNotificationStatus = pNotificationStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onInitlizeOrbot(String pBridgeCustomBridge, boolean pBridgeGatewayManual, String pBridgeCustomType, boolean pBridgeStatus, String pBridgesDefault){
|
private void onInitlizeOrbot(String pBridgeCustomBridge, boolean pBridgeGatewayManual, String pBridgeCustomType, boolean pBridgeStatus, String pBridgesDefault){
|
||||||
|
@ -78,10 +78,6 @@ public class orbotManager
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onInitNotificationStatus(int status){
|
|
||||||
orbotLocalConstants.mNotificationStatus = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Helper Methods*/
|
/*Helper Methods*/
|
||||||
|
|
||||||
public Object onTriggerCommands(List<Object> pData, pluginEnums.eOrbotManager pCommands){
|
public Object onTriggerCommands(List<Object> pData, pluginEnums.eOrbotManager pCommands){
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
package com.hiddenservices.onionservices.pluginManager;
|
package com.hiddenservices.onionservices.pluginManager;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.AlarmManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import com.example.myapplication.R;
|
||||||
import com.hiddenservices.onionservices.appManager.activityContextManager;
|
import com.hiddenservices.onionservices.appManager.activityContextManager;
|
||||||
import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.geckoSession;
|
import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.geckoSession;
|
||||||
import com.hiddenservices.onionservices.appManager.homeManager.homeController.homeController;
|
import com.hiddenservices.onionservices.appManager.homeManager.homeController.homeController;
|
||||||
|
@ -16,7 +23,7 @@ import com.hiddenservices.onionservices.dataManager.dataController;
|
||||||
import com.hiddenservices.onionservices.dataManager.dataEnums;
|
import com.hiddenservices.onionservices.dataManager.dataEnums;
|
||||||
import com.hiddenservices.onionservices.eventObserver;
|
import com.hiddenservices.onionservices.eventObserver;
|
||||||
import com.hiddenservices.onionservices.helperManager.helperMethod;
|
import com.hiddenservices.onionservices.helperManager.helperMethod;
|
||||||
import com.hiddenservices.onionservices.pluginManager.adPluginManager.mopubManager;
|
import com.hiddenservices.onionservices.pluginManager.adPluginManager.appLovinManager;
|
||||||
import com.hiddenservices.onionservices.pluginManager.analyticPluginManager.analyticManager;
|
import com.hiddenservices.onionservices.pluginManager.analyticPluginManager.analyticManager;
|
||||||
import com.hiddenservices.onionservices.pluginManager.downloadPluginManager.downloadManager;
|
import com.hiddenservices.onionservices.pluginManager.downloadPluginManager.downloadManager;
|
||||||
import com.hiddenservices.onionservices.pluginManager.langPluginManager.langManager;
|
import com.hiddenservices.onionservices.pluginManager.langPluginManager.langManager;
|
||||||
|
@ -44,7 +51,7 @@ public class pluginController
|
||||||
{
|
{
|
||||||
/*Plugin Instance*/
|
/*Plugin Instance*/
|
||||||
|
|
||||||
private mopubManager mAdManager;
|
private appLovinManager mAdManager;
|
||||||
private analyticManager mAnalyticsManager;
|
private analyticManager mAnalyticsManager;
|
||||||
private messageManager mMessageManager;
|
private messageManager mMessageManager;
|
||||||
private notifictionManager mNotificationManager;
|
private notifictionManager mNotificationManager;
|
||||||
|
@ -85,7 +92,7 @@ public class pluginController
|
||||||
mContextManager = activityContextManager.getInstance();
|
mContextManager = activityContextManager.getInstance();
|
||||||
|
|
||||||
mNotificationManager = new notifictionManager(mHomeController,new notificationCallback());
|
mNotificationManager = new notifictionManager(mHomeController,new notificationCallback());
|
||||||
mAdManager = new mopubManager(new admobCallback(), ((homeController)mHomeController.get()).getBannerAd(), mHomeController.get());
|
mAdManager = new appLovinManager(new admobCallback(), ((homeController)mHomeController.get()).getBannerAd(), mHomeController.get());
|
||||||
mAnalyticsManager = new analyticManager(mHomeController,new analyticCallback());
|
mAnalyticsManager = new analyticManager(mHomeController,new analyticCallback());
|
||||||
mMessageManager = new messageManager(new messageCallback());
|
mMessageManager = new messageManager(new messageCallback());
|
||||||
mOrbotManager = orbotManager.getInstance();
|
mOrbotManager = orbotManager.getInstance();
|
||||||
|
@ -168,12 +175,7 @@ public class pluginController
|
||||||
{
|
{
|
||||||
if(event_type.equals(enums.etype.M_DOWNLOAD_FAILURE))
|
if(event_type.equals(enums.etype.M_DOWNLOAD_FAILURE))
|
||||||
{
|
{
|
||||||
mHomeController.get().runOnUiThread(new Runnable() {
|
mMessageManager.onTrigger(Arrays.asList(pData.get(0).toString(), mHomeController.get()),M_DOWNLOAD_FAILURE);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mMessageManager.onTrigger(Arrays.asList(pData.get(0).toString(), mHomeController.get()),M_DOWNLOAD_FAILURE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -346,20 +348,21 @@ public class pluginController
|
||||||
mHomeController.get().runOnUiThread(() -> mHomeController.get().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE));
|
mHomeController.get().runOnUiThread(() -> mHomeController.get().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE));
|
||||||
}
|
}
|
||||||
else if(pEventType.equals(M_IMAGE_UPDATE_RESTART)){
|
else if(pEventType.equals(M_IMAGE_UPDATE_RESTART)){
|
||||||
if(pData!=null && pData.get(0)!=null){
|
Intent mStartActivity = new Intent(mHomeController.get(), homeController.class);
|
||||||
((AppCompatActivity)pData.get(0)).finish();
|
int mPendingIntentId = 123456;
|
||||||
activityContextManager.getInstance().getHomeController().quitApplication();
|
PendingIntent mPendingIntent = null;
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||||
|
mPendingIntent = PendingIntent.getActivity(mHomeController.get(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_IMMUTABLE);
|
||||||
|
}else {
|
||||||
|
mPendingIntent = PendingIntent.getActivity(mHomeController.get(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
}
|
}
|
||||||
new Thread(){
|
AlarmManager mgr = (AlarmManager)mHomeController.get().getSystemService(Context.ALARM_SERVICE);
|
||||||
public void run(){
|
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 500, mPendingIntent);
|
||||||
try {
|
|
||||||
sleep(500);
|
pluginController.getInstance().onOrbotInvoke(Collections.singletonList(status.mThemeApplying), pluginEnums.eOrbotManager.M_DESTROY);
|
||||||
android.os.Process.killProcess(android.os.Process.myPid());
|
activityContextManager.getInstance().getHomeController().onResetData();
|
||||||
} catch (InterruptedException e) {
|
status.sSettingIsAppStarted = false;
|
||||||
e.printStackTrace();
|
mHomeController.get().finishAndRemoveTask();
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,17 +6,16 @@ public class pluginEnums
|
||||||
public enum eAdManager {
|
public enum eAdManager {
|
||||||
M_INITIALIZE_BANNER_ADS, M_IS_ADVERT_LOADED, M_DESTROY
|
M_INITIALIZE_BANNER_ADS, M_IS_ADVERT_LOADED, M_DESTROY
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum eAdManagerCallbacks {
|
public enum eAdManagerCallbacks {
|
||||||
M_ON_AD_CLICK, M_ON_AD_LOAD, M_ON_AD_HIDE
|
M_ON_AD_CLICK, M_ON_AD_LOAD, M_ON_AD_HIDE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*Analytics Manager*/
|
/*Analytics Manager*/
|
||||||
public enum eAnalyticManager {
|
public enum eAnalyticManager {
|
||||||
M_LOG_EVENT
|
M_LOG_EVENT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*Lanuage Manager*/
|
/*Lanuage Manager*/
|
||||||
public enum eLangManager{
|
public enum eLangManager{
|
||||||
M_SET_LANGUAGE, M_ACTIVITY_CREATED, M_RESUME, M_SUPPORTED_SYSTEM_LANGUAGE_INFO, M_INIT_LOCALE, M_UPDATE_LOCAL
|
M_SET_LANGUAGE, M_ACTIVITY_CREATED, M_RESUME, M_SUPPORTED_SYSTEM_LANGUAGE_INFO, M_INIT_LOCALE, M_UPDATE_LOCAL
|
||||||
|
@ -30,13 +29,14 @@ public class pluginEnums
|
||||||
public enum eMessageManager{
|
public enum eMessageManager{
|
||||||
M_RESET, M_DATA_CLEARED, M_COPY, M_APPLICATION_CRASH, M_DELETE_BOOKMARK, M_UPDATE_BOOKMARK, M_IMAGE_UPDATE,M_OPEN_ACTIVITY_FAILED, M_OPEN_CICADA, M_SECURE_CONNECTION, M_SECURITY_INFO, M_POPUP_BLOCKED, M_PANIC, M_MAX_TAB_REACHED, M_ORBOT_LOADING, M_LOAD_NEW_TAB, M_UNDO,M_DOWNLOAD_SINGLE, M_UPDATE_BRIDGES, M_NEW_IDENTITY, M_NOT_SUPPORTED, M_BRIDGE_MAIL, M_LONG_PRESS_WITH_LINK, M_LONG_PRESS_URL, M_LONG_PRESS_DOWNLOAD, M_START_ORBOT, M_DOWNLOAD_FAILURE, M_DOWNLOAD_FILE, M_RATE_APP, M_REPORT_URL, M_CLEAR_BOOKMARK, M_CLEAR_HISTORY, M_BOOKMARK, M_PANIC_RESET, M_RATE_SUCCESS, M_RATE_FAILURE, M_LANGUAGE_SUPPORT_FAILURE, M_WELCOME
|
M_RESET, M_DATA_CLEARED, M_COPY, M_APPLICATION_CRASH, M_DELETE_BOOKMARK, M_UPDATE_BOOKMARK, M_IMAGE_UPDATE,M_OPEN_ACTIVITY_FAILED, M_OPEN_CICADA, M_SECURE_CONNECTION, M_SECURITY_INFO, M_POPUP_BLOCKED, M_PANIC, M_MAX_TAB_REACHED, M_ORBOT_LOADING, M_LOAD_NEW_TAB, M_UNDO,M_DOWNLOAD_SINGLE, M_UPDATE_BRIDGES, M_NEW_IDENTITY, M_NOT_SUPPORTED, M_BRIDGE_MAIL, M_LONG_PRESS_WITH_LINK, M_LONG_PRESS_URL, M_LONG_PRESS_DOWNLOAD, M_START_ORBOT, M_DOWNLOAD_FAILURE, M_DOWNLOAD_FILE, M_RATE_APP, M_REPORT_URL, M_CLEAR_BOOKMARK, M_CLEAR_HISTORY, M_BOOKMARK, M_PANIC_RESET, M_RATE_SUCCESS, M_RATE_FAILURE, M_LANGUAGE_SUPPORT_FAILURE, M_WELCOME
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum eMessageManagerCallbacks{
|
public enum eMessageManagerCallbacks{
|
||||||
M_CANCEL_WELCOME, M_APP_RATED, M_DOWNLOAD_FILE_MANUAL, M_OPEN_LINK_CURRENT_TAB, M_COPY_LINK, M_REQUEST_BRIDGES, M_SET_BRIDGES, M_OPEN_LINK_NEW_TAB, M_CLEAR_TAB, M_RATE_APPLICATION, M_OPEN_PRIVACY, M_CLEAR_HISTORY, M_CLEAR_BOOKMARK,M_ADJUST_INPUT_RESIZE, M_UNDO_SESSION, M_OPEN_LOGS, M_LOAD_NEW_TAB, M_UNDO_TAB, M_CUSTOM_BRIDGE, M_BRIDGE_TYPE, M_DATA_CLEARED_EXTERNAL, M_IMAGE_UPDATE_RESTART
|
M_CANCEL_WELCOME, M_APP_RATED, M_DOWNLOAD_FILE_MANUAL, M_OPEN_LINK_CURRENT_TAB, M_COPY_LINK, M_REQUEST_BRIDGES, M_SET_BRIDGES, M_OPEN_LINK_NEW_TAB, M_CLEAR_TAB, M_RATE_APPLICATION, M_OPEN_PRIVACY, M_CLEAR_HISTORY, M_CLEAR_BOOKMARK,M_ADJUST_INPUT_RESIZE, M_UNDO_SESSION, M_OPEN_LOGS, M_LOAD_NEW_TAB, M_UNDO_TAB, M_CUSTOM_BRIDGE, M_BRIDGE_TYPE, M_DATA_CLEARED_EXTERNAL, M_IMAGE_UPDATE_RESTART
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Download Manager*/
|
/*Download Manager*/
|
||||||
public enum eDownloadManager{
|
public enum eDownloadManager{
|
||||||
M_DOWNLOAD_FILE, M_CANCEL, M_TRIGGER, M_START_SERVICE, M_DOWNLOAD_BLOB, M_SWIPE
|
M_START_DOWNLOAD, M_CANCEL_DOWNLOAD, M_URL_DOWNLOAD_REQUEST, M_WEB_DOWNLOAD_REQUEST, M_BLOB_DOWNLOAD_REQUEST, M_SWIPE
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Notification Manager*/
|
/*Notification Manager*/
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.hiddenservices.onionservices.pluginManager.pluginReciever;
|
package com.hiddenservices.onionservices.pluginManager.pluginReciever;
|
||||||
|
|
||||||
|
import static com.hiddenservices.onionservices.constants.constants.*;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -7,17 +8,15 @@ import com.hiddenservices.onionservices.pluginManager.pluginController;
|
||||||
import com.hiddenservices.onionservices.pluginManager.pluginEnums;
|
import com.hiddenservices.onionservices.pluginManager.pluginEnums;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import static com.hiddenservices.onionservices.constants.constants.*;
|
|
||||||
|
|
||||||
public class downloadNotificationReciever extends BroadcastReceiver {
|
public class downloadNotificationReciever extends BroadcastReceiver {
|
||||||
public void onReceive (Context context , Intent intent) {
|
public void onReceive (Context context , Intent intent) {
|
||||||
int mCommand = intent.getExtras().getInt(CONST_DOWNLOAD_COMMAND);
|
int mCommand = intent.getExtras().getInt(CONST_DOWNLOAD_COMMAND);
|
||||||
if(mCommand==1){
|
if(mCommand==1){
|
||||||
pluginController.getInstance().onDownloadInvoke(Collections.singletonList(intent.getExtras().getInt(CONST_DOWNLOAD_INTENT_KEY)), pluginEnums.eDownloadManager.M_TRIGGER);
|
pluginController.getInstance().onDownloadInvoke(Collections.singletonList(intent.getExtras().getInt(CONST_DOWNLOAD_INTENT_KEY)), pluginEnums.eDownloadManager.M_URL_DOWNLOAD_REQUEST);
|
||||||
}else if(mCommand==0 || mCommand==2) {
|
}else if(mCommand==0 || mCommand==2) {
|
||||||
pluginController.getInstance().onDownloadInvoke(Collections.singletonList(intent.getExtras().getInt(CONST_DOWNLOAD_INTENT_KEY)), pluginEnums.eDownloadManager.M_CANCEL);
|
pluginController.getInstance().onDownloadInvoke(Collections.singletonList(intent.getExtras().getInt(CONST_DOWNLOAD_INTENT_KEY)), pluginEnums.eDownloadManager.M_CANCEL_DOWNLOAD);
|
||||||
}else if(mCommand==3) {
|
}else if(mCommand==3) {
|
||||||
pluginController.getInstance().onDownloadInvoke(Collections.singletonList(intent.getExtras().getInt(CONST_DOWNLOAD_INTENT_KEY)), pluginEnums.eDownloadManager.M_CANCEL);
|
pluginController.getInstance().onDownloadInvoke(Collections.singletonList(intent.getExtras().getInt(CONST_DOWNLOAD_INTENT_KEY)), pluginEnums.eDownloadManager.M_CANCEL_DOWNLOAD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
|
||||||
<paths>
|
<paths>
|
||||||
<external-path
|
<external-path
|
||||||
name="Download"
|
name="external_files"
|
||||||
path="." />
|
path="." />
|
||||||
</paths>
|
</paths>
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">الحرية الرقمية</string>
|
<string name="GENERAL_LOADING" translatable="true">الحرية الرقمية</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">إعادة تحميل</string>
|
<string name="GENERAL_RELOAD" translatable="true">إعادة تحميل</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">لديك واحدة من المشاكل التالية. قد لا تعمل صفحة الويب أو موقع الويب. قد يكون اتصالك بالإنترنت معطلاً. ربما كنت تستخدم وكيل. قد يتم حظر موقع الويب بواسطة جدار حماية</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">لديك واحدة من المشاكل التالية. قد لا تعمل صفحة الويب أو موقع الويب. قد يكون اتصالك بالإنترنت معطلاً. ربما كنت تستخدم وكيل. قد يتم حظر موقع الويب بواسطة جدار حماية</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">بي بي سي | هاجمت إسرائيل مرة أخرى</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">بي بي سي | هاجمت إسرائيل مرة أخرى</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">llibertat digital</string>
|
<string name="GENERAL_LOADING" translatable="true">llibertat digital</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">recarregar</string>
|
<string name="GENERAL_RELOAD" translatable="true">recarregar</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">us trobeu amb el problema següent. pot ser que la pàgina web o el lloc web no funcionin. és possible que la vostra connexió a Internet sigui deficient. és possible que utilitzeu un servidor intermediari. el tallafoc podria bloquejar el lloc web</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">us trobeu amb el problema següent. pot ser que la pàgina web o el lloc web no funcionin. és possible que la vostra connexió a Internet sigui deficient. és possible que utilitzeu un servidor intermediari. el tallafoc podria bloquejar el lloc web</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC, Israel torna a atacar</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC, Israel torna a atacar</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">digitální svoboda</string>
|
<string name="GENERAL_LOADING" translatable="true">digitální svoboda</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">Znovu načíst</string>
|
<string name="GENERAL_RELOAD" translatable="true">Znovu načíst</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">čelíte jednomu z následujících problémů. webová stránka nebo web nemusí fungovat. vaše připojení k internetu může být špatné. možná používáte proxy. web může být blokován bránou firewall</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">čelíte jednomu z následujících problémů. webová stránka nebo web nemusí fungovat. vaše připojení k internetu může být špatné. možná používáte proxy. web může být blokován bránou firewall</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Izrael znovu udeří</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Izrael znovu udeří</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">digitale Freiheit</string>
|
<string name="GENERAL_LOADING" translatable="true">digitale Freiheit</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">neu laden</string>
|
<string name="GENERAL_RELOAD" translatable="true">neu laden</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">Sie stehen vor einem der folgenden Probleme. Webseite oder Website funktioniert möglicherweise nicht. Ihre Internetverbindung ist möglicherweise schlecht. Möglicherweise verwenden Sie einen Proxy. Die Website wird möglicherweise von der Firewall blockiert</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">Sie stehen vor einem der folgenden Probleme. Webseite oder Website funktioniert möglicherweise nicht. Ihre Internetverbindung ist möglicherweise schlecht. Möglicherweise verwenden Sie einen Proxy. Die Website wird möglicherweise von der Firewall blockiert</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israel schlägt erneut zu</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israel schlägt erneut zu</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">ψηφιακή ελευθερία</string>
|
<string name="GENERAL_LOADING" translatable="true">ψηφιακή ελευθερία</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">φορτώνω πάλι</string>
|
<string name="GENERAL_RELOAD" translatable="true">φορτώνω πάλι</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">αντιμετωπίζετε ένα από τα ακόλουθα προβλήματα. η ιστοσελίδα ή ο ιστότοπος ενδέχεται να μην λειτουργούν. η σύνδεσή σας στο Διαδίκτυο μπορεί να είναι κακή. μπορεί να χρησιμοποιείτε διακομιστή μεσολάβησης. Ο ιστότοπος ενδέχεται να αποκλειστεί από το τείχος προστασίας</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">αντιμετωπίζετε ένα από τα ακόλουθα προβλήματα. η ιστοσελίδα ή ο ιστότοπος ενδέχεται να μην λειτουργούν. η σύνδεσή σας στο Διαδίκτυο μπορεί να είναι κακή. μπορεί να χρησιμοποιείτε διακομιστή μεσολάβησης. Ο ιστότοπος ενδέχεται να αποκλειστεί από το τείχος προστασίας</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Το Ισραήλ χτυπά ξανά</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Το Ισραήλ χτυπά ξανά</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">liberté numérique</string>
|
<string name="GENERAL_LOADING" translatable="true">liberté numérique</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">recharger</string>
|
<string name="GENERAL_RELOAD" translatable="true">recharger</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">vous êtes confronté à l\'un des problèmes suivants. la page Web ou le site Web peut ne pas fonctionner. votre connexion Internet est peut-être mauvaise. vous utilisez peut-être un proxy. le site Web peut être bloqué par le pare-feu</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">vous êtes confronté à l\'un des problèmes suivants. la page Web ou le site Web peut ne pas fonctionner. votre connexion Internet est peut-être mauvaise. vous utilisez peut-être un proxy. le site Web peut être bloqué par le pare-feu</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israël frappe à nouveau</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israël frappe à nouveau</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">digitális szabadság</string>
|
<string name="GENERAL_LOADING" translatable="true">digitális szabadság</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">újratöltés</string>
|
<string name="GENERAL_RELOAD" translatable="true">újratöltés</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">a következő probléma egyikével áll szemben. előfordulhat, hogy egy weboldal vagy webhely nem működik. gyenge lehet az internetkapcsolat. lehet, hogy proxyt használ. előfordulhat, hogy a webhelyet tűzfal blokkolja</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">a következő probléma egyikével áll szemben. előfordulhat, hogy egy weboldal vagy webhely nem működik. gyenge lehet az internetkapcsolat. lehet, hogy proxyt használ. előfordulhat, hogy a webhelyet tűzfal blokkolja</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Izrael újra sztrájkol</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Izrael újra sztrájkol</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">libertà digitale</string>
|
<string name="GENERAL_LOADING" translatable="true">libertà digitale</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">ricaricare</string>
|
<string name="GENERAL_RELOAD" translatable="true">ricaricare</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">stai affrontando uno dei seguenti problemi. la pagina web o il sito web potrebbero non funzionare. la tua connessione Internet potrebbe essere scarsa. potresti utilizzare un proxy. il sito Web potrebbe essere bloccato dal firewall</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">stai affrontando uno dei seguenti problemi. la pagina web o il sito web potrebbero non funzionare. la tua connessione Internet potrebbe essere scarsa. potresti utilizzare un proxy. il sito Web potrebbe essere bloccato dal firewall</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israele colpisce ancora</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israele colpisce ancora</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">デジタルの自由</string>
|
<string name="GENERAL_LOADING" translatable="true">デジタルの自由</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">リロード</string>
|
<string name="GENERAL_RELOAD" translatable="true">リロード</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">次のいずれかの問題が発生しています。ウェブページまたはウェブサイトが機能していない可能性があります。インターネット接続が悪い可能性があります。プロキシを使用している可能性があります。ウェブサイトがファイアウォールによってブロックされている可能性があります</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">次のいずれかの問題が発生しています。ウェブページまたはウェブサイトが機能していない可能性があります。インターネット接続が悪い可能性があります。プロキシを使用している可能性があります。ウェブサイトがファイアウォールによってブロックされている可能性があります</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC |イスラエルが再びストライキ</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC |イスラエルが再びストライキ</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">디지털 자유</string>
|
<string name="GENERAL_LOADING" translatable="true">디지털 자유</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">재 장전</string>
|
<string name="GENERAL_RELOAD" translatable="true">재 장전</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">다음 문제 중 하나에 직면하고 있습니다. 웹 페이지 또는 웹 사이트가 작동하지 않을 수 있습니다. 인터넷 연결 상태가 좋지 않을 수 있습니다. 프록시를 사용하고있을 수 있습니다. 웹 사이트가 방화벽에 의해 차단 될 수 있음</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">다음 문제 중 하나에 직면하고 있습니다. 웹 페이지 또는 웹 사이트가 작동하지 않을 수 있습니다. 인터넷 연결 상태가 좋지 않을 수 있습니다. 프록시를 사용하고있을 수 있습니다. 웹 사이트가 방화벽에 의해 차단 될 수 있음</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | 이스라엘이 다시 공격하다</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | 이스라엘이 다시 공격하다</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">digital freedom</string>
|
<string name="GENERAL_LOADING" translatable="true">digital freedom</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">recarregar</string>
|
<string name="GENERAL_RELOAD" translatable="true">recarregar</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">você está enfrentando um dos seguintes problemas. página da Web ou site pode não estar funcionando. sua conexão com a internet pode estar ruim. você pode estar usando um proxy. site pode estar bloqueado por firewall</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">você está enfrentando um dos seguintes problemas. página da Web ou site pode não estar funcionando. sua conexão com a internet pode estar ruim. você pode estar usando um proxy. site pode estar bloqueado por firewall</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israel ataca novamente</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israel ataca novamente</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">libertatea digitală</string>
|
<string name="GENERAL_LOADING" translatable="true">libertatea digitală</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">reîncărcați</string>
|
<string name="GENERAL_RELOAD" translatable="true">reîncărcați</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">vă confruntați cu una dintre următoarele probleme. este posibil ca pagina web sau site-ul web să nu funcționeze. conexiunea la internet ar putea fi slabă. s-ar putea să utilizați un proxy. site-ul web ar putea fi blocat de firewall</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">vă confruntați cu una dintre următoarele probleme. este posibil ca pagina web sau site-ul web să nu funcționeze. conexiunea la internet ar putea fi slabă. s-ar putea să utilizați un proxy. site-ul web ar putea fi blocat de firewall</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israelul lovește din nou</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israelul lovește din nou</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">цифровая свобода</string>
|
<string name="GENERAL_LOADING" translatable="true">цифровая свобода</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">перезагрузить</string>
|
<string name="GENERAL_RELOAD" translatable="true">перезагрузить</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">вы столкнулись с одной из следующих проблем. веб-страница или веб-сайт могут не работать. ваше интернет-соединение может быть плохим. вы можете использовать прокси. веб-сайт может быть заблокирован брандмауэром</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">вы столкнулись с одной из следующих проблем. веб-страница или веб-сайт могут не работать. ваше интернет-соединение может быть плохим. вы можете использовать прокси. веб-сайт может быть заблокирован брандмауэром</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Израиль снова наносит удар</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Израиль снова наносит удар</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">เสรีภาพดิจิทัล</string>
|
<string name="GENERAL_LOADING" translatable="true">เสรีภาพดิจิทัล</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">โหลดใหม่</string>
|
<string name="GENERAL_RELOAD" translatable="true">โหลดใหม่</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">คุณกำลังประสบปัญหาอย่างใดอย่างหนึ่งต่อไปนี้ หน้าเว็บหรือเว็บไซต์อาจไม่ทำงาน การเชื่อมต่ออินเทอร์เน็ตของคุณอาจไม่ดี คุณอาจใช้พร็อกซี เว็บไซต์อาจถูกปิดกั้นโดยไฟร์วอลล์</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">คุณกำลังประสบปัญหาอย่างใดอย่างหนึ่งต่อไปนี้ หน้าเว็บหรือเว็บไซต์อาจไม่ทำงาน การเชื่อมต่ออินเทอร์เน็ตของคุณอาจไม่ดี คุณอาจใช้พร็อกซี เว็บไซต์อาจถูกปิดกั้นโดยไฟร์วอลล์</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | อิสราเอลนัดหยุดงานอีกครั้ง</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | อิสราเอลนัดหยุดงานอีกครั้ง</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">dijital özgürlük</string>
|
<string name="GENERAL_LOADING" translatable="true">dijital özgürlük</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">Tekrar yükle</string>
|
<string name="GENERAL_RELOAD" translatable="true">Tekrar yükle</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">aşağıdaki problemlerden biriyle karşı karşıyasınız. web sayfası veya web sitesi çalışmıyor olabilir. İnternet bağlantınız zayıf olabilir. bir proxy kullanıyor olabilirsiniz. web sitesi güvenlik duvarı tarafından engelleniyor olabilir</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">aşağıdaki problemlerden biriyle karşı karşıyasınız. web sayfası veya web sitesi çalışmıyor olabilir. İnternet bağlantınız zayıf olabilir. bir proxy kullanıyor olabilirsiniz. web sitesi güvenlik duvarı tarafından engelleniyor olabilir</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | İsrail Yeniden Grevde</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | İsrail Yeniden Grevde</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">ڈیجیٹل آزادی</string>
|
<string name="GENERAL_LOADING" translatable="true">ڈیجیٹل آزادی</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">دوبارہ لوڈ کریں</string>
|
<string name="GENERAL_RELOAD" translatable="true">دوبارہ لوڈ کریں</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">آپ کو مندرجہ ذیل میں سے ایک مسئلہ درپیش ہے۔ ہوسکتا ہے کہ ویب صفحہ یا ویب سائٹ کام نہیں کررہی ہے۔ ہوسکتا ہے کہ آپ کا انٹرنیٹ کنیکشن خراب ہو۔ آپ شاید ایک پراکسی استعمال کر رہے ہوں گے۔ ہوسکتا ہے کہ ویب سائٹ فائر وال کے ذریعے مسدود کردی جائے</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">آپ کو مندرجہ ذیل میں سے ایک مسئلہ درپیش ہے۔ ہوسکتا ہے کہ ویب صفحہ یا ویب سائٹ کام نہیں کررہی ہے۔ ہوسکتا ہے کہ آپ کا انٹرنیٹ کنیکشن خراب ہو۔ آپ شاید ایک پراکسی استعمال کر رہے ہوں گے۔ ہوسکتا ہے کہ ویب سائٹ فائر وال کے ذریعے مسدود کردی جائے</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">بی بی سی | اسرائیل نے ایک بار پھر حملہ کیا</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">بی بی سی | اسرائیل نے ایک بار پھر حملہ کیا</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">tự do kỹ thuật số</string>
|
<string name="GENERAL_LOADING" translatable="true">tự do kỹ thuật số</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">tải lại</string>
|
<string name="GENERAL_RELOAD" translatable="true">tải lại</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">bạn đang phải đối mặt với một trong những vấn đề sau. trang web hoặc trang web có thể không hoạt động. kết nối internet của bạn có thể kém. bạn có thể đang sử dụng proxy. trang web có thể bị tường lửa chặn</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">bạn đang phải đối mặt với một trong những vấn đề sau. trang web hoặc trang web có thể không hoạt động. kết nối internet của bạn có thể kém. bạn có thể đang sử dụng proxy. trang web có thể bị tường lửa chặn</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israel lại tấn công</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israel lại tấn công</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">数字自由</string>
|
<string name="GENERAL_LOADING" translatable="true">数字自由</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">重装</string>
|
<string name="GENERAL_RELOAD" translatable="true">重装</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">您正面临以下问题之一。网页或网站可能无法正常工作。您的互联网连接可能不佳。您可能正在使用代理。网站可能被防火墙阻止</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">您正面临以下问题之一。网页或网站可能无法正常工作。您的互联网连接可能不佳。您可能正在使用代理。网站可能被防火墙阻止</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">英国广播公司|以色列再次罢工</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">英国广播公司|以色列再次罢工</string>
|
||||||
|
|
||||||
<!-- Shortcuts -->
|
<!-- Shortcuts -->
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<string name="GENERAL_LOADING" translatable="true">Online Freedom</string>
|
<string name="GENERAL_LOADING" translatable="true">Online Freedom</string>
|
||||||
<string name="GENERAL_RELOAD" translatable="true">Reload</string>
|
<string name="GENERAL_RELOAD" translatable="true">Reload</string>
|
||||||
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">These might be the problems you are facing \n\n• Webpage or Website might be down \n• Your Internet connection might be poor \n• You might be using a proxy \n• Website might be blocked by firewall</string>
|
<string name="GENERAL_INTERNET_ERROR_MESSAGE" translatable="true">These might be the problems you are facing \n\n• Webpage or Website might be down \n• Your Internet connection might be poor \n• You might be using a proxy \n• Website might be blocked by firewall</string>
|
||||||
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.genesissearchengine.production.provider</string>
|
<string name="GENERAL_FILE_PROVIDER_AUTHORITY" translatable="false">com.hiddenservices.onionservices.provider</string>
|
||||||
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israel Strikes Again</string>
|
<string name="GENERAL_DEFAULT_HINT_SUGGESTION" translatable="true">BBC | Israel Strikes Again</string>
|
||||||
<string name="GENERAL_HIDDEN_WEB" translatable="false">Search the web ...</string>
|
<string name="GENERAL_HIDDEN_WEB" translatable="false">Search the web ...</string>
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ project.ext.target_sdk_version = 31
|
||||||
project.ext.build_tool_version = '31'
|
project.ext.build_tool_version = '31'
|
||||||
project.ext.ndk_version = '21.4.7075529'
|
project.ext.ndk_version = '21.4.7075529'
|
||||||
// project.ext.application_id = "com.hiddenservices.genesissearchengine.production"
|
// project.ext.application_id = "com.hiddenservices.genesissearchengine.production"
|
||||||
project.ext.application_id = "com.darkweb.genesissearchengine.production"
|
project.ext.application_id = "com.hiddenservices.onionservices"
|
||||||
|
|
||||||
project.ext.debugSymbolLevel = 'FULL'
|
project.ext.debugSymbolLevel = 'FULL'
|
||||||
|
|
||||||
|
|
44
build.gradle
44
build.gradle
|
@ -8,57 +8,27 @@ buildscript {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
maven {
|
maven { url "https://maven.mozilla.org/maven2" }
|
||||||
url "https://maven.mozilla.org/maven2"
|
maven { url "https://nightly.maven.mozilla.org/maven2" }
|
||||||
}
|
|
||||||
maven {
|
|
||||||
url "https://nightly.maven.mozilla.org/maven2"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.1.2'
|
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||||
classpath 'com.google.gms:google-services:4.3.10'
|
classpath 'com.google.gms:google-services:4.3.10'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
|
||||||
classpath "org.mozilla.components:tooling-glean-gradle:100.0.20220327143103"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven {
|
maven { url "https://nightly.maven.mozilla.org/maven2" }
|
||||||
url "https://nightly.maven.mozilla.org/maven2"
|
maven { url "https://maven.mozilla.org/maven2" }
|
||||||
}
|
maven { url "https://jitpack.io"
|
||||||
maven {
|
credentials { username "48a9b4c06b5dabbc03328ddcdbb7dfd8fab253ae" }}
|
||||||
url "https://maven.mozilla.org/maven2"
|
|
||||||
}
|
|
||||||
maven {
|
|
||||||
url "https://jitpack.io"
|
|
||||||
credentials { username "48a9b4c06b5dabbc03328ddcdbb7dfd8fab253ae" }
|
|
||||||
}
|
|
||||||
maven { url 'https://jitpack.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
maven { url "https://raw.githubusercontent.com/guardianproject/gpmaven/master" }
|
maven { url "https://raw.githubusercontent.com/guardianproject/gpmaven/master" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
GSoC Plan
|
|
||||||
=========
|
|
||||||
|
|
||||||
A tl;dr version
|
|
||||||
---------------
|
|
||||||
I will be improving the Orbot UI/UX, and adding several features such as data statistics and also
|
|
||||||
implementing the TorCheck API. I plan on extending the ORLib library and also creating an ORLib enabled
|
|
||||||
app as a sort of primer for other third party apps to follow
|
|
||||||
|
|
||||||
The full version
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Orbot UI/UX
|
|
||||||
===========
|
|
||||||
At the moment, the Orbot UI/UX is clustered and not very intuitive. I plan on improving the existing
|
|
||||||
elements of the UI and also add a variety of new features such as
|
|
||||||
|
|
||||||
* A new Set – up Wizard ( which checks for iptables )
|
|
||||||
* Changes to the preferences ( should be made to follow the Android guidelines)
|
|
||||||
|
|
||||||
Orbot Core app work
|
|
||||||
===================
|
|
||||||
At the moment, Orbot displays a successful connection without actually checking the connection. This is a
|
|
||||||
pressing issue, because the user is not notified if the set-up has failed, unless he/she manually checks
|
|
||||||
the torcheck web service. This should be made automatic by making using of the TorCheck API. Also, Orbot
|
|
||||||
should be configured to show more information about the data being transmitted such as -
|
|
||||||
|
|
||||||
* Amount of data transferred
|
|
||||||
* Quality of the connection
|
|
||||||
* Number of circuits connected
|
|
||||||
|
|
||||||
ORLib
|
|
||||||
=====
|
|
||||||
Currently, ORLib is very minimal at the moment, both in term of features and support/documentation. ORLib
|
|
||||||
is very critical to the use of Orbot as it provides transparent proxying on non-rooted devices ( A major
|
|
||||||
chunk of android phones are un-rooted). I intend to -
|
|
||||||
|
|
||||||
* Improve the existing library by adding additional features
|
|
||||||
* Check for existing of Orbot
|
|
||||||
* Check status of connection to Tor
|
|
||||||
* Provide option to start Orbot via intent
|
|
||||||
* Request hidden service by port, and get return hidden service .onion address
|
|
||||||
* Create an ORLib enabled “Twitter, Status.net or other micro blogging Client” – A sort of primer for
|
|
||||||
third-party apps
|
|
||||||
* Improve the documentation
|
|
|
@ -1,85 +0,0 @@
|
||||||
|
|
||||||
.
|
|
||||||
└── org
|
|
||||||
└── torproject
|
|
||||||
└── android
|
|
||||||
├── AppManager.java
|
|
||||||
//this is what helps us track the app-by-app torification
|
|
||||||
//and gets the app name, icon, etc for display - we have some problems here
|
|
||||||
//in normalizing the icon on the list label
|
|
||||||
//some of this code came originally from DroidWall project (yay open source)
|
|
||||||
|
|
||||||
├── boot
|
|
||||||
│ └── OnbootBroadcastReceiver.java
|
|
||||||
//i think this is a dup now and should be removed
|
|
||||||
|
|
||||||
├── HiddenServiceManager.java
|
|
||||||
//empty! but at some point i thought it would be good to aggregate HS functions here
|
|
||||||
|
|
||||||
├── OnBootReceiver.java
|
|
||||||
//this is the class registered in AndroidManifest.xml to handle Onboot events
|
|
||||||
//to start Orbot/Tor when the device boots if the user has elected to do so - what kind of permissions does this require?
|
|
||||||
// <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
|
||||||
|
|
||||||
├── OrbotMainActivity.java
|
|
||||||
//our wonderful main activity!
|
|
||||||
|
|
||||||
├── ProcessSettingsAsyncTask.java
|
|
||||||
//this was just added in 1.0.5.x, but it was meant to help stop the UI blocking while processing settings and prefs
|
|
||||||
//it uses the AsyncTask feature of Android, which seems to work pretty well
|
|
||||||
//for this type of non-time critical function you just want to happen in the background at some point soon-ish
|
|
||||||
|
|
||||||
├── SettingsPreferences.java
|
|
||||||
// Settings activity that loads the res/xml/preferences.xml resource up
|
|
||||||
// has some custom event handlng, onActivityResult callback result code's as well
|
|
||||||
// basically meant to tell Orbot activity if critical settings have been modified and whether
|
|
||||||
// those new settings should be applied (like iptables/transproxy changes)
|
|
||||||
|
|
||||||
├── TorConstants.java
|
|
||||||
// globals! well, constants! but yeah, just a place to put values we use a lot
|
|
||||||
|
|
||||||
├── TorifiedApp.java
|
|
||||||
// object to store a single app's metadata for display in UI and for transproxy process
|
|
||||||
|
|
||||||
├── Utils.java
|
|
||||||
// random methods that can be useful, a.k.a. another place to put stuff
|
|
||||||
|
|
||||||
├── WizardActivity.java
|
|
||||||
// our original attempt at wizard activity that didn't get far
|
|
||||||
|
|
||||||
└── WizardHelper.java
|
|
||||||
// the helper class that manages the dialog based wizard
|
|
||||||
|
|
||||||
├── service //okay the Service subpackage!
|
|
||||||
|
|
||||||
│ ├── Api.java
|
|
||||||
//this is more code taken from DroidWall, that needs to be cleaned up and paired down to just what we need it for
|
|
||||||
//this is related to 1.0.5.x changes with how we bundle and install our C binaries (tor, privoxy and iptables)
|
|
||||||
|
|
||||||
│ ├── ITorService.aidl
|
|
||||||
// the android remote interface definition file;
|
|
||||||
// this is the remote interface which the Orbot activity gets a reference to
|
|
||||||
// and that in the TorService is instantiated as the "binder"
|
|
||||||
|
|
||||||
│ ├── ITorServiceCallback.aidl
|
|
||||||
// this is the callback interface that the Orbot activity instantiates, and passes
|
|
||||||
// to the ITorService; reverse of ITorService in a sense
|
|
||||||
|
|
||||||
│ ├── TorBinaryInstaller.java
|
|
||||||
// this handles installation of binaries; uses Api.java; // tied into Wizard as well
|
|
||||||
|
|
||||||
│ ├── TorServiceConstants.java
|
|
||||||
// reusable constants for just the Service package
|
|
||||||
|
|
||||||
│ ├── TorService.java
|
|
||||||
// the main might powerful service class; Orbot and TorService are the front and backends of this whole app
|
|
||||||
// should run as a remote service, but the manifest doesn't seem to indicate that at the moment
|
|
||||||
|
|
||||||
│ ├── TorServiceUtils.java
|
|
||||||
//utility methods for the service; specificaly check for root and tools for finding processID of background binaries
|
|
||||||
|
|
||||||
│ └── TorTransProxy.java
|
|
||||||
// all the code for iptables transproxying management
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,77 +0,0 @@
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
|
|
||||||
LOCAL_STATIC_LIBRARIES := libancillary
|
|
||||||
|
|
||||||
LOCAL_MODULE := tun2socks
|
|
||||||
|
|
||||||
LOCAL_CFLAGS := -std=gnu99
|
|
||||||
LOCAL_CFLAGS += -DBADVPN_THREAD_SAFE=0 -DBADVPN_LINUX -DBADVPN_BREACTOR_BADVPN -D_GNU_SOURCE
|
|
||||||
LOCAL_CFLAGS += -DBADVPN_USE_SELFPIPE -DBADVPN_USE_EPOLL
|
|
||||||
LOCAL_CFLAGS += -DBADVPN_LITTLE_ENDIAN
|
|
||||||
LOCAL_CFLAGS += -DPSIPHON
|
|
||||||
|
|
||||||
LOCAL_C_INCLUDES:= \
|
|
||||||
$(LOCAL_PATH) \
|
|
||||||
$(LOCAL_PATH)/lwip/src/include/ipv4 \
|
|
||||||
$(LOCAL_PATH)/lwip/src/include/ipv6 \
|
|
||||||
$(LOCAL_PATH)/lwip/src/include \
|
|
||||||
$(LOCAL_PATH)/lwip/custom
|
|
||||||
|
|
||||||
LOCAL_SRC_FILES := \
|
|
||||||
base/BLog_syslog.c \
|
|
||||||
system/BReactor_badvpn.c \
|
|
||||||
system/BSignal.c \
|
|
||||||
system/BConnection_unix.c \
|
|
||||||
system/BTime.c \
|
|
||||||
system/BUnixSignal.c \
|
|
||||||
system/BNetwork.c \
|
|
||||||
flow/StreamRecvInterface.c \
|
|
||||||
flow/PacketRecvInterface.c \
|
|
||||||
flow/PacketPassInterface.c \
|
|
||||||
flow/StreamPassInterface.c \
|
|
||||||
flow/SinglePacketBuffer.c \
|
|
||||||
flow/BufferWriter.c \
|
|
||||||
flow/PacketBuffer.c \
|
|
||||||
flow/PacketStreamSender.c \
|
|
||||||
flow/PacketPassConnector.c \
|
|
||||||
flow/PacketProtoFlow.c \
|
|
||||||
flow/PacketPassFairQueue.c \
|
|
||||||
flow/PacketProtoEncoder.c \
|
|
||||||
flow/PacketProtoDecoder.c \
|
|
||||||
socksclient/BSocksClient.c \
|
|
||||||
tuntap/BTap.c \
|
|
||||||
lwip/src/core/timers.c \
|
|
||||||
lwip/src/core/udp.c \
|
|
||||||
lwip/src/core/memp.c \
|
|
||||||
lwip/src/core/init.c \
|
|
||||||
lwip/src/core/pbuf.c \
|
|
||||||
lwip/src/core/tcp.c \
|
|
||||||
lwip/src/core/tcp_out.c \
|
|
||||||
lwip/src/core/netif.c \
|
|
||||||
lwip/src/core/def.c \
|
|
||||||
lwip/src/core/mem.c \
|
|
||||||
lwip/src/core/tcp_in.c \
|
|
||||||
lwip/src/core/stats.c \
|
|
||||||
lwip/src/core/inet_chksum.c \
|
|
||||||
lwip/src/core/ipv4/icmp.c \
|
|
||||||
lwip/src/core/ipv4/ip4.c \
|
|
||||||
lwip/src/core/ipv4/ip4_addr.c \
|
|
||||||
lwip/src/core/ipv4/ip_frag.c \
|
|
||||||
lwip/src/core/ipv6/ip6.c \
|
|
||||||
lwip/src/core/ipv6/nd6.c \
|
|
||||||
lwip/src/core/ipv6/icmp6.c \
|
|
||||||
lwip/src/core/ipv6/ip6_addr.c \
|
|
||||||
lwip/src/core/ipv6/ip6_frag.c \
|
|
||||||
lwip/custom/sys.c \
|
|
||||||
tun2socks/tun2socks.c \
|
|
||||||
base/DebugObject.c \
|
|
||||||
base/BLog.c \
|
|
||||||
base/BPending.c \
|
|
||||||
flowextra/PacketPassInactivityMonitor.c \
|
|
||||||
tun2socks/SocksUdpGwClient.c \
|
|
||||||
udpgw_client/UdpGwClient.c
|
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
||||||
|
|
|
@ -1,408 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 2.8)
|
|
||||||
project(BADVPN C)
|
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")
|
|
||||||
|
|
||||||
include(TestBigEndian)
|
|
||||||
include(CheckIncludeFiles)
|
|
||||||
include(CheckSymbolExists)
|
|
||||||
include(CheckTypeSize)
|
|
||||||
|
|
||||||
set(BUILD_COMPONENTS)
|
|
||||||
|
|
||||||
macro (build_switch name text default)
|
|
||||||
if (BUILD_NOTHING_BY_DEFAULT)
|
|
||||||
option(BUILD_${name} "${text}" OFF)
|
|
||||||
else ()
|
|
||||||
option(BUILD_${name} "${text}" "${default}")
|
|
||||||
endif ()
|
|
||||||
list(APPEND BUILD_COMPONENTS "${name}")
|
|
||||||
endmacro ()
|
|
||||||
|
|
||||||
# detect Emscripten
|
|
||||||
if (CMAKE_C_COMPILER MATCHES "/emcc$")
|
|
||||||
set(EMSCRIPTEN ON)
|
|
||||||
else ()
|
|
||||||
set(EMSCRIPTEN OFF)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (EMSCRIPTEN)
|
|
||||||
set(ON_IF_NOT_EMSCRIPTEN OFF)
|
|
||||||
else ()
|
|
||||||
set(ON_IF_NOT_EMSCRIPTEN ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT EMSCRIPTEN)
|
|
||||||
set(ON_IF_LINUX ON)
|
|
||||||
else ()
|
|
||||||
set(ON_IF_LINUX OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR EMSCRIPTEN)
|
|
||||||
set(ON_IF_LINUX_OR_EMSCRIPTEN ON)
|
|
||||||
else ()
|
|
||||||
set(ON_IF_LINUX_OR_EMSCRIPTEN OFF)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# define build defaults
|
|
||||||
build_switch(EXAMPLES "build example programs" ON)
|
|
||||||
build_switch(TESTS "build some other example programs" ON)
|
|
||||||
build_switch(SERVER "build badvpn-server" ${ON_IF_NOT_EMSCRIPTEN})
|
|
||||||
build_switch(CLIENT "build badvpn-client" ${ON_IF_NOT_EMSCRIPTEN})
|
|
||||||
build_switch(FLOODER "build badvpn-flooder" ${ON_IF_NOT_EMSCRIPTEN})
|
|
||||||
build_switch(TUN2SOCKS "build badvpn-tun2socks" ${ON_IF_NOT_EMSCRIPTEN})
|
|
||||||
build_switch(UDPGW "build badvpn-udpgw" ${ON_IF_NOT_EMSCRIPTEN})
|
|
||||||
build_switch(NCD "build badvpn-ncd" ${ON_IF_LINUX_OR_EMSCRIPTEN})
|
|
||||||
build_switch(TUNCTL "build badvpn-tunctl" ${ON_IF_LINUX})
|
|
||||||
build_switch(DOSTEST "build dostest-server and dostest-attacker" OFF)
|
|
||||||
|
|
||||||
if (BUILD_NCD AND NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
|
|
||||||
message(FATAL_ERROR "NCD is only available on Linux")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (BUILD_CLIENT OR BUILD_SERVER)
|
|
||||||
find_package(OpenSSL REQUIRED)
|
|
||||||
set(LIBCRYPTO_INCLUDE_DIRS "${OpenSSL_INCLUDE_DIRS}")
|
|
||||||
set(LIBCRYPTO_LIBRARY_DIRS "${OpenSSL_LIBRARY_DIRS}")
|
|
||||||
set(LIBCRYPTO_LIBRARIES "${OpenSSL_LIBRARIES}")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (BUILD_SERVER OR BUILD_CLIENT OR BUILD_FLOODER)
|
|
||||||
find_package(NSPR REQUIRED)
|
|
||||||
find_package(NSS REQUIRED)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# choose reactor
|
|
||||||
if (DEFINED BREACTOR_BACKEND)
|
|
||||||
if (NOT (BREACTOR_BACKEND STREQUAL "badvpn" OR BREACTOR_BACKEND STREQUAL "glib"))
|
|
||||||
message(FATAL_ERROR "unknown reactor backend specified")
|
|
||||||
endif ()
|
|
||||||
else ()
|
|
||||||
if (EMSCRIPTEN)
|
|
||||||
set(BREACTOR_BACKEND "emscripten")
|
|
||||||
else ()
|
|
||||||
set(BREACTOR_BACKEND "badvpn")
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (BREACTOR_BACKEND STREQUAL "badvpn")
|
|
||||||
add_definitions(-DBADVPN_BREACTOR_BADVPN)
|
|
||||||
elseif (BREACTOR_BACKEND STREQUAL "glib")
|
|
||||||
if (NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
|
|
||||||
message(FATAL_ERROR "GLib reactor backend is only available on Linux")
|
|
||||||
endif ()
|
|
||||||
find_package(GLIB2 REQUIRED)
|
|
||||||
add_definitions(-DBADVPN_BREACTOR_GLIB)
|
|
||||||
elseif (BREACTOR_BACKEND STREQUAL "emscripten")
|
|
||||||
add_definitions(-DBADVPN_BREACTOR_EMSCRIPTEN)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
include_directories(
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
${LIBCRYPTO_INCLUDE_DIRS}
|
|
||||||
${NSPR_INCLUDE_DIRS}
|
|
||||||
${NSS_INCLUDE_DIRS}
|
|
||||||
${GLIB2_INCLUDE_DIR}
|
|
||||||
lwip/custom
|
|
||||||
lwip/src/include
|
|
||||||
lwip/src/include/ipv4
|
|
||||||
lwip/src/include/ipv6
|
|
||||||
)
|
|
||||||
|
|
||||||
link_directories(
|
|
||||||
${LIBCRYPTO_LIBRARY_DIRS}
|
|
||||||
${NSPR_LIBRARY_DIRS}
|
|
||||||
${NSS_LIBRARY_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
test_big_endian(BIG_ENDIAN)
|
|
||||||
|
|
||||||
check_type_size(int INT_SIZE)
|
|
||||||
if (NOT (INT_SIZE GREATER "3"))
|
|
||||||
message(FATAL_ERROR "int must be at least 32 bits")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
check_type_size(size_t SIZE_SIZE)
|
|
||||||
if (NOT (SIZE_SIZE GREATER INT_SIZE OR SIZE_SIZE EQUAL INT_SIZE))
|
|
||||||
message(FATAL_ERROR "size_t must be greater or equal than int")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (MSVC)
|
|
||||||
add_definitions(/TP -D_CRT_SECURE_NO_WARNINGS /wd4065 /wd4018 /wd4533 /wd4244 /wd4102)
|
|
||||||
else ()
|
|
||||||
add_definitions(-std=gnu99 -Wall -Wno-unused-value -Wno-parentheses -Wno-switch -Wredundant-decls)
|
|
||||||
|
|
||||||
if (NOT CMAKE_C_COMPILER_ID STREQUAL "PathScale")
|
|
||||||
add_definitions(-Werror=implicit-function-declaration -Wno-switch-enum -Wno-unused-function
|
|
||||||
-Wstrict-aliasing)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (CMAKE_C_COMPILER_ID MATCHES "^Clang")
|
|
||||||
add_definitions(-Wno-initializer-overrides -Wno-tautological-constant-out-of-range-compare)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# platform-specific stuff
|
|
||||||
if (WIN32)
|
|
||||||
add_definitions(-DBADVPN_USE_WINAPI -D_WIN32_WINNT=0x600 -DWIN32_LEAN_AND_MEAN)
|
|
||||||
add_definitions(-DBADVPN_THREAD_SAFE=0)
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_DEFINITIONS "-D_WIN32_WINNT=0x600")
|
|
||||||
check_symbol_exists(WSAID_WSASENDMSG "winsock2.h;mswsock.h" HAVE_MSW_1)
|
|
||||||
check_symbol_exists(WSAID_WSARECVMSG "winsock2.h;mswsock.h" HAVE_MSW_2)
|
|
||||||
check_symbol_exists(WSAID_ACCEPTEX "winsock2.h;mswsock.h" HAVE_MSW_3)
|
|
||||||
check_symbol_exists(WSAID_GETACCEPTEXSOCKADDRS "winsock2.h;mswsock.h" HAVE_MSW_4)
|
|
||||||
check_symbol_exists(WSAID_CONNECTEX "winsock2.h;mswsock.h" HAVE_MSW_5)
|
|
||||||
set(CMAKE_REQUIRED_DEFINITIONS "")
|
|
||||||
if (NOT (HAVE_MSW_1 AND HAVE_MSW_2 AND HAVE_MSW_3 AND HAVE_MSW_4 AND HAVE_MSW_5))
|
|
||||||
add_definitions(-DBADVPN_USE_SHIPPED_MSWSOCK)
|
|
||||||
check_type_size(WSAMSG HAVE_WSAMSG)
|
|
||||||
if (NOT HAVE_WSAMSG)
|
|
||||||
add_definitions(-DBADVPN_SHIPPED_MSWSOCK_DECLARE_WSAMSG)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
else ()
|
|
||||||
set(BADVPN_THREADWORK_USE_PTHREAD 1)
|
|
||||||
add_definitions(-DBADVPN_THREADWORK_USE_PTHREAD)
|
|
||||||
add_definitions(-DBADVPN_THREAD_SAFE=1)
|
|
||||||
|
|
||||||
link_libraries(rt)
|
|
||||||
|
|
||||||
if (EMSCRIPTEN)
|
|
||||||
add_definitions(-DBADVPN_EMSCRIPTEN)
|
|
||||||
add_definitions(-DBADVPN_NO_PROCESS -DBADVPN_NO_UDEV -DBADVPN_NO_RANDOM)
|
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
add_definitions(-DBADVPN_LINUX)
|
|
||||||
|
|
||||||
check_include_files(sys/signalfd.h HAVE_SYS_SIGNALFD_H)
|
|
||||||
if (HAVE_SYS_SIGNALFD_H)
|
|
||||||
add_definitions(-DBADVPN_USE_SIGNALFD)
|
|
||||||
else ()
|
|
||||||
add_definitions(-DBADVPN_USE_SELFPIPE)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
check_include_files(sys/epoll.h HAVE_SYS_EPOLL_H)
|
|
||||||
if (HAVE_SYS_EPOLL_H)
|
|
||||||
add_definitions(-DBADVPN_USE_EPOLL)
|
|
||||||
else ()
|
|
||||||
add_definitions(-DBADVPN_USE_POLL)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
check_include_files(linux/rfkill.h HAVE_LINUX_RFKILL_H)
|
|
||||||
if (HAVE_LINUX_RFKILL_H)
|
|
||||||
add_definitions(-DBADVPN_USE_LINUX_RFKILL)
|
|
||||||
set(BADVPN_USE_LINUX_RFKILL 1)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
check_include_files(linux/input.h HAVE_LINUX_INPUT_H)
|
|
||||||
if (HAVE_LINUX_INPUT_H)
|
|
||||||
add_definitions(-DBADVPN_USE_LINUX_INPUT)
|
|
||||||
set(BADVPN_USE_LINUX_INPUT 1)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
check_include_files(sys/inotify.h HAVE_SYS_INOTIFY_H)
|
|
||||||
if (HAVE_SYS_INOTIFY_H)
|
|
||||||
add_definitions(-DBADVPN_USE_INOTIFY)
|
|
||||||
set(BADVPN_USE_INOTIFY 1)
|
|
||||||
endif ()
|
|
||||||
elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
|
||||||
add_definitions(-DBADVPN_FREEBSD)
|
|
||||||
|
|
||||||
check_symbol_exists(kqueue "sys/types.h;sys/event.h;sys/time.h" HAVE_KQUEUE)
|
|
||||||
if (NOT HAVE_KQUEUE)
|
|
||||||
message(FATAL_ERROR "kqueue is required")
|
|
||||||
endif ()
|
|
||||||
add_definitions(-DBADVPN_USE_KEVENT)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT DEFINED BADVPN_WITHOUT_CRYPTODEV)
|
|
||||||
check_include_files(crypto/cryptodev.h HAVE_CRYPTO_CRYPTODEV_H)
|
|
||||||
if (HAVE_CRYPTO_CRYPTODEV_H)
|
|
||||||
add_definitions(-DBADVPN_USE_CRYPTODEV)
|
|
||||||
elseif (DEFINED BADVPN_WITH_CRYPTODEV)
|
|
||||||
message(FATAL_ERROR "crypto/cryptodev.h not found")
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# check for syslog
|
|
||||||
check_include_files(syslog.h HAVE_SYSLOG_H)
|
|
||||||
if (HAVE_SYSLOG_H)
|
|
||||||
add_definitions(-DBADVPN_USE_SYSLOG)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# add preprocessor definitions
|
|
||||||
if (BIG_ENDIAN)
|
|
||||||
add_definitions(-DBADVPN_BIG_ENDIAN)
|
|
||||||
else ()
|
|
||||||
add_definitions(-DBADVPN_LITTLE_ENDIAN)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# install man pages
|
|
||||||
install(
|
|
||||||
FILES badvpn.7
|
|
||||||
DESTINATION share/man/man7
|
|
||||||
)
|
|
||||||
|
|
||||||
# reset variables indicating whether we're building various libraries,
|
|
||||||
# and set them in the respective CMakeLists files. This is used to disable
|
|
||||||
# building examples and tests which require libraries that are not available.
|
|
||||||
set(BUILDING_SECURITY 0)
|
|
||||||
set(BUILDING_DHCPCLIENT 0)
|
|
||||||
set(BUILDING_ARPPROBE 0)
|
|
||||||
set(BUILDING_BKIO 0)
|
|
||||||
set(BUILDING_PREDICATE 0)
|
|
||||||
set(BUILDING_UDEVMONITOR 0)
|
|
||||||
set(BUILDING_THREADWORK 0)
|
|
||||||
set(BUILDING_RANDOM 0)
|
|
||||||
|
|
||||||
# Used to register an internal library.
|
|
||||||
# This will also add a library with the -plugin suffix, which is useful
|
|
||||||
# for use by dynamic libraries (e.g. NCD modules):
|
|
||||||
# - If BUILD_SHARED_LIBS is off (default), the libraries ${LIB_NAME} and ${LIB_NAME}-plugin
|
|
||||||
# are built separately. Both are static libraries but the -plugin variant is build as position
|
|
||||||
# independent code, so it can be (statically) linked into dynamic libraries.
|
|
||||||
# - If BUILD_SHARED_LIBS is on, only ${LIB_NAME} is built, as a shared library.
|
|
||||||
# The ${LIB_NAME}-plugin target is set up as an alias to ${LIB_NAME}.
|
|
||||||
function(badvpn_add_library LIB_NAME LINK_BADVPN_LIBS LINK_SYS_LIBS LIB_SOURCES)
|
|
||||||
set(BADVPN_LIBS_EXEC)
|
|
||||||
set(BADVPN_LIBS_PLUGIN)
|
|
||||||
foreach(LIB ${LINK_BADVPN_LIBS})
|
|
||||||
list(APPEND BADVPN_LIBS_EXEC "${LIB}")
|
|
||||||
list(APPEND BADVPN_LIBS_PLUGIN "${LIB}-plugin")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
add_library("${LIB_NAME}" ${LIB_SOURCES})
|
|
||||||
target_link_libraries("${LIB_NAME}" ${BADVPN_LIBS_EXEC} ${LINK_SYS_LIBS})
|
|
||||||
set_target_properties("${LIB_NAME}" PROPERTIES OUTPUT_NAME "badvpn-${LIB_NAME}")
|
|
||||||
|
|
||||||
if (BUILD_SHARED_LIBS)
|
|
||||||
add_library("${LIB_NAME}-plugin" ALIAS "${LIB_NAME}")
|
|
||||||
else ()
|
|
||||||
add_library("${LIB_NAME}-plugin" STATIC ${LIB_SOURCES})
|
|
||||||
target_link_libraries("${LIB_NAME}-plugin" ${BADVPN_LIBS_PLUGIN} ${LINK_SYS_LIBS})
|
|
||||||
set_target_properties("${LIB_NAME}-plugin" PROPERTIES OUTPUT_NAME "badvpn-${LIB_NAME}-plugin")
|
|
||||||
set_target_properties("${LIB_NAME}-plugin" PROPERTIES POSITION_INDEPENDENT_CODE YES)
|
|
||||||
set_target_properties("${LIB_NAME}-plugin" PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -DBADVPN_PLUGIN")
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# internal libraries
|
|
||||||
add_subdirectory(base)
|
|
||||||
add_subdirectory(system)
|
|
||||||
add_subdirectory(flow)
|
|
||||||
add_subdirectory(flowextra)
|
|
||||||
if (OpenSSL_FOUND)
|
|
||||||
set(BUILDING_SECURITY 1)
|
|
||||||
add_subdirectory(security)
|
|
||||||
endif ()
|
|
||||||
if (NSS_FOUND)
|
|
||||||
add_subdirectory(nspr_support)
|
|
||||||
endif ()
|
|
||||||
if (BUILD_CLIENT OR BUILDING_SECURITY)
|
|
||||||
set(BUILDING_THREADWORK 1)
|
|
||||||
add_subdirectory(threadwork)
|
|
||||||
endif ()
|
|
||||||
if (BUILD_CLIENT OR BUILD_TUN2SOCKS)
|
|
||||||
add_subdirectory(tuntap)
|
|
||||||
endif ()
|
|
||||||
if (BUILD_SERVER)
|
|
||||||
set(BUILDING_PREDICATE 1)
|
|
||||||
add_subdirectory(predicate)
|
|
||||||
endif ()
|
|
||||||
if (BUILD_CLIENT OR BUILD_FLOODER)
|
|
||||||
add_subdirectory(server_connection)
|
|
||||||
endif ()
|
|
||||||
if (BUILD_NCD AND NOT EMSCRIPTEN)
|
|
||||||
set(BUILDING_DHCPCLIENT 1)
|
|
||||||
set(BUILDING_ARPPROBE 1)
|
|
||||||
set(BUILDING_UDEVMONITOR 1)
|
|
||||||
set(BUILDING_RANDOM 1)
|
|
||||||
add_subdirectory(stringmap)
|
|
||||||
add_subdirectory(udevmonitor)
|
|
||||||
add_subdirectory(dhcpclient)
|
|
||||||
add_subdirectory(arpprobe)
|
|
||||||
add_subdirectory(random)
|
|
||||||
endif ()
|
|
||||||
if (BUILD_TUN2SOCKS)
|
|
||||||
add_subdirectory(socksclient)
|
|
||||||
add_subdirectory(udpgw_client)
|
|
||||||
add_subdirectory(lwip)
|
|
||||||
endif ()
|
|
||||||
if (BUILD_TUNCTL)
|
|
||||||
add_subdirectory(tunctl)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# example programs
|
|
||||||
if (BUILD_EXAMPLES)
|
|
||||||
add_subdirectory(examples)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# tests
|
|
||||||
if (BUILD_TESTS)
|
|
||||||
add_subdirectory(tests)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# server
|
|
||||||
if (BUILD_SERVER)
|
|
||||||
add_subdirectory(server)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# client
|
|
||||||
if (BUILD_CLIENT)
|
|
||||||
add_subdirectory(client)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# flooder
|
|
||||||
if (BUILD_FLOODER)
|
|
||||||
add_subdirectory(flooder)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# tun2socks
|
|
||||||
if (BUILD_TUN2SOCKS)
|
|
||||||
add_subdirectory(tun2socks)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# udpgw
|
|
||||||
if (BUILD_UDPGW)
|
|
||||||
add_subdirectory(udpgw)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# ncd
|
|
||||||
if (BUILD_NCD)
|
|
||||||
add_subdirectory(ncd)
|
|
||||||
if (NOT EMSCRIPTEN)
|
|
||||||
add_subdirectory(ncd-request)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# dostest
|
|
||||||
if (BUILD_DOSTEST)
|
|
||||||
add_subdirectory(dostest)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
message(STATUS "Building components:")
|
|
||||||
|
|
||||||
# print what we're building and what not
|
|
||||||
foreach (name ${BUILD_COMPONENTS})
|
|
||||||
# to lower name
|
|
||||||
string(TOLOWER "${name}" name_withspaces)
|
|
||||||
|
|
||||||
# append spaces to name
|
|
||||||
#while (TRUE)
|
|
||||||
# string(LENGTH "${name_withspaces}" length)
|
|
||||||
# if (NOT (length LESS 12))
|
|
||||||
# break()
|
|
||||||
# endif ()
|
|
||||||
# set(name_withspaces "${name_withspaces} ")
|
|
||||||
#endwhile ()
|
|
||||||
|
|
||||||
# determine if we're building
|
|
||||||
if (BUILD_${name})
|
|
||||||
set(building "yes")
|
|
||||||
else ()
|
|
||||||
set(building "no")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
message(STATUS " ${name_withspaces} ${building}")
|
|
||||||
endforeach ()
|
|
|
@ -1,24 +0,0 @@
|
||||||
Copyright (c) 2009, Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the author nor the
|
|
||||||
names of its contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
@ -1,216 +0,0 @@
|
||||||
Version 1.999.129:
|
|
||||||
|
|
||||||
- ncd: modules: file_open: Fix typo in assertion.
|
|
||||||
|
|
||||||
- server: Fix bug forgetting to call BSSLConnection_ReleaseBuffers(). Unless threads are enabled, this is an assert failure if NDEBUG is not defined an a non-issue otherwise.
|
|
||||||
|
|
||||||
- ncd: Look for various programs in PATH instead of hardcoded paths.
|
|
||||||
|
|
||||||
- Add compile-udpgw.sh.
|
|
||||||
|
|
||||||
- ncd: modules: net_dns: Implement net.dns.resolvconf() forspecification of arbitrary resolv.conf lines
|
|
||||||
|
|
||||||
Version 1.999.128:
|
|
||||||
|
|
||||||
- tun2socks: add option --append-source-to-username to give the SOCKS server the source IP of the connection
|
|
||||||
|
|
||||||
- tun2socks: IPv6 support, and updated to newer version of lwIP
|
|
||||||
|
|
||||||
- tun2socks: fix some bugs/crashes
|
|
||||||
|
|
||||||
- tun2socks, udpgw: transparent DNS forwarding, though no Windows support on udpgw side (contributed by Kerem Hadimli)
|
|
||||||
|
|
||||||
- NCD: preliminary support for dynamically loading commands
|
|
||||||
|
|
||||||
Version 1.999.127:
|
|
||||||
|
|
||||||
- client, server: implement experimental support for performing SSL operations in worker threads. Currently it's rather inefficient.
|
|
||||||
|
|
||||||
- NCD: modules: value: implement value::append() for appending to a list
|
|
||||||
|
|
||||||
- NCD: modules: net_iptables: add single-argument form of append and insert commands, allowing for generic use
|
|
||||||
|
|
||||||
- NCD: modules: net_iptables: implement net.iptables.insert() and net.ebtables.insert()
|
|
||||||
|
|
||||||
- NCD: modules: sys_start_process: implement options, including username, term_on_deinit and deinit_kill_time
|
|
||||||
|
|
||||||
- NCD: modules: sys_request_server: implement _caller in request handler
|
|
||||||
|
|
||||||
- NCD: modules: add getenv()
|
|
||||||
|
|
||||||
- NCD: modules: daemon: implement options, including username option
|
|
||||||
|
|
||||||
- NCD: modules: runonce: add new options format with a map, implement username option
|
|
||||||
|
|
||||||
- NCD: modules: add buffer(), which exposes a buffer with efficient appending and removing from the beginning.
|
|
||||||
|
|
||||||
- NCD: add a new internal string representation called ComposedString. This allows modules to expose the concatenation of multiple memroy buffers as a single string value, efficiently.
|
|
||||||
|
|
||||||
- fix many, hopefully all, strict aliasing violations. In particular, this fixes a bug where the DHCP client integrated into NCD won't work correctly, subject to optimization flags.
|
|
||||||
|
|
||||||
- NCD: modules: sleep: interpret empty string as no sleeping, add sleep(ms_start) with one argument
|
|
||||||
|
|
||||||
- NCD: modules: add log(), log_r() and log_fr() commands for logging via the BLog system
|
|
||||||
|
|
||||||
Version 1.999.126:
|
|
||||||
|
|
||||||
- NCD: modules: sleep: interpret empty string time as no sleeping, add sleep(ms_start) with one argument
|
|
||||||
|
|
||||||
- NCD: modules: add log module for message logging using the BLog system
|
|
||||||
|
|
||||||
- NCD: implement the "include" and "include_guard" directives, which allow separating reusable code into files
|
|
||||||
|
|
||||||
- NCD: modules: call2: implement call_with_caller_target(), which makes it easier to write reusable code that calls back user-provided code
|
|
||||||
|
|
||||||
- NCD: modules: call2: remove call2_if(), call2_ifelse(), embcall2(), embcall2_if(), embcall2_ifelse()
|
|
||||||
|
|
||||||
- NCD: modules: add sys.start_process(), which implements starting and controlling external processes and reading/writing their stdout/stdin
|
|
||||||
|
|
||||||
- tun2socks: implement SOCKS password authentication
|
|
||||||
|
|
||||||
- NCD: track the depth of values and limit the maximum depth. This avoids stack overflow with very deeply nested values.
|
|
||||||
|
|
||||||
- NCD: modules: add substr()
|
|
||||||
|
|
||||||
- NCD: process_manager: add 2-argument start() method which doesn't take a process identifier
|
|
||||||
|
|
||||||
- NCD: process_manager: allow process identifiers to be any value not just strings
|
|
||||||
|
|
||||||
- NCD: multidepend, depend_scope: fix immediate effect order when a depend finishes backtracking
|
|
||||||
|
|
||||||
- NCD: add depend_scope module to do exactly what the multidepend module does, but with separate non-global dependency name scopes
|
|
||||||
|
|
||||||
- NCD: multidepend: allow dependency names to be any value not just strings
|
|
||||||
|
|
||||||
- NCD: implement value::insert(what) for appending to a list
|
|
||||||
|
|
||||||
- NCD: change the format of addresses in sys.request_server() and sys.request_client() to be the same as in the socket module
|
|
||||||
|
|
||||||
- NCD: add socket module (sys.connect() and sys.listen())
|
|
||||||
|
|
||||||
- NCD: fix bug where duplicate template/process names would not be detected and weird behaviour would result
|
|
||||||
|
|
||||||
- NCD: add backtrack_point() for simple backtracking
|
|
||||||
|
|
||||||
- NCD: add file_open() for more complete file I/O
|
|
||||||
|
|
||||||
- NCD: implement parse_ipv6_addr() and parse_ipv6_cidr_addr()
|
|
||||||
|
|
||||||
- NCD: port to Emscripten/Javascript, for the in-browser demo
|
|
||||||
|
|
||||||
- NCD: many performance and memory usage improvements
|
|
||||||
|
|
||||||
- NCD: add assert_false()
|
|
||||||
|
|
||||||
- NCD: don't link to OpenSSL to for random number generator. Use /dev/urandom instead to generate XIDs for DHCP.
|
|
||||||
|
|
||||||
- NCD: deprecate ip_in_network() and instead add net.ipv{4,6}.addr_in_network(), net.ipv{4,6}.ifnot_addr_in_network()
|
|
||||||
|
|
||||||
- NCD: implement some IPv6 modules: net.ipv6.addr(), net.ipv6.route()
|
|
||||||
|
|
||||||
- NCD: support CIDR style addr/prefix addresses in various modules
|
|
||||||
|
|
||||||
- NCD: recognize Elif and Else with capital first letter to be consistent with other reserved keywords
|
|
||||||
|
|
||||||
Version 1.999.123:
|
|
||||||
|
|
||||||
- NCD: performance improvements related to finding modules for statements
|
|
||||||
|
|
||||||
- NCD: performance improvements related to resolving object names
|
|
||||||
|
|
||||||
- NCD: performance improvements related to instantiating statement arguments
|
|
||||||
|
|
||||||
- NCD: add value::replace_this() and value::replace_this_undo()
|
|
||||||
|
|
||||||
- NCD: add value::reset()
|
|
||||||
|
|
||||||
- NCD: add value::replace() and value::replace_undo()
|
|
||||||
|
|
||||||
- Port to compile with MSVC for Windows.
|
|
||||||
|
|
||||||
- NCD: add Foreach clause
|
|
||||||
|
|
||||||
- NCD: implement _caller in spawn(), add spawn::join()
|
|
||||||
|
|
||||||
- NCD: add explode()
|
|
||||||
|
|
||||||
- NCD: add hard_reboot() and hard_poweroff()
|
|
||||||
|
|
||||||
- NCD: add file_stat() and file_lstat()
|
|
||||||
|
|
||||||
- NCD: fix regex_replace() semantics. It was very broken because it did a complete replacement pass for every regex on the list, so it would match parts that have already been replaced, producing unexpected results.
|
|
||||||
|
|
||||||
- NCD: small performance improvement
|
|
||||||
|
|
||||||
Version 1.999.121:
|
|
||||||
|
|
||||||
- NCD: improve error handling semantics; see http://code.google.com/p/badvpn/source/detail?r=1376
|
|
||||||
|
|
||||||
- NCD: fix assertion failure in sys.evdev() if a device error occurs (e.g. device unplugged) while an event is being processed. Similar fix in some other modules, but these may not be reproducable.
|
|
||||||
|
|
||||||
- NCD: some more performance improvements
|
|
||||||
|
|
||||||
- NCD: some performance improvements (~30% faster interpretation of cpu-bound code)
|
|
||||||
|
|
||||||
- NCD: implemented If..elif..else clause.
|
|
||||||
|
|
||||||
- NCD: net.backend.wpa_supplicant: fix to work with wpa_supplicant>=1.0
|
|
||||||
|
|
||||||
Version 1.999.115:
|
|
||||||
|
|
||||||
- NCD: Many improvements; new statements, including call(), alias(), foreach(), choose().
|
|
||||||
|
|
||||||
Version 1.999.113:
|
|
||||||
|
|
||||||
- NCD: when starting child processes, make sure that file descriptors for standard
|
|
||||||
streams are always open in the child, by opening /dev/null if they are not.
|
|
||||||
|
|
||||||
- Improve build system to allow selective building of components.
|
|
||||||
By default, everything is built, unless -DBUILD_NOTHING_BY_DEFAULT=1 is given.
|
|
||||||
Individual components can then be enabled or disabled using -DBUILD_COMPONENT=1
|
|
||||||
and -DBUILD_COMPONENT=0.
|
|
||||||
|
|
||||||
- When starting any BadVPN program, make sure that file descriptors for standard
|
|
||||||
streams are always open in the child, by opening /dev/null if they are not.
|
|
||||||
|
|
||||||
- NCD: net.backend.wpa_supplicant(): add 'bssid' and 'ssid' variables to allow
|
|
||||||
determining what wireless network wpa_supplicant connected to.
|
|
||||||
|
|
||||||
- NCD: net.backend.wpa_supplicant(): do not require the user to start wpa_supplicant via
|
|
||||||
stdbuf, but do it automatically.
|
|
||||||
|
|
||||||
Version 1.999.111:
|
|
||||||
|
|
||||||
- Improved protocol such that peers can use SSL when comminicating via the server. This
|
|
||||||
improves security, as compromising the server will not allow the attacker to see secret
|
|
||||||
data shared by peers (in particular, encryption keys and OTP seeds when in UDP mode).
|
|
||||||
|
|
||||||
Compatibility is preserved if an only if the following conditions are met:
|
|
||||||
- The server is using the latest version.
|
|
||||||
- If the network is using SSL, all clients using the new version are using the
|
|
||||||
"--allow-peer-talk-without-ssl" command line option.
|
|
||||||
|
|
||||||
Be aware, however, that using the "--allow-peer-talk-without-ssl" option negates the
|
|
||||||
security benefits of the new SSL support - not only between pairs of peers where one
|
|
||||||
peer is using the old version, but also between pairs where both peers are capable
|
|
||||||
of SSL. This is because the server can re-initialize the pair, telling them not to use
|
|
||||||
SSL.
|
|
||||||
|
|
||||||
Version 1.999.107:
|
|
||||||
|
|
||||||
- Added Windows IOCP support, removing the limitation on ~64 connections. This is important
|
|
||||||
for tun2socks, which may have to handle several hundred connections.
|
|
||||||
|
|
||||||
Version 1.999.105.2:
|
|
||||||
|
|
||||||
- Fixed an assertion failure in tun2socks related to sending data to SOCKS.
|
|
||||||
|
|
||||||
Version 1.999.101.3:
|
|
||||||
|
|
||||||
- Fixed UDP transport on Windows 7 which didn't work (was only tested on XP).
|
|
||||||
|
|
||||||
Version 1.999.101:
|
|
||||||
|
|
||||||
- Fixed a protocol issue present in versions <=1.999.100.3. Compatibility is preserved in
|
|
||||||
case of a new server and old clients, but it is not possible to connect to an old server
|
|
||||||
with a new client.
|
|
|
@ -1,76 +0,0 @@
|
||||||
1 Requirements
|
|
||||||
|
|
||||||
1.1 Operating system
|
|
||||||
|
|
||||||
Linux:
|
|
||||||
- Linux kernel 2.6. Kernel 2.4 will work, but performance will suffer.
|
|
||||||
- tested on x86, x86_64 and ARM architectures. Not tested on any big-endian architecture.
|
|
||||||
|
|
||||||
Windows:
|
|
||||||
- Windows XP or newer; tested on Windows XP and Windows 7
|
|
||||||
|
|
||||||
FreeBSD:
|
|
||||||
- Not regularly tested.
|
|
||||||
|
|
||||||
Other systems are not supported.
|
|
||||||
|
|
||||||
1.2 Compilers
|
|
||||||
|
|
||||||
Linux:
|
|
||||||
- gcc
|
|
||||||
- clang, except >=3.0 (clang bug http://llvm.org/bugs/show_bug.cgi?id=11535)
|
|
||||||
|
|
||||||
Windows:
|
|
||||||
- gcc from the mingw-w64 project for 32-bit targets
|
|
||||||
|
|
||||||
C language features used:
|
|
||||||
- Standard (all part of C99):
|
|
||||||
- designated initializers
|
|
||||||
- stdint.h, inttypes.h, stddef.h
|
|
||||||
- intermingled declarations and code
|
|
||||||
- for loop initial declaration
|
|
||||||
- one-line "//" comments
|
|
||||||
- Extensions:
|
|
||||||
- packed structure attribute (to pack a structure and allow unaligned access)
|
|
||||||
|
|
||||||
1.3 CMake
|
|
||||||
|
|
||||||
The build system uses CMake.
|
|
||||||
|
|
||||||
1.4 OpenSSL
|
|
||||||
|
|
||||||
Libcrypto (part of OpenSSL) is used for block ciphers, hash functions and random data generation.
|
|
||||||
|
|
||||||
1.5 Network Security Services (NSS)
|
|
||||||
|
|
||||||
The NSS library from Mozilla is used for TLS support. NSS command-line tools are also needed
|
|
||||||
for setting up certificates.
|
|
||||||
|
|
||||||
1.6 TAP-Win32 (Windows only) (runtime only)
|
|
||||||
|
|
||||||
The TAP-Win32 driver, part of OpenVPN.
|
|
||||||
|
|
||||||
2 Compilation
|
|
||||||
|
|
||||||
2.1 Compiling on Linux
|
|
||||||
|
|
||||||
$ tar xf badvpn-<version>.tar.bz2
|
|
||||||
$ mkdir build
|
|
||||||
$ cd build
|
|
||||||
$ cmake ../badvpn-<version> -DCMAKE_INSTALL_PREFIX=/usr/local
|
|
||||||
$ make
|
|
||||||
If you want to install it, run as root:
|
|
||||||
# make install
|
|
||||||
|
|
||||||
If you only want NCD or tun2socks and not the VPN system, you can avoid the NSS dependency by passing
|
|
||||||
the following to the cmake command:
|
|
||||||
-DBUILD_NCD=1 -DBUILD_TUN2SOCKS=1 -DBUILD_NOTHING_BY_DEFAULT=1
|
|
||||||
|
|
||||||
2.2 Compiling for Windows
|
|
||||||
|
|
||||||
See the file INSTALL-WINDOWS for detailed instructions.
|
|
||||||
|
|
||||||
3 Usage
|
|
||||||
|
|
||||||
The primary documentation is on the BadVPN homepage, http://code.google.com/p/badvpn/ .
|
|
||||||
Additionally, some man pages are installed (badvpn(7), badvpn-server(8), badvpn-client(8)).
|
|
|
@ -1,72 +0,0 @@
|
||||||
There are many ways to build BadVPN for Windows. It can be built with MSVC or GCC compilers,
|
|
||||||
and it be built natively from Windows or cross-compiled from Linux. However, this document
|
|
||||||
only describes building natively from Windows using MSVC.
|
|
||||||
|
|
||||||
1. Get a MSVC compiler, e.g. from Visual Studio, Visual Studio Express or from the Windows SDK.
|
|
||||||
|
|
||||||
2. Choose a directory where built stuff will be installed into; we call it <root>.
|
|
||||||
|
|
||||||
3. Build the NSS library.
|
|
||||||
NOTE: you can also use the prebuilt version in the BadVPN windows download.
|
|
||||||
|
|
||||||
- Install MozillaBuild:
|
|
||||||
http://ftp.mozilla.org/pub/mozilla.org/mozilla/libraries/win32/MozillaBuildSetup-Latest.exe .
|
|
||||||
|
|
||||||
- Download the NSS source code that includes NSPR. As of the time of writing the latest version was 3.13.5:
|
|
||||||
https://ftp.mozilla.org/pub/mozilla.org/security/nss/releases/NSS_3_13_5_RTM/src/nss-3.13.5-with-nspr-4.9.1.tar.gz .
|
|
||||||
|
|
||||||
Extract it to c:\ so that you have C:\mozilla .
|
|
||||||
|
|
||||||
- Open a terminal with access to the Visual Studio compilers and other tools. E.g. if you use the Windows SDK,
|
|
||||||
activate the following start menu item: Programs -> Microsoft Windows SDK v7.1 -> Windows SDK 7.1 Command Prompt.
|
|
||||||
|
|
||||||
- In this terminal, run:
|
|
||||||
|
|
||||||
> c:\mozilla-build\start-l10n.bat
|
|
||||||
|
|
||||||
- Either a new terminal opens with a bash shell, or a bash shell starts in the existing terminal. Either way,
|
|
||||||
enter the following commands to finally build NSS: (here paths are written as /driveletter/...)
|
|
||||||
|
|
||||||
$ export OS_TARGET=WINNT
|
|
||||||
$ export BUILD_OPT=1
|
|
||||||
$ cd <nss_source_dir>/mozilla/security/nss
|
|
||||||
$ make nss_build_all
|
|
||||||
|
|
||||||
Now use a script shipped with the BadVPN source to copy the resulting files into appropriate directories within <root>:
|
|
||||||
|
|
||||||
$ <badvpn_source_dir>/scripts/copy_nss ../../dist <root>
|
|
||||||
|
|
||||||
4. Build the OpenSSL library.
|
|
||||||
NOTE: you can also use the prebuilt version in the BadVPN windows download.
|
|
||||||
|
|
||||||
- Install ActivePerl.
|
|
||||||
|
|
||||||
- Download the OpenSSL source code and extract it.
|
|
||||||
|
|
||||||
- Open a compiler terminal, as was done when building NSS. Inside it, run:
|
|
||||||
|
|
||||||
> cd <openssl_source_dir>
|
|
||||||
> perl Configure VC-WIN32 --prefix=<root>
|
|
||||||
> ms\do_ms
|
|
||||||
> nmake -f ms\ntdll.mak
|
|
||||||
|
|
||||||
To copy the results into <root>:
|
|
||||||
|
|
||||||
> nmake -f ms\ntdll.mak install
|
|
||||||
|
|
||||||
5. Build BadVPN.
|
|
||||||
|
|
||||||
- Install CMake. During installation, select the option to include cmake in PATH
|
|
||||||
to avoid having to type a long path into the terminal.
|
|
||||||
|
|
||||||
- Create an empty folder where BadVPN will be built; call it <build>.
|
|
||||||
|
|
||||||
- Open a compiler terminal. Inside it, run:
|
|
||||||
|
|
||||||
> cd <build>
|
|
||||||
> cmake <badvpn_source_dir> -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX=<root> -DCMAKE_BUILD_TYPE=Release
|
|
||||||
> nmake
|
|
||||||
|
|
||||||
To copy the results into <root>:
|
|
||||||
|
|
||||||
> nmake install
|
|
|
@ -1,359 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BArpProbe.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/if_arp.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <linux/filter.h>
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <misc/byteorder.h>
|
|
||||||
#include <misc/ethernet_proto.h>
|
|
||||||
#include <misc/ipv4_proto.h>
|
|
||||||
#include <misc/udp_proto.h>
|
|
||||||
#include <misc/get_iface_info.h>
|
|
||||||
#include <base/BLog.h>
|
|
||||||
|
|
||||||
#include "BArpProbe.h"
|
|
||||||
|
|
||||||
#include <generated/blog_channel_BArpProbe.h>
|
|
||||||
|
|
||||||
#define STATE_INITIAL 1
|
|
||||||
#define STATE_NOEXIST 2
|
|
||||||
#define STATE_EXIST 3
|
|
||||||
#define STATE_EXIST_PANIC 4
|
|
||||||
|
|
||||||
static void dgram_handler (BArpProbe *o, int event)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
BLog(BLOG_ERROR, "packet socket error");
|
|
||||||
|
|
||||||
// report error
|
|
||||||
DEBUGERROR(&o->d_err, o->handler(o->user, BARPPROBE_EVENT_ERROR));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void send_request (BArpProbe *o)
|
|
||||||
{
|
|
||||||
if (o->send_sending) {
|
|
||||||
BLog(BLOG_ERROR, "cannot send packet while another packet is being sent!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// build packet
|
|
||||||
struct arp_packet *arp = &o->send_packet;
|
|
||||||
arp->hardware_type = hton16(ARP_HARDWARE_TYPE_ETHERNET);
|
|
||||||
arp->protocol_type = hton16(ETHERTYPE_IPV4);
|
|
||||||
arp->hardware_size = hton8(6);
|
|
||||||
arp->protocol_size = hton8(4);
|
|
||||||
arp->opcode = hton16(ARP_OPCODE_REQUEST);
|
|
||||||
memcpy(arp->sender_mac, o->if_mac, 6);
|
|
||||||
arp->sender_ip = hton32(0);
|
|
||||||
memset(arp->target_mac, 0, sizeof(arp->target_mac));
|
|
||||||
arp->target_ip = o->addr;
|
|
||||||
|
|
||||||
// send packet
|
|
||||||
PacketPassInterface_Sender_Send(o->send_if, (uint8_t *)&o->send_packet, sizeof(o->send_packet));
|
|
||||||
|
|
||||||
// set sending
|
|
||||||
o->send_sending = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void send_if_handler_done (BArpProbe *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(o->send_sending)
|
|
||||||
|
|
||||||
// set not sending
|
|
||||||
o->send_sending = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void recv_if_handler_done (BArpProbe *o, int data_len)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(data_len >= 0)
|
|
||||||
ASSERT(data_len <= sizeof(struct arp_packet))
|
|
||||||
|
|
||||||
// receive next packet
|
|
||||||
PacketRecvInterface_Receiver_Recv(o->recv_if, (uint8_t *)&o->recv_packet);
|
|
||||||
|
|
||||||
if (data_len != sizeof(struct arp_packet)) {
|
|
||||||
BLog(BLOG_WARNING, "receive: wrong size");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct arp_packet *arp = &o->recv_packet;
|
|
||||||
|
|
||||||
if (ntoh16(arp->hardware_type) != ARP_HARDWARE_TYPE_ETHERNET) {
|
|
||||||
BLog(BLOG_WARNING, "receive: wrong hardware type");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntoh16(arp->protocol_type) != ETHERTYPE_IPV4) {
|
|
||||||
BLog(BLOG_WARNING, "receive: wrong protocol type");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntoh8(arp->hardware_size) != 6) {
|
|
||||||
BLog(BLOG_WARNING, "receive: wrong hardware size");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntoh8(arp->protocol_size) != 4) {
|
|
||||||
BLog(BLOG_WARNING, "receive: wrong protocol size");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntoh16(arp->opcode) != ARP_OPCODE_REPLY) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arp->sender_ip != o->addr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int old_state = o->state;
|
|
||||||
|
|
||||||
// set minus one missed
|
|
||||||
o->num_missed = -1;
|
|
||||||
|
|
||||||
// set timer
|
|
||||||
BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_WAITSEND);
|
|
||||||
|
|
||||||
// set state exist
|
|
||||||
o->state = STATE_EXIST;
|
|
||||||
|
|
||||||
// report exist if needed
|
|
||||||
if (old_state == STATE_INITIAL || old_state == STATE_NOEXIST) {
|
|
||||||
o->handler(o->user, BARPPROBE_EVENT_EXIST);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void timer_handler (BArpProbe *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// send request
|
|
||||||
send_request(o);
|
|
||||||
|
|
||||||
switch (o->state) {
|
|
||||||
case STATE_INITIAL: {
|
|
||||||
ASSERT(o->num_missed >= 0)
|
|
||||||
ASSERT(o->num_missed < BARPPROBE_INITIAL_NUM_ATTEMPTS)
|
|
||||||
|
|
||||||
// increment missed
|
|
||||||
o->num_missed++;
|
|
||||||
|
|
||||||
// all attempts failed?
|
|
||||||
if (o->num_missed == BARPPROBE_INITIAL_NUM_ATTEMPTS) {
|
|
||||||
// set timer
|
|
||||||
BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_NOEXIST_WAITRECV);
|
|
||||||
|
|
||||||
// set state noexist
|
|
||||||
o->state = STATE_NOEXIST;
|
|
||||||
|
|
||||||
// report noexist
|
|
||||||
o->handler(o->user, BARPPROBE_EVENT_NOEXIST);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set timer
|
|
||||||
BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_INITIAL_WAITRECV);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case STATE_NOEXIST: {
|
|
||||||
// set timer
|
|
||||||
BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_NOEXIST_WAITRECV);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case STATE_EXIST: {
|
|
||||||
ASSERT(o->num_missed >= -1)
|
|
||||||
ASSERT(o->num_missed < BARPPROBE_EXIST_NUM_NOREPLY)
|
|
||||||
|
|
||||||
// increment missed
|
|
||||||
o->num_missed++;
|
|
||||||
|
|
||||||
// all missed?
|
|
||||||
if (o->num_missed == BARPPROBE_EXIST_NUM_NOREPLY) {
|
|
||||||
// set timer
|
|
||||||
BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_PANIC_WAITRECV);
|
|
||||||
|
|
||||||
// set zero missed
|
|
||||||
o->num_missed = 0;
|
|
||||||
|
|
||||||
// set state panic
|
|
||||||
o->state = STATE_EXIST_PANIC;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set timer
|
|
||||||
BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_WAITRECV);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case STATE_EXIST_PANIC: {
|
|
||||||
ASSERT(o->num_missed >= 0)
|
|
||||||
ASSERT(o->num_missed < BARPPROBE_EXIST_PANIC_NUM_NOREPLY)
|
|
||||||
|
|
||||||
// increment missed
|
|
||||||
o->num_missed++;
|
|
||||||
|
|
||||||
// all missed?
|
|
||||||
if (o->num_missed == BARPPROBE_EXIST_PANIC_NUM_NOREPLY) {
|
|
||||||
// set timer
|
|
||||||
BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_NOEXIST_WAITRECV);
|
|
||||||
|
|
||||||
// set state panic
|
|
||||||
o->state = STATE_NOEXIST;
|
|
||||||
|
|
||||||
// report noexist
|
|
||||||
o->handler(o->user, BARPPROBE_EVENT_NOEXIST);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set timer
|
|
||||||
BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_PANIC_WAITRECV);
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int BArpProbe_Init (BArpProbe *o, const char *ifname, uint32_t addr, BReactor *reactor, void *user, BArpProbe_handler handler)
|
|
||||||
{
|
|
||||||
ASSERT(ifname)
|
|
||||||
ASSERT(handler)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->addr = addr;
|
|
||||||
o->reactor = reactor;
|
|
||||||
o->user = user;
|
|
||||||
o->handler = handler;
|
|
||||||
|
|
||||||
// get interface information
|
|
||||||
int if_mtu;
|
|
||||||
int if_index;
|
|
||||||
if (!badvpn_get_iface_info(ifname, o->if_mac, &if_mtu, &if_index)) {
|
|
||||||
BLog(BLOG_ERROR, "failed to get interface information");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *if_mac = o->if_mac;
|
|
||||||
BLog(BLOG_INFO, "if_mac=%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8" if_mtu=%d if_index=%d",
|
|
||||||
if_mac[0], if_mac[1], if_mac[2], if_mac[3], if_mac[4], if_mac[5], if_mtu, if_index);
|
|
||||||
|
|
||||||
// check MTU
|
|
||||||
if (if_mtu < sizeof(struct arp_packet)) {
|
|
||||||
BLog(BLOG_ERROR, "MTU is too small for ARP !?!");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init dgram
|
|
||||||
if (!BDatagram_Init(&o->dgram, BADDR_TYPE_PACKET, o->reactor, o, (BDatagram_handler)dgram_handler)) {
|
|
||||||
BLog(BLOG_ERROR, "BDatagram_Init failed");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind dgram
|
|
||||||
BAddr bind_addr;
|
|
||||||
BAddr_InitPacket(&bind_addr, hton16(ETHERTYPE_ARP), if_index, BADDR_PACKET_HEADER_TYPE_ETHERNET, BADDR_PACKET_PACKET_TYPE_HOST, if_mac);
|
|
||||||
if (!BDatagram_Bind(&o->dgram, bind_addr)) {
|
|
||||||
BLog(BLOG_ERROR, "BDatagram_Bind failed");
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set dgram send addresses
|
|
||||||
BAddr dest_addr;
|
|
||||||
uint8_t broadcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
||||||
BAddr_InitPacket(&dest_addr, hton16(ETHERTYPE_ARP), if_index, BADDR_PACKET_HEADER_TYPE_ETHERNET, BADDR_PACKET_PACKET_TYPE_BROADCAST, broadcast_mac);
|
|
||||||
BIPAddr local_addr;
|
|
||||||
BIPAddr_InitInvalid(&local_addr);
|
|
||||||
BDatagram_SetSendAddrs(&o->dgram, dest_addr, local_addr);
|
|
||||||
|
|
||||||
// init send interface
|
|
||||||
BDatagram_SendAsync_Init(&o->dgram, sizeof(struct arp_packet));
|
|
||||||
o->send_if = BDatagram_SendAsync_GetIf(&o->dgram);
|
|
||||||
PacketPassInterface_Sender_Init(o->send_if, (PacketPassInterface_handler_done)send_if_handler_done, o);
|
|
||||||
|
|
||||||
// set not sending
|
|
||||||
o->send_sending = 0;
|
|
||||||
|
|
||||||
// init recv interface
|
|
||||||
BDatagram_RecvAsync_Init(&o->dgram, sizeof(struct arp_packet));
|
|
||||||
o->recv_if = BDatagram_RecvAsync_GetIf(&o->dgram);
|
|
||||||
PacketRecvInterface_Receiver_Init(o->recv_if, (PacketRecvInterface_handler_done)recv_if_handler_done, o);
|
|
||||||
|
|
||||||
// init timer
|
|
||||||
BTimer_Init(&o->timer, 0, (BTimer_handler)timer_handler, o);
|
|
||||||
|
|
||||||
// receive first packet
|
|
||||||
PacketRecvInterface_Receiver_Recv(o->recv_if, (uint8_t *)&o->recv_packet);
|
|
||||||
|
|
||||||
// send request
|
|
||||||
send_request(o);
|
|
||||||
|
|
||||||
// set timer
|
|
||||||
BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_INITIAL_WAITRECV);
|
|
||||||
|
|
||||||
// set zero missed
|
|
||||||
o->num_missed = 0;
|
|
||||||
|
|
||||||
// set state initial
|
|
||||||
o->state = STATE_INITIAL;
|
|
||||||
|
|
||||||
DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail1:
|
|
||||||
BDatagram_Free(&o->dgram);
|
|
||||||
fail0:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BArpProbe_Free (BArpProbe *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
DebugError_Free(&o->d_err);
|
|
||||||
|
|
||||||
// free timer
|
|
||||||
BReactor_RemoveTimer(o->reactor, &o->timer);
|
|
||||||
|
|
||||||
// free recv interface
|
|
||||||
BDatagram_RecvAsync_Free(&o->dgram);
|
|
||||||
|
|
||||||
// free send interface
|
|
||||||
BDatagram_SendAsync_Free(&o->dgram);
|
|
||||||
|
|
||||||
// free dgram
|
|
||||||
BDatagram_Free(&o->dgram);
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BArpProbe.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_BARPPROBE_H
|
|
||||||
#define BADVPN_BARPPROBE_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <misc/debugerror.h>
|
|
||||||
#include <misc/arp_proto.h>
|
|
||||||
#include <misc/ethernet_proto.h>
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
#include <system/BDatagram.h>
|
|
||||||
#include <system/BReactor.h>
|
|
||||||
|
|
||||||
#define BARPPROBE_INITIAL_WAITRECV 1000
|
|
||||||
#define BARPPROBE_INITIAL_NUM_ATTEMPTS 6
|
|
||||||
#define BARPPROBE_NOEXIST_WAITRECV 15000
|
|
||||||
#define BARPPROBE_EXIST_WAITSEND 15000
|
|
||||||
#define BARPPROBE_EXIST_WAITRECV 10000
|
|
||||||
#define BARPPROBE_EXIST_NUM_NOREPLY 2
|
|
||||||
#define BARPPROBE_EXIST_PANIC_WAITRECV 1000
|
|
||||||
#define BARPPROBE_EXIST_PANIC_NUM_NOREPLY 6
|
|
||||||
|
|
||||||
#define BARPPROBE_EVENT_EXIST 1
|
|
||||||
#define BARPPROBE_EVENT_NOEXIST 2
|
|
||||||
#define BARPPROBE_EVENT_ERROR 3
|
|
||||||
|
|
||||||
typedef void (*BArpProbe_handler) (void *user, int event);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t addr;
|
|
||||||
BReactor *reactor;
|
|
||||||
void *user;
|
|
||||||
BArpProbe_handler handler;
|
|
||||||
BDatagram dgram;
|
|
||||||
uint8_t if_mac[6];
|
|
||||||
PacketPassInterface *send_if;
|
|
||||||
int send_sending;
|
|
||||||
struct arp_packet send_packet;
|
|
||||||
PacketRecvInterface *recv_if;
|
|
||||||
struct arp_packet recv_packet;
|
|
||||||
BTimer timer;
|
|
||||||
int state;
|
|
||||||
int num_missed;
|
|
||||||
DebugError d_err;
|
|
||||||
DebugObject d_obj;
|
|
||||||
} BArpProbe;
|
|
||||||
|
|
||||||
int BArpProbe_Init (BArpProbe *o, const char *ifname, uint32_t addr, BReactor *reactor, void *user, BArpProbe_handler handler) WARN_UNUSED;
|
|
||||||
void BArpProbe_Free (BArpProbe *o);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1 +0,0 @@
|
||||||
badvpn_add_library(arpprobe "base;system;flow" "" BArpProbe.c)
|
|
|
@ -1,324 +0,0 @@
|
||||||
.TH badvpn 7 "6 October 2010"
|
|
||||||
.SH NAME
|
|
||||||
BadVPN - peer-to-peer VPN system
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.P
|
|
||||||
BadVPN is a peer-to-peer VPN system. It provides a Layer 2 (Ethernet) network between
|
|
||||||
the peers (VPN network nodes). The peers connect to a central server which acts as a chat
|
|
||||||
server for them to establish direct connections between each other (data connections).
|
|
||||||
These connections are used for transferring network data (Ethernet frames).
|
|
||||||
.SS "Features"
|
|
||||||
.P
|
|
||||||
.B "Data connections"
|
|
||||||
.P
|
|
||||||
Peers can transfer network data either over UDP or TCP. For both there are ways of
|
|
||||||
securing the data (see below).
|
|
||||||
.P
|
|
||||||
.B "IPv6 support"
|
|
||||||
.P
|
|
||||||
IPv6 can be used for both server connections and data connections, alongside with IPv4.
|
|
||||||
Additionally, both can be combined to allow gradual migration to IPv6.
|
|
||||||
.P
|
|
||||||
.B "Address selection"
|
|
||||||
.P
|
|
||||||
Because NATs and firewalls are widespread, it is harder for peer-to-peer services to operate.
|
|
||||||
In general, for two computers to be able to communicate, one computer must
|
|
||||||
.I bind
|
|
||||||
to one of its addresses, and the other computer must
|
|
||||||
.I connect
|
|
||||||
to the computer that binded (both for TCP and UDP). In a network with point-to-point
|
|
||||||
connectivity, the connecting computer can connect to the same address as the binding computer
|
|
||||||
bound to, so it is sufficient for the binding computer to send its address to the connecting
|
|
||||||
computer. However, NATs and firewalls break point-to-point connectivity. When a network is
|
|
||||||
behind a NAT, it is, by default, impossible for computers outside of that network to connect
|
|
||||||
to computers inside the network. This is because computers inside the network have no externally
|
|
||||||
visible IP address, and only communicate with the outside world through the external IP address
|
|
||||||
of the NAT router. It is however possible to manually configure the NAT router to
|
|
||||||
.I forward
|
|
||||||
a specific port number on its external IP address to a specific computer inside the network.
|
|
||||||
This makes it possible for a computer outside of the network to connect to a computer inside
|
|
||||||
a network, however, it must connect to the external address of the NAT router (rather than
|
|
||||||
the address the computer inside bound to, which is its internal address). So there needs
|
|
||||||
to be some way for the connecting peer to know what address to connect to.
|
|
||||||
.P
|
|
||||||
BadVPN solves this problem with so-called
|
|
||||||
.IR "address scopes" "."
|
|
||||||
The peer that binds must have a list of external addresses for each address it can bind to,
|
|
||||||
possibly ordered from best to worst. Each external address has its scope name. A scope name
|
|
||||||
represents part of a network from which an external address can be reached. On the other hand,
|
|
||||||
the peer that connects must have a list of scopes which it can reach. When a peer binds to an
|
|
||||||
address, it sends the other peer a list of external addresses along with scope names. That peer
|
|
||||||
than chooses the first external address whose scope it recognizes and attempts to connect to it
|
|
||||||
(if there is one).
|
|
||||||
.P
|
|
||||||
BadVPN also allows a peer to have multiple addresses for binding to. It is possible to specify
|
|
||||||
both an IPv4 and an IPv6 address to work in a multi-protocol environment.
|
|
||||||
.P
|
|
||||||
.B "Relaying"
|
|
||||||
.P
|
|
||||||
BadVPN can be configured to allow pairs of peers that cannot communicate directly (i.e. because of
|
|
||||||
NATs or firewalls) to relay network data through a third peer. Relaying is only attempted if
|
|
||||||
none of the two peers recognize any of the other peer's external addresses (or there are none).
|
|
||||||
For relaying to work, for each of the two peers (P1, other one P2) there must be at least one
|
|
||||||
third peer (R) that P1 it is allowed to relay through and can communicate directly with, and all
|
|
||||||
such peers R must be able to communicate directly with P2.
|
|
||||||
.P
|
|
||||||
.B "IGMP snooping"
|
|
||||||
.P
|
|
||||||
BadVPN nodes perform IGMP snooping in order to efficiently deliver multicast frames. For example,
|
|
||||||
this makes it possible to use BadVPN as a tunnel into an IPTV network of an Internet Service Provider
|
|
||||||
for you to watch TV from wherever you want (given sufficient link quality).
|
|
||||||
.P
|
|
||||||
.B "Code quality"
|
|
||||||
.P
|
|
||||||
BadVPN has great focus on code quality and reliability. BadVPN is written in the C programming
|
|
||||||
language. It is a single-threaded event-driven program. This allows for low resource usage and
|
|
||||||
fast response times. Even though C is a relatively low-level language, the programs are made of
|
|
||||||
small, highly cohesive and loosely coupled modules that are combined into a complete program on
|
|
||||||
a high level. Modules are accesed and communicate through small, simple and to-the-point interfaces.
|
|
||||||
It utilizes a flow-based design which greatly simplifies processing of data and input and output
|
|
||||||
of the programs.
|
|
||||||
.SS "Security features"
|
|
||||||
.P
|
|
||||||
BadVPN contains many security features, all of which are optional. The included security
|
|
||||||
features are described here.
|
|
||||||
.P
|
|
||||||
.B TLS for client-server connections
|
|
||||||
.P
|
|
||||||
It is possible for the peers to communicate with the chat server securely with TLS. It is
|
|
||||||
highly recommended that this feature is used if any security whatsoever is needed. Not
|
|
||||||
using it renders all other security features useless, since clients exchange keys
|
|
||||||
unencrypted via the server. When enabled, the chat server requires each client to identify
|
|
||||||
itself with a certificate.
|
|
||||||
.P
|
|
||||||
BadVPN uses Mozilla's NSS library for TLS support. This means that the required certificates
|
|
||||||
and keys must be available in a NSS database. The database and certificates can be
|
|
||||||
generated with the
|
|
||||||
.B certutil
|
|
||||||
command. See the examples section on how to generate and distribute the certificates.
|
|
||||||
.P
|
|
||||||
.B TLS for peer messaging
|
|
||||||
.P
|
|
||||||
If TLS is being used for client-server connections, it will also be used between each pair of
|
|
||||||
peers communicating via the server, on top of the TLS connections to the server. This secures
|
|
||||||
the messages from the server itself. It is important because the messages may include
|
|
||||||
encryption keys and other private data.
|
|
||||||
.P
|
|
||||||
.B TLS for TCP data connections
|
|
||||||
.P
|
|
||||||
If TCP is used for data connections between the peers, the data connections can be secured
|
|
||||||
with TLS. This requires using TLS for client-server connections. The clients need to trust
|
|
||||||
each others' certificates to be able to connect. Additionally, each client must identify to
|
|
||||||
its peers with the same certificates it used for connecting to the server.
|
|
||||||
.P
|
|
||||||
.B Encryption for UDP data connections
|
|
||||||
.P
|
|
||||||
If UDP is used for data connections, it is possible for each pair of peers to encrypt their
|
|
||||||
UDP packets with a symmetric block cipher. Note that the encryption keys are transmitted
|
|
||||||
through the server unencrypted, so for this to be useful, server connections must be secured
|
|
||||||
with TLS. The encryption aims to prevent third parties from seeing the real contents of
|
|
||||||
the network data being transfered.
|
|
||||||
.P
|
|
||||||
.B Hashes for UDP data connections
|
|
||||||
.P
|
|
||||||
If UDP is used for data connections, it is possible to include hashes in packets. Note that
|
|
||||||
hashes are only useful together with encryption. If enabled, the hash is calculated on the
|
|
||||||
packet with the hash field zeroed and then written to the hash field. Hashes are calculated
|
|
||||||
and included before encryption (if enabled). Combined with encryption, hashes aim to prevent
|
|
||||||
third parties from tampering with the packets and injecting them into the network.
|
|
||||||
.P
|
|
||||||
.B One-time passwords for UDP data connections
|
|
||||||
.P
|
|
||||||
If UDP is used for data connections, it is possible to include one-time passwords in packets.
|
|
||||||
Note that for this to be useful, server connections must be secured with TLS.
|
|
||||||
One-time passwords are generated from a seed value by encrypting zero data with a block cipher.
|
|
||||||
The seed contains the encryption key for the block cipher and the initialization vector.
|
|
||||||
Only a fixed number of passwords are used from a single seed. The peers exchange seeds through
|
|
||||||
the server. One-time passwords aim to prevent replay attacks.
|
|
||||||
.P
|
|
||||||
.B Control over peer communication
|
|
||||||
.P
|
|
||||||
It is possible to instruct the chat server to only allow certain peers to communicate. This
|
|
||||||
will break end-to-end connectivity in the virtual network. It is useful in certain cases
|
|
||||||
to improve security, for example when the VPN is used only to allow clients to securely connect
|
|
||||||
to a central service.
|
|
||||||
.SH "EXAMPLES"
|
|
||||||
.SS "Setting up certificates"
|
|
||||||
.P
|
|
||||||
If you want to use TLS for server connections (recommended), the server and all the peers will
|
|
||||||
need certificates. This section explains how to generate and distribute the certificates using
|
|
||||||
NSS command line tools.
|
|
||||||
.P
|
|
||||||
.B Setting up the Certificate Authority (CA)
|
|
||||||
.P
|
|
||||||
On the system that will host the CA, create a NSS database for the CA and generate a CA certificate
|
|
||||||
valid for 24 months:
|
|
||||||
.P
|
|
||||||
vpnca $ certutil -d sql:/home/vpnca/nssdb -N
|
|
||||||
.br
|
|
||||||
vpnca $ certutil -d sql:/home/vpnca/nssdb -S -n "vpnca" -s "CN=vpnca" -t "TC,," -x -2 -v 24
|
|
||||||
.br
|
|
||||||
> Is this a CA certificate [y/N]? y
|
|
||||||
.br
|
|
||||||
> Enter the path length constraint, enter to skip [<0 for unlimited path]: > -1
|
|
||||||
.br
|
|
||||||
> Is this a critical extension [y/N]? n
|
|
||||||
.P
|
|
||||||
Export the public CA certificate (this file is public):
|
|
||||||
.P
|
|
||||||
vpnca $ certutil -d sql:/home/vpnca/nssdb -L -n vpnca -a > ca.pem
|
|
||||||
.P
|
|
||||||
.B Setting up the server certificate
|
|
||||||
.P
|
|
||||||
On the CA system, generate a certificate for the server valid for 24 months, with TLS server usage context:
|
|
||||||
.P
|
|
||||||
vpnca $ certutil -d sql:/home/vpnca/nssdb -S -n "<insert_server_name>" -s "CN=<insert_server_name>" -c "vpnca" -t ",," -2 -6 -v 24
|
|
||||||
.br
|
|
||||||
> 0
|
|
||||||
.br
|
|
||||||
> -1
|
|
||||||
.br
|
|
||||||
> Is this a critical extension [y/N]? n
|
|
||||||
.br
|
|
||||||
> Is this a CA certificate [y/N]? n
|
|
||||||
.br
|
|
||||||
> Enter the path length constraint, enter to skip [<0 for unlimited path]: >
|
|
||||||
.br
|
|
||||||
> Is this a critical extension [y/N]? n
|
|
||||||
.P
|
|
||||||
Export the server certificate to a PKCS#12 file (this file must be kept secret):
|
|
||||||
.P
|
|
||||||
vpnca $ pk12util -d sql:/home/vpnca/nssdb -o server.p12 -n "<insert_server_name>"
|
|
||||||
.P
|
|
||||||
On the system that will run the server, create a NSS database and import the CA certificate
|
|
||||||
and the server cerificate:
|
|
||||||
.P
|
|
||||||
vpnserver $ certutil -d sql:/home/vpnserver/nssdb -N
|
|
||||||
.br
|
|
||||||
vpnserver $ certutil -d sql:/home/vpnserver/nssdb -A -t "CT,," -n "vpnca" -i /path/to/ca.pem
|
|
||||||
.br
|
|
||||||
vpnserver $ pk12util -d sql:/home/vpnserver/nssdb -i /path/to/server.p12
|
|
||||||
.P
|
|
||||||
.B Setting up peer certificates
|
|
||||||
.P
|
|
||||||
On the CA system, generate a certificate for the peer valid for 24 months, with TLS client and
|
|
||||||
TLS server usage contexts:
|
|
||||||
.P
|
|
||||||
vpnca $ certutil -d sql:/home/vpnca/nssdb -S -n "peer-<insert_name>" -s "CN=peer-<insert_name>" -c "vpnca" -t ",," -2 -6 -v 24
|
|
||||||
.br
|
|
||||||
> 0
|
|
||||||
.br
|
|
||||||
> 1
|
|
||||||
.br
|
|
||||||
> -1
|
|
||||||
.br
|
|
||||||
> Is this a critical extension [y/N]? n
|
|
||||||
.br
|
|
||||||
> Is this a CA certificate [y/N]? n
|
|
||||||
.br
|
|
||||||
> Enter the path length constraint, enter to skip [<0 for unlimited path]: >
|
|
||||||
.br
|
|
||||||
> Is this a critical extension [y/N]? n
|
|
||||||
.P
|
|
||||||
Export the peer certificate to a PKCS#12 file (this file must be kept secret):
|
|
||||||
.P
|
|
||||||
vpnca $ pk12util -d sql:/home/vpnca/nssdb -o peer-<insert_name>.p12 -n "peer-<insert_name>"
|
|
||||||
.P
|
|
||||||
On the system that will run the VPN client, create a NSS database and import the CA certificate
|
|
||||||
and the peer cerificate:
|
|
||||||
.P
|
|
||||||
vpnclient $ certutil -d sql:/home/vpnclient/nssdb -N
|
|
||||||
.br
|
|
||||||
vpnclient $ certutil -d sql:/home/vpnclient/nssdb -A -t "CT,," -n "vpnca" -i /path/to/ca.pem
|
|
||||||
.br
|
|
||||||
vpnclient $ pk12util -d sql:/home/vpnclient/nssdb -i /path/to/peer-<insert_name>.p12
|
|
||||||
.SS "Setting up TAP devices"
|
|
||||||
.P
|
|
||||||
You need to create and configure TAP devices on all computers that will participate in the virtual network
|
|
||||||
(i.e. run the client program). See
|
|
||||||
.BR badvpn-client (8),
|
|
||||||
section `TAP DEVICE CONFIGURATION` for details.
|
|
||||||
.SS "Example: Local IPv4 network, UDP transport, zero security"
|
|
||||||
.P
|
|
||||||
.B Starting the server:
|
|
||||||
.P
|
|
||||||
badvpn-server --listen-addr 0.0.0.0:7000
|
|
||||||
.P
|
|
||||||
.B Starting the peers:
|
|
||||||
.P
|
|
||||||
badvpn-client
|
|
||||||
.RS
|
|
||||||
--server-addr <insert_server_local_address>:7000
|
|
||||||
.br
|
|
||||||
--transport-mode udp --encryption-mode none --hash-mode none
|
|
||||||
.br
|
|
||||||
--scope local1
|
|
||||||
.br
|
|
||||||
--bind-addr 0.0.0.0:8000 --num-ports 30 --ext-addr {server_reported}:8000 local1
|
|
||||||
.br
|
|
||||||
--tapdev tap0
|
|
||||||
.RE
|
|
||||||
.SS "Example: Adding TLS and UDP security"
|
|
||||||
.P
|
|
||||||
.B Starting the server (other options as above):
|
|
||||||
.P
|
|
||||||
badvpn-server ...
|
|
||||||
.RS
|
|
||||||
--ssl --nssdb sql:/home/vpnserver/nssdb --server-cert-name "<insert_server_name>"
|
|
||||||
.RE
|
|
||||||
.P
|
|
||||||
.B Starting the peers (other options as above):
|
|
||||||
.P
|
|
||||||
badvpn-client ...
|
|
||||||
.RS
|
|
||||||
--ssl --nssdb sql:/home/vpnclient/nssdb --client-cert-name "peer-<insert_name>"
|
|
||||||
.br
|
|
||||||
--encryption-mode blowfish --hash-mode md5 --otp blowfish 3000 2000
|
|
||||||
.RE
|
|
||||||
.SS "Example: Multiple local networks behind NATs, all connected to the Internet"
|
|
||||||
.P
|
|
||||||
For each peer in the existing local network, configure the NAT router to forward its
|
|
||||||
range of ports to it (assuming their port ranges do not overlap). The clients also need
|
|
||||||
to know the external IP address of the NAT router. If you don't have a static one,
|
|
||||||
you'll need to discover it before starting the clients. Also forward the server port to
|
|
||||||
the server.
|
|
||||||
.P
|
|
||||||
.B Starting the peers in the local network (other options as above):
|
|
||||||
.P
|
|
||||||
badvpn-client
|
|
||||||
.RS
|
|
||||||
.RB "..."
|
|
||||||
.br
|
|
||||||
--scope internet
|
|
||||||
.br
|
|
||||||
.RB "..."
|
|
||||||
.br
|
|
||||||
--ext-addr <insert_NAT_routers_external_IP>:<insert_start_of_forwarded_port_range> internet
|
|
||||||
.br
|
|
||||||
.RB "..."
|
|
||||||
.RE
|
|
||||||
.P
|
|
||||||
The --ext-addr option applies to the previously specified --bind-addr option, and must come after
|
|
||||||
the first --ext-addr option which specifies a local address.
|
|
||||||
.P
|
|
||||||
Now perform a similar setup in some other local network behind a NAT. However:
|
|
||||||
.br
|
|
||||||
- Don't set up a new server, instead make the peers connect to the existing server in the first
|
|
||||||
local network.
|
|
||||||
.br
|
|
||||||
- You can't use {server_reported} for the local address --ext-addr options, because the server
|
|
||||||
would report the NAT router's external address rather than the peer's internal address. Instead
|
|
||||||
each peer has to know its internal IP address.
|
|
||||||
.br
|
|
||||||
- Use a different scope name for it, e.g. "local2" instead of "local1".
|
|
||||||
.P
|
|
||||||
If setup correctly, all peers will be able to communicate: those in the same local network will
|
|
||||||
communicate directly through local addresses, and those in different local networks will
|
|
||||||
communicate through the Internet.
|
|
||||||
.SH "PROTOCOL"
|
|
||||||
The protocols used in BadVPN are described in the source code in the protocol/ directory.
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR badvpn-server (8),
|
|
||||||
.BR badvpn-client (8)
|
|
||||||
.SH AUTHORS
|
|
||||||
Ambroz Bizjak <ambrop7@gmail.com>
|
|
|
@ -1,96 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BLog.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "BLog.h"
|
|
||||||
|
|
||||||
#ifndef BADVPN_PLUGIN
|
|
||||||
|
|
||||||
struct _BLog_channel blog_channel_list[] = {
|
|
||||||
#include <generated/blog_channels_list.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _BLog_global blog_global = {
|
|
||||||
#ifndef NDEBUG
|
|
||||||
0
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// keep in sync with level numbers in BLog.h!
|
|
||||||
static char *level_names[] = { NULL, "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG" };
|
|
||||||
|
|
||||||
static void stdout_log (int channel, int level, const char *msg)
|
|
||||||
{
|
|
||||||
fprintf(stdout, "%s(%s): %s\n", level_names[level], blog_global.channels[channel].name, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stderr_log (int channel, int level, const char *msg)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s(%s): %s\n", level_names[level], blog_global.channels[channel].name, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stdout_stderr_free (void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_InitStdout (void)
|
|
||||||
{
|
|
||||||
BLog_Init(stdout_log, stdout_stderr_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_InitStderr (void)
|
|
||||||
{
|
|
||||||
BLog_Init(stderr_log, stdout_stderr_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==== PSIPHON ====
|
|
||||||
#ifdef PSIPHON
|
|
||||||
|
|
||||||
void PsiphonLog(const char *level, const char *channel, const char *msg);
|
|
||||||
|
|
||||||
static void psiphon_log (int channel, int level, const char *msg)
|
|
||||||
{
|
|
||||||
PsiphonLog(level_names[level], blog_global.channels[channel].name, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void psiphon_free (void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_InitPsiphon (void)
|
|
||||||
{
|
|
||||||
BLog_Init(psiphon_log, psiphon_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
// ==== PSIPHON ====
|
|
|
@ -1,402 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BLog.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* A global object for logging.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_BLOG_H
|
|
||||||
#define BADVPN_BLOG_H
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <base/BMutex.h>
|
|
||||||
|
|
||||||
// auto-generated channel numbers and number of channels
|
|
||||||
#include <generated/blog_channels_defines.h>
|
|
||||||
|
|
||||||
// keep in sync with level names in BLog.c!
|
|
||||||
#define BLOG_ERROR 1
|
|
||||||
#define BLOG_WARNING 2
|
|
||||||
#define BLOG_NOTICE 3
|
|
||||||
#define BLOG_INFO 4
|
|
||||||
#define BLOG_DEBUG 5
|
|
||||||
|
|
||||||
#define BLog(...) BLog_LogToChannel(BLOG_CURRENT_CHANNEL, __VA_ARGS__)
|
|
||||||
#define BContextLog(context, ...) BLog_ContextLog((context), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
|
|
||||||
#define BLOG_CCCC(context) BLog_MakeChannelContext((context), BLOG_CURRENT_CHANNEL)
|
|
||||||
|
|
||||||
typedef void (*_BLog_log_func) (int channel, int level, const char *msg);
|
|
||||||
typedef void (*_BLog_free_func) (void);
|
|
||||||
|
|
||||||
struct _BLog_channel {
|
|
||||||
const char *name;
|
|
||||||
int loglevel;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _BLog_global {
|
|
||||||
#ifndef NDEBUG
|
|
||||||
int initialized; // initialized statically
|
|
||||||
#endif
|
|
||||||
struct _BLog_channel channels[BLOG_NUM_CHANNELS];
|
|
||||||
_BLog_log_func log_func;
|
|
||||||
_BLog_free_func free_func;
|
|
||||||
BMutex mutex;
|
|
||||||
#ifndef NDEBUG
|
|
||||||
int logging;
|
|
||||||
#endif
|
|
||||||
char logbuf[2048];
|
|
||||||
int logbuf_pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct _BLog_channel blog_channel_list[];
|
|
||||||
extern struct _BLog_global blog_global;
|
|
||||||
|
|
||||||
typedef void (*BLog_logfunc) (void *);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
BLog_logfunc logfunc;
|
|
||||||
void *logfunc_user;
|
|
||||||
} BLogContext;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
BLogContext context;
|
|
||||||
int channel;
|
|
||||||
} BLogChannelContext;
|
|
||||||
|
|
||||||
static int BLogGlobal_GetChannelByName (const char *channel_name);
|
|
||||||
|
|
||||||
static void BLog_Init (_BLog_log_func log_func, _BLog_free_func free_func);
|
|
||||||
static void BLog_Free (void);
|
|
||||||
static void BLog_SetChannelLoglevel (int channel, int loglevel);
|
|
||||||
static int BLog_WouldLog (int channel, int level);
|
|
||||||
static void BLog_Begin (void);
|
|
||||||
static void BLog_AppendVarArg (const char *fmt, va_list vl);
|
|
||||||
static void BLog_Append (const char *fmt, ...);
|
|
||||||
static void BLog_AppendBytes (const char *data, size_t len);
|
|
||||||
static void BLog_Finish (int channel, int level);
|
|
||||||
static void BLog_LogToChannelVarArg (int channel, int level, const char *fmt, va_list vl);
|
|
||||||
static void BLog_LogToChannel (int channel, int level, const char *fmt, ...);
|
|
||||||
static void BLog_LogViaFuncVarArg (BLog_logfunc func, void *arg, int channel, int level, const char *fmt, va_list vl);
|
|
||||||
static void BLog_LogViaFunc (BLog_logfunc func, void *arg, int channel, int level, const char *fmt, ...);
|
|
||||||
static BLogContext BLog_RootContext (void);
|
|
||||||
static BLogContext BLog_MakeContext (BLog_logfunc logfunc, void *logfunc_user);
|
|
||||||
static void BLog_ContextLogVarArg (BLogContext context, int channel, int level, const char *fmt, va_list vl);
|
|
||||||
static void BLog_ContextLog (BLogContext context, int channel, int level, const char *fmt, ...);
|
|
||||||
static BLogChannelContext BLog_MakeChannelContext (BLogContext context, int channel);
|
|
||||||
static void BLog_ChannelContextLogVarArg (BLogChannelContext ccontext, int level, const char *fmt, va_list vl);
|
|
||||||
static void BLog_ChannelContextLog (BLogChannelContext ccontext, int level, const char *fmt, ...);
|
|
||||||
|
|
||||||
void BLog_InitStdout (void);
|
|
||||||
void BLog_InitStderr (void);
|
|
||||||
|
|
||||||
// PSIPHON
|
|
||||||
void BLog_InitPsiphon (void);
|
|
||||||
|
|
||||||
int BLogGlobal_GetChannelByName (const char *channel_name)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < BLOG_NUM_CHANNELS; i++) {
|
|
||||||
if (!strcmp(blog_channel_list[i].name, channel_name)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_Init (_BLog_log_func log_func, _BLog_free_func free_func)
|
|
||||||
{
|
|
||||||
ASSERT(!blog_global.initialized)
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
blog_global.initialized = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// initialize channels
|
|
||||||
memcpy(blog_global.channels, blog_channel_list, BLOG_NUM_CHANNELS * sizeof(struct _BLog_channel));
|
|
||||||
|
|
||||||
blog_global.log_func = log_func;
|
|
||||||
blog_global.free_func = free_func;
|
|
||||||
#ifndef NDEBUG
|
|
||||||
blog_global.logging = 0;
|
|
||||||
#endif
|
|
||||||
blog_global.logbuf_pos = 0;
|
|
||||||
blog_global.logbuf[0] = '\0';
|
|
||||||
|
|
||||||
ASSERT_FORCE(BMutex_Init(&blog_global.mutex))
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_Free (void)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
#ifndef NDEBUG
|
|
||||||
ASSERT(!blog_global.logging)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BMutex_Free(&blog_global.mutex);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
blog_global.initialized = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
blog_global.free_func();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_SetChannelLoglevel (int channel, int loglevel)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
|
|
||||||
ASSERT(loglevel >= 0 && loglevel <= BLOG_DEBUG)
|
|
||||||
|
|
||||||
blog_global.channels[channel].loglevel = loglevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
int BLog_WouldLog (int channel, int level)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
|
|
||||||
ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
|
|
||||||
|
|
||||||
return (level <= blog_global.channels[channel].loglevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_Begin (void)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
|
|
||||||
BMutex_Lock(&blog_global.mutex);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
ASSERT(!blog_global.logging)
|
|
||||||
blog_global.logging = 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_AppendVarArg (const char *fmt, va_list vl)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
#ifndef NDEBUG
|
|
||||||
ASSERT(blog_global.logging)
|
|
||||||
#endif
|
|
||||||
ASSERT(blog_global.logbuf_pos >= 0)
|
|
||||||
ASSERT(blog_global.logbuf_pos < sizeof(blog_global.logbuf))
|
|
||||||
|
|
||||||
int w = vsnprintf(blog_global.logbuf + blog_global.logbuf_pos, sizeof(blog_global.logbuf) - blog_global.logbuf_pos, fmt, vl);
|
|
||||||
|
|
||||||
if (w >= sizeof(blog_global.logbuf) - blog_global.logbuf_pos) {
|
|
||||||
blog_global.logbuf_pos = sizeof(blog_global.logbuf) - 1;
|
|
||||||
} else {
|
|
||||||
blog_global.logbuf_pos += w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_Append (const char *fmt, ...)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
#ifndef NDEBUG
|
|
||||||
ASSERT(blog_global.logging)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
va_list vl;
|
|
||||||
va_start(vl, fmt);
|
|
||||||
BLog_AppendVarArg(fmt, vl);
|
|
||||||
va_end(vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_AppendBytes (const char *data, size_t len)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
#ifndef NDEBUG
|
|
||||||
ASSERT(blog_global.logging)
|
|
||||||
#endif
|
|
||||||
ASSERT(blog_global.logbuf_pos >= 0)
|
|
||||||
ASSERT(blog_global.logbuf_pos < sizeof(blog_global.logbuf))
|
|
||||||
|
|
||||||
size_t avail = (sizeof(blog_global.logbuf) - 1) - blog_global.logbuf_pos;
|
|
||||||
len = (len > avail ? avail : len);
|
|
||||||
|
|
||||||
memcpy(blog_global.logbuf + blog_global.logbuf_pos, data, len);
|
|
||||||
blog_global.logbuf_pos += len;
|
|
||||||
blog_global.logbuf[blog_global.logbuf_pos] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_Finish (int channel, int level)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
#ifndef NDEBUG
|
|
||||||
ASSERT(blog_global.logging)
|
|
||||||
#endif
|
|
||||||
ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
|
|
||||||
ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
|
|
||||||
ASSERT(BLog_WouldLog(channel, level))
|
|
||||||
|
|
||||||
ASSERT(blog_global.logbuf_pos >= 0)
|
|
||||||
ASSERT(blog_global.logbuf_pos < sizeof(blog_global.logbuf))
|
|
||||||
ASSERT(blog_global.logbuf[blog_global.logbuf_pos] == '\0')
|
|
||||||
|
|
||||||
blog_global.log_func(channel, level, blog_global.logbuf);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
blog_global.logging = 0;
|
|
||||||
#endif
|
|
||||||
blog_global.logbuf_pos = 0;
|
|
||||||
blog_global.logbuf[0] = '\0';
|
|
||||||
|
|
||||||
BMutex_Unlock(&blog_global.mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_LogToChannelVarArg (int channel, int level, const char *fmt, va_list vl)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
|
|
||||||
ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
|
|
||||||
|
|
||||||
if (!BLog_WouldLog(channel, level)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLog_Begin();
|
|
||||||
BLog_AppendVarArg(fmt, vl);
|
|
||||||
BLog_Finish(channel, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_LogToChannel (int channel, int level, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
|
|
||||||
ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
|
|
||||||
|
|
||||||
if (!BLog_WouldLog(channel, level)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_list vl;
|
|
||||||
va_start(vl, fmt);
|
|
||||||
|
|
||||||
BLog_Begin();
|
|
||||||
BLog_AppendVarArg(fmt, vl);
|
|
||||||
BLog_Finish(channel, level);
|
|
||||||
|
|
||||||
va_end(vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_LogViaFuncVarArg (BLog_logfunc func, void *arg, int channel, int level, const char *fmt, va_list vl)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
|
|
||||||
ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
|
|
||||||
|
|
||||||
if (!BLog_WouldLog(channel, level)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLog_Begin();
|
|
||||||
func(arg);
|
|
||||||
BLog_AppendVarArg(fmt, vl);
|
|
||||||
BLog_Finish(channel, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLog_LogViaFunc (BLog_logfunc func, void *arg, int channel, int level, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
ASSERT(blog_global.initialized)
|
|
||||||
ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
|
|
||||||
ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
|
|
||||||
|
|
||||||
if (!BLog_WouldLog(channel, level)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_list vl;
|
|
||||||
va_start(vl, fmt);
|
|
||||||
|
|
||||||
BLog_Begin();
|
|
||||||
func(arg);
|
|
||||||
BLog_AppendVarArg(fmt, vl);
|
|
||||||
BLog_Finish(channel, level);
|
|
||||||
|
|
||||||
va_end(vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BLog__root_logfunc (void *unused)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLogContext BLog_RootContext (void)
|
|
||||||
{
|
|
||||||
return BLog_MakeContext(BLog__root_logfunc, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLogContext BLog_MakeContext (BLog_logfunc logfunc, void *logfunc_user)
|
|
||||||
{
|
|
||||||
ASSERT(logfunc)
|
|
||||||
|
|
||||||
BLogContext context;
|
|
||||||
context.logfunc = logfunc;
|
|
||||||
context.logfunc_user = logfunc_user;
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BLog_ContextLogVarArg (BLogContext context, int channel, int level, const char *fmt, va_list vl)
|
|
||||||
{
|
|
||||||
BLog_LogViaFuncVarArg(context.logfunc, context.logfunc_user, channel, level, fmt, vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BLog_ContextLog (BLogContext context, int channel, int level, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list vl;
|
|
||||||
va_start(vl, fmt);
|
|
||||||
BLog_ContextLogVarArg(context, channel, level, fmt, vl);
|
|
||||||
va_end(vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLogChannelContext BLog_MakeChannelContext (BLogContext context, int channel)
|
|
||||||
{
|
|
||||||
BLogChannelContext ccontext;
|
|
||||||
ccontext.context = context;
|
|
||||||
ccontext.channel = channel;
|
|
||||||
return ccontext;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BLog_ChannelContextLogVarArg (BLogChannelContext ccontext, int level, const char *fmt, va_list vl)
|
|
||||||
{
|
|
||||||
BLog_ContextLogVarArg(ccontext.context, ccontext.channel, level, fmt, vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BLog_ChannelContextLog (BLogChannelContext ccontext, int level, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list vl;
|
|
||||||
va_start(vl, fmt);
|
|
||||||
BLog_ChannelContextLogVarArg(ccontext, level, fmt, vl);
|
|
||||||
va_end(vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,150 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BLog_syslog.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
|
|
||||||
#include "BLog_syslog.h"
|
|
||||||
|
|
||||||
static int resolve_facility (char *str, int *out)
|
|
||||||
{
|
|
||||||
if (!strcmp(str, "authpriv")) {
|
|
||||||
*out = LOG_AUTHPRIV;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "cron")) {
|
|
||||||
*out = LOG_CRON;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "daemon")) {
|
|
||||||
*out = LOG_DAEMON;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "ftp")) {
|
|
||||||
*out = LOG_FTP;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "local0")) {
|
|
||||||
*out = LOG_LOCAL0;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "local1")) {
|
|
||||||
*out = LOG_LOCAL1;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "local2")) {
|
|
||||||
*out = LOG_LOCAL2;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "local3")) {
|
|
||||||
*out = LOG_LOCAL3;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "local4")) {
|
|
||||||
*out = LOG_LOCAL4;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "local5")) {
|
|
||||||
*out = LOG_LOCAL5;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "local6")) {
|
|
||||||
*out = LOG_LOCAL6;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "local7")) {
|
|
||||||
*out = LOG_LOCAL7;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "lpr")) {
|
|
||||||
*out = LOG_LPR;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "mail")) {
|
|
||||||
*out = LOG_MAIL;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "news")) {
|
|
||||||
*out = LOG_NEWS;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "syslog")) {
|
|
||||||
*out = LOG_SYSLOG;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "user")) {
|
|
||||||
*out = LOG_USER;
|
|
||||||
}
|
|
||||||
else if (!strcmp(str, "uucp")) {
|
|
||||||
*out = LOG_UUCP;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int convert_level (int level)
|
|
||||||
{
|
|
||||||
ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
|
|
||||||
|
|
||||||
switch (level) {
|
|
||||||
case BLOG_ERROR:
|
|
||||||
return LOG_ERR;
|
|
||||||
case BLOG_WARNING:
|
|
||||||
return LOG_WARNING;
|
|
||||||
case BLOG_NOTICE:
|
|
||||||
return LOG_NOTICE;
|
|
||||||
case BLOG_INFO:
|
|
||||||
return LOG_INFO;
|
|
||||||
case BLOG_DEBUG:
|
|
||||||
return LOG_DEBUG;
|
|
||||||
default:
|
|
||||||
ASSERT(0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
char ident[200];
|
|
||||||
} syslog_global;
|
|
||||||
|
|
||||||
static void syslog_log (int channel, int level, const char *msg)
|
|
||||||
{
|
|
||||||
syslog(convert_level(level), "%s: %s", blog_global.channels[channel].name, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void syslog_free (void)
|
|
||||||
{
|
|
||||||
closelog();
|
|
||||||
}
|
|
||||||
|
|
||||||
int BLog_InitSyslog (char *ident, char *facility_str)
|
|
||||||
{
|
|
||||||
int facility;
|
|
||||||
if (!resolve_facility(facility_str, &facility)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(syslog_global.ident, sizeof(syslog_global.ident), "%s", ident);
|
|
||||||
|
|
||||||
openlog(syslog_global.ident, 0, facility);
|
|
||||||
|
|
||||||
BLog_Init(syslog_log, syslog_free);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BLog_syslog.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* BLog syslog backend.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_BLOG_SYSLOG_H
|
|
||||||
#define BADVPN_BLOG_SYSLOG_H
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <base/BLog.h>
|
|
||||||
|
|
||||||
int BLog_InitSyslog (char *ident, char *facility) WARN_UNUSED;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,101 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BMutex.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_BMUTEX_H
|
|
||||||
#define BADVPN_BMUTEX_H
|
|
||||||
|
|
||||||
#if !defined(BADVPN_THREAD_SAFE) || (BADVPN_THREAD_SAFE != 0 && BADVPN_THREAD_SAFE != 1)
|
|
||||||
#error BADVPN_THREAD_SAFE is not defined or incorrect
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
#include <pthread.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
pthread_mutex_t pthread_mutex;
|
|
||||||
#endif
|
|
||||||
DebugObject d_obj;
|
|
||||||
} BMutex;
|
|
||||||
|
|
||||||
static int BMutex_Init (BMutex *o) WARN_UNUSED;
|
|
||||||
static void BMutex_Free (BMutex *o);
|
|
||||||
static void BMutex_Lock (BMutex *o);
|
|
||||||
static void BMutex_Unlock (BMutex *o);
|
|
||||||
|
|
||||||
static int BMutex_Init (BMutex *o)
|
|
||||||
{
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
if (pthread_mutex_init(&o->pthread_mutex, NULL) != 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BMutex_Free (BMutex *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
int res = pthread_mutex_destroy(&o->pthread_mutex);
|
|
||||||
B_USE(res)
|
|
||||||
ASSERT(res == 0)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BMutex_Lock (BMutex *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
int res = pthread_mutex_lock(&o->pthread_mutex);
|
|
||||||
B_USE(res)
|
|
||||||
ASSERT(res == 0)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BMutex_Unlock (BMutex *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
int res = pthread_mutex_unlock(&o->pthread_mutex);
|
|
||||||
B_USE(res)
|
|
||||||
ASSERT(res == 0)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,205 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BPending.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <misc/offset.h>
|
|
||||||
|
|
||||||
#include "BPending.h"
|
|
||||||
|
|
||||||
#include "BPending_list.h"
|
|
||||||
#include <structure/SLinkedList_impl.h>
|
|
||||||
|
|
||||||
void BPendingGroup_Init (BPendingGroup *g)
|
|
||||||
{
|
|
||||||
// init jobs list
|
|
||||||
BPending__List_Init(&g->jobs);
|
|
||||||
|
|
||||||
// init pending counter
|
|
||||||
DebugCounter_Init(&g->pending_ctr);
|
|
||||||
|
|
||||||
// init debug object
|
|
||||||
DebugObject_Init(&g->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BPendingGroup_Free (BPendingGroup *g)
|
|
||||||
{
|
|
||||||
DebugCounter_Free(&g->pending_ctr);
|
|
||||||
ASSERT(BPending__List_IsEmpty(&g->jobs))
|
|
||||||
DebugObject_Free(&g->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int BPendingGroup_HasJobs (BPendingGroup *g)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&g->d_obj);
|
|
||||||
|
|
||||||
return !BPending__List_IsEmpty(&g->jobs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BPendingGroup_ExecuteJob (BPendingGroup *g)
|
|
||||||
{
|
|
||||||
ASSERT(!BPending__List_IsEmpty(&g->jobs))
|
|
||||||
DebugObject_Access(&g->d_obj);
|
|
||||||
|
|
||||||
// get a job
|
|
||||||
BSmallPending *p = BPending__List_First(&g->jobs);
|
|
||||||
ASSERT(!BPending__ListIsRemoved(p))
|
|
||||||
ASSERT(p->pending)
|
|
||||||
|
|
||||||
// remove from jobs list
|
|
||||||
BPending__List_RemoveFirst(&g->jobs);
|
|
||||||
|
|
||||||
// set not pending
|
|
||||||
BPending__ListMarkRemoved(p);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
p->pending = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// execute job
|
|
||||||
p->handler(p->user);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BSmallPending * BPendingGroup_PeekJob (BPendingGroup *g)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&g->d_obj);
|
|
||||||
|
|
||||||
return BPending__List_First(&g->jobs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BSmallPending_Init (BSmallPending *o, BPendingGroup *g, BSmallPending_handler handler, void *user)
|
|
||||||
{
|
|
||||||
// init arguments
|
|
||||||
o->handler = handler;
|
|
||||||
o->user = user;
|
|
||||||
|
|
||||||
// set not pending
|
|
||||||
BPending__ListMarkRemoved(o);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
o->pending = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// increment pending counter
|
|
||||||
DebugCounter_Increment(&g->pending_ctr);
|
|
||||||
|
|
||||||
// init debug object
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BSmallPending_Free (BSmallPending *o, BPendingGroup *g)
|
|
||||||
{
|
|
||||||
DebugCounter_Decrement(&g->pending_ctr);
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
ASSERT(o->pending == !BPending__ListIsRemoved(o))
|
|
||||||
|
|
||||||
// remove from jobs list
|
|
||||||
if (!BPending__ListIsRemoved(o)) {
|
|
||||||
BPending__List_Remove(&g->jobs, o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BSmallPending_SetHandler (BSmallPending *o, BSmallPending_handler handler, void *user)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// set handler
|
|
||||||
o->handler = handler;
|
|
||||||
o->user = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BSmallPending_Set (BSmallPending *o, BPendingGroup *g)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(o->pending == !BPending__ListIsRemoved(o))
|
|
||||||
|
|
||||||
// remove from jobs list
|
|
||||||
if (!BPending__ListIsRemoved(o)) {
|
|
||||||
BPending__List_Remove(&g->jobs, o);
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert to jobs list
|
|
||||||
BPending__List_Prepend(&g->jobs, o);
|
|
||||||
|
|
||||||
// set pending
|
|
||||||
#ifndef NDEBUG
|
|
||||||
o->pending = 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void BSmallPending_Unset (BSmallPending *o, BPendingGroup *g)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(o->pending == !BPending__ListIsRemoved(o))
|
|
||||||
|
|
||||||
if (!BPending__ListIsRemoved(o)) {
|
|
||||||
// remove from jobs list
|
|
||||||
BPending__List_Remove(&g->jobs, o);
|
|
||||||
|
|
||||||
// set not pending
|
|
||||||
BPending__ListMarkRemoved(o);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
o->pending = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int BSmallPending_IsSet (BSmallPending *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(o->pending == !BPending__ListIsRemoved(o))
|
|
||||||
|
|
||||||
return !BPending__ListIsRemoved(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BPending_Init (BPending *o, BPendingGroup *g, BPending_handler handler, void *user)
|
|
||||||
{
|
|
||||||
BSmallPending_Init(&o->base, g, handler, user);
|
|
||||||
o->g = g;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BPending_Free (BPending *o)
|
|
||||||
{
|
|
||||||
BSmallPending_Free(&o->base, o->g);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BPending_Set (BPending *o)
|
|
||||||
{
|
|
||||||
BSmallPending_Set(&o->base, o->g);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BPending_Unset (BPending *o)
|
|
||||||
{
|
|
||||||
BSmallPending_Unset(&o->base, o->g);
|
|
||||||
}
|
|
||||||
|
|
||||||
int BPending_IsSet (BPending *o)
|
|
||||||
{
|
|
||||||
return BSmallPending_IsSet(&o->base);
|
|
||||||
}
|
|
|
@ -1,250 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BPending.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* Module for managing a queue of jobs pending execution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_BPENDING_H
|
|
||||||
#define BADVPN_BPENDING_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <misc/debugcounter.h>
|
|
||||||
#include <structure/SLinkedList.h>
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
|
|
||||||
struct BSmallPending_s;
|
|
||||||
|
|
||||||
#include "BPending_list.h"
|
|
||||||
#include <structure/SLinkedList_decl.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Job execution handler.
|
|
||||||
* It is guaranteed that the associated {@link BSmallPending} object was
|
|
||||||
* in set state.
|
|
||||||
* The {@link BSmallPending} object enters not set state before the handler
|
|
||||||
* is called.
|
|
||||||
*
|
|
||||||
* @param user as in {@link BSmallPending_Init}
|
|
||||||
*/
|
|
||||||
typedef void (*BSmallPending_handler) (void *user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Job execution handler.
|
|
||||||
* It is guaranteed that the associated {@link BPending} object was
|
|
||||||
* in set state.
|
|
||||||
* The {@link BPending} object enters not set state before the handler
|
|
||||||
* is called.
|
|
||||||
*
|
|
||||||
* @param user as in {@link BPending_Init}
|
|
||||||
*/
|
|
||||||
typedef void (*BPending_handler) (void *user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object that contains a list of jobs pending execution.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
BPending__List jobs;
|
|
||||||
DebugCounter pending_ctr;
|
|
||||||
DebugObject d_obj;
|
|
||||||
} BPendingGroup;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object for queuing a job for execution.
|
|
||||||
*/
|
|
||||||
typedef struct BSmallPending_s {
|
|
||||||
BPending_handler handler;
|
|
||||||
void *user;
|
|
||||||
BPending__ListNode pending_node; // optimization: if not pending, .next is this
|
|
||||||
#ifndef NDEBUG
|
|
||||||
uint8_t pending;
|
|
||||||
#endif
|
|
||||||
DebugObject d_obj;
|
|
||||||
} BSmallPending;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object for queuing a job for execution. This is a convenience wrapper
|
|
||||||
* around {@link BSmallPending} with an extra field to remember the
|
|
||||||
* {@link BPendingGroup} being used.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
BSmallPending base;
|
|
||||||
BPendingGroup *g;
|
|
||||||
} BPending;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the object.
|
|
||||||
*
|
|
||||||
* @param g the object
|
|
||||||
*/
|
|
||||||
void BPendingGroup_Init (BPendingGroup *g);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the object.
|
|
||||||
* There must be no {@link BPending} or {@link BSmallPending} objects using
|
|
||||||
* this group.
|
|
||||||
*
|
|
||||||
* @param g the object
|
|
||||||
*/
|
|
||||||
void BPendingGroup_Free (BPendingGroup *g);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if there is at least one job in the queue.
|
|
||||||
*
|
|
||||||
* @param g the object
|
|
||||||
* @return 1 if there is at least one job, 0 if not
|
|
||||||
*/
|
|
||||||
int BPendingGroup_HasJobs (BPendingGroup *g);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the top job on the job list.
|
|
||||||
* The job is removed from the list and enters
|
|
||||||
* not set state before being executed.
|
|
||||||
* There must be at least one job in job list.
|
|
||||||
*
|
|
||||||
* @param g the object
|
|
||||||
*/
|
|
||||||
void BPendingGroup_ExecuteJob (BPendingGroup *g);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the top job on the job list, or NULL if there are none.
|
|
||||||
*
|
|
||||||
* @param g the object
|
|
||||||
* @return the top job if there is at least one job, NULL if not
|
|
||||||
*/
|
|
||||||
BSmallPending * BPendingGroup_PeekJob (BPendingGroup *g);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the object.
|
|
||||||
* The object is initialized in not set state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param g pending group to use
|
|
||||||
* @param handler job execution handler
|
|
||||||
* @param user value to pass to handler
|
|
||||||
*/
|
|
||||||
void BSmallPending_Init (BSmallPending *o, BPendingGroup *g, BSmallPending_handler handler, void *user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the object.
|
|
||||||
* The execution handler will not be called after the object
|
|
||||||
* is freed.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param g pending group. Must be the same as was used in {@link BSmallPending_Init}.
|
|
||||||
*/
|
|
||||||
void BSmallPending_Free (BSmallPending *o, BPendingGroup *g);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the job execution handler.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param handler job execution handler
|
|
||||||
* @param user value to pass to handler
|
|
||||||
*/
|
|
||||||
void BSmallPending_SetHandler (BSmallPending *o, BSmallPending_handler handler, void *user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables the job, pushing it to the top of the job list.
|
|
||||||
* If the object was already in set state, the job is removed from its
|
|
||||||
* current position in the list before being pushed.
|
|
||||||
* The object enters set state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param g pending group. Must be the same as was used in {@link BSmallPending_Init}.
|
|
||||||
*/
|
|
||||||
void BSmallPending_Set (BSmallPending *o, BPendingGroup *g);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables the job, removing it from the job list.
|
|
||||||
* If the object was not in set state, nothing is done.
|
|
||||||
* The object enters not set state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param g pending group. Must be the same as was used in {@link BSmallPending_Init}.
|
|
||||||
*/
|
|
||||||
void BSmallPending_Unset (BSmallPending *o, BPendingGroup *g);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the job is in set state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @return 1 if in set state, 0 if not
|
|
||||||
*/
|
|
||||||
int BSmallPending_IsSet (BSmallPending *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the object.
|
|
||||||
* The object is initialized in not set state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param g pending group to use
|
|
||||||
* @param handler job execution handler
|
|
||||||
* @param user value to pass to handler
|
|
||||||
*/
|
|
||||||
void BPending_Init (BPending *o, BPendingGroup *g, BPending_handler handler, void *user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the object.
|
|
||||||
* The execution handler will not be called after the object
|
|
||||||
* is freed.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void BPending_Free (BPending *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables the job, pushing it to the top of the job list.
|
|
||||||
* If the object was already in set state, the job is removed from its
|
|
||||||
* current position in the list before being pushed.
|
|
||||||
* The object enters set state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void BPending_Set (BPending *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables the job, removing it from the job list.
|
|
||||||
* If the object was not in set state, nothing is done.
|
|
||||||
* The object enters not set state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void BPending_Unset (BPending *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the job is in set state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @return 1 if in set state, 0 if not
|
|
||||||
*/
|
|
||||||
int BPending_IsSet (BPending *o);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,4 +0,0 @@
|
||||||
#define SLINKEDLIST_PARAM_NAME BPending__List
|
|
||||||
#define SLINKEDLIST_PARAM_FEATURE_LAST 0
|
|
||||||
#define SLINKEDLIST_PARAM_TYPE_ENTRY struct BSmallPending_s
|
|
||||||
#define SLINKEDLIST_PARAM_MEMBER_NODE pending_node
|
|
|
@ -1,13 +0,0 @@
|
||||||
set(BASE_ADDITIONAL_SOURCES)
|
|
||||||
|
|
||||||
if (HAVE_SYSLOG_H)
|
|
||||||
list(APPEND BASE_ADDITIONAL_SOURCES BLog_syslog.c)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(BASE_SOURCES
|
|
||||||
DebugObject.c
|
|
||||||
BLog.c
|
|
||||||
BPending.c
|
|
||||||
${BASE_ADDITIONAL_SOURCES}
|
|
||||||
)
|
|
||||||
badvpn_add_library(base "" "" "${BASE_SOURCES}")
|
|
|
@ -1,39 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DebugObject.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "DebugObject.h"
|
|
||||||
|
|
||||||
#ifndef BADVPN_PLUGIN
|
|
||||||
#ifndef NDEBUG
|
|
||||||
DebugCounter debugobject_counter = DEBUGCOUNTER_STATIC;
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
pthread_mutex_t debugobject_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,147 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DebugObject.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* Object used for detecting leaks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_DEBUGOBJECT_H
|
|
||||||
#define BADVPN_DEBUGOBJECT_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#if !defined(BADVPN_THREAD_SAFE) || (BADVPN_THREAD_SAFE != 0 && BADVPN_THREAD_SAFE != 1)
|
|
||||||
#error BADVPN_THREAD_SAFE is not defined or incorrect
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
#include <pthread.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <misc/debugcounter.h>
|
|
||||||
|
|
||||||
#define DEBUGOBJECT_VALID UINT32_C(0x31415926)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object used for detecting leaks.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
#ifndef NDEBUG
|
|
||||||
uint32_t c;
|
|
||||||
#endif
|
|
||||||
} DebugObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the object.
|
|
||||||
*
|
|
||||||
* @param obj the object
|
|
||||||
*/
|
|
||||||
static void DebugObject_Init (DebugObject *obj);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the object.
|
|
||||||
*
|
|
||||||
* @param obj the object
|
|
||||||
*/
|
|
||||||
static void DebugObject_Free (DebugObject *obj);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does nothing.
|
|
||||||
*
|
|
||||||
* @param obj the object
|
|
||||||
*/
|
|
||||||
static void DebugObject_Access (const DebugObject *obj);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does nothing.
|
|
||||||
* There must be no {@link DebugObject}'s initialized.
|
|
||||||
*/
|
|
||||||
static void DebugObjectGlobal_Finish (void);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
extern DebugCounter debugobject_counter;
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
extern pthread_mutex_t debugobject_mutex;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void DebugObject_Init (DebugObject *obj)
|
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
obj->c = DEBUGOBJECT_VALID;
|
|
||||||
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
ASSERT_FORCE(pthread_mutex_lock(&debugobject_mutex) == 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DebugCounter_Increment(&debugobject_counter);
|
|
||||||
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
ASSERT_FORCE(pthread_mutex_unlock(&debugobject_mutex) == 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugObject_Free (DebugObject *obj)
|
|
||||||
{
|
|
||||||
ASSERT(obj->c == DEBUGOBJECT_VALID)
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
obj->c = 0;
|
|
||||||
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
ASSERT_FORCE(pthread_mutex_lock(&debugobject_mutex) == 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DebugCounter_Decrement(&debugobject_counter);
|
|
||||||
|
|
||||||
#if BADVPN_THREAD_SAFE
|
|
||||||
ASSERT_FORCE(pthread_mutex_unlock(&debugobject_mutex) == 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugObject_Access (const DebugObject *obj)
|
|
||||||
{
|
|
||||||
ASSERT(obj->c == DEBUGOBJECT_VALID)
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugObjectGlobal_Finish (void)
|
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
DebugCounter_Free(&debugobject_counter);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,145 +0,0 @@
|
||||||
server 4
|
|
||||||
client 4
|
|
||||||
flooder 4
|
|
||||||
tun2socks 4
|
|
||||||
ncd 4
|
|
||||||
ncd_var 4
|
|
||||||
ncd_list 4
|
|
||||||
ncd_depend 4
|
|
||||||
ncd_multidepend 4
|
|
||||||
ncd_dynamic_depend 4
|
|
||||||
ncd_concat 4
|
|
||||||
ncd_if 4
|
|
||||||
ncd_strcmp 4
|
|
||||||
ncd_regex_match 4
|
|
||||||
ncd_logical 4
|
|
||||||
ncd_sleep 4
|
|
||||||
ncd_print 4
|
|
||||||
ncd_blocker 4
|
|
||||||
ncd_run 4
|
|
||||||
ncd_runonce 4
|
|
||||||
ncd_daemon 4
|
|
||||||
ncd_spawn 4
|
|
||||||
ncd_imperative 4
|
|
||||||
ncd_ref 4
|
|
||||||
ncd_index 4
|
|
||||||
ncd_alias 4
|
|
||||||
ncd_process_manager 4
|
|
||||||
ncd_ondemand 4
|
|
||||||
ncd_foreach 4
|
|
||||||
ncd_choose 4
|
|
||||||
ncd_net_backend_waitdevice 4
|
|
||||||
ncd_net_backend_waitlink 4
|
|
||||||
ncd_net_backend_badvpn 4
|
|
||||||
ncd_net_backend_wpa_supplicant 4
|
|
||||||
ncd_net_backend_rfkill 4
|
|
||||||
ncd_net_up 4
|
|
||||||
ncd_net_dns 4
|
|
||||||
ncd_net_iptables 4
|
|
||||||
ncd_net_ipv4_addr 4
|
|
||||||
ncd_net_ipv4_route 4
|
|
||||||
ncd_net_ipv4_dhcp 4
|
|
||||||
ncd_net_ipv4_arp_probe 4
|
|
||||||
ncd_net_watch_interfaces 4
|
|
||||||
ncd_sys_watch_input 4
|
|
||||||
ncd_sys_watch_usb 4
|
|
||||||
ncd_sys_evdev 4
|
|
||||||
ncd_sys_watch_directory 4
|
|
||||||
StreamPeerIO 4
|
|
||||||
DatagramPeerIO 4
|
|
||||||
BReactor 3
|
|
||||||
BSignal 3
|
|
||||||
FragmentProtoAssembler 4
|
|
||||||
BPredicate 3
|
|
||||||
ServerConnection 4
|
|
||||||
Listener 4
|
|
||||||
DataProto 4
|
|
||||||
FrameDecider 4
|
|
||||||
BSocksClient 4
|
|
||||||
BDHCPClientCore 4
|
|
||||||
BDHCPClient 4
|
|
||||||
NCDIfConfig 4
|
|
||||||
BUnixSignal 4
|
|
||||||
BProcess 4
|
|
||||||
PRStreamSink 4
|
|
||||||
PRStreamSource 4
|
|
||||||
PacketProtoDecoder 4
|
|
||||||
DPRelay 4
|
|
||||||
BThreadWork 4
|
|
||||||
DPReceive 4
|
|
||||||
BInputProcess 4
|
|
||||||
NCDUdevMonitorParser 4
|
|
||||||
NCDUdevMonitor 4
|
|
||||||
NCDUdevCache 4
|
|
||||||
NCDUdevManager 4
|
|
||||||
BTime 4
|
|
||||||
BEncryption 4
|
|
||||||
SPProtoDecoder 4
|
|
||||||
LineBuffer 4
|
|
||||||
BTap 4
|
|
||||||
lwip 4
|
|
||||||
NCDConfigTokenizer 4
|
|
||||||
NCDConfigParser 4
|
|
||||||
NCDValParser 4
|
|
||||||
nsskey 4
|
|
||||||
addr 4
|
|
||||||
PasswordListener 4
|
|
||||||
NCDInterfaceMonitor 4
|
|
||||||
NCDRfkillMonitor 4
|
|
||||||
udpgw 4
|
|
||||||
UdpGwClient 4
|
|
||||||
SocksUdpGwClient 4
|
|
||||||
BNetwork 4
|
|
||||||
BConnection 4
|
|
||||||
BSSLConnection 4
|
|
||||||
BDatagram 4
|
|
||||||
PeerChat 4
|
|
||||||
BArpProbe 4
|
|
||||||
NCDModuleIndex 4
|
|
||||||
NCDModuleProcess 4
|
|
||||||
NCDValGenerator 4
|
|
||||||
ncd_from_string 4
|
|
||||||
ncd_to_string 4
|
|
||||||
ncd_value 4
|
|
||||||
ncd_try 4
|
|
||||||
ncd_sys_request_server 4
|
|
||||||
NCDRequest 4
|
|
||||||
ncd_net_ipv6_wait_dynamic_addr 4
|
|
||||||
NCDRequestClient 4
|
|
||||||
ncd_request 4
|
|
||||||
ncd_sys_request_client 4
|
|
||||||
ncd_exit 4
|
|
||||||
ncd_getargs 4
|
|
||||||
ncd_arithmetic 4
|
|
||||||
ncd_parse 4
|
|
||||||
ncd_valuemetic 4
|
|
||||||
ncd_file 4
|
|
||||||
ncd_netmask 4
|
|
||||||
ncd_implode 4
|
|
||||||
ncd_call2 4
|
|
||||||
ncd_assert 4
|
|
||||||
ncd_reboot 4
|
|
||||||
ncd_explode 4
|
|
||||||
NCDPlaceholderDb 4
|
|
||||||
NCDVal 4
|
|
||||||
ncd_net_ipv6_addr 4
|
|
||||||
ncd_net_ipv6_route 4
|
|
||||||
ncd_net_ipv4_addr_in_network 4
|
|
||||||
ncd_net_ipv6_addr_in_network 4
|
|
||||||
dostest_server 4
|
|
||||||
dostest_attacker 4
|
|
||||||
ncd_timer 4
|
|
||||||
ncd_file_open 4
|
|
||||||
ncd_backtrack 4
|
|
||||||
ncd_socket 4
|
|
||||||
ncd_depend_scope 4
|
|
||||||
ncd_substr 4
|
|
||||||
ncd_sys_start_process 4
|
|
||||||
NCDBuildProgram 4
|
|
||||||
ncd_log 4
|
|
||||||
ncd_log_msg 4
|
|
||||||
ncd_buffer 4
|
|
||||||
ncd_getenv 4
|
|
||||||
BThreadSignal 4
|
|
||||||
BLockReactor 4
|
|
||||||
ncd_load_module 4
|
|
|
@ -1,121 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
require_once "blog_functions.php";
|
|
||||||
|
|
||||||
function assert_failure ($script, $line, $message)
|
|
||||||
{
|
|
||||||
if ($message == "") {
|
|
||||||
fatal_error("Assertion failure at {$script}:{$line}");
|
|
||||||
} else {
|
|
||||||
fatal_error("Assertion failure at {$script}:{$line}: {$message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_options(ASSERT_CALLBACK, "assert_failure");
|
|
||||||
|
|
||||||
function print_help ($name)
|
|
||||||
{
|
|
||||||
echo <<<EOD
|
|
||||||
Usage: {$name}
|
|
||||||
--input-file <file> Input channels file.
|
|
||||||
--output-dir <dir> Destination directory for generated files.
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
$input_file = "";
|
|
||||||
$output_dir = "";
|
|
||||||
|
|
||||||
for ($i = 1; $i < $argc;) {
|
|
||||||
$arg = $argv[$i++];
|
|
||||||
switch ($arg) {
|
|
||||||
case "--input-file":
|
|
||||||
$input_file = $argv[$i++];
|
|
||||||
break;
|
|
||||||
case "--output-dir":
|
|
||||||
$output_dir = $argv[$i++];
|
|
||||||
break;
|
|
||||||
case "--help":
|
|
||||||
print_help($argv[0]);
|
|
||||||
exit(0);
|
|
||||||
default:
|
|
||||||
fatal_error("Unknown option: {$arg}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($input_file == "") {
|
|
||||||
fatal_error("--input-file missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($output_dir == "") {
|
|
||||||
fatal_error("--output-dir missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($data = file_get_contents($input_file)) === FALSE) {
|
|
||||||
fatal_error("Failed to read input file");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tokenize($data, $tokens)) {
|
|
||||||
fatal_error("Failed to tokenize");
|
|
||||||
}
|
|
||||||
|
|
||||||
$i = 0;
|
|
||||||
$channels_defines = "";
|
|
||||||
$channels_list = "";
|
|
||||||
|
|
||||||
reset($tokens);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if (($ch_name = current($tokens)) === FALSE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
next($tokens);
|
|
||||||
if (($ch_priority = current($tokens)) === FALSE) {
|
|
||||||
fatal_error("missing priority");
|
|
||||||
}
|
|
||||||
next($tokens);
|
|
||||||
if ($ch_name[0] != "name") {
|
|
||||||
fatal_error("name is not a name");
|
|
||||||
}
|
|
||||||
if ($ch_priority[0] != "number") {
|
|
||||||
fatal_error("priority is not a number");
|
|
||||||
}
|
|
||||||
|
|
||||||
$channel_file = <<<EOD
|
|
||||||
#ifdef BLOG_CURRENT_CHANNEL
|
|
||||||
#undef BLOG_CURRENT_CHANNEL
|
|
||||||
#endif
|
|
||||||
#define BLOG_CURRENT_CHANNEL BLOG_CHANNEL_{$ch_name[1]}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
$channels_defines .= <<<EOD
|
|
||||||
#define BLOG_CHANNEL_{$ch_name[1]} {$i}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
$channels_list .= <<<EOD
|
|
||||||
{"{$ch_name[1]}", {$ch_priority[1]}},
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
if (file_put_contents("{$output_dir}/blog_channel_{$ch_name[1]}.h", $channel_file) === NULL) {
|
|
||||||
fatal_error("{$input_file}: Failed to write channel file");
|
|
||||||
}
|
|
||||||
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
$channels_defines .= <<<EOD
|
|
||||||
#define BLOG_NUM_CHANNELS {$i}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
if (file_put_contents("{$output_dir}/blog_channels_defines.h", $channels_defines) === NULL) {
|
|
||||||
fatal_error("{$input_file}: Failed to write channels defines file");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_put_contents("{$output_dir}/blog_channels_list.h", $channels_list) === NULL) {
|
|
||||||
fatal_error("{$input_file}: Failed to write channels list file");
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
function tokenize ($str, &$out) {
|
|
||||||
$out = array();
|
|
||||||
|
|
||||||
while (strlen($str) > 0) {
|
|
||||||
if (preg_match('/^\\/\\/.*/', $str, $matches)) {
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^\\s+/', $str, $matches)) {
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^[0-9]+/', $str, $matches)) {
|
|
||||||
$out[] = array('number', $matches[0]);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*/', $str, $matches)) {
|
|
||||||
$out[] = array('name', $matches[0]);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fatal_error ($message)
|
|
||||||
{
|
|
||||||
fwrite(STDERR, "Fatal error: $message\n");
|
|
||||||
|
|
||||||
ob_get_clean();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
/**
|
|
||||||
* @file BProto.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* Definitions for BProto serialization.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_BPROTO_BPROTO_H
|
|
||||||
#define BADVPN_BPROTO_BPROTO_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <misc/packed.h>
|
|
||||||
|
|
||||||
#define BPROTO_TYPE_UINT8 1
|
|
||||||
#define BPROTO_TYPE_UINT16 2
|
|
||||||
#define BPROTO_TYPE_UINT32 3
|
|
||||||
#define BPROTO_TYPE_UINT64 4
|
|
||||||
#define BPROTO_TYPE_DATA 5
|
|
||||||
#define BPROTO_TYPE_CONSTDATA 6
|
|
||||||
|
|
||||||
B_START_PACKED
|
|
||||||
struct BProto_header_s {
|
|
||||||
uint16_t id;
|
|
||||||
uint16_t type;
|
|
||||||
} B_PACKED;
|
|
||||||
B_END_PACKED
|
|
||||||
|
|
||||||
B_START_PACKED
|
|
||||||
struct BProto_uint8_s {
|
|
||||||
uint8_t v;
|
|
||||||
} B_PACKED;
|
|
||||||
B_END_PACKED
|
|
||||||
|
|
||||||
B_START_PACKED
|
|
||||||
struct BProto_uint16_s {
|
|
||||||
uint16_t v;
|
|
||||||
} B_PACKED;
|
|
||||||
B_END_PACKED
|
|
||||||
|
|
||||||
B_START_PACKED
|
|
||||||
struct BProto_uint32_s {
|
|
||||||
uint32_t v;
|
|
||||||
} B_PACKED;
|
|
||||||
B_END_PACKED
|
|
||||||
|
|
||||||
B_START_PACKED
|
|
||||||
struct BProto_uint64_s {
|
|
||||||
uint64_t v;
|
|
||||||
} B_PACKED;
|
|
||||||
B_END_PACKED
|
|
||||||
|
|
||||||
B_START_PACKED
|
|
||||||
struct BProto_data_header_s {
|
|
||||||
uint32_t len;
|
|
||||||
} B_PACKED;
|
|
||||||
B_END_PACKED
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,99 +0,0 @@
|
||||||
%class ProtoParser
|
|
||||||
%start file
|
|
||||||
|
|
||||||
file =
|
|
||||||
directives messages {
|
|
||||||
$$ = array(
|
|
||||||
"directives" => $1,
|
|
||||||
"messages" => $2
|
|
||||||
);
|
|
||||||
}.
|
|
||||||
|
|
||||||
directives =
|
|
||||||
{
|
|
||||||
$$ = array();
|
|
||||||
} |
|
|
||||||
directive semicolon directives {
|
|
||||||
$$ = array_merge(array($1), $3);
|
|
||||||
}.
|
|
||||||
|
|
||||||
directive =
|
|
||||||
include string {
|
|
||||||
$$ = array(
|
|
||||||
"type" => "include",
|
|
||||||
"file" => $2
|
|
||||||
);
|
|
||||||
}.
|
|
||||||
|
|
||||||
messages =
|
|
||||||
msgspec {
|
|
||||||
$$ = array($1);
|
|
||||||
} |
|
|
||||||
msgspec messages {
|
|
||||||
$$ = array_merge(array($1), $2);
|
|
||||||
}.
|
|
||||||
|
|
||||||
msgspec =
|
|
||||||
message name spar entries epar semicolon {
|
|
||||||
$$ = array(
|
|
||||||
"name" => $2,
|
|
||||||
"entries" => $4
|
|
||||||
);
|
|
||||||
}.
|
|
||||||
|
|
||||||
entries =
|
|
||||||
entry {
|
|
||||||
$$ = array($1);
|
|
||||||
} |
|
|
||||||
entry entries {
|
|
||||||
$$ = array_merge(array($1), $2);
|
|
||||||
}.
|
|
||||||
|
|
||||||
entry =
|
|
||||||
cardinality type name equals number semicolon {
|
|
||||||
$$ = array(
|
|
||||||
"cardinality" => $1,
|
|
||||||
"type" => $2,
|
|
||||||
"name" => $3,
|
|
||||||
"id" => $5
|
|
||||||
);
|
|
||||||
}.
|
|
||||||
|
|
||||||
cardinality =
|
|
||||||
repeated {
|
|
||||||
$$ = "repeated";
|
|
||||||
} |
|
|
||||||
optional {
|
|
||||||
$$ = "optional";
|
|
||||||
} |
|
|
||||||
required {
|
|
||||||
$$ = "required";
|
|
||||||
} |
|
|
||||||
required repeated {
|
|
||||||
$$ = "required repeated";
|
|
||||||
}.
|
|
||||||
|
|
||||||
type =
|
|
||||||
uint {
|
|
||||||
$$ = array(
|
|
||||||
"type" => "uint",
|
|
||||||
"size" => $1
|
|
||||||
);
|
|
||||||
} |
|
|
||||||
data {
|
|
||||||
$$ = array(
|
|
||||||
"type" => "data"
|
|
||||||
);
|
|
||||||
} |
|
|
||||||
data srpar string erpar {
|
|
||||||
$$ = array(
|
|
||||||
"type" => "constdata",
|
|
||||||
"size" => $3
|
|
||||||
);
|
|
||||||
} |
|
|
||||||
message name {
|
|
||||||
$$ = array(
|
|
||||||
"type" => "message",
|
|
||||||
"message" => $2
|
|
||||||
);
|
|
||||||
}.
|
|
|
@ -1,560 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
DON'T EDIT THIS FILE!
|
|
||||||
|
|
||||||
This file was automatically generated by the Lime parser generator.
|
|
||||||
The real source code you should be looking at is in one or more
|
|
||||||
grammar files in the Lime format.
|
|
||||||
|
|
||||||
THE ONLY REASON TO LOOK AT THIS FILE is to see where in the grammar
|
|
||||||
file that your error happened, because there are enough comments to
|
|
||||||
help you debug your grammar.
|
|
||||||
|
|
||||||
If you ignore this warning, you're shooting yourself in the brain,
|
|
||||||
not the foot.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ProtoParser extends lime_parser {
|
|
||||||
var $qi = 0;
|
|
||||||
var $i = array (
|
|
||||||
0 =>
|
|
||||||
array (
|
|
||||||
'directives' => 's 1',
|
|
||||||
'directive' => 's 30',
|
|
||||||
'include' => 's 33',
|
|
||||||
'file' => 's 35',
|
|
||||||
'\'start\'' => 'a \'start\'',
|
|
||||||
'message' => 'r 1',
|
|
||||||
),
|
|
||||||
1 =>
|
|
||||||
array (
|
|
||||||
'messages' => 's 2',
|
|
||||||
'msgspec' => 's 3',
|
|
||||||
'message' => 's 5',
|
|
||||||
),
|
|
||||||
2 =>
|
|
||||||
array (
|
|
||||||
'#' => 'r 0',
|
|
||||||
),
|
|
||||||
3 =>
|
|
||||||
array (
|
|
||||||
'msgspec' => 's 3',
|
|
||||||
'messages' => 's 4',
|
|
||||||
'message' => 's 5',
|
|
||||||
'#' => 'r 4',
|
|
||||||
),
|
|
||||||
4 =>
|
|
||||||
array (
|
|
||||||
'#' => 'r 5',
|
|
||||||
),
|
|
||||||
5 =>
|
|
||||||
array (
|
|
||||||
'name' => 's 6',
|
|
||||||
),
|
|
||||||
6 =>
|
|
||||||
array (
|
|
||||||
'spar' => 's 7',
|
|
||||||
),
|
|
||||||
7 =>
|
|
||||||
array (
|
|
||||||
'entries' => 's 8',
|
|
||||||
'entry' => 's 11',
|
|
||||||
'cardinality' => 's 13',
|
|
||||||
'repeated' => 's 26',
|
|
||||||
'optional' => 's 27',
|
|
||||||
'required' => 's 28',
|
|
||||||
),
|
|
||||||
8 =>
|
|
||||||
array (
|
|
||||||
'epar' => 's 9',
|
|
||||||
),
|
|
||||||
9 =>
|
|
||||||
array (
|
|
||||||
'semicolon' => 's 10',
|
|
||||||
),
|
|
||||||
10 =>
|
|
||||||
array (
|
|
||||||
'message' => 'r 6',
|
|
||||||
'#' => 'r 6',
|
|
||||||
),
|
|
||||||
11 =>
|
|
||||||
array (
|
|
||||||
'entry' => 's 11',
|
|
||||||
'entries' => 's 12',
|
|
||||||
'cardinality' => 's 13',
|
|
||||||
'repeated' => 's 26',
|
|
||||||
'optional' => 's 27',
|
|
||||||
'required' => 's 28',
|
|
||||||
'epar' => 'r 7',
|
|
||||||
),
|
|
||||||
12 =>
|
|
||||||
array (
|
|
||||||
'epar' => 'r 8',
|
|
||||||
),
|
|
||||||
13 =>
|
|
||||||
array (
|
|
||||||
'type' => 's 14',
|
|
||||||
'uint' => 's 19',
|
|
||||||
'data' => 's 20',
|
|
||||||
'message' => 's 24',
|
|
||||||
),
|
|
||||||
14 =>
|
|
||||||
array (
|
|
||||||
'name' => 's 15',
|
|
||||||
),
|
|
||||||
15 =>
|
|
||||||
array (
|
|
||||||
'equals' => 's 16',
|
|
||||||
),
|
|
||||||
16 =>
|
|
||||||
array (
|
|
||||||
'number' => 's 17',
|
|
||||||
),
|
|
||||||
17 =>
|
|
||||||
array (
|
|
||||||
'semicolon' => 's 18',
|
|
||||||
),
|
|
||||||
18 =>
|
|
||||||
array (
|
|
||||||
'repeated' => 'r 9',
|
|
||||||
'optional' => 'r 9',
|
|
||||||
'required' => 'r 9',
|
|
||||||
'epar' => 'r 9',
|
|
||||||
),
|
|
||||||
19 =>
|
|
||||||
array (
|
|
||||||
'name' => 'r 14',
|
|
||||||
),
|
|
||||||
20 =>
|
|
||||||
array (
|
|
||||||
'srpar' => 's 21',
|
|
||||||
'name' => 'r 15',
|
|
||||||
),
|
|
||||||
21 =>
|
|
||||||
array (
|
|
||||||
'string' => 's 22',
|
|
||||||
),
|
|
||||||
22 =>
|
|
||||||
array (
|
|
||||||
'erpar' => 's 23',
|
|
||||||
),
|
|
||||||
23 =>
|
|
||||||
array (
|
|
||||||
'name' => 'r 16',
|
|
||||||
),
|
|
||||||
24 =>
|
|
||||||
array (
|
|
||||||
'name' => 's 25',
|
|
||||||
),
|
|
||||||
25 =>
|
|
||||||
array (
|
|
||||||
'name' => 'r 17',
|
|
||||||
),
|
|
||||||
26 =>
|
|
||||||
array (
|
|
||||||
'uint' => 'r 10',
|
|
||||||
'data' => 'r 10',
|
|
||||||
'message' => 'r 10',
|
|
||||||
),
|
|
||||||
27 =>
|
|
||||||
array (
|
|
||||||
'uint' => 'r 11',
|
|
||||||
'data' => 'r 11',
|
|
||||||
'message' => 'r 11',
|
|
||||||
),
|
|
||||||
28 =>
|
|
||||||
array (
|
|
||||||
'repeated' => 's 29',
|
|
||||||
'uint' => 'r 12',
|
|
||||||
'data' => 'r 12',
|
|
||||||
'message' => 'r 12',
|
|
||||||
),
|
|
||||||
29 =>
|
|
||||||
array (
|
|
||||||
'uint' => 'r 13',
|
|
||||||
'data' => 'r 13',
|
|
||||||
'message' => 'r 13',
|
|
||||||
),
|
|
||||||
30 =>
|
|
||||||
array (
|
|
||||||
'semicolon' => 's 31',
|
|
||||||
),
|
|
||||||
31 =>
|
|
||||||
array (
|
|
||||||
'directive' => 's 30',
|
|
||||||
'directives' => 's 32',
|
|
||||||
'include' => 's 33',
|
|
||||||
'message' => 'r 1',
|
|
||||||
),
|
|
||||||
32 =>
|
|
||||||
array (
|
|
||||||
'message' => 'r 2',
|
|
||||||
),
|
|
||||||
33 =>
|
|
||||||
array (
|
|
||||||
'string' => 's 34',
|
|
||||||
),
|
|
||||||
34 =>
|
|
||||||
array (
|
|
||||||
'semicolon' => 'r 3',
|
|
||||||
),
|
|
||||||
35 =>
|
|
||||||
array (
|
|
||||||
'#' => 'r 18',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
function reduce_0_file_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (0) file := directives messages
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array(
|
|
||||||
"directives" => $tokens[0],
|
|
||||||
"messages" => $tokens[1]
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_1_directives_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (1) directives :=
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_2_directives_2($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (2) directives := directive semicolon directives
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array_merge(array($tokens[0]), $tokens[2]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_3_directive_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (3) directive := include string
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array(
|
|
||||||
"type" => "include",
|
|
||||||
"file" => $tokens[1]
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_4_messages_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (4) messages := msgspec
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array($tokens[0]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_5_messages_2($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (5) messages := msgspec messages
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array_merge(array($tokens[0]), $tokens[1]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_6_msgspec_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (6) msgspec := message name spar entries epar semicolon
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array(
|
|
||||||
"name" => $tokens[1],
|
|
||||||
"entries" => $tokens[3]
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_7_entries_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (7) entries := entry
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array($tokens[0]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_8_entries_2($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (8) entries := entry entries
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array_merge(array($tokens[0]), $tokens[1]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_9_entry_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (9) entry := cardinality type name equals number semicolon
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array(
|
|
||||||
"cardinality" => $tokens[0],
|
|
||||||
"type" => $tokens[1],
|
|
||||||
"name" => $tokens[2],
|
|
||||||
"id" => $tokens[4]
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_10_cardinality_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (10) cardinality := repeated
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = "repeated";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_11_cardinality_2($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (11) cardinality := optional
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = "optional";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_12_cardinality_3($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (12) cardinality := required
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = "required";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_13_cardinality_4($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (13) cardinality := required repeated
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = "required repeated";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_14_type_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (14) type := uint
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array(
|
|
||||||
"type" => "uint",
|
|
||||||
"size" => $tokens[0]
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_15_type_2($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (15) type := data
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array(
|
|
||||||
"type" => "data"
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_16_type_3($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (16) type := data srpar string erpar
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array(
|
|
||||||
"type" => "constdata",
|
|
||||||
"size" => $tokens[2]
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_17_type_4($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (17) type := message name
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
$result = array(
|
|
||||||
"type" => "message",
|
|
||||||
"message" => $tokens[1]
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function reduce_18_start_1($tokens, &$result) {
|
|
||||||
#
|
|
||||||
# (18) 'start' := file
|
|
||||||
#
|
|
||||||
$result = reset($tokens);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var $method = array (
|
|
||||||
0 => 'reduce_0_file_1',
|
|
||||||
1 => 'reduce_1_directives_1',
|
|
||||||
2 => 'reduce_2_directives_2',
|
|
||||||
3 => 'reduce_3_directive_1',
|
|
||||||
4 => 'reduce_4_messages_1',
|
|
||||||
5 => 'reduce_5_messages_2',
|
|
||||||
6 => 'reduce_6_msgspec_1',
|
|
||||||
7 => 'reduce_7_entries_1',
|
|
||||||
8 => 'reduce_8_entries_2',
|
|
||||||
9 => 'reduce_9_entry_1',
|
|
||||||
10 => 'reduce_10_cardinality_1',
|
|
||||||
11 => 'reduce_11_cardinality_2',
|
|
||||||
12 => 'reduce_12_cardinality_3',
|
|
||||||
13 => 'reduce_13_cardinality_4',
|
|
||||||
14 => 'reduce_14_type_1',
|
|
||||||
15 => 'reduce_15_type_2',
|
|
||||||
16 => 'reduce_16_type_3',
|
|
||||||
17 => 'reduce_17_type_4',
|
|
||||||
18 => 'reduce_18_start_1',
|
|
||||||
);
|
|
||||||
var $a = array (
|
|
||||||
0 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'file',
|
|
||||||
'len' => 2,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
1 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'directives',
|
|
||||||
'len' => 0,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
2 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'directives',
|
|
||||||
'len' => 3,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
3 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'directive',
|
|
||||||
'len' => 2,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
4 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'messages',
|
|
||||||
'len' => 1,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
5 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'messages',
|
|
||||||
'len' => 2,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
6 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'msgspec',
|
|
||||||
'len' => 6,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
7 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'entries',
|
|
||||||
'len' => 1,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
8 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'entries',
|
|
||||||
'len' => 2,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
9 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'entry',
|
|
||||||
'len' => 6,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
10 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'cardinality',
|
|
||||||
'len' => 1,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
11 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'cardinality',
|
|
||||||
'len' => 1,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
12 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'cardinality',
|
|
||||||
'len' => 1,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
13 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'cardinality',
|
|
||||||
'len' => 2,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
14 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'type',
|
|
||||||
'len' => 1,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
15 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'type',
|
|
||||||
'len' => 1,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
16 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'type',
|
|
||||||
'len' => 4,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
17 =>
|
|
||||||
array (
|
|
||||||
'symbol' => 'type',
|
|
||||||
'len' => 2,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
18 =>
|
|
||||||
array (
|
|
||||||
'symbol' => '\'start\'',
|
|
||||||
'len' => 1,
|
|
||||||
'replace' => true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* @file bproto.php
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once "lime/parse_engine.php";
|
|
||||||
require_once "ProtoParser.php";
|
|
||||||
require_once "bproto_functions.php";
|
|
||||||
|
|
||||||
function assert_failure ($script, $line, $message)
|
|
||||||
{
|
|
||||||
if ($message == "") {
|
|
||||||
fatal_error("Assertion failure at {$script}:{$line}");
|
|
||||||
} else {
|
|
||||||
fatal_error("Assertion failure at {$script}:{$line}: {$message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_options(ASSERT_CALLBACK, "assert_failure");
|
|
||||||
|
|
||||||
function print_help ($name)
|
|
||||||
{
|
|
||||||
echo <<<EOD
|
|
||||||
Usage: {$name}
|
|
||||||
--name <string> Output file prefix.
|
|
||||||
--input-file <file> Message file to generate source for.
|
|
||||||
--output-dir <dir> Destination directory for generated files.
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = "";
|
|
||||||
$input_file = "";
|
|
||||||
$output_dir = "";
|
|
||||||
|
|
||||||
for ($i = 1; $i < $argc;) {
|
|
||||||
$arg = $argv[$i++];
|
|
||||||
switch ($arg) {
|
|
||||||
case "--name":
|
|
||||||
$name = $argv[$i++];
|
|
||||||
break;
|
|
||||||
case "--input-file":
|
|
||||||
$input_file = $argv[$i++];
|
|
||||||
break;
|
|
||||||
case "--output-dir":
|
|
||||||
$output_dir = $argv[$i++];
|
|
||||||
break;
|
|
||||||
case "--help":
|
|
||||||
print_help($argv[0]);
|
|
||||||
exit(0);
|
|
||||||
default:
|
|
||||||
fatal_error("Unknown option: {$arg}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($name == "") {
|
|
||||||
fatal_error("--name missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($input_file == "") {
|
|
||||||
fatal_error("--input-file missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($output_dir == "") {
|
|
||||||
fatal_error("--output-dir missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($data = file_get_contents($input_file)) === FALSE) {
|
|
||||||
fatal_error("Failed to read input file");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tokenize($data, $tokens)) {
|
|
||||||
fatal_error("Failed to tokenize");
|
|
||||||
}
|
|
||||||
|
|
||||||
$parser = new parse_engine(new ProtoParser());
|
|
||||||
|
|
||||||
try {
|
|
||||||
foreach ($tokens as $token) {
|
|
||||||
$parser->eat($token[0], $token[1]);
|
|
||||||
}
|
|
||||||
$parser->eat_eof();
|
|
||||||
} catch (parse_error $e) {
|
|
||||||
fatal_error("$input_file: Parse error: ".$e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = generate_header($name, $parser->semantic["directives"], $parser->semantic["messages"]);
|
|
||||||
if (file_put_contents("{$output_dir}/{$name}.h", $data) === NULL) {
|
|
||||||
fatal_error("{$input_file}: Failed to write .h file");
|
|
||||||
}
|
|
|
@ -1,777 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
function tokenize ($str, &$out) {
|
|
||||||
$out = array();
|
|
||||||
|
|
||||||
while (strlen($str) > 0) {
|
|
||||||
if (preg_match('/^\\/\\/.*/', $str, $matches)) {
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^\\s+/', $str, $matches)) {
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^include/', $str, $matches)) {
|
|
||||||
$out[] = array('include', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^message/', $str, $matches)) {
|
|
||||||
$out[] = array('message', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^repeated/', $str, $matches)) {
|
|
||||||
$out[] = array('repeated', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^required/', $str, $matches)) {
|
|
||||||
$out[] = array('required', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^optional/', $str, $matches)) {
|
|
||||||
$out[] = array('optional', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^{/', $str, $matches)) {
|
|
||||||
$out[] = array('spar', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^}/', $str, $matches)) {
|
|
||||||
$out[] = array('epar', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^\(/', $str, $matches)) {
|
|
||||||
$out[] = array('srpar', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^\)/', $str, $matches)) {
|
|
||||||
$out[] = array('erpar', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^=/', $str, $matches)) {
|
|
||||||
$out[] = array('equals', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^;/', $str, $matches)) {
|
|
||||||
$out[] = array('semicolon', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^uint(8|16|32|64)/', $str, $matches)) {
|
|
||||||
$out[] = array('uint', $matches[1]);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^data/', $str, $matches)) {
|
|
||||||
$out[] = array('data', null);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^[0-9]+/', $str, $matches)) {
|
|
||||||
$out[] = array('number', $matches[0]);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*/', $str, $matches)) {
|
|
||||||
$out[] = array('name', $matches[0]);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^"([^"]*)"/', $str, $matches)) {
|
|
||||||
$out[] = array('string', $matches[1]);
|
|
||||||
$str = substr($str, strlen($matches[0]));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fatal_error ($message)
|
|
||||||
{
|
|
||||||
fwrite(STDERR, "Fatal error: $message\n");
|
|
||||||
|
|
||||||
ob_get_clean();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_writer_decl ($msg, $entry)
|
|
||||||
{
|
|
||||||
switch ($entry["type"]["type"]) {
|
|
||||||
case "uint":
|
|
||||||
return "void {$msg["name"]}Writer_Add{$entry["name"]} ({$msg["name"]}Writer *o, uint{$entry["type"]["size"]}_t v)";
|
|
||||||
case "data":
|
|
||||||
return "uint8_t * {$msg["name"]}Writer_Add{$entry["name"]} ({$msg["name"]}Writer *o, int len)";
|
|
||||||
case "constdata":
|
|
||||||
return "uint8_t * {$msg["name"]}Writer_Add{$entry["name"]} ({$msg["name"]}Writer *o)";
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_parser_decl ($msg, $entry)
|
|
||||||
{
|
|
||||||
switch ($entry["type"]["type"]) {
|
|
||||||
case "uint":
|
|
||||||
return "int {$msg["name"]}Parser_Get{$entry["name"]} ({$msg["name"]}Parser *o, uint{$entry["type"]["size"]}_t *v)";
|
|
||||||
case "data":
|
|
||||||
return "int {$msg["name"]}Parser_Get{$entry["name"]} ({$msg["name"]}Parser *o, uint8_t **data, int *data_len)";
|
|
||||||
case "constdata":
|
|
||||||
return "int {$msg["name"]}Parser_Get{$entry["name"]} ({$msg["name"]}Parser *o, uint8_t **data)";
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_parser_reset_decl ($msg, $entry)
|
|
||||||
{
|
|
||||||
return "void {$msg["name"]}Parser_Reset{$entry["name"]} ({$msg["name"]}Parser *o)";
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_parser_forward_decl ($msg, $entry)
|
|
||||||
{
|
|
||||||
return "void {$msg["name"]}Parser_Forward{$entry["name"]} ({$msg["name"]}Parser *o)";
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_type_name ($msg, $entry)
|
|
||||||
{
|
|
||||||
switch ($entry["type"]["type"]) {
|
|
||||||
case "uint":
|
|
||||||
return "BPROTO_TYPE_UINT{$entry["type"]["size"]}";
|
|
||||||
case "data":
|
|
||||||
return "BPROTO_TYPE_DATA";
|
|
||||||
case "constdata":
|
|
||||||
return "BPROTO_TYPE_CONSTDATA";
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_finish_assert ($msg, $entry)
|
|
||||||
{
|
|
||||||
switch ($entry["cardinality"]) {
|
|
||||||
case "repeated":
|
|
||||||
return "ASSERT(o->{$entry["name"]}_count >= 0)";
|
|
||||||
case "required repeated":
|
|
||||||
return "ASSERT(o->{$entry["name"]}_count >= 1)";
|
|
||||||
case "optional":
|
|
||||||
return "ASSERT(o->{$entry["name"]}_count >= 0 && o->{$entry["name"]}_count <= 1)";
|
|
||||||
case "required":
|
|
||||||
return "ASSERT(o->{$entry["name"]}_count == 1)";
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_add_count_assert ($msg, $entry)
|
|
||||||
{
|
|
||||||
if (in_array($entry["cardinality"], array("optional", "required"))) {
|
|
||||||
return "ASSERT(o->{$entry["name"]}_count == 0)";
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_add_length_assert ($msg, $entry)
|
|
||||||
{
|
|
||||||
if ($entry["type"]["type"] == "data") {
|
|
||||||
return "ASSERT(len >= 0 && len <= UINT32_MAX)";
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_size_define ($msg, $entry)
|
|
||||||
{
|
|
||||||
switch ($entry["type"]["type"]) {
|
|
||||||
case "uint":
|
|
||||||
return "#define {$msg["name"]}_SIZE{$entry["name"]} (sizeof(struct BProto_header_s) + sizeof(struct BProto_uint{$entry["type"]["size"]}_s))";
|
|
||||||
case "data":
|
|
||||||
return "#define {$msg["name"]}_SIZE{$entry["name"]}(_len) (sizeof(struct BProto_header_s) + sizeof(struct BProto_data_header_s) + (_len))";
|
|
||||||
case "constdata":
|
|
||||||
return "#define {$msg["name"]}_SIZE{$entry["name"]} (sizeof(struct BProto_header_s) + sizeof(struct BProto_data_header_s) + ({$entry["type"]["size"]}))";
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function generate_header ($name, $directives, $messages) {
|
|
||||||
ob_start();
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
/*
|
|
||||||
DO NOT EDIT THIS FILE!
|
|
||||||
This file was automatically generated by the bproto generator.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <misc/byteorder.h>
|
|
||||||
#include <bproto/BProto.h>
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($directives as $directive) {
|
|
||||||
if ($directive["type"] == "include") {
|
|
||||||
echo <<<EOD
|
|
||||||
#include "{$directive["file"]}"
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($messages as $msg) {
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
$def = make_size_define($msg, $entry);
|
|
||||||
echo <<<EOD
|
|
||||||
{$def}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t *out;
|
|
||||||
int used;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
echo <<<EOD
|
|
||||||
int {$entry["name"]}_count;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
} {$msg["name"]}Writer;
|
|
||||||
|
|
||||||
static void {$msg["name"]}Writer_Init ({$msg["name"]}Writer *o, uint8_t *out);
|
|
||||||
static int {$msg["name"]}Writer_Finish ({$msg["name"]}Writer *o);
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
$decl = make_writer_decl($msg, $entry);
|
|
||||||
echo <<<EOD
|
|
||||||
static {$decl};
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t *buf;
|
|
||||||
int buf_len;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
echo <<<EOD
|
|
||||||
int {$entry["name"]}_start;
|
|
||||||
int {$entry["name"]}_span;
|
|
||||||
int {$entry["name"]}_pos;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
} {$msg["name"]}Parser;
|
|
||||||
|
|
||||||
static int {$msg["name"]}Parser_Init ({$msg["name"]}Parser *o, uint8_t *buf, int buf_len);
|
|
||||||
static int {$msg["name"]}Parser_GotEverything ({$msg["name"]}Parser *o);
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
$decl = make_parser_decl($msg, $entry);
|
|
||||||
$reset_decl = make_parser_reset_decl($msg, $entry);
|
|
||||||
$forward_decl = make_parser_forward_decl($msg, $entry);
|
|
||||||
echo <<<EOD
|
|
||||||
static {$decl};
|
|
||||||
static {$reset_decl};
|
|
||||||
static {$forward_decl};
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
void {$msg["name"]}Writer_Init ({$msg["name"]}Writer *o, uint8_t *out)
|
|
||||||
{
|
|
||||||
o->out = out;
|
|
||||||
o->used = 0;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
echo <<<EOD
|
|
||||||
o->{$entry["name"]}_count = 0;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
}
|
|
||||||
|
|
||||||
int {$msg["name"]}Writer_Finish ({$msg["name"]}Writer *o)
|
|
||||||
{
|
|
||||||
ASSERT(o->used >= 0)
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
$ass = make_finish_assert($msg, $entry);
|
|
||||||
echo <<<EOD
|
|
||||||
{$ass}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
return o->used;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
$decl = make_writer_decl($msg, $entry);
|
|
||||||
$type = make_type_name($msg, $entry);
|
|
||||||
$add_count_assert = make_add_count_assert($msg, $entry);
|
|
||||||
$add_length_assert = make_add_length_assert($msg, $entry);
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
{$decl}
|
|
||||||
{
|
|
||||||
ASSERT(o->used >= 0)
|
|
||||||
{$add_count_assert}
|
|
||||||
{$add_length_assert}
|
|
||||||
|
|
||||||
struct BProto_header_s header;
|
|
||||||
header.id = htol16({$entry["id"]});
|
|
||||||
header.type = htol16({$type});
|
|
||||||
memcpy(o->out + o->used, &header, sizeof(header));
|
|
||||||
o->used += sizeof(struct BProto_header_s);
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
switch ($entry["type"]["type"]) {
|
|
||||||
case "uint":
|
|
||||||
echo <<<EOD
|
|
||||||
struct BProto_uint{$entry["type"]["size"]}_s data;
|
|
||||||
data.v = htol{$entry["type"]["size"]}(v);
|
|
||||||
memcpy(o->out + o->used, &data, sizeof(data));
|
|
||||||
o->used += sizeof(struct BProto_uint{$entry["type"]["size"]}_s);
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
break;
|
|
||||||
case "data":
|
|
||||||
echo <<<EOD
|
|
||||||
struct BProto_data_header_s data;
|
|
||||||
data.len = htol32(len);
|
|
||||||
memcpy(o->out + o->used, &data, sizeof(data));
|
|
||||||
o->used += sizeof(struct BProto_data_header_s);
|
|
||||||
|
|
||||||
uint8_t *dest = (o->out + o->used);
|
|
||||||
o->used += len;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
break;
|
|
||||||
case "constdata":
|
|
||||||
echo <<<EOD
|
|
||||||
struct BProto_data_header_s data;
|
|
||||||
data.len = htol32({$entry["type"]["size"]});
|
|
||||||
memcpy(o->out + o->used, &data, sizeof(data));
|
|
||||||
o->used += sizeof(struct BProto_data_header_s);
|
|
||||||
|
|
||||||
uint8_t *dest = (o->out + o->used);
|
|
||||||
o->used += ({$entry["type"]["size"]});
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
o->{$entry["name"]}_count++;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
if (in_array($entry["type"]["type"], array("data", "constdata"))) {
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
return dest;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
int {$msg["name"]}Parser_Init ({$msg["name"]}Parser *o, uint8_t *buf, int buf_len)
|
|
||||||
{
|
|
||||||
ASSERT(buf_len >= 0)
|
|
||||||
|
|
||||||
o->buf = buf;
|
|
||||||
o->buf_len = buf_len;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
echo <<<EOD
|
|
||||||
o->{$entry["name"]}_start = o->buf_len;
|
|
||||||
o->{$entry["name"]}_span = 0;
|
|
||||||
o->{$entry["name"]}_pos = 0;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
echo <<<EOD
|
|
||||||
int {$entry["name"]}_count = 0;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
int left = o->buf_len;
|
|
||||||
|
|
||||||
while (left > 0) {
|
|
||||||
int entry_pos = pos;
|
|
||||||
|
|
||||||
if (!(left >= sizeof(struct BProto_header_s))) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
struct BProto_header_s header;
|
|
||||||
memcpy(&header, o->buf + pos, sizeof(header));
|
|
||||||
pos += sizeof(struct BProto_header_s);
|
|
||||||
left -= sizeof(struct BProto_header_s);
|
|
||||||
uint16_t type = ltoh16(header.type);
|
|
||||||
uint16_t id = ltoh16(header.id);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach (array(8, 16, 32, 64) as $bits) {
|
|
||||||
echo <<<EOD
|
|
||||||
case BPROTO_TYPE_UINT{$bits}: {
|
|
||||||
if (!(left >= sizeof(struct BProto_uint{$bits}_s))) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pos += sizeof(struct BProto_uint{$bits}_s);
|
|
||||||
left -= sizeof(struct BProto_uint{$bits}_s);
|
|
||||||
|
|
||||||
switch (id) {
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
if (!($entry["type"]["type"] == "uint" && $entry["type"]["size"] == $bits)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$type = make_type_name($msg, $entry);
|
|
||||||
echo <<<EOD
|
|
||||||
case {$entry["id"]}:
|
|
||||||
if (o->{$entry["name"]}_start == o->buf_len) {
|
|
||||||
o->{$entry["name"]}_start = entry_pos;
|
|
||||||
}
|
|
||||||
o->{$entry["name"]}_span = pos - o->{$entry["name"]}_start;
|
|
||||||
{$entry["name"]}_count++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
case BPROTO_TYPE_DATA:
|
|
||||||
case BPROTO_TYPE_CONSTDATA:
|
|
||||||
{
|
|
||||||
if (!(left >= sizeof(struct BProto_data_header_s))) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
struct BProto_data_header_s val;
|
|
||||||
memcpy(&val, o->buf + pos, sizeof(val));
|
|
||||||
pos += sizeof(struct BProto_data_header_s);
|
|
||||||
left -= sizeof(struct BProto_data_header_s);
|
|
||||||
|
|
||||||
uint32_t payload_len = ltoh32(val.len);
|
|
||||||
if (!(left >= payload_len)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pos += payload_len;
|
|
||||||
left -= payload_len;
|
|
||||||
|
|
||||||
switch (id) {
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
if (!in_array($entry["type"]["type"], array("data", "constdata"))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$type = make_type_name($msg, $entry);
|
|
||||||
echo <<<EOD
|
|
||||||
case {$entry["id"]}:
|
|
||||||
if (!(type == {$type})) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
if ($entry["type"]["type"] == "constdata") {
|
|
||||||
echo <<<EOD
|
|
||||||
if (!(payload_len == ({$entry["type"]["size"]}))) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
echo <<<EOD
|
|
||||||
if (o->{$entry["name"]}_start == o->buf_len) {
|
|
||||||
o->{$entry["name"]}_start = entry_pos;
|
|
||||||
}
|
|
||||||
o->{$entry["name"]}_span = pos - o->{$entry["name"]}_start;
|
|
||||||
{$entry["name"]}_count++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
$cond = "";
|
|
||||||
switch ($entry["cardinality"]) {
|
|
||||||
case "repeated":
|
|
||||||
break;
|
|
||||||
case "required repeated":
|
|
||||||
$cond = "{$entry["name"]}_count >= 1";
|
|
||||||
break;
|
|
||||||
case "optional":
|
|
||||||
$cond = "{$entry["name"]}_count <= 1";
|
|
||||||
break;
|
|
||||||
case "required":
|
|
||||||
$cond = "{$entry["name"]}_count == 1";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
if ($cond) {
|
|
||||||
echo <<<EOD
|
|
||||||
if (!({$cond})) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int {$msg["name"]}Parser_GotEverything ({$msg["name"]}Parser *o)
|
|
||||||
{
|
|
||||||
return (
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
$first = 1;
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
if ($first) {
|
|
||||||
$first = 0;
|
|
||||||
} else {
|
|
||||||
echo <<<EOD
|
|
||||||
&&
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
echo <<<EOD
|
|
||||||
o->{$entry["name"]}_pos == o->{$entry["name"]}_span
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach ($msg["entries"] as $entry) {
|
|
||||||
$decl = make_parser_decl($msg, $entry);
|
|
||||||
$reset_decl = make_parser_reset_decl($msg, $entry);
|
|
||||||
$forward_decl = make_parser_forward_decl($msg, $entry);
|
|
||||||
$type = make_type_name($msg, $entry);
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
{$decl}
|
|
||||||
{
|
|
||||||
ASSERT(o->{$entry["name"]}_pos >= 0)
|
|
||||||
ASSERT(o->{$entry["name"]}_pos <= o->{$entry["name"]}_span)
|
|
||||||
|
|
||||||
int left = o->{$entry["name"]}_span - o->{$entry["name"]}_pos;
|
|
||||||
|
|
||||||
while (left > 0) {
|
|
||||||
ASSERT(left >= sizeof(struct BProto_header_s))
|
|
||||||
struct BProto_header_s header;
|
|
||||||
memcpy(&header, o->buf + o->{$entry["name"]}_start + o->{$entry["name"]}_pos, sizeof(header));
|
|
||||||
o->{$entry["name"]}_pos += sizeof(struct BProto_header_s);
|
|
||||||
left -= sizeof(struct BProto_header_s);
|
|
||||||
uint16_t type = ltoh16(header.type);
|
|
||||||
uint16_t id = ltoh16(header.id);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
|
|
||||||
foreach (array(8, 16, 32, 64) as $bits) {
|
|
||||||
echo <<<EOD
|
|
||||||
case BPROTO_TYPE_UINT{$bits}: {
|
|
||||||
ASSERT(left >= sizeof(struct BProto_uint{$bits}_s))
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
if ($entry["type"]["type"] == "uint" && $entry["type"]["size"] == $bits) {
|
|
||||||
echo <<<EOD
|
|
||||||
struct BProto_uint{$bits}_s val;
|
|
||||||
memcpy(&val, o->buf + o->{$entry["name"]}_start + o->{$entry["name"]}_pos, sizeof(val));
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
echo <<<EOD
|
|
||||||
o->{$entry["name"]}_pos += sizeof(struct BProto_uint{$bits}_s);
|
|
||||||
left -= sizeof(struct BProto_uint{$bits}_s);
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
if ($entry["type"]["type"] == "uint" && $entry["type"]["size"] == $bits) {
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
if (id == {$entry["id"]}) {
|
|
||||||
*v = ltoh{$bits}(val.v);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
} break;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
case BPROTO_TYPE_DATA:
|
|
||||||
case BPROTO_TYPE_CONSTDATA:
|
|
||||||
{
|
|
||||||
ASSERT(left >= sizeof(struct BProto_data_header_s))
|
|
||||||
struct BProto_data_header_s val;
|
|
||||||
memcpy(&val, o->buf + o->{$entry["name"]}_start + o->{$entry["name"]}_pos, sizeof(val));
|
|
||||||
o->{$entry["name"]}_pos += sizeof(struct BProto_data_header_s);
|
|
||||||
left -= sizeof(struct BProto_data_header_s);
|
|
||||||
|
|
||||||
uint32_t payload_len = ltoh32(val.len);
|
|
||||||
ASSERT(left >= payload_len)
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
if ($entry["type"]["type"] == "data" || $entry["type"]["type"] == "constdata") {
|
|
||||||
echo <<<EOD
|
|
||||||
uint8_t *payload = o->buf + o->{$entry["name"]}_start + o->{$entry["name"]}_pos;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
echo <<<EOD
|
|
||||||
o->{$entry["name"]}_pos += payload_len;
|
|
||||||
left -= payload_len;
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
if ($entry["type"]["type"] == "data") {
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
if (type == BPROTO_TYPE_DATA && id == {$entry["id"]}) {
|
|
||||||
*data = payload;
|
|
||||||
*data_len = payload_len;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
else if ($entry["type"]["type"] == "constdata") {
|
|
||||||
echo <<<EOD
|
|
||||||
|
|
||||||
if (type == BPROTO_TYPE_CONSTDATA && id == {$entry["id"]}) {
|
|
||||||
*data = payload;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo <<<EOD
|
|
||||||
} break;
|
|
||||||
default:
|
|
||||||
ASSERT(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
{$reset_decl}
|
|
||||||
{
|
|
||||||
o->{$entry["name"]}_pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
{$forward_decl}
|
|
||||||
{
|
|
||||||
o->{$entry["name"]}_pos = o->{$entry["name"]}_span;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EOD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ob_get_clean();
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
add_executable(badvpn-client
|
|
||||||
client.c
|
|
||||||
StreamPeerIO.c
|
|
||||||
DatagramPeerIO.c
|
|
||||||
PasswordListener.c
|
|
||||||
DataProto.c
|
|
||||||
FrameDecider.c
|
|
||||||
DPRelay.c
|
|
||||||
DPReceive.c
|
|
||||||
FragmentProtoDisassembler.c
|
|
||||||
FragmentProtoAssembler.c
|
|
||||||
SPProtoEncoder.c
|
|
||||||
SPProtoDecoder.c
|
|
||||||
DataProtoKeepaliveSource.c
|
|
||||||
PeerChat.c
|
|
||||||
SCOutmsgEncoder.c
|
|
||||||
SimpleStreamBuffer.c
|
|
||||||
SinglePacketSource.c
|
|
||||||
)
|
|
||||||
target_link_libraries(badvpn-client system flow flowextra tuntap server_conection security threadwork ${NSPR_LIBRARIES} ${NSS_LIBRARIES})
|
|
||||||
|
|
||||||
install(
|
|
||||||
TARGETS badvpn-client
|
|
||||||
RUNTIME DESTINATION bin
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
FILES badvpn-client.8
|
|
||||||
DESTINATION share/man/man8
|
|
||||||
)
|
|
|
@ -1,324 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DPReceive.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <protocol/dataproto.h>
|
|
||||||
#include <misc/byteorder.h>
|
|
||||||
#include <misc/offset.h>
|
|
||||||
#include <base/BLog.h>
|
|
||||||
|
|
||||||
#include <client/DPReceive.h>
|
|
||||||
|
|
||||||
#include <generated/blog_channel_DPReceive.h>
|
|
||||||
|
|
||||||
static DPReceivePeer * find_peer (DPReceiveDevice *o, peerid_t id)
|
|
||||||
{
|
|
||||||
for (LinkedList1Node *node = LinkedList1_GetFirst(&o->peers_list); node; node = LinkedList1Node_Next(node)) {
|
|
||||||
DPReceivePeer *p = UPPER_OBJECT(node, DPReceivePeer, list_node);
|
|
||||||
if (p->peer_id == id) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void receiver_recv_handler_send (DPReceiveReceiver *o, uint8_t *packet, int packet_len)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
DPReceivePeer *peer = o->peer;
|
|
||||||
DPReceiveDevice *device = peer->device;
|
|
||||||
ASSERT(packet_len >= 0)
|
|
||||||
ASSERT(packet_len <= device->packet_mtu)
|
|
||||||
|
|
||||||
uint8_t *data = packet;
|
|
||||||
int data_len = packet_len;
|
|
||||||
|
|
||||||
int local = 0;
|
|
||||||
DPReceivePeer *src_peer;
|
|
||||||
DPReceivePeer *relay_dest_peer = NULL;
|
|
||||||
|
|
||||||
// check header
|
|
||||||
if (data_len < sizeof(struct dataproto_header)) {
|
|
||||||
BLog(BLOG_WARNING, "no dataproto header");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
struct dataproto_header header;
|
|
||||||
memcpy(&header, data, sizeof(header));
|
|
||||||
data += sizeof(header);
|
|
||||||
data_len -= sizeof(header);
|
|
||||||
uint8_t flags = ltoh8(header.flags);
|
|
||||||
peerid_t from_id = ltoh16(header.from_id);
|
|
||||||
int num_ids = ltoh16(header.num_peer_ids);
|
|
||||||
|
|
||||||
// check destination ID
|
|
||||||
if (!(num_ids == 0 || num_ids == 1)) {
|
|
||||||
BLog(BLOG_WARNING, "wrong number of destinations");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
peerid_t to_id = 0; // to remove warning
|
|
||||||
if (num_ids == 1) {
|
|
||||||
if (data_len < sizeof(struct dataproto_peer_id)) {
|
|
||||||
BLog(BLOG_WARNING, "missing destination");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
struct dataproto_peer_id id;
|
|
||||||
memcpy(&id, data, sizeof(id));
|
|
||||||
to_id = ltoh16(id.id);
|
|
||||||
data += sizeof(id);
|
|
||||||
data_len -= sizeof(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check remaining data
|
|
||||||
if (data_len > device->device_mtu) {
|
|
||||||
BLog(BLOG_WARNING, "frame too large");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// inform sink of received packet
|
|
||||||
if (peer->dp_sink) {
|
|
||||||
DataProtoSink_Received(peer->dp_sink, !!(flags & DATAPROTO_FLAGS_RECEIVING_KEEPALIVES));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_ids == 1) {
|
|
||||||
// find source peer
|
|
||||||
if (!(src_peer = find_peer(device, from_id))) {
|
|
||||||
BLog(BLOG_INFO, "source peer %d not known", (int)from_id);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is frame for device or another peer?
|
|
||||||
if (device->have_peer_id && to_id == device->peer_id) {
|
|
||||||
// let the frame decider analyze the frame
|
|
||||||
FrameDeciderPeer_Analyze(src_peer->decider_peer, data, data_len);
|
|
||||||
|
|
||||||
// pass frame to device
|
|
||||||
local = 1;
|
|
||||||
} else {
|
|
||||||
// check if relaying is allowed
|
|
||||||
if (!peer->is_relay_client) {
|
|
||||||
BLog(BLOG_WARNING, "relaying not allowed");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// provided source ID must be the peer sending the frame
|
|
||||||
if (src_peer != peer) {
|
|
||||||
BLog(BLOG_WARNING, "relay source must be the sending peer");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find destination peer
|
|
||||||
DPReceivePeer *dest_peer = find_peer(device, to_id);
|
|
||||||
if (!dest_peer) {
|
|
||||||
BLog(BLOG_INFO, "relay destination peer not known");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// destination cannot be source
|
|
||||||
if (dest_peer == src_peer) {
|
|
||||||
BLog(BLOG_WARNING, "relay destination cannot be the source");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
relay_dest_peer = dest_peer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
// accept packet
|
|
||||||
PacketPassInterface_Done(&o->recv_if);
|
|
||||||
|
|
||||||
// pass packet to device
|
|
||||||
if (local) {
|
|
||||||
o->device->output_func(o->device->output_func_user, data, data_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// relay frame
|
|
||||||
if (relay_dest_peer) {
|
|
||||||
DPRelayRouter_SubmitFrame(&device->relay_router, &src_peer->relay_source, &relay_dest_peer->relay_sink, data, data_len, device->relay_flow_buffer_size, device->relay_flow_inactivity_time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int DPReceiveDevice_Init (DPReceiveDevice *o, int device_mtu, DPReceiveDevice_output_func output_func, void *output_func_user, BReactor *reactor, int relay_flow_buffer_size, int relay_flow_inactivity_time)
|
|
||||||
{
|
|
||||||
ASSERT(device_mtu >= 0)
|
|
||||||
ASSERT(device_mtu <= INT_MAX - DATAPROTO_MAX_OVERHEAD)
|
|
||||||
ASSERT(output_func)
|
|
||||||
ASSERT(relay_flow_buffer_size > 0)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->device_mtu = device_mtu;
|
|
||||||
o->output_func = output_func;
|
|
||||||
o->output_func_user = output_func_user;
|
|
||||||
o->reactor = reactor;
|
|
||||||
o->relay_flow_buffer_size = relay_flow_buffer_size;
|
|
||||||
o->relay_flow_inactivity_time = relay_flow_inactivity_time;
|
|
||||||
|
|
||||||
// remember packet MTU
|
|
||||||
o->packet_mtu = DATAPROTO_MAX_OVERHEAD + o->device_mtu;
|
|
||||||
|
|
||||||
// init relay router
|
|
||||||
if (!DPRelayRouter_Init(&o->relay_router, o->device_mtu, o->reactor)) {
|
|
||||||
BLog(BLOG_ERROR, "DPRelayRouter_Init failed");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// have no peer ID
|
|
||||||
o->have_peer_id = 0;
|
|
||||||
|
|
||||||
// init peers list
|
|
||||||
LinkedList1_Init(&o->peers_list);
|
|
||||||
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail0:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPReceiveDevice_Free (DPReceiveDevice *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
ASSERT(LinkedList1_IsEmpty(&o->peers_list))
|
|
||||||
|
|
||||||
// free relay router
|
|
||||||
DPRelayRouter_Free(&o->relay_router);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPReceiveDevice_SetPeerID (DPReceiveDevice *o, peerid_t peer_id)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// remember peer ID
|
|
||||||
o->peer_id = peer_id;
|
|
||||||
o->have_peer_id = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPReceivePeer_Init (DPReceivePeer *o, DPReceiveDevice *device, peerid_t peer_id, FrameDeciderPeer *decider_peer, int is_relay_client)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&device->d_obj);
|
|
||||||
ASSERT(is_relay_client == 0 || is_relay_client == 1)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->device = device;
|
|
||||||
o->peer_id = peer_id;
|
|
||||||
o->decider_peer = decider_peer;
|
|
||||||
o->is_relay_client = is_relay_client;
|
|
||||||
|
|
||||||
// init relay source
|
|
||||||
DPRelaySource_Init(&o->relay_source, &device->relay_router, o->peer_id, device->reactor);
|
|
||||||
|
|
||||||
// init relay sink
|
|
||||||
DPRelaySink_Init(&o->relay_sink, o->peer_id);
|
|
||||||
|
|
||||||
// have no sink
|
|
||||||
o->dp_sink = NULL;
|
|
||||||
|
|
||||||
// insert to peers list
|
|
||||||
LinkedList1_Append(&device->peers_list, &o->list_node);
|
|
||||||
|
|
||||||
DebugCounter_Init(&o->d_receivers_ctr);
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPReceivePeer_Free (DPReceivePeer *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
DebugCounter_Free(&o->d_receivers_ctr);
|
|
||||||
ASSERT(!o->dp_sink)
|
|
||||||
|
|
||||||
// remove from peers list
|
|
||||||
LinkedList1_Remove(&o->device->peers_list, &o->list_node);
|
|
||||||
|
|
||||||
// free relay sink
|
|
||||||
DPRelaySink_Free(&o->relay_sink);
|
|
||||||
|
|
||||||
// free relay source
|
|
||||||
DPRelaySource_Free(&o->relay_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPReceivePeer_AttachSink (DPReceivePeer *o, DataProtoSink *dp_sink)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(!o->dp_sink)
|
|
||||||
ASSERT(dp_sink)
|
|
||||||
|
|
||||||
// attach relay sink
|
|
||||||
DPRelaySink_Attach(&o->relay_sink, dp_sink);
|
|
||||||
|
|
||||||
o->dp_sink = dp_sink;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPReceivePeer_DetachSink (DPReceivePeer *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(o->dp_sink)
|
|
||||||
|
|
||||||
// detach relay sink
|
|
||||||
DPRelaySink_Detach(&o->relay_sink);
|
|
||||||
|
|
||||||
o->dp_sink = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPReceiveReceiver_Init (DPReceiveReceiver *o, DPReceivePeer *peer)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&peer->d_obj);
|
|
||||||
DPReceiveDevice *device = peer->device;
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->peer = peer;
|
|
||||||
|
|
||||||
// remember device
|
|
||||||
o->device = device;
|
|
||||||
|
|
||||||
// init receive interface
|
|
||||||
PacketPassInterface_Init(&o->recv_if, device->packet_mtu, (PacketPassInterface_handler_send)receiver_recv_handler_send, o, BReactor_PendingGroup(device->reactor));
|
|
||||||
|
|
||||||
DebugCounter_Increment(&peer->d_receivers_ctr);
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPReceiveReceiver_Free (DPReceiveReceiver *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
DebugCounter_Decrement(&o->peer->d_receivers_ctr);
|
|
||||||
|
|
||||||
// free receive interface
|
|
||||||
PacketPassInterface_Free(&o->recv_if);
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketPassInterface * DPReceiveReceiver_GetInput (DPReceiveReceiver *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
return &o->recv_if;
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DPReceive.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* Receive processing for the VPN client.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_CLIENT_DPRECEIVE_H
|
|
||||||
#define BADVPN_CLIENT_DPRECEIVE_H
|
|
||||||
|
|
||||||
#include <protocol/scproto.h>
|
|
||||||
#include <misc/debugcounter.h>
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <structure/LinkedList1.h>
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
#include <client/DataProto.h>
|
|
||||||
#include <client/DPRelay.h>
|
|
||||||
#include <client/FrameDecider.h>
|
|
||||||
|
|
||||||
typedef void (*DPReceiveDevice_output_func) (void *output_user, uint8_t *data, int data_len);
|
|
||||||
|
|
||||||
struct DPReceiveReceiver_s;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int device_mtu;
|
|
||||||
DPReceiveDevice_output_func output_func;
|
|
||||||
void *output_func_user;
|
|
||||||
BReactor *reactor;
|
|
||||||
int relay_flow_buffer_size;
|
|
||||||
int relay_flow_inactivity_time;
|
|
||||||
int packet_mtu;
|
|
||||||
DPRelayRouter relay_router;
|
|
||||||
int have_peer_id;
|
|
||||||
peerid_t peer_id;
|
|
||||||
LinkedList1 peers_list;
|
|
||||||
DebugObject d_obj;
|
|
||||||
} DPReceiveDevice;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
DPReceiveDevice *device;
|
|
||||||
peerid_t peer_id;
|
|
||||||
FrameDeciderPeer *decider_peer;
|
|
||||||
int is_relay_client;
|
|
||||||
DPRelaySource relay_source;
|
|
||||||
DPRelaySink relay_sink;
|
|
||||||
DataProtoSink *dp_sink;
|
|
||||||
LinkedList1Node list_node;
|
|
||||||
DebugObject d_obj;
|
|
||||||
DebugCounter d_receivers_ctr;
|
|
||||||
} DPReceivePeer;
|
|
||||||
|
|
||||||
typedef struct DPReceiveReceiver_s {
|
|
||||||
DPReceivePeer *peer;
|
|
||||||
DPReceiveDevice *device;
|
|
||||||
PacketPassInterface recv_if;
|
|
||||||
DebugObject d_obj;
|
|
||||||
} DPReceiveReceiver;
|
|
||||||
|
|
||||||
int DPReceiveDevice_Init (DPReceiveDevice *o, int device_mtu, DPReceiveDevice_output_func output_func, void *output_func_user, BReactor *reactor, int relay_flow_buffer_size, int relay_flow_inactivity_time) WARN_UNUSED;
|
|
||||||
void DPReceiveDevice_Free (DPReceiveDevice *o);
|
|
||||||
void DPReceiveDevice_SetPeerID (DPReceiveDevice *o, peerid_t peer_id);
|
|
||||||
|
|
||||||
void DPReceivePeer_Init (DPReceivePeer *o, DPReceiveDevice *device, peerid_t peer_id, FrameDeciderPeer *decider_peer, int is_relay_client);
|
|
||||||
void DPReceivePeer_Free (DPReceivePeer *o);
|
|
||||||
void DPReceivePeer_AttachSink (DPReceivePeer *o, DataProtoSink *dp_sink);
|
|
||||||
void DPReceivePeer_DetachSink (DPReceivePeer *o);
|
|
||||||
|
|
||||||
void DPReceiveReceiver_Init (DPReceiveReceiver *o, DPReceivePeer *peer);
|
|
||||||
void DPReceiveReceiver_Free (DPReceiveReceiver *o);
|
|
||||||
PacketPassInterface * DPReceiveReceiver_GetInput (DPReceiveReceiver *o);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,307 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DPRelay.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <misc/offset.h>
|
|
||||||
#include <base/BLog.h>
|
|
||||||
|
|
||||||
#include <client/DPRelay.h>
|
|
||||||
|
|
||||||
#include <generated/blog_channel_DPRelay.h>
|
|
||||||
|
|
||||||
static void flow_inactivity_handler (struct DPRelay_flow *flow);
|
|
||||||
|
|
||||||
static struct DPRelay_flow * create_flow (DPRelaySource *src, DPRelaySink *sink, int num_packets, int inactivity_time)
|
|
||||||
{
|
|
||||||
ASSERT(num_packets > 0)
|
|
||||||
|
|
||||||
// allocate structure
|
|
||||||
struct DPRelay_flow *flow = (struct DPRelay_flow *)malloc(sizeof(*flow));
|
|
||||||
if (!flow) {
|
|
||||||
BLog(BLOG_ERROR, "relay flow %d->%d: malloc failed", (int)src->source_id, (int)sink->dest_id);
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set src and sink
|
|
||||||
flow->src = src;
|
|
||||||
flow->sink = sink;
|
|
||||||
|
|
||||||
// init DataProtoFlow
|
|
||||||
if (!DataProtoFlow_Init(&flow->dp_flow, &src->router->dp_source, src->source_id, sink->dest_id, num_packets, inactivity_time, flow, (DataProtoFlow_handler_inactivity)flow_inactivity_handler)) {
|
|
||||||
BLog(BLOG_ERROR, "relay flow %d->%d: DataProtoFlow_Init failed", (int)src->source_id, (int)sink->dest_id);
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert to source list
|
|
||||||
LinkedList1_Append(&src->flows_list, &flow->src_list_node);
|
|
||||||
|
|
||||||
// insert to sink list
|
|
||||||
LinkedList1_Append(&sink->flows_list, &flow->sink_list_node);
|
|
||||||
|
|
||||||
// attach flow if needed
|
|
||||||
if (sink->dp_sink) {
|
|
||||||
DataProtoFlow_Attach(&flow->dp_flow, sink->dp_sink);
|
|
||||||
}
|
|
||||||
|
|
||||||
BLog(BLOG_INFO, "relay flow %d->%d: created", (int)src->source_id, (int)sink->dest_id);
|
|
||||||
|
|
||||||
return flow;
|
|
||||||
|
|
||||||
fail1:
|
|
||||||
free(flow);
|
|
||||||
fail0:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_flow (struct DPRelay_flow *flow)
|
|
||||||
{
|
|
||||||
// detach flow if needed
|
|
||||||
if (flow->sink->dp_sink) {
|
|
||||||
DataProtoFlow_Detach(&flow->dp_flow);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove posible router reference
|
|
||||||
if (flow->src->router->current_flow == flow) {
|
|
||||||
flow->src->router->current_flow = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove from sink list
|
|
||||||
LinkedList1_Remove(&flow->sink->flows_list, &flow->sink_list_node);
|
|
||||||
|
|
||||||
// remove from source list
|
|
||||||
LinkedList1_Remove(&flow->src->flows_list, &flow->src_list_node);
|
|
||||||
|
|
||||||
// free DataProtoFlow
|
|
||||||
DataProtoFlow_Free(&flow->dp_flow);
|
|
||||||
|
|
||||||
// free structore
|
|
||||||
free(flow);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flow_inactivity_handler (struct DPRelay_flow *flow)
|
|
||||||
{
|
|
||||||
BLog(BLOG_INFO, "relay flow %d->%d: timed out", (int)flow->src->source_id, (int)flow->sink->dest_id);
|
|
||||||
|
|
||||||
free_flow(flow);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct DPRelay_flow * source_find_flow (DPRelaySource *o, DPRelaySink *sink)
|
|
||||||
{
|
|
||||||
for (LinkedList1Node *node = LinkedList1_GetFirst(&o->flows_list); node; node = LinkedList1Node_Next(node)) {
|
|
||||||
struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, src_list_node);
|
|
||||||
ASSERT(flow->src == o)
|
|
||||||
if (flow->sink == sink) {
|
|
||||||
return flow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void router_dp_source_handler (DPRelayRouter *o, const uint8_t *frame, int frame_len)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
if (!o->current_flow) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// route frame to current flow
|
|
||||||
DataProtoFlow_Route(&o->current_flow->dp_flow, 0);
|
|
||||||
|
|
||||||
// set no current flow
|
|
||||||
o->current_flow = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DPRelayRouter_Init (DPRelayRouter *o, int frame_mtu, BReactor *reactor)
|
|
||||||
{
|
|
||||||
ASSERT(frame_mtu >= 0)
|
|
||||||
ASSERT(frame_mtu <= INT_MAX - DATAPROTO_MAX_OVERHEAD)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->frame_mtu = frame_mtu;
|
|
||||||
|
|
||||||
// init BufferWriter
|
|
||||||
BufferWriter_Init(&o->writer, frame_mtu, BReactor_PendingGroup(reactor));
|
|
||||||
|
|
||||||
// init DataProtoSource
|
|
||||||
if (!DataProtoSource_Init(&o->dp_source, BufferWriter_GetOutput(&o->writer), (DataProtoSource_handler)router_dp_source_handler, o, reactor)) {
|
|
||||||
BLog(BLOG_ERROR, "DataProtoSource_Init failed");
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// have no current flow
|
|
||||||
o->current_flow = NULL;
|
|
||||||
|
|
||||||
DebugCounter_Init(&o->d_ctr);
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail1:
|
|
||||||
BufferWriter_Free(&o->writer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPRelayRouter_Free (DPRelayRouter *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
DebugCounter_Free(&o->d_ctr);
|
|
||||||
ASSERT(!o->current_flow) // have no sources
|
|
||||||
|
|
||||||
// free DataProtoSource
|
|
||||||
DataProtoSource_Free(&o->dp_source);
|
|
||||||
|
|
||||||
// free BufferWriter
|
|
||||||
BufferWriter_Free(&o->writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPRelayRouter_SubmitFrame (DPRelayRouter *o, DPRelaySource *src, DPRelaySink *sink, uint8_t *data, int data_len, int num_packets, int inactivity_time)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
DebugObject_Access(&src->d_obj);
|
|
||||||
DebugObject_Access(&sink->d_obj);
|
|
||||||
ASSERT(!o->current_flow)
|
|
||||||
ASSERT(src->router == o)
|
|
||||||
ASSERT(data_len >= 0)
|
|
||||||
ASSERT(data_len <= o->frame_mtu)
|
|
||||||
ASSERT(num_packets > 0)
|
|
||||||
|
|
||||||
// get memory location
|
|
||||||
uint8_t *out;
|
|
||||||
if (!BufferWriter_StartPacket(&o->writer, &out)) {
|
|
||||||
BLog(BLOG_ERROR, "BufferWriter_StartPacket failed for frame %d->%d !?", (int)src->source_id, (int)sink->dest_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write frame
|
|
||||||
memcpy(out, data, data_len);
|
|
||||||
|
|
||||||
// submit frame
|
|
||||||
BufferWriter_EndPacket(&o->writer, data_len);
|
|
||||||
|
|
||||||
// get a flow
|
|
||||||
// this comes _after_ writing the packet, in case flow initialization schedules jobs
|
|
||||||
struct DPRelay_flow *flow = source_find_flow(src, sink);
|
|
||||||
if (!flow) {
|
|
||||||
if (!(flow = create_flow(src, sink, num_packets, inactivity_time))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember flow so we know where to route the frame in router_dp_source_handler
|
|
||||||
o->current_flow = flow;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPRelaySource_Init (DPRelaySource *o, DPRelayRouter *router, peerid_t source_id, BReactor *reactor)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&router->d_obj);
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->router = router;
|
|
||||||
o->source_id = source_id;
|
|
||||||
|
|
||||||
// init flows list
|
|
||||||
LinkedList1_Init(&o->flows_list);
|
|
||||||
|
|
||||||
DebugCounter_Increment(&o->router->d_ctr);
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPRelaySource_Free (DPRelaySource *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
DebugCounter_Decrement(&o->router->d_ctr);
|
|
||||||
|
|
||||||
// free flows, detaching them if needed
|
|
||||||
LinkedList1Node *node;
|
|
||||||
while (node = LinkedList1_GetFirst(&o->flows_list)) {
|
|
||||||
struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, src_list_node);
|
|
||||||
free_flow(flow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPRelaySink_Init (DPRelaySink *o, peerid_t dest_id)
|
|
||||||
{
|
|
||||||
// init arguments
|
|
||||||
o->dest_id = dest_id;
|
|
||||||
|
|
||||||
// init flows list
|
|
||||||
LinkedList1_Init(&o->flows_list);
|
|
||||||
|
|
||||||
// have no sink
|
|
||||||
o->dp_sink = NULL;
|
|
||||||
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPRelaySink_Free (DPRelaySink *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
ASSERT(!o->dp_sink)
|
|
||||||
|
|
||||||
// free flows
|
|
||||||
LinkedList1Node *node;
|
|
||||||
while (node = LinkedList1_GetFirst(&o->flows_list)) {
|
|
||||||
struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, sink_list_node);
|
|
||||||
free_flow(flow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPRelaySink_Attach (DPRelaySink *o, DataProtoSink *dp_sink)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(!o->dp_sink)
|
|
||||||
ASSERT(dp_sink)
|
|
||||||
|
|
||||||
// attach flows
|
|
||||||
for (LinkedList1Node *node = LinkedList1_GetFirst(&o->flows_list); node; node = LinkedList1Node_Next(node)) {
|
|
||||||
struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, sink_list_node);
|
|
||||||
DataProtoFlow_Attach(&flow->dp_flow, dp_sink);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set sink
|
|
||||||
o->dp_sink = dp_sink;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DPRelaySink_Detach (DPRelaySink *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(o->dp_sink)
|
|
||||||
|
|
||||||
// detach flows
|
|
||||||
for (LinkedList1Node *node = LinkedList1_GetFirst(&o->flows_list); node; node = LinkedList1Node_Next(node)) {
|
|
||||||
struct DPRelay_flow *flow = UPPER_OBJECT(node, struct DPRelay_flow, sink_list_node);
|
|
||||||
DataProtoFlow_Detach(&flow->dp_flow);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set no sink
|
|
||||||
o->dp_sink = NULL;
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DPRelay.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_CLIENT_DPRELAY_H
|
|
||||||
#define BADVPN_CLIENT_DPRELAY_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include <protocol/scproto.h>
|
|
||||||
#include <protocol/dataproto.h>
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <structure/LinkedList1.h>
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
#include <flow/BufferWriter.h>
|
|
||||||
#include <client/DataProto.h>
|
|
||||||
|
|
||||||
struct DPRelay_flow;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int frame_mtu;
|
|
||||||
BufferWriter writer;
|
|
||||||
DataProtoSource dp_source;
|
|
||||||
struct DPRelay_flow *current_flow;
|
|
||||||
DebugObject d_obj;
|
|
||||||
DebugCounter d_ctr;
|
|
||||||
} DPRelayRouter;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
DPRelayRouter *router;
|
|
||||||
peerid_t source_id;
|
|
||||||
LinkedList1 flows_list;
|
|
||||||
DebugObject d_obj;
|
|
||||||
} DPRelaySource;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
peerid_t dest_id;
|
|
||||||
LinkedList1 flows_list;
|
|
||||||
DataProtoSink *dp_sink;
|
|
||||||
DebugObject d_obj;
|
|
||||||
} DPRelaySink;
|
|
||||||
|
|
||||||
struct DPRelay_flow {
|
|
||||||
DPRelaySource *src;
|
|
||||||
DPRelaySink *sink;
|
|
||||||
DataProtoFlow dp_flow;
|
|
||||||
LinkedList1Node src_list_node;
|
|
||||||
LinkedList1Node sink_list_node;
|
|
||||||
};
|
|
||||||
|
|
||||||
int DPRelayRouter_Init (DPRelayRouter *o, int frame_mtu, BReactor *reactor) WARN_UNUSED;
|
|
||||||
void DPRelayRouter_Free (DPRelayRouter *o);
|
|
||||||
void DPRelayRouter_SubmitFrame (DPRelayRouter *o, DPRelaySource *src, DPRelaySink *sink, uint8_t *data, int data_len, int num_packets, int inactivity_time);
|
|
||||||
|
|
||||||
void DPRelaySource_Init (DPRelaySource *o, DPRelayRouter *router, peerid_t source_id, BReactor *reactor);
|
|
||||||
void DPRelaySource_Free (DPRelaySource *o);
|
|
||||||
|
|
||||||
void DPRelaySink_Init (DPRelaySink *o, peerid_t dest_id);
|
|
||||||
void DPRelaySink_Free (DPRelaySink *o);
|
|
||||||
void DPRelaySink_Attach (DPRelaySink *o, DataProtoSink *dp_sink);
|
|
||||||
void DPRelaySink_Detach (DPRelaySink *o);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,566 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DataProto.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include <protocol/dataproto.h>
|
|
||||||
#include <misc/byteorder.h>
|
|
||||||
#include <base/BLog.h>
|
|
||||||
|
|
||||||
#include <client/DataProto.h>
|
|
||||||
|
|
||||||
#include <generated/blog_channel_DataProto.h>
|
|
||||||
|
|
||||||
static void monitor_handler (DataProtoSink *o);
|
|
||||||
static void refresh_up_job (DataProtoSink *o);
|
|
||||||
static void receive_timer_handler (DataProtoSink *o);
|
|
||||||
static void notifier_handler (DataProtoSink *o, uint8_t *data, int data_len);
|
|
||||||
static void up_job_handler (DataProtoSink *o);
|
|
||||||
static void flow_buffer_free (struct DataProtoFlow_buffer *b);
|
|
||||||
static void flow_buffer_attach (struct DataProtoFlow_buffer *b, DataProtoSink *sink);
|
|
||||||
static void flow_buffer_detach (struct DataProtoFlow_buffer *b);
|
|
||||||
static void flow_buffer_schedule_detach (struct DataProtoFlow_buffer *b);
|
|
||||||
static void flow_buffer_finish_detach (struct DataProtoFlow_buffer *b);
|
|
||||||
static void flow_buffer_qflow_handler_busy (struct DataProtoFlow_buffer *b);
|
|
||||||
|
|
||||||
void monitor_handler (DataProtoSink *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// send keep-alive
|
|
||||||
PacketRecvBlocker_AllowBlockedPacket(&o->ka_blocker);
|
|
||||||
}
|
|
||||||
|
|
||||||
void refresh_up_job (DataProtoSink *o)
|
|
||||||
{
|
|
||||||
if (o->up != o->up_report) {
|
|
||||||
BPending_Set(&o->up_job);
|
|
||||||
} else {
|
|
||||||
BPending_Unset(&o->up_job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void receive_timer_handler (DataProtoSink *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// consider down
|
|
||||||
o->up = 0;
|
|
||||||
|
|
||||||
refresh_up_job(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
void notifier_handler (DataProtoSink *o, uint8_t *data, int data_len)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(data_len >= sizeof(struct dataproto_header))
|
|
||||||
|
|
||||||
int flags = 0;
|
|
||||||
|
|
||||||
// if we are receiving keepalives, set the flag
|
|
||||||
if (BTimer_IsRunning(&o->receive_timer)) {
|
|
||||||
flags |= DATAPROTO_FLAGS_RECEIVING_KEEPALIVES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// modify existing packet here
|
|
||||||
struct dataproto_header header;
|
|
||||||
memcpy(&header, data, sizeof(header));
|
|
||||||
header.flags = hton8(flags);
|
|
||||||
memcpy(data, &header, sizeof(header));
|
|
||||||
}
|
|
||||||
|
|
||||||
void up_job_handler (DataProtoSink *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(o->up != o->up_report)
|
|
||||||
|
|
||||||
o->up_report = o->up;
|
|
||||||
|
|
||||||
o->handler(o->user, o->up);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void source_router_handler (DataProtoSource *o, uint8_t *buf, int recv_len)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(buf)
|
|
||||||
ASSERT(recv_len >= 0)
|
|
||||||
ASSERT(recv_len <= o->frame_mtu)
|
|
||||||
|
|
||||||
// remember packet
|
|
||||||
o->current_buf = buf;
|
|
||||||
o->current_recv_len = recv_len;
|
|
||||||
|
|
||||||
// call handler
|
|
||||||
o->handler(o->user, buf + DATAPROTO_MAX_OVERHEAD, recv_len);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flow_buffer_free (struct DataProtoFlow_buffer *b)
|
|
||||||
{
|
|
||||||
ASSERT(!b->sink)
|
|
||||||
|
|
||||||
// free route buffer
|
|
||||||
RouteBuffer_Free(&b->rbuf);
|
|
||||||
|
|
||||||
// free inactivity monitor
|
|
||||||
if (b->inactivity_time >= 0) {
|
|
||||||
PacketPassInactivityMonitor_Free(&b->monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// free connector
|
|
||||||
PacketPassConnector_Free(&b->connector);
|
|
||||||
|
|
||||||
// free buffer structure
|
|
||||||
free(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flow_buffer_attach (struct DataProtoFlow_buffer *b, DataProtoSink *sink)
|
|
||||||
{
|
|
||||||
ASSERT(!b->sink)
|
|
||||||
|
|
||||||
// init queue flow
|
|
||||||
PacketPassFairQueueFlow_Init(&b->sink_qflow, &sink->queue);
|
|
||||||
|
|
||||||
// connect to queue flow
|
|
||||||
PacketPassConnector_ConnectOutput(&b->connector, PacketPassFairQueueFlow_GetInput(&b->sink_qflow));
|
|
||||||
|
|
||||||
// set DataProto
|
|
||||||
b->sink = sink;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flow_buffer_detach (struct DataProtoFlow_buffer *b)
|
|
||||||
{
|
|
||||||
ASSERT(b->sink)
|
|
||||||
PacketPassFairQueueFlow_AssertFree(&b->sink_qflow);
|
|
||||||
|
|
||||||
// disconnect from queue flow
|
|
||||||
PacketPassConnector_DisconnectOutput(&b->connector);
|
|
||||||
|
|
||||||
// free queue flow
|
|
||||||
PacketPassFairQueueFlow_Free(&b->sink_qflow);
|
|
||||||
|
|
||||||
// clear reference to this buffer in the sink
|
|
||||||
if (b->sink->detaching_buffer == b) {
|
|
||||||
b->sink->detaching_buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set no DataProto
|
|
||||||
b->sink = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flow_buffer_schedule_detach (struct DataProtoFlow_buffer *b)
|
|
||||||
{
|
|
||||||
ASSERT(b->sink)
|
|
||||||
ASSERT(PacketPassFairQueueFlow_IsBusy(&b->sink_qflow))
|
|
||||||
ASSERT(!b->sink->detaching_buffer || b->sink->detaching_buffer == b)
|
|
||||||
|
|
||||||
if (b->sink->detaching_buffer == b) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// request cancel
|
|
||||||
PacketPassFairQueueFlow_RequestCancel(&b->sink_qflow);
|
|
||||||
|
|
||||||
// set busy handler
|
|
||||||
PacketPassFairQueueFlow_SetBusyHandler(&b->sink_qflow, (PacketPassFairQueue_handler_busy)flow_buffer_qflow_handler_busy, b);
|
|
||||||
|
|
||||||
// remember this buffer in the sink so it can handle us if it goes away
|
|
||||||
b->sink->detaching_buffer = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flow_buffer_finish_detach (struct DataProtoFlow_buffer *b)
|
|
||||||
{
|
|
||||||
ASSERT(b->sink)
|
|
||||||
ASSERT(b->sink->detaching_buffer == b)
|
|
||||||
PacketPassFairQueueFlow_AssertFree(&b->sink_qflow);
|
|
||||||
|
|
||||||
// detach
|
|
||||||
flow_buffer_detach(b);
|
|
||||||
|
|
||||||
if (!b->flow) {
|
|
||||||
// free
|
|
||||||
flow_buffer_free(b);
|
|
||||||
} else if (b->flow->sink_desired) {
|
|
||||||
// attach
|
|
||||||
flow_buffer_attach(b, b->flow->sink_desired);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void flow_buffer_qflow_handler_busy (struct DataProtoFlow_buffer *b)
|
|
||||||
{
|
|
||||||
ASSERT(b->sink)
|
|
||||||
ASSERT(b->sink->detaching_buffer == b)
|
|
||||||
PacketPassFairQueueFlow_AssertFree(&b->sink_qflow);
|
|
||||||
|
|
||||||
flow_buffer_finish_detach(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DataProtoSink_Init (DataProtoSink *o, BReactor *reactor, PacketPassInterface *output, btime_t keepalive_time, btime_t tolerance_time, DataProtoSink_handler handler, void *user)
|
|
||||||
{
|
|
||||||
ASSERT(PacketPassInterface_HasCancel(output))
|
|
||||||
ASSERT(PacketPassInterface_GetMTU(output) >= DATAPROTO_MAX_OVERHEAD)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->reactor = reactor;
|
|
||||||
o->handler = handler;
|
|
||||||
o->user = user;
|
|
||||||
|
|
||||||
// set frame MTU
|
|
||||||
o->frame_mtu = PacketPassInterface_GetMTU(output) - DATAPROTO_MAX_OVERHEAD;
|
|
||||||
|
|
||||||
// init notifier
|
|
||||||
PacketPassNotifier_Init(&o->notifier, output, BReactor_PendingGroup(o->reactor));
|
|
||||||
PacketPassNotifier_SetHandler(&o->notifier, (PacketPassNotifier_handler_notify)notifier_handler, o);
|
|
||||||
|
|
||||||
// init monitor
|
|
||||||
PacketPassInactivityMonitor_Init(&o->monitor, PacketPassNotifier_GetInput(&o->notifier), o->reactor, keepalive_time, (PacketPassInactivityMonitor_handler)monitor_handler, o);
|
|
||||||
PacketPassInactivityMonitor_Force(&o->monitor);
|
|
||||||
|
|
||||||
// init queue
|
|
||||||
if (!PacketPassFairQueue_Init(&o->queue, PacketPassInactivityMonitor_GetInput(&o->monitor), BReactor_PendingGroup(o->reactor), 1, 1)) {
|
|
||||||
BLog(BLOG_ERROR, "PacketPassFairQueue_Init failed");
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init keepalive queue flow
|
|
||||||
PacketPassFairQueueFlow_Init(&o->ka_qflow, &o->queue);
|
|
||||||
|
|
||||||
// init keepalive source
|
|
||||||
DataProtoKeepaliveSource_Init(&o->ka_source, BReactor_PendingGroup(o->reactor));
|
|
||||||
|
|
||||||
// init keepalive blocker
|
|
||||||
PacketRecvBlocker_Init(&o->ka_blocker, DataProtoKeepaliveSource_GetOutput(&o->ka_source), BReactor_PendingGroup(o->reactor));
|
|
||||||
|
|
||||||
// init keepalive buffer
|
|
||||||
if (!SinglePacketBuffer_Init(&o->ka_buffer, PacketRecvBlocker_GetOutput(&o->ka_blocker), PacketPassFairQueueFlow_GetInput(&o->ka_qflow), BReactor_PendingGroup(o->reactor))) {
|
|
||||||
BLog(BLOG_ERROR, "SinglePacketBuffer_Init failed");
|
|
||||||
goto fail2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init receive timer
|
|
||||||
BTimer_Init(&o->receive_timer, tolerance_time, (BTimer_handler)receive_timer_handler, o);
|
|
||||||
|
|
||||||
// init handler job
|
|
||||||
BPending_Init(&o->up_job, BReactor_PendingGroup(o->reactor), (BPending_handler)up_job_handler, o);
|
|
||||||
|
|
||||||
// set not up
|
|
||||||
o->up = 0;
|
|
||||||
o->up_report = 0;
|
|
||||||
|
|
||||||
// set no detaching buffer
|
|
||||||
o->detaching_buffer = NULL;
|
|
||||||
|
|
||||||
DebugCounter_Init(&o->d_ctr);
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail2:
|
|
||||||
PacketRecvBlocker_Free(&o->ka_blocker);
|
|
||||||
DataProtoKeepaliveSource_Free(&o->ka_source);
|
|
||||||
PacketPassFairQueueFlow_Free(&o->ka_qflow);
|
|
||||||
PacketPassFairQueue_Free(&o->queue);
|
|
||||||
fail1:
|
|
||||||
PacketPassInactivityMonitor_Free(&o->monitor);
|
|
||||||
PacketPassNotifier_Free(&o->notifier);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProtoSink_Free (DataProtoSink *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
DebugCounter_Free(&o->d_ctr);
|
|
||||||
|
|
||||||
// allow freeing queue flows
|
|
||||||
PacketPassFairQueue_PrepareFree(&o->queue);
|
|
||||||
|
|
||||||
// release detaching buffer
|
|
||||||
if (o->detaching_buffer) {
|
|
||||||
ASSERT(!o->detaching_buffer->flow || o->detaching_buffer->flow->sink_desired != o)
|
|
||||||
flow_buffer_finish_detach(o->detaching_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// free handler job
|
|
||||||
BPending_Free(&o->up_job);
|
|
||||||
|
|
||||||
// free receive timer
|
|
||||||
BReactor_RemoveTimer(o->reactor, &o->receive_timer);
|
|
||||||
|
|
||||||
// free keepalive buffer
|
|
||||||
SinglePacketBuffer_Free(&o->ka_buffer);
|
|
||||||
|
|
||||||
// free keepalive blocker
|
|
||||||
PacketRecvBlocker_Free(&o->ka_blocker);
|
|
||||||
|
|
||||||
// free keepalive source
|
|
||||||
DataProtoKeepaliveSource_Free(&o->ka_source);
|
|
||||||
|
|
||||||
// free keepalive queue flow
|
|
||||||
PacketPassFairQueueFlow_Free(&o->ka_qflow);
|
|
||||||
|
|
||||||
// free queue
|
|
||||||
PacketPassFairQueue_Free(&o->queue);
|
|
||||||
|
|
||||||
// free monitor
|
|
||||||
PacketPassInactivityMonitor_Free(&o->monitor);
|
|
||||||
|
|
||||||
// free notifier
|
|
||||||
PacketPassNotifier_Free(&o->notifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProtoSink_Received (DataProtoSink *o, int peer_receiving)
|
|
||||||
{
|
|
||||||
ASSERT(peer_receiving == 0 || peer_receiving == 1)
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// reset receive timer
|
|
||||||
BReactor_SetTimer(o->reactor, &o->receive_timer);
|
|
||||||
|
|
||||||
if (!peer_receiving) {
|
|
||||||
// peer reports not receiving, consider down
|
|
||||||
o->up = 0;
|
|
||||||
// send keep-alive to converge faster
|
|
||||||
PacketRecvBlocker_AllowBlockedPacket(&o->ka_blocker);
|
|
||||||
} else {
|
|
||||||
// consider up
|
|
||||||
o->up = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh_up_job(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DataProtoSource_Init (DataProtoSource *o, PacketRecvInterface *input, DataProtoSource_handler handler, void *user, BReactor *reactor)
|
|
||||||
{
|
|
||||||
ASSERT(PacketRecvInterface_GetMTU(input) <= INT_MAX - DATAPROTO_MAX_OVERHEAD)
|
|
||||||
ASSERT(handler)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->handler = handler;
|
|
||||||
o->user = user;
|
|
||||||
o->reactor = reactor;
|
|
||||||
|
|
||||||
// remember frame MTU
|
|
||||||
o->frame_mtu = PacketRecvInterface_GetMTU(input);
|
|
||||||
|
|
||||||
// init router
|
|
||||||
if (!PacketRouter_Init(&o->router, DATAPROTO_MAX_OVERHEAD + o->frame_mtu, DATAPROTO_MAX_OVERHEAD, input, (PacketRouter_handler)source_router_handler, o, BReactor_PendingGroup(reactor))) {
|
|
||||||
BLog(BLOG_ERROR, "PacketRouter_Init failed");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugCounter_Init(&o->d_ctr);
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail0:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProtoSource_Free (DataProtoSource *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
DebugCounter_Free(&o->d_ctr);
|
|
||||||
|
|
||||||
// free router
|
|
||||||
PacketRouter_Free(&o->router);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DataProtoFlow_Init (DataProtoFlow *o, DataProtoSource *source, peerid_t source_id, peerid_t dest_id, int num_packets, int inactivity_time, void *user,
|
|
||||||
DataProtoFlow_handler_inactivity handler_inactivity)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&source->d_obj);
|
|
||||||
ASSERT(num_packets > 0)
|
|
||||||
ASSERT(!(inactivity_time >= 0) || handler_inactivity)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->source = source;
|
|
||||||
o->source_id = source_id;
|
|
||||||
o->dest_id = dest_id;
|
|
||||||
|
|
||||||
// set no desired sink
|
|
||||||
o->sink_desired = NULL;
|
|
||||||
|
|
||||||
// allocate buffer structure
|
|
||||||
struct DataProtoFlow_buffer *b = (struct DataProtoFlow_buffer *)malloc(sizeof(*b));
|
|
||||||
if (!b) {
|
|
||||||
BLog(BLOG_ERROR, "malloc failed");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
o->b = b;
|
|
||||||
|
|
||||||
// set parent
|
|
||||||
b->flow = o;
|
|
||||||
|
|
||||||
// remember inactivity time
|
|
||||||
b->inactivity_time = inactivity_time;
|
|
||||||
|
|
||||||
// init connector
|
|
||||||
PacketPassConnector_Init(&b->connector, DATAPROTO_MAX_OVERHEAD + source->frame_mtu, BReactor_PendingGroup(source->reactor));
|
|
||||||
|
|
||||||
// init inactivity monitor
|
|
||||||
PacketPassInterface *buf_out = PacketPassConnector_GetInput(&b->connector);
|
|
||||||
if (b->inactivity_time >= 0) {
|
|
||||||
PacketPassInactivityMonitor_Init(&b->monitor, buf_out, source->reactor, b->inactivity_time, handler_inactivity, user);
|
|
||||||
buf_out = PacketPassInactivityMonitor_GetInput(&b->monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// init route buffer
|
|
||||||
if (!RouteBuffer_Init(&b->rbuf, DATAPROTO_MAX_OVERHEAD + source->frame_mtu, buf_out, num_packets)) {
|
|
||||||
BLog(BLOG_ERROR, "RouteBuffer_Init failed");
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set no sink
|
|
||||||
b->sink = NULL;
|
|
||||||
|
|
||||||
DebugCounter_Increment(&source->d_ctr);
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail1:
|
|
||||||
if (b->inactivity_time >= 0) {
|
|
||||||
PacketPassInactivityMonitor_Free(&b->monitor);
|
|
||||||
}
|
|
||||||
PacketPassConnector_Free(&b->connector);
|
|
||||||
free(b);
|
|
||||||
fail0:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProtoFlow_Free (DataProtoFlow *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
DebugCounter_Decrement(&o->source->d_ctr);
|
|
||||||
ASSERT(!o->sink_desired)
|
|
||||||
struct DataProtoFlow_buffer *b = o->b;
|
|
||||||
|
|
||||||
if (b->sink) {
|
|
||||||
if (PacketPassFairQueueFlow_IsBusy(&b->sink_qflow)) {
|
|
||||||
// schedule detach, free buffer after detach
|
|
||||||
flow_buffer_schedule_detach(b);
|
|
||||||
b->flow = NULL;
|
|
||||||
|
|
||||||
// remove inactivity handler
|
|
||||||
if (b->inactivity_time >= 0) {
|
|
||||||
PacketPassInactivityMonitor_SetHandler(&b->monitor, NULL, NULL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// detach and free buffer now
|
|
||||||
flow_buffer_detach(b);
|
|
||||||
flow_buffer_free(b);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// free buffer
|
|
||||||
flow_buffer_free(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProtoFlow_Route (DataProtoFlow *o, int more)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
PacketRouter_AssertRoute(&o->source->router);
|
|
||||||
ASSERT(o->source->current_buf)
|
|
||||||
ASSERT(more == 0 || more == 1)
|
|
||||||
struct DataProtoFlow_buffer *b = o->b;
|
|
||||||
|
|
||||||
// write header. Don't set flags, it will be set in notifier_handler.
|
|
||||||
struct dataproto_header header;
|
|
||||||
struct dataproto_peer_id id;
|
|
||||||
header.from_id = htol16(o->source_id);
|
|
||||||
header.num_peer_ids = htol16(1);
|
|
||||||
id.id = htol16(o->dest_id);
|
|
||||||
memcpy(o->source->current_buf, &header, sizeof(header));
|
|
||||||
memcpy(o->source->current_buf + sizeof(header), &id, sizeof(id));
|
|
||||||
|
|
||||||
// route
|
|
||||||
uint8_t *next_buf;
|
|
||||||
if (!PacketRouter_Route(&o->source->router, DATAPROTO_MAX_OVERHEAD + o->source->current_recv_len, &b->rbuf,
|
|
||||||
&next_buf, DATAPROTO_MAX_OVERHEAD, (more ? o->source->current_recv_len : 0)
|
|
||||||
)) {
|
|
||||||
BLog(BLOG_NOTICE, "buffer full: %d->%d", (int)o->source_id, (int)o->dest_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember next buffer, or don't allow further routing if more==0
|
|
||||||
o->source->current_buf = (more ? next_buf : NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProtoFlow_Attach (DataProtoFlow *o, DataProtoSink *sink)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
DebugObject_Access(&sink->d_obj);
|
|
||||||
ASSERT(!o->sink_desired)
|
|
||||||
ASSERT(sink)
|
|
||||||
ASSERT(o->source->frame_mtu <= sink->frame_mtu)
|
|
||||||
struct DataProtoFlow_buffer *b = o->b;
|
|
||||||
|
|
||||||
if (b->sink) {
|
|
||||||
if (PacketPassFairQueueFlow_IsBusy(&b->sink_qflow)) {
|
|
||||||
// schedule detach and reattach
|
|
||||||
flow_buffer_schedule_detach(b);
|
|
||||||
} else {
|
|
||||||
// detach and reattach now
|
|
||||||
flow_buffer_detach(b);
|
|
||||||
flow_buffer_attach(b, sink);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// attach
|
|
||||||
flow_buffer_attach(b, sink);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set desired sink
|
|
||||||
o->sink_desired = sink;
|
|
||||||
|
|
||||||
DebugCounter_Increment(&sink->d_ctr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProtoFlow_Detach (DataProtoFlow *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(o->sink_desired)
|
|
||||||
struct DataProtoFlow_buffer *b = o->b;
|
|
||||||
ASSERT(b->sink)
|
|
||||||
|
|
||||||
DataProtoSink *sink = o->sink_desired;
|
|
||||||
|
|
||||||
if (PacketPassFairQueueFlow_IsBusy(&b->sink_qflow)) {
|
|
||||||
// schedule detach
|
|
||||||
flow_buffer_schedule_detach(b);
|
|
||||||
} else {
|
|
||||||
// detach now
|
|
||||||
flow_buffer_detach(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set no desired sink
|
|
||||||
o->sink_desired = NULL;
|
|
||||||
|
|
||||||
DebugCounter_Decrement(&sink->d_ctr);
|
|
||||||
}
|
|
|
@ -1,237 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DataProto.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* Mudule for frame sending used in the VPN client program.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_CLIENT_DATAPROTO_H
|
|
||||||
#define BADVPN_CLIENT_DATAPROTO_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <misc/debugcounter.h>
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
#include <system/BReactor.h>
|
|
||||||
#include <flow/PacketPassFairQueue.h>
|
|
||||||
#include <flow/PacketPassNotifier.h>
|
|
||||||
#include <flow/PacketRecvBlocker.h>
|
|
||||||
#include <flow/SinglePacketBuffer.h>
|
|
||||||
#include <flow/PacketPassConnector.h>
|
|
||||||
#include <flow/PacketRouter.h>
|
|
||||||
#include <flowextra/PacketPassInactivityMonitor.h>
|
|
||||||
#include <client/DataProtoKeepaliveSource.h>
|
|
||||||
|
|
||||||
typedef void (*DataProtoSink_handler) (void *user, int up);
|
|
||||||
typedef void (*DataProtoSource_handler) (void *user, const uint8_t *frame, int frame_len);
|
|
||||||
typedef void (*DataProtoFlow_handler_inactivity) (void *user);
|
|
||||||
|
|
||||||
struct DataProtoFlow_buffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frame destination.
|
|
||||||
* Represents a peer as a destination for sending frames to.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
BReactor *reactor;
|
|
||||||
int frame_mtu;
|
|
||||||
PacketPassFairQueue queue;
|
|
||||||
PacketPassInactivityMonitor monitor;
|
|
||||||
PacketPassNotifier notifier;
|
|
||||||
DataProtoKeepaliveSource ka_source;
|
|
||||||
PacketRecvBlocker ka_blocker;
|
|
||||||
SinglePacketBuffer ka_buffer;
|
|
||||||
PacketPassFairQueueFlow ka_qflow;
|
|
||||||
BTimer receive_timer;
|
|
||||||
int up;
|
|
||||||
int up_report;
|
|
||||||
DataProtoSink_handler handler;
|
|
||||||
void *user;
|
|
||||||
BPending up_job;
|
|
||||||
struct DataProtoFlow_buffer *detaching_buffer;
|
|
||||||
DebugObject d_obj;
|
|
||||||
DebugCounter d_ctr;
|
|
||||||
} DataProtoSink;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receives frames from a {@link PacketRecvInterface} input and
|
|
||||||
* allows the user to route them to buffers in {@link DataProtoFlow}'s.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
DataProtoSource_handler handler;
|
|
||||||
void *user;
|
|
||||||
BReactor *reactor;
|
|
||||||
int frame_mtu;
|
|
||||||
PacketRouter router;
|
|
||||||
uint8_t *current_buf;
|
|
||||||
int current_recv_len;
|
|
||||||
DebugObject d_obj;
|
|
||||||
DebugCounter d_ctr;
|
|
||||||
} DataProtoSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains a buffer for frames from a specific peer to a specific peer.
|
|
||||||
* Receives frames from a {@link DataProtoSource} as routed by the user.
|
|
||||||
* Can be attached to a {@link DataProtoSink} to send out frames.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
DataProtoSource *source;
|
|
||||||
peerid_t source_id;
|
|
||||||
peerid_t dest_id;
|
|
||||||
DataProtoSink *sink_desired;
|
|
||||||
struct DataProtoFlow_buffer *b;
|
|
||||||
DebugObject d_obj;
|
|
||||||
} DataProtoFlow;
|
|
||||||
|
|
||||||
struct DataProtoFlow_buffer {
|
|
||||||
DataProtoFlow *flow;
|
|
||||||
int inactivity_time;
|
|
||||||
RouteBuffer rbuf;
|
|
||||||
PacketPassInactivityMonitor monitor;
|
|
||||||
PacketPassConnector connector;
|
|
||||||
DataProtoSink *sink;
|
|
||||||
PacketPassFairQueueFlow sink_qflow;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the sink.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param reactor reactor we live in
|
|
||||||
* @param output output interface. Must support cancel functionality. Its MTU must be
|
|
||||||
* >=DATAPROTO_MAX_OVERHEAD.
|
|
||||||
* @param keepalive_time keepalive time
|
|
||||||
* @param tolerance_time after how long of not having received anything from the peer
|
|
||||||
* to consider the link down
|
|
||||||
* @param handler up state handler
|
|
||||||
* @param user value to pass to handler
|
|
||||||
* @return 1 on success, 0 on failure
|
|
||||||
*/
|
|
||||||
int DataProtoSink_Init (DataProtoSink *o, BReactor *reactor, PacketPassInterface *output, btime_t keepalive_time, btime_t tolerance_time, DataProtoSink_handler handler, void *user) WARN_UNUSED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the sink.
|
|
||||||
* There must be no local sources attached.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void DataProtoSink_Free (DataProtoSink *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies the sink that a packet was received from the peer.
|
|
||||||
* Must not be in freeing state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param peer_receiving whether the DATAPROTO_FLAGS_RECEIVING_KEEPALIVES flag was set in the packet.
|
|
||||||
* Must be 0 or 1.
|
|
||||||
*/
|
|
||||||
void DataProtoSink_Received (DataProtoSink *o, int peer_receiving);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initiazes the source.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param input frame input. Its input MTU must be <= INT_MAX - DATAPROTO_MAX_OVERHEAD.
|
|
||||||
* @param handler handler called when a frame arrives to allow the user to route it to
|
|
||||||
* appropriate {@link DataProtoFlow}'s.
|
|
||||||
* @param user value passed to handler
|
|
||||||
* @param reactor reactor we live in
|
|
||||||
* @return 1 on success, 0 on failure
|
|
||||||
*/
|
|
||||||
int DataProtoSource_Init (DataProtoSource *o, PacketRecvInterface *input, DataProtoSource_handler handler, void *user, BReactor *reactor) WARN_UNUSED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the source.
|
|
||||||
* There must be no {@link DataProtoFlow}'s using this source.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void DataProtoSource_Free (DataProtoSource *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the flow.
|
|
||||||
* The flow is initialized in not attached state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param source source to receive frames from
|
|
||||||
* @param source_id source peer ID to encode in the headers (i.e. our ID)
|
|
||||||
* @param dest_id destination peer ID to encode in the headers (i.e. ID if the peer this
|
|
||||||
* flow belongs to)
|
|
||||||
* @param num_packets number of packets the buffer should hold. Must be >0.
|
|
||||||
* @param inactivity_time milliseconds of output inactivity after which to call the
|
|
||||||
* inactivity handler; <0 to disable. Note that the flow is considered
|
|
||||||
* active as long as its buffer is non-empty, even if is not attached to
|
|
||||||
* a {@link DataProtoSink}.
|
|
||||||
* @param user value to pass to handler
|
|
||||||
* @param handler_inactivity inactivity handler, if inactivity_time >=0
|
|
||||||
* @return 1 on success, 0 on failure
|
|
||||||
*/
|
|
||||||
int DataProtoFlow_Init (DataProtoFlow *o, DataProtoSource *source, peerid_t source_id, peerid_t dest_id, int num_packets, int inactivity_time, void *user,
|
|
||||||
DataProtoFlow_handler_inactivity handler_inactivity) WARN_UNUSED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the flow.
|
|
||||||
* The flow must be in not attached state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void DataProtoFlow_Free (DataProtoFlow *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Routes a frame from the flow's source to this flow.
|
|
||||||
* Must be called from within the job context of the {@link DataProtoSource_handler} handler.
|
|
||||||
* Must not be called after this has been called with more=0 for the current frame.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param more whether the current frame may have to be routed to more
|
|
||||||
* flows. If 0, must not be called again until the handler is
|
|
||||||
* called for the next frame. Must be 0 or 1.
|
|
||||||
*/
|
|
||||||
void DataProtoFlow_Route (DataProtoFlow *o, int more);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attaches the flow to a sink.
|
|
||||||
* The flow must be in not attached state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param sink sink to attach to. This flow's frame_mtu must be <=
|
|
||||||
* (output MTU of sink) - DATAPROTO_MAX_OVERHEAD.
|
|
||||||
*/
|
|
||||||
void DataProtoFlow_Attach (DataProtoFlow *o, DataProtoSink *sink);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detaches the flow from a destination.
|
|
||||||
* The flow must be in attached state.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void DataProtoFlow_Detach (DataProtoFlow *o);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,72 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DataProtoKeepaliveSource.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <protocol/dataproto.h>
|
|
||||||
#include <misc/byteorder.h>
|
|
||||||
|
|
||||||
#include "DataProtoKeepaliveSource.h"
|
|
||||||
|
|
||||||
static void output_handler_recv (DataProtoKeepaliveSource *o, uint8_t *data)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
struct dataproto_header header;
|
|
||||||
header.flags = htol8(0);
|
|
||||||
header.from_id = htol16(0);
|
|
||||||
header.num_peer_ids = htol16(0);
|
|
||||||
memcpy(data, &header, sizeof(header));
|
|
||||||
|
|
||||||
// finish packet
|
|
||||||
PacketRecvInterface_Done(&o->output, sizeof(struct dataproto_header));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProtoKeepaliveSource_Init (DataProtoKeepaliveSource *o, BPendingGroup *pg)
|
|
||||||
{
|
|
||||||
// init output
|
|
||||||
PacketRecvInterface_Init(&o->output, sizeof(struct dataproto_header), (PacketRecvInterface_handler_recv)output_handler_recv, o, pg);
|
|
||||||
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProtoKeepaliveSource_Free (DataProtoKeepaliveSource *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
|
|
||||||
// free output
|
|
||||||
PacketRecvInterface_Free(&o->output);
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketRecvInterface * DataProtoKeepaliveSource_GetOutput (DataProtoKeepaliveSource *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
return &o->output;
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DataProtoKeepaliveSource.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* A {@link PacketRecvInterface} source which provides DataProto keepalive packets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_DATAPROTOKEEPALIVESOURCE_H
|
|
||||||
#define BADVPN_DATAPROTOKEEPALIVESOURCE_H
|
|
||||||
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
#include <flow/PacketRecvInterface.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link PacketRecvInterface} source which provides DataProto keepalive packets.
|
|
||||||
* These packets have no payload, no destination peers and flags zero.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
DebugObject d_obj;
|
|
||||||
PacketRecvInterface output;
|
|
||||||
} DataProtoKeepaliveSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the object.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param pg pending group
|
|
||||||
*/
|
|
||||||
void DataProtoKeepaliveSource_Init (DataProtoKeepaliveSource *o, BPendingGroup *pg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the object.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void DataProtoKeepaliveSource_Free (DataProtoKeepaliveSource *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the output interface.
|
|
||||||
* The MTU of the output interface will be sizeof(struct dataproto_header).
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @return output interface
|
|
||||||
*/
|
|
||||||
PacketRecvInterface * DataProtoKeepaliveSource_GetOutput (DataProtoKeepaliveSource *o);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,425 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DatagramPeerIO.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <client/DatagramPeerIO.h>
|
|
||||||
|
|
||||||
#include <generated/blog_channel_DatagramPeerIO.h>
|
|
||||||
|
|
||||||
#define DATAGRAMPEERIO_MODE_NONE 0
|
|
||||||
#define DATAGRAMPEERIO_MODE_CONNECT 1
|
|
||||||
#define DATAGRAMPEERIO_MODE_BIND 2
|
|
||||||
|
|
||||||
#define PeerLog(_o, ...) BLog_LogViaFunc((_o)->logfunc, (_o)->user, BLOG_CURRENT_CHANNEL, __VA_ARGS__)
|
|
||||||
|
|
||||||
static void init_io (DatagramPeerIO *o);
|
|
||||||
static void free_io (DatagramPeerIO *o);
|
|
||||||
static void dgram_handler (DatagramPeerIO *o, int event);
|
|
||||||
static void reset_mode (DatagramPeerIO *o);
|
|
||||||
static void recv_decoder_notifier_handler (DatagramPeerIO *o, uint8_t *data, int data_len);
|
|
||||||
|
|
||||||
void init_io (DatagramPeerIO *o)
|
|
||||||
{
|
|
||||||
// init dgram recv interface
|
|
||||||
BDatagram_RecvAsync_Init(&o->dgram, o->effective_socket_mtu);
|
|
||||||
|
|
||||||
// connect source
|
|
||||||
PacketRecvConnector_ConnectInput(&o->recv_connector, BDatagram_RecvAsync_GetIf(&o->dgram));
|
|
||||||
|
|
||||||
// init dgram send interface
|
|
||||||
BDatagram_SendAsync_Init(&o->dgram, o->effective_socket_mtu);
|
|
||||||
|
|
||||||
// connect sink
|
|
||||||
PacketPassConnector_ConnectOutput(&o->send_connector, BDatagram_SendAsync_GetIf(&o->dgram));
|
|
||||||
}
|
|
||||||
|
|
||||||
void free_io (DatagramPeerIO *o)
|
|
||||||
{
|
|
||||||
// disconnect sink
|
|
||||||
PacketPassConnector_DisconnectOutput(&o->send_connector);
|
|
||||||
|
|
||||||
// free dgram send interface
|
|
||||||
BDatagram_SendAsync_Free(&o->dgram);
|
|
||||||
|
|
||||||
// disconnect source
|
|
||||||
PacketRecvConnector_DisconnectInput(&o->recv_connector);
|
|
||||||
|
|
||||||
// free dgram recv interface
|
|
||||||
BDatagram_RecvAsync_Free(&o->dgram);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dgram_handler (DatagramPeerIO *o, int event)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(o->mode == DATAGRAMPEERIO_MODE_CONNECT || o->mode == DATAGRAMPEERIO_MODE_BIND)
|
|
||||||
|
|
||||||
PeerLog(o, BLOG_NOTICE, "error");
|
|
||||||
|
|
||||||
// reset mode
|
|
||||||
reset_mode(o);
|
|
||||||
|
|
||||||
// report error
|
|
||||||
if (o->handler_error) {
|
|
||||||
o->handler_error(o->user);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset_mode (DatagramPeerIO *o)
|
|
||||||
{
|
|
||||||
ASSERT(o->mode == DATAGRAMPEERIO_MODE_NONE || o->mode == DATAGRAMPEERIO_MODE_CONNECT || o->mode == DATAGRAMPEERIO_MODE_BIND)
|
|
||||||
|
|
||||||
if (o->mode == DATAGRAMPEERIO_MODE_NONE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove recv notifier handler
|
|
||||||
PacketPassNotifier_SetHandler(&o->recv_notifier, NULL, NULL);
|
|
||||||
|
|
||||||
// free I/O
|
|
||||||
free_io(o);
|
|
||||||
|
|
||||||
// free datagram object
|
|
||||||
BDatagram_Free(&o->dgram);
|
|
||||||
|
|
||||||
// set mode
|
|
||||||
o->mode = DATAGRAMPEERIO_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void recv_decoder_notifier_handler (DatagramPeerIO *o, uint8_t *data, int data_len)
|
|
||||||
{
|
|
||||||
ASSERT(o->mode == DATAGRAMPEERIO_MODE_BIND)
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// obtain addresses from last received packet
|
|
||||||
BAddr addr;
|
|
||||||
BIPAddr local_addr;
|
|
||||||
ASSERT_EXECUTE(BDatagram_GetLastReceiveAddrs(&o->dgram, &addr, &local_addr))
|
|
||||||
|
|
||||||
// check address family just in case
|
|
||||||
if (!BDatagram_AddressFamilySupported(addr.type)) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "unsupported receive address");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update addresses
|
|
||||||
BDatagram_SetSendAddrs(&o->dgram, addr, local_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DatagramPeerIO_Init (
|
|
||||||
DatagramPeerIO *o,
|
|
||||||
BReactor *reactor,
|
|
||||||
int payload_mtu,
|
|
||||||
int socket_mtu,
|
|
||||||
struct spproto_security_params sp_params,
|
|
||||||
btime_t latency,
|
|
||||||
int num_frames,
|
|
||||||
PacketPassInterface *recv_userif,
|
|
||||||
int otp_warning_count,
|
|
||||||
BThreadWorkDispatcher *twd,
|
|
||||||
void *user,
|
|
||||||
BLog_logfunc logfunc,
|
|
||||||
DatagramPeerIO_handler_error handler_error,
|
|
||||||
DatagramPeerIO_handler_otp_warning handler_otp_warning,
|
|
||||||
DatagramPeerIO_handler_otp_ready handler_otp_ready
|
|
||||||
)
|
|
||||||
{
|
|
||||||
ASSERT(payload_mtu >= 0)
|
|
||||||
ASSERT(socket_mtu >= 0)
|
|
||||||
spproto_assert_security_params(sp_params);
|
|
||||||
ASSERT(num_frames > 0)
|
|
||||||
ASSERT(PacketPassInterface_GetMTU(recv_userif) >= payload_mtu)
|
|
||||||
if (SPPROTO_HAVE_OTP(sp_params)) {
|
|
||||||
ASSERT(otp_warning_count > 0)
|
|
||||||
ASSERT(otp_warning_count <= sp_params.otp_num)
|
|
||||||
}
|
|
||||||
|
|
||||||
// set parameters
|
|
||||||
o->reactor = reactor;
|
|
||||||
o->payload_mtu = payload_mtu;
|
|
||||||
o->sp_params = sp_params;
|
|
||||||
o->user = user;
|
|
||||||
o->logfunc = logfunc;
|
|
||||||
o->handler_error = handler_error;
|
|
||||||
|
|
||||||
// check num frames (for FragmentProtoAssembler)
|
|
||||||
if (num_frames >= FPA_MAX_TIME) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "num_frames is too big");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check payload MTU (for FragmentProto)
|
|
||||||
if (o->payload_mtu > UINT16_MAX) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "payload MTU is too big");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate SPProto payload MTU
|
|
||||||
if ((o->spproto_payload_mtu = spproto_payload_mtu_for_carrier_mtu(o->sp_params, socket_mtu)) <= (int)sizeof(struct fragmentproto_chunk_header)) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "socket MTU is too small");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate effective socket MTU
|
|
||||||
if ((o->effective_socket_mtu = spproto_carrier_mtu_for_payload_mtu(o->sp_params, o->spproto_payload_mtu)) < 0) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "spproto_carrier_mtu_for_payload_mtu failed !?");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init receiving
|
|
||||||
|
|
||||||
// init assembler
|
|
||||||
if (!FragmentProtoAssembler_Init(&o->recv_assembler, o->spproto_payload_mtu, recv_userif, num_frames, fragmentproto_max_chunks_for_frame(o->spproto_payload_mtu, o->payload_mtu),
|
|
||||||
BReactor_PendingGroup(o->reactor), o->user, o->logfunc
|
|
||||||
)) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "FragmentProtoAssembler_Init failed");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init notifier
|
|
||||||
PacketPassNotifier_Init(&o->recv_notifier, FragmentProtoAssembler_GetInput(&o->recv_assembler), BReactor_PendingGroup(o->reactor));
|
|
||||||
|
|
||||||
// init decoder
|
|
||||||
if (!SPProtoDecoder_Init(&o->recv_decoder, PacketPassNotifier_GetInput(&o->recv_notifier), o->sp_params, 2, BReactor_PendingGroup(o->reactor), twd, o->user, o->logfunc)) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "SPProtoDecoder_Init failed");
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
SPProtoDecoder_SetHandlers(&o->recv_decoder, handler_otp_ready, user);
|
|
||||||
|
|
||||||
// init connector
|
|
||||||
PacketRecvConnector_Init(&o->recv_connector, o->effective_socket_mtu, BReactor_PendingGroup(o->reactor));
|
|
||||||
|
|
||||||
// init buffer
|
|
||||||
if (!SinglePacketBuffer_Init(&o->recv_buffer, PacketRecvConnector_GetOutput(&o->recv_connector), SPProtoDecoder_GetInput(&o->recv_decoder), BReactor_PendingGroup(o->reactor))) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "SinglePacketBuffer_Init failed");
|
|
||||||
goto fail2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init sending base
|
|
||||||
|
|
||||||
// init disassembler
|
|
||||||
FragmentProtoDisassembler_Init(&o->send_disassembler, o->reactor, o->payload_mtu, o->spproto_payload_mtu, -1, latency);
|
|
||||||
|
|
||||||
// init encoder
|
|
||||||
if (!SPProtoEncoder_Init(&o->send_encoder, FragmentProtoDisassembler_GetOutput(&o->send_disassembler), o->sp_params, otp_warning_count, BReactor_PendingGroup(o->reactor), twd)) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "SPProtoEncoder_Init failed");
|
|
||||||
goto fail3;
|
|
||||||
}
|
|
||||||
SPProtoEncoder_SetHandlers(&o->send_encoder, handler_otp_warning, user);
|
|
||||||
|
|
||||||
// init connector
|
|
||||||
PacketPassConnector_Init(&o->send_connector, o->effective_socket_mtu, BReactor_PendingGroup(o->reactor));
|
|
||||||
|
|
||||||
// init buffer
|
|
||||||
if (!SinglePacketBuffer_Init(&o->send_buffer, SPProtoEncoder_GetOutput(&o->send_encoder), PacketPassConnector_GetInput(&o->send_connector), BReactor_PendingGroup(o->reactor))) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "SinglePacketBuffer_Init failed");
|
|
||||||
goto fail4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set mode
|
|
||||||
o->mode = DATAGRAMPEERIO_MODE_NONE;
|
|
||||||
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail4:
|
|
||||||
PacketPassConnector_Free(&o->send_connector);
|
|
||||||
SPProtoEncoder_Free(&o->send_encoder);
|
|
||||||
fail3:
|
|
||||||
FragmentProtoDisassembler_Free(&o->send_disassembler);
|
|
||||||
SinglePacketBuffer_Free(&o->recv_buffer);
|
|
||||||
fail2:
|
|
||||||
PacketRecvConnector_Free(&o->recv_connector);
|
|
||||||
SPProtoDecoder_Free(&o->recv_decoder);
|
|
||||||
fail1:
|
|
||||||
PacketPassNotifier_Free(&o->recv_notifier);
|
|
||||||
FragmentProtoAssembler_Free(&o->recv_assembler);
|
|
||||||
fail0:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatagramPeerIO_Free (DatagramPeerIO *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
|
|
||||||
// reset mode
|
|
||||||
reset_mode(o);
|
|
||||||
|
|
||||||
// free sending base
|
|
||||||
SinglePacketBuffer_Free(&o->send_buffer);
|
|
||||||
PacketPassConnector_Free(&o->send_connector);
|
|
||||||
SPProtoEncoder_Free(&o->send_encoder);
|
|
||||||
FragmentProtoDisassembler_Free(&o->send_disassembler);
|
|
||||||
|
|
||||||
// free receiving
|
|
||||||
SinglePacketBuffer_Free(&o->recv_buffer);
|
|
||||||
PacketRecvConnector_Free(&o->recv_connector);
|
|
||||||
SPProtoDecoder_Free(&o->recv_decoder);
|
|
||||||
PacketPassNotifier_Free(&o->recv_notifier);
|
|
||||||
FragmentProtoAssembler_Free(&o->recv_assembler);
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketPassInterface * DatagramPeerIO_GetSendInput (DatagramPeerIO *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
return FragmentProtoDisassembler_GetInput(&o->send_disassembler);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DatagramPeerIO_Connect (DatagramPeerIO *o, BAddr addr)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// reset mode
|
|
||||||
reset_mode(o);
|
|
||||||
|
|
||||||
// check address
|
|
||||||
if (!BDatagram_AddressFamilySupported(addr.type)) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "BDatagram_AddressFamilySupported failed");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init dgram
|
|
||||||
if (!BDatagram_Init(&o->dgram, addr.type, o->reactor, o, (BDatagram_handler)dgram_handler)) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "BDatagram_Init failed");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set send address
|
|
||||||
BIPAddr local_addr;
|
|
||||||
BIPAddr_InitInvalid(&local_addr);
|
|
||||||
BDatagram_SetSendAddrs(&o->dgram, addr, local_addr);
|
|
||||||
|
|
||||||
// init I/O
|
|
||||||
init_io(o);
|
|
||||||
|
|
||||||
// set mode
|
|
||||||
o->mode = DATAGRAMPEERIO_MODE_CONNECT;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail0:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DatagramPeerIO_Bind (DatagramPeerIO *o, BAddr addr)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
ASSERT(BDatagram_AddressFamilySupported(addr.type))
|
|
||||||
|
|
||||||
// reset mode
|
|
||||||
reset_mode(o);
|
|
||||||
|
|
||||||
// init dgram
|
|
||||||
if (!BDatagram_Init(&o->dgram, addr.type, o->reactor, o, (BDatagram_handler)dgram_handler)) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "BDatagram_Init failed");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind dgram
|
|
||||||
if (!BDatagram_Bind(&o->dgram, addr)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "BDatagram_Bind failed");
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init I/O
|
|
||||||
init_io(o);
|
|
||||||
|
|
||||||
// set recv notifier handler
|
|
||||||
PacketPassNotifier_SetHandler(&o->recv_notifier, (PacketPassNotifier_handler_notify)recv_decoder_notifier_handler, o);
|
|
||||||
|
|
||||||
// set mode
|
|
||||||
o->mode = DATAGRAMPEERIO_MODE_BIND;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail1:
|
|
||||||
BDatagram_Free(&o->dgram);
|
|
||||||
fail0:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatagramPeerIO_SetEncryptionKey (DatagramPeerIO *o, uint8_t *encryption_key)
|
|
||||||
{
|
|
||||||
ASSERT(SPPROTO_HAVE_ENCRYPTION(o->sp_params))
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// set sending key
|
|
||||||
SPProtoEncoder_SetEncryptionKey(&o->send_encoder, encryption_key);
|
|
||||||
|
|
||||||
// set receiving key
|
|
||||||
SPProtoDecoder_SetEncryptionKey(&o->recv_decoder, encryption_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatagramPeerIO_RemoveEncryptionKey (DatagramPeerIO *o)
|
|
||||||
{
|
|
||||||
ASSERT(SPPROTO_HAVE_ENCRYPTION(o->sp_params))
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// remove sending key
|
|
||||||
SPProtoEncoder_RemoveEncryptionKey(&o->send_encoder);
|
|
||||||
|
|
||||||
// remove receiving key
|
|
||||||
SPProtoDecoder_RemoveEncryptionKey(&o->recv_decoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatagramPeerIO_SetOTPSendSeed (DatagramPeerIO *o, uint16_t seed_id, uint8_t *key, uint8_t *iv)
|
|
||||||
{
|
|
||||||
ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// set sending seed
|
|
||||||
SPProtoEncoder_SetOTPSeed(&o->send_encoder, seed_id, key, iv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatagramPeerIO_RemoveOTPSendSeed (DatagramPeerIO *o)
|
|
||||||
{
|
|
||||||
ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// remove sending seed
|
|
||||||
SPProtoEncoder_RemoveOTPSeed(&o->send_encoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatagramPeerIO_AddOTPRecvSeed (DatagramPeerIO *o, uint16_t seed_id, uint8_t *key, uint8_t *iv)
|
|
||||||
{
|
|
||||||
ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// add receiving seed
|
|
||||||
SPProtoDecoder_AddOTPSeed(&o->recv_decoder, seed_id, key, iv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatagramPeerIO_RemoveOTPRecvSeeds (DatagramPeerIO *o)
|
|
||||||
{
|
|
||||||
ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// remove receiving seeds
|
|
||||||
SPProtoDecoder_RemoveOTPSeeds(&o->recv_decoder);
|
|
||||||
}
|
|
|
@ -1,271 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DatagramPeerIO.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* Object for comminicating with a peer using a datagram socket.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_CLIENT_DATAGRAMPEERIO_H
|
|
||||||
#define BADVPN_CLIENT_DATAGRAMPEERIO_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <protocol/spproto.h>
|
|
||||||
#include <protocol/fragmentproto.h>
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
#include <base/BLog.h>
|
|
||||||
#include <system/BReactor.h>
|
|
||||||
#include <system/BAddr.h>
|
|
||||||
#include <system/BDatagram.h>
|
|
||||||
#include <system/BTime.h>
|
|
||||||
#include <flow/PacketPassInterface.h>
|
|
||||||
#include <flow/PacketPassConnector.h>
|
|
||||||
#include <flow/SinglePacketBuffer.h>
|
|
||||||
#include <flow/PacketRecvConnector.h>
|
|
||||||
#include <flow/PacketPassNotifier.h>
|
|
||||||
#include <client/FragmentProtoDisassembler.h>
|
|
||||||
#include <client/FragmentProtoAssembler.h>
|
|
||||||
#include <client/SPProtoEncoder.h>
|
|
||||||
#include <client/SPProtoDecoder.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback function invoked when an error occurs with the peer connection.
|
|
||||||
* The object has entered default state.
|
|
||||||
* May be called from within a sending Send call.
|
|
||||||
*
|
|
||||||
* @param user as in {@link DatagramPeerIO_SetHandlers}
|
|
||||||
*/
|
|
||||||
typedef void (*DatagramPeerIO_handler_error) (void *user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler function invoked when the number of used OTPs has reached
|
|
||||||
* the specified warning number in {@link DatagramPeerIO_SetOTPWarningHandler}.
|
|
||||||
* May be called from within a sending Send call.
|
|
||||||
*
|
|
||||||
* @param user as in {@link DatagramPeerIO_SetHandlers}
|
|
||||||
*/
|
|
||||||
typedef void (*DatagramPeerIO_handler_otp_warning) (void *user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler called when OTP generation for a new receive seed is finished.
|
|
||||||
*
|
|
||||||
* @param user as in {@link DatagramPeerIO_SetHandlers}
|
|
||||||
*/
|
|
||||||
typedef void (*DatagramPeerIO_handler_otp_ready) (void *user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object for comminicating with a peer using a datagram socket.
|
|
||||||
*
|
|
||||||
* The user provides data for sending to the peer through {@link PacketPassInterface}.
|
|
||||||
* Received data is provided to the user through {@link PacketPassInterface}.
|
|
||||||
*
|
|
||||||
* The object has a logical state called a mode, which is one of the following:
|
|
||||||
* - default - nothing is send or received
|
|
||||||
* - connecting - an address was provided by the user for sending datagrams to.
|
|
||||||
* Datagrams are being sent to that address through a socket,
|
|
||||||
* and datagrams are being received on the same socket.
|
|
||||||
* - binding - an address was provided by the user to bind a socket to.
|
|
||||||
* Datagrams are being received on the socket. Datagrams are not being
|
|
||||||
* sent initially. When a datagram is received, its source address is
|
|
||||||
* used as a destination address for sending datagrams.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
DebugObject d_obj;
|
|
||||||
BReactor *reactor;
|
|
||||||
int payload_mtu;
|
|
||||||
struct spproto_security_params sp_params;
|
|
||||||
void *user;
|
|
||||||
BLog_logfunc logfunc;
|
|
||||||
DatagramPeerIO_handler_error handler_error;
|
|
||||||
int spproto_payload_mtu;
|
|
||||||
int effective_socket_mtu;
|
|
||||||
|
|
||||||
// sending base
|
|
||||||
FragmentProtoDisassembler send_disassembler;
|
|
||||||
SPProtoEncoder send_encoder;
|
|
||||||
SinglePacketBuffer send_buffer;
|
|
||||||
PacketPassConnector send_connector;
|
|
||||||
|
|
||||||
// receiving
|
|
||||||
PacketRecvConnector recv_connector;
|
|
||||||
SinglePacketBuffer recv_buffer;
|
|
||||||
SPProtoDecoder recv_decoder;
|
|
||||||
PacketPassNotifier recv_notifier;
|
|
||||||
FragmentProtoAssembler recv_assembler;
|
|
||||||
|
|
||||||
// mode
|
|
||||||
int mode;
|
|
||||||
|
|
||||||
// datagram object
|
|
||||||
BDatagram dgram;
|
|
||||||
} DatagramPeerIO;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the object.
|
|
||||||
* The interface is initialized in default mode.
|
|
||||||
* {@link BLog_Init} must have been done.
|
|
||||||
* {@link BNetwork_GlobalInit} must have been done.
|
|
||||||
* {@link BSecurity_GlobalInitThreadSafe} must have been done if
|
|
||||||
* {@link BThreadWorkDispatcher_UsingThreads}(twd) = 1.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param reactor {@link BReactor} we live in
|
|
||||||
* @param payload_mtu maximum payload size. Must be >=0.
|
|
||||||
* @param socket_mtu maximum datagram size for the socket. Must be >=0. Must be large enough so it is possible to
|
|
||||||
* send a FragmentProto chunk with one byte of data over SPProto, i.e. the following has to hold:
|
|
||||||
* spproto_payload_mtu_for_carrier_mtu(sp_params, socket_mtu) > sizeof(struct fragmentproto_chunk_header)
|
|
||||||
* @param sp_params SPProto security parameters
|
|
||||||
* @param latency latency parameter to {@link FragmentProtoDisassembler_Init}.
|
|
||||||
* @param num_frames num_frames parameter to {@link FragmentProtoAssembler_Init}. Must be >0.
|
|
||||||
* @param recv_userif interface to pass received packets to the user. Its MTU must be >=payload_mtu.
|
|
||||||
* @param otp_warning_count If using OTPs, after how many encoded packets to call the handler.
|
|
||||||
* In this case, must be >0 and <=sp_params.otp_num.
|
|
||||||
* @param twd thread work dispatcher
|
|
||||||
* @param user value to pass to handlers
|
|
||||||
* @param logfunc function which prepends the log prefix using {@link BLog_Append}
|
|
||||||
* @param handler_error error handler
|
|
||||||
* @param handler_otp_warning OTP warning handler
|
|
||||||
* @param handler_otp_ready handler called when OTP generation for a new receive seed is finished
|
|
||||||
* @return 1 on success, 0 on failure
|
|
||||||
*/
|
|
||||||
int DatagramPeerIO_Init (
|
|
||||||
DatagramPeerIO *o,
|
|
||||||
BReactor *reactor,
|
|
||||||
int payload_mtu,
|
|
||||||
int socket_mtu,
|
|
||||||
struct spproto_security_params sp_params,
|
|
||||||
btime_t latency,
|
|
||||||
int num_frames,
|
|
||||||
PacketPassInterface *recv_userif,
|
|
||||||
int otp_warning_count,
|
|
||||||
BThreadWorkDispatcher *twd,
|
|
||||||
void *user,
|
|
||||||
BLog_logfunc logfunc,
|
|
||||||
DatagramPeerIO_handler_error handler_error,
|
|
||||||
DatagramPeerIO_handler_otp_warning handler_otp_warning,
|
|
||||||
DatagramPeerIO_handler_otp_ready handler_otp_ready
|
|
||||||
) WARN_UNUSED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the object.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void DatagramPeerIO_Free (DatagramPeerIO *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an interface the user should use to send packets.
|
|
||||||
* The OTP warning handler may be called from within Send calls
|
|
||||||
* to the interface.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @return sending interface
|
|
||||||
*/
|
|
||||||
PacketPassInterface * DatagramPeerIO_GetSendInput (DatagramPeerIO *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to establish connection to the peer which has bound to an address.
|
|
||||||
* On success, the interface enters connecting mode.
|
|
||||||
* On failure, the interface enters default mode.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param addr address to send packets to
|
|
||||||
* @return 1 on success, 0 on failure
|
|
||||||
*/
|
|
||||||
int DatagramPeerIO_Connect (DatagramPeerIO *o, BAddr addr) WARN_UNUSED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to establish connection to the peer by binding to an address.
|
|
||||||
* On success, the interface enters connecting mode.
|
|
||||||
* On failure, the interface enters default mode.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param addr address to bind to. Must be supported according to
|
|
||||||
* {@link BDatagram_AddressFamilySupported}.
|
|
||||||
* @return 1 on success, 0 on failure
|
|
||||||
*/
|
|
||||||
int DatagramPeerIO_Bind (DatagramPeerIO *o, BAddr addr) WARN_UNUSED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the encryption key to use for sending and receiving.
|
|
||||||
* Encryption must be enabled.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param encryption_key key to use
|
|
||||||
*/
|
|
||||||
void DatagramPeerIO_SetEncryptionKey (DatagramPeerIO *o, uint8_t *encryption_key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removed the encryption key to use for sending and receiving.
|
|
||||||
* Encryption must be enabled.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void DatagramPeerIO_RemoveEncryptionKey (DatagramPeerIO *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the OTP seed for sending.
|
|
||||||
* OTPs must be enabled.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param seed_id seed identifier
|
|
||||||
* @param key OTP encryption key
|
|
||||||
* @param iv OTP initialization vector
|
|
||||||
*/
|
|
||||||
void DatagramPeerIO_SetOTPSendSeed (DatagramPeerIO *o, uint16_t seed_id, uint8_t *key, uint8_t *iv);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the OTP seed for sending of one is configured.
|
|
||||||
* OTPs must be enabled.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void DatagramPeerIO_RemoveOTPSendSeed (DatagramPeerIO *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an OTP seed for reciving.
|
|
||||||
* OTPs must be enabled.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param seed_id seed identifier
|
|
||||||
* @param key OTP encryption key
|
|
||||||
* @param iv OTP initialization vector
|
|
||||||
*/
|
|
||||||
void DatagramPeerIO_AddOTPRecvSeed (DatagramPeerIO *o, uint16_t seed_id, uint8_t *key, uint8_t *iv);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all OTP seeds for reciving.
|
|
||||||
* OTPs must be enabled.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void DatagramPeerIO_RemoveOTPRecvSeeds (DatagramPeerIO *o);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,469 +0,0 @@
|
||||||
/**
|
|
||||||
* @file FragmentProtoAssembler.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <misc/offset.h>
|
|
||||||
#include <misc/byteorder.h>
|
|
||||||
#include <misc/balloc.h>
|
|
||||||
|
|
||||||
#include "FragmentProtoAssembler.h"
|
|
||||||
|
|
||||||
#include <generated/blog_channel_FragmentProtoAssembler.h>
|
|
||||||
|
|
||||||
#define PeerLog(_o, ...) BLog_LogViaFunc((_o)->logfunc, (_o)->user, BLOG_CURRENT_CHANNEL, __VA_ARGS__)
|
|
||||||
|
|
||||||
#include "FragmentProtoAssembler_tree.h"
|
|
||||||
#include <structure/SAvl_impl.h>
|
|
||||||
|
|
||||||
static void free_frame (FragmentProtoAssembler *o, struct FragmentProtoAssembler_frame *frame)
|
|
||||||
{
|
|
||||||
// remove from used list
|
|
||||||
LinkedList1_Remove(&o->frames_used, &frame->list_node);
|
|
||||||
// remove from used tree
|
|
||||||
FPAFramesTree_Remove(&o->frames_used_tree, 0, frame);
|
|
||||||
|
|
||||||
// append to free list
|
|
||||||
LinkedList1_Append(&o->frames_free, &frame->list_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_oldest_frame (FragmentProtoAssembler *o)
|
|
||||||
{
|
|
||||||
ASSERT(!LinkedList1_IsEmpty(&o->frames_used))
|
|
||||||
|
|
||||||
// obtain oldest frame (first on the list)
|
|
||||||
LinkedList1Node *list_node = LinkedList1_GetFirst(&o->frames_used);
|
|
||||||
ASSERT(list_node)
|
|
||||||
struct FragmentProtoAssembler_frame *frame = UPPER_OBJECT(list_node, struct FragmentProtoAssembler_frame, list_node);
|
|
||||||
|
|
||||||
// free frame
|
|
||||||
free_frame(o, frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct FragmentProtoAssembler_frame * allocate_new_frame (FragmentProtoAssembler *o, fragmentproto_frameid id)
|
|
||||||
{
|
|
||||||
ASSERT(!FPAFramesTree_LookupExact(&o->frames_used_tree, 0, id))
|
|
||||||
|
|
||||||
// if there are no free entries, free the oldest used one
|
|
||||||
if (LinkedList1_IsEmpty(&o->frames_free)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "freeing used frame");
|
|
||||||
free_oldest_frame(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
// obtain frame entry
|
|
||||||
LinkedList1Node *list_node = LinkedList1_GetFirst(&o->frames_free);
|
|
||||||
ASSERT(list_node)
|
|
||||||
struct FragmentProtoAssembler_frame *frame = UPPER_OBJECT(list_node, struct FragmentProtoAssembler_frame, list_node);
|
|
||||||
|
|
||||||
// remove from free list
|
|
||||||
LinkedList1_Remove(&o->frames_free, &frame->list_node);
|
|
||||||
|
|
||||||
// initialize values
|
|
||||||
frame->id = id;
|
|
||||||
frame->time = o->time;
|
|
||||||
frame->num_chunks = 0;
|
|
||||||
frame->sum = 0;
|
|
||||||
frame->length = -1;
|
|
||||||
frame->length_so_far = 0;
|
|
||||||
|
|
||||||
// append to used list
|
|
||||||
LinkedList1_Append(&o->frames_used, &frame->list_node);
|
|
||||||
// insert to used tree
|
|
||||||
int res = FPAFramesTree_Insert(&o->frames_used_tree, 0, frame, NULL);
|
|
||||||
ASSERT_EXECUTE(res)
|
|
||||||
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int chunks_overlap (int c1_start, int c1_len, int c2_start, int c2_len)
|
|
||||||
{
|
|
||||||
return (c1_start + c1_len > c2_start && c2_start + c2_len > c1_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int frame_is_timed_out (FragmentProtoAssembler *o, struct FragmentProtoAssembler_frame *frame)
|
|
||||||
{
|
|
||||||
ASSERT(frame->time <= o->time)
|
|
||||||
|
|
||||||
return (o->time - frame->time > o->time_tolerance);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reduce_times (FragmentProtoAssembler *o)
|
|
||||||
{
|
|
||||||
// find the frame with minimal time, removing timed out frames
|
|
||||||
struct FragmentProtoAssembler_frame *minframe = NULL;
|
|
||||||
LinkedList1Node *list_node = LinkedList1_GetFirst(&o->frames_used);
|
|
||||||
while (list_node) {
|
|
||||||
LinkedList1Node *next = LinkedList1Node_Next(list_node);
|
|
||||||
struct FragmentProtoAssembler_frame *frame = UPPER_OBJECT(list_node, struct FragmentProtoAssembler_frame, list_node);
|
|
||||||
if (frame_is_timed_out(o, frame)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "freeing timed out frame (while reducing times)");
|
|
||||||
free_frame(o, frame);
|
|
||||||
} else {
|
|
||||||
if (!minframe || frame->time < minframe->time) {
|
|
||||||
minframe = frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list_node = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!minframe) {
|
|
||||||
// have no frames, set packet time to zero
|
|
||||||
o->time = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t min_time = minframe->time;
|
|
||||||
|
|
||||||
// subtract minimal time from all frames
|
|
||||||
for (list_node = LinkedList1_GetFirst(&o->frames_used); list_node; list_node = LinkedList1Node_Next(list_node)) {
|
|
||||||
struct FragmentProtoAssembler_frame *frame = UPPER_OBJECT(list_node, struct FragmentProtoAssembler_frame, list_node);
|
|
||||||
frame->time -= min_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
// subtract minimal time from packet time
|
|
||||||
o->time -= min_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int process_chunk (FragmentProtoAssembler *o, fragmentproto_frameid frame_id, int chunk_start, int chunk_len, int is_last, uint8_t *payload)
|
|
||||||
{
|
|
||||||
ASSERT(chunk_start >= 0)
|
|
||||||
ASSERT(chunk_len >= 0)
|
|
||||||
ASSERT(is_last == 0 || is_last == 1)
|
|
||||||
|
|
||||||
// verify chunk
|
|
||||||
|
|
||||||
// check start
|
|
||||||
if (chunk_start > o->output_mtu) {
|
|
||||||
PeerLog(o, BLOG_INFO, "chunk starts outside");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check frame size bound
|
|
||||||
if (chunk_len > o->output_mtu - chunk_start) {
|
|
||||||
PeerLog(o, BLOG_INFO, "chunk ends outside");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate end
|
|
||||||
int chunk_end = chunk_start + chunk_len;
|
|
||||||
ASSERT(chunk_end >= 0)
|
|
||||||
ASSERT(chunk_end <= o->output_mtu)
|
|
||||||
|
|
||||||
// lookup frame
|
|
||||||
struct FragmentProtoAssembler_frame *frame = FPAFramesTree_LookupExact(&o->frames_used_tree, 0, frame_id);
|
|
||||||
if (!frame) {
|
|
||||||
// frame not found, add a new one
|
|
||||||
frame = allocate_new_frame(o, frame_id);
|
|
||||||
} else {
|
|
||||||
// have existing frame with that ID
|
|
||||||
// check frame time
|
|
||||||
if (frame_is_timed_out(o, frame)) {
|
|
||||||
// frame is timed out, remove it and use a new one
|
|
||||||
PeerLog(o, BLOG_INFO, "freeing timed out frame (while processing chunk)");
|
|
||||||
free_frame(o, frame);
|
|
||||||
frame = allocate_new_frame(o, frame_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(frame->num_chunks < o->num_chunks)
|
|
||||||
|
|
||||||
// check if the chunk overlaps with any existing chunks
|
|
||||||
for (int i = 0; i < frame->num_chunks; i++) {
|
|
||||||
struct FragmentProtoAssembler_chunk *chunk = &frame->chunks[i];
|
|
||||||
if (chunks_overlap(chunk->start, chunk->len, chunk_start, chunk_len)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "chunk overlaps with existing chunk");
|
|
||||||
goto fail_frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_last) {
|
|
||||||
// this chunk is marked as last
|
|
||||||
if (frame->length >= 0) {
|
|
||||||
PeerLog(o, BLOG_INFO, "got last chunk, but already have one");
|
|
||||||
goto fail_frame;
|
|
||||||
}
|
|
||||||
// check if frame size according to this packet is consistent
|
|
||||||
// with existing chunks
|
|
||||||
if (frame->length_so_far > chunk_end) {
|
|
||||||
PeerLog(o, BLOG_INFO, "got last chunk, but already have data over its bound");
|
|
||||||
goto fail_frame;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// if we have length, chunk must be in its bound
|
|
||||||
if (frame->length >= 0) {
|
|
||||||
if (chunk_end > frame->length) {
|
|
||||||
PeerLog(o, BLOG_INFO, "chunk out of length bound");
|
|
||||||
goto fail_frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// chunk is good, add it
|
|
||||||
|
|
||||||
// update frame time
|
|
||||||
frame->time = o->time;
|
|
||||||
|
|
||||||
// add chunk entry
|
|
||||||
struct FragmentProtoAssembler_chunk *chunk = &frame->chunks[frame->num_chunks];
|
|
||||||
chunk->start = chunk_start;
|
|
||||||
chunk->len = chunk_len;
|
|
||||||
frame->num_chunks++;
|
|
||||||
|
|
||||||
// update sum
|
|
||||||
frame->sum += chunk_len;
|
|
||||||
|
|
||||||
// update length
|
|
||||||
if (is_last) {
|
|
||||||
frame->length = chunk_end;
|
|
||||||
} else {
|
|
||||||
if (frame->length < 0) {
|
|
||||||
if (frame->length_so_far < chunk_end) {
|
|
||||||
frame->length_so_far = chunk_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy chunk payload to buffer
|
|
||||||
memcpy(frame->buffer + chunk_start, payload, chunk_len);
|
|
||||||
|
|
||||||
// is frame incomplete?
|
|
||||||
if (frame->length < 0 || frame->sum < frame->length) {
|
|
||||||
// if all chunks are used, fail it
|
|
||||||
if (frame->num_chunks == o->num_chunks) {
|
|
||||||
PeerLog(o, BLOG_INFO, "all chunks used, but frame not complete");
|
|
||||||
goto fail_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for more chunks
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(frame->sum == frame->length)
|
|
||||||
|
|
||||||
PeerLog(o, BLOG_DEBUG, "frame complete");
|
|
||||||
|
|
||||||
// free frame entry
|
|
||||||
free_frame(o, frame);
|
|
||||||
|
|
||||||
// send frame
|
|
||||||
PacketPassInterface_Sender_Send(o->output, frame->buffer, frame->length);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail_frame:
|
|
||||||
free_frame(o, frame);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void process_input (FragmentProtoAssembler *o)
|
|
||||||
{
|
|
||||||
ASSERT(o->in_len >= 0)
|
|
||||||
|
|
||||||
// read chunks
|
|
||||||
while (o->in_pos < o->in_len) {
|
|
||||||
// obtain header
|
|
||||||
if (o->in_len - o->in_pos < sizeof(struct fragmentproto_chunk_header)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "too little data for chunk header");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
struct fragmentproto_chunk_header header;
|
|
||||||
memcpy(&header, o->in + o->in_pos, sizeof(header));
|
|
||||||
o->in_pos += sizeof(struct fragmentproto_chunk_header);
|
|
||||||
fragmentproto_frameid frame_id = ltoh16(header.frame_id);
|
|
||||||
int chunk_start = ltoh16(header.chunk_start);
|
|
||||||
int chunk_len = ltoh16(header.chunk_len);
|
|
||||||
int is_last = ltoh8(header.is_last);
|
|
||||||
|
|
||||||
// check is_last field
|
|
||||||
if (!(is_last == 0 || is_last == 1)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "chunk is_last wrong");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// obtain data
|
|
||||||
if (o->in_len - o->in_pos < chunk_len) {
|
|
||||||
PeerLog(o, BLOG_INFO, "too little data for chunk data");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// process chunk
|
|
||||||
int res = process_chunk(o, frame_id, chunk_start, chunk_len, is_last, o->in + o->in_pos);
|
|
||||||
o->in_pos += chunk_len;
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
// sending complete frame, stop processing input
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment packet time
|
|
||||||
if (o->time == FPA_MAX_TIME) {
|
|
||||||
reduce_times(o);
|
|
||||||
if (!LinkedList1_IsEmpty(&o->frames_used)) {
|
|
||||||
ASSERT(o->time < FPA_MAX_TIME) // If there was a frame with zero time, it was removed because
|
|
||||||
// time_tolerance < FPA_MAX_TIME. So something >0 was subtracted.
|
|
||||||
o->time++;
|
|
||||||
} else {
|
|
||||||
// it was set to zero by reduce_times
|
|
||||||
ASSERT(o->time == 0)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
o->time++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set no input packet
|
|
||||||
o->in_len = -1;
|
|
||||||
|
|
||||||
// finish input
|
|
||||||
PacketPassInterface_Done(&o->input);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void input_handler_send (FragmentProtoAssembler *o, uint8_t *data, int data_len)
|
|
||||||
{
|
|
||||||
ASSERT(data_len >= 0)
|
|
||||||
ASSERT(o->in_len == -1)
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// save input packet
|
|
||||||
o->in_len = data_len;
|
|
||||||
o->in = data;
|
|
||||||
o->in_pos = 0;
|
|
||||||
|
|
||||||
process_input(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void output_handler_done (FragmentProtoAssembler *o)
|
|
||||||
{
|
|
||||||
ASSERT(o->in_len >= 0)
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
process_input(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
int FragmentProtoAssembler_Init (FragmentProtoAssembler *o, int input_mtu, PacketPassInterface *output, int num_frames, int num_chunks, BPendingGroup *pg, void *user, BLog_logfunc logfunc)
|
|
||||||
{
|
|
||||||
ASSERT(input_mtu >= 0)
|
|
||||||
ASSERT(num_frames > 0)
|
|
||||||
ASSERT(num_frames < FPA_MAX_TIME) // needed so we can always subtract times when packet time is maximum
|
|
||||||
ASSERT(num_chunks > 0)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->output = output;
|
|
||||||
o->num_chunks = num_chunks;
|
|
||||||
o->user = user;
|
|
||||||
o->logfunc = logfunc;
|
|
||||||
|
|
||||||
// init input
|
|
||||||
PacketPassInterface_Init(&o->input, input_mtu, (PacketPassInterface_handler_send)input_handler_send, o, pg);
|
|
||||||
|
|
||||||
// init output
|
|
||||||
PacketPassInterface_Sender_Init(o->output, (PacketPassInterface_handler_done)output_handler_done, o);
|
|
||||||
|
|
||||||
// remebmer output MTU
|
|
||||||
o->output_mtu = PacketPassInterface_GetMTU(o->output);
|
|
||||||
|
|
||||||
// set packet time to zero
|
|
||||||
o->time = 0;
|
|
||||||
|
|
||||||
// set time tolerance to num_frames
|
|
||||||
o->time_tolerance = num_frames;
|
|
||||||
|
|
||||||
// allocate frames
|
|
||||||
if (!(o->frames_entries = (struct FragmentProtoAssembler_frame *)BAllocArray(num_frames, sizeof(o->frames_entries[0])))) {
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate chunks
|
|
||||||
if (!(o->frames_chunks = (struct FragmentProtoAssembler_chunk *)BAllocArray2(num_frames, o->num_chunks, sizeof(o->frames_chunks[0])))) {
|
|
||||||
goto fail2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate buffers
|
|
||||||
if (!(o->frames_buffer = (uint8_t *)BAllocArray(num_frames, o->output_mtu))) {
|
|
||||||
goto fail3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init frame lists
|
|
||||||
LinkedList1_Init(&o->frames_free);
|
|
||||||
LinkedList1_Init(&o->frames_used);
|
|
||||||
|
|
||||||
// initialize frame entries
|
|
||||||
for (int i = 0; i < num_frames; i++) {
|
|
||||||
struct FragmentProtoAssembler_frame *frame = &o->frames_entries[i];
|
|
||||||
// set chunks array pointer
|
|
||||||
frame->chunks = o->frames_chunks + (size_t)i * o->num_chunks;
|
|
||||||
// set buffer pointer
|
|
||||||
frame->buffer = o->frames_buffer + (size_t)i * o->output_mtu;
|
|
||||||
// add to free list
|
|
||||||
LinkedList1_Append(&o->frames_free, &frame->list_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// init tree
|
|
||||||
FPAFramesTree_Init(&o->frames_used_tree);
|
|
||||||
|
|
||||||
// have no input packet
|
|
||||||
o->in_len = -1;
|
|
||||||
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail3:
|
|
||||||
BFree(o->frames_chunks);
|
|
||||||
fail2:
|
|
||||||
BFree(o->frames_entries);
|
|
||||||
fail1:
|
|
||||||
PacketPassInterface_Free(&o->input);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FragmentProtoAssembler_Free (FragmentProtoAssembler *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
|
|
||||||
// free buffers
|
|
||||||
BFree(o->frames_buffer);
|
|
||||||
|
|
||||||
// free chunks
|
|
||||||
BFree(o->frames_chunks);
|
|
||||||
|
|
||||||
// free frames
|
|
||||||
BFree(o->frames_entries);
|
|
||||||
|
|
||||||
// free input
|
|
||||||
PacketPassInterface_Free(&o->input);
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketPassInterface * FragmentProtoAssembler_GetInput (FragmentProtoAssembler *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
return &o->input;
|
|
||||||
}
|
|
|
@ -1,134 +0,0 @@
|
||||||
/**
|
|
||||||
* @file FragmentProtoAssembler.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* Object which decodes packets according to FragmentProto.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_CLIENT_FRAGMENTPROTOASSEMBLER_H
|
|
||||||
#define BADVPN_CLIENT_FRAGMENTPROTOASSEMBLER_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <protocol/fragmentproto.h>
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <misc/compare.h>
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
#include <base/BLog.h>
|
|
||||||
#include <structure/LinkedList1.h>
|
|
||||||
#include <structure/SAvl.h>
|
|
||||||
#include <flow/PacketPassInterface.h>
|
|
||||||
|
|
||||||
#define FPA_MAX_TIME UINT32_MAX
|
|
||||||
|
|
||||||
struct FragmentProtoAssembler_frame;
|
|
||||||
|
|
||||||
#include "FragmentProtoAssembler_tree.h"
|
|
||||||
#include <structure/SAvl_decl.h>
|
|
||||||
|
|
||||||
struct FragmentProtoAssembler_chunk {
|
|
||||||
int start;
|
|
||||||
int len;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FragmentProtoAssembler_frame {
|
|
||||||
LinkedList1Node list_node; // node in free or used list
|
|
||||||
struct FragmentProtoAssembler_chunk *chunks; // array of chunks, up to num_chunks
|
|
||||||
uint8_t *buffer; // buffer with frame data, size output_mtu
|
|
||||||
// everything below only defined when frame entry is used
|
|
||||||
fragmentproto_frameid id; // frame identifier
|
|
||||||
uint32_t time; // packet time when the last chunk was received
|
|
||||||
FPAFramesTreeNode tree_node; // node fields in tree for searching frames by id
|
|
||||||
int num_chunks; // number of valid chunks
|
|
||||||
int sum; // sum of all chunks' lengths
|
|
||||||
int length; // length of the frame, or -1 if not yet known
|
|
||||||
int length_so_far; // if length=-1, current data set's upper bound
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object which decodes packets according to FragmentProto.
|
|
||||||
*
|
|
||||||
* Input is with {@link PacketPassInterface}.
|
|
||||||
* Output is with {@link PacketPassInterface}.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
void *user;
|
|
||||||
BLog_logfunc logfunc;
|
|
||||||
PacketPassInterface input;
|
|
||||||
PacketPassInterface *output;
|
|
||||||
int output_mtu;
|
|
||||||
int num_chunks;
|
|
||||||
uint32_t time;
|
|
||||||
int time_tolerance;
|
|
||||||
struct FragmentProtoAssembler_frame *frames_entries;
|
|
||||||
struct FragmentProtoAssembler_chunk *frames_chunks;
|
|
||||||
uint8_t *frames_buffer;
|
|
||||||
LinkedList1 frames_free;
|
|
||||||
LinkedList1 frames_used;
|
|
||||||
FPAFramesTree frames_used_tree;
|
|
||||||
int in_len;
|
|
||||||
uint8_t *in;
|
|
||||||
int in_pos;
|
|
||||||
DebugObject d_obj;
|
|
||||||
} FragmentProtoAssembler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the object.
|
|
||||||
* {@link BLog_Init} must have been done.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param input_mtu maximum input packet size. Must be >=0.
|
|
||||||
* @param output output interface
|
|
||||||
* @param num_frames number of frames we can hold. Must be >0 and < FPA_MAX_TIME.
|
|
||||||
* To make the assembler tolerate out-of-order input of degree D, set to D+2.
|
|
||||||
* Here, D is the minimum size of a hypothetical buffer needed to order the input.
|
|
||||||
* @param num_chunks maximum number of chunks a frame can come in. Must be >0.
|
|
||||||
* @param pg pending group
|
|
||||||
* @param user argument to handlers
|
|
||||||
* @param logfunc function which prepends the log prefix using {@link BLog_Append}
|
|
||||||
* @return 1 on success, 0 on failure
|
|
||||||
*/
|
|
||||||
int FragmentProtoAssembler_Init (FragmentProtoAssembler *o, int input_mtu, PacketPassInterface *output, int num_frames, int num_chunks, BPendingGroup *pg, void *user, BLog_logfunc logfunc) WARN_UNUSED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the object.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void FragmentProtoAssembler_Free (FragmentProtoAssembler *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the input interface.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @return input interface
|
|
||||||
*/
|
|
||||||
PacketPassInterface * FragmentProtoAssembler_GetInput (FragmentProtoAssembler *o);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,9 +0,0 @@
|
||||||
#define SAVL_PARAM_NAME FPAFramesTree
|
|
||||||
#define SAVL_PARAM_FEATURE_COUNTS 0
|
|
||||||
#define SAVL_PARAM_FEATURE_NOKEYS 0
|
|
||||||
#define SAVL_PARAM_TYPE_ENTRY struct FragmentProtoAssembler_frame
|
|
||||||
#define SAVL_PARAM_TYPE_KEY fragmentproto_frameid
|
|
||||||
#define SAVL_PARAM_TYPE_ARG int
|
|
||||||
#define SAVL_PARAM_FUN_COMPARE_ENTRIES(arg, entry1, entry2) B_COMPARE((entry1)->id, (entry2)->id)
|
|
||||||
#define SAVL_PARAM_FUN_COMPARE_KEY_ENTRY(arg, key1, entry2) B_COMPARE((key1), (entry2)->id)
|
|
||||||
#define SAVL_PARAM_MEMBER_NODE tree_node
|
|
|
@ -1,229 +0,0 @@
|
||||||
/**
|
|
||||||
* @file FragmentProtoDisassembler.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <misc/byteorder.h>
|
|
||||||
#include <misc/minmax.h>
|
|
||||||
|
|
||||||
#include "client/FragmentProtoDisassembler.h"
|
|
||||||
|
|
||||||
static void write_chunks (FragmentProtoDisassembler *o)
|
|
||||||
{
|
|
||||||
#define IN_AVAIL (o->in_len - o->in_used)
|
|
||||||
#define OUT_AVAIL ((o->output_mtu - o->out_used) - (int)sizeof(struct fragmentproto_chunk_header))
|
|
||||||
|
|
||||||
ASSERT(o->in_len >= 0)
|
|
||||||
ASSERT(o->out)
|
|
||||||
ASSERT(OUT_AVAIL > 0)
|
|
||||||
|
|
||||||
// write chunks to output packet
|
|
||||||
do {
|
|
||||||
// calculate chunk length
|
|
||||||
int chunk_len = bmin_int(IN_AVAIL, OUT_AVAIL);
|
|
||||||
if (o->chunk_mtu > 0) {
|
|
||||||
chunk_len = bmin_int(chunk_len, o->chunk_mtu);
|
|
||||||
}
|
|
||||||
|
|
||||||
// write chunk header
|
|
||||||
struct fragmentproto_chunk_header header;
|
|
||||||
header.frame_id = htol16(o->frame_id);
|
|
||||||
header.chunk_start = htol16(o->in_used);
|
|
||||||
header.chunk_len = htol16(chunk_len);
|
|
||||||
header.is_last = (chunk_len == IN_AVAIL);
|
|
||||||
memcpy(o->out + o->out_used, &header, sizeof(header));
|
|
||||||
|
|
||||||
// write chunk data
|
|
||||||
memcpy(o->out + o->out_used + sizeof(struct fragmentproto_chunk_header), o->in + o->in_used, chunk_len);
|
|
||||||
|
|
||||||
// increment pointers
|
|
||||||
o->in_used += chunk_len;
|
|
||||||
o->out_used += sizeof(struct fragmentproto_chunk_header) + chunk_len;
|
|
||||||
} while (IN_AVAIL > 0 && OUT_AVAIL > 0);
|
|
||||||
|
|
||||||
// have we finished the input packet?
|
|
||||||
if (IN_AVAIL == 0) {
|
|
||||||
// set no input packet
|
|
||||||
o->in_len = -1;
|
|
||||||
|
|
||||||
// increment frame ID
|
|
||||||
o->frame_id++;
|
|
||||||
|
|
||||||
// finish input
|
|
||||||
PacketPassInterface_Done(&o->input);
|
|
||||||
}
|
|
||||||
|
|
||||||
// should we finish the output packet?
|
|
||||||
if (OUT_AVAIL <= 0 || o->latency < 0) {
|
|
||||||
// set no output packet
|
|
||||||
o->out = NULL;
|
|
||||||
|
|
||||||
// stop timer (if it's running)
|
|
||||||
if (o->latency >= 0) {
|
|
||||||
BReactor_RemoveTimer(o->reactor, &o->timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// finish output
|
|
||||||
PacketRecvInterface_Done(&o->output, o->out_used);
|
|
||||||
} else {
|
|
||||||
// start timer if we have output and it's not running (output was empty before)
|
|
||||||
if (!BTimer_IsRunning(&o->timer)) {
|
|
||||||
BReactor_SetTimer(o->reactor, &o->timer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void input_handler_send (FragmentProtoDisassembler *o, uint8_t *data, int data_len)
|
|
||||||
{
|
|
||||||
ASSERT(data_len >= 0)
|
|
||||||
ASSERT(o->in_len == -1)
|
|
||||||
|
|
||||||
// set input packet
|
|
||||||
o->in_len = data_len;
|
|
||||||
o->in = data;
|
|
||||||
o->in_used = 0;
|
|
||||||
|
|
||||||
// if there is no output, wait for it
|
|
||||||
if (!o->out) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_chunks(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void input_handler_requestcancel (FragmentProtoDisassembler *o)
|
|
||||||
{
|
|
||||||
ASSERT(o->in_len >= 0)
|
|
||||||
ASSERT(!o->out)
|
|
||||||
|
|
||||||
// set no input packet
|
|
||||||
o->in_len = -1;
|
|
||||||
|
|
||||||
// finish input
|
|
||||||
PacketPassInterface_Done(&o->input);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void output_handler_recv (FragmentProtoDisassembler *o, uint8_t *data)
|
|
||||||
{
|
|
||||||
ASSERT(data)
|
|
||||||
ASSERT(!o->out)
|
|
||||||
|
|
||||||
// set output packet
|
|
||||||
o->out = data;
|
|
||||||
o->out_used = 0;
|
|
||||||
|
|
||||||
// if there is no input, wait for it
|
|
||||||
if (o->in_len < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_chunks(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void timer_handler (FragmentProtoDisassembler *o)
|
|
||||||
{
|
|
||||||
ASSERT(o->latency >= 0)
|
|
||||||
ASSERT(o->out)
|
|
||||||
ASSERT(o->in_len == -1)
|
|
||||||
|
|
||||||
// set no output packet
|
|
||||||
o->out = NULL;
|
|
||||||
|
|
||||||
// finish output
|
|
||||||
PacketRecvInterface_Done(&o->output, o->out_used);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FragmentProtoDisassembler_Init (FragmentProtoDisassembler *o, BReactor *reactor, int input_mtu, int output_mtu, int chunk_mtu, btime_t latency)
|
|
||||||
{
|
|
||||||
ASSERT(input_mtu >= 0)
|
|
||||||
ASSERT(input_mtu <= UINT16_MAX)
|
|
||||||
ASSERT(output_mtu > sizeof(struct fragmentproto_chunk_header))
|
|
||||||
ASSERT(chunk_mtu > 0 || chunk_mtu < 0)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->reactor = reactor;
|
|
||||||
o->output_mtu = output_mtu;
|
|
||||||
o->chunk_mtu = chunk_mtu;
|
|
||||||
o->latency = latency;
|
|
||||||
|
|
||||||
// init input
|
|
||||||
PacketPassInterface_Init(&o->input, input_mtu, (PacketPassInterface_handler_send)input_handler_send, o, BReactor_PendingGroup(reactor));
|
|
||||||
PacketPassInterface_EnableCancel(&o->input, (PacketPassInterface_handler_requestcancel)input_handler_requestcancel);
|
|
||||||
|
|
||||||
// init output
|
|
||||||
PacketRecvInterface_Init(&o->output, o->output_mtu, (PacketRecvInterface_handler_recv)output_handler_recv, o, BReactor_PendingGroup(reactor));
|
|
||||||
|
|
||||||
// init timer
|
|
||||||
if (o->latency >= 0) {
|
|
||||||
BTimer_Init(&o->timer, o->latency, (BTimer_handler)timer_handler, o);
|
|
||||||
}
|
|
||||||
|
|
||||||
// have no input packet
|
|
||||||
o->in_len = -1;
|
|
||||||
|
|
||||||
// have no output packet
|
|
||||||
o->out = NULL;
|
|
||||||
|
|
||||||
// start with zero frame ID
|
|
||||||
o->frame_id = 0;
|
|
||||||
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FragmentProtoDisassembler_Free (FragmentProtoDisassembler *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
|
|
||||||
// free timer
|
|
||||||
if (o->latency >= 0) {
|
|
||||||
BReactor_RemoveTimer(o->reactor, &o->timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// free output
|
|
||||||
PacketRecvInterface_Free(&o->output);
|
|
||||||
|
|
||||||
// free input
|
|
||||||
PacketPassInterface_Free(&o->input);
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketPassInterface * FragmentProtoDisassembler_GetInput (FragmentProtoDisassembler *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
return &o->input;
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketRecvInterface * FragmentProtoDisassembler_GetOutput (FragmentProtoDisassembler *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
return &o->output;
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
/**
|
|
||||||
* @file FragmentProtoDisassembler.h
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @section DESCRIPTION
|
|
||||||
*
|
|
||||||
* Object which encodes packets into packets composed of chunks
|
|
||||||
* according to FragmentProto.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BADVPN_CLIENT_CCPROTODISASSEMBLER_H
|
|
||||||
#define BADVPN_CLIENT_CCPROTODISASSEMBLER_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <protocol/fragmentproto.h>
|
|
||||||
#include <base/DebugObject.h>
|
|
||||||
#include <system/BReactor.h>
|
|
||||||
#include <system/BTime.h>
|
|
||||||
#include <flow/PacketPassInterface.h>
|
|
||||||
#include <flow/PacketRecvInterface.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object which encodes packets into packets composed of chunks
|
|
||||||
* according to FragmentProto.
|
|
||||||
*
|
|
||||||
* Input is with {@link PacketPassInterface}.
|
|
||||||
* Output is with {@link PacketRecvInterface}.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
BReactor *reactor;
|
|
||||||
int output_mtu;
|
|
||||||
int chunk_mtu;
|
|
||||||
btime_t latency;
|
|
||||||
PacketPassInterface input;
|
|
||||||
PacketRecvInterface output;
|
|
||||||
BTimer timer;
|
|
||||||
int in_len;
|
|
||||||
uint8_t *in;
|
|
||||||
int in_used;
|
|
||||||
uint8_t *out;
|
|
||||||
int out_used;
|
|
||||||
fragmentproto_frameid frame_id;
|
|
||||||
DebugObject d_obj;
|
|
||||||
} FragmentProtoDisassembler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the object.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @param reactor reactor we live in
|
|
||||||
* @param input_mtu maximum input packet size. Must be >=0 and <=UINT16_MAX.
|
|
||||||
* @param output_mtu maximum output packet size. Must be >sizeof(struct fragmentproto_chunk_header).
|
|
||||||
* @param chunk_mtu maximum chunk size. Must be >0, or <0 for no explicit limit.
|
|
||||||
* @param latency maximum time a pending output packet with some data can wait for more data
|
|
||||||
* before being sent out. If nonnegative, a timer will be used. If negative,
|
|
||||||
* packets will always be sent out immediately. If low latency is desired,
|
|
||||||
* prefer setting this to zero rather than negative.
|
|
||||||
*/
|
|
||||||
void FragmentProtoDisassembler_Init (FragmentProtoDisassembler *o, BReactor *reactor, int input_mtu, int output_mtu, int chunk_mtu, btime_t latency);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees the object.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
*/
|
|
||||||
void FragmentProtoDisassembler_Free (FragmentProtoDisassembler *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the input interface.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @return input interface
|
|
||||||
*/
|
|
||||||
PacketPassInterface * FragmentProtoDisassembler_GetInput (FragmentProtoDisassembler *o);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the output interface.
|
|
||||||
*
|
|
||||||
* @param o the object
|
|
||||||
* @return output interface
|
|
||||||
*/
|
|
||||||
PacketRecvInterface * FragmentProtoDisassembler_GetOutput (FragmentProtoDisassembler *o);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,795 +0,0 @@
|
||||||
/**
|
|
||||||
* @file FrameDecider.c
|
|
||||||
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
|
||||||
*
|
|
||||||
* @section LICENSE
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include <misc/debug.h>
|
|
||||||
#include <misc/offset.h>
|
|
||||||
#include <misc/balloc.h>
|
|
||||||
#include <misc/ethernet_proto.h>
|
|
||||||
#include <misc/ipv4_proto.h>
|
|
||||||
#include <misc/igmp_proto.h>
|
|
||||||
#include <misc/byteorder.h>
|
|
||||||
#include <misc/compare.h>
|
|
||||||
#include <misc/print_macros.h>
|
|
||||||
|
|
||||||
#include <client/FrameDecider.h>
|
|
||||||
|
|
||||||
#include <generated/blog_channel_FrameDecider.h>
|
|
||||||
|
|
||||||
#define DECIDE_STATE_NONE 1
|
|
||||||
#define DECIDE_STATE_UNICAST 2
|
|
||||||
#define DECIDE_STATE_FLOOD 3
|
|
||||||
#define DECIDE_STATE_MULTICAST 4
|
|
||||||
|
|
||||||
#define PeerLog(_o, ...) BLog_LogViaFunc((_o)->logfunc, (_o)->user, BLOG_CURRENT_CHANNEL, __VA_ARGS__)
|
|
||||||
|
|
||||||
static int compare_macs (const uint8_t *mac1, const uint8_t *mac2)
|
|
||||||
{
|
|
||||||
int c = memcmp(mac1, mac2, 6);
|
|
||||||
return B_COMPARE(c, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "FrameDecider_macs_tree.h"
|
|
||||||
#include <structure/SAvl_impl.h>
|
|
||||||
|
|
||||||
#include "FrameDecider_groups_tree.h"
|
|
||||||
#include <structure/SAvl_impl.h>
|
|
||||||
|
|
||||||
#include "FrameDecider_multicast_tree.h"
|
|
||||||
#include <structure/SAvl_impl.h>
|
|
||||||
|
|
||||||
static void add_mac_to_peer (FrameDeciderPeer *o, uint8_t *mac)
|
|
||||||
{
|
|
||||||
FrameDecider *d = o->d;
|
|
||||||
|
|
||||||
// locate entry in tree
|
|
||||||
struct _FrameDecider_mac_entry *e_entry = FDMacsTree_LookupExact(&d->macs_tree, 0, mac);
|
|
||||||
if (e_entry) {
|
|
||||||
if (e_entry->peer == o) {
|
|
||||||
// this is our MAC; only move it to the end of the used list
|
|
||||||
LinkedList1_Remove(&o->mac_entries_used, &e_entry->list_node);
|
|
||||||
LinkedList1_Append(&o->mac_entries_used, &e_entry->list_node);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// some other peer has that MAC; disassociate it
|
|
||||||
FDMacsTree_Remove(&d->macs_tree, 0, e_entry);
|
|
||||||
LinkedList1_Remove(&e_entry->peer->mac_entries_used, &e_entry->list_node);
|
|
||||||
LinkedList1_Append(&e_entry->peer->mac_entries_free, &e_entry->list_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// aquire MAC address entry, if there are no free ones reuse the oldest used one
|
|
||||||
LinkedList1Node *list_node;
|
|
||||||
struct _FrameDecider_mac_entry *entry;
|
|
||||||
if (list_node = LinkedList1_GetFirst(&o->mac_entries_free)) {
|
|
||||||
entry = UPPER_OBJECT(list_node, struct _FrameDecider_mac_entry, list_node);
|
|
||||||
ASSERT(entry->peer == o)
|
|
||||||
|
|
||||||
// remove from free
|
|
||||||
LinkedList1_Remove(&o->mac_entries_free, &entry->list_node);
|
|
||||||
} else {
|
|
||||||
list_node = LinkedList1_GetFirst(&o->mac_entries_used);
|
|
||||||
ASSERT(list_node)
|
|
||||||
entry = UPPER_OBJECT(list_node, struct _FrameDecider_mac_entry, list_node);
|
|
||||||
ASSERT(entry->peer == o)
|
|
||||||
|
|
||||||
// remove from used
|
|
||||||
FDMacsTree_Remove(&d->macs_tree, 0, entry);
|
|
||||||
LinkedList1_Remove(&o->mac_entries_used, &entry->list_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
PeerLog(o, BLOG_INFO, "adding MAC %02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8"", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
||||||
|
|
||||||
// set MAC in entry
|
|
||||||
memcpy(entry->mac, mac, sizeof(entry->mac));
|
|
||||||
|
|
||||||
// add to used
|
|
||||||
LinkedList1_Append(&o->mac_entries_used, &entry->list_node);
|
|
||||||
int res = FDMacsTree_Insert(&d->macs_tree, 0, entry, NULL);
|
|
||||||
ASSERT_EXECUTE(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t compute_sig_for_group (uint32_t group)
|
|
||||||
{
|
|
||||||
return hton32(ntoh32(group)&0x7FFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t compute_sig_for_mac (uint8_t *mac)
|
|
||||||
{
|
|
||||||
uint32_t sig;
|
|
||||||
memcpy(&sig, mac + 2, 4);
|
|
||||||
sig = hton32(ntoh32(sig)&0x7FFFFF);
|
|
||||||
return sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void add_to_multicast (FrameDecider *d, struct _FrameDecider_group_entry *group_entry)
|
|
||||||
{
|
|
||||||
// compute sig
|
|
||||||
uint32_t sig = compute_sig_for_group(group_entry->group);
|
|
||||||
|
|
||||||
struct _FrameDecider_group_entry *master = FDMulticastTree_LookupExact(&d->multicast_tree, 0, sig);
|
|
||||||
if (master) {
|
|
||||||
// use existing master
|
|
||||||
ASSERT(master->is_master)
|
|
||||||
|
|
||||||
// set not master
|
|
||||||
group_entry->is_master = 0;
|
|
||||||
|
|
||||||
// insert to list
|
|
||||||
LinkedList3Node_InitAfter(&group_entry->sig_list_node, &master->sig_list_node);
|
|
||||||
} else {
|
|
||||||
// make this entry master
|
|
||||||
|
|
||||||
// set master
|
|
||||||
group_entry->is_master = 1;
|
|
||||||
|
|
||||||
// set sig
|
|
||||||
group_entry->master.sig = sig;
|
|
||||||
|
|
||||||
// insert to multicast tree
|
|
||||||
int res = FDMulticastTree_Insert(&d->multicast_tree, 0, group_entry, NULL);
|
|
||||||
ASSERT_EXECUTE(res)
|
|
||||||
|
|
||||||
// init list node
|
|
||||||
LinkedList3Node_InitLonely(&group_entry->sig_list_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void remove_from_multicast (FrameDecider *d, struct _FrameDecider_group_entry *group_entry)
|
|
||||||
{
|
|
||||||
// compute sig
|
|
||||||
uint32_t sig = compute_sig_for_group(group_entry->group);
|
|
||||||
|
|
||||||
if (group_entry->is_master) {
|
|
||||||
// remove master from multicast tree
|
|
||||||
FDMulticastTree_Remove(&d->multicast_tree, 0, group_entry);
|
|
||||||
|
|
||||||
if (!LinkedList3Node_IsLonely(&group_entry->sig_list_node)) {
|
|
||||||
// at least one more group entry for this sig; make another entry the master
|
|
||||||
|
|
||||||
// get an entry
|
|
||||||
LinkedList3Node *list_node = LinkedList3Node_NextOrPrev(&group_entry->sig_list_node);
|
|
||||||
struct _FrameDecider_group_entry *newmaster = UPPER_OBJECT(list_node, struct _FrameDecider_group_entry, sig_list_node);
|
|
||||||
ASSERT(!newmaster->is_master)
|
|
||||||
|
|
||||||
// set master
|
|
||||||
newmaster->is_master = 1;
|
|
||||||
|
|
||||||
// set sig
|
|
||||||
newmaster->master.sig = sig;
|
|
||||||
|
|
||||||
// insert to multicast tree
|
|
||||||
int res = FDMulticastTree_Insert(&d->multicast_tree, 0, newmaster, NULL);
|
|
||||||
ASSERT_EXECUTE(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// free linked list node
|
|
||||||
LinkedList3Node_Free(&group_entry->sig_list_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void add_group_to_peer (FrameDeciderPeer *o, uint32_t group)
|
|
||||||
{
|
|
||||||
FrameDecider *d = o->d;
|
|
||||||
|
|
||||||
struct _FrameDecider_group_entry *group_entry = FDGroupsTree_LookupExact(&o->groups_tree, 0, group);
|
|
||||||
if (group_entry) {
|
|
||||||
// move to end of used list
|
|
||||||
LinkedList1_Remove(&o->group_entries_used, &group_entry->list_node);
|
|
||||||
LinkedList1_Append(&o->group_entries_used, &group_entry->list_node);
|
|
||||||
} else {
|
|
||||||
PeerLog(o, BLOG_INFO, "joined group %"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"",
|
|
||||||
((uint8_t *)&group)[0], ((uint8_t *)&group)[1], ((uint8_t *)&group)[2], ((uint8_t *)&group)[3]
|
|
||||||
);
|
|
||||||
|
|
||||||
// aquire group entry, if there are no free ones reuse the earliest used one
|
|
||||||
LinkedList1Node *node;
|
|
||||||
if (node = LinkedList1_GetFirst(&o->group_entries_free)) {
|
|
||||||
group_entry = UPPER_OBJECT(node, struct _FrameDecider_group_entry, list_node);
|
|
||||||
|
|
||||||
// remove from free list
|
|
||||||
LinkedList1_Remove(&o->group_entries_free, &group_entry->list_node);
|
|
||||||
} else {
|
|
||||||
node = LinkedList1_GetFirst(&o->group_entries_used);
|
|
||||||
ASSERT(node)
|
|
||||||
group_entry = UPPER_OBJECT(node, struct _FrameDecider_group_entry, list_node);
|
|
||||||
|
|
||||||
// remove from multicast
|
|
||||||
remove_from_multicast(d, group_entry);
|
|
||||||
|
|
||||||
// remove from peer's groups tree
|
|
||||||
FDGroupsTree_Remove(&o->groups_tree, 0, group_entry);
|
|
||||||
|
|
||||||
// remove from used list
|
|
||||||
LinkedList1_Remove(&o->group_entries_used, &group_entry->list_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add entry to used list
|
|
||||||
LinkedList1_Append(&o->group_entries_used, &group_entry->list_node);
|
|
||||||
|
|
||||||
// set group address
|
|
||||||
group_entry->group = group;
|
|
||||||
|
|
||||||
// insert to peer's groups tree
|
|
||||||
int res = FDGroupsTree_Insert(&o->groups_tree, 0, group_entry, NULL);
|
|
||||||
ASSERT_EXECUTE(res)
|
|
||||||
|
|
||||||
// add to multicast
|
|
||||||
add_to_multicast(d, group_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set timer
|
|
||||||
group_entry->timer_endtime = btime_gettime() + d->igmp_group_membership_interval;
|
|
||||||
BReactor_SetTimerAbsolute(d->reactor, &group_entry->timer, group_entry->timer_endtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void remove_group_entry (struct _FrameDecider_group_entry *group_entry)
|
|
||||||
{
|
|
||||||
FrameDeciderPeer *peer = group_entry->peer;
|
|
||||||
FrameDecider *d = peer->d;
|
|
||||||
|
|
||||||
uint32_t group = group_entry->group;
|
|
||||||
|
|
||||||
PeerLog(peer, BLOG_INFO, "left group %"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"",
|
|
||||||
((uint8_t *)&group)[0], ((uint8_t *)&group)[1], ((uint8_t *)&group)[2], ((uint8_t *)&group)[3]
|
|
||||||
);
|
|
||||||
|
|
||||||
// remove from multicast
|
|
||||||
remove_from_multicast(d, group_entry);
|
|
||||||
|
|
||||||
// remove from peer's groups tree
|
|
||||||
FDGroupsTree_Remove(&peer->groups_tree, 0, group_entry);
|
|
||||||
|
|
||||||
// remove from used list
|
|
||||||
LinkedList1_Remove(&peer->group_entries_used, &group_entry->list_node);
|
|
||||||
|
|
||||||
// add to free list
|
|
||||||
LinkedList1_Append(&peer->group_entries_free, &group_entry->list_node);
|
|
||||||
|
|
||||||
// stop timer
|
|
||||||
BReactor_RemoveTimer(d->reactor, &group_entry->timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lower_group_timers_to_lmqt (FrameDecider *d, uint32_t group)
|
|
||||||
{
|
|
||||||
// have to lower all the group timers of this group down to LMQT
|
|
||||||
|
|
||||||
// compute sig
|
|
||||||
uint32_t sig = compute_sig_for_group(group);
|
|
||||||
|
|
||||||
// look up the sig in multicast tree
|
|
||||||
struct _FrameDecider_group_entry *master = FDMulticastTree_LookupExact(&d->multicast_tree, 0, sig);
|
|
||||||
if (!master) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ASSERT(master->is_master)
|
|
||||||
|
|
||||||
// iterate all group entries with this sig
|
|
||||||
LinkedList3Iterator it;
|
|
||||||
LinkedList3Iterator_Init(&it, LinkedList3Node_First(&master->sig_list_node), 1);
|
|
||||||
LinkedList3Node *sig_list_node;
|
|
||||||
while (sig_list_node = LinkedList3Iterator_Next(&it)) {
|
|
||||||
struct _FrameDecider_group_entry *group_entry = UPPER_OBJECT(sig_list_node, struct _FrameDecider_group_entry, sig_list_node);
|
|
||||||
|
|
||||||
// skip wrong groups
|
|
||||||
if (group_entry->group != group) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// lower timer down to LMQT
|
|
||||||
btime_t now = btime_gettime();
|
|
||||||
if (group_entry->timer_endtime > now + d->igmp_last_member_query_time) {
|
|
||||||
group_entry->timer_endtime = now + d->igmp_last_member_query_time;
|
|
||||||
BReactor_SetTimerAbsolute(d->reactor, &group_entry->timer, group_entry->timer_endtime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void group_entry_timer_handler (struct _FrameDecider_group_entry *group_entry)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&group_entry->peer->d_obj);
|
|
||||||
|
|
||||||
remove_group_entry(group_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrameDecider_Init (FrameDecider *o, int max_peer_macs, int max_peer_groups, btime_t igmp_group_membership_interval, btime_t igmp_last_member_query_time, BReactor *reactor)
|
|
||||||
{
|
|
||||||
ASSERT(max_peer_macs > 0)
|
|
||||||
ASSERT(max_peer_groups > 0)
|
|
||||||
|
|
||||||
// init arguments
|
|
||||||
o->max_peer_macs = max_peer_macs;
|
|
||||||
o->max_peer_groups = max_peer_groups;
|
|
||||||
o->igmp_group_membership_interval = igmp_group_membership_interval;
|
|
||||||
o->igmp_last_member_query_time = igmp_last_member_query_time;
|
|
||||||
o->reactor = reactor;
|
|
||||||
|
|
||||||
// init peers list
|
|
||||||
LinkedList1_Init(&o->peers_list);
|
|
||||||
|
|
||||||
// init MAC tree
|
|
||||||
FDMacsTree_Init(&o->macs_tree);
|
|
||||||
|
|
||||||
// init multicast tree
|
|
||||||
FDMulticastTree_Init(&o->multicast_tree);
|
|
||||||
|
|
||||||
// init decide state
|
|
||||||
o->decide_state = DECIDE_STATE_NONE;
|
|
||||||
|
|
||||||
// set no current flood peer
|
|
||||||
o->decide_flood_current = NULL;
|
|
||||||
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrameDecider_Free (FrameDecider *o)
|
|
||||||
{
|
|
||||||
ASSERT(FDMulticastTree_IsEmpty(&o->multicast_tree))
|
|
||||||
ASSERT(FDMacsTree_IsEmpty(&o->macs_tree))
|
|
||||||
ASSERT(LinkedList1_IsEmpty(&o->peers_list))
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrameDecider_AnalyzeAndDecide (FrameDecider *o, const uint8_t *frame, int frame_len)
|
|
||||||
{
|
|
||||||
ASSERT(frame_len >= 0)
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
// reset decide state
|
|
||||||
switch (o->decide_state) {
|
|
||||||
case DECIDE_STATE_NONE:
|
|
||||||
break;
|
|
||||||
case DECIDE_STATE_UNICAST:
|
|
||||||
break;
|
|
||||||
case DECIDE_STATE_FLOOD:
|
|
||||||
break;
|
|
||||||
case DECIDE_STATE_MULTICAST:
|
|
||||||
LinkedList3Iterator_Free(&o->decide_multicast_it);
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
ASSERT(0);
|
|
||||||
}
|
|
||||||
o->decide_state = DECIDE_STATE_NONE;
|
|
||||||
o->decide_flood_current = NULL;
|
|
||||||
|
|
||||||
// analyze frame
|
|
||||||
|
|
||||||
const uint8_t *pos = frame;
|
|
||||||
int len = frame_len;
|
|
||||||
|
|
||||||
if (len < sizeof(struct ethernet_header)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct ethernet_header eh;
|
|
||||||
memcpy(&eh, pos, sizeof(eh));
|
|
||||||
pos += sizeof(struct ethernet_header);
|
|
||||||
len -= sizeof(struct ethernet_header);
|
|
||||||
|
|
||||||
int is_igmp = 0;
|
|
||||||
|
|
||||||
switch (ntoh16(eh.type)) {
|
|
||||||
case ETHERTYPE_IPV4: {
|
|
||||||
// check IPv4 header
|
|
||||||
struct ipv4_header ipv4_header;
|
|
||||||
if (!ipv4_check((uint8_t *)pos, len, &ipv4_header, (uint8_t **)&pos, &len)) {
|
|
||||||
BLog(BLOG_INFO, "decide: wrong IP packet");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if it's IGMP
|
|
||||||
if (ntoh8(ipv4_header.protocol) != IPV4_PROTOCOL_IGMP) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember that it's IGMP; we have to flood IGMP frames
|
|
||||||
is_igmp = 1;
|
|
||||||
|
|
||||||
// check IGMP header
|
|
||||||
if (len < sizeof(struct igmp_base)) {
|
|
||||||
BLog(BLOG_INFO, "decide: IGMP: short packet");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
struct igmp_base igmp_base;
|
|
||||||
memcpy(&igmp_base, pos, sizeof(igmp_base));
|
|
||||||
pos += sizeof(struct igmp_base);
|
|
||||||
len -= sizeof(struct igmp_base);
|
|
||||||
|
|
||||||
switch (ntoh8(igmp_base.type)) {
|
|
||||||
case IGMP_TYPE_MEMBERSHIP_QUERY: {
|
|
||||||
if (len == sizeof(struct igmp_v2_extra) && ntoh8(igmp_base.max_resp_code) != 0) {
|
|
||||||
// V2 query
|
|
||||||
struct igmp_v2_extra query;
|
|
||||||
memcpy(&query, pos, sizeof(query));
|
|
||||||
pos += sizeof(struct igmp_v2_extra);
|
|
||||||
len -= sizeof(struct igmp_v2_extra);
|
|
||||||
|
|
||||||
if (ntoh32(query.group) != 0) {
|
|
||||||
// got a Group-Specific Query, lower group timers to LMQT
|
|
||||||
lower_group_timers_to_lmqt(o, query.group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (len >= sizeof(struct igmp_v3_query_extra)) {
|
|
||||||
// V3 query
|
|
||||||
struct igmp_v3_query_extra query;
|
|
||||||
memcpy(&query, pos, sizeof(query));
|
|
||||||
pos += sizeof(struct igmp_v3_query_extra);
|
|
||||||
len -= sizeof(struct igmp_v3_query_extra);
|
|
||||||
|
|
||||||
// iterate sources
|
|
||||||
uint16_t num_sources = ntoh16(query.number_of_sources);
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < num_sources; i++) {
|
|
||||||
// check source
|
|
||||||
if (len < sizeof(struct igmp_source)) {
|
|
||||||
BLog(BLOG_NOTICE, "decide: IGMP: short source");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
pos += sizeof(struct igmp_source);
|
|
||||||
len -= sizeof(struct igmp_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntoh32(query.group) != 0 && num_sources == 0) {
|
|
||||||
// got a Group-Specific Query, lower group timers to LMQT
|
|
||||||
lower_group_timers_to_lmqt(o, query.group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:;
|
|
||||||
|
|
||||||
const uint8_t broadcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
||||||
const uint8_t multicast_mac_header[] = {0x01, 0x00, 0x5e};
|
|
||||||
|
|
||||||
// if it's broadcast or IGMP, flood it
|
|
||||||
if (is_igmp || !memcmp(eh.dest, broadcast_mac, sizeof(broadcast_mac))) {
|
|
||||||
o->decide_state = DECIDE_STATE_FLOOD;
|
|
||||||
o->decide_flood_current = LinkedList1_GetFirst(&o->peers_list);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if it's multicast, forward to all peers with the given sig
|
|
||||||
if (!memcmp(eh.dest, multicast_mac_header, sizeof(multicast_mac_header))) {
|
|
||||||
// extract group's sig from destination MAC
|
|
||||||
uint32_t sig = compute_sig_for_mac(eh.dest);
|
|
||||||
|
|
||||||
// look up the sig in multicast tree
|
|
||||||
struct _FrameDecider_group_entry *master = FDMulticastTree_LookupExact(&o->multicast_tree, 0, sig);
|
|
||||||
if (master) {
|
|
||||||
ASSERT(master->is_master)
|
|
||||||
|
|
||||||
o->decide_state = DECIDE_STATE_MULTICAST;
|
|
||||||
LinkedList3Iterator_Init(&o->decide_multicast_it, LinkedList3Node_First(&master->sig_list_node), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// look for MAC entry
|
|
||||||
struct _FrameDecider_mac_entry *entry = FDMacsTree_LookupExact(&o->macs_tree, 0, eh.dest);
|
|
||||||
if (entry) {
|
|
||||||
o->decide_state = DECIDE_STATE_UNICAST;
|
|
||||||
o->decide_unicast_peer = entry->peer;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unknown destination MAC, flood
|
|
||||||
o->decide_state = DECIDE_STATE_FLOOD;
|
|
||||||
o->decide_flood_current = LinkedList1_GetFirst(&o->peers_list);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameDeciderPeer * FrameDecider_NextDestination (FrameDecider *o)
|
|
||||||
{
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
switch (o->decide_state) {
|
|
||||||
case DECIDE_STATE_NONE: {
|
|
||||||
return NULL;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case DECIDE_STATE_UNICAST: {
|
|
||||||
o->decide_state = DECIDE_STATE_NONE;
|
|
||||||
|
|
||||||
return o->decide_unicast_peer;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case DECIDE_STATE_FLOOD: {
|
|
||||||
if (!o->decide_flood_current) {
|
|
||||||
o->decide_state = DECIDE_STATE_NONE;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LinkedList1Node *list_node = o->decide_flood_current;
|
|
||||||
o->decide_flood_current = LinkedList1Node_Next(o->decide_flood_current);
|
|
||||||
|
|
||||||
FrameDeciderPeer *peer = UPPER_OBJECT(list_node, FrameDeciderPeer, list_node);
|
|
||||||
|
|
||||||
return peer;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case DECIDE_STATE_MULTICAST: {
|
|
||||||
LinkedList3Node *list_node = LinkedList3Iterator_Next(&o->decide_multicast_it);
|
|
||||||
if (!list_node) {
|
|
||||||
o->decide_state = DECIDE_STATE_NONE;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
struct _FrameDecider_group_entry *group_entry = UPPER_OBJECT(list_node, struct _FrameDecider_group_entry, sig_list_node);
|
|
||||||
|
|
||||||
return group_entry->peer;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ASSERT(0);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int FrameDeciderPeer_Init (FrameDeciderPeer *o, FrameDecider *d, void *user, BLog_logfunc logfunc)
|
|
||||||
{
|
|
||||||
// init arguments
|
|
||||||
o->d = d;
|
|
||||||
o->user = user;
|
|
||||||
o->logfunc = logfunc;
|
|
||||||
|
|
||||||
// allocate MAC entries
|
|
||||||
if (!(o->mac_entries = (struct _FrameDecider_mac_entry *)BAllocArray(d->max_peer_macs, sizeof(struct _FrameDecider_mac_entry)))) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "failed to allocate MAC entries");
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate group entries
|
|
||||||
if (!(o->group_entries = (struct _FrameDecider_group_entry *)BAllocArray(d->max_peer_groups, sizeof(struct _FrameDecider_group_entry)))) {
|
|
||||||
PeerLog(o, BLOG_ERROR, "failed to allocate group entries");
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert to peers list
|
|
||||||
LinkedList1_Append(&d->peers_list, &o->list_node);
|
|
||||||
|
|
||||||
// init MAC entry lists
|
|
||||||
LinkedList1_Init(&o->mac_entries_free);
|
|
||||||
LinkedList1_Init(&o->mac_entries_used);
|
|
||||||
|
|
||||||
// initialize MAC entries
|
|
||||||
for (int i = 0; i < d->max_peer_macs; i++) {
|
|
||||||
struct _FrameDecider_mac_entry *entry = &o->mac_entries[i];
|
|
||||||
|
|
||||||
// set peer
|
|
||||||
entry->peer = o;
|
|
||||||
|
|
||||||
// insert to free list
|
|
||||||
LinkedList1_Append(&o->mac_entries_free, &entry->list_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// init group entry lists
|
|
||||||
LinkedList1_Init(&o->group_entries_free);
|
|
||||||
LinkedList1_Init(&o->group_entries_used);
|
|
||||||
|
|
||||||
// initialize group entries
|
|
||||||
for (int i = 0; i < d->max_peer_groups; i++) {
|
|
||||||
struct _FrameDecider_group_entry *entry = &o->group_entries[i];
|
|
||||||
|
|
||||||
// set peer
|
|
||||||
entry->peer = o;
|
|
||||||
|
|
||||||
// insert to free list
|
|
||||||
LinkedList1_Append(&o->group_entries_free, &entry->list_node);
|
|
||||||
|
|
||||||
// init timer
|
|
||||||
BTimer_Init(&entry->timer, 0, (BTimer_handler)group_entry_timer_handler, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize groups tree
|
|
||||||
FDGroupsTree_Init(&o->groups_tree);
|
|
||||||
|
|
||||||
DebugObject_Init(&o->d_obj);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail1:
|
|
||||||
BFree(o->mac_entries);
|
|
||||||
fail0:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrameDeciderPeer_Free (FrameDeciderPeer *o)
|
|
||||||
{
|
|
||||||
DebugObject_Free(&o->d_obj);
|
|
||||||
|
|
||||||
FrameDecider *d = o->d;
|
|
||||||
|
|
||||||
// remove decide unicast reference
|
|
||||||
if (d->decide_state == DECIDE_STATE_UNICAST && d->decide_unicast_peer == o) {
|
|
||||||
d->decide_state = DECIDE_STATE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LinkedList1Node *node;
|
|
||||||
|
|
||||||
// free group entries
|
|
||||||
for (node = LinkedList1_GetFirst(&o->group_entries_used); node; node = LinkedList1Node_Next(node)) {
|
|
||||||
struct _FrameDecider_group_entry *entry = UPPER_OBJECT(node, struct _FrameDecider_group_entry, list_node);
|
|
||||||
|
|
||||||
// remove from multicast
|
|
||||||
remove_from_multicast(d, entry);
|
|
||||||
|
|
||||||
// stop timer
|
|
||||||
BReactor_RemoveTimer(d->reactor, &entry->timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove used MAC entries from tree
|
|
||||||
for (node = LinkedList1_GetFirst(&o->mac_entries_used); node; node = LinkedList1Node_Next(node)) {
|
|
||||||
struct _FrameDecider_mac_entry *entry = UPPER_OBJECT(node, struct _FrameDecider_mac_entry, list_node);
|
|
||||||
|
|
||||||
// remove from tree
|
|
||||||
FDMacsTree_Remove(&d->macs_tree, 0, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove from peers list
|
|
||||||
if (d->decide_flood_current == &o->list_node) {
|
|
||||||
d->decide_flood_current = LinkedList1Node_Next(d->decide_flood_current);
|
|
||||||
}
|
|
||||||
LinkedList1_Remove(&d->peers_list, &o->list_node);
|
|
||||||
|
|
||||||
// free group entries
|
|
||||||
BFree(o->group_entries);
|
|
||||||
|
|
||||||
// free MAC entries
|
|
||||||
BFree(o->mac_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrameDeciderPeer_Analyze (FrameDeciderPeer *o, const uint8_t *frame, int frame_len)
|
|
||||||
{
|
|
||||||
ASSERT(frame_len >= 0)
|
|
||||||
DebugObject_Access(&o->d_obj);
|
|
||||||
|
|
||||||
const uint8_t *pos = frame;
|
|
||||||
int len = frame_len;
|
|
||||||
|
|
||||||
if (len < sizeof(struct ethernet_header)) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
struct ethernet_header eh;
|
|
||||||
memcpy(&eh, pos, sizeof(eh));
|
|
||||||
pos += sizeof(struct ethernet_header);
|
|
||||||
len -= sizeof(struct ethernet_header);
|
|
||||||
|
|
||||||
// register source MAC address with this peer
|
|
||||||
add_mac_to_peer(o, eh.source);
|
|
||||||
|
|
||||||
switch (ntoh16(eh.type)) {
|
|
||||||
case ETHERTYPE_IPV4: {
|
|
||||||
// check IPv4 header
|
|
||||||
struct ipv4_header ipv4_header;
|
|
||||||
if (!ipv4_check((uint8_t *)pos, len, &ipv4_header, (uint8_t **)&pos, &len)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "analyze: wrong IP packet");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if it's IGMP
|
|
||||||
if (ntoh8(ipv4_header.protocol) != IPV4_PROTOCOL_IGMP) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check IGMP header
|
|
||||||
if (len < sizeof(struct igmp_base)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "analyze: IGMP: short packet");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
struct igmp_base igmp_base;
|
|
||||||
memcpy(&igmp_base, pos, sizeof(igmp_base));
|
|
||||||
pos += sizeof(struct igmp_base);
|
|
||||||
len -= sizeof(struct igmp_base);
|
|
||||||
|
|
||||||
switch (ntoh8(igmp_base.type)) {
|
|
||||||
case IGMP_TYPE_V2_MEMBERSHIP_REPORT: {
|
|
||||||
// check extra
|
|
||||||
if (len < sizeof(struct igmp_v2_extra)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "analyze: IGMP: short v2 report");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
struct igmp_v2_extra report;
|
|
||||||
memcpy(&report, pos, sizeof(report));
|
|
||||||
pos += sizeof(struct igmp_v2_extra);
|
|
||||||
len -= sizeof(struct igmp_v2_extra);
|
|
||||||
|
|
||||||
// add to group
|
|
||||||
add_group_to_peer(o, report.group);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case IGMP_TYPE_V3_MEMBERSHIP_REPORT: {
|
|
||||||
// check extra
|
|
||||||
if (len < sizeof(struct igmp_v3_report_extra)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "analyze: IGMP: short v3 report");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
struct igmp_v3_report_extra report;
|
|
||||||
memcpy(&report, pos, sizeof(report));
|
|
||||||
pos += sizeof(struct igmp_v3_report_extra);
|
|
||||||
len -= sizeof(struct igmp_v3_report_extra);
|
|
||||||
|
|
||||||
// iterate records
|
|
||||||
uint16_t num_records = ntoh16(report.number_of_group_records);
|
|
||||||
for (int i = 0; i < num_records; i++) {
|
|
||||||
// check record
|
|
||||||
if (len < sizeof(struct igmp_v3_report_record)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "analyze: IGMP: short record header");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
struct igmp_v3_report_record record;
|
|
||||||
memcpy(&record, pos, sizeof(record));
|
|
||||||
pos += sizeof(struct igmp_v3_report_record);
|
|
||||||
len -= sizeof(struct igmp_v3_report_record);
|
|
||||||
|
|
||||||
// iterate sources
|
|
||||||
uint16_t num_sources = ntoh16(record.number_of_sources);
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < num_sources; j++) {
|
|
||||||
// check source
|
|
||||||
if (len < sizeof(struct igmp_source)) {
|
|
||||||
PeerLog(o, BLOG_INFO, "analyze: IGMP: short source");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
pos += sizeof(struct igmp_source);
|
|
||||||
len -= sizeof(struct igmp_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check aux data
|
|
||||||
uint16_t aux_len = ntoh16(record.aux_data_len);
|
|
||||||
if (len < aux_len) {
|
|
||||||
PeerLog(o, BLOG_INFO, "analyze: IGMP: short record aux data");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
pos += aux_len;
|
|
||||||
len -= aux_len;
|
|
||||||
|
|
||||||
switch (record.type) {
|
|
||||||
case IGMP_RECORD_TYPE_MODE_IS_INCLUDE:
|
|
||||||
case IGMP_RECORD_TYPE_CHANGE_TO_INCLUDE_MODE:
|
|
||||||
if (num_sources != 0) {
|
|
||||||
add_group_to_peer(o, record.group);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case IGMP_RECORD_TYPE_MODE_IS_EXCLUDE:
|
|
||||||
case IGMP_RECORD_TYPE_CHANGE_TO_EXCLUDE_MODE:
|
|
||||||
add_group_to_peer(o, record.group);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:;
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue