mirror of
https://github.com/snltty/linker.git
synced 2025-10-14 21:25:51 +08:00
sync
This commit is contained in:
@@ -42,6 +42,7 @@ namespace linker.tunnel
|
|||||||
}
|
}
|
||||||
|
|
||||||
var transportItems = tunnelAdapter.GetTunnelTransports();
|
var transportItems = tunnelAdapter.GetTunnelTransports();
|
||||||
|
var names = transportItems.Select(c => c.Name);
|
||||||
transportItems = transportItems.Concat(transports.Select(c => new TunnelTransportItemInfo
|
transportItems = transportItems.Concat(transports.Select(c => new TunnelTransportItemInfo
|
||||||
{
|
{
|
||||||
Label = c.Label,
|
Label = c.Label,
|
||||||
@@ -74,8 +75,7 @@ namespace linker.tunnel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tunnelAdapter.SetTunnelTransports(transportItems, names.SequenceEqual(transportItems.Select(c => c.Name)) == false);
|
||||||
tunnelAdapter.SetTunnelTransports(transportItems);
|
|
||||||
|
|
||||||
LoggerHelper.Instance.Warning($"load tunnel transport:{string.Join(",", transports.Select(c => c.Name))}");
|
LoggerHelper.Instance.Warning($"load tunnel transport:{string.Join(",", transports.Select(c => c.Name))}");
|
||||||
LoggerHelper.Instance.Warning($"used tunnel transport:{string.Join(",", transportItems.Where(c => c.Disabled == false).Select(c => c.Name))}");
|
LoggerHelper.Instance.Warning($"used tunnel transport:{string.Join(",", transportItems.Where(c => c.Disabled == false).Select(c => c.Name))}");
|
||||||
@@ -136,7 +136,7 @@ namespace linker.tunnel
|
|||||||
|
|
||||||
foreach (var wanPortProtocol in tunnelAdapter.GetTunnelWanPortProtocols().Where(c => c.Disabled == false && string.IsNullOrWhiteSpace(c.Host) == false))
|
foreach (var wanPortProtocol in tunnelAdapter.GetTunnelWanPortProtocols().Where(c => c.Disabled == false && string.IsNullOrWhiteSpace(c.Host) == false))
|
||||||
{
|
{
|
||||||
|
|
||||||
//这个打洞协议不支持这个外网端口协议
|
//这个打洞协议不支持这个外网端口协议
|
||||||
if ((transport.AllowWanPortProtocolType & wanPortProtocol.ProtocolType) != wanPortProtocol.ProtocolType)
|
if ((transport.AllowWanPortProtocolType & wanPortProtocol.ProtocolType) != wanPortProtocol.ProtocolType)
|
||||||
{
|
{
|
||||||
|
@@ -26,7 +26,7 @@ namespace linker.tunnel.adapter
|
|||||||
/// 保存外网端口协议列表
|
/// 保存外网端口协议列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="compacts"></param>
|
/// <param name="compacts"></param>
|
||||||
public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> protocols);
|
public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> protocols,bool updateVersion);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取打洞协议列表
|
/// 获取打洞协议列表
|
||||||
@@ -37,7 +37,7 @@ namespace linker.tunnel.adapter
|
|||||||
/// 保存打洞协议列表
|
/// 保存打洞协议列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="transports"></param>
|
/// <param name="transports"></param>
|
||||||
public void SetTunnelTransports(List<TunnelTransportItemInfo> transports);
|
public void SetTunnelTransports(List<TunnelTransportItemInfo> transports, bool updateVersion);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取本地网络信息
|
/// 获取本地网络信息
|
||||||
|
@@ -14,6 +14,7 @@ namespace linker.tunnel.wanport
|
|||||||
|
|
||||||
public TunnelWanPortTransfer()
|
public TunnelWanPortTransfer()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -10,6 +10,9 @@ export const removeForwardConnection = (id) => {
|
|||||||
export const getForwardInfo = () => {
|
export const getForwardInfo = () => {
|
||||||
return sendWebsocketMsg('forwardclient/get');
|
return sendWebsocketMsg('forwardclient/get');
|
||||||
}
|
}
|
||||||
|
export const getForwardRemoteInfo = (data) => {
|
||||||
|
return sendWebsocketMsg('forwardclient/getremote', data);
|
||||||
|
}
|
||||||
export const getForwardIpv4 = () => {
|
export const getForwardIpv4 = () => {
|
||||||
return sendWebsocketMsg('forwardclient/bindips');
|
return sendWebsocketMsg('forwardclient/bindips');
|
||||||
}
|
}
|
||||||
|
5
linker.web/src/apis/running.js
Normal file
5
linker.web/src/apis/running.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { sendWebsocketMsg } from './request'
|
||||||
|
|
||||||
|
export const updateVersion = (data) => {
|
||||||
|
return sendWebsocketMsg('RunningConfig/UpdateVersion', data);
|
||||||
|
}
|
@@ -9,6 +9,9 @@ export const setSForwardSecretKey = (data) => {
|
|||||||
export const getSForwardInfo = () => {
|
export const getSForwardInfo = () => {
|
||||||
return sendWebsocketMsg('sforwardclient/get');
|
return sendWebsocketMsg('sforwardclient/get');
|
||||||
}
|
}
|
||||||
|
export const getSForwardRemoteInfo = (data) => {
|
||||||
|
return sendWebsocketMsg('sforwardclient/getremote', data);
|
||||||
|
}
|
||||||
export const removeSForwardInfo = (id) => {
|
export const removeSForwardInfo = (id) => {
|
||||||
return sendWebsocketMsg('sforwardclient/remove', id);
|
return sendWebsocketMsg('sforwardclient/remove', id);
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,9 @@ export const getSignInfo = () => {
|
|||||||
export const getSignInList = (data) => {
|
export const getSignInList = (data) => {
|
||||||
return sendWebsocketMsg('signInclient/List', data);
|
return sendWebsocketMsg('signInclient/List', data);
|
||||||
}
|
}
|
||||||
|
export const getSignInIds = (data) => {
|
||||||
|
return sendWebsocketMsg('signInclient/ids', data);
|
||||||
|
}
|
||||||
export const signInDel = (machineId) => {
|
export const signInDel = (machineId) => {
|
||||||
return sendWebsocketMsg('signInclient/del', machineId);
|
return sendWebsocketMsg('signInclient/del', machineId);
|
||||||
}
|
}
|
||||||
|
@@ -304,14 +304,11 @@ span.split-pad10 {
|
|||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table--border,
|
.el-table thead.is-group th.el-table__cell {
|
||||||
.el-table--group,
|
background: var(--el-table-header-bg-color) !important;
|
||||||
.el-table-filter,
|
|
||||||
.el-table td,
|
|
||||||
.el-table th.is-leaf {
|
|
||||||
border-color: var(--main-border-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.el-pagination.is-background .el-pager li:not(.disabled).active {
|
.el-pagination.is-background .el-pager li:not(.disabled).active {
|
||||||
background-color: var(--main-color);
|
background-color: var(--main-color);
|
||||||
}
|
}
|
||||||
|
@@ -20,105 +20,16 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-dialog class="options-center" title="管理接口" destroy-on-close v-model="showPort" center :show-close="false"
|
|
||||||
:close-on-click-modal="false" align-center width="200">
|
|
||||||
<div class="port-wrap t-c">
|
|
||||||
<div>
|
|
||||||
接口 : <el-input v-model="state.api" style="width:70%"></el-input>
|
|
||||||
</div>
|
|
||||||
<div class="pdt-10">
|
|
||||||
秘钥 : <el-input type="password" v-model="state.psd" style="width:70%"></el-input>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<el-button type="success" @click="handleConnect" plain>确 定</el-button>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { computed, onMounted, reactive, watch } from 'vue';
|
|
||||||
import { initWebsocket, subWebsocketState,closeWebsocket } from '../apis/request'
|
|
||||||
import { getConfig,getSignInfo } from '../apis/signin'
|
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
|
||||||
import { injectGlobalData } from '../provide';
|
|
||||||
import {Tools,StarFilled,WarnTriangleFilled} from '@element-plus/icons-vue'
|
import {Tools,StarFilled,WarnTriangleFilled} from '@element-plus/icons-vue'
|
||||||
export default {
|
export default {
|
||||||
components:{Tools,StarFilled,WarnTriangleFilled},
|
components:{Tools,StarFilled,WarnTriangleFilled},
|
||||||
setup() {
|
setup() {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const queryCache = JSON.parse(localStorage.getItem('api-cache') || JSON.stringify({api:`${window.location.hostname}:1803`,psd:'snltty',groupid:'snltty'}));
|
|
||||||
const state = reactive({
|
|
||||||
api:queryCache.api,
|
|
||||||
psd:queryCache.psd,
|
|
||||||
groupid:globalData.value.groupid || queryCache.groupid,
|
|
||||||
showPort: false
|
|
||||||
});
|
|
||||||
const showPort = computed(() => globalData.value.connected == false && state.showPort);
|
|
||||||
|
|
||||||
const handleConnect = () => {
|
|
||||||
globalData.value.groupid = state.groupid;
|
|
||||||
queryCache.api = state.api;
|
|
||||||
queryCache.psd = state.psd;
|
|
||||||
queryCache.groupid = state.groupid;
|
|
||||||
localStorage.setItem('api-cache',JSON.stringify(queryCache));
|
|
||||||
|
|
||||||
closeWebsocket();
|
|
||||||
//initWebsocket(`ws://192.168.1.18:1803`,state.psd);
|
|
||||||
initWebsocket(`ws://${state.api}`,state.psd);
|
|
||||||
}
|
|
||||||
|
|
||||||
const _getConfig = ()=>{
|
|
||||||
getConfig().then((res)=>{
|
|
||||||
globalData.value.config.Common = res.Common;
|
|
||||||
globalData.value.config.Client = res.Client;
|
|
||||||
globalData.value.config.Running = res.Running;
|
|
||||||
globalData.value.configed = true;
|
|
||||||
setTimeout(()=>{
|
|
||||||
_getConfig();
|
|
||||||
},1000);
|
|
||||||
}).catch((err)=>{
|
|
||||||
setTimeout(()=>{
|
|
||||||
_getConfig();
|
|
||||||
},1000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const _getSignInfoInfo = ()=>{
|
|
||||||
getSignInfo().then((res)=>{
|
|
||||||
globalData.value.signin.Connected = res.Connected;
|
|
||||||
globalData.value.signin.Connecting = res.Connecting;
|
|
||||||
globalData.value.signin.Version = res.Version;
|
|
||||||
setTimeout(()=>{
|
|
||||||
_getSignInfoInfo();
|
|
||||||
},1000);
|
|
||||||
}).catch((err)=>{
|
|
||||||
setTimeout(()=>{
|
|
||||||
_getSignInfoInfo();
|
|
||||||
},1000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
setTimeout(() => { state.showPort = true; }, 100);
|
|
||||||
subWebsocketState((state) => { if (state) {
|
|
||||||
_getConfig();
|
|
||||||
_getSignInfoInfo();
|
|
||||||
}});
|
|
||||||
router.isReady().then(()=>{
|
|
||||||
state.api = route.query.api ?`${window.location.hostname}:${route.query.api}` : state.api;
|
|
||||||
state.psd = route.query.psd || state.psd;
|
|
||||||
state.groupid = route.query.groupid || state.groupid;
|
|
||||||
handleConnect();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state, showPort, handleConnect
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,20 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="status-api-wrap" :class="{connected:connected}">
|
<div class="status-api-wrap" :class="{connected:connected}">
|
||||||
<el-popconfirm confirm-button-text="是" cancel-button-text="否" title="确定清楚连接信息并刷新吗?" @confirm="handleResetConnect" >
|
<el-popconfirm confirm-button-text="清除" cancel-button-text="更改" title="确定你的惭怍?" @cancel="handleShow" @confirm="handleResetConnect" >
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<a href="javascript:;" >
|
<a href="javascript:;" >
|
||||||
<el-icon size="16"><Tools /></el-icon>
|
<el-icon size="16"><Tools /></el-icon>
|
||||||
<template v-if="connected">管理接口</template>
|
管理接口
|
||||||
<template v-else>管理接口</template>
|
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
</el-popconfirm>
|
</el-popconfirm>
|
||||||
|
<el-dialog class="options-center" title="管理接口" destroy-on-close v-model="showPort" center :show-close="false"
|
||||||
|
:close-on-click-modal="false" align-center width="200">
|
||||||
|
<div class="port-wrap t-c">
|
||||||
|
<div>
|
||||||
|
接口 : <el-input v-model="state.api" style="width:70%"></el-input>
|
||||||
|
</div>
|
||||||
|
<div class="pdt-10">
|
||||||
|
秘钥 : <el-input type="password" v-model="state.psd" style="width:70%"></el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button type="success" @click="handleConnect1" plain>确 定</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import {computed} from 'vue'
|
|
||||||
import {useRoute,useRouter} from 'vue-router'
|
import {useRoute,useRouter} from 'vue-router'
|
||||||
import {injectGlobalData} from '../../provide'
|
import {injectGlobalData} from '../../provide'
|
||||||
|
import { computed, onMounted, reactive } from 'vue';
|
||||||
|
import { initWebsocket, subWebsocketState,closeWebsocket } from '../../apis/request'
|
||||||
|
import { getConfig,getSignInfo } from '../../apis/signin'
|
||||||
import {Tools} from '@element-plus/icons-vue'
|
import {Tools} from '@element-plus/icons-vue'
|
||||||
export default {
|
export default {
|
||||||
components:{Tools},
|
components:{Tools},
|
||||||
@@ -24,13 +39,87 @@ export default {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
const defaultInfo = {api:`${window.location.hostname}:1803`,psd:'snltty'};
|
||||||
const handleResetConnect = () => {
|
const handleResetConnect = () => {
|
||||||
localStorage.setItem('api-cache', '');
|
localStorage.setItem('api-cache', '');
|
||||||
router.push({name:route.name});
|
router.push({name:route.name});
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
const queryCache = JSON.parse(localStorage.getItem('api-cache') || JSON.stringify(defaultInfo));
|
||||||
|
const state = reactive({
|
||||||
|
api:queryCache.api,
|
||||||
|
psd:queryCache.psd,
|
||||||
|
groupid:globalData.value.groupid || queryCache.groupid,
|
||||||
|
showPort: false
|
||||||
|
});
|
||||||
|
const showPort = computed(() => globalData.value.connected == false && state.showPort);
|
||||||
|
|
||||||
return {connected,handleResetConnect};
|
const handleConnect = () => {
|
||||||
|
globalData.value.groupid = state.groupid;
|
||||||
|
queryCache.api = state.api;
|
||||||
|
queryCache.psd = state.psd;
|
||||||
|
queryCache.groupid = state.groupid;
|
||||||
|
localStorage.setItem('api-cache',JSON.stringify(queryCache));
|
||||||
|
|
||||||
|
closeWebsocket();
|
||||||
|
initWebsocket(`ws://${state.api}`,state.psd);
|
||||||
|
}
|
||||||
|
const handleConnect1 = ()=>{
|
||||||
|
handleConnect();
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
const handleShow = ()=>{
|
||||||
|
//state.showPort = true;
|
||||||
|
closeWebsocket();
|
||||||
|
initWebsocket(`ws://${window.location.hostname}:12345`,state.psd);
|
||||||
|
}
|
||||||
|
|
||||||
|
const _getConfig = ()=>{
|
||||||
|
getConfig().then((res)=>{
|
||||||
|
globalData.value.config.Common = res.Common;
|
||||||
|
globalData.value.config.Client = res.Client;
|
||||||
|
globalData.value.config.Running = res.Running;
|
||||||
|
globalData.value.configed = true;
|
||||||
|
setTimeout(()=>{
|
||||||
|
_getConfig();
|
||||||
|
},1000);
|
||||||
|
}).catch((err)=>{
|
||||||
|
setTimeout(()=>{
|
||||||
|
_getConfig();
|
||||||
|
},1000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const _getSignInfoInfo = ()=>{
|
||||||
|
getSignInfo().then((res)=>{
|
||||||
|
globalData.value.signin.Connected = res.Connected;
|
||||||
|
globalData.value.signin.Connecting = res.Connecting;
|
||||||
|
globalData.value.signin.Version = res.Version;
|
||||||
|
setTimeout(()=>{
|
||||||
|
_getSignInfoInfo();
|
||||||
|
},1000);
|
||||||
|
}).catch((err)=>{
|
||||||
|
setTimeout(()=>{
|
||||||
|
_getSignInfoInfo();
|
||||||
|
},1000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => { state.showPort = true; }, 100);
|
||||||
|
subWebsocketState((state) => { if (state) {
|
||||||
|
_getConfig();
|
||||||
|
_getSignInfoInfo();
|
||||||
|
}});
|
||||||
|
router.isReady().then(()=>{
|
||||||
|
state.api = route.query.api ?`${window.location.hostname}:${route.query.api}` : state.api;
|
||||||
|
state.psd = route.query.psd || state.psd;
|
||||||
|
state.groupid = route.query.groupid || state.groupid;
|
||||||
|
handleConnect();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return { state, showPort, handleConnect1,connected,handleShow,handleResetConnect};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -15,7 +15,7 @@ import 'element-plus/theme-chalk/display.css'
|
|||||||
import 'element-plus/theme-chalk/dark/css-vars.css'
|
import 'element-plus/theme-chalk/dark/css-vars.css'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ArrowDown, Top, Bottom, Delete, Plus, Select, Refresh
|
ArrowDown, Top, Bottom, Delete, Plus, Select, Refresh, Search
|
||||||
} from '@element-plus/icons-vue'
|
} from '@element-plus/icons-vue'
|
||||||
app.component(ArrowDown.name, ArrowDown);
|
app.component(ArrowDown.name, ArrowDown);
|
||||||
app.component(Top.name, Top);
|
app.component(Top.name, Top);
|
||||||
@@ -24,6 +24,7 @@ app.component(Delete.name, Delete);
|
|||||||
app.component(Plus.name, Plus);
|
app.component(Plus.name, Plus);
|
||||||
app.component(Select.name, Select);
|
app.component(Select.name, Select);
|
||||||
app.component(Refresh.name, Refresh);
|
app.component(Refresh.name, Refresh);
|
||||||
|
app.component(Search.name, Search);
|
||||||
|
|
||||||
|
|
||||||
app.use(ElementPlus, { size: 'default' }).use(router).mount('#app');
|
app.use(ElementPlus, { size: 'default' }).use(router).mount('#app');
|
||||||
|
@@ -51,16 +51,17 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { onMounted, reactive, watch,inject,computed } from 'vue';
|
import { reactive, watch,computed } from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { useConnections, useForwardConnections, useTuntapConnections } from './connections';
|
||||||
export default {
|
export default {
|
||||||
props: ['modelValue'],
|
props: ['modelValue'],
|
||||||
emits: ['change','update:modelValue'],
|
emits: ['change','update:modelValue'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const connections = inject('connections');
|
const connections = useConnections();
|
||||||
const forwardConnections = inject('forward-connections');
|
const forwardConnections =useForwardConnections();
|
||||||
const tuntapConnections = inject('tuntap-connections');
|
const tuntapConnections = useTuntapConnections();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
show: true,
|
show: true,
|
||||||
protocolTypes:{1:'tcp',2:'udp',4:'msquic'},
|
protocolTypes:{1:'tcp',2:'udp',4:'msquic'},
|
||||||
|
@@ -3,12 +3,10 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<span class="flex-1">设备</span>
|
<span class="flex-1">设备</span>
|
||||||
<span> <el-input size="small" v-model="name" clearable @change="handleRefresh" >
|
<span> <el-input size="small" v-model="name" clearable @input="handleRefresh" placeholder="设备/虚拟网卡/端口转发" ></el-input> </span>
|
||||||
<template #prefix>
|
<span>
|
||||||
<el-icon><Search /></el-icon>
|
<el-button size="small" @click="handleRefresh"><el-icon><Search /></el-icon></el-button>
|
||||||
</template>
|
</span>
|
||||||
</el-input> </span>
|
|
||||||
<el-button size="small" @click="handleRefresh"><el-icon><Refresh /></el-icon></el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -71,7 +69,7 @@ a.green{color:green}
|
|||||||
.el-icon{vertical-align:middle}
|
.el-icon{vertical-align:middle}
|
||||||
}
|
}
|
||||||
.el-input{
|
.el-input{
|
||||||
width:8rem;
|
width:15rem;
|
||||||
margin-right:.6rem
|
margin-right:.6rem
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@@ -53,23 +53,27 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { inject } from 'vue';
|
import { useForward } from './forward';
|
||||||
|
import { useSforward } from './sforward';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
emits: ['edit','sedit'],
|
emits: ['edit','sedit'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const forward = inject('forward')
|
const forward = useForward()
|
||||||
const sforward = inject('sforward')
|
const sforward = useSforward()
|
||||||
const handleEdit = (machineId)=>{
|
const handleEdit = (machineId)=>{
|
||||||
emit('edit',machineId)
|
emit('edit',machineId)
|
||||||
}
|
}
|
||||||
const handleSEdit = ()=>{
|
const handleSEdit = ()=>{
|
||||||
emit('sedit')
|
emit('sedit')
|
||||||
}
|
}
|
||||||
|
const handleForwardRefresh = ()=>{
|
||||||
|
emit('refresh');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
forward,sforward, handleEdit,handleSEdit
|
forward,sforward, handleEdit,handleSEdit,handleForwardRefresh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
154
linker.web/src/views/devices/ForwardCopy.vue
Normal file
154
linker.web/src/views/devices/ForwardCopy.vue
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" title="复制端口转发" top="1vh" width="500">
|
||||||
|
<div>
|
||||||
|
<div class="t-c head">
|
||||||
|
<span>复制</span>
|
||||||
|
<el-select v-model="state.machineId" @change="handleMachineChange"
|
||||||
|
filterable remote :loading="state.loading" :remote-method="handleSearch">
|
||||||
|
<template #header>
|
||||||
|
<div class="t-c">
|
||||||
|
<div class="page-wrap">
|
||||||
|
<el-pagination small background layout="prev, pager, next"
|
||||||
|
:page-size="state.machineIds.Request.Size"
|
||||||
|
:total="state.machineIds.Count"
|
||||||
|
:pager-count="5"
|
||||||
|
:current-page="state.machineIds.Request.Page" @current-change="handlePageChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-option v-for="(item, index) in state.machineIds.List" :key="index" :label="item.MachineName" :value="item.MachineId">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<span>到【{{ state.toMachineName }}】的端口转发记录</span>
|
||||||
|
</div>
|
||||||
|
<el-table :data="state.forwards" size="small" border>
|
||||||
|
<el-table-column property="Name" label="名称"></el-table-column>
|
||||||
|
<el-table-column prop="BufferSize" label="缓冲区" width="60">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ (1<<scope.row.BufferSize) }}KB
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="Port" label="监听端口" width="80"></el-table-column>
|
||||||
|
<el-table-column property="TargetEP" label="目标服务" width="140"></el-table-column>
|
||||||
|
<el-table-column label="操作" width="80">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-checkbox v-model="scope.row.use">使用</el-checkbox>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="foot t-c">
|
||||||
|
<el-button type="primary" @click="handleConfirm">确定复制</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { onMounted, onUnmounted, reactive, watch } from 'vue';
|
||||||
|
import { getForwardRemoteInfo,addForwardInfo } from '@/apis/forward'
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import {WarnTriangleFilled} from '@element-plus/icons-vue'
|
||||||
|
import { injectGlobalData } from '@/provide';
|
||||||
|
import { useForward } from './forward';
|
||||||
|
import { getSignInIds } from '@/apis/signin';
|
||||||
|
export default {
|
||||||
|
props: ['modelValue'],
|
||||||
|
emits: ['update:modelValue'],
|
||||||
|
components:{WarnTriangleFilled},
|
||||||
|
setup(props, { emit }) {
|
||||||
|
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const forward = useForward();
|
||||||
|
const state = reactive({
|
||||||
|
show: true,
|
||||||
|
loading:false,
|
||||||
|
machineId: '',
|
||||||
|
toMachineId: forward.value.current,
|
||||||
|
toMachineName: forward.value.machineName,
|
||||||
|
machineIds:{
|
||||||
|
Request: {
|
||||||
|
Page: 1, Size:10, Name: ''
|
||||||
|
},
|
||||||
|
Count: 0,
|
||||||
|
List: []
|
||||||
|
},
|
||||||
|
forwards: []
|
||||||
|
});
|
||||||
|
watch(() => state.show, (val) => {
|
||||||
|
if (!val) {
|
||||||
|
setTimeout(() => {
|
||||||
|
emit('update:modelValue', val);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleOnShowList = () => {
|
||||||
|
_getMachineIds();
|
||||||
|
}
|
||||||
|
const _getMachineIds = ()=>{
|
||||||
|
state.loading = true;
|
||||||
|
getSignInIds(state.machineIds.Request).then((res)=>{
|
||||||
|
state.loading = false;
|
||||||
|
state.machineIds.Request = res.Request;
|
||||||
|
state.machineIds.Count = res.Count;
|
||||||
|
state.machineIds.List = res.List;
|
||||||
|
if(!state.machineId && state.machineIds.List.length > 0){
|
||||||
|
state.machineId = state.machineIds.List[0].MachineId;
|
||||||
|
_getForwardRemoteInfo();
|
||||||
|
}
|
||||||
|
}).catch((e)=>{
|
||||||
|
state.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const handlePageChange = (page)=>{
|
||||||
|
state.machineIds.Request.Page = page;
|
||||||
|
_getMachineIds();
|
||||||
|
}
|
||||||
|
const handleSearch = (name)=>{
|
||||||
|
state.machineIds.Request.Name = name;
|
||||||
|
_getMachineIds();
|
||||||
|
}
|
||||||
|
const _getForwardRemoteInfo = ()=>{
|
||||||
|
getForwardRemoteInfo({
|
||||||
|
MachineId: state.machineId,
|
||||||
|
ToMachineId: state.toMachineId
|
||||||
|
}).then((res)=>{
|
||||||
|
res.forEach(c=>{
|
||||||
|
c.use = true;
|
||||||
|
});
|
||||||
|
state.forwards = res;
|
||||||
|
}).catch((e)=>{
|
||||||
|
console.log(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const handleMachineChange = ()=>{
|
||||||
|
_getForwardRemoteInfo();
|
||||||
|
}
|
||||||
|
const handleConfirm = ()=>{
|
||||||
|
const tasks = state.forwards.filter(c=>c.use)
|
||||||
|
.map(c=>addForwardInfo({Name:c.Name,Port:c.Port,TargetEP:c.TargetEP,BufferSize:c.BufferSize,MachineId:state.toMachineId}));
|
||||||
|
Promise.all(tasks).then(()=>{
|
||||||
|
ElMessage.success('已操作!');
|
||||||
|
state.show = false;
|
||||||
|
}).catch(()=>{
|
||||||
|
ElMessage.success('操作失败!');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(()=>{
|
||||||
|
_getMachineIds();
|
||||||
|
});
|
||||||
|
onUnmounted(()=>{
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,handleSearch, handleOnShowList,handleMachineChange,handleConfirm,handlePageChange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.el-select{width : 12rem}
|
||||||
|
.head{padding-bottom:1rem}
|
||||||
|
.foot{padding-top:1rem}
|
||||||
|
.page-wrap{display:inline-block}
|
||||||
|
</style>
|
@@ -4,6 +4,7 @@
|
|||||||
<div class="t-c head">
|
<div class="t-c head">
|
||||||
<el-button type="success" size="small" @click="handleAdd">添加</el-button>
|
<el-button type="success" size="small" @click="handleAdd">添加</el-button>
|
||||||
<el-button size="small" @click="handleRefresh">刷新</el-button>
|
<el-button size="small" @click="handleRefresh">刷新</el-button>
|
||||||
|
<el-button size="small" @click="handleCopy">复制转发配置</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
||||||
<el-table-column property="Name" label="名称">
|
<el-table-column property="Name" label="名称">
|
||||||
@@ -96,11 +97,12 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { inject, onMounted, onUnmounted, reactive, watch } from 'vue';
|
import { onMounted, onUnmounted, reactive, watch } from 'vue';
|
||||||
import { getForwardInfo, removeForwardInfo, addForwardInfo ,getForwardIpv4,testTargetForwardInfo,testListenForwardInfo } from '@/apis/forward'
|
import { getForwardInfo, removeForwardInfo, addForwardInfo ,getForwardIpv4,testTargetForwardInfo,testListenForwardInfo } from '@/apis/forward'
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import {WarnTriangleFilled} from '@element-plus/icons-vue'
|
import {WarnTriangleFilled} from '@element-plus/icons-vue'
|
||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
|
import { useForward } from './forward';
|
||||||
export default {
|
export default {
|
||||||
props: ['data','modelValue'],
|
props: ['data','modelValue'],
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
@@ -108,7 +110,7 @@ export default {
|
|||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const forward = inject('forward');
|
const forward = useForward();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
show: true,
|
show: true,
|
||||||
machineId: forward.value.current,
|
machineId: forward.value.current,
|
||||||
@@ -210,11 +212,16 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleCopy = ()=>{
|
||||||
|
forward.value.showCopy = true;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
_getForwardInfo();
|
_getForwardInfo();
|
||||||
_getForwardIpv4();
|
_getForwardIpv4();
|
||||||
_testTargetForwardInfo();
|
_testTargetForwardInfo();
|
||||||
_testListenForwardInfo();
|
_testListenForwardInfo();
|
||||||
|
|
||||||
});
|
});
|
||||||
onUnmounted(()=>{
|
onUnmounted(()=>{
|
||||||
clearTimeout(state.timerTestTarget);
|
clearTimeout(state.timerTestTarget);
|
||||||
@@ -222,7 +229,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state, handleOnShowList, handleCellClick, handleRefresh, handleAdd, handleEdit, handleEditBlur, handleDel, handleStartChange
|
state, handleOnShowList, handleCellClick, handleRefresh, handleAdd, handleEdit, handleEditBlur, handleDel, handleStartChange,handleCopy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="home-list-wrap absolute" >
|
<div class="home-list-wrap absolute" >
|
||||||
<el-table :data="state.page.List" stripe border style="width: 100%" :height="`${state.height}px`" size="small">
|
<el-table :data="devices.page.List" stripe border style="width: 100%" :height="`${state.height}px`" size="small">
|
||||||
<Device @edit="handleDeviceEdit" @refresh="handlePageRefresh"></Device>
|
<Device @edit="handleDeviceEdit" @refresh="handlePageRefresh"></Device>
|
||||||
<Tunnel @edit="handleTunnelEdit" @refresh="handleTunnelRefresh" @connections="handleTunnelConnections"></Tunnel>
|
<Tunnel @edit="handleTunnelEdit" @refresh="handleTunnelRefresh" @connections="handleTunnelConnections"></Tunnel>
|
||||||
<Tuntap @edit="handleTuntapEdit" @refresh="handleTuntapRefresh"></Tuntap>
|
<Tuntap @edit="handleTuntapEdit" @refresh="handleTuntapRefresh"></Tuntap>
|
||||||
<Forward @edit="handleForwardEdit" @sedit="handleSForwardEdit" @refresh="handleForwardRefresh"></Forward>
|
<Forward @edit="_handleForwardEdit" @sedit="handleSForwardEdit"></Forward>
|
||||||
<el-table-column label="操作" width="54" fixed="right">
|
<el-table-column label="操作" width="54" fixed="right">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-popconfirm v-if="scope.row.showDel" confirm-button-text="确认"
|
<el-popconfirm v-if="scope.row.showDel" confirm-button-text="确认" cancel-button-text="取消" title="删除不可逆,是否确认?" @confirm="handleDel(scope.row.MachineId)">
|
||||||
cancel-button-text="取消" title="删除不可逆,是否确认?" @confirm="handleDel(scope.row.MachineId)">
|
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button type="danger" size="small"><el-icon><Delete /></el-icon></el-button>
|
<el-button type="danger" size="small"><el-icon><Delete /></el-icon></el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -18,28 +17,25 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
<div class="page t-c">
|
<div class="page t-c">
|
||||||
<div class="page-wrap">
|
<div class="page-wrap">
|
||||||
<el-pagination small background layout="total,prev, pager, next" :total="state.page.Count"
|
<el-pagination small background layout="total,sizes,prev,pager, next" :total="devices.page.Count"
|
||||||
:page-size="state.page.Request.Size" :current-page="state.page.Request.Page"
|
:page-size="devices.page.Request.Size" :current-page="devices.page.Request.Page"
|
||||||
@current-change="handlePageChange" />
|
@current-change="handlePageChange" @size-change="handlePageSizeChange" :page-sizes="[10, 20, 50, 100,255]" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DeviceEdit v-if="state.showDeviceEdit" v-model="state.showDeviceEdit" @change="handlePageChange" :data="state.deviceInfo"></DeviceEdit>
|
<DeviceEdit v-if="devices.showDeviceEdit" v-model="devices.showDeviceEdit" @change="handlePageChange" :data="devices.deviceInfo"></DeviceEdit>
|
||||||
<TunnelEdit v-if="tunnel.showEdit" v-model="tunnel.showEdit" @change="handleTunnelChange"></TunnelEdit>
|
<TunnelEdit v-if="tunnel.showEdit" v-model="tunnel.showEdit" @change="handleTunnelRefresh"></TunnelEdit>
|
||||||
<ConnectionsEdit v-if="connections.showEdit" v-model="connections.showEdit" ></ConnectionsEdit>
|
<ConnectionsEdit v-if="connections.showEdit" v-model="connections.showEdit" ></ConnectionsEdit>
|
||||||
<TuntapEdit v-if="tuntap.showEdit" v-model="tuntap.showEdit" @change="handleTuntapChange"></TuntapEdit>
|
<TuntapEdit v-if="tuntap.showEdit" v-model="tuntap.showEdit" @change="handleTuntapRefresh"></TuntapEdit>
|
||||||
<ForwardEdit v-if="forward.showEdit" v-model="forward.showEdit" @change="handleForwardChange"></ForwardEdit>
|
<ForwardEdit v-if="forward.showEdit" v-model="forward.showEdit" ></ForwardEdit>
|
||||||
<SForwardEdit v-if="sforward.showEdit" v-model="sforward.showEdit" @change="handleSForwardChange"></SForwardEdit>
|
<ForwardCopy v-if="forward.showCopy" v-model="forward.showCopy" ></ForwardCopy>
|
||||||
|
<SForwardEdit v-if="sforward.showEdit" v-model="sforward.showEdit" ></SForwardEdit>
|
||||||
|
<SForwardCopy v-if="sforward.showCopy" v-model="sforward.showCopy" ></SForwardCopy>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { getSignInList, signInDel } from '@/apis/signin.js'
|
|
||||||
import { subWebsocketState } from '@/apis/request.js'
|
import { subWebsocketState } from '@/apis/request.js'
|
||||||
import { getTuntapInfo,refreshTuntap,getTuntapConnections,removeTuntapConnection } from '@/apis/tuntap'
|
|
||||||
import { getForwardInfo ,testTargetForwardInfo,testListenForwardInfo,getForwardConnections,removeForwardConnection} from '@/apis/forward'
|
|
||||||
import { getSForwardInfo,testLocalSForwardInfo} from '@/apis/sforward'
|
|
||||||
import { getTunnelInfo ,refreshTunnel} from '@/apis/tunnel'
|
|
||||||
import { injectGlobalData } from '@/provide.js'
|
import { injectGlobalData } from '@/provide.js'
|
||||||
import { reactive, onMounted, ref, nextTick, onUnmounted, computed, provide } from 'vue'
|
import { reactive, onMounted, onUnmounted, computed } from 'vue'
|
||||||
import Device from './Device.vue'
|
import Device from './Device.vue'
|
||||||
import DeviceEdit from './DeviceEdit.vue'
|
import DeviceEdit from './DeviceEdit.vue'
|
||||||
import Tuntap from './Tuntap.vue'
|
import Tuntap from './Tuntap.vue'
|
||||||
@@ -48,334 +44,69 @@ import Tunnel from './Tunnel.vue'
|
|||||||
import TunnelEdit from './TunnelEdit.vue'
|
import TunnelEdit from './TunnelEdit.vue'
|
||||||
import Forward from './Forward.vue'
|
import Forward from './Forward.vue'
|
||||||
import ForwardEdit from './ForwardEdit.vue'
|
import ForwardEdit from './ForwardEdit.vue'
|
||||||
|
import ForwardCopy from './ForwardCopy.vue'
|
||||||
import SForwardEdit from './SForwardEdit.vue'
|
import SForwardEdit from './SForwardEdit.vue'
|
||||||
|
import SForwardCopy from './SForwardCopy.vue'
|
||||||
import ConnectionsEdit from './ConnectionsEdit.vue'
|
import ConnectionsEdit from './ConnectionsEdit.vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { provideTuntap } from './tuntap'
|
||||||
|
import { provideTunnel } from './tunnel'
|
||||||
|
import { provideForward } from './forward'
|
||||||
|
import { provideConnections } from './connections'
|
||||||
|
import { provideSforward } from './sforward'
|
||||||
|
import { provideDevices } from './devices'
|
||||||
export default {
|
export default {
|
||||||
components: {Device,DeviceEdit,Tunnel,TunnelEdit,ConnectionsEdit, Tuntap,TuntapEdit, Forward,ForwardEdit,SForwardEdit },
|
components: {Device,DeviceEdit,Tunnel,TunnelEdit,ConnectionsEdit, Tuntap,TuntapEdit, Forward,ForwardEdit,ForwardCopy,SForwardEdit,SForwardCopy },
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const machineId = computed(() => globalData.value.config.Client.Id);
|
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
timer:0,
|
|
||||||
page: {
|
|
||||||
Request: { Page: 1, Size: 10, GroupId: globalData.value.groupid,Name:'' },
|
|
||||||
Count: 0,
|
|
||||||
List: []
|
|
||||||
},
|
|
||||||
|
|
||||||
showDeviceEdit:false,
|
|
||||||
deviceInfo: null,
|
|
||||||
|
|
||||||
height: computed(()=>globalData.value.height-60),
|
height: computed(()=>globalData.value.height-60),
|
||||||
});
|
});
|
||||||
|
|
||||||
const tuntap = ref({
|
const {devices, machineId, _getSignList, _getSignList1,
|
||||||
timer:0,
|
handleDeviceEdit, handlePageChange, handlePageSizeChange, handleDel,clearDevicesTimeout} = provideDevices();
|
||||||
showEdit:false,
|
|
||||||
current: null,
|
|
||||||
list: {},
|
|
||||||
hashcode: 0,
|
|
||||||
});
|
|
||||||
provide('tuntap',tuntap);
|
|
||||||
const _getTuntapInfo = () => {
|
|
||||||
if (globalData.value.connected) {
|
|
||||||
getTuntapInfo(tuntap.value.hashcode.toString()).then((res) => {
|
|
||||||
tuntap.value.hashcode = res.HashCode;
|
|
||||||
if (res.List) {
|
|
||||||
for (let j in res.List) {
|
|
||||||
res.List[j].running = res.List[j].Status == 2;
|
|
||||||
res.List[j].loading = res.List[j].Status == 1;
|
|
||||||
}
|
|
||||||
tuntap.value.list = res.List;
|
|
||||||
}
|
|
||||||
tuntap.value.timer = setTimeout(_getTuntapInfo, 200);
|
|
||||||
}).catch(() => {
|
|
||||||
tuntap.value.timer = setTimeout(_getTuntapInfo, 200);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
tuntap.value.timer = setTimeout(_getTuntapInfo, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleTuntapEdit = (_tuntap)=>{
|
|
||||||
tuntap.value.current = _tuntap;
|
|
||||||
tuntap.value.showEdit = true;
|
|
||||||
|
|
||||||
}
|
const {tuntap,_getTuntapInfo,handleTuntapEdit,handleTuntapRefresh,clearTuntapTimeout,getTuntapMachines} = provideTuntap();
|
||||||
const handleTuntapChange = (page) => {
|
const {tunnel,_getTunnelInfo,handleTunnelEdit,handleTunnelRefresh,clearTunnelTimeout} = provideTunnel();
|
||||||
if(page){
|
const {forward,_getForwardInfo,handleForwardEdit,_testTargetForwardInfo,_testListenForwardInfo,clearForwardTimeout,getForwardMachines} = provideForward();
|
||||||
state.page.Request.Page = page;
|
const {sforward,_getSForwardInfo,handleSForwardEdit,_testLocalSForwardInfo,clearSForwardTimeout,getSForwardMachines} = provideSforward();
|
||||||
}
|
const {connections,
|
||||||
_getSignList();
|
forwardConnections,_getForwardConnections,
|
||||||
}
|
tuntapConnections,_getTuntapConnections,
|
||||||
const handleTuntapRefresh = ()=>{
|
handleTunnelConnections,clearConnectionsTimeout
|
||||||
refreshTuntap();
|
} = provideConnections();
|
||||||
ElMessage.success('刷新成功');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const tunnel = ref({
|
const _handleForwardEdit = (machineId) => {
|
||||||
timer:0,
|
handleForwardEdit(machineId,devices.page.List.filter(c => c.MachineId == machineId)[0].MachineName);
|
||||||
showEdit:false,
|
|
||||||
current: null,
|
|
||||||
list: {},
|
|
||||||
hashcode: 0,
|
|
||||||
});
|
|
||||||
provide('tunnel',tunnel);
|
|
||||||
const _getTunnelInfo = () => {
|
|
||||||
if (globalData.value.connected) {
|
|
||||||
getTunnelInfo(tunnel.value.hashcode.toString()).then((res) => {
|
|
||||||
tunnel.value.hashcode = res.HashCode;
|
|
||||||
if (res.List) {
|
|
||||||
tunnel.value.list = res.List;
|
|
||||||
}
|
|
||||||
tunnel.value.timer = setTimeout(_getTunnelInfo, 1000);
|
|
||||||
}).catch(() => {
|
|
||||||
tunnel.value.timer = setTimeout(_getTunnelInfo, 1000);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
tunnel.value.timer = setTimeout(_getTunnelInfo, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleTunnelEdit = (_tunnel)=>{
|
|
||||||
tunnel.value.current = _tunnel;
|
|
||||||
tunnel.value.showEdit = true;
|
|
||||||
}
|
|
||||||
const handleTunnelChange = () => {
|
|
||||||
_getSignList();
|
|
||||||
}
|
|
||||||
const handleTunnelRefresh = ()=>{
|
|
||||||
refreshTunnel();
|
|
||||||
ElMessage.success('刷新成功');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const connections = ref({
|
|
||||||
showEdit:false,
|
|
||||||
speedCache: {},
|
|
||||||
current:''
|
|
||||||
});
|
|
||||||
provide('connections',connections);
|
|
||||||
|
|
||||||
const forwardConnections = ref({
|
|
||||||
timer:0,
|
|
||||||
list: {},
|
|
||||||
});
|
|
||||||
provide('forward-connections',forwardConnections);
|
|
||||||
const _getForwardConnections = ()=>{
|
|
||||||
if (globalData.value.connected) {
|
|
||||||
getForwardConnections().then((res)=>{
|
|
||||||
parseConnections(res,removeForwardConnection);
|
|
||||||
forwardConnections.value.list = res;
|
|
||||||
forwardConnections.value.timer = setTimeout(_getForwardConnections, 1000);
|
|
||||||
}).catch((e)=>{
|
|
||||||
forwardConnections.value.timer = setTimeout(_getForwardConnections, 1000);
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
forwardConnections.value.timer = setTimeout(_getForwardConnections, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const tuntapConnections = ref({
|
|
||||||
timer:0,
|
|
||||||
list: {},
|
|
||||||
});
|
|
||||||
provide('tuntap-connections',tuntapConnections);
|
|
||||||
const _getTuntapConnections = ()=>{
|
|
||||||
if (globalData.value.connected) {
|
|
||||||
getTuntapConnections().then((res)=>{
|
|
||||||
parseConnections(res,removeTuntapConnection);
|
|
||||||
tuntapConnections.value.list = res;
|
|
||||||
tuntapConnections.value.timer = setTimeout(_getTuntapConnections, 1000);
|
|
||||||
}).catch((e)=>{
|
|
||||||
tuntapConnections.value.timer = setTimeout(_getTuntapConnections, 1000);
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
tuntapConnections.value.timer = setTimeout(_getTuntapConnections, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const parseConnections = (_connections,removeFunc)=>{
|
|
||||||
const caches = connections.value.speedCache;
|
|
||||||
for(let machineId in _connections){
|
|
||||||
const connection = _connections[machineId];
|
|
||||||
connection.removeFunc = removeFunc;
|
|
||||||
|
|
||||||
const key = `${connection.RemoteMachineId}-${connection.TransactionId}`;
|
|
||||||
const cache = caches[key] || {SendBytes:0,ReceiveBytes:0};
|
|
||||||
|
|
||||||
connection.SendBytesText = parseSpeed(connection.SendBytes - cache.SendBytes);
|
|
||||||
connection.ReceiveBytesText = parseSpeed(connection.ReceiveBytes - cache.ReceiveBytes);
|
|
||||||
|
|
||||||
cache.SendBytes = connection.SendBytes;
|
|
||||||
cache.ReceiveBytes = connection.ReceiveBytes;
|
|
||||||
caches[key] = cache;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const parseSpeed = (num)=>{
|
|
||||||
let index = 0;
|
|
||||||
while(num >= 1024){
|
|
||||||
num/=1024;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
return `${num.toFixed(2)}${['B/s','KB/s','MB/s','GB/s','TB/s'][index]}`;
|
|
||||||
}
|
|
||||||
const handleTunnelConnections = (machineId)=>{
|
|
||||||
connections.value.current = machineId;
|
|
||||||
connections.value.showEdit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const forward = ref({
|
|
||||||
timer:0,
|
|
||||||
showEdit:false,
|
|
||||||
current: null,
|
|
||||||
list: {}
|
|
||||||
});
|
|
||||||
provide('forward',forward);
|
|
||||||
const _getForwardInfo = () => {
|
|
||||||
if (globalData.value.connected) {
|
|
||||||
getForwardInfo().then((res) => {
|
|
||||||
forward.value.list = res;
|
|
||||||
|
|
||||||
forward.value.timer = setTimeout(_getForwardInfo, 1000);
|
|
||||||
}).catch(() => {
|
|
||||||
forward.value.timer = setTimeout(_getForwardInfo, 1000);
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
forward.value.timer = setTimeout(_getForwardInfo, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleForwardEdit = (machineId)=>{
|
|
||||||
forward.value.current = machineId;
|
|
||||||
forward.value.machineName =state.page.List.filter(c=>c.MachineId == machineId)[0].MachineName ;
|
|
||||||
forward.value.showEdit = true;
|
|
||||||
}
|
|
||||||
const handleForwardChange = () => {
|
|
||||||
_getSignList();
|
|
||||||
}
|
|
||||||
const handleForwardRefresh = ()=>{
|
|
||||||
_getSignList();
|
|
||||||
ElMessage.success('刷新成功');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const sforward = ref({
|
|
||||||
timer:0,
|
|
||||||
showEdit:false,
|
|
||||||
list: []
|
|
||||||
});
|
|
||||||
provide('sforward',sforward);
|
|
||||||
const _getSForwardInfo = () => {
|
|
||||||
if (globalData.value.connected) {
|
|
||||||
getSForwardInfo().then((res) => {
|
|
||||||
sforward.value.list = res;
|
|
||||||
sforward.value.timer = setTimeout(_getSForwardInfo, 1000);
|
|
||||||
}).catch(() => {
|
|
||||||
sforward.value.timer = setTimeout(_getSForwardInfo, 1000);
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
sforward.value.timer = setTimeout(_getSForwardInfo, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleSForwardEdit = ()=>{
|
|
||||||
sforward.value.showEdit = true;
|
|
||||||
}
|
|
||||||
const handleSForwardChange = () => {
|
|
||||||
_getSignList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _getSignList = () => {
|
|
||||||
state.page.Request.GroupId = globalData.value.groupid;
|
|
||||||
getSignInList(state.page.Request).then((res) => {
|
|
||||||
state.page.Request = res.Request;
|
|
||||||
state.page.Count = res.Count;
|
|
||||||
for (let j in res.List) {
|
|
||||||
res.List[j].showTunnel = machineId.value != res.List[j].MachineId;
|
|
||||||
res.List[j].showForward = machineId.value != res.List[j].MachineId;
|
|
||||||
res.List[j].showSForward = machineId.value == res.List[j].MachineId;
|
|
||||||
res.List[j].showDel = machineId.value != res.List[j].MachineId && res.List[j].Connected == false;
|
|
||||||
res.List[j].isSelf = machineId.value == res.List[j].MachineId;
|
|
||||||
}
|
|
||||||
state.page.List = res.List.sort((a,b)=>b.Connected - a.Connected);
|
|
||||||
}).catch((err) => { });
|
|
||||||
}
|
|
||||||
const _getSignList1 = () => {
|
|
||||||
if (globalData.value.connected) {
|
|
||||||
state.page.Request.GroupId = globalData.value.groupid;
|
|
||||||
getSignInList(state.page.Request).then((res) => {
|
|
||||||
for (let j in res.List) {
|
|
||||||
const item = state.page.List.filter(c=>c.MachineId == res.List[j].MachineId)[0];
|
|
||||||
if(item){
|
|
||||||
item.Connected = res.List[j].Connected;
|
|
||||||
item.Version = res.List[j].Version;
|
|
||||||
item.LastSignIn = res.List[j].LastSignIn;
|
|
||||||
item.Args = res.List[j].Args;
|
|
||||||
item.showTunnel = machineId.value != res.List[j].MachineId;
|
|
||||||
item.showForward = machineId.value != res.List[j].MachineId;
|
|
||||||
item.showSForward = machineId.value == res.List[j].MachineId;
|
|
||||||
item.showDel = machineId.value != res.List[j].MachineId && res.List[j].Connected == false;
|
|
||||||
item.isSelf = machineId.value == res.List[j].MachineId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.timer = setTimeout(_getSignList1, 5000);
|
|
||||||
}).catch((err) => {
|
|
||||||
state.timer = setTimeout(_getSignList1, 5000);
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
state.timer = setTimeout(_getSignList1, 5000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDeviceEdit = (row)=>{
|
|
||||||
state.deviceInfo = row;
|
|
||||||
state.showDeviceEdit = true;
|
|
||||||
}
|
|
||||||
const handlePageRefresh = (name)=>{
|
const handlePageRefresh = (name)=>{
|
||||||
state.page.Request.Name = name;
|
devices.page.Request.Name = name || '';
|
||||||
handlePageChange();
|
if(devices.page.Request.Name){
|
||||||
refreshTunnel();
|
devices.page.Request.Ids = getTuntapMachines(devices.page.Request.Name)
|
||||||
refreshTuntap();
|
.concat(getForwardMachines(devices.page.Request.Name))
|
||||||
ElMessage.success('刷新成功');
|
.concat(getSForwardMachines(devices.page.Request.Name))
|
||||||
}
|
.reduce((arr,id)=>{
|
||||||
const handlePageChange = (page) => {
|
if(arr.indexOf(id) == -1){
|
||||||
if(page){
|
arr.push(id);
|
||||||
state.page.Request.Page = page;
|
}
|
||||||
_getSignList();
|
return arr;
|
||||||
|
},[]);
|
||||||
|
}else{
|
||||||
|
devices.page.Request.Ids = [];
|
||||||
}
|
}
|
||||||
|
handlePageChange();
|
||||||
|
handleTunnelRefresh();
|
||||||
|
handleTuntapRefresh();
|
||||||
|
ElMessage.success({message:'刷新成功',grouping:true});
|
||||||
}
|
}
|
||||||
const handleDel = (name) => {
|
const handlePageSearch = ()=>{
|
||||||
signInDel(name).then(() => {
|
handlePageChange();
|
||||||
_getSignList();
|
handleTunnelRefresh();
|
||||||
});
|
handleTuntapRefresh();
|
||||||
}
|
ElMessage.success({message:'刷新成功',grouping:true});
|
||||||
|
|
||||||
|
|
||||||
const timerState = reactive({
|
|
||||||
timerTestTarget:0,
|
|
||||||
timerTestListen:0,
|
|
||||||
timerTestLocal:0,
|
|
||||||
})
|
|
||||||
const _testTargetForwardInfo = ()=>{
|
|
||||||
testTargetForwardInfo(forward.value.current).then((res)=>{
|
|
||||||
timerState.timerTestTarget = setTimeout(_testTargetForwardInfo,5000);
|
|
||||||
}).catch(()=>{
|
|
||||||
timerState.timerTestTarget = setTimeout(_testTargetForwardInfo,5000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const _testListenForwardInfo = ()=>{
|
|
||||||
testListenForwardInfo(forward.value.current).then((res)=>{
|
|
||||||
timerState.timerTestListen = setTimeout(_testListenForwardInfo,5000);
|
|
||||||
}).catch(()=>{
|
|
||||||
timerState.timerTestListen = setTimeout(_testListenForwardInfo,5000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const _testLocalSForwardInfo = ()=>{
|
|
||||||
testLocalSForwardInfo().then((res)=>{
|
|
||||||
timerState.timerTestLocal = setTimeout(_testLocalSForwardInfo,5000);
|
|
||||||
}).catch(()=>{
|
|
||||||
timerState.timerTestLocal = setTimeout(_testLocalSForwardInfo,5000);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -399,23 +130,21 @@ export default {
|
|||||||
_testLocalSForwardInfo();
|
_testLocalSForwardInfo();
|
||||||
});
|
});
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
clearTimeout( state.timer);
|
clearDevicesTimeout();
|
||||||
clearTimeout(tuntap.value.timer);
|
clearConnectionsTimeout();
|
||||||
clearTimeout(tunnel.value.timer);
|
clearTuntapTimeout();
|
||||||
clearTimeout(forward.value.timer);
|
clearTunnelTimeout();
|
||||||
clearTimeout(sforward.value.timer);
|
clearForwardTimeout();
|
||||||
|
clearSForwardTimeout();
|
||||||
clearTimeout(timerState.timerTestTarget);
|
|
||||||
clearTimeout(timerState.timerTestListen);
|
|
||||||
clearTimeout(timerState.timerTestLocal);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
machineId, state,
|
state,devices, machineId,
|
||||||
handleDeviceEdit,handlePageRefresh, handlePageChange, handleDel,
|
handleDeviceEdit,handlePageRefresh,handlePageSearch, handlePageChange,handlePageSizeChange, handleDel,
|
||||||
tuntap, handleTuntapEdit, handleTuntapChange, handleTuntapRefresh,
|
tuntap, handleTuntapEdit, handleTuntapRefresh,
|
||||||
tunnel,connections, handleTunnelEdit, handleTunnelChange, handleTunnelRefresh,handleTunnelConnections,
|
tunnel,connections, handleTunnelEdit, handleTunnelRefresh,handleTunnelConnections,
|
||||||
forward,sforward, handleForwardEdit,handleForwardChange,handleForwardRefresh,handleSForwardEdit,handleSForwardChange
|
forward,_handleForwardEdit,
|
||||||
|
sforward,handleSForwardEdit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
146
linker.web/src/views/devices/SForwardCopy.vue
Normal file
146
linker.web/src/views/devices/SForwardCopy.vue
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" title="复制服务器代理穿透" top="1vh" width="500">
|
||||||
|
<div>
|
||||||
|
<div class="t-c head">
|
||||||
|
<span>复制</span>
|
||||||
|
<el-select v-model="state.machineId" @change="handleMachineChange"
|
||||||
|
filterable remote :loading="state.loading" :remote-method="handleSearch">
|
||||||
|
<template #header>
|
||||||
|
<div class="t-c">
|
||||||
|
<div class="page-wrap">
|
||||||
|
<el-pagination small background layout="prev, pager, next"
|
||||||
|
:page-size="state.machineIds.Request.Size"
|
||||||
|
:total="state.machineIds.Count"
|
||||||
|
:pager-count="5"
|
||||||
|
:current-page="state.machineIds.Request.Page" @current-change="handlePageChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-option v-for="(item, index) in state.machineIds.List" :key="index" :label="item.MachineName" :value="item.MachineId">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<span>的服务器代理穿透记录</span>
|
||||||
|
</div>
|
||||||
|
<el-table :data="state.forwards" size="small" border>
|
||||||
|
<el-table-column property="Name" label="名称"></el-table-column>
|
||||||
|
<el-table-column property="Domain" label="域名/端口">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.Domain || scope.row.RemotePort }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="LocalEP" label="本机服务" width="140"></el-table-column>
|
||||||
|
<el-table-column label="操作" width="80">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-checkbox v-model="scope.row.use">使用</el-checkbox>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="foot t-c">
|
||||||
|
<el-button type="primary" @click="handleConfirm">确定复制</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { onMounted, onUnmounted, reactive, watch } from 'vue';
|
||||||
|
import { getSForwardRemoteInfo,addSForwardInfo } from '@/apis/sforward'
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import {WarnTriangleFilled} from '@element-plus/icons-vue'
|
||||||
|
import { injectGlobalData } from '@/provide';
|
||||||
|
import { getSignInIds } from '@/apis/signin';
|
||||||
|
export default {
|
||||||
|
props: ['modelValue'],
|
||||||
|
emits: ['update:modelValue'],
|
||||||
|
components:{WarnTriangleFilled},
|
||||||
|
setup(props, { emit }) {
|
||||||
|
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const state = reactive({
|
||||||
|
show: true,
|
||||||
|
loading:false,
|
||||||
|
machineId: '',
|
||||||
|
machineIds:{
|
||||||
|
Request: {
|
||||||
|
Page: 1, Size:10, Name: ''
|
||||||
|
},
|
||||||
|
Count: 0,
|
||||||
|
List: []
|
||||||
|
},
|
||||||
|
forwards: []
|
||||||
|
});
|
||||||
|
watch(() => state.show, (val) => {
|
||||||
|
if (!val) {
|
||||||
|
setTimeout(() => {
|
||||||
|
emit('update:modelValue', val);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleOnShowList = () => {
|
||||||
|
_getMachineIds();
|
||||||
|
}
|
||||||
|
const _getMachineIds = ()=>{
|
||||||
|
state.loading = true;
|
||||||
|
getSignInIds(state.machineIds.Request).then((res)=>{
|
||||||
|
state.loading = false;
|
||||||
|
state.machineIds.Request = res.Request;
|
||||||
|
state.machineIds.Count = res.Count;
|
||||||
|
state.machineIds.List = res.List;
|
||||||
|
if(!state.machineId && state.machineIds.List.length > 0){
|
||||||
|
state.machineId = state.machineIds.List[0].MachineId;
|
||||||
|
_getForwardRemoteInfo();
|
||||||
|
}
|
||||||
|
}).catch((e)=>{
|
||||||
|
state.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const handlePageChange = (page)=>{
|
||||||
|
state.machineIds.Request.Page = page;
|
||||||
|
_getMachineIds();
|
||||||
|
}
|
||||||
|
const handleSearch = (name)=>{
|
||||||
|
state.machineIds.Request.Name = name;
|
||||||
|
_getMachineIds();
|
||||||
|
}
|
||||||
|
const _getForwardRemoteInfo = ()=>{
|
||||||
|
getSForwardRemoteInfo(state.machineId).then((res)=>{
|
||||||
|
res.forEach(c=>{
|
||||||
|
c.use = true;
|
||||||
|
});
|
||||||
|
state.forwards = res;
|
||||||
|
}).catch((e)=>{
|
||||||
|
console.log(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const handleMachineChange = ()=>{
|
||||||
|
_getForwardRemoteInfo();
|
||||||
|
}
|
||||||
|
const handleConfirm = ()=>{
|
||||||
|
const tasks = state.forwards.filter(c=>c.use)
|
||||||
|
.map(c=>addSForwardInfo({Name:c.Name,Domain:c.Domain,RemotePort:c.RemotePort,LocalEP:c.LocalEP}));
|
||||||
|
Promise.all(tasks).then(()=>{
|
||||||
|
ElMessage.success('已操作!');
|
||||||
|
state.show = false;
|
||||||
|
}).catch(()=>{
|
||||||
|
ElMessage.success('操作失败!');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(()=>{
|
||||||
|
_getMachineIds();
|
||||||
|
});
|
||||||
|
onUnmounted(()=>{
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,handleSearch, handleOnShowList,handleMachineChange,handleConfirm,handlePageChange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.el-select{width : 12rem}
|
||||||
|
.head{padding-bottom:1rem}
|
||||||
|
.foot{padding-top:1rem}
|
||||||
|
.page-wrap{display:inline-block}
|
||||||
|
</style>
|
@@ -1,9 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" title="服务器端口转发到本机" top="1vh" width="700">
|
<el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" title="服务器代理穿透" top="1vh" width="700">
|
||||||
<div>
|
<div>
|
||||||
<div class="t-c head">
|
<div class="t-c head">
|
||||||
<el-button type="success" size="small" @click="handleAdd">添加</el-button>
|
<el-button type="success" size="small" @click="handleAdd">添加</el-button>
|
||||||
<el-button size="small" @click="handleRefresh">刷新</el-button>
|
<el-button size="small" @click="handleRefresh">刷新</el-button>
|
||||||
|
<el-button size="small" @click="handleCopy">复制穿透配置</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
||||||
<el-table-column property="Name" label="名称">
|
<el-table-column property="Name" label="名称">
|
||||||
@@ -85,11 +86,12 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { inject, onMounted, onUnmounted, reactive, watch } from 'vue';
|
import { onMounted, onUnmounted, reactive, watch } from 'vue';
|
||||||
import { getSForwardInfo, removeSForwardInfo, addSForwardInfo,testLocalSForwardInfo } from '@/apis/sforward'
|
import { getSForwardInfo, removeSForwardInfo, addSForwardInfo,testLocalSForwardInfo } from '@/apis/sforward'
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import {WarnTriangleFilled} from '@element-plus/icons-vue'
|
import {WarnTriangleFilled} from '@element-plus/icons-vue'
|
||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
|
import { useSforward } from './sforward';
|
||||||
export default {
|
export default {
|
||||||
props: ['data','modelValue'],
|
props: ['data','modelValue'],
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
@@ -97,7 +99,7 @@ export default {
|
|||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const sforward = inject('sforward');
|
const sforward = useSforward();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
bufferSize:globalData.value.bufferSize,
|
bufferSize:globalData.value.bufferSize,
|
||||||
show: true,
|
show: true,
|
||||||
@@ -197,6 +199,9 @@ export default {
|
|||||||
ElMessage.error(err);
|
ElMessage.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const handleCopy = ()=>{
|
||||||
|
sforward.value.showCopy = true;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
_getSForwardInfo();
|
_getSForwardInfo();
|
||||||
@@ -207,7 +212,7 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state, handleOnShowList, handleCellClick, handleRefresh, handleAdd, handleEdit, handleEditBlur, handleDel, handleStartChange
|
state, handleOnShowList, handleCellClick, handleRefresh, handleAdd, handleEdit, handleEditBlur, handleDel, handleStartChange,handleCopy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-table-column prop="tuntap" label="隧道" width="90">
|
<el-table-column prop="tunnel" label="隧道" width="90">
|
||||||
<template #header>
|
|
||||||
<div class="flex">
|
|
||||||
<span class="flex-1">隧道</span>
|
|
||||||
<el-button size="small" @click="handleTunnelRefresh"><el-icon><Refresh /></el-icon></el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div v-if="tunnel.list[scope.row.MachineId]">
|
<div v-if="tunnel.list[scope.row.MachineId]">
|
||||||
<p>
|
<p>
|
||||||
@@ -23,16 +17,17 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { computed, inject, reactive } from 'vue';
|
import { useTunnel } from './tunnel';
|
||||||
|
import { useConnections,useForwardConnections,useTuntapConnections } from './connections';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
emits: ['edit','refresh'],
|
emits: ['edit','refresh'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const tunnel = inject('tunnel');
|
const tunnel = useTunnel();
|
||||||
|
const connections = useConnections();
|
||||||
const forwardConnections = inject('forward-connections');
|
const forwardConnections =useForwardConnections();
|
||||||
const tuntapConnections = inject('tuntap-connections');
|
const tuntapConnections = useTuntapConnections();
|
||||||
|
|
||||||
const connectionCount = (machineId)=>{
|
const connectionCount = (machineId)=>{
|
||||||
return [
|
return [
|
||||||
|
@@ -36,14 +36,15 @@
|
|||||||
<script>
|
<script>
|
||||||
import {setTunnelRouteLevel } from '@/apis/tunnel';
|
import {setTunnelRouteLevel } from '@/apis/tunnel';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { inject, reactive, ref, watch } from 'vue';
|
import { reactive, ref, watch } from 'vue';
|
||||||
|
import { useTunnel } from './tunnel';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['modelValue'],
|
props: ['modelValue'],
|
||||||
emits: ['change','update:modelValue'],
|
emits: ['change','update:modelValue'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const tunnel = inject('tunnel');
|
const tunnel = useTunnel();
|
||||||
const ruleFormRef = ref(null);
|
const ruleFormRef = ref(null);
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
show: true,
|
show: true,
|
||||||
|
@@ -1,11 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-table-column prop="tuntap" label="虚拟网卡" width="150">
|
<el-table-column prop="tuntap" label="虚拟网卡" width="150">
|
||||||
<template #header>
|
|
||||||
<div class="flex">
|
|
||||||
<span class="flex-1">虚拟网卡</span>
|
|
||||||
<el-button size="small" @click="handleRuntapRefresh"><el-icon><Refresh /></el-icon></el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div v-if="tuntap.list[scope.row.MachineId]">
|
<div v-if="tuntap.list[scope.row.MachineId]">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
@@ -40,13 +34,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import { stopTuntap, runTuntap } from '@/apis/tuntap';
|
import { stopTuntap, runTuntap } from '@/apis/tuntap';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { inject, reactive } from 'vue';
|
import { useTuntap } from './tuntap';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
emits: ['edit','refresh'],
|
emits: ['edit','refresh'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const tuntap = inject('tuntap');
|
const tuntap = useTuntap();
|
||||||
const handleTuntap = (tuntap) => {
|
const handleTuntap = (tuntap) => {
|
||||||
const fn = tuntap.running ? stopTuntap (tuntap.MachineId) : runTuntap(tuntap.MachineId);
|
const fn = tuntap.running ? stopTuntap (tuntap.MachineId) : runTuntap(tuntap.MachineId);
|
||||||
fn.then(() => {
|
fn.then(() => {
|
||||||
@@ -58,12 +52,12 @@ export default {
|
|||||||
const handleTuntapIP = (tuntap) => {
|
const handleTuntapIP = (tuntap) => {
|
||||||
emit('edit',tuntap);
|
emit('edit',tuntap);
|
||||||
}
|
}
|
||||||
const handleRuntapRefresh = ()=>{
|
const handleTuntapRefresh = ()=>{
|
||||||
emit('refresh');
|
emit('refresh');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tuntap, handleTuntap, handleTuntapIP,handleRuntapRefresh
|
tuntap, handleTuntap, handleTuntapIP,handleTuntapRefresh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,4 +66,7 @@ export default {
|
|||||||
.green{color:green;}
|
.green{color:green;}
|
||||||
.error{color:red;}
|
.error{color:red;}
|
||||||
.el-switch.is-disabled{opacity :1;}
|
.el-switch.is-disabled{opacity :1;}
|
||||||
|
.el-input{
|
||||||
|
width:8rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@@ -37,7 +37,8 @@
|
|||||||
import {updateTuntap } from '@/apis/tuntap';
|
import {updateTuntap } from '@/apis/tuntap';
|
||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { inject, reactive, ref, watch } from 'vue';
|
import { reactive, ref, watch } from 'vue';
|
||||||
|
import { useTuntap } from './tuntap';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['modelValue'],
|
props: ['modelValue'],
|
||||||
@@ -45,8 +46,7 @@ export default {
|
|||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
|
const tuntap = useTuntap();
|
||||||
const tuntap = inject('tuntap');
|
|
||||||
const ruleFormRef = ref(null);
|
const ruleFormRef = ref(null);
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
show: true,
|
show: true,
|
||||||
|
102
linker.web/src/views/devices/connections.js
Normal file
102
linker.web/src/views/devices/connections.js
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import { getForwardConnections } from "@/apis/forward";
|
||||||
|
import { getTuntapConnections } from "@/apis/tuntap";
|
||||||
|
import { injectGlobalData } from "@/provide";
|
||||||
|
import { inject, provide, ref } from "vue";
|
||||||
|
|
||||||
|
const connectionsSymbol = Symbol();
|
||||||
|
const forwardConnectionsSymbol = Symbol();
|
||||||
|
const tuntapConnectionsSymbol = Symbol();
|
||||||
|
export const provideConnections = () => {
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const connections = ref({
|
||||||
|
showEdit: false,
|
||||||
|
speedCache: {},
|
||||||
|
current: ''
|
||||||
|
});
|
||||||
|
provide(connectionsSymbol, connections);
|
||||||
|
|
||||||
|
const forwardConnections = ref({
|
||||||
|
timer: 0,
|
||||||
|
list: {},
|
||||||
|
});
|
||||||
|
provide(forwardConnectionsSymbol, forwardConnections);
|
||||||
|
const _getForwardConnections = () => {
|
||||||
|
if (globalData.value.connected) {
|
||||||
|
getForwardConnections().then((res) => {
|
||||||
|
parseConnections(res, removeForwardConnection);
|
||||||
|
forwardConnections.value.list = res;
|
||||||
|
forwardConnections.value.timer = setTimeout(_getForwardConnections, 1000);
|
||||||
|
}).catch((e) => {
|
||||||
|
forwardConnections.value.timer = setTimeout(_getForwardConnections, 1000);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
forwardConnections.value.timer = setTimeout(_getForwardConnections, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const tuntapConnections = ref({
|
||||||
|
timer: 0,
|
||||||
|
list: {},
|
||||||
|
});
|
||||||
|
provide(tuntapConnectionsSymbol, tuntapConnections);
|
||||||
|
const _getTuntapConnections = () => {
|
||||||
|
if (globalData.value.connected) {
|
||||||
|
getTuntapConnections().then((res) => {
|
||||||
|
parseConnections(res, removeTuntapConnection);
|
||||||
|
tuntapConnections.value.list = res;
|
||||||
|
tuntapConnections.value.timer = setTimeout(_getTuntapConnections, 1000);
|
||||||
|
}).catch((e) => {
|
||||||
|
tuntapConnections.value.timer = setTimeout(_getTuntapConnections, 1000);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
tuntapConnections.value.timer = setTimeout(_getTuntapConnections, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const parseConnections = (_connections, removeFunc) => {
|
||||||
|
const caches = connections.value.speedCache;
|
||||||
|
for (let machineId in _connections) {
|
||||||
|
const connection = _connections[machineId];
|
||||||
|
connection.removeFunc = removeFunc;
|
||||||
|
|
||||||
|
const key = `${connection.RemoteMachineId}-${connection.TransactionId}`;
|
||||||
|
const cache = caches[key] || { SendBytes: 0, ReceiveBytes: 0 };
|
||||||
|
|
||||||
|
connection.SendBytesText = parseSpeed(connection.SendBytes - cache.SendBytes);
|
||||||
|
connection.ReceiveBytesText = parseSpeed(connection.ReceiveBytes - cache.ReceiveBytes);
|
||||||
|
|
||||||
|
cache.SendBytes = connection.SendBytes;
|
||||||
|
cache.ReceiveBytes = connection.ReceiveBytes;
|
||||||
|
caches[key] = cache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const parseSpeed = (num) => {
|
||||||
|
let index = 0;
|
||||||
|
while (num >= 1024) {
|
||||||
|
num /= 1024;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return `${num.toFixed(2)}${['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s'][index]}`;
|
||||||
|
}
|
||||||
|
const handleTunnelConnections = (machineId) => {
|
||||||
|
connections.value.current = machineId;
|
||||||
|
connections.value.showEdit = true;
|
||||||
|
}
|
||||||
|
const clearConnectionsTimeout = () => {
|
||||||
|
clearTimeout(forwardConnections.value.timer);
|
||||||
|
clearTimeout(tuntapConnections.value.timer);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
connections,
|
||||||
|
forwardConnections, _getForwardConnections,
|
||||||
|
tuntapConnections, _getTuntapConnections,
|
||||||
|
handleTunnelConnections, clearConnectionsTimeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const useConnections = () => {
|
||||||
|
return inject(connectionsSymbol);
|
||||||
|
}
|
||||||
|
export const useForwardConnections = () => {
|
||||||
|
return inject(forwardConnectionsSymbol);
|
||||||
|
}
|
||||||
|
export const useTuntapConnections = () => {
|
||||||
|
return inject(tuntapConnectionsSymbol);
|
||||||
|
}
|
95
linker.web/src/views/devices/devices.js
Normal file
95
linker.web/src/views/devices/devices.js
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import { getSignInList, signInDel } from "@/apis/signin";
|
||||||
|
import { injectGlobalData } from "@/provide";
|
||||||
|
import { computed, reactive } from "vue";
|
||||||
|
|
||||||
|
export const provideDevices = () => {
|
||||||
|
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const machineId = computed(() => globalData.value.config.Client.Id);
|
||||||
|
const devices = reactive({
|
||||||
|
timer: 0,
|
||||||
|
page: {
|
||||||
|
Request: {
|
||||||
|
Page: 1, Size: +(localStorage.getItem('ps') || '10'),
|
||||||
|
GroupId: globalData.value.groupid, Name: '', Ids: []
|
||||||
|
},
|
||||||
|
Count: 0,
|
||||||
|
List: []
|
||||||
|
},
|
||||||
|
|
||||||
|
showDeviceEdit: false,
|
||||||
|
deviceInfo: null
|
||||||
|
});
|
||||||
|
const _getSignList = () => {
|
||||||
|
devices.page.Request.GroupId = globalData.value.groupid;
|
||||||
|
getSignInList(devices.page.Request).then((res) => {
|
||||||
|
devices.page.Request = res.Request;
|
||||||
|
devices.page.Count = res.Count;
|
||||||
|
for (let j in res.List) {
|
||||||
|
res.List[j].showTunnel = machineId.value != res.List[j].MachineId;
|
||||||
|
res.List[j].showForward = machineId.value != res.List[j].MachineId;
|
||||||
|
res.List[j].showSForward = machineId.value == res.List[j].MachineId;
|
||||||
|
res.List[j].showDel = machineId.value != res.List[j].MachineId && res.List[j].Connected == false;
|
||||||
|
res.List[j].isSelf = machineId.value == res.List[j].MachineId;
|
||||||
|
}
|
||||||
|
devices.page.List = res.List.sort((a, b) => b.Connected - a.Connected);
|
||||||
|
}).catch((err) => { });
|
||||||
|
}
|
||||||
|
const _getSignList1 = () => {
|
||||||
|
if (globalData.value.connected) {
|
||||||
|
devices.page.Request.GroupId = globalData.value.groupid;
|
||||||
|
getSignInList(devices.page.Request).then((res) => {
|
||||||
|
for (let j in res.List) {
|
||||||
|
const item = devices.page.List.filter(c => c.MachineId == res.List[j].MachineId)[0];
|
||||||
|
if (item) {
|
||||||
|
item.Connected = res.List[j].Connected;
|
||||||
|
item.Version = res.List[j].Version;
|
||||||
|
item.LastSignIn = res.List[j].LastSignIn;
|
||||||
|
item.Args = res.List[j].Args;
|
||||||
|
item.showTunnel = machineId.value != res.List[j].MachineId;
|
||||||
|
item.showForward = machineId.value != res.List[j].MachineId;
|
||||||
|
item.showSForward = machineId.value == res.List[j].MachineId;
|
||||||
|
item.showDel = machineId.value != res.List[j].MachineId && res.List[j].Connected == false;
|
||||||
|
item.isSelf = machineId.value == res.List[j].MachineId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
devices.timer = setTimeout(_getSignList1, 5000);
|
||||||
|
}).catch((err) => {
|
||||||
|
devices.timer = setTimeout(_getSignList1, 5000);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
devices.timer = setTimeout(_getSignList1, 5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeviceEdit = (row) => {
|
||||||
|
devices.deviceInfo = row;
|
||||||
|
devices.showDeviceEdit = true;
|
||||||
|
}
|
||||||
|
const handlePageChange = (page) => {
|
||||||
|
if (page) {
|
||||||
|
devices.page.Request.Page = page;
|
||||||
|
}
|
||||||
|
_getSignList();
|
||||||
|
}
|
||||||
|
const handlePageSizeChange = (size) => {
|
||||||
|
if (size) {
|
||||||
|
devices.page.Request.Size = size;
|
||||||
|
localStorage.setItem('ps', size);
|
||||||
|
}
|
||||||
|
_getSignList();
|
||||||
|
}
|
||||||
|
const handleDel = (name) => {
|
||||||
|
signInDel(name).then(() => {
|
||||||
|
_getSignList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const clearDevicesTimeout = () => {
|
||||||
|
clearTimeout(devices.timer);
|
||||||
|
devices.timer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
devices, machineId, _getSignList, _getSignList1, handleDeviceEdit, handlePageChange, handlePageSizeChange, handleDel, clearDevicesTimeout
|
||||||
|
}
|
||||||
|
}
|
69
linker.web/src/views/devices/forward.js
Normal file
69
linker.web/src/views/devices/forward.js
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { getForwardInfo, testListenForwardInfo, testTargetForwardInfo } from "@/apis/forward";
|
||||||
|
import { injectGlobalData } from "@/provide";
|
||||||
|
import { inject, provide, ref } from "vue";
|
||||||
|
|
||||||
|
const forwardSymbol = Symbol();
|
||||||
|
export const provideForward = () => {
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const forward = ref({
|
||||||
|
timer: 0,
|
||||||
|
showEdit: false,
|
||||||
|
showCopy: false,
|
||||||
|
current: null,
|
||||||
|
list: {},
|
||||||
|
testTimer: 0,
|
||||||
|
testTargetTimer: 0,
|
||||||
|
});
|
||||||
|
provide(forwardSymbol, forward);
|
||||||
|
const _getForwardInfo = () => {
|
||||||
|
if (globalData.value.connected) {
|
||||||
|
getForwardInfo().then((res) => {
|
||||||
|
forward.value.list = res;
|
||||||
|
forward.value.timer = setTimeout(_getForwardInfo, 1000);
|
||||||
|
}).catch(() => {
|
||||||
|
forward.value.timer = setTimeout(_getForwardInfo, 1000);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
forward.value.timer = setTimeout(_getForwardInfo, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleForwardEdit = (machineId, machineName) => {
|
||||||
|
forward.value.current = machineId;
|
||||||
|
forward.value.machineName = machineName;
|
||||||
|
forward.value.showEdit = true;
|
||||||
|
}
|
||||||
|
const _testTargetForwardInfo = () => {
|
||||||
|
clearTimeout(forward.value.testTargetTimer)
|
||||||
|
testTargetForwardInfo(forward.value.current).then((res) => {
|
||||||
|
forward.value.testTargetTimer = setTimeout(_testTargetForwardInfo, 5000);
|
||||||
|
}).catch(() => {
|
||||||
|
forward.value.testTargetTimer = setTimeout(_testTargetForwardInfo, 5000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const _testListenForwardInfo = () => {
|
||||||
|
clearTimeout(forward.value.testTimer)
|
||||||
|
testListenForwardInfo(forward.value.current).then((res) => {
|
||||||
|
forward.value.testTimer = setTimeout(_testListenForwardInfo, 5000);
|
||||||
|
}).catch(() => {
|
||||||
|
forward.value.testTimer = setTimeout(_testListenForwardInfo, 5000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const clearForwardTimeout = () => {
|
||||||
|
clearTimeout(forward.value.timer);
|
||||||
|
clearTimeout(forward.value.testTimer);
|
||||||
|
clearTimeout(forward.value.testTargetTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getForwardMachines = (name) => {
|
||||||
|
return Object.values(forward.value.list)
|
||||||
|
.filter(c => (c.Name || '').indexOf(name) >= 0 || (c.BindIPAddress || '').indexOf(name) >= 0 || (c.Port.toString()).indexOf(name) >= 0 || (c.TargetEP || '').indexOf(name) >= 0)
|
||||||
|
.map(c => c.MachineId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
forward, _getForwardInfo, handleForwardEdit, _testTargetForwardInfo, _testListenForwardInfo, clearForwardTimeout, getForwardMachines
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const useForward = () => {
|
||||||
|
return inject(forwardSymbol);
|
||||||
|
}
|
61
linker.web/src/views/devices/sforward.js
Normal file
61
linker.web/src/views/devices/sforward.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
import { getSForwardInfo, testLocalSForwardInfo } from '@/apis/sforward';
|
||||||
|
import { injectGlobalData } from '@/provide';
|
||||||
|
import { ref, provide, inject, computed } from 'vue';
|
||||||
|
|
||||||
|
const sforwardSymbol = Symbol();
|
||||||
|
export const provideSforward = () => {
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const machineId = computed(() => globalData.value.config.Client.Id);
|
||||||
|
const sforward = ref({
|
||||||
|
timer: 0,
|
||||||
|
showEdit: false,
|
||||||
|
showCopy: false,
|
||||||
|
list: [],
|
||||||
|
testTimer: 0
|
||||||
|
});
|
||||||
|
provide(sforwardSymbol, sforward);
|
||||||
|
const _getSForwardInfo = () => {
|
||||||
|
if (globalData.value.connected) {
|
||||||
|
getSForwardInfo().then((res) => {
|
||||||
|
sforward.value.list = res;
|
||||||
|
sforward.value.timer = setTimeout(_getSForwardInfo, 1000);
|
||||||
|
}).catch(() => {
|
||||||
|
sforward.value.timer = setTimeout(_getSForwardInfo, 1000);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sforward.value.timer = setTimeout(_getSForwardInfo, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleSForwardEdit = () => {
|
||||||
|
sforward.value.showEdit = true;
|
||||||
|
}
|
||||||
|
const _testLocalSForwardInfo = () => {
|
||||||
|
clearTimeout(sforward.value.testTimer)
|
||||||
|
testLocalSForwardInfo().then((res) => {
|
||||||
|
sforward.value.testTimer = setTimeout(_testLocalSForwardInfo, 5000);
|
||||||
|
}).catch(() => {
|
||||||
|
sforward.value.testTimer = setTimeout(_testLocalSForwardInfo, 5000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const clearSForwardTimeout = () => {
|
||||||
|
clearTimeout(sforward.value.timer);
|
||||||
|
clearTimeout(sforward.value.testTimer);
|
||||||
|
}
|
||||||
|
const getSForwardMachines = (name) => {
|
||||||
|
const sfs = sforward.value.list
|
||||||
|
.filter(c => (c.Name || '').indexOf(name) >= 0 || (c.Domain || '').indexOf(name) >= 0 || (c.RemotePort.toString()).indexOf(name) >= 0 || c.LocalEP.indexOf(name) >= 0);
|
||||||
|
|
||||||
|
if (sfs.length > 0) {
|
||||||
|
return [machineId.value];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
sforward, _getSForwardInfo, handleSForwardEdit, _testLocalSForwardInfo, clearSForwardTimeout, getSForwardMachines
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export const useSforward = () => {
|
||||||
|
return inject(sforwardSymbol);
|
||||||
|
}
|
49
linker.web/src/views/devices/tunnel.js
Normal file
49
linker.web/src/views/devices/tunnel.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import { getTunnelInfo, refreshTunnel } from "@/apis/tunnel";
|
||||||
|
import { injectGlobalData } from "@/provide";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { inject, provide, ref } from "vue";
|
||||||
|
|
||||||
|
const tunnelSymbol = Symbol();
|
||||||
|
export const provideTunnel = () => {
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const tunnel = ref({
|
||||||
|
timer: 0,
|
||||||
|
showEdit: false,
|
||||||
|
current: null,
|
||||||
|
list: {},
|
||||||
|
hashcode: 0,
|
||||||
|
});
|
||||||
|
provide(tunnelSymbol, tunnel);
|
||||||
|
const _getTunnelInfo = () => {
|
||||||
|
if (globalData.value.connected) {
|
||||||
|
getTunnelInfo(tunnel.value.hashcode.toString()).then((res) => {
|
||||||
|
tunnel.value.hashcode = res.HashCode;
|
||||||
|
if (res.List) {
|
||||||
|
tunnel.value.list = res.List;
|
||||||
|
}
|
||||||
|
tunnel.value.timer = setTimeout(_getTunnelInfo, 1000);
|
||||||
|
}).catch(() => {
|
||||||
|
tunnel.value.timer = setTimeout(_getTunnelInfo, 1000);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tunnel.value.timer = setTimeout(_getTunnelInfo, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleTunnelEdit = (_tunnel) => {
|
||||||
|
tunnel.value.current = _tunnel;
|
||||||
|
tunnel.value.showEdit = true;
|
||||||
|
}
|
||||||
|
const handleTunnelRefresh = () => {
|
||||||
|
refreshTunnel();
|
||||||
|
ElMessage.success({ message: '刷新成功', grouping: true });
|
||||||
|
}
|
||||||
|
const clearTunnelTimeout = () => {
|
||||||
|
clearTimeout(tunnel.value.timer);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
tunnel, _getTunnelInfo, handleTunnelEdit, handleTunnelRefresh, clearTunnelTimeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const useTunnel = () => {
|
||||||
|
return inject(tunnelSymbol);
|
||||||
|
}
|
62
linker.web/src/views/devices/tuntap.js
Normal file
62
linker.web/src/views/devices/tuntap.js
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import { injectGlobalData } from "@/provide";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { inject, provide, ref } from "vue"
|
||||||
|
import { getTuntapInfo, refreshTuntap } from "@/apis/tuntap";
|
||||||
|
|
||||||
|
const tuntapSymbol = Symbol();
|
||||||
|
export const provideTuntap = () => {
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const tuntap = ref({
|
||||||
|
timer: 0,
|
||||||
|
showEdit: false,
|
||||||
|
current: null,
|
||||||
|
list: {},
|
||||||
|
hashcode: 0
|
||||||
|
});
|
||||||
|
provide(tuntapSymbol, tuntap);
|
||||||
|
const _getTuntapInfo = () => {
|
||||||
|
clearTimeout(tuntap.value.timer);
|
||||||
|
if (globalData.value.connected) {
|
||||||
|
getTuntapInfo(tuntap.value.hashcode.toString()).then((res) => {
|
||||||
|
tuntap.value.hashcode = res.HashCode;
|
||||||
|
if (res.List) {
|
||||||
|
for (let j in res.List) {
|
||||||
|
res.List[j].running = res.List[j].Status == 2;
|
||||||
|
res.List[j].loading = res.List[j].Status == 1;
|
||||||
|
}
|
||||||
|
tuntap.value.list = res.List;
|
||||||
|
}
|
||||||
|
tuntap.value.timer = setTimeout(_getTuntapInfo, 200);
|
||||||
|
}).catch(() => {
|
||||||
|
tuntap.value.timer = setTimeout(_getTuntapInfo, 200);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tuntap.value.timer = setTimeout(_getTuntapInfo, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleTuntapEdit = (_tuntap) => {
|
||||||
|
tuntap.value.current = _tuntap;
|
||||||
|
tuntap.value.showEdit = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
const handleTuntapRefresh = () => {
|
||||||
|
refreshTuntap();
|
||||||
|
ElMessage.success({ message: '刷新成功', grouping: true });
|
||||||
|
}
|
||||||
|
const clearTuntapTimeout = () => {
|
||||||
|
clearTimeout(tuntap.value.timer);
|
||||||
|
tuntap.value.timer = 0;
|
||||||
|
}
|
||||||
|
const getTuntapMachines = (name) => {
|
||||||
|
return Object.values(tuntap.value.list)
|
||||||
|
.filter(c => c.IP.indexOf(name) >= 0 || (c.LanIPs.filter(d => d.indexOf(name) >= 0).length > 0))
|
||||||
|
.map(c => c.MachineId);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
tuntap, _getTuntapInfo, handleTuntapEdit, handleTuntapRefresh, clearTuntapTimeout, getTuntapMachines
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useTuntap = () => {
|
||||||
|
return inject(tuntapSymbol);
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<Version ckey="excludeIPConfig"/>
|
||||||
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
||||||
<el-table-column prop="IPAddress" label="IP">
|
<el-table-column prop="IPAddress" label="IP">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -43,16 +44,18 @@ import { setTunnelExcludeIPs } from '@/apis/tunnel';
|
|||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { computed, inject, onMounted, reactive } from 'vue'
|
import { computed, inject, onMounted, reactive } from 'vue'
|
||||||
|
import Version from './Version.vue';
|
||||||
export default {
|
export default {
|
||||||
label:'打洞排除IP',
|
label:'打洞排除IP',
|
||||||
name:'excludeIP',
|
name:'excludeIP',
|
||||||
order:3,
|
order:3,
|
||||||
|
components:{Version},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
list:((globalData.value.config.Running.Tunnel || {ExcludeIPs:[]}).ExcludeIPs || [{IPAddress:'0.0.0.0',Mask:32}]),
|
list:((globalData.value.config.Running.Tunnel || {ExcludeIPs:[]}).ExcludeIPs || [{IPAddress:'0.0.0.0',Mask:32}]),
|
||||||
types:[],
|
types:[],
|
||||||
height: computed(()=>globalData.value.height-92)
|
height: computed(()=>globalData.value.height-127)
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleCellClick = (row, column) => {
|
const handleCellClick = (row, column) => {
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<Version ckey="relayServers"/>
|
||||||
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
||||||
<el-table-column prop="Name" label="名称" width="100">
|
<el-table-column prop="Name" label="名称" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -81,16 +82,18 @@ import { setRelayServers,getRelayTypes } from '@/apis/relay';
|
|||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { computed, inject, onMounted, reactive } from 'vue'
|
import { computed, inject, onMounted, reactive } from 'vue'
|
||||||
|
import Version from './Version.vue';
|
||||||
export default {
|
export default {
|
||||||
label:'中继服务器',
|
label:'中继服务器',
|
||||||
name:'relayServers',
|
name:'relayServers',
|
||||||
order:4,
|
order:4,
|
||||||
|
components:{Version},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
list:((globalData.value.config.Running.Relay || {Servers:[]}).Servers || []).sort((a,b)=>a.Disabled - b.Disabled),
|
list:((globalData.value.config.Running.Relay || {Servers:[]}).Servers || []).sort((a,b)=>a.Disabled - b.Disabled),
|
||||||
types:[],
|
types:[],
|
||||||
height: computed(()=>globalData.value.height-92)
|
height: computed(()=>globalData.value.height-127)
|
||||||
});
|
});
|
||||||
|
|
||||||
const _getRelayTypes = ()=>{
|
const _getRelayTypes = ()=>{
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<Version ckey="sforwardKey"/>
|
||||||
<div style="width: 30rem;padding: 5rem 0; margin: 0 auto;">
|
<div style="width: 30rem;padding: 5rem 0; margin: 0 auto;">
|
||||||
<p class="t-c">
|
<p class="t-c">
|
||||||
服务器代理穿透密钥
|
服务器代理穿透密钥
|
||||||
@@ -13,10 +14,12 @@ import { getSForwardSecretKey,setSForwardSecretKey } from '@/apis/sforward';
|
|||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { computed, inject, onMounted, reactive } from 'vue'
|
import { computed, inject, onMounted, reactive } from 'vue'
|
||||||
|
import Version from './Version.vue';
|
||||||
export default {
|
export default {
|
||||||
label:'服务器代理穿透',
|
label:'服务器代理穿透',
|
||||||
name:'sforward',
|
name:'sforward',
|
||||||
order:5,
|
order:5,
|
||||||
|
components:{Version},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<Version ckey="signServers"/>
|
||||||
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
||||||
<el-table-column prop="Name" label="名称">
|
<el-table-column prop="Name" label="名称">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -50,16 +51,18 @@ import { setSignInServers } from '@/apis/signin';
|
|||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { computed, inject, reactive } from 'vue'
|
import { computed, inject, reactive } from 'vue'
|
||||||
|
import Version from './Version.vue';
|
||||||
export default {
|
export default {
|
||||||
label:'信标服务器',
|
label:'信标服务器',
|
||||||
name:'signInServers',
|
name:'signInServers',
|
||||||
order:0,
|
order:0,
|
||||||
|
components:{Version},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
list:globalData.value.config.Running.Client.Servers || [],
|
list:globalData.value.config.Running.Client.Servers || [],
|
||||||
server:computed(()=>globalData.value.config.Client.Server),
|
server:computed(()=>globalData.value.config.Client.Server),
|
||||||
height: computed(()=>globalData.value.height-92),
|
height: computed(()=>globalData.value.height-127),
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleCellClick = (row, column) => {
|
const handleCellClick = (row, column) => {
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<Version ckey="tunnelTransports"/>
|
||||||
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" >
|
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" >
|
||||||
<el-table-column prop="Name" label="名称" width="120"></el-table-column>
|
<el-table-column prop="Name" label="名称" width="120"></el-table-column>
|
||||||
<el-table-column prop="Label" label="说明"></el-table-column>
|
<el-table-column prop="Label" label="说明"></el-table-column>
|
||||||
@@ -44,15 +45,17 @@ import { getTunnelTransports,setTunnelTransports } from '@/apis/tunnel';
|
|||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { computed, inject, onMounted, reactive } from 'vue'
|
import { computed, inject, onMounted, reactive } from 'vue'
|
||||||
|
import Version from './Version.vue';
|
||||||
export default {
|
export default {
|
||||||
label:'打洞协议',
|
label:'打洞协议',
|
||||||
name:'transports',
|
name:'transports',
|
||||||
order:2,
|
order:2,
|
||||||
|
components:{Version},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
list:[],
|
list:[],
|
||||||
height: computed(()=>globalData.value.height-92),
|
height: computed(()=>globalData.value.height-127),
|
||||||
bufferSize:globalData.value.bufferSize
|
bufferSize:globalData.value.bufferSize
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<Version ckey="tunnelWanPortProtocols"/>
|
||||||
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
||||||
<el-table-column prop="Name" label="名称">
|
<el-table-column prop="Name" label="名称">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -78,17 +79,19 @@ import { setTunnelServers,getTunnelTypes } from '@/apis/tunnel';
|
|||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { computed, inject, onMounted, reactive } from 'vue'
|
import { computed, inject, onMounted, reactive } from 'vue'
|
||||||
|
import Version from './Version.vue';
|
||||||
export default {
|
export default {
|
||||||
label:'外网端口服务器',
|
label:'外网端口服务器',
|
||||||
name:'tunnelServers',
|
name:'tunnelServers',
|
||||||
order:1,
|
order:1,
|
||||||
|
components:{Version},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const list = ((globalData.value.config.Running.Tunnel || {Servers:[]}).Servers || []).sort((a,b)=>a.Disabled - b.Disabled);
|
const list = ((globalData.value.config.Running.Tunnel || {Servers:[]}).Servers || []).sort((a,b)=>a.Disabled - b.Disabled);
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
list:list,
|
list:list,
|
||||||
types:[],
|
types:[],
|
||||||
height: computed(()=>globalData.value.height-92)
|
height: computed(()=>globalData.value.height-127)
|
||||||
});
|
});
|
||||||
|
|
||||||
const _getTunnelTypes = ()=>{
|
const _getTunnelTypes = ()=>{
|
||||||
|
50
linker.web/src/views/settings/Version.vue
Normal file
50
linker.web/src/views/settings/Version.vue
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<div class="running-version-wrap">
|
||||||
|
<span>配置版本 : {{version}}</span>
|
||||||
|
<el-button size="small" @click=handleEdit>手动修改版本</el-button>
|
||||||
|
<span>高版本一端自动同步到低版本一端</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {updateVersion} from '@/apis/running'
|
||||||
|
import { injectGlobalData } from '@/provide';
|
||||||
|
import { ElMessageBox } from 'element-plus';
|
||||||
|
import { computed } from 'vue'
|
||||||
|
export default {
|
||||||
|
props:['ckey'],
|
||||||
|
setup(props) {
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const version = computed(()=>globalData.value.config.Running.Versions[props.ckey]);
|
||||||
|
|
||||||
|
|
||||||
|
const handleEdit = () => {
|
||||||
|
ElMessageBox.prompt('输入你要修改到的版本', '修改版本', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
inputValue:version.value,
|
||||||
|
inputPattern:/\d+/,
|
||||||
|
inputErrorMessage: 'Invalid Number',
|
||||||
|
}).then(({ value }) => {
|
||||||
|
value = +value;
|
||||||
|
if(isNaN(value)) return ;
|
||||||
|
updateVersion({key:props.ckey,version:value});
|
||||||
|
}).catch(()=>{
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
version,handleEdit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.running-version-wrap{
|
||||||
|
span{
|
||||||
|
vertical-align:middle
|
||||||
|
}
|
||||||
|
padding:0 0 1rem 0;
|
||||||
|
line-height:2.4rem
|
||||||
|
}
|
||||||
|
</style>
|
@@ -176,6 +176,7 @@ namespace linker.client
|
|||||||
public async Task UpdateServers(ClientServerInfo[] servers)
|
public async Task UpdateServers(ClientServerInfo[] servers)
|
||||||
{
|
{
|
||||||
await SetServers(servers);
|
await SetServers(servers);
|
||||||
|
runningConfigTransfer.IncrementVersion(configKey);
|
||||||
SyncServers();
|
SyncServers();
|
||||||
}
|
}
|
||||||
private void SetServers(Memory<byte> data)
|
private void SetServers(Memory<byte> data)
|
||||||
|
@@ -5,6 +5,7 @@ using System.Reflection;
|
|||||||
using linker.client.args;
|
using linker.client.args;
|
||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
using linker.config;
|
using linker.config;
|
||||||
|
using linker.client.config.messenger;
|
||||||
|
|
||||||
namespace linker.client
|
namespace linker.client
|
||||||
{
|
{
|
||||||
@@ -23,6 +24,8 @@ namespace linker.client
|
|||||||
{
|
{
|
||||||
serviceCollection.AddSingleton<RunningConfig>();
|
serviceCollection.AddSingleton<RunningConfig>();
|
||||||
serviceCollection.AddSingleton<RunningConfigTransfer>();
|
serviceCollection.AddSingleton<RunningConfigTransfer>();
|
||||||
|
serviceCollection.AddSingleton<ConfigClientMessenger>();
|
||||||
|
serviceCollection.AddSingleton<RunningConfigApiController>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<SignInArgsTransfer>();
|
serviceCollection.AddSingleton<SignInArgsTransfer>();
|
||||||
|
|
||||||
@@ -43,7 +46,7 @@ namespace linker.client
|
|||||||
|
|
||||||
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies)
|
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies)
|
||||||
{
|
{
|
||||||
|
serviceCollection.AddSingleton<ConfigServerMessenger>();
|
||||||
}
|
}
|
||||||
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies)
|
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies)
|
||||||
{
|
{
|
||||||
|
28
linker/client/config/RunningConfigApiController.cs
Normal file
28
linker/client/config/RunningConfigApiController.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using linker.libs.api;
|
||||||
|
using linker.client.capi;
|
||||||
|
using linker.libs.extends;
|
||||||
|
|
||||||
|
namespace linker.client.config
|
||||||
|
{
|
||||||
|
public sealed class RunningConfigApiController : IApiClientController
|
||||||
|
{
|
||||||
|
private readonly RunningConfigTransfer runningConfigTransfer;
|
||||||
|
|
||||||
|
public RunningConfigApiController(RunningConfigTransfer runningConfigTransfer)
|
||||||
|
{
|
||||||
|
this.runningConfigTransfer = runningConfigTransfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateVersion(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
UpdateVersionInfo info = param.Content.DeJson<UpdateVersionInfo>();
|
||||||
|
runningConfigTransfer.UpdateVersion(info.Key, info.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class UpdateVersionInfo
|
||||||
|
{
|
||||||
|
public string Key { get; set; }
|
||||||
|
public ulong Version { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -2,7 +2,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.server;
|
using linker.server;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace linker.client.config
|
namespace linker.client.config
|
||||||
@@ -45,7 +44,7 @@ namespace linker.client.config
|
|||||||
|
|
||||||
public Memory<byte> InputConfig(ConfigVersionInfo info)
|
public Memory<byte> InputConfig(ConfigVersionInfo info)
|
||||||
{
|
{
|
||||||
CheckVersion(info.Key, out ulong version);
|
ulong version = GetVersion(info.Key);
|
||||||
|
|
||||||
if (setters.TryGetValue(info.Key, out Action<Memory<byte>> setter) && info.Version > version)
|
if (setters.TryGetValue(info.Key, out Action<Memory<byte>> setter) && info.Version > version)
|
||||||
{
|
{
|
||||||
@@ -54,7 +53,12 @@ namespace linker.client.config
|
|||||||
}
|
}
|
||||||
else if (getters.TryGetValue(info.Key, out Func<Memory<byte>> getter) && version > info.Version)
|
else if (getters.TryGetValue(info.Key, out Func<Memory<byte>> getter) && version > info.Version)
|
||||||
{
|
{
|
||||||
return getter();
|
return MemoryPackSerializer.Serialize(new ConfigVersionInfo
|
||||||
|
{
|
||||||
|
Data = getter(),
|
||||||
|
Key = info.Key,
|
||||||
|
Version = version
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Helper.EmptyArray;
|
return Helper.EmptyArray;
|
||||||
@@ -64,8 +68,7 @@ namespace linker.client.config
|
|||||||
private object syncLockObj = new();
|
private object syncLockObj = new();
|
||||||
public void Sync(string key, Memory<byte> data)
|
public void Sync(string key, Memory<byte> data)
|
||||||
{
|
{
|
||||||
CheckVersion(key, out ulong version);
|
ulong version = GetVersion(key);
|
||||||
|
|
||||||
sender.SendReply(new MessageRequestWrap
|
sender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = clientSignInState.Connection,
|
Connection = clientSignInState.Connection,
|
||||||
@@ -93,31 +96,25 @@ namespace linker.client.config
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckVersion(string key, out ulong version)
|
|
||||||
{
|
|
||||||
if (runningConfig.Data.Versions.TryGetValue(key, out version) == false)
|
|
||||||
{
|
|
||||||
version = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
version++;
|
|
||||||
}
|
|
||||||
runningConfig.Data.Versions[key] = version;
|
|
||||||
runningConfig.Data.Update();
|
|
||||||
}
|
|
||||||
private ulong GetVersion(string key)
|
private ulong GetVersion(string key)
|
||||||
{
|
{
|
||||||
if (runningConfig.Data.Versions.TryGetValue(key, out ulong version) == false)
|
if (runningConfig.Data.Versions.TryGetValue(key, out ulong version) == false)
|
||||||
{
|
{
|
||||||
return 0;
|
version = 1;
|
||||||
|
runningConfig.Data.Versions[key] = version;
|
||||||
|
runningConfig.Data.Update();
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
private 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();
|
||||||
}
|
}
|
||||||
|
public void IncrementVersion(string key)
|
||||||
|
{
|
||||||
|
ulong version = GetVersion(key);
|
||||||
|
UpdateVersion(key, version + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,10 @@ using linker.libs;
|
|||||||
using linker.plugins.forward.proxy;
|
using linker.plugins.forward.proxy;
|
||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using linker.plugins.forward.messenger;
|
||||||
|
using linker.server;
|
||||||
|
using linker.client;
|
||||||
|
using MemoryPack;
|
||||||
|
|
||||||
namespace linker.plugins.forward
|
namespace linker.plugins.forward
|
||||||
{
|
{
|
||||||
@@ -14,11 +18,15 @@ namespace linker.plugins.forward
|
|||||||
{
|
{
|
||||||
private readonly ForwardTransfer forwardTransfer;
|
private readonly ForwardTransfer forwardTransfer;
|
||||||
private readonly ForwardProxy forwardProxy;
|
private readonly ForwardProxy forwardProxy;
|
||||||
|
private readonly MessengerSender messengerSender;
|
||||||
|
private readonly ClientSignInState clientSignInState;
|
||||||
|
|
||||||
public ForwardClientApiController(ForwardTransfer forwardTransfer, ForwardProxy forwardProxy)
|
public ForwardClientApiController(ForwardTransfer forwardTransfer, ForwardProxy forwardProxy, MessengerSender messengerSender, ClientSignInState clientSignInState)
|
||||||
{
|
{
|
||||||
this.forwardTransfer = forwardTransfer;
|
this.forwardTransfer = forwardTransfer;
|
||||||
this.forwardProxy = forwardProxy;
|
this.forwardProxy = forwardProxy;
|
||||||
|
this.messengerSender = messengerSender;
|
||||||
|
this.clientSignInState = clientSignInState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConcurrentDictionary<string, ITunnelConnection> Connections(ApiControllerParamsInfo param)
|
public ConcurrentDictionary<string, ITunnelConnection> Connections(ApiControllerParamsInfo param)
|
||||||
@@ -51,6 +59,21 @@ namespace linker.plugins.forward
|
|||||||
{
|
{
|
||||||
return forwardTransfer.Get();
|
return forwardTransfer.Get();
|
||||||
}
|
}
|
||||||
|
public async Task<List<ForwardRemoteInfo>> GetRemote(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
GetForwardInfo request = param.Content.DeJson<GetForwardInfo>();
|
||||||
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = clientSignInState.Connection,
|
||||||
|
MessengerId = (ushort)ForwardMessengerIds.GetForward,
|
||||||
|
Payload = MemoryPackSerializer.Serialize(request)
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
if (resp.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
return MemoryPackSerializer.Deserialize<List<ForwardRemoteInfo>>(resp.Data.Span);
|
||||||
|
}
|
||||||
|
return new List<ForwardRemoteInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
public IPAddress[] BindIPs(ApiControllerParamsInfo param)
|
public IPAddress[] BindIPs(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
@@ -62,7 +85,6 @@ namespace linker.plugins.forward
|
|||||||
ForwardInfo info = param.Content.DeJson<ForwardInfo>();
|
ForwardInfo info = param.Content.DeJson<ForwardInfo>();
|
||||||
return forwardTransfer.Add(info);
|
return forwardTransfer.Add(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(ApiControllerParamsInfo param)
|
public bool Remove(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
if (uint.TryParse(param.Content, out uint id))
|
if (uint.TryParse(param.Content, out uint id))
|
||||||
|
@@ -40,4 +40,10 @@ namespace linker.client.config
|
|||||||
public List<IPEndPoint> EndPoints { get; set; }
|
public List<IPEndPoint> EndPoints { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public sealed partial class GetForwardInfo
|
||||||
|
{
|
||||||
|
public string MachineId { get; set; }
|
||||||
|
public string ToMachineId { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
using linker.plugins.signin.messenger;
|
using linker.plugins.signin.messenger;
|
||||||
using linker.server;
|
using linker.server;
|
||||||
|
using LiteDB;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace linker.plugins.forward.messenger
|
namespace linker.plugins.forward.messenger
|
||||||
{
|
{
|
||||||
@@ -45,6 +47,34 @@ namespace linker.plugins.forward.messenger
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)ForwardMessengerIds.GetForward)]
|
||||||
|
public void GetForward(IConnection connection)
|
||||||
|
{
|
||||||
|
GetForwardInfo info = MemoryPackSerializer.Deserialize<GetForwardInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache1.GroupId == cache.GroupId)
|
||||||
|
{
|
||||||
|
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
||||||
|
sender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = cache.Connection,
|
||||||
|
MessengerId = (ushort)ForwardMessengerIds.Get,
|
||||||
|
Payload = connection.ReceiveRequestWrap.Payload
|
||||||
|
}).ContinueWith(async (result) =>
|
||||||
|
{
|
||||||
|
if (result.Result.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
await sender.ReplyOnly(new MessageResponseWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
Code = MessageResponeCodes.OK,
|
||||||
|
Payload = result.Result.Data,
|
||||||
|
RequestId = requestid
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ForwardClientMessenger : IMessenger
|
public sealed class ForwardClientMessenger : IMessenger
|
||||||
@@ -75,7 +105,31 @@ namespace linker.plugins.forward.messenger
|
|||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)ForwardMessengerIds.Get)]
|
||||||
|
public void Get(IConnection connection)
|
||||||
|
{
|
||||||
|
GetForwardInfo info = MemoryPackSerializer.Deserialize<GetForwardInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (forwardTransfer.Get().TryGetValue(info.ToMachineId, out List<ForwardInfo> list))
|
||||||
|
{
|
||||||
|
var result = list.Select(c => new ForwardRemoteInfo { BufferSize = c.BufferSize, Name = c.Name, Port = c.Port, TargetEP = c.TargetEP }).ToList();
|
||||||
|
connection.Write(MemoryPackSerializer.Serialize(result));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
connection.Write(MemoryPackSerializer.Serialize(new List<ForwardRemoteInfo>()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public sealed partial class ForwardRemoteInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Port { get; set; }
|
||||||
|
|
||||||
|
[MemoryPackAllowSerialize]
|
||||||
|
public IPEndPoint TargetEP { get; set; }
|
||||||
|
|
||||||
|
public byte BufferSize { get; set; } = 3;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,9 @@
|
|||||||
TestForward = 2401,
|
TestForward = 2401,
|
||||||
Test = 2402,
|
Test = 2402,
|
||||||
|
|
||||||
|
GetForward = 2403,
|
||||||
|
Get = 2404,
|
||||||
|
|
||||||
Max = 2499
|
Max = 2499
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -85,6 +85,7 @@ namespace linker.plugins.relay
|
|||||||
{
|
{
|
||||||
running.Data.Relay.Servers = servers;
|
running.Data.Relay.Servers = servers;
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
|
runningConfigTransfer.IncrementVersion(configKey);
|
||||||
SyncServers();
|
SyncServers();
|
||||||
}
|
}
|
||||||
private void SetServers(Memory<byte> data)
|
private void SetServers(Memory<byte> data)
|
||||||
|
@@ -2,24 +2,22 @@
|
|||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using linker.client.capi;
|
using linker.client.capi;
|
||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
using linker.server;
|
|
||||||
using linker.client;
|
using linker.client;
|
||||||
using linker.plugins.sforward.messenger;
|
using linker.server;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
|
using linker.plugins.sforward.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.sforward
|
namespace linker.plugins.sforward
|
||||||
{
|
{
|
||||||
public sealed class SForwardClientApiController : IApiClientController
|
public sealed class SForwardClientApiController : IApiClientController
|
||||||
{
|
{
|
||||||
private readonly SForwardTransfer forwardTransfer;
|
private readonly SForwardTransfer forwardTransfer;
|
||||||
private readonly RunningConfig runningConfig;
|
|
||||||
private readonly MessengerSender messengerSender;
|
private readonly MessengerSender messengerSender;
|
||||||
private readonly ClientSignInState clientSignInState;
|
private readonly ClientSignInState clientSignInState;
|
||||||
|
|
||||||
public SForwardClientApiController(SForwardTransfer forwardTransfer, RunningConfig runningConfig, MessengerSender messengerSender, ClientSignInState clientSignInState)
|
public SForwardClientApiController(SForwardTransfer forwardTransfer, MessengerSender messengerSender, ClientSignInState clientSignInState)
|
||||||
{
|
{
|
||||||
this.forwardTransfer = forwardTransfer;
|
this.forwardTransfer = forwardTransfer;
|
||||||
this.runningConfig = runningConfig;
|
|
||||||
this.messengerSender = messengerSender;
|
this.messengerSender = messengerSender;
|
||||||
this.clientSignInState = clientSignInState;
|
this.clientSignInState = clientSignInState;
|
||||||
}
|
}
|
||||||
@@ -38,6 +36,20 @@ namespace linker.plugins.sforward
|
|||||||
{
|
{
|
||||||
return forwardTransfer.Get();
|
return forwardTransfer.Get();
|
||||||
}
|
}
|
||||||
|
public async Task<List<SForwardRemoteInfo>> GetRemote(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = clientSignInState.Connection,
|
||||||
|
MessengerId = (ushort)SForwardMessengerIds.GetForward,
|
||||||
|
Payload = MemoryPackSerializer.Serialize(param.Content)
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
if (resp.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
return MemoryPackSerializer.Deserialize<List<SForwardRemoteInfo>>(resp.Data.Span);
|
||||||
|
}
|
||||||
|
return new List<SForwardRemoteInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
public bool Add(ApiControllerParamsInfo param)
|
public bool Add(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
|
@@ -46,6 +46,7 @@ namespace linker.plugins.sforward
|
|||||||
{
|
{
|
||||||
running.Data.SForwardSecretKey = key;
|
running.Data.SForwardSecretKey = key;
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
|
runningConfigTransfer.IncrementVersion(configKey);
|
||||||
SyncKey();
|
SyncKey();
|
||||||
}
|
}
|
||||||
private void SetSecretKey(Memory<byte> data)
|
private void SetSecretKey(Memory<byte> data)
|
||||||
@@ -237,7 +238,6 @@ namespace linker.plugins.sforward
|
|||||||
Start();
|
Start();
|
||||||
running.Data.SForwards.Remove(old);
|
running.Data.SForwards.Remove(old);
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,9 @@ using linker.server;
|
|||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using linker.plugins.sforward.proxy;
|
using linker.plugins.sforward.proxy;
|
||||||
using linker.config;
|
using linker.config;
|
||||||
|
using LiteDB;
|
||||||
|
using System.Net;
|
||||||
|
using linker.plugins.forward.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.sforward.messenger
|
namespace linker.plugins.sforward.messenger
|
||||||
{
|
{
|
||||||
@@ -151,6 +154,34 @@ namespace linker.plugins.sforward.messenger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)SForwardMessengerIds.GetForward)]
|
||||||
|
public void GetForward(IConnection connection)
|
||||||
|
{
|
||||||
|
string machineId = MemoryPackSerializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(machineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache1.GroupId == cache.GroupId)
|
||||||
|
{
|
||||||
|
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
||||||
|
sender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = cache.Connection,
|
||||||
|
MessengerId = (ushort)SForwardMessengerIds.Get,
|
||||||
|
Payload = connection.ReceiveRequestWrap.Payload
|
||||||
|
}).ContinueWith(async (result) =>
|
||||||
|
{
|
||||||
|
if (result.Result.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
await sender.ReplyOnly(new MessageResponseWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
Code = MessageResponeCodes.OK,
|
||||||
|
Payload = result.Result.Data,
|
||||||
|
RequestId = requestid
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<bool> WebConnect(string host, int port, ulong id)
|
private async Task<bool> WebConnect(string host, int port, ulong id)
|
||||||
{
|
{
|
||||||
if (sForwardServerCahing.TryGet(host, out string machineId) && signCaching.TryGet(machineId, out SignCacheInfo sign) && sign.Connected)
|
if (sForwardServerCahing.TryGet(host, out string machineId) && signCaching.TryGet(machineId, out SignCacheInfo sign) && sign.Connected)
|
||||||
@@ -159,7 +190,7 @@ namespace linker.plugins.sforward.messenger
|
|||||||
{
|
{
|
||||||
Connection = sign.Connection,
|
Connection = sign.Connection,
|
||||||
MessengerId = (ushort)SForwardMessengerIds.Proxy,
|
MessengerId = (ushort)SForwardMessengerIds.Proxy,
|
||||||
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { Domain = host, RemotePort = port, Id = id, BufferSize= configWrap.Data.Server.SForward.BufferSize })
|
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { Domain = host, RemotePort = port, Id = id, BufferSize = configWrap.Data.Server.SForward.BufferSize })
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -196,11 +227,13 @@ namespace linker.plugins.sforward.messenger
|
|||||||
{
|
{
|
||||||
private readonly SForwardProxy proxy;
|
private readonly SForwardProxy proxy;
|
||||||
private readonly RunningConfig runningConfig;
|
private readonly RunningConfig runningConfig;
|
||||||
|
private readonly SForwardTransfer sForwardTransfer;
|
||||||
|
|
||||||
public SForwardClientMessenger(SForwardProxy proxy, RunningConfig runningConfig)
|
public SForwardClientMessenger(SForwardProxy proxy, RunningConfig runningConfig, SForwardTransfer sForwardTransfer)
|
||||||
{
|
{
|
||||||
this.proxy = proxy;
|
this.proxy = proxy;
|
||||||
this.runningConfig = runningConfig;
|
this.runningConfig = runningConfig;
|
||||||
|
this.sForwardTransfer = sForwardTransfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MessengerId((ushort)SForwardMessengerIds.Proxy)]
|
[MessengerId((ushort)SForwardMessengerIds.Proxy)]
|
||||||
@@ -213,7 +246,7 @@ namespace linker.plugins.sforward.messenger
|
|||||||
SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.Domain == sForwardProxyInfo.Domain);
|
SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.Domain == sForwardProxyInfo.Domain);
|
||||||
if (sForwardInfo != null)
|
if (sForwardInfo != null)
|
||||||
{
|
{
|
||||||
_ = proxy.OnConnectTcp(sForwardProxyInfo.BufferSize,sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
|
_ = proxy.OnConnectTcp(sForwardProxyInfo.BufferSize, sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sForwardProxyInfo.RemotePort > 0)
|
else if (sForwardProxyInfo.RemotePort > 0)
|
||||||
@@ -225,6 +258,7 @@ namespace linker.plugins.sforward.messenger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MessengerId((ushort)SForwardMessengerIds.ProxyUdp)]
|
[MessengerId((ushort)SForwardMessengerIds.ProxyUdp)]
|
||||||
public void ProxyUdp(IConnection connection)
|
public void ProxyUdp(IConnection connection)
|
||||||
{
|
{
|
||||||
@@ -238,5 +272,33 @@ namespace linker.plugins.sforward.messenger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)SForwardMessengerIds.Get)]
|
||||||
|
public void Get(IConnection connection)
|
||||||
|
{
|
||||||
|
List<SForwardRemoteInfo> result = sForwardTransfer.Get().Select(c => new SForwardRemoteInfo
|
||||||
|
{
|
||||||
|
BufferSize = c.BufferSize,
|
||||||
|
Domain = c.Domain,
|
||||||
|
LocalEP = c.LocalEP,
|
||||||
|
Name = c.Name,
|
||||||
|
RemotePort = c.RemotePort,
|
||||||
|
}).ToList();
|
||||||
|
connection.Write(MemoryPackSerializer.Serialize(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public sealed partial class SForwardRemoteInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Domain { get; set; }
|
||||||
|
public int RemotePort { get; set; }
|
||||||
|
|
||||||
|
public byte BufferSize { get; set; } = 3;
|
||||||
|
|
||||||
|
[MemoryPackAllowSerialize]
|
||||||
|
public IPEndPoint LocalEP { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,9 @@
|
|||||||
Proxy = 2303,
|
Proxy = 2303,
|
||||||
ProxyUdp = 2304,
|
ProxyUdp = 2304,
|
||||||
|
|
||||||
|
GetForward = 2305,
|
||||||
|
Get = 2306,
|
||||||
|
|
||||||
Max = 2399
|
Max = 2399
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -74,6 +74,21 @@ namespace linker.plugins.signin
|
|||||||
}
|
}
|
||||||
return new SignInListResponseInfo { };
|
return new SignInListResponseInfo { };
|
||||||
}
|
}
|
||||||
|
public async Task<SignInIdsResponseInfo> Ids(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
SignInIdsRequestInfo request = param.Content.DeJson<SignInIdsRequestInfo>();
|
||||||
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = clientSignInState.Connection,
|
||||||
|
MessengerId = (ushort)SignInMessengerIds.Ids,
|
||||||
|
Payload = MemoryPackSerializer.Serialize(request)
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
if (resp.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
return MemoryPackSerializer.Deserialize<SignInIdsResponseInfo>(resp.Data.Span);
|
||||||
|
}
|
||||||
|
return new SignInIdsResponseInfo { };
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> SetName(ApiControllerParamsInfo param)
|
public async Task<bool> SetName(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
|
@@ -8,11 +8,9 @@ namespace linker.plugins.signin.messenger
|
|||||||
{
|
{
|
||||||
public sealed class SignInClientMessenger : IMessenger
|
public sealed class SignInClientMessenger : IMessenger
|
||||||
{
|
{
|
||||||
private readonly ConfigWrap config;
|
|
||||||
private readonly ClientSignInTransfer clientSignInTransfer;
|
private readonly ClientSignInTransfer clientSignInTransfer;
|
||||||
public SignInClientMessenger(ConfigWrap config, ClientSignInTransfer clientSignInTransfer)
|
public SignInClientMessenger(ConfigWrap config, ClientSignInTransfer clientSignInTransfer)
|
||||||
{
|
{
|
||||||
this.config = config;
|
|
||||||
this.clientSignInTransfer = clientSignInTransfer;
|
this.clientSignInTransfer = clientSignInTransfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,13 +56,12 @@ namespace linker.plugins.signin.messenger
|
|||||||
public void List(IConnection connection)
|
public void List(IConnection connection)
|
||||||
{
|
{
|
||||||
SignInListRequestInfo request = MemoryPackSerializer.Deserialize<SignInListRequestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
SignInListRequestInfo request = MemoryPackSerializer.Deserialize<SignInListRequestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
|
||||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
|
||||||
{
|
{
|
||||||
IEnumerable<SignCacheInfo> list = signCaching.Get(cache.GroupId).OrderByDescending(c => c.MachineName).OrderByDescending(c => c.LastSignIn).OrderByDescending(c => c.Version).ToList();
|
IEnumerable<SignCacheInfo> list = signCaching.Get(cache.GroupId).OrderByDescending(c => c.MachineName).OrderByDescending(c => c.LastSignIn).OrderByDescending(c => c.Version).ToList();
|
||||||
if (string.IsNullOrWhiteSpace(request.Name) == false)
|
if (string.IsNullOrWhiteSpace(request.Name) == false)
|
||||||
{
|
{
|
||||||
list = list.Where(c => c.MachineName.Contains(request.Name));
|
list = list.Where(c => c.Version.Contains(request.Name) || c.IP.ToString().Contains(request.Name) || c.MachineName.Contains(request.Name) || request.Ids.Contains(c.MachineId));
|
||||||
}
|
}
|
||||||
int count = list.Count();
|
int count = list.Count();
|
||||||
list = list.Skip((request.Page - 1) * request.Size).Take(request.Size);
|
list = list.Skip((request.Page - 1) * request.Size).Take(request.Size);
|
||||||
@@ -109,6 +106,31 @@ namespace linker.plugins.signin.messenger
|
|||||||
connection.Write(MemoryPackSerializer.Serialize(config.Data.Version));
|
connection.Write(MemoryPackSerializer.Serialize(config.Data.Version));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MessengerId((ushort)SignInMessengerIds.Ids)]
|
||||||
|
public void Ids(IConnection connection)
|
||||||
|
{
|
||||||
|
SignInIdsRequestInfo request = MemoryPackSerializer.Deserialize<SignInIdsRequestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
|
||||||
|
{
|
||||||
|
IEnumerable<SignCacheInfo> list = signCaching.Get(cache.GroupId).OrderByDescending(c => c.MachineName).OrderByDescending(c => c.LastSignIn).OrderByDescending(c => c.Version).ToList();
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Name) == false)
|
||||||
|
{
|
||||||
|
list = list.Where(c => c.MachineName.Contains(request.Name));
|
||||||
|
}
|
||||||
|
int count = list.Count();
|
||||||
|
list = list.Skip((request.Page - 1) * request.Size).Take(request.Size);
|
||||||
|
|
||||||
|
SignInIdsResponseInfo response = new SignInIdsResponseInfo
|
||||||
|
{
|
||||||
|
Request = request,
|
||||||
|
Count = count,
|
||||||
|
List = list.Select(c => new SignInIdsResponseItemInfo { MachineId = c.MachineId, MachineName = c.MachineName }).ToList()
|
||||||
|
};
|
||||||
|
|
||||||
|
connection.Write(MemoryPackSerializer.Serialize(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MemoryPackable]
|
[MemoryPackable]
|
||||||
@@ -130,6 +152,10 @@ namespace linker.plugins.signin.messenger
|
|||||||
/// 按名称搜索
|
/// 按名称搜索
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 按id获取
|
||||||
|
/// </summary>
|
||||||
|
public string[] Ids { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MemoryPackable]
|
[MemoryPackable]
|
||||||
@@ -139,4 +165,37 @@ namespace linker.plugins.signin.messenger
|
|||||||
public int Count { get; set; }
|
public int Count { get; set; }
|
||||||
public List<SignCacheInfo> List { get; set; } = new List<SignCacheInfo>();
|
public List<SignCacheInfo> List { get; set; } = new List<SignCacheInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public sealed partial class SignInIdsRequestInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 当前页
|
||||||
|
/// </summary>
|
||||||
|
public int Page { get; set; } = 1;
|
||||||
|
/// <summary>
|
||||||
|
/// 每页大小
|
||||||
|
/// </summary>
|
||||||
|
public int Size { get; set; } = 10;
|
||||||
|
/// <summary>
|
||||||
|
/// 按名称搜索
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public sealed partial class SignInIdsResponseInfo
|
||||||
|
{
|
||||||
|
public SignInIdsRequestInfo Request { get; set; } = new SignInIdsRequestInfo();
|
||||||
|
public int Count { get; set; }
|
||||||
|
public List<SignInIdsResponseItemInfo> List { get; set; } = new List<SignInIdsResponseItemInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public sealed partial class SignInIdsResponseItemInfo
|
||||||
|
{
|
||||||
|
public string MachineId { get; set; }
|
||||||
|
public string MachineName { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
Version = 7,
|
Version = 7,
|
||||||
|
|
||||||
|
Ids = 8,
|
||||||
|
|
||||||
None = 99
|
None = 99
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -68,10 +68,12 @@ namespace linker.plugins.tunnel
|
|||||||
{
|
{
|
||||||
return running.Data.Tunnel.Servers;
|
return running.Data.Tunnel.Servers;
|
||||||
}
|
}
|
||||||
public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> compacts)
|
public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> compacts, bool updateVersion)
|
||||||
{
|
{
|
||||||
running.Data.Tunnel.Servers = compacts;
|
running.Data.Tunnel.Servers = compacts;
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
|
if (updateVersion)
|
||||||
|
runningConfigTransfer.IncrementVersion(wanPortConfigKey);
|
||||||
SyncWanPort();
|
SyncWanPort();
|
||||||
}
|
}
|
||||||
private void SetTunnelWanPortProtocols(Memory<byte> data)
|
private void SetTunnelWanPortProtocols(Memory<byte> data)
|
||||||
@@ -84,10 +86,12 @@ namespace linker.plugins.tunnel
|
|||||||
{
|
{
|
||||||
return running.Data.Tunnel.Transports;
|
return running.Data.Tunnel.Transports;
|
||||||
}
|
}
|
||||||
public void SetTunnelTransports(List<TunnelTransportItemInfo> transports)
|
public void SetTunnelTransports(List<TunnelTransportItemInfo> transports, bool updateVersion)
|
||||||
{
|
{
|
||||||
running.Data.Tunnel.Transports = transports;
|
running.Data.Tunnel.Transports = transports;
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
|
if (updateVersion)
|
||||||
|
runningConfigTransfer.IncrementVersion(transportConfigKey);
|
||||||
SyncTransport();
|
SyncTransport();
|
||||||
}
|
}
|
||||||
private void SetTunnelTransports(Memory<byte> data)
|
private void SetTunnelTransports(Memory<byte> data)
|
||||||
|
@@ -81,7 +81,7 @@ namespace linker.plugins.tunnel
|
|||||||
public bool SetServers(ApiControllerParamsInfo param)
|
public bool SetServers(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
List<TunnelWanPortInfo> info = param.Content.DeJson<List<TunnelWanPortInfo>>();
|
List<TunnelWanPortInfo> info = param.Content.DeJson<List<TunnelWanPortInfo>>();
|
||||||
tunnelMessengerAdapter.SetTunnelWanPortProtocols(info);
|
tunnelMessengerAdapter.SetTunnelWanPortProtocols(info,true);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ namespace linker.plugins.tunnel
|
|||||||
public bool SetTransports(ApiControllerParamsInfo param)
|
public bool SetTransports(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
List<TunnelTransportItemInfo> info = param.Content.DeJson<List<TunnelTransportItemInfo>>();
|
List<TunnelTransportItemInfo> info = param.Content.DeJson<List<TunnelTransportItemInfo>>();
|
||||||
tunnelMessengerAdapter.SetTunnelTransports(info);
|
tunnelMessengerAdapter.SetTunnelTransports(info, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ using linker.client.config;
|
|||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.plugins.tunnel.messenger;
|
using linker.plugins.tunnel.messenger;
|
||||||
using linker.server;
|
using linker.server;
|
||||||
|
using linker.tunnel.adapter;
|
||||||
using linker.tunnel.wanport;
|
using linker.tunnel.wanport;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@@ -16,6 +17,7 @@ namespace linker.plugins.tunnel
|
|||||||
private readonly ClientSignInState clientSignInState;
|
private readonly ClientSignInState clientSignInState;
|
||||||
private readonly MessengerSender messengerSender;
|
private readonly MessengerSender messengerSender;
|
||||||
private readonly RunningConfigTransfer runningConfigTransfer;
|
private readonly RunningConfigTransfer runningConfigTransfer;
|
||||||
|
private readonly ITunnelAdapter tunnelAdapter;
|
||||||
|
|
||||||
private string exipConfigKey = "excludeIPConfig";
|
private string exipConfigKey = "excludeIPConfig";
|
||||||
|
|
||||||
@@ -24,13 +26,14 @@ 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)
|
public TunnelConfigTransfer(ConfigWrap config, RunningConfig running, ClientSignInState clientSignInState, MessengerSender messengerSender, RunningConfigTransfer runningConfigTransfer, ITunnelAdapter tunnelAdapter)
|
||||||
{
|
{
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.running = running;
|
this.running = running;
|
||||||
this.clientSignInState = clientSignInState;
|
this.clientSignInState = clientSignInState;
|
||||||
this.messengerSender = messengerSender;
|
this.messengerSender = messengerSender;
|
||||||
this.runningConfigTransfer = runningConfigTransfer;
|
this.runningConfigTransfer = runningConfigTransfer;
|
||||||
|
this.tunnelAdapter = tunnelAdapter;
|
||||||
|
|
||||||
clientSignInState.NetworkEnabledHandle += (times) =>
|
clientSignInState.NetworkEnabledHandle += (times) =>
|
||||||
{
|
{
|
||||||
@@ -48,9 +51,11 @@ namespace linker.plugins.tunnel
|
|||||||
}
|
}
|
||||||
private void InitConfig()
|
private void InitConfig()
|
||||||
{
|
{
|
||||||
if (running.Data.Tunnel.Servers.FirstOrDefault(c => c.Type == TunnelWanPortType.Linker && c.ProtocolType == TunnelWanPortProtocolType.Udp) == null)
|
bool updateVersion = false;
|
||||||
|
List<TunnelWanPortInfo> server = running.Data.Tunnel.Servers;
|
||||||
|
if (server.FirstOrDefault(c => c.Type == TunnelWanPortType.Linker && c.ProtocolType == TunnelWanPortProtocolType.Udp) == null)
|
||||||
{
|
{
|
||||||
running.Data.Tunnel.Servers.Add(new TunnelWanPortInfo
|
server.Add(new TunnelWanPortInfo
|
||||||
{
|
{
|
||||||
Name = "Linker Udp",
|
Name = "Linker Udp",
|
||||||
Type = TunnelWanPortType.Linker,
|
Type = TunnelWanPortType.Linker,
|
||||||
@@ -58,10 +63,11 @@ namespace linker.plugins.tunnel
|
|||||||
Disabled = false,
|
Disabled = false,
|
||||||
Host = running.Data.Client.Servers.FirstOrDefault().Host,
|
Host = running.Data.Client.Servers.FirstOrDefault().Host,
|
||||||
});
|
});
|
||||||
|
updateVersion = true;
|
||||||
}
|
}
|
||||||
if (running.Data.Tunnel.Servers.FirstOrDefault(c => c.Type == TunnelWanPortType.Linker && c.ProtocolType == TunnelWanPortProtocolType.Tcp) == null)
|
if (server.FirstOrDefault(c => c.Type == TunnelWanPortType.Linker && c.ProtocolType == TunnelWanPortProtocolType.Tcp) == null)
|
||||||
{
|
{
|
||||||
running.Data.Tunnel.Servers.Add(new TunnelWanPortInfo
|
server.Add(new TunnelWanPortInfo
|
||||||
{
|
{
|
||||||
Name = "Linker Tcp",
|
Name = "Linker Tcp",
|
||||||
Type = TunnelWanPortType.Linker,
|
Type = TunnelWanPortType.Linker,
|
||||||
@@ -69,7 +75,9 @@ namespace linker.plugins.tunnel
|
|||||||
Disabled = false,
|
Disabled = false,
|
||||||
Host = running.Data.Client.Servers.FirstOrDefault().Host,
|
Host = running.Data.Client.Servers.FirstOrDefault().Host,
|
||||||
});
|
});
|
||||||
|
updateVersion = true;
|
||||||
}
|
}
|
||||||
|
tunnelAdapter.SetTunnelWanPortProtocols(server, updateVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -147,6 +155,7 @@ namespace linker.plugins.tunnel
|
|||||||
{
|
{
|
||||||
running.Data.Tunnel.ExcludeIPs = ips;
|
running.Data.Tunnel.ExcludeIPs = ips;
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
|
runningConfigTransfer.IncrementVersion(exipConfigKey);
|
||||||
SyncExcludeIP();
|
SyncExcludeIP();
|
||||||
}
|
}
|
||||||
private void SettExcludeIPs(Memory<byte> data)
|
private void SettExcludeIPs(Memory<byte> data)
|
||||||
|
@@ -6,8 +6,6 @@ using linker.tunnel.adapter;
|
|||||||
using linker.tunnel.transport;
|
using linker.tunnel.transport;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using linker.tunnel.wanport;
|
|
||||||
using linker.client.config;
|
|
||||||
|
|
||||||
namespace linker.plugins.tunnel.messenger
|
namespace linker.plugins.tunnel.messenger
|
||||||
{
|
{
|
||||||
@@ -15,13 +13,11 @@ namespace linker.plugins.tunnel.messenger
|
|||||||
{
|
{
|
||||||
private readonly TunnelTransfer tunnel;
|
private readonly TunnelTransfer tunnel;
|
||||||
private readonly TunnelConfigTransfer tunnelConfigTransfer;
|
private readonly TunnelConfigTransfer tunnelConfigTransfer;
|
||||||
private readonly ITunnelAdapter tunnelMessengerAdapter;
|
|
||||||
|
|
||||||
public TunnelClientMessenger(TunnelTransfer tunnel, TunnelConfigTransfer tunnelConfigTransfer, ITunnelAdapter tunnelMessengerAdapter)
|
public TunnelClientMessenger(TunnelTransfer tunnel, TunnelConfigTransfer tunnelConfigTransfer)
|
||||||
{
|
{
|
||||||
this.tunnel = tunnel;
|
this.tunnel = tunnel;
|
||||||
this.tunnelConfigTransfer = tunnelConfigTransfer;
|
this.tunnelConfigTransfer = tunnelConfigTransfer;
|
||||||
this.tunnelMessengerAdapter = tunnelMessengerAdapter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MessengerId((ushort)TunnelMessengerIds.Begin)]
|
[MessengerId((ushort)TunnelMessengerIds.Begin)]
|
||||||
|
Reference in New Issue
Block a user