This commit is contained in:
snltty
2024-07-14 14:45:23 +08:00
parent aa65b16892
commit cfa6d18010
63 changed files with 1088 additions and 504 deletions

1
linker.doc.web Submodule

Submodule linker.doc.web added at 1207b6c05a

View File

@@ -119,7 +119,6 @@ namespace linker.tunnel
public async Task<ITunnelConnection> ConnectAsync(string remoteMachineId, string transactionId) public async Task<ITunnelConnection> ConnectAsync(string remoteMachineId, string transactionId)
{ {
if (connectingDic.TryAdd(remoteMachineId, true) == false) return null; if (connectingDic.TryAdd(remoteMachineId, true) == false) return null;
if (IsBackground(remoteMachineId, transactionId)) return null;
try try
{ {
@@ -394,15 +393,23 @@ namespace linker.tunnel
private ConcurrentDictionary<string, bool> backgroundDic = new ConcurrentDictionary<string, bool>(); private ConcurrentDictionary<string, bool> backgroundDic = new ConcurrentDictionary<string, bool>();
public void StartBackground(string remoteMachineId, string transactionId) /// <summary>
/// 开始后台打洞
/// </summary>
/// <param name="remoteMachineId"></param>
/// <param name="transactionId"></param>
public void StartBackground(string remoteMachineId, string transactionId,int times = 10)
{ {
if (IsBackground(remoteMachineId, transactionId)) return; if (AddBackground(remoteMachineId, transactionId) == false)
AddBackground(remoteMachineId, transactionId); {
LoggerHelper.Instance.Error($"tunnel background {remoteMachineId}@{transactionId} already exists");
return;
}
Task.Run(async () => Task.Run(async () =>
{ {
try try
{ {
for (int i = 0; i < 10; i++) for (int i = 0; i < times; i++)
{ {
await Task.Delay(3000); await Task.Delay(3000);
@@ -423,9 +430,9 @@ namespace linker.tunnel
}); });
} }
private void AddBackground(string remoteMachineId, string transactionId) private bool AddBackground(string remoteMachineId, string transactionId)
{ {
backgroundDic.TryAdd(GetBackgroundKey(remoteMachineId, transactionId), true); return backgroundDic.TryAdd(GetBackgroundKey(remoteMachineId, transactionId), true);
} }
private void RemoveBackground(string remoteMachineId, string transactionId) private void RemoveBackground(string remoteMachineId, string transactionId)
{ {

View File

@@ -115,16 +115,41 @@ namespace linker.tunnel.transport
public sealed partial class TunnelTransportItemInfo public sealed partial class TunnelTransportItemInfo
{ {
/// <summary>
/// 协议名称
/// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// 协议描述
/// </summary>
public string Label { get; set; } public string Label { get; set; }
/// <summary>
/// 协议
/// </summary>
public string ProtocolType { get; set; } public string ProtocolType { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool Disabled { get; set; } = false; public bool Disabled { get; set; } = false;
/// <summary>
/// 是否反向打洞
/// </summary>
public bool Reverse { get; set; } = true; public bool Reverse { get; set; } = true;
/// <summary>
/// 是否允许修改反向打洞状态
/// </summary>
public bool DisableReverse { get; set; } = false; public bool DisableReverse { get; set; } = false;
/// <summary>
/// 是否开启ssl
/// </summary>
public bool SSL { get; set; } = true; public bool SSL { get; set; } = true;
/// <summary>
/// 是否允许修改ssl配置
/// </summary>
public bool DisableSSL { get; set; } = false; public bool DisableSSL { get; set; } = false;
/// <summary>
/// 缓冲区大小
/// </summary>
public byte BufferSize { get; set; } = 4; public byte BufferSize { get; set; } = 4;
} }
public sealed class TunnelTransportItemInfoEqualityComparer : IEqualityComparer<TunnelTransportItemInfo> public sealed class TunnelTransportItemInfoEqualityComparer : IEqualityComparer<TunnelTransportItemInfo>
@@ -171,9 +196,13 @@ namespace linker.tunnel.transport
/// 需要加密 /// 需要加密
/// </summary> /// </summary>
public bool SSL { get; set; } public bool SSL { get; set; }
/// <summary>
/// 缓冲区
/// </summary>
public byte BufferSize { get; set; } = 3; public byte BufferSize { get; set; } = 3;
/// <summary>
/// 目标ip列表
/// </summary>
public List<IPEndPoint> RemoteEndPoints { get; set; } public List<IPEndPoint> RemoteEndPoints { get; set; }
} }

View File

@@ -0,0 +1,9 @@
import { sendWebsocketMsg } from './request'
export const getConfig = () => {
return sendWebsocketMsg('configclient/get');
}
export const install = (data) => {
return sendWebsocketMsg('configclient/install', data);
}

View File

@@ -1,8 +1,6 @@
import { sendWebsocketMsg } from './request' import { sendWebsocketMsg } from './request'
export const getConfig = () => {
return sendWebsocketMsg('signInclient/config');
}
export const setSignIn = (data) => { export const setSignIn = (data) => {
return sendWebsocketMsg('signInclient/set', data); return sendWebsocketMsg('signInclient/set', data);
} }
@@ -26,6 +24,3 @@ export const signInDel = (machineId) => {
export const setSignInName = (data) => { export const setSignInName = (data) => {
return sendWebsocketMsg('signInclient/setname', data); return sendWebsocketMsg('signInclient/setname', data);
} }
export const install = (data) => {
return sendWebsocketMsg('signInclient/install', data);
}

View File

@@ -0,0 +1,133 @@
<template>
<div>
<el-form ref="formDom" :model="state.form" :rules="state.rules" label-width="8rem">
<el-form-item label="" label-width="0">
<div class="t-c w-100">
<p>端口为0则不监听</p>
<p>相同分组名之间的客户端相互可见</p>
</div>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="机器名" prop="name">
<el-input v-model="state.form.name" maxlength="12" show-word-limit />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="分组名" prop="groupid">
<el-input v-model="state.form.groupid" maxlength="36" show-word-limit />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="接口端口" prop="api">
<el-input v-model="state.form.api" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="网页端口" prop="web">
<el-input v-model="state.form.web" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-form-item label="接口密码" prop="password">
<el-input type="password" v-model="state.form.password" show-password maxlength="36"
show-word-limit />
</el-form-item>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { injectGlobalData } from '@/provide';
import { reactive, watch, ref, inject, onMounted } from 'vue';
export default {
setup(props) {
const step = inject('step');
const globalData = injectGlobalData();
const state = reactive({
form: {
name: globalData.value.config.Client.Name,
groupid: globalData.value.config.Client.GroupId,
api: globalData.value.config.Client.CApi.ApiPort,
web: globalData.value.config.Client.CApi.WebPort,
password: globalData.value.config.Client.CApi.ApiPassword
},
rules: {
name: [{ required: true, message: "必填", trigger: "blur" }],
groupid: [{ required: true, message: "必填", trigger: "blur" }],
password: [{ required: true, message: "必填", trigger: "blur" }],
api: [
{ required: true, message: "必填", trigger: "blur" },
{
type: "number",
min: 0,
max: 65535,
message: "数字 0-65535",
trigger: "blur",
transform(value) {
return Number(value);
},
},
],
web: [
{ required: true, message: "必填", trigger: "blur" },
{
type: "number",
min: 0,
max: 65535,
message: "数字 0-65535",
trigger: "blur",
transform(value) {
return Number(value);
},
},
],
}
});
const formDom = ref(null);
const handleValidate = () => {
return new Promise((resolve, reject) => {
formDom.value.validate((valid) => {
if (valid) {
resolve({
Client:{
name: state.form.name,
groupid: state.form.groupid,
api: +state.form.api,
web: +state.form.web,
password: state.form.password
}
});
} else {
reject();
}
})
})
}
onMounted(()=>{
if(step.value.json.Common.client == false){
step.value.step +=step.value.increment;
}
})
return { state, handleValidate, formDom };
}
}
</script>
<style lang="stylus" scoped>
.body{
padding:1rem 0 0 0;
}
.footer{
padding: 1rem 0;
}
</style>

View File

@@ -0,0 +1,52 @@
<template>
<div class="t-c">
<el-checkbox v-model="state.form.client" label="作为客户端" />
<el-checkbox v-model="state.form.server" label="作为服务端" />
</div>
</template>
<script>
import {inject, reactive} from 'vue'
import {ElMessage} from 'element-plus'
export default {
name: 'Common',
setup () {
const step = inject('step');
const state = reactive({
form: {
client: (step.value.json.Common && step.value.json.Common.client) || false,
server: (step.value.json.Common && step.value.json.Common.server) || false,
}
});
const handleValidate = (prevJson) => {
return new Promise((resolve, reject) => {
if(!state.form.client && !state.form.server){
ElMessage.error('请选择客户端或服务端');
reject();
}else{
resolve({
Common:{
client: state.form.client,
server: state.form.server,
modes:[
state.form.client ? 'client' : '',
state.form.server ? 'server' : ''
].filter(c=>!!c)
}
});
}
});
}
return {
state,handleValidate
}
}
}
</script>
<style lang="stylus" scoped>
</style>

View File

@@ -2,215 +2,94 @@
<div> <div>
<el-dialog v-model="state.show" title="初始化配置" width="500" top="2vh"> <el-dialog v-model="state.show" title="初始化配置" width="500" top="2vh">
<div> <div>
<div class="head t-c"> <div class="head">
<el-checkbox v-model="state.form.client" label="客户端" /> <el-steps :active="step.step" finish-status="success">
<el-checkbox v-model="state.form.server" label="服务端" /> <template v-for="(item,index) in state.steps">
<el-step :title="item" />
</template>
</el-steps>
</div> </div>
<div class="body"> <div class="body">
<el-card shadow="never" v-if="state.form.client"> <el-card shadow="never" v-if="step.step == 1">
<template #header> <Common ref="currentDom"></Common>
<div class="card-header"><span>客户端</span></div>
</template>
<div>
<el-form ref="formDom" :model="state.form" :rules="state.rules" label-width="8rem">
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="机器名" prop="name">
<el-input v-model="state.form.name" maxlength="12" show-word-limit />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="分组名" prop="groupid">
<el-input v-model="state.form.groupid" maxlength="36" show-word-limit />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="接口端口" prop="api">
<el-input v-model="state.form.api" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="网页端口" prop="web">
<el-input v-model="state.form.web" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-form-item label="接口密码" prop="password">
<el-input type="password" v-model="state.form.password" show-password maxlength="36"
show-word-limit />
</el-form-item>
</el-form-item>
</el-form>
</div>
</el-card> </el-card>
<el-card shadow="never" v-if="state.form.server"> <el-card shadow="never" v-if="step.step == 2">
<template #header> <Server ref="currentDom"></Server>
<div class="card-header"><span>服务端</span></div>
</template>
<div>
<el-form ref="formDom" :model="state.form" :rules="state.rules" label-width="10rem">
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="服务端口" prop="servicePort">
<el-input v-model="state.form.servicePort" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="web穿透端口" prop="sforwardPort">
<el-input v-model="state.form.sforwardPort" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="开放最小端口" prop="sforwardPort1">
<el-input v-model="state.form.sforwardPort1" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="开放最大端口" prop="sforwardPort2">
<el-input v-model="state.form.sforwardPort2" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="穿透密钥" prop="sforwardKey">
<el-input v-model="state.form.sforwardKey" maxlength="36" show-word-limit />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="中继密钥" prop="relayKey">
<el-input v-model="state.form.relayKey" maxlength="36" show-word-limit />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
</el-form>
</div>
</el-card> </el-card>
<el-card shadow="never" v-if="step.step == 3">
<Client ref="currentDom"></Client>
</el-card>
<el-card shadow="never" v-if="step.step == 4">
<div class="t-c">完成保存后请重启软件</div>
</el-card>
</div>
<div class="footer t-c">
<el-button :disabled="step.step <= 1" @click="handlePrev">上一步</el-button>
<el-button v-if="step.step < state.steps.length" type="primary" @click="handleNext">下一步</el-button>
<el-button v-else type="primary" @click="handleSave">完成</el-button>
</div> </div>
</div> </div>
<template #footer>
<div class="dialog-footer t-c">
<el-button @click="state.show = false" :loading="state.loading">取消</el-button>
<el-button type="primary" @click="handleSave" :loading="state.loading">确定保存</el-button>
</div>
</template>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { injectGlobalData } from '@/provide'; import { injectGlobalData } from '@/provide';
import { install } from '@/apis/signin'; import { install } from '@/apis/config';
import { reactive, computed, watch, ref } from 'vue'; import { reactive, watch, ref, provide } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import Common from './Common.vue'
import Client from './Client.vue'
import Server from './Server.vue'
export default { export default {
components: { Common,Client,Server },
setup(props) { setup(props) {
const globalData = injectGlobalData(); const globalData = injectGlobalData();
const state = reactive({ const state = reactive({
show: false, show: false,
form: { steps:['选择模式','服务端','客户端','完成']
client: true,
server: true,
restart: false,
name: '',
groupid: '',
api: 0,
web: 0,
password: '',
relayKey:'',
sforwardKey:'',
servicePort:1802,
sforwardPort:80,
sforwardPort1:10000,
sforwardPort2:60000,
},
rules: {
name: [{ required: true, message: "必填", trigger: "blur" }],
groupid: [{ required: true, message: "必填", trigger: "blur" }],
password: [{ required: true, message: "必填", trigger: "blur" }],
api: [
{ required: true, message: "必填", trigger: "blur" },
{
type: "number",
min: 1,
max: 65535,
message: "数字 1-65535",
trigger: "blur",
transform(value) {
return Number(value);
},
},
],
web: [
{ required: true, message: "必填", trigger: "blur" },
{
type: "number",
min: 1,
max: 65535,
message: "数字 1-65535",
trigger: "blur",
transform(value) {
return Number(value);
},
},
],
},
loading: false,
}); });
watch(() => globalData.value.configed, (val) => { watch(() => globalData.value.configed, (val) => {
if (val) { if (val) {
state.show = globalData.value.connected && globalData.value.configed && !globalData.value.config.Client.GroupId; state.show = globalData.value.connected && globalData.value.configed && globalData.value.config.Common.Install == false;
state.form.name = globalData.value.config.Client.Name;
state.form.groupid = globalData.value.config.Client.GroupId;
state.form.api = globalData.value.config.Client.CApi.ApiPort;
state.form.web = globalData.value.config.Client.CApi.WebPort;
state.form.password = globalData.value.config.Client.CApi.ApiPassword;
} }
}) });
const formDom = ref(null); const currentDom = ref(null);
const handleSave = () => { const step = ref({
formDom.value.validate((valid) => { step:1,
if (valid == false) { increment:1,
return false; json:{}
} });
state.loading = true; provide('step',step);
install(state.form).then(() => { const handlePrev = ()=>{
state.loading = false; step.value.step --;
ElMessage.success('已操作!'); step.value.increment = -1;
}).catch(() => { }
state.loading = false; const handleNext = ()=>{
}) step.value.increment = 1;
currentDom.value.handleValidate().then((json)=>{
step.value.json = Object.assign(step.value.json,json);
step.value.step ++;
}).catch(()=>{
}); });
} }
const handleSave = ()=>{
install(step.value.json).then(()=>{
ElMessage.success('保存成功');
}).catch(()=>{
ElMessage.error('保存失败');
})
}
return { state, handleSave, formDom }; return { state,currentDom,step,handlePrev,handleNext,handleSave};
} }
} }
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.body{ .body{margin-top:1rem;}
padding:1rem 0 0 0;
}
.footer{ .footer{
padding: 1rem 0; margin-top:2rem
} }
.el-card+.el-card{margin-top:1rem;}
</style> </style>

View File

@@ -0,0 +1,172 @@
<template>
<div>
<el-form ref="formDom" :model="state.form" :rules="state.rules" label-width="10rem">
<el-form-item label="" label-width="0">
<div class="t-c w-100">端口为0则不监听</div>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="服务端口" prop="servicePort">
<el-input v-model="state.form.servicePort" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="web穿透端口" prop="webPort">
<el-input v-model="state.form.webPort" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="开放最小端口" prop="tunnelPort1">
<el-input v-model="state.form.tunnelPort1" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="开放最大端口" prop="tunnelPort2">
<el-input v-model="state.form.tunnelPort2" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="穿透密钥" prop="sForwardSecretKey">
<el-input v-model="state.form.sForwardSecretKey" maxlength="36" show-word-limit />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="中继密钥" prop="relaySecretKey">
<el-input v-model="state.form.relaySecretKey" maxlength="36" show-word-limit />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { injectGlobalData } from '@/provide';
import { reactive, watch, ref, inject, onMounted } from 'vue';
export default {
setup(props) {
const step = inject('step');
const globalData = injectGlobalData();
const state = reactive({
show: false,
form: {
relaySecretKey:globalData.value.config.Server.Relay.SecretKey,
sForwardSecretKey:globalData.value.config.Server.SForward.SecretKey,
servicePort:globalData.value.config.Server.ServicePort,
webPort:globalData.value.config.Server.SForward.WebPort,
tunnelPort1:globalData.value.config.Server.SForward.TunnelPortRange[0],
tunnelPort2:globalData.value.config.Server.SForward.TunnelPortRange[1],
},
rules: {
relaySecretKey: [{ required: true, message: "必填", trigger: "blur" }],
sForwardSecretKey: [{ required: true, message: "必填", trigger: "blur" }],
servicePort: [
{ required: true, message: "必填", trigger: "blur" },
{
type: "number",
min: 0,
max: 65535,
message: "数字 0-65535",
trigger: "blur",
transform(value) {
return Number(value);
},
},
],
webPort: [
{ required: true, message: "必填", trigger: "blur" },
{
type: "number",
min: 0,
max: 65535,
message: "数字 0-65535",
trigger: "blur",
transform(value) {
return Number(value);
},
},
],
tunnelPort1: [
{ required: true, message: "必填", trigger: "blur" },
{
type: "number",
min: 0,
max: 65535,
message: "数字 0-65535",
trigger: "blur",
transform(value) {
return Number(value);
},
},
],
tunnelPort2: [
{ required: true, message: "必填", trigger: "blur" },
{
type: "number",
min: 0,
max: 65535,
message: "数字 0-65535",
trigger: "blur",
transform(value) {
return Number(value);
},
},
],
},
});
const formDom = ref(null);
const handleValidate = () => {
return new Promise((resolve, reject) => {
formDom.value.validate((valid) => {
if (valid == false) {
reject();
}else{
resolve({
Server:{
ServicePort: +state.form.servicePort,
Relay:{
SecretKey: state.form.relaySecretKey
},
SForward:{
SecretKey: state.form.sForwardSecretKey,
WebPort: +state.form.webPort,
TunnelPortRange: [+state.form.tunnelPort1, +state.form.tunnelPort2]
}
}
});
}
});
})
}
onMounted(()=>{
if(step.value.json.Common.server == false){
step.value.step+=step.value.increment;
}
})
return { state, handleValidate, formDom };
}
}
</script>
<style lang="stylus" scoped>
.body{
padding:1rem 0 0 0;
}
.footer{
padding: 1rem 0;
}
.el-card+.el-card{margin-top:1rem;}
</style>

View File

@@ -29,7 +29,8 @@ import {useRoute,useRouter} from 'vue-router'
import {injectGlobalData} from '../../provide' import {injectGlobalData} from '../../provide'
import { computed, onMounted, reactive } from 'vue'; import { computed, onMounted, reactive } from 'vue';
import { initWebsocket, subWebsocketState,closeWebsocket } from '../../apis/request' import { initWebsocket, subWebsocketState,closeWebsocket } from '../../apis/request'
import { getConfig,getSignInfo } from '../../apis/signin' import { getSignInfo } from '../../apis/signin'
import { getConfig } from '../../apis/config'
import {Tools} from '@element-plus/icons-vue' import {Tools} from '@element-plus/icons-vue'
export default { export default {
components:{Tools}, components:{Tools},
@@ -49,16 +50,13 @@ export default {
const state = reactive({ const state = reactive({
api:queryCache.api, api:queryCache.api,
psd:queryCache.psd, psd:queryCache.psd,
groupid:globalData.value.groupid || queryCache.groupid,
showPort: false showPort: false
}); });
const showPort = computed(() => globalData.value.connected == false && state.showPort); const showPort = computed(() => globalData.value.connected == false && state.showPort);
const handleConnect = () => { const handleConnect = () => {
globalData.value.groupid = state.groupid;
queryCache.api = state.api; queryCache.api = state.api;
queryCache.psd = state.psd; queryCache.psd = state.psd;
queryCache.groupid = state.groupid;
localStorage.setItem('api-cache',JSON.stringify(queryCache)); localStorage.setItem('api-cache',JSON.stringify(queryCache));
closeWebsocket(); closeWebsocket();
@@ -69,7 +67,6 @@ export default {
window.location.reload(); window.location.reload();
} }
const handleShow = ()=>{ const handleShow = ()=>{
//state.showPort = true;
closeWebsocket(); closeWebsocket();
initWebsocket(`ws://${window.location.hostname}:12345`,state.psd); initWebsocket(`ws://${window.location.hostname}:12345`,state.psd);
} }
@@ -78,6 +75,7 @@ export default {
getConfig().then((res)=>{ getConfig().then((res)=>{
globalData.value.config.Common = res.Common; globalData.value.config.Common = res.Common;
globalData.value.config.Client = res.Client; globalData.value.config.Client = res.Client;
globalData.value.config.Server = res.Server;
globalData.value.config.Running = res.Running; globalData.value.config.Running = res.Running;
globalData.value.configed = true; globalData.value.configed = true;
setTimeout(()=>{ setTimeout(()=>{
@@ -114,7 +112,6 @@ export default {
router.isReady().then(()=>{ router.isReady().then(()=>{
state.api = route.query.api ?`${window.location.hostname}:${route.query.api}` : state.api; state.api = route.query.api ?`${window.location.hostname}:${route.query.api}` : state.api;
state.psd = route.query.psd || state.psd; state.psd = route.query.psd || state.psd;
state.groupid = route.query.groupid || state.groupid;
handleConnect(); handleConnect();
}); });
}); });

View File

@@ -9,10 +9,9 @@ export const provideGlobalData = () => {
connected: false, connected: false,
updateFlag: false, updateFlag: false,
height: 0, height: 0,
config: { Common: {}, Client: {}, Running: {} }, config: { Common: {}, Client: {}, Server: {}, Running: {} },
configed: false, configed: false,
signin: { Connected: false, Connecting: false, Version: 'v1.0.0.0' }, signin: { Connected: false, Connecting: false, Version: 'v1.0.0.0' },
groupid: '',
bufferSize: ['1KB', '2KB', '4KB', '8KB', '16KB', '32KB', '64KB', '128KB', '256KB', '512KB', '1024KB'] bufferSize: ['1KB', '2KB', '4KB', '8KB', '16KB', '32KB', '64KB', '128KB', '256KB', '512KB', '1024KB']
}); });
subWebsocketState((state) => { subWebsocketState((state) => {

View File

@@ -3,7 +3,7 @@
<div> <div>
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="auto"> <el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="auto">
<el-form-item label=""> <el-form-item label="">
<div>这将会关闭程序如果以服务启动稍后会自动启动否则你需要手动重新运行</div> <div>修改后最好能重启一次客户端</div>
</el-form-item> </el-form-item>
<el-form-item label="设备名" prop="MachineName"> <el-form-item label="设备名" prop="MachineName">
<el-input maxlength="12" show-word-limit v-model="state.ruleForm.MachineName" /> <el-input maxlength="12" show-word-limit v-model="state.ruleForm.MachineName" />

View File

@@ -10,8 +10,7 @@ export const provideDevices = () => {
timer: 0, timer: 0,
page: { page: {
Request: { Request: {
Page: 1, Size: +(localStorage.getItem('ps') || '10'), Page: 1, Size: +(localStorage.getItem('ps') || '10'), Name: '', Ids: []
GroupId: globalData.value.groupid, Name: '', Ids: []
}, },
Count: 0, Count: 0,
List: [] List: []
@@ -21,7 +20,6 @@ export const provideDevices = () => {
deviceInfo: null deviceInfo: null
}); });
const _getSignList = () => { const _getSignList = () => {
devices.page.Request.GroupId = globalData.value.groupid;
getSignInList(devices.page.Request).then((res) => { getSignInList(devices.page.Request).then((res) => {
devices.page.Request = res.Request; devices.page.Request = res.Request;
devices.page.Count = res.Count; devices.page.Count = res.Count;
@@ -37,7 +35,6 @@ export const provideDevices = () => {
} }
const _getSignList1 = () => { const _getSignList1 = () => {
if (globalData.value.connected) { if (globalData.value.connected) {
devices.page.Request.GroupId = globalData.value.groupid;
getSignInList(devices.page.Request).then((res) => { getSignInList(devices.page.Request).then((res) => {
for (let j in res.List) { for (let j in res.List) {
const item = devices.page.List.filter(c => c.MachineId == res.List[j].MachineId)[0]; const item = devices.page.List.filter(c => c.MachineId == res.List[j].MachineId)[0];

View File

@@ -19,7 +19,7 @@ namespace linker
Init(); Init();
//初始化配置文件 //初始化配置文件
ConfigWrap config = new ConfigWrap(); FileConfig config = new FileConfig();
LoggerHelper.Instance.Warning($"current version : {config.Data.Version}"); LoggerHelper.Instance.Warning($"current version : {config.Data.Version}");

View File

@@ -18,7 +18,7 @@ namespace linker.client
{ {
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly RunningConfig runningConfig; private readonly RunningConfig runningConfig;
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly TcpServer tcpServer; private readonly TcpServer tcpServer;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
private readonly SignInArgsTransfer signInArgsTransfer; private readonly SignInArgsTransfer signInArgsTransfer;
@@ -26,7 +26,7 @@ namespace linker.client
private string configKey = "signServers"; private string configKey = "signServers";
public ClientSignInTransfer(ClientSignInState clientSignInState, RunningConfig runningConfig, ConfigWrap config, TcpServer tcpServer, MessengerSender messengerSender, SignInArgsTransfer signInArgsTransfer, RunningConfigTransfer runningConfigTransfer) public ClientSignInTransfer(ClientSignInState clientSignInState, RunningConfig runningConfig, FileConfig config, TcpServer tcpServer, MessengerSender messengerSender, SignInArgsTransfer signInArgsTransfer, RunningConfigTransfer runningConfigTransfer)
{ {
this.clientSignInState = clientSignInState; this.clientSignInState = clientSignInState;
this.runningConfig = runningConfig; this.runningConfig = runningConfig;
@@ -121,89 +121,6 @@ namespace linker.client
BooleanHelper.CompareExchange(ref clientSignInState.connecting, false, true); BooleanHelper.CompareExchange(ref clientSignInState.connecting, false, true);
} }
} }
/// <summary>
/// 登出
/// </summary>
public void SignOut()
{
if (clientSignInState.Connected)
clientSignInState.Connection.Disponse(5);
}
/// <summary>
/// 修改客户端名称
/// </summary>
/// <param name="newName"></param>
public void UpdateName(string newName)
{
string name = config.Data.Client.Name;
if (name != newName)
{
config.Data.Client.Name = newName;
config.Save();
SignOut();
_ = SignIn();
}
}
/// <summary>
/// 修改客户端名称和分组编号
/// </summary>
/// <param name="newName"></param>
/// <param name="newGroupid"></param>
public void UpdateName(string newName, string newGroupid)
{
string name = config.Data.Client.Name;
string gid = config.Data.Client.GroupId;
if (name != newName || gid != newGroupid)
{
config.Data.Client.Name = newName;
config.Data.Client.GroupId = newGroupid;
config.Save();
SignOut();
_ = SignIn();
}
}
/// <summary>
/// 修改信标服务器列表
/// </summary>
/// <param name="servers"></param>
public async Task UpdateServers(ClientServerInfo[] servers)
{
await SetServers(servers);
runningConfigTransfer.IncrementVersion(configKey);
SyncServers();
}
private void SetServers(Memory<byte> data)
{
_ = SetServers(MemoryPackSerializer.Deserialize<ClientServerInfo[]>(data.Span));
}
private async Task SetServers(ClientServerInfo[] servers)
{
string server = config.Data.Client.Server;
runningConfig.Data.Client.Servers = servers;
if (runningConfig.Data.Client.Servers.Length > 0)
{
config.Data.Client.Server = runningConfig.Data.Client.Servers.FirstOrDefault().Host;
}
runningConfig.Data.Update();
if (server != config.Data.Client.Server)
{
SignOut();
await SignIn();
}
}
private void SyncServers()
{
runningConfigTransfer.Sync(configKey, MemoryPackSerializer.Serialize(runningConfig.Data.Client.Servers));
}
/// <summary> /// <summary>
/// 连接到信标服务器 /// 连接到信标服务器
/// </summary> /// </summary>
@@ -252,7 +169,6 @@ namespace linker.client
clientSignInState.Connection?.Disponse(6); clientSignInState.Connection?.Disponse(6);
return false; return false;
} }
/// <summary> /// <summary>
/// 获取服务器版本 /// 获取服务器版本
/// </summary> /// </summary>
@@ -273,5 +189,87 @@ namespace linker.client
clientSignInState.Version = "v1.0.0.0"; clientSignInState.Version = "v1.0.0.0";
} }
} }
/// <summary>
/// 登出
/// </summary>
public void SignOut()
{
if (clientSignInState.Connected)
clientSignInState.Connection.Disponse(5);
}
/// <summary>
/// 修改客户端名称
/// </summary>
/// <param name="newName"></param>
public void SetName(string newName)
{
string name = config.Data.Client.Name;
if (name != newName)
{
config.Data.Client.Name = newName;
config.Save();
SignOut();
_ = SignIn();
}
}
/// <summary>
/// 修改客户端名称和分组编号
/// </summary>
/// <param name="newName"></param>
/// <param name="newGroupid"></param>
public void Set(string newName, string newGroupid)
{
string name = config.Data.Client.Name;
string gid = config.Data.Client.GroupId;
if (name != newName || gid != newGroupid)
{
config.Data.Client.Name = newName;
config.Data.Client.GroupId = newGroupid;
config.Save();
SignOut();
_ = SignIn();
}
}
/// <summary>
/// 修改信标服务器列表
/// </summary>
/// <param name="servers"></param>
public async Task SetServers(ClientServerInfo[] servers)
{
await SetServersReSignin(servers);
runningConfigTransfer.IncrementVersion(configKey);
SyncServers();
}
private void SetServers(Memory<byte> data)
{
_ = SetServersReSignin(MemoryPackSerializer.Deserialize<ClientServerInfo[]>(data.Span));
}
private async Task SetServersReSignin(ClientServerInfo[] servers)
{
string server = config.Data.Client.Server;
runningConfig.Data.Client.Servers = servers;
if (runningConfig.Data.Client.Servers.Length > 0)
{
config.Data.Client.Server = runningConfig.Data.Client.Servers.FirstOrDefault().Host;
}
runningConfig.Data.Update();
if (server != config.Data.Client.Server)
{
SignOut();
await SignIn();
}
}
private void SyncServers()
{
runningConfigTransfer.Sync(configKey, MemoryPackSerializer.Serialize(runningConfig.Data.Client.Servers));
}
} }
} }

View File

@@ -20,7 +20,7 @@ namespace linker.client
public string[] Dependent => new string[] { "firewall", "signin", "serialize" }; public string[] Dependent => new string[] { "firewall", "signin", "serialize" };
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<RunningConfig>(); serviceCollection.AddSingleton<RunningConfig>();
serviceCollection.AddSingleton<RunningConfigTransfer>(); serviceCollection.AddSingleton<RunningConfigTransfer>();
@@ -34,7 +34,7 @@ namespace linker.client
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
LoggerHelper.Instance.Info($"start client"); LoggerHelper.Instance.Info($"start client");
@@ -44,11 +44,11 @@ namespace linker.client
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<ConfigServerMessenger>(); serviceCollection.AddSingleton<ConfigServerMessenger>();
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -9,7 +9,7 @@ namespace linker.client.args
{ {
private List<ISignInArgs> startups; private List<ISignInArgs> startups;
public SignInArgsTransfer(ServiceProvider serviceProvider, ConfigWrap config) public SignInArgsTransfer(ServiceProvider serviceProvider, FileConfig config)
{ {
var types = ReflectionHelper.GetInterfaceSchieves(typeof(ISignInArgs)); var types = ReflectionHelper.GetInterfaceSchieves(typeof(ISignInArgs));
startups = types.Select(c => serviceProvider.GetService(c) as ISignInArgs).Where(c=>c != null).ToList(); startups = types.Select(c => serviceProvider.GetService(c) as ISignInArgs).Where(c=>c != null).ToList();

View File

@@ -67,7 +67,7 @@ namespace linker.config
} }
} }
#if DEBUG #if DEBUG
private string groupid = string.Empty;//"snltty"; private string groupid = "snltty";
#else #else
private string groupid = string.Empty; private string groupid = string.Empty;
#endif #endif

View File

@@ -5,6 +5,9 @@ using System.Text.Json.Serialization;
namespace linker.client.config namespace linker.client.config
{ {
/// <summary>
/// 运行时配置
/// </summary>
public sealed class RunningConfig public sealed class RunningConfig
{ {
private readonly ILiteCollection<RunningConfigInfo> liteCollection; private readonly ILiteCollection<RunningConfigInfo> liteCollection;

View File

@@ -8,17 +8,31 @@ namespace linker.client.config
{ {
public sealed partial class RunningConfigInfo public sealed partial class RunningConfigInfo
{ {
/// <summary>
/// 同步配置的版本记录
/// </summary>
public Dictionary<string, ulong> Versions { get; set; } = new Dictionary<string, ulong>(); public Dictionary<string, ulong> Versions { get; set; } = new Dictionary<string, ulong>();
} }
[MemoryPackable] [MemoryPackable]
public sealed partial class ConfigVersionInfo public sealed partial class ConfigVersionInfo
{ {
/// <summary>
/// 配置key
/// </summary>
public string Key { get; set; } public string Key { get; set; }
/// <summary>
/// 配置版本
/// </summary>
public ulong Version { get; set; } public ulong Version { get; set; }
/// <summary>
/// 配置数据
/// </summary>
public Memory<byte> Data { get; set; } public Memory<byte> Data { get; set; }
} }
/// <summary>
/// 配置同步
/// </summary>
public sealed class RunningConfigTransfer public sealed class RunningConfigTransfer
{ {
private ConcurrentDictionary<string, Action<Memory<byte>>> setters = new ConcurrentDictionary<string, Action<Memory<byte>>>(); private ConcurrentDictionary<string, Action<Memory<byte>>> setters = new ConcurrentDictionary<string, Action<Memory<byte>>>();
@@ -33,15 +47,30 @@ namespace linker.client.config
this.sender = sender; this.sender = sender;
this.clientSignInState = clientSignInState; this.clientSignInState = clientSignInState;
} }
/// <summary>
/// 设置配置
/// </summary>
/// <param name="key"></param>
/// <param name="callback"></param>
public void Setter(string key, Action<Memory<byte>> callback) public void Setter(string key, Action<Memory<byte>> callback)
{ {
setters.TryAdd(key, callback); setters.TryAdd(key, callback);
} }
/// <summary>
/// 获取配置
/// </summary>
/// <param name="key"></param>
/// <param name="callback"></param>
public void Getter(string key, Func<Memory<byte>> callback) public void Getter(string key, Func<Memory<byte>> callback)
{ {
getters.TryAdd(key, callback); getters.TryAdd(key, callback);
} }
/// <summary>
/// 输入配置
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
public Memory<byte> InputConfig(ConfigVersionInfo info) public Memory<byte> InputConfig(ConfigVersionInfo info)
{ {
ulong version = GetVersion(info.Key); ulong version = GetVersion(info.Key);
@@ -66,6 +95,11 @@ namespace linker.client.config
private object syncLockObj = new(); private object syncLockObj = new();
/// <summary>
/// 同步配置
/// </summary>
/// <param name="key"></param>
/// <param name="data"></param>
public void Sync(string key, Memory<byte> data) public void Sync(string key, Memory<byte> data)
{ {
ulong version = GetVersion(key); ulong version = GetVersion(key);
@@ -106,11 +140,20 @@ namespace linker.client.config
} }
return version; return version;
} }
/// <summary>
/// 更新版本
/// </summary>
/// <param name="key"></param>
/// <param name="version"></param>
public void UpdateVersion(string key, ulong version) public void UpdateVersion(string key, ulong version)
{ {
runningConfig.Data.Versions[key] = version; runningConfig.Data.Versions[key] = version;
runningConfig.Data.Update(); runningConfig.Data.Update();
} }
/// <summary>
/// 版本+1
/// </summary>
/// <param name="key"></param>
public void IncrementVersion(string key) public void IncrementVersion(string key)
{ {
ulong version = GetVersion(key); ulong version = GetVersion(key);

View File

@@ -1,11 +1,12 @@
using linker.libs; using linker.libs;
using linker.libs.extends; using linker.libs.extends;
using LiteDB;
using System.Reflection; using System.Reflection;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace linker.config namespace linker.config
{ {
public sealed class ConfigWrap public sealed class FileConfig
{ {
private SemaphoreSlim slim = new SemaphoreSlim(1); private SemaphoreSlim slim = new SemaphoreSlim(1);
private string configPath = "./configs/"; private string configPath = "./configs/";
@@ -14,11 +15,12 @@ namespace linker.config
public ConfigInfo Data { get; private set; } = new ConfigInfo(); public ConfigInfo Data { get; private set; } = new ConfigInfo();
public ConfigWrap() public FileConfig()
{ {
Init(); Init();
Load(); Load();
Save(); Save();
SaveTask();
} }
private void Init() private void Init()
@@ -46,7 +48,6 @@ namespace linker.config
}); });
} }
} }
private void Load() private void Load()
{ {
slim.Wait(); slim.Wait();
@@ -78,8 +79,7 @@ namespace linker.config
} }
} }
private void Save()
public void Save()
{ {
slim.Wait(); slim.Wait();
try try
@@ -106,7 +106,21 @@ namespace linker.config
} }
} }
private void SaveTask()
{
Task.Run(async () =>
{
while (true)
{
while (Data.Updated > 0)
{
Save();
Data.Updated--;
}
await Task.Delay(1000).ConfigureAwait(false);
}
});
}
} }
public sealed class FileReadWrite public sealed class FileReadWrite
@@ -129,16 +143,29 @@ namespace linker.config
public string Version { get; set; } = $"v{Assembly.GetEntryAssembly().GetName().Version}"; public string Version { get; set; } = $"v{Assembly.GetEntryAssembly().GetName().Version}";
[JsonIgnore] [JsonIgnore]
public bool Elevated { get; set; } public bool Elevated { get; set; }
[JsonIgnore, BsonIgnore]
public uint Updated { get; set; } = 1;
public void Update()
{
Updated++;
}
} }
public sealed partial class ConfigCommonInfo public sealed partial class ConfigCommonInfo
{ {
public string[] Modes { get; set; } = new string[] { "client", "server" }; public string[] Modes { get; set; } = new string[] { "client", "server" };
#if DEBUG #if DEBUG
private LoggerTypes loggerType { get; set; } = LoggerTypes.DEBUG; private LoggerTypes loggerType { get; set; } = LoggerTypes.DEBUG;
public bool Install { get; set; } = true;
#else #else
private LoggerTypes loggerType { get; set; } = LoggerTypes.WARNING; private LoggerTypes loggerType { get; set; } = LoggerTypes.WARNING;
public bool Install { get; set; } = false;
#endif #endif
[JsonIgnore] [JsonIgnore]

View File

@@ -13,9 +13,9 @@ namespace linker.plugins.capi
public sealed class ApiClientServer : ApiServer, IApiClientServer public sealed class ApiClientServer : ApiServer, IApiClientServer
{ {
private readonly ServiceProvider serviceProvider; private readonly ServiceProvider serviceProvider;
private readonly ConfigWrap config; private readonly FileConfig config;
public ApiClientServer(ServiceProvider serviceProvider, ConfigWrap config) public ApiClientServer(ServiceProvider serviceProvider, FileConfig config)
{ {
this.serviceProvider = serviceProvider; this.serviceProvider = serviceProvider;
this.config = config; this.config = config;

View File

@@ -15,13 +15,13 @@ namespace linker.plugins.capi
public string[] Dependent => new string[] {}; public string[] Dependent => new string[] {};
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<IApiClientServer, ApiClientServer>(); serviceCollection.AddSingleton<IApiClientServer, ApiClientServer>();
serviceCollection.AddSingleton<IWebClientServer, WebClientServer>(); serviceCollection.AddSingleton<IWebClientServer, WebClientServer>();
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
if (config.Data.Client.CApi.ApiPort > 0) if (config.Data.Client.CApi.ApiPort > 0)
{ {
@@ -42,11 +42,11 @@ namespace linker.plugins.capi
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -4,15 +4,30 @@ namespace linker.config
{ {
public partial class ConfigClientInfo public partial class ConfigClientInfo
{ {
/// <summary>
/// 客户端管理接口配置
/// </summary>
public CApiConfigClientInfo CApi { get; set; } = new CApiConfigClientInfo(); public CApiConfigClientInfo CApi { get; set; } = new CApiConfigClientInfo();
} }
public sealed class CApiConfigClientInfo public sealed class CApiConfigClientInfo
{ {
/// <summary>
/// 管理接口端口
/// </summary>
public int ApiPort { get; set; } = 1803; public int ApiPort { get; set; } = 1803;
/// <summary>
/// 管理接口密码
/// </summary>
public string ApiPassword { get; set; } = Helper.GlobalString; public string ApiPassword { get; set; } = Helper.GlobalString;
/// <summary>
/// 网站端口
/// </summary>
public int WebPort { get; set; } = 1804; public int WebPort { get; set; } = 1804;
/// <summary>
/// 网站根目录
/// </summary>
public string WebRoot { get; set; } = "./web/"; public string WebRoot { get; set; } = "./web/";
} }
} }

View File

@@ -0,0 +1,89 @@
using linker.config;
using linker.libs.api;
using linker.libs.extends;
using linker.client.capi;
using linker.client.config;
namespace linker.plugins.config
{
public sealed class ConfigClientApiController : IApiClientController
{
private readonly RunningConfig runningConfig;
private readonly FileConfig config;
public ConfigClientApiController(RunningConfig runningConfig, FileConfig config)
{
this.runningConfig = runningConfig;
this.config = config;
}
public object Get(ApiControllerParamsInfo param)
{
return new { Common = config.Data.Common, Client = config.Data.Client, Server = config.Data.Server, Running = runningConfig.Data };
}
public bool Install(ApiControllerParamsInfo param)
{
ConfigInstallInfo info = param.Content.DeJson<ConfigInstallInfo>();
if (info.Common.Modes.Contains("client"))
{
config.Data.Client.Name = info.Client.Name;
config.Data.Client.GroupId = info.Client.GroupId;
config.Data.Client.CApi.WebPort = info.Client.Web;
config.Data.Client.CApi.ApiPort = info.Client.Api;
config.Data.Client.CApi.ApiPassword = info.Client.Password;
}
if (info.Common.Modes.Contains("server"))
{
config.Data.Server.ServicePort = info.Server.ServicePort;
config.Data.Server.Relay.SecretKey = info.Server.Relay.SecretKey;
config.Data.Server.SForward.SecretKey = info.Server.SForward.SecretKey;
config.Data.Server.SForward.WebPort = info.Server.SForward.WebPort;
config.Data.Server.SForward.TunnelPortRange = info.Server.SForward.TunnelPortRange;
}
config.Data.Common.Modes = info.Common.Modes;
config.Data.Common.Install = true;
config.Save();
return true;
}
}
public sealed class ConfigInstallInfo
{
public ConfigInstallClientInfo Client { get; set; } = new ConfigInstallClientInfo();
public ConfigInstallServerInfo Server { get; set; } = new ConfigInstallServerInfo();
public ConfigInstallCommonInfo Common { get; set; } = new ConfigInstallCommonInfo();
}
public sealed class ConfigInstallClientInfo
{
public string Name { get; set; }
public string GroupId { get; set; }
public int Api { get; set; }
public int Web { get; set; }
public string Password { get; set; }
}
public sealed class ConfigInstallServerInfo
{
public int ServicePort { get; set; }
public ConfigInstallServerRelayInfo Relay { get; set; }
public ConfigInstallServerSForwardInfo SForward { get; set; }
}
public sealed class ConfigInstallServerRelayInfo
{
public string SecretKey { get; set; }
}
public sealed class ConfigInstallServerSForwardInfo
{
public string SecretKey { get; set; }
public int WebPort { get; set; }
public int[] TunnelPortRange { get; set; }
}
public sealed class ConfigInstallCommonInfo
{
public string[] Modes { get; set; }
}
}

View File

@@ -0,0 +1,37 @@
using linker.config;
using linker.startup;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
namespace linker.plugins.config
{
public sealed class ConfigStartup : IStartup
{
public string Name => "config";
public bool Required => true;
public StartupLevel Level => StartupLevel.Normal;
public string[] Dependent => Array.Empty<string>();
public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{
serviceCollection.AddSingleton<ConfigClientApiController>();
}
public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{
}
public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{
}
public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{
}
}
}

View File

@@ -13,7 +13,7 @@ namespace linker.plugins.firewall
public string[] Dependent => new string[] { }; public string[] Dependent => new string[] { };
public StartupLoadType LoadType => StartupLoadType.Dependent; public StartupLoadType LoadType => StartupLoadType.Dependent;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
#if DEBUG #if DEBUG
#else #else
@@ -21,15 +21,15 @@ namespace linker.plugins.firewall
#endif #endif
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -17,7 +17,7 @@ namespace linker.plugins.forward
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<ForwardClientApiController>(); serviceCollection.AddSingleton<ForwardClientApiController>();
serviceCollection.AddSingleton<ForwardTransfer>(); serviceCollection.AddSingleton<ForwardTransfer>();
@@ -27,17 +27,17 @@ namespace linker.plugins.forward
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<ForwardServerMessenger>(); serviceCollection.AddSingleton<ForwardServerMessenger>();
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
ForwardTransfer forwardTransfer = serviceProvider.GetService<ForwardTransfer>(); ForwardTransfer forwardTransfer = serviceProvider.GetService<ForwardTransfer>();
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -7,23 +7,54 @@ namespace linker.client.config
{ {
public sealed partial class RunningConfigInfo public sealed partial class RunningConfigInfo
{ {
/// <summary>
/// 端口转发配置
/// </summary>
public List<ForwardInfo> Forwards { get; set; } = new List<ForwardInfo>(); public List<ForwardInfo> Forwards { get; set; } = new List<ForwardInfo>();
} }
/// <summary>
/// 端口转发配置
/// </summary>
public sealed class ForwardInfo public sealed class ForwardInfo
{ {
public uint Id { get; set; } public uint Id { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// 目标设备
/// </summary>
public string MachineId { get; set; } public string MachineId { get; set; }
/// <summary>
/// 本地绑定IP
/// </summary>
public IPAddress BindIPAddress { get; set; } = IPAddress.Any; public IPAddress BindIPAddress { get; set; } = IPAddress.Any;
/// <summary>
/// 本地监听端口
/// </summary>
public int Port { get; set; } public int Port { get; set; }
/// <summary>
/// 目标设备服务
/// </summary>
public IPEndPoint TargetEP { get; set; } public IPEndPoint TargetEP { get; set; }
/// <summary>
/// 已启动
/// </summary>
public bool Started { get; set; } public bool Started { get; set; }
/// <summary>
/// 缓冲区
/// </summary>
public byte BufferSize { get; set; } = 3; public byte BufferSize { get; set; } = 3;
/// <summary>
/// 本地监听错误信息
/// </summary>
public string Msg { get; set; } public string Msg { get; set; }
/// <summary>
/// 目标服务错误信息
/// </summary>
public string TargetMsg { get; set; } public string TargetMsg { get; set; }
[JsonIgnore, BsonIgnore] [JsonIgnore, BsonIgnore]

View File

@@ -12,7 +12,7 @@ namespace linker.plugins.forward.proxy
{ {
public sealed class ForwardProxy : TunnelProxy public sealed class ForwardProxy : TunnelProxy
{ {
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly TunnelTransfer tunnelTransfer; private readonly TunnelTransfer tunnelTransfer;
private readonly RelayTransfer relayTransfer; private readonly RelayTransfer relayTransfer;
@@ -20,7 +20,7 @@ namespace linker.plugins.forward.proxy
private readonly ConcurrentDictionary<string, ITunnelConnection> connections = new ConcurrentDictionary<string, ITunnelConnection>(); private readonly ConcurrentDictionary<string, ITunnelConnection> connections = new ConcurrentDictionary<string, ITunnelConnection>();
private readonly ConcurrentDictionary<string, SemaphoreSlim> locks = new ConcurrentDictionary<string, SemaphoreSlim>(); private readonly ConcurrentDictionary<string, SemaphoreSlim> locks = new ConcurrentDictionary<string, SemaphoreSlim>();
public ForwardProxy(ConfigWrap config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer) public ForwardProxy(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer)
{ {
this.config = config; this.config = config;
this.tunnelTransfer = tunnelTransfer; this.tunnelTransfer = tunnelTransfer;
@@ -36,6 +36,10 @@ namespace linker.plugins.forward.proxy
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Warning($"TryAdd {connection.GetHashCode()} {connection.TransactionId} {connection.ToJson()}"); LoggerHelper.Instance.Warning($"TryAdd {connection.GetHashCode()} {connection.TransactionId} {connection.ToJson()}");
if (connections.TryGetValue(connection.RemoteMachineId, out ITunnelConnection connectionOld))
{
connectionOld?.Dispose();
}
//把隧道对象添加到缓存,方便下次直接获取 //把隧道对象添加到缓存,方便下次直接获取
connections.AddOrUpdate(connection.RemoteMachineId, connection, (a, b) => connection); connections.AddOrUpdate(connection.RemoteMachineId, connection, (a, b) => connection);
BindConnectionReceive(connection); BindConnectionReceive(connection);
@@ -113,12 +117,13 @@ namespace linker.plugins.forward.proxy
if (connection == null) if (connection == null)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"forward relay to {machineId}"); if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"forward relay to {machineId}");
//转入后台打洞
tunnelTransfer.StartBackground(machineId, "forward");
//尝试中继 //尝试中继
connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "forward").ConfigureAwait(false); connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "forward").ConfigureAwait(false);
if (connection != null) if (connection != null)
{ {
//转入后台打洞
tunnelTransfer.StartBackground(machineId, "forward");
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"forward relay to {machineId} success"); if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"forward relay to {machineId} success");
} }
} }

View File

@@ -10,8 +10,8 @@ namespace linker.plugins.logger
{ {
private readonly List<LoggerModel> loggers = new List<LoggerModel>(); private readonly List<LoggerModel> loggers = new List<LoggerModel>();
private readonly ConfigWrap config; private readonly FileConfig config;
public LoggerClientApiController(ConfigWrap config) public LoggerClientApiController(FileConfig config)
{ {
this.config = config; this.config = config;
LoggerHelper.Instance.OnLogger += (LoggerModel logger) => LoggerHelper.Instance.OnLogger += (LoggerModel logger) =>

View File

@@ -17,22 +17,22 @@ namespace linker.plugins.logger
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<LoggerClientApiController>(); serviceCollection.AddSingleton<LoggerClientApiController>();
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
LoggerClientApiController logger = serviceProvider.GetService<LoggerClientApiController>(); LoggerClientApiController logger = serviceProvider.GetService<LoggerClientApiController>();
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -14,12 +14,12 @@ namespace linker.plugins.relay
/// </summary> /// </summary>
public sealed class RelayApiController : IApiClientController public sealed class RelayApiController : IApiClientController
{ {
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly RelayTransfer relayTransfer; private readonly RelayTransfer relayTransfer;
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
public RelayApiController(ConfigWrap config, RelayTransfer relayTransfer, ClientSignInState clientSignInState, MessengerSender messengerSender) public RelayApiController(FileConfig config, RelayTransfer relayTransfer, ClientSignInState clientSignInState, MessengerSender messengerSender)
{ {
this.config = config; this.config = config;
this.relayTransfer = relayTransfer; this.relayTransfer = relayTransfer;

View File

@@ -21,7 +21,7 @@ namespace linker.plugins.relay
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<RelayApiController>(); serviceCollection.AddSingleton<RelayApiController>();
serviceCollection.AddSingleton<RelayClientMessenger>(); serviceCollection.AddSingleton<RelayClientMessenger>();
@@ -30,18 +30,18 @@ namespace linker.plugins.relay
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<RelayServerMessenger>(); serviceCollection.AddSingleton<RelayServerMessenger>();
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
RelayTransfer relayTransfer = serviceProvider.GetService<RelayTransfer>(); RelayTransfer relayTransfer = serviceProvider.GetService<RelayTransfer>();
relayTransfer.Load(assemblies); relayTransfer.Load(assemblies);
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -8,12 +8,18 @@ namespace linker.client.config
{ {
public sealed partial class RunningConfigInfo public sealed partial class RunningConfigInfo
{ {
/// <summary>
/// 中继配置
/// </summary>
public RelayRunningInfo Relay { get; set; } = new RelayRunningInfo(); public RelayRunningInfo Relay { get; set; } = new RelayRunningInfo();
} }
public sealed class RelayRunningInfo public sealed class RelayRunningInfo
{ {
public ObjectId Id { get; set; } public ObjectId Id { get; set; }
/// <summary>
/// 中继服务器列表
/// </summary>
public RelayServerInfo[] Servers { get; set; } = Array.Empty<RelayServerInfo>(); public RelayServerInfo[] Servers { get; set; } = Array.Empty<RelayServerInfo>();
} }
} }
@@ -23,23 +29,53 @@ namespace linker.config
{ {
public partial class ConfigServerInfo public partial class ConfigServerInfo
{ {
/// <summary>
/// 中继配置
/// </summary>
public RelayConfigServerInfo Relay { get; set; } = new RelayConfigServerInfo(); public RelayConfigServerInfo Relay { get; set; } = new RelayConfigServerInfo();
} }
public sealed class RelayConfigServerInfo public sealed class RelayConfigServerInfo
{ {
/// <summary>
/// 中继密钥
/// </summary>
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper(); public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
/// <summary>
/// 缓冲区
/// </summary>
public byte BufferSize { get; set; } = 3; public byte BufferSize { get; set; } = 3;
} }
/// <summary>
/// 中继服务器
/// </summary>
[MemoryPackable] [MemoryPackable]
public sealed partial class RelayServerInfo public sealed partial class RelayServerInfo
{ {
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
/// <summary>
/// 中继服务器类别
/// </summary>
public RelayType RelayType { get; set; } = RelayType.Linker; public RelayType RelayType { get; set; } = RelayType.Linker;
/// <summary>
/// 密钥
/// </summary>
public string SecretKey { get; set; } = "snltty"; public string SecretKey { get; set; } = "snltty";
/// <summary>
/// 服务器地址
/// </summary>
public string Host { get; set; } = string.Empty; public string Host { get; set; } = string.Empty;
/// <summary>
/// 禁用
/// </summary>
public bool Disabled { get; set; } public bool Disabled { get; set; }
/// <summary>
/// 开启ssl
/// </summary>
public bool SSL { get; set; } = true; public bool SSL { get; set; } = true;
} }

View File

@@ -39,14 +39,14 @@ namespace linker.plugins.relay.messenger
/// </summary> /// </summary>
public sealed class RelayServerMessenger : IMessenger public sealed class RelayServerMessenger : IMessenger
{ {
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
private readonly SignCaching signCaching; private readonly SignCaching signCaching;
private readonly ConcurrentDictionary<ulong, TcsWrap> dic = new ConcurrentDictionary<ulong, TcsWrap>(); private readonly ConcurrentDictionary<ulong, TcsWrap> dic = new ConcurrentDictionary<ulong, TcsWrap>();
private ulong flowingId = 0; private ulong flowingId = 0;
public RelayServerMessenger(ConfigWrap config, MessengerSender messengerSender, SignCaching signCaching) public RelayServerMessenger(FileConfig config, MessengerSender messengerSender, SignCaching signCaching)
{ {
this.config = config; this.config = config;
this.messengerSender = messengerSender; this.messengerSender = messengerSender;

View File

@@ -26,7 +26,7 @@ namespace linker.plugins.relay.transport
private X509Certificate2 certificate; private X509Certificate2 certificate;
public TransportSelfHost(TcpServer tcpServer, MessengerSender messengerSender, ConfigWrap config) public TransportSelfHost(TcpServer tcpServer, MessengerSender messengerSender, FileConfig config)
{ {
this.tcpServer = tcpServer; this.tcpServer = tcpServer;
this.messengerSender = messengerSender; this.messengerSender = messengerSender;

View File

@@ -22,7 +22,7 @@ namespace linker.plugins.sforward
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
Add(serviceCollection, config, assemblies); Add(serviceCollection, config, assemblies);
serviceCollection.AddSingleton<SForwardClientApiController>(); serviceCollection.AddSingleton<SForwardClientApiController>();
@@ -30,7 +30,7 @@ namespace linker.plugins.sforward
serviceCollection.AddSingleton<SForwardClientMessenger>(); serviceCollection.AddSingleton<SForwardClientMessenger>();
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
Add(serviceCollection, config, assemblies); Add(serviceCollection, config, assemblies);
serviceCollection.AddSingleton<SForwardServerMessenger>(); serviceCollection.AddSingleton<SForwardServerMessenger>();
@@ -40,7 +40,7 @@ namespace linker.plugins.sforward
} }
bool added = false; bool added = false;
private void Add(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) private void Add(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
if (added == false) if (added == false)
{ {
@@ -49,12 +49,12 @@ namespace linker.plugins.sforward
} }
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
SForwardTransfer forwardTransfer = serviceProvider.GetService<SForwardTransfer>(); SForwardTransfer forwardTransfer = serviceProvider.GetService<SForwardTransfer>();
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
SForwardProxy sForwardProxy = serviceProvider.GetService<SForwardProxy>(); SForwardProxy sForwardProxy = serviceProvider.GetService<SForwardProxy>();
if (config.Data.Server.SForward.WebPort > 0) if (config.Data.Server.SForward.WebPort > 0)

View File

@@ -8,24 +8,53 @@ namespace linker.client.config
{ {
public sealed partial class RunningConfigInfo public sealed partial class RunningConfigInfo
{ {
/// <summary>
/// 服务器穿透密钥
/// </summary>
public string SForwardSecretKey { get; set; } = "snltty"; public string SForwardSecretKey { get; set; } = "snltty";
/// <summary>
/// 服务器穿透列表
/// </summary>
public List<SForwardInfo> SForwards { get; set; } =new List<SForwardInfo>(); public List<SForwardInfo> SForwards { get; set; } =new List<SForwardInfo>();
} }
public sealed class SForwardInfo public sealed class SForwardInfo
{ {
/// <summary>
/// 穿透id
/// </summary>
public uint Id { get; set; } public uint Id { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// 域名
/// </summary>
public string Domain { get; set; } public string Domain { get; set; }
/// <summary>
/// 端口,
/// </summary>
public int RemotePort { get; set; } public int RemotePort { get; set; }
/// <summary>
/// 缓冲区
/// </summary>
public byte BufferSize { get; set; } = 3; public byte BufferSize { get; set; } = 3;
/// <summary>
/// 本地服务
/// </summary>
public IPEndPoint LocalEP { get; set; } public IPEndPoint LocalEP { get; set; }
/// <summary>
/// 已启动
/// </summary>
public bool Started { get; set; } public bool Started { get; set; }
/// <summary>
/// 服务器错误信息
/// </summary>
public string Msg { get; set; } public string Msg { get; set; }
/// <summary>
/// 本地错误信息
/// </summary>
public string LocalMsg { get; set; } public string LocalMsg { get; set; }
[JsonIgnore, BsonIgnore] [JsonIgnore, BsonIgnore]
@@ -38,14 +67,29 @@ namespace linker.config
{ {
public partial class ConfigServerInfo public partial class ConfigServerInfo
{ {
/// <summary>
/// 服务器穿透配置
/// </summary>
public SForwardConfigServerInfo SForward { get; set; } = new SForwardConfigServerInfo(); public SForwardConfigServerInfo SForward { get; set; } = new SForwardConfigServerInfo();
} }
public sealed class SForwardConfigServerInfo public sealed class SForwardConfigServerInfo
{ {
/// <summary>
/// 密钥
/// </summary>
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper(); public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
/// <summary>
/// 缓冲区
/// </summary>
public byte BufferSize { get; set; } = 3; public byte BufferSize { get; set; } = 3;
/// <summary>
/// web端口
/// </summary>
public int WebPort { get; set; } public int WebPort { get; set; }
/// <summary>
/// 开放端口范围
/// </summary>
public int[] TunnelPortRange { get; set; } = new int[] { 10000, 60000 }; public int[] TunnelPortRange { get; set; } = new int[] { 10000, 60000 };
} }
@@ -67,7 +111,6 @@ namespace linker.plugins.sforward.config
{ {
public bool Success { get; set; } public bool Success { get; set; }
public string Message { get; set; } public string Message { get; set; }
public byte BufferSize { get; set; } public byte BufferSize { get; set; }
} }
@@ -78,7 +121,6 @@ namespace linker.plugins.sforward.config
public ulong Id { get; set; } public ulong Id { get; set; }
public string Domain { get; set; } public string Domain { get; set; }
public int RemotePort { get; set; } public int RemotePort { get; set; }
public byte BufferSize { get; set; } = 3; public byte BufferSize { get; set; } = 3;
} }
} }

View File

@@ -19,10 +19,10 @@ namespace linker.plugins.sforward.messenger
private readonly ISForwardServerCahing sForwardServerCahing; private readonly ISForwardServerCahing sForwardServerCahing;
private readonly MessengerSender sender; private readonly MessengerSender sender;
private readonly SignCaching signCaching; private readonly SignCaching signCaching;
private readonly ConfigWrap configWrap; private readonly FileConfig configWrap;
private readonly IValidator validator; private readonly IValidator validator;
public SForwardServerMessenger(SForwardProxy proxy, ISForwardServerCahing sForwardServerCahing, MessengerSender sender, SignCaching signCaching, ConfigWrap configWrap, IValidator validator) public SForwardServerMessenger(SForwardProxy proxy, ISForwardServerCahing sForwardServerCahing, MessengerSender sender, SignCaching signCaching, FileConfig configWrap, IValidator validator)
{ {
this.proxy = proxy; this.proxy = proxy;
proxy.WebConnect = WebConnect; proxy.WebConnect = WebConnect;

View File

@@ -6,8 +6,8 @@ namespace linker.plugins.sforward.validator
{ {
public sealed class Validator : IValidator public sealed class Validator : IValidator
{ {
private readonly ConfigWrap config; private readonly FileConfig config;
public Validator(ConfigWrap config) public Validator(FileConfig config)
{ {
this.config = config; this.config = config;
} }

View File

@@ -6,23 +6,18 @@ using linker.client;
using linker.server; using linker.server;
using MemoryPack; using MemoryPack;
using linker.client.capi; using linker.client.capi;
using linker.client.config;
using System.Diagnostics;
using linker.libs;
namespace linker.plugins.signin namespace linker.plugins.signin
{ {
public sealed class SignInClientApiController : IApiClientController public sealed class SignInClientApiController : IApiClientController
{ {
private readonly RunningConfig runningConfig; private readonly FileConfig config;
private readonly ConfigWrap config;
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly ClientSignInTransfer clientSignInTransfer; private readonly ClientSignInTransfer clientSignInTransfer;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
public SignInClientApiController(RunningConfig runningConfig, ConfigWrap config, ClientSignInState clientSignInState, ClientSignInTransfer clientSignInTransfer, MessengerSender messengerSender) public SignInClientApiController(FileConfig config, ClientSignInState clientSignInState, ClientSignInTransfer clientSignInTransfer, MessengerSender messengerSender)
{ {
this.runningConfig = runningConfig;
this.config = config; this.config = config;
this.clientSignInState = clientSignInState; this.clientSignInState = clientSignInState;
this.clientSignInTransfer = clientSignInTransfer; this.clientSignInTransfer = clientSignInTransfer;
@@ -30,22 +25,38 @@ namespace linker.plugins.signin
} }
public object Config(ApiControllerParamsInfo param)
{
return new { Common = config.Data.Common, Client = config.Data.Client, Running = runningConfig.Data };
}
public void Set(ApiControllerParamsInfo param) public void Set(ApiControllerParamsInfo param)
{ {
ConfigSetInfo info = param.Content.DeJson<ConfigSetInfo>(); ConfigSetInfo info = param.Content.DeJson<ConfigSetInfo>();
clientSignInTransfer.UpdateName(info.Name, info.GroupId); clientSignInTransfer.Set(info.Name, info.GroupId);
}
public async Task<bool> SeName(ApiControllerParamsInfo param)
{
ConfigSetNameInfo info = param.Content.DeJson<ConfigSetNameInfo>();
if (info.Id == config.Data.Client.Id)
{
clientSignInTransfer.SetName(info.NewName);
}
else
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)SignInMessengerIds.SetNameForward,
Payload = MemoryPackSerializer.Serialize(info)
}).ConfigureAwait(false);
}
return true;
} }
public async Task<bool> SetServers(ApiControllerParamsInfo param) public async Task<bool> SetServers(ApiControllerParamsInfo param)
{ {
ClientServerInfo[] servers = param.Content.DeJson<ClientServerInfo[]>(); ClientServerInfo[] servers = param.Content.DeJson<ClientServerInfo[]>();
await clientSignInTransfer.UpdateServers(servers); await clientSignInTransfer.SetServers(servers);
return true; return true;
} }
public ClientSignInState Info(ApiControllerParamsInfo param) public ClientSignInState Info(ApiControllerParamsInfo param)
{ {
return clientSignInState; return clientSignInState;
@@ -90,50 +101,6 @@ namespace linker.plugins.signin
return new SignInIdsResponseInfo { }; return new SignInIdsResponseInfo { };
} }
public async Task<bool> SetName(ApiControllerParamsInfo param)
{
ConfigSetNameInfo info = param.Content.DeJson<ConfigSetNameInfo>();
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)SignInMessengerIds.NameForward,
Payload = MemoryPackSerializer.Serialize(info)
}).ConfigureAwait(false);
if (info.Id == config.Data.Client.Id)
{
clientSignInTransfer.UpdateName(info.NewName);
}
return true;
}
public bool Install(ApiControllerParamsInfo param)
{
ConfigInstallInfo info = param.Content.DeJson<ConfigInstallInfo>();
config.Data.Client.Name = info.Name;
config.Data.Client.GroupId = info.GroupId;
config.Data.Client.CApi.WebPort = info.Web;
config.Data.Client.CApi.ApiPort = info.Api;
config.Data.Client.CApi.ApiPassword = info.Password;
config.Data.Common.Modes = new string[] { "client" };
config.Save();
if (info.Restart)
{
try
{
CommandHelper.Execute(Process.GetCurrentProcess().MainModule.FileName, string.Empty);
Environment.Exit(0);
}
catch (Exception)
{
}
}
return true;
}
} }
[MemoryPackable] [MemoryPackable]
@@ -149,13 +116,4 @@ namespace linker.plugins.signin
public string GroupId { get; set; } public string GroupId { get; set; }
} }
public sealed class ConfigInstallInfo
{
public string Name { get; set; }
public string GroupId { get; set; }
public int Api { get; set; }
public int Web { get; set; }
public string Password { get; set; }
public bool Restart { get; set; }
}
} }

View File

@@ -18,23 +18,23 @@ namespace linker.plugins.signin
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<SignInClientMessenger>(); serviceCollection.AddSingleton<SignInClientMessenger>();
serviceCollection.AddSingleton<SignInClientApiController>(); serviceCollection.AddSingleton<SignInClientApiController>();
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<SignCaching>(); serviceCollection.AddSingleton<SignCaching>();
serviceCollection.AddSingleton<SignInServerMessenger>(); serviceCollection.AddSingleton<SignInServerMessenger>();
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -9,16 +9,16 @@ namespace linker.plugins.signin.messenger
public sealed class SignInClientMessenger : IMessenger public sealed class SignInClientMessenger : IMessenger
{ {
private readonly ClientSignInTransfer clientSignInTransfer; private readonly ClientSignInTransfer clientSignInTransfer;
public SignInClientMessenger(ConfigWrap config, ClientSignInTransfer clientSignInTransfer) public SignInClientMessenger(FileConfig config, ClientSignInTransfer clientSignInTransfer)
{ {
this.clientSignInTransfer = clientSignInTransfer; this.clientSignInTransfer = clientSignInTransfer;
} }
[MessengerId((ushort)SignInMessengerIds.Name)] [MessengerId((ushort)SignInMessengerIds.SetName)]
public void Name(IConnection connection) public void Name(IConnection connection)
{ {
ConfigSetNameInfo info = MemoryPackSerializer.Deserialize<ConfigSetNameInfo>(connection.ReceiveRequestWrap.Payload.Span); ConfigSetNameInfo info = MemoryPackSerializer.Deserialize<ConfigSetNameInfo>(connection.ReceiveRequestWrap.Payload.Span);
clientSignInTransfer.UpdateName(info.NewName); clientSignInTransfer.SetName(info.NewName);
} }
} }
@@ -26,10 +26,10 @@ namespace linker.plugins.signin.messenger
public sealed class SignInServerMessenger : IMessenger public sealed class SignInServerMessenger : IMessenger
{ {
private readonly SignCaching signCaching; private readonly SignCaching signCaching;
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
public SignInServerMessenger(SignCaching signCaching, ConfigWrap config, MessengerSender messengerSender) public SignInServerMessenger(SignCaching signCaching, FileConfig config, MessengerSender messengerSender)
{ {
this.signCaching = signCaching; this.signCaching = signCaching;
this.config = config; this.config = config;
@@ -82,7 +82,7 @@ namespace linker.plugins.signin.messenger
} }
} }
[MessengerId((ushort)SignInMessengerIds.NameForward)] [MessengerId((ushort)SignInMessengerIds.SetNameForward)]
public async Task NameForward(IConnection connection) public async Task NameForward(IConnection connection)
{ {
ConfigSetNameInfo info = MemoryPackSerializer.Deserialize<ConfigSetNameInfo>(connection.ReceiveRequestWrap.Payload.Span); ConfigSetNameInfo info = MemoryPackSerializer.Deserialize<ConfigSetNameInfo>(connection.ReceiveRequestWrap.Payload.Span);
@@ -93,7 +93,7 @@ namespace linker.plugins.signin.messenger
await messengerSender.SendOnly(new MessageRequestWrap await messengerSender.SendOnly(new MessageRequestWrap
{ {
Connection = cache.Connection, Connection = cache.Connection,
MessengerId = (ushort)SignInMessengerIds.Name, MessengerId = (ushort)SignInMessengerIds.SetName,
Payload = connection.ReceiveRequestWrap.Payload, Payload = connection.ReceiveRequestWrap.Payload,
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }

View File

@@ -6,8 +6,8 @@
List = 1, List = 1,
Delete = 2, Delete = 2,
Name = 3, SetName = 3,
NameForward = 4, SetNameForward = 4,
Version = 7, Version = 7,

View File

@@ -22,14 +22,14 @@ namespace linker.plugins.tunnel
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly RunningConfig running; private readonly RunningConfig running;
private readonly RunningConfigTransfer runningConfigTransfer; private readonly RunningConfigTransfer runningConfigTransfer;
private string wanPortConfigKey = "tunnelWanPortProtocols"; private string wanPortConfigKey = "tunnelWanPortProtocols";
private string transportConfigKey = "tunnelTransports"; private string transportConfigKey = "tunnelTransports";
public TunnelAdapter(ClientSignInState clientSignInState, MessengerSender messengerSender, ConfigWrap config, RunningConfig running, RunningConfigTransfer runningConfigTransfer) public TunnelAdapter(ClientSignInState clientSignInState, MessengerSender messengerSender, FileConfig config, RunningConfig running, RunningConfigTransfer runningConfigTransfer)
{ {
this.clientSignInState = clientSignInState; this.clientSignInState = clientSignInState;
this.messengerSender = messengerSender; this.messengerSender = messengerSender;

View File

@@ -19,14 +19,14 @@ namespace linker.plugins.tunnel
/// </summary> /// </summary>
public sealed class TunnelApiController : IApiClientController public sealed class TunnelApiController : IApiClientController
{ {
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly TunnelWanPortTransfer compactTransfer; private readonly TunnelWanPortTransfer compactTransfer;
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
private readonly TunnelConfigTransfer tunnelConfigTransfer; private readonly TunnelConfigTransfer tunnelConfigTransfer;
private readonly ITunnelAdapter tunnelMessengerAdapter; private readonly ITunnelAdapter tunnelMessengerAdapter;
public TunnelApiController(ConfigWrap config, TunnelWanPortTransfer compactTransfer, ClientSignInState clientSignInState, MessengerSender messengerSender, TunnelConfigTransfer tunnelConfigTransfer, ITunnelAdapter tunnelMessengerAdapter) public TunnelApiController(FileConfig config, TunnelWanPortTransfer compactTransfer, ClientSignInState clientSignInState, MessengerSender messengerSender, TunnelConfigTransfer tunnelConfigTransfer, ITunnelAdapter tunnelMessengerAdapter)
{ {
this.config = config; this.config = config;
this.compactTransfer = compactTransfer; this.compactTransfer = compactTransfer;
@@ -92,11 +92,11 @@ namespace linker.plugins.tunnel
/// <returns></returns> /// <returns></returns>
public async Task<bool> SetRouteLevel(ApiControllerParamsInfo param) public async Task<bool> SetRouteLevel(ApiControllerParamsInfo param)
{ {
TunnelTransportRouteLevelInfo tunnelTransportConfigWrapInfo = param.Content.DeJson<TunnelTransportRouteLevelInfo>(); TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo = param.Content.DeJson<TunnelTransportRouteLevelInfo>();
if (tunnelTransportConfigWrapInfo.MachineId == config.Data.Client.Id) if (tunnelTransportFileConfigInfo.MachineId == config.Data.Client.Id)
{ {
tunnelConfigTransfer.OnLocalRouteLevel(tunnelTransportConfigWrapInfo); tunnelConfigTransfer.OnLocalRouteLevel(tunnelTransportFileConfigInfo);
} }
else else
{ {
@@ -104,7 +104,7 @@ namespace linker.plugins.tunnel
{ {
Connection = clientSignInState.Connection, Connection = clientSignInState.Connection,
MessengerId = (ushort)TunnelMessengerIds.RouteLevelForward, MessengerId = (ushort)TunnelMessengerIds.RouteLevelForward,
Payload = MemoryPackSerializer.Serialize(tunnelTransportConfigWrapInfo) Payload = MemoryPackSerializer.Serialize(tunnelTransportFileConfigInfo)
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
@@ -141,7 +141,6 @@ namespace linker.plugins.tunnel
tunnelConfigTransfer.SettExcludeIPs(info); tunnelConfigTransfer.SettExcludeIPs(info);
} }
public sealed class TunnelListInfo public sealed class TunnelListInfo
{ {
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> List { get; set; } public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> List { get; set; }

View File

@@ -12,7 +12,7 @@ namespace linker.plugins.tunnel
{ {
public sealed class TunnelConfigTransfer public sealed class TunnelConfigTransfer
{ {
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly RunningConfig running; private readonly RunningConfig running;
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
@@ -26,7 +26,7 @@ namespace linker.plugins.tunnel
private ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> configs = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>(); private ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> configs = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>();
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config => configs; public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config => configs;
public TunnelConfigTransfer(ConfigWrap config, RunningConfig running, ClientSignInState clientSignInState, MessengerSender messengerSender, RunningConfigTransfer runningConfigTransfer, ITunnelAdapter tunnelAdapter) public TunnelConfigTransfer(FileConfig config, RunningConfig running, ClientSignInState clientSignInState, MessengerSender messengerSender, RunningConfigTransfer runningConfigTransfer, ITunnelAdapter tunnelAdapter)
{ {
this.config = config; this.config = config;
this.running = running; this.running = running;
@@ -90,21 +90,21 @@ namespace linker.plugins.tunnel
/// <summary> /// <summary>
/// 修改自己的网关层级信息 /// 修改自己的网关层级信息
/// </summary> /// </summary>
/// <param name="tunnelTransportConfigWrapInfo"></param> /// <param name="tunnelTransportFileConfigInfo"></param>
public void OnLocalRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportConfigWrapInfo) public void OnLocalRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo)
{ {
running.Data.Tunnel.RouteLevelPlus = tunnelTransportConfigWrapInfo.RouteLevelPlus; running.Data.Tunnel.RouteLevelPlus = tunnelTransportFileConfigInfo.RouteLevelPlus;
running.Data.Update(); running.Data.Update();
GetRemoveRouteLevel(); GetRemoveRouteLevel();
} }
/// <summary> /// <summary>
/// 收到别人发给我的修改我的信息 /// 收到别人发给我的修改我的信息
/// </summary> /// </summary>
/// <param name="tunnelTransportConfigWrapInfo"></param> /// <param name="tunnelTransportFileConfigInfo"></param>
/// <returns></returns> /// <returns></returns>
public TunnelTransportRouteLevelInfo OnRemoteRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportConfigWrapInfo) public TunnelTransportRouteLevelInfo OnRemoteRouteLevel(TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo)
{ {
configs.AddOrUpdate(tunnelTransportConfigWrapInfo.MachineId, tunnelTransportConfigWrapInfo, (a, b) => tunnelTransportConfigWrapInfo); configs.AddOrUpdate(tunnelTransportFileConfigInfo.MachineId, tunnelTransportFileConfigInfo, (a, b) => tunnelTransportFileConfigInfo);
Interlocked.Increment(ref version); Interlocked.Increment(ref version);
return GetLocalRouteLevel(); return GetLocalRouteLevel();
} }

View File

@@ -27,7 +27,7 @@ namespace linker.plugins.tunnel
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
//序列化扩展 //序列化扩展
MemoryPackFormatterProvider.Register(new TunnelWanPortInfoFormatter()); MemoryPackFormatterProvider.Register(new TunnelWanPortInfoFormatter());
@@ -66,7 +66,7 @@ namespace linker.plugins.tunnel
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
MemoryPackFormatterProvider.Register(new TunnelWanPortInfoFormatter()); MemoryPackFormatterProvider.Register(new TunnelWanPortInfoFormatter());
MemoryPackFormatterProvider.Register(new TunnelTransportWanPortInfoFormatter()); MemoryPackFormatterProvider.Register(new TunnelTransportWanPortInfoFormatter());
@@ -77,7 +77,7 @@ namespace linker.plugins.tunnel
serviceCollection.AddSingleton<TunnelServerMessenger>(); serviceCollection.AddSingleton<TunnelServerMessenger>();
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
ITunnelAdapter tunnelAdapter = serviceProvider.GetService<ITunnelAdapter>(); ITunnelAdapter tunnelAdapter = serviceProvider.GetService<ITunnelAdapter>();
@@ -95,7 +95,7 @@ namespace linker.plugins.tunnel
TunnelConfigTransfer tunnelConfigTransfer = serviceProvider.GetService<TunnelConfigTransfer>(); TunnelConfigTransfer tunnelConfigTransfer = serviceProvider.GetService<TunnelConfigTransfer>();
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }

View File

@@ -6,24 +6,37 @@ using MemoryPack;
using System.Net; using System.Net;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using linker.tunnel.adapter; using linker.tunnel.adapter;
using System.Net.Sockets;
namespace linker.client.config namespace linker.client.config
{ {
public sealed partial class RunningConfigInfo public sealed partial class RunningConfigInfo
{ {
/// <summary>
/// 打洞配置
/// </summary>
public TunnelRunningInfo Tunnel { get; set; } = new TunnelRunningInfo(); public TunnelRunningInfo Tunnel { get; set; } = new TunnelRunningInfo();
} }
public sealed class TunnelRunningInfo public sealed class TunnelRunningInfo
{ {
public ObjectId Id { get; set; } public ObjectId Id { get; set; }
/// <summary>
/// 外网端口服务器列表
/// </summary>
public List<TunnelWanPortInfo> Servers { get; set; } = new List<TunnelWanPortInfo>(); public List<TunnelWanPortInfo> Servers { get; set; } = new List<TunnelWanPortInfo>();
/// <summary>
/// 附加的网关层级
/// </summary>
public int RouteLevelPlus { get; set; } = 0; public int RouteLevelPlus { get; set; } = 0;
/// <summary>
/// 打洞排除IP列表
/// </summary>
public ExcludeIPItem[] ExcludeIPs { get; set; } = Array.Empty<ExcludeIPItem>(); public ExcludeIPItem[] ExcludeIPs { get; set; } = Array.Empty<ExcludeIPItem>();
/// <summary>
/// 打洞协议列表
/// </summary>
public List<TunnelTransportItemInfo> Transports { get; set; } = new List<TunnelTransportItemInfo>(); public List<TunnelTransportItemInfo> Transports { get; set; } = new List<TunnelTransportItemInfo>();
} }

View File

@@ -68,15 +68,15 @@ namespace linker.plugins.tunnel.messenger
[MessengerId((ushort)TunnelMessengerIds.RouteLevel)] [MessengerId((ushort)TunnelMessengerIds.RouteLevel)]
public void RouteLevel(IConnection connection) public void RouteLevel(IConnection connection)
{ {
TunnelTransportRouteLevelInfo tunnelTransportConfigWrapInfo = MemoryPackSerializer.Deserialize<TunnelTransportRouteLevelInfo>(connection.ReceiveRequestWrap.Payload.Span); TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo = MemoryPackSerializer.Deserialize<TunnelTransportRouteLevelInfo>(connection.ReceiveRequestWrap.Payload.Span);
tunnelConfigTransfer.OnLocalRouteLevel(tunnelTransportConfigWrapInfo); tunnelConfigTransfer.OnLocalRouteLevel(tunnelTransportFileConfigInfo);
} }
[MessengerId((ushort)TunnelMessengerIds.Config)] [MessengerId((ushort)TunnelMessengerIds.Config)]
public void Config(IConnection connection) public void Config(IConnection connection)
{ {
TunnelTransportRouteLevelInfo tunnelTransportConfigWrapInfo = MemoryPackSerializer.Deserialize<TunnelTransportRouteLevelInfo>(connection.ReceiveRequestWrap.Payload.Span); TunnelTransportRouteLevelInfo tunnelTransportFileConfigInfo = MemoryPackSerializer.Deserialize<TunnelTransportRouteLevelInfo>(connection.ReceiveRequestWrap.Payload.Span);
TunnelTransportRouteLevelInfo result = tunnelConfigTransfer.OnRemoteRouteLevel(tunnelTransportConfigWrapInfo); TunnelTransportRouteLevelInfo result = tunnelConfigTransfer.OnRemoteRouteLevel(tunnelTransportFileConfigInfo);
connection.Write(MemoryPackSerializer.Serialize(result)); connection.Write(MemoryPackSerializer.Serialize(result));
} }

View File

@@ -19,10 +19,10 @@ namespace linker.plugins.tuntap
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
private readonly TuntapTransfer tuntapTransfer; private readonly TuntapTransfer tuntapTransfer;
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly TuntapProxy tuntapProxy; private readonly TuntapProxy tuntapProxy;
public TuntapClientApiController(MessengerSender messengerSender, TuntapTransfer tuntapTransfer, ClientSignInState clientSignInState, ConfigWrap config, TuntapProxy tuntapProxy) public TuntapClientApiController(MessengerSender messengerSender, TuntapTransfer tuntapTransfer, ClientSignInState clientSignInState, FileConfig config, TuntapProxy tuntapProxy)
{ {
this.messengerSender = messengerSender; this.messengerSender = messengerSender;
this.tuntapTransfer = tuntapTransfer; this.tuntapTransfer = tuntapTransfer;

View File

@@ -21,7 +21,7 @@ namespace linker.plugins.tuntap
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
//不同平台下的虚拟网卡 //不同平台下的虚拟网卡
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<ITuntapVea, TuntapVeaWindows>(); if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<ITuntapVea, TuntapVeaWindows>();
@@ -35,18 +35,18 @@ namespace linker.plugins.tuntap
serviceCollection.AddSingleton<TuntapClientMessenger>(); serviceCollection.AddSingleton<TuntapClientMessenger>();
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<TuntapServerMessenger>(); serviceCollection.AddSingleton<TuntapServerMessenger>();
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
TuntapProxy tuntapProxy = serviceProvider.GetService<TuntapProxy>(); TuntapProxy tuntapProxy = serviceProvider.GetService<TuntapProxy>();
TuntapTransfer tuntapTransfer = serviceProvider.GetService<TuntapTransfer>(); TuntapTransfer tuntapTransfer = serviceProvider.GetService<TuntapTransfer>();
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -21,7 +21,7 @@ namespace linker.plugins.tuntap
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly ITuntapVea tuntapVea; private readonly ITuntapVea tuntapVea;
private readonly ConfigWrap config; private readonly FileConfig config;
private readonly TuntapProxy tuntapProxy; private readonly TuntapProxy tuntapProxy;
private readonly RunningConfig runningConfig; private readonly RunningConfig runningConfig;
@@ -34,7 +34,7 @@ namespace linker.plugins.tuntap
private bool starting = false; private bool starting = false;
public TuntapStatus Status => tuntapVea.Running ? TuntapStatus.Running : (starting ? TuntapStatus.Starting : TuntapStatus.Normal); public TuntapStatus Status => tuntapVea.Running ? TuntapStatus.Running : (starting ? TuntapStatus.Starting : TuntapStatus.Normal);
public TuntapTransfer(MessengerSender messengerSender, ClientSignInState clientSignInState, ITuntapVea tuntapVea, ConfigWrap config, TuntapProxy tuntapProxy, RunningConfig runningConfig) public TuntapTransfer(MessengerSender messengerSender, ClientSignInState clientSignInState, ITuntapVea tuntapVea, FileConfig config, TuntapProxy tuntapProxy, RunningConfig runningConfig)
{ {
this.messengerSender = messengerSender; this.messengerSender = messengerSender;
this.clientSignInState = clientSignInState; this.clientSignInState = clientSignInState;

View File

@@ -20,13 +20,22 @@ namespace linker.plugins.tuntap.config
} }
public uint IpInt { get; private set; } public uint IpInt { get; private set; }
/// <summary>
/// 缓冲区大小
/// </summary>
public byte BufferSize { get; set; } = 3; public byte BufferSize { get; set; } = 3;
/// <summary> /// <summary>
/// 局域网IP列表 /// 局域网IP列表
/// </summary> /// </summary>
public IPAddress[] LanIPs { get; set; } = Array.Empty<IPAddress>(); public IPAddress[] LanIPs { get; set; } = Array.Empty<IPAddress>();
/// <summary>
/// 局域网掩码列表与IP列表一一对应
/// </summary>
public int[] Masks { get; set; } = Array.Empty<int>(); public int[] Masks { get; set; } = Array.Empty<int>();
/// <summary>
/// 是否在运行中
/// </summary>
public bool Running { get; set; } public bool Running { get; set; }
} }
} }
@@ -36,6 +45,9 @@ namespace linker.client.config
{ {
public sealed partial class RunningConfigInfo public sealed partial class RunningConfigInfo
{ {
/// <summary>
/// 虚拟网卡配置
/// </summary>
public TuntapConfigInfo Tuntap { get; set; } = new TuntapConfigInfo(); public TuntapConfigInfo Tuntap { get; set; } = new TuntapConfigInfo();
} }
} }

View File

@@ -20,7 +20,7 @@ namespace linker.plugins.tuntap.proxy
private readonly TunnelTransfer tunnelTransfer; private readonly TunnelTransfer tunnelTransfer;
private readonly RelayTransfer relayTransfer; private readonly RelayTransfer relayTransfer;
private readonly RunningConfig runningConfig; private readonly RunningConfig runningConfig;
private readonly ConfigWrap config; private readonly FileConfig config;
private IPEndPoint proxyEP; private IPEndPoint proxyEP;
public override IPAddress UdpBindAdress { get; set; } public override IPAddress UdpBindAdress { get; set; }
@@ -30,7 +30,7 @@ namespace linker.plugins.tuntap.proxy
private readonly ConcurrentDictionary<string, ITunnelConnection> connections = new ConcurrentDictionary<string, ITunnelConnection>(); private readonly ConcurrentDictionary<string, ITunnelConnection> connections = new ConcurrentDictionary<string, ITunnelConnection>();
private readonly ConcurrentDictionary<string, SemaphoreSlim> dicLocks = new ConcurrentDictionary<string, SemaphoreSlim>(); private readonly ConcurrentDictionary<string, SemaphoreSlim> dicLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
public TuntapProxy(TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, RunningConfig runningConfig, ConfigWrap config) public TuntapProxy(TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, RunningConfig runningConfig, FileConfig config)
{ {
this.tunnelTransfer = tunnelTransfer; this.tunnelTransfer = tunnelTransfer;
this.relayTransfer = relayTransfer; this.relayTransfer = relayTransfer;
@@ -60,6 +60,10 @@ namespace linker.plugins.tuntap.proxy
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Warning($"tuntap add connection {connection.GetHashCode()} {connection.ToJson()}"); LoggerHelper.Instance.Warning($"tuntap add connection {connection.GetHashCode()} {connection.ToJson()}");
if(connections.TryGetValue(connection.RemoteMachineId,out ITunnelConnection connectionOld))
{
connectionOld?.Dispose();
}
connections.AddOrUpdate(connection.RemoteMachineId, connection, (a, b) => connection); connections.AddOrUpdate(connection.RemoteMachineId, connection, (a, b) => connection);
BindConnectionReceive(connection); BindConnectionReceive(connection);
} }
@@ -245,7 +249,6 @@ namespace linker.plugins.tuntap.proxy
try try
{ {
if (connections.TryGetValue(machineId, out connection) && connection.Connected) if (connections.TryGetValue(machineId, out connection) && connection.Connected)
{ {
return connection; return connection;
@@ -262,10 +265,10 @@ namespace linker.plugins.tuntap.proxy
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap relay to {machineId}"); if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap relay to {machineId}");
tunnelTransfer.StartBackground(machineId, "tuntap");
connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "tuntap").ConfigureAwait(false); connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "tuntap").ConfigureAwait(false);
if (connection != null) if (connection != null)
{ {
tunnelTransfer.StartBackground(machineId, "tuntap");
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap relay success,{connection.ToString()}"); if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap relay success,{connection.ToString()}");
} }
} }

View File

@@ -19,15 +19,15 @@ namespace linker.plugins.updater
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
foreach (var item in Process.GetProcessesByName("linker.updater")) foreach (var item in Process.GetProcessesByName("linker.updater"))
{ {
@@ -36,7 +36,7 @@ namespace linker.plugins.updater
//CommandHelper.Execute(); //CommandHelper.Execute();
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -17,24 +17,24 @@ namespace linker.serializes
public string[] Dependent => Array.Empty<string>(); public string[] Dependent => Array.Empty<string>();
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
MemoryPackFormatterProvider.Register(new IPEndPointFormatter()); MemoryPackFormatterProvider.Register(new IPEndPointFormatter());
MemoryPackFormatterProvider.Register(new IPAddressFormatter()); MemoryPackFormatterProvider.Register(new IPAddressFormatter());
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
MemoryPackFormatterProvider.Register(new IPEndPointFormatter()); MemoryPackFormatterProvider.Register(new IPEndPointFormatter());
MemoryPackFormatterProvider.Register(new IPAddressFormatter()); MemoryPackFormatterProvider.Register(new IPAddressFormatter());
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }

View File

@@ -16,7 +16,7 @@ namespace linker.server
public interface IConnection public interface IConnection
{ {
/// <summary> /// <summary>
/// 连接id /// 连接id存的应该是客户端id
/// </summary> /// </summary>
public string Id { get; set; } public string Id { get; set; }
/// <summary> /// <summary>

View File

@@ -17,14 +17,14 @@ namespace linker.server
public string[] Dependent => new string[] { "serialize", "firewall", "signin" }; public string[] Dependent => new string[] { "serialize", "firewall", "signin" };
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<MessengerSender>(); serviceCollection.AddSingleton<MessengerSender>();
serviceCollection.AddSingleton<MessengerResolver>(); serviceCollection.AddSingleton<MessengerResolver>();
serviceCollection.AddSingleton<TcpServer>(); serviceCollection.AddSingleton<TcpServer>();
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
serviceCollection.AddSingleton<MessengerSender>(); serviceCollection.AddSingleton<MessengerSender>();
serviceCollection.AddSingleton<MessengerResolver>(); serviceCollection.AddSingleton<MessengerResolver>();
@@ -34,7 +34,7 @@ namespace linker.server
private bool loaded = false; private bool loaded = false;
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
if (loaded == false) if (loaded == false)
{ {
@@ -44,7 +44,7 @@ namespace linker.server
} }
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
if (loaded == false) if (loaded == false)
{ {
@@ -59,7 +59,10 @@ namespace linker.server
//服务 //服务
TcpServer tcpServer = serviceProvider.GetService<TcpServer>(); TcpServer tcpServer = serviceProvider.GetService<TcpServer>();
tcpServer.Init(config.Data.Server.Certificate, config.Data.Server.Password); tcpServer.Init(config.Data.Server.Certificate, config.Data.Server.Password);
tcpServer.Start(config.Data.Server.ServicePort); if(config.Data.Server.ServicePort > 0)
{
tcpServer.Start(config.Data.Server.ServicePort);
}
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -27,11 +27,11 @@ namespace linker.startup
/// </summary> /// </summary>
public StartupLoadType LoadType { get; } public StartupLoadType LoadType { get; }
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies); public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies);
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies); public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies);
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies); public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies);
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies); public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies);
} }
public enum StartupLoadType public enum StartupLoadType

View File

@@ -13,7 +13,7 @@ namespace linker.startup
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config"></param>
/// <param name="assemblies"></param> /// <param name="assemblies"></param>
public static void Init(ConfigWrap config, Assembly[] assemblies) public static void Init(FileConfig config, Assembly[] assemblies)
{ {
var types = ReflectionHelper.GetInterfaceSchieves(assemblies, typeof(IStartup)); var types = ReflectionHelper.GetInterfaceSchieves(assemblies, typeof(IStartup));
List<IStartup> temps = types.Select(c => Activator.CreateInstance(c) as IStartup).OrderByDescending(c => c.Level).ToList(); List<IStartup> temps = types.Select(c => Activator.CreateInstance(c) as IStartup).OrderByDescending(c => c.Level).ToList();
@@ -41,7 +41,7 @@ namespace linker.startup
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config"></param>
/// <param name="temps"></param> /// <param name="temps"></param>
private static void LoadPlugins(ConfigWrap config, List<IStartup> temps) private static void LoadPlugins(FileConfig config, List<IStartup> temps)
{ {
//只要哪些 //只要哪些
if (config.Data.Common.IncludePlugins.Length > 0) if (config.Data.Common.IncludePlugins.Length > 0)
@@ -84,7 +84,7 @@ namespace linker.startup
/// <param name="serviceCollection"></param> /// <param name="serviceCollection"></param>
/// <param name="config"></param> /// <param name="config"></param>
/// <param name="assemblies"></param> /// <param name="assemblies"></param>
public static void Add(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public static void Add(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
foreach (var startup in startups) foreach (var startup in startups)
{ {
@@ -101,7 +101,7 @@ namespace linker.startup
/// <param name="serviceProvider"></param> /// <param name="serviceProvider"></param>
/// <param name="config"></param> /// <param name="config"></param>
/// <param name="assemblies"></param> /// <param name="assemblies"></param>
public static void Use(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public static void Use(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
foreach (var startup in startups) foreach (var startup in startups)
{ {

View File

@@ -17,17 +17,17 @@ namespace linker.store
public StartupLoadType LoadType => StartupLoadType.Normal; public StartupLoadType LoadType => StartupLoadType.Normal;
bool loaded = false; bool loaded = false;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
Add(serviceCollection, config, assemblies); Add(serviceCollection, config, assemblies);
} }
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
Add(serviceCollection, config, assemblies); Add(serviceCollection, config, assemblies);
} }
private void Add(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies) private void Add(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
if (loaded == false) if (loaded == false)
{ {
@@ -36,11 +36,11 @@ namespace linker.store
} }
} }
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies) public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
{ {
} }
} }