mirror of
https://github.com/snltty/linker.git
synced 2025-10-17 22:50:44 +08:00
更多提醒
This commit is contained in:
15
.github/workflows/dotnet.yml
vendored
15
.github/workflows/dotnet.yml
vendored
@@ -48,18 +48,15 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}'
|
GITHUB_TOKEN: '${{ secrets.ACTIONS_TOKEN }}'
|
||||||
with:
|
with:
|
||||||
tag_name: v1.1.2.2
|
tag_name: v1.1.2.3
|
||||||
release_name: v1.1.2.2.${{ steps.date.outputs.today }}
|
release_name: v1.1.2.3.${{ steps.date.outputs.today }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
body: |
|
body: |
|
||||||
1. 更新配置同步方式,以版本同步
|
1. 修复虚拟网卡添加路由错误
|
||||||
2. 设备列表搜索,按 设备名/设备IP/虚拟网卡IP/端口转发端口和IP 搜索
|
2. 自动更新,客户端和服务端
|
||||||
3. 端口转发配置复制,可以将A转发到B的配置复制给C转发到B
|
3. 更多的消息提醒,需要重启时提醒
|
||||||
4. 服务器代理穿透配置复制
|
4. 请更新服务端
|
||||||
5. 修复虚拟网卡添加路由错误
|
|
||||||
6. 自动更新,管理所有客户端更新
|
|
||||||
7. 请更新服务端
|
|
||||||
|
|
||||||
- name: upload win x64
|
- name: upload win x64
|
||||||
id: upload-win-x64
|
id: upload-win-x64
|
||||||
|
@@ -15,8 +15,8 @@
|
|||||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||||
<Version>1.1.2</Version>
|
<Version>1.1.2</Version>
|
||||||
<AssemblyVersion>1.1.2.2</AssemblyVersion>
|
<AssemblyVersion>1.1.2.3</AssemblyVersion>
|
||||||
<FileVersion>1.1.2.2</FileVersion>
|
<FileVersion>1.1.2.3</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
|
@@ -22,8 +22,8 @@
|
|||||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||||
<PackageReleaseNotes>snltty service</PackageReleaseNotes>
|
<PackageReleaseNotes>snltty service</PackageReleaseNotes>
|
||||||
<AssemblyVersion>1.1.2.2</AssemblyVersion>
|
<AssemblyVersion>1.1.2.3</AssemblyVersion>
|
||||||
<FileVersion>1.1.2.2</FileVersion>
|
<FileVersion>1.1.2.3</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
@@ -17,8 +17,8 @@
|
|||||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||||
<PackageReleaseNotes>linker tunnel</PackageReleaseNotes>
|
<PackageReleaseNotes>linker tunnel</PackageReleaseNotes>
|
||||||
<AssemblyVersion>1.1.2.2</AssemblyVersion>
|
<AssemblyVersion>1.1.2.3</AssemblyVersion>
|
||||||
<FileVersion>1.1.2.2</FileVersion>
|
<FileVersion>1.1.2.3</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
@@ -10,8 +10,6 @@ using System.Net.Sockets;
|
|||||||
using System.Security.Authentication;
|
using System.Security.Authentication;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using linker.tunnel.wanport;
|
using linker.tunnel.wanport;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace linker.tunnel.transport
|
namespace linker.tunnel.transport
|
||||||
{
|
{
|
||||||
@@ -664,7 +662,6 @@ namespace linker.tunnel.transport
|
|||||||
{
|
{
|
||||||
if (OperatingSystem.IsWindows() || OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
if (OperatingSystem.IsWindows() || OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
TestQuic();
|
|
||||||
if (QuicListener.IsSupported == false)
|
if (QuicListener.IsSupported == false)
|
||||||
{
|
{
|
||||||
LoggerHelper.Instance.Error($"msquic not supported, need win11+,or linux, or try to restart linker");
|
LoggerHelper.Instance.Error($"msquic not supported, need win11+,or linux, or try to restart linker");
|
||||||
@@ -729,28 +726,7 @@ namespace linker.tunnel.transport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void TestQuic()
|
|
||||||
{
|
|
||||||
if (OperatingSystem.IsWindows())
|
|
||||||
{
|
|
||||||
if (QuicListener.IsSupported == false)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (File.Exists("msquic-openssl.dll"))
|
|
||||||
{
|
|
||||||
LoggerHelper.Instance.Info($"copy msquic-openssl.dll -> msquic.dll");
|
|
||||||
File.Move("msquic-openssl.dll", "msquic.dll", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sealed class ListenAsyncToken
|
sealed class ListenAsyncToken
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -773,10 +749,5 @@ namespace linker.tunnel.transport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ListenStep : byte
|
|
||||||
{
|
|
||||||
Auth = 0,
|
|
||||||
Forward = 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -157,6 +157,14 @@ span.split-pad10 {
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.green {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.yellow {
|
||||||
|
color: #e68906
|
||||||
|
}
|
||||||
|
|
||||||
.scrollbar,
|
.scrollbar,
|
||||||
.scrollbar-1,
|
.scrollbar-1,
|
||||||
.scrollbar-4,
|
.scrollbar-4,
|
||||||
@@ -214,6 +222,9 @@ span.split-pad10 {
|
|||||||
--el-color-primary-dark-2: var(--el-color-success-dark-2) !important;
|
--el-color-primary-dark-2: var(--el-color-success-dark-2) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-table .cell {
|
||||||
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
.el-table--scrollable-y .el-table__body-wrapper::-webkit-scrollbar {
|
.el-table--scrollable-y .el-table__body-wrapper::-webkit-scrollbar {
|
||||||
background: #f5f5f5
|
background: #f5f5f5
|
||||||
|
@@ -56,8 +56,11 @@ export default {
|
|||||||
setup(props) {
|
setup(props) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const updaterCurrent = ref({Version: '', Status: 0, Length: 0, Current: 0});
|
const updaterCurrent = ref({Version: '', Msg: [], DateTime: '', Status: 0, Length: 0, Current: 0});
|
||||||
const updaterServer = ref({Version: '', Status: 0, Length: 0, Current: 0});
|
const updaterServer = ref({Version: '', Status: 0, Length: 0, Current: 0});
|
||||||
|
const updaterMsg = computed(()=>{
|
||||||
|
return `${updaterCurrent.value.Version}->${updaterCurrent.value.DateTime}\n${updaterCurrent.value.Msg.map((value,index)=>`${index+1}、${value}`).join('\n')}`;
|
||||||
|
});
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
show: false,
|
show: false,
|
||||||
@@ -75,10 +78,12 @@ export default {
|
|||||||
|
|
||||||
const _getUpdaterCurrent = ()=>{
|
const _getUpdaterCurrent = ()=>{
|
||||||
getUpdaterCurrent().then((res)=>{
|
getUpdaterCurrent().then((res)=>{
|
||||||
|
updaterCurrent.value.DateTime = res.DateTime;
|
||||||
updaterCurrent.value.Version = res.Version;
|
updaterCurrent.value.Version = res.Version;
|
||||||
updaterCurrent.value.Status = res.Status;
|
updaterCurrent.value.Status = res.Status;
|
||||||
updaterCurrent.value.Length = res.Length;
|
updaterCurrent.value.Length = res.Length;
|
||||||
updaterCurrent.value.Current = res.Current;
|
updaterCurrent.value.Current = res.Current;
|
||||||
|
updaterCurrent.value.Msg = res.Msg;
|
||||||
setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
_getUpdaterCurrent();
|
_getUpdaterCurrent();
|
||||||
},1000);
|
},1000);
|
||||||
@@ -111,8 +116,8 @@ export default {
|
|||||||
}
|
}
|
||||||
if(updaterServer.value.Status <= 2) {
|
if(updaterServer.value.Status <= 2) {
|
||||||
return state.version != updaterCurrent.value.Version
|
return state.version != updaterCurrent.value.Version
|
||||||
? `不是最新版本(${updaterCurrent.value.Version}),建议更新`
|
? `不是最新版本(${updaterCurrent.value.Version}),建议更新\n${updaterMsg.value}`
|
||||||
: '是最新版本,但我无法阻止你喜欢更新'
|
: `是最新版本,但我无法阻止你喜欢更新\n${updaterMsg.value}`
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
3:'正在下载',
|
3:'正在下载',
|
||||||
@@ -216,12 +221,8 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.download{
|
a.download{
|
||||||
&.green{color:green}
|
|
||||||
&.red{color:red}
|
|
||||||
&.yellow{color:#e68906}
|
|
||||||
.el-icon{
|
.el-icon{
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
&.yellow{color:#e68906}
|
|
||||||
&.loading{
|
&.loading{
|
||||||
animation:loading 1s linear infinite;
|
animation:loading 1s linear infinite;
|
||||||
}
|
}
|
||||||
|
@@ -2,8 +2,6 @@ import { createApp } from 'vue'
|
|||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
|
||||||
// import VConsole from 'vconsole';
|
|
||||||
// new VConsole();
|
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
@@ -14,17 +12,4 @@ import 'element-plus/dist/index.css'
|
|||||||
import 'element-plus/theme-chalk/display.css'
|
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 {
|
|
||||||
ArrowDown, Top, Bottom, Delete, Plus, Select, Refresh, Search
|
|
||||||
} from '@element-plus/icons-vue'
|
|
||||||
app.component(ArrowDown.name, ArrowDown);
|
|
||||||
app.component(Top.name, Top);
|
|
||||||
app.component(Bottom.name, Bottom);
|
|
||||||
app.component(Delete.name, Delete);
|
|
||||||
app.component(Plus.name, Plus);
|
|
||||||
app.component(Select.name, Select);
|
|
||||||
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');
|
||||||
|
@@ -54,9 +54,11 @@
|
|||||||
import { reactive, watch,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';
|
import { useConnections, useForwardConnections, useTuntapConnections } from './connections';
|
||||||
|
import { Delete } from '@element-plus/icons-vue';
|
||||||
export default {
|
export default {
|
||||||
props: ['modelValue'],
|
props: ['modelValue'],
|
||||||
emits: ['change','update:modelValue'],
|
emits: ['change','update:modelValue'],
|
||||||
|
components: {Delete},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const connections = useConnections();
|
const connections = useConnections();
|
||||||
@@ -97,5 +99,4 @@ export default {
|
|||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
|
||||||
.head{padding-bottom:1rem}
|
.head{padding-bottom:1rem}
|
||||||
.green{color:green}
|
|
||||||
</style>
|
</style>
|
@@ -18,7 +18,7 @@
|
|||||||
<p class="flex">
|
<p class="flex">
|
||||||
<span>{{ scope.row.IP }}</span>
|
<span>{{ scope.row.IP }}</span>
|
||||||
<span class="flex-1"></span>
|
<span class="flex-1"></span>
|
||||||
<a href="javascript:;" class="download" title="下载更新" @click="handleUpdate(scope.row)" :title="updateText(scope.row)" :class="updateColor(scope.row)">
|
<a href="javascript:;" class="download" @click="handleUpdate(scope.row)" :title="updateText(scope.row)" :class="updateColor(scope.row)">
|
||||||
<span>
|
<span>
|
||||||
<span>{{scope.row.Version}}</span>
|
<span>{{scope.row.Version}}</span>
|
||||||
<template v-if="updater.list[scope.row.MachineId]">
|
<template v-if="updater.list[scope.row.MachineId]">
|
||||||
@@ -65,16 +65,21 @@ export default {
|
|||||||
const updater = useUpdater();
|
const updater = useUpdater();
|
||||||
const serverVersion = computed(()=>globalData.value.signin.Version);
|
const serverVersion = computed(()=>globalData.value.signin.Version);
|
||||||
const updaterVersion = computed(()=>updater.value.current.Version);
|
const updaterVersion = computed(()=>updater.value.current.Version);
|
||||||
|
const updaterMsg = computed(()=>{
|
||||||
|
return `${updaterVersion.value}->${updater.value.current.DateTime}\n${updater.value.current.Msg.map((value,index)=>`${index+1}、${value}`).join('\n')}`;
|
||||||
|
});
|
||||||
|
|
||||||
const updateText = (row)=>{
|
const updateText = (row)=>{
|
||||||
if(!updater.value.list[row.MachineId]){
|
if(!updater.value.list[row.MachineId]){
|
||||||
return '未检测到更新';
|
return '未检测到更新';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(updater.value.list[row.MachineId].Status <= 2) {
|
if(updater.value.list[row.MachineId].Status <= 2) {
|
||||||
return row.Version != serverVersion.value
|
return row.Version != serverVersion.value
|
||||||
? `与服务器版本(${serverVersion.value})不一致,建议更新`
|
? `与服务器版本(${serverVersion.value})不一致,建议更新`
|
||||||
: updaterVersion.value != row.Version
|
: updaterVersion.value != row.Version
|
||||||
? `不是最新版本(${updaterVersion.value}),建议更新` : '是最新版本,但我无法阻止你喜欢更新'
|
? `不是最新版本(${updaterVersion.value}),建议更新\n${updaterMsg.value}`
|
||||||
|
: `是最新版本,但我无法阻止你喜欢更新\n${updaterMsg.value}`
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
3:'正在下载',
|
3:'正在下载',
|
||||||
@@ -170,12 +175,8 @@ a{
|
|||||||
|
|
||||||
a.download{
|
a.download{
|
||||||
margin-left:.6rem
|
margin-left:.6rem
|
||||||
&.green{color:green}
|
|
||||||
&.red{color:red}
|
|
||||||
&.yellow{color:#e68906}
|
|
||||||
.el-icon{
|
.el-icon{
|
||||||
vertical-align:middle;font-weight:bold;
|
vertical-align:middle;font-weight:bold;
|
||||||
&.yellow{color:#e68906}
|
|
||||||
&.loading{
|
&.loading{
|
||||||
animation:loading 1s linear infinite;
|
animation:loading 1s linear infinite;
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="!scope.row.isSelf">
|
<template v-else>
|
||||||
<div>
|
<div>
|
||||||
<ul class="list sforward">
|
<ul class="list sforward">
|
||||||
<template v-if="sforward.list && sforward.list.length > 0">
|
<template v-if="sforward.list && sforward.list.length > 0">
|
||||||
@@ -48,7 +48,6 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>--</template>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
@@ -83,6 +82,5 @@ a{
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
}
|
}
|
||||||
span.green,a.green{color:green}
|
|
||||||
span.error{color:red}
|
span.error{color:red}
|
||||||
</style>
|
</style>
|
@@ -100,13 +100,13 @@
|
|||||||
import { 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,Delete} from '@element-plus/icons-vue'
|
||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { useForward } from './forward';
|
import { useForward } from './forward';
|
||||||
export default {
|
export default {
|
||||||
props: ['data','modelValue'],
|
props: ['data','modelValue'],
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
components:{WarnTriangleFilled},
|
components:{WarnTriangleFilled,Delete},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
|
@@ -5,15 +5,7 @@
|
|||||||
<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"></Forward>
|
<Forward @edit="_handleForwardEdit" @sedit="handleSForwardEdit"></Forward>
|
||||||
<el-table-column label="操作" width="54" fixed="right">
|
<Oper @refresh="handlePageRefresh"></Oper>
|
||||||
<template #default="scope">
|
|
||||||
<el-popconfirm v-if="scope.row.showDel" confirm-button-text="确认" cancel-button-text="取消" title="删除不可逆,是否确认?" @confirm="handleDel(scope.row.MachineId)">
|
|
||||||
<template #reference>
|
|
||||||
<el-button type="danger" size="small"><el-icon><Delete /></el-icon></el-button>
|
|
||||||
</template>
|
|
||||||
</el-popconfirm>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
</el-table>
|
||||||
<div class="page t-c">
|
<div class="page t-c">
|
||||||
<div class="page-wrap">
|
<div class="page-wrap">
|
||||||
@@ -36,6 +28,7 @@
|
|||||||
import { subWebsocketState } from '@/apis/request.js'
|
import { subWebsocketState } from '@/apis/request.js'
|
||||||
import { injectGlobalData } from '@/provide.js'
|
import { injectGlobalData } from '@/provide.js'
|
||||||
import { reactive, onMounted, onUnmounted, computed } from 'vue'
|
import { reactive, onMounted, onUnmounted, computed } from 'vue'
|
||||||
|
import Oper from './Oper.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'
|
||||||
@@ -57,7 +50,7 @@ import { provideSforward } from './sforward'
|
|||||||
import { provideDevices } from './devices'
|
import { provideDevices } from './devices'
|
||||||
import { provideUpdater } from './updater'
|
import { provideUpdater } from './updater'
|
||||||
export default {
|
export default {
|
||||||
components: {Device,DeviceEdit,Tunnel,TunnelEdit,ConnectionsEdit, Tuntap,TuntapEdit, Forward,ForwardEdit,ForwardCopy,SForwardEdit,SForwardCopy },
|
components: {Oper,Device,DeviceEdit,Tunnel,TunnelEdit,ConnectionsEdit, Tuntap,TuntapEdit, Forward,ForwardEdit,ForwardCopy,SForwardEdit,SForwardCopy },
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
@@ -164,8 +157,6 @@ export default {
|
|||||||
.home-list-wrap{
|
.home-list-wrap{
|
||||||
padding:1rem;
|
padding:1rem;
|
||||||
|
|
||||||
.green{color:green;}
|
|
||||||
|
|
||||||
.page{padding-top:1rem}
|
.page{padding-top:1rem}
|
||||||
.page-wrap{
|
.page-wrap{
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
|
86
linker.web/src/views/devices/Oper.vue
Normal file
86
linker.web/src/views/devices/Oper.vue
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<el-table-column label="操作" width="74" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-dropdown size="small">
|
||||||
|
<div class="dropdown">
|
||||||
|
<!-- <span class="badge">1</span> -->
|
||||||
|
<span>操作</span>
|
||||||
|
<el-icon class="el-icon--right">
|
||||||
|
<ArrowDown />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item v-if="scope.row.showReboot" @click="handleExit(scope.row.MachineId,scope.row.MachineName)"><el-icon><SwitchButton /></el-icon> 重启</el-dropdown-item>
|
||||||
|
<el-dropdown-item v-if="scope.row.showDel" @click="handleDel(scope.row.MachineId,scope.row.MachineName)"><el-icon><Delete /></el-icon> 删除</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { signInDel } from '@/apis/signin';
|
||||||
|
import { exit } from '@/apis/updater';
|
||||||
|
import { Delete,SwitchButton,ArrowDown } from '@element-plus/icons-vue'
|
||||||
|
import { ElMessageBox } from 'element-plus';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
emits:['refresh'],
|
||||||
|
components:{Delete,SwitchButton,ArrowDown},
|
||||||
|
setup (props,{emit}) {
|
||||||
|
|
||||||
|
const handleDel = (machineId,machineName)=>{
|
||||||
|
ElMessageBox.confirm(`确认删除[${machineName}]?`, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
}).then(() => {
|
||||||
|
signInDel(machineId).then(()=>{
|
||||||
|
emit('refresh');
|
||||||
|
});
|
||||||
|
}).catch(() => {});
|
||||||
|
}
|
||||||
|
const handleExit = (machineId,machineName)=>{
|
||||||
|
ElMessageBox.confirm(`确认关闭[${machineName}]?`, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
}).then(() => {
|
||||||
|
exit(machineId).then(()=>{
|
||||||
|
emit('refresh');
|
||||||
|
})
|
||||||
|
}).catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {handleDel,handleExit}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.dropdown{
|
||||||
|
border:1px solid #ddd;
|
||||||
|
padding:.4rem;
|
||||||
|
font-size:1.3rem;
|
||||||
|
border-radius:.4rem;
|
||||||
|
position:relative;
|
||||||
|
.el-icon{
|
||||||
|
vertical-align:middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge{
|
||||||
|
position:absolute;
|
||||||
|
right:-1rem;
|
||||||
|
top:-50%;
|
||||||
|
border-radius:10px;
|
||||||
|
background-color:#f1ae05;
|
||||||
|
color:#fff;
|
||||||
|
padding:.2rem .6rem;
|
||||||
|
font-size:1.2rem;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@@ -89,13 +89,13 @@
|
|||||||
import { 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,Delete} from '@element-plus/icons-vue'
|
||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { useSforward } from './sforward';
|
import { useSforward } from './sforward';
|
||||||
export default {
|
export default {
|
||||||
props: ['data','modelValue'],
|
props: ['data','modelValue'],
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
components:{WarnTriangleFilled},
|
components:{WarnTriangleFilled,Delete},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
|
@@ -2,17 +2,18 @@
|
|||||||
<el-table-column prop="tunnel" label="隧道" width="90">
|
<el-table-column prop="tunnel" label="隧道" width="90">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div v-if="tunnel.list[scope.row.MachineId]">
|
<div v-if="tunnel.list[scope.row.MachineId]">
|
||||||
<p>
|
<a href="javascript:;" class="a-line"
|
||||||
<a href="javascript:;" class="a-line" @click="handleTunnel(tunnel.list[scope.row.MachineId])">
|
:class="{yellow:tunnel.list[scope.row.MachineId].NeedReboot}"
|
||||||
|
:title="tunnel.list[scope.row.MachineId].NeedReboot?'需要重启':''"
|
||||||
|
@click="handleTunnel(tunnel.list[scope.row.MachineId])">
|
||||||
<span>网关 : {{tunnel.list[scope.row.MachineId].RouteLevel}} + {{tunnel.list[scope.row.MachineId].RouteLevelPlus}}</span>
|
<span>网关 : {{tunnel.list[scope.row.MachineId].RouteLevel}} + {{tunnel.list[scope.row.MachineId].RouteLevelPlus}}</span>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<div>
|
||||||
<a href="javascript:;" class="a-line" @click="handleConnections(scope.row.MachineId)">
|
<a href="javascript:;" class="a-line" @click="handleConnections(scope.row.MachineId)">
|
||||||
<span>连接数 : {{connectionCount(scope.row.MachineId)}}</span>
|
<span>连接数 : {{connectionCount(scope.row.MachineId)}}</span>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
@@ -54,6 +55,6 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.green{color:green;}
|
|
||||||
.el-switch.is-disabled{opacity :1;}
|
.el-switch.is-disabled{opacity :1;}
|
||||||
</style>
|
</style>
|
@@ -82,6 +82,5 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.green{color:green;}
|
|
||||||
.el-switch.is-disabled{opacity :1;}
|
.el-switch.is-disabled{opacity :1;}
|
||||||
</style>
|
</style>
|
@@ -9,7 +9,7 @@
|
|||||||
<template v-if="tuntap.list[scope.row.MachineId].Error">
|
<template v-if="tuntap.list[scope.row.MachineId].Error">
|
||||||
<el-popover placement="top" title="msg" width="20rem" trigger="hover" :content="tuntap.list[scope.row.MachineId].Error">
|
<el-popover placement="top" title="msg" width="20rem" trigger="hover" :content="tuntap.list[scope.row.MachineId].Error">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<strong class="error">{{ tuntap.list[scope.row.MachineId].IP }}</strong>
|
<strong class="red">{{ tuntap.list[scope.row.MachineId].IP }}</strong>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</template>
|
</template>
|
||||||
@@ -67,8 +67,6 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.green{color:green;}
|
|
||||||
.error{color:red;}
|
|
||||||
.el-switch.is-disabled{opacity :1;}
|
.el-switch.is-disabled{opacity :1;}
|
||||||
.el-input{
|
.el-input{
|
||||||
width:8rem;
|
width:8rem;
|
||||||
|
@@ -39,10 +39,11 @@ import { injectGlobalData } from '@/provide';
|
|||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { reactive, ref, watch } from 'vue';
|
import { reactive, ref, watch } from 'vue';
|
||||||
import { useTuntap } from './tuntap';
|
import { useTuntap } from './tuntap';
|
||||||
|
import { Delete, Plus } from '@element-plus/icons-vue'
|
||||||
export default {
|
export default {
|
||||||
props: ['modelValue'],
|
props: ['modelValue'],
|
||||||
emits: ['change','update:modelValue'],
|
emits: ['change','update:modelValue'],
|
||||||
|
components: {Delete,Plus},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
@@ -117,6 +118,5 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.green{color:green;}
|
|
||||||
.el-switch.is-disabled{opacity :1;}
|
.el-switch.is-disabled{opacity :1;}
|
||||||
</style>
|
</style>
|
@@ -25,6 +25,7 @@ export const provideDevices = () => {
|
|||||||
devices.page.Count = res.Count;
|
devices.page.Count = res.Count;
|
||||||
for (let j in res.List) {
|
for (let j in res.List) {
|
||||||
res.List[j].showDel = machineId.value != res.List[j].MachineId && res.List[j].Connected == false;
|
res.List[j].showDel = machineId.value != res.List[j].MachineId && res.List[j].Connected == false;
|
||||||
|
res.List[j].showReboot = res.List[j].Connected;
|
||||||
res.List[j].isSelf = machineId.value == res.List[j].MachineId;
|
res.List[j].isSelf = machineId.value == res.List[j].MachineId;
|
||||||
}
|
}
|
||||||
devices.page.List = res.List.sort((a, b) => b.Connected - a.Connected);
|
devices.page.List = res.List.sort((a, b) => b.Connected - a.Connected);
|
||||||
@@ -41,6 +42,7 @@ export const provideDevices = () => {
|
|||||||
item.LastSignIn = res.List[j].LastSignIn;
|
item.LastSignIn = res.List[j].LastSignIn;
|
||||||
item.Args = res.List[j].Args;
|
item.Args = res.List[j].Args;
|
||||||
item.showDel = machineId.value != res.List[j].MachineId && res.List[j].Connected == false;
|
item.showDel = machineId.value != res.List[j].MachineId && res.List[j].Connected == false;
|
||||||
|
item.showReboot = res.List[j].Connected;
|
||||||
item.isSelf = machineId.value == res.List[j].MachineId;
|
item.isSelf = machineId.value == res.List[j].MachineId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,18 +8,21 @@ export const provideUpdater = () => {
|
|||||||
const updater = ref({
|
const updater = ref({
|
||||||
timer: 0,
|
timer: 0,
|
||||||
list: {},
|
list: {},
|
||||||
current: { Version: '', Status: 0, Length: 0, Current: 0 }
|
current: { Version: '', Msg: [], DateTime: '', Status: 0, Length: 0, Current: 0 }
|
||||||
});
|
});
|
||||||
provide(updaterSymbol, updater);
|
provide(updaterSymbol, updater);
|
||||||
const _getUpdater = () => {
|
const _getUpdater = () => {
|
||||||
if (globalData.value.api.connected) {
|
if (globalData.value.api.connected) {
|
||||||
getUpdater().then((res) => {
|
getUpdater().then((res) => {
|
||||||
|
console.log(res);
|
||||||
const self = Object.values(res).filter(c => !!c.Version)[0];
|
const self = Object.values(res).filter(c => !!c.Version)[0];
|
||||||
if (self) {
|
if (self) {
|
||||||
|
updater.value.current.DateTime = self.DateTime;
|
||||||
updater.value.current.Version = self.Version;
|
updater.value.current.Version = self.Version;
|
||||||
updater.value.current.Status = self.Status;
|
updater.value.current.Status = self.Status;
|
||||||
updater.value.current.Length = self.Length;
|
updater.value.current.Length = self.Length;
|
||||||
updater.value.current.Current = self.Current;
|
updater.value.current.Current = self.Current;
|
||||||
|
updater.value.current.Msg = self.Msg;
|
||||||
}
|
}
|
||||||
updater.value.list = res;
|
updater.value.list = res;
|
||||||
updater.value.timer = setTimeout(_getUpdater, 800);
|
updater.value.timer = setTimeout(_getUpdater, 800);
|
||||||
|
@@ -45,11 +45,12 @@ 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';
|
import Version from './Version.vue';
|
||||||
|
import { Delete,Plus } from '@element-plus/icons-vue';
|
||||||
export default {
|
export default {
|
||||||
label:'打洞排除IP',
|
label:'打洞排除IP',
|
||||||
name:'excludeIP',
|
name:'excludeIP',
|
||||||
order:3,
|
order:3,
|
||||||
components:{Version},
|
components:{Version,Delete,Plus},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
|
@@ -83,11 +83,12 @@ 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';
|
import Version from './Version.vue';
|
||||||
|
import { Delete,Plus,Top,Bottom } from '@element-plus/icons-vue';
|
||||||
export default {
|
export default {
|
||||||
label:'中继服务器',
|
label:'中继服务器',
|
||||||
name:'relayServers',
|
name:'relayServers',
|
||||||
order:4,
|
order:4,
|
||||||
components:{Version},
|
components:{Version,Delete,Plus,Top,Bottom},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
|
@@ -52,11 +52,12 @@ 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';
|
import Version from './Version.vue';
|
||||||
|
import { Delete,Plus,Select } from '@element-plus/icons-vue';
|
||||||
export default {
|
export default {
|
||||||
label:'信标服务器',
|
label:'信标服务器',
|
||||||
name:'signInServers',
|
name:'signInServers',
|
||||||
order:0,
|
order:0,
|
||||||
components:{Version},
|
components:{Version,Delete,Plus,Select },
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
|
@@ -46,11 +46,12 @@ 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';
|
import Version from './Version.vue';
|
||||||
|
import { Delete,Plus,Top,Bottom } from '@element-plus/icons-vue';
|
||||||
export default {
|
export default {
|
||||||
label:'打洞协议',
|
label:'打洞协议',
|
||||||
name:'transports',
|
name:'transports',
|
||||||
order:2,
|
order:2,
|
||||||
components:{Version},
|
components:{Version, Delete,Plus,Top,Bottom},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
|
@@ -78,13 +78,14 @@
|
|||||||
import { setTunnelServers,getTunnelTypes } from '@/apis/tunnel';
|
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, onMounted, reactive } from 'vue'
|
||||||
import Version from './Version.vue';
|
import Version from './Version.vue';
|
||||||
|
import { Delete,Plus,Top,Bottom } from '@element-plus/icons-vue';
|
||||||
export default {
|
export default {
|
||||||
label:'端口服务器',
|
label:'端口服务器',
|
||||||
name:'tunnelServers',
|
name:'tunnelServers',
|
||||||
order:1,
|
order:1,
|
||||||
components:{Version},
|
components:{Version,Delete,Plus,Top,Bottom},
|
||||||
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);
|
||||||
|
@@ -25,8 +25,8 @@
|
|||||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||||
<PackageReleaseNotes>linker</PackageReleaseNotes>
|
<PackageReleaseNotes>linker</PackageReleaseNotes>
|
||||||
<AssemblyVersion>1.1.2.2</AssemblyVersion>
|
<AssemblyVersion>1.1.2.3</AssemblyVersion>
|
||||||
<FileVersion>1.1.2.2</FileVersion>
|
<FileVersion>1.1.2.3</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using linker.client.capi;
|
using linker.config;
|
||||||
using linker.config;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using linker.client.capi;
|
using linker.config;
|
||||||
using linker.config;
|
|
||||||
using linker.startup;
|
using linker.startup;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace linker.client.capi
|
namespace linker.plugins.capi
|
||||||
{
|
{
|
||||||
public interface IApiClientController : IApiController
|
public interface IApiClientController : IApiController
|
||||||
{
|
{
|
@@ -1,7 +1,7 @@
|
|||||||
using linker.server;
|
using linker.plugins.messenger;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace linker.client
|
namespace linker.plugins.client
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 登入对象
|
/// 登入对象
|
@@ -1,15 +1,16 @@
|
|||||||
using linker.client.args;
|
using linker.client.config;
|
||||||
using linker.client.config;
|
|
||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.plugins.signin.messenger;
|
using linker.plugins.signin.messenger;
|
||||||
using linker.server;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using linker.plugins.client.args;
|
||||||
|
using linker.plugins.server;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.client
|
namespace linker.plugins.client
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 登入
|
/// 登入
|
||||||
@@ -19,20 +20,20 @@ namespace linker.client
|
|||||||
private readonly ClientSignInState clientSignInState;
|
private readonly ClientSignInState clientSignInState;
|
||||||
private readonly RunningConfig runningConfig;
|
private readonly RunningConfig runningConfig;
|
||||||
private readonly FileConfig config;
|
private readonly FileConfig config;
|
||||||
private readonly TcpServer tcpServer;
|
|
||||||
private readonly MessengerSender messengerSender;
|
private readonly MessengerSender messengerSender;
|
||||||
|
private readonly MessengerResolver messengerResolver;
|
||||||
private readonly SignInArgsTransfer signInArgsTransfer;
|
private readonly SignInArgsTransfer signInArgsTransfer;
|
||||||
private readonly RunningConfigTransfer runningConfigTransfer;
|
private readonly RunningConfigTransfer runningConfigTransfer;
|
||||||
|
|
||||||
private string configKey = "signServers";
|
private string configKey = "signServers";
|
||||||
|
|
||||||
public ClientSignInTransfer(ClientSignInState clientSignInState, RunningConfig runningConfig, FileConfig config, TcpServer tcpServer, MessengerSender messengerSender, SignInArgsTransfer signInArgsTransfer, RunningConfigTransfer runningConfigTransfer)
|
public ClientSignInTransfer(ClientSignInState clientSignInState, RunningConfig runningConfig, FileConfig config, MessengerSender messengerSender, MessengerResolver messengerResolver, SignInArgsTransfer signInArgsTransfer, RunningConfigTransfer runningConfigTransfer)
|
||||||
{
|
{
|
||||||
this.clientSignInState = clientSignInState;
|
this.clientSignInState = clientSignInState;
|
||||||
this.runningConfig = runningConfig;
|
this.runningConfig = runningConfig;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.tcpServer = tcpServer;
|
|
||||||
this.messengerSender = messengerSender;
|
this.messengerSender = messengerSender;
|
||||||
|
this.messengerResolver = messengerResolver;
|
||||||
this.signInArgsTransfer = signInArgsTransfer;
|
this.signInArgsTransfer = signInArgsTransfer;
|
||||||
this.runningConfigTransfer = runningConfigTransfer;
|
this.runningConfigTransfer = runningConfigTransfer;
|
||||||
|
|
||||||
@@ -131,7 +132,7 @@ namespace linker.client
|
|||||||
Socket socket = new Socket(remote.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
Socket socket = new Socket(remote.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
socket.KeepAlive();
|
socket.KeepAlive();
|
||||||
await socket.ConnectAsync(remote).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
|
await socket.ConnectAsync(remote).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
|
||||||
clientSignInState.Connection = await tcpServer.BeginReceive(socket).ConfigureAwait(false);
|
clientSignInState.Connection = await messengerResolver.BeginReceiveClient(socket).ConfigureAwait(false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -169,6 +170,16 @@ namespace linker.client
|
|||||||
clientSignInState.Connection?.Disponse(6);
|
clientSignInState.Connection?.Disponse(6);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 登出
|
||||||
|
/// </summary>
|
||||||
|
public void SignOut()
|
||||||
|
{
|
||||||
|
if (clientSignInState.Connected)
|
||||||
|
clientSignInState.Connection.Disponse(5);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取服务器版本
|
/// 获取服务器版本
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -189,14 +200,7 @@ namespace linker.client
|
|||||||
clientSignInState.Version = "v1.0.0.0";
|
clientSignInState.Version = "v1.0.0.0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
|
||||||
/// 登出
|
|
||||||
/// </summary>
|
|
||||||
public void SignOut()
|
|
||||||
{
|
|
||||||
if (clientSignInState.Connected)
|
|
||||||
clientSignInState.Connection.Disponse(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 修改客户端名称
|
/// 修改客户端名称
|
@@ -2,12 +2,10 @@
|
|||||||
using linker.startup;
|
using linker.startup;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using linker.client.args;
|
|
||||||
using linker.client.config;
|
|
||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.client.config.messenger;
|
using linker.plugins.client.args;
|
||||||
|
|
||||||
namespace linker.client
|
namespace linker.plugins.client
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 客户端插件
|
/// 客户端插件
|
||||||
@@ -17,16 +15,11 @@ namespace linker.client
|
|||||||
public StartupLevel Level => StartupLevel.Bottom;
|
public StartupLevel Level => StartupLevel.Bottom;
|
||||||
public string Name => "client";
|
public string Name => "client";
|
||||||
public bool Required => true;
|
public bool Required => true;
|
||||||
public string[] Dependent => new string[] { "firewall", "signin", "serialize" };
|
public string[] Dependent => new string[] { "messenger", "firewall", "signin", "serialize", "config" };
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
||||||
{
|
{
|
||||||
serviceCollection.AddSingleton<RunningConfig>();
|
|
||||||
serviceCollection.AddSingleton<RunningConfigTransfer>();
|
|
||||||
serviceCollection.AddSingleton<ConfigClientMessenger>();
|
|
||||||
serviceCollection.AddSingleton<RunningConfigApiController>();
|
|
||||||
|
|
||||||
serviceCollection.AddSingleton<SignInArgsTransfer>();
|
serviceCollection.AddSingleton<SignInArgsTransfer>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ClientSignInState>();
|
serviceCollection.AddSingleton<ClientSignInState>();
|
||||||
@@ -46,7 +39,7 @@ namespace linker.client
|
|||||||
|
|
||||||
public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
||||||
{
|
{
|
||||||
serviceCollection.AddSingleton<ConfigServerMessenger>();
|
|
||||||
}
|
}
|
||||||
public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
|
public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
|
||||||
{
|
{
|
@@ -1,4 +1,4 @@
|
|||||||
namespace linker.client.args
|
namespace linker.plugins.client.args
|
||||||
{
|
{
|
||||||
public interface ISignInArgs
|
public interface ISignInArgs
|
||||||
{
|
{
|
@@ -3,7 +3,7 @@ using linker.libs;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace linker.client.args
|
namespace linker.plugins.client.args
|
||||||
{
|
{
|
||||||
public sealed class SignInArgsTransfer
|
public sealed class SignInArgsTransfer
|
||||||
{
|
{
|
||||||
@@ -12,7 +12,7 @@ namespace linker.client.args
|
|||||||
public SignInArgsTransfer(ServiceProvider serviceProvider, FileConfig config)
|
public SignInArgsTransfer(ServiceProvider serviceProvider, FileConfig config)
|
||||||
{
|
{
|
||||||
var types = ReflectionHelper.GetInterfaceSchieves(typeof(ISignInArgs));
|
var types = ReflectionHelper.GetInterfaceSchieves(typeof(ISignInArgs));
|
||||||
startups = types.Select(c => serviceProvider.GetService(c) as ISignInArgs).Where(c=>c != null).ToList();
|
startups = types.Select(c => serviceProvider.GetService(c) as ISignInArgs).Where(c => c != null).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Invoke(Dictionary<string, string> args)
|
public void Invoke(Dictionary<string, string> args)
|
@@ -1,8 +1,8 @@
|
|||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using linker.client.capi;
|
|
||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
|
using linker.plugins.capi;
|
||||||
|
|
||||||
namespace linker.plugins.config
|
namespace linker.plugins.config
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
using linker.config;
|
using linker.client.config;
|
||||||
|
using linker.config;
|
||||||
|
using linker.plugins.config.messenger;
|
||||||
using linker.startup;
|
using linker.startup;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@@ -11,19 +13,26 @@ namespace linker.plugins.config
|
|||||||
|
|
||||||
public bool Required => true;
|
public bool Required => true;
|
||||||
|
|
||||||
public StartupLevel Level => StartupLevel.Normal;
|
public StartupLevel Level => StartupLevel.Normal;
|
||||||
|
|
||||||
public string[] Dependent => Array.Empty<string>();
|
public string[] Dependent => new string[] { "messenger", "signin", "serialize" };
|
||||||
|
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
||||||
{
|
{
|
||||||
serviceCollection.AddSingleton<ConfigClientApiController>();
|
serviceCollection.AddSingleton<ConfigClientApiController>();
|
||||||
|
|
||||||
|
serviceCollection.AddSingleton<ConfigClientMessenger>();
|
||||||
|
serviceCollection.AddSingleton<RunningConfigApiController>();
|
||||||
|
|
||||||
|
serviceCollection.AddSingleton<RunningConfig>();
|
||||||
|
serviceCollection.AddSingleton<RunningConfigTransfer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
||||||
{
|
{
|
||||||
|
serviceCollection.AddSingleton<ConfigServerMessenger>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
|
public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
using linker.client.capi;
|
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.client.config;
|
||||||
|
using linker.plugins.capi;
|
||||||
|
|
||||||
namespace linker.client.config
|
namespace linker.plugins.config
|
||||||
{
|
{
|
||||||
public sealed class RunningConfigApiController : IApiClientController
|
public sealed class RunningConfigApiController : IApiClientController
|
||||||
{
|
{
|
||||||
private readonly RunningConfigTransfer runningConfigTransfer;
|
private readonly RunningConfigTransfer runningConfigTransfer;
|
||||||
|
|
||||||
public RunningConfigApiController(RunningConfigTransfer runningConfigTransfer)
|
public RunningConfigApiController(RunningConfigTransfer runningConfigTransfer)
|
||||||
{
|
{
|
@@ -1,6 +1,7 @@
|
|||||||
using linker.client.config.messenger;
|
using linker.libs;
|
||||||
using linker.libs;
|
using linker.plugins.client;
|
||||||
using linker.server;
|
using linker.plugins.config.messenger;
|
||||||
|
using linker.plugins.messenger;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ namespace linker.client.config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Memory<byte> Data { get; set; }
|
public Memory<byte> Data { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置同步
|
/// 配置同步
|
||||||
/// </summary>
|
/// </summary>
|
@@ -1,8 +1,9 @@
|
|||||||
using linker.plugins.signin.messenger;
|
using linker.client.config;
|
||||||
using linker.server;
|
using linker.plugins.messenger;
|
||||||
|
using linker.plugins.signin.messenger;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
|
|
||||||
namespace linker.client.config.messenger
|
namespace linker.plugins.config.messenger
|
||||||
{
|
{
|
||||||
public sealed class ConfigServerMessenger : IMessenger
|
public sealed class ConfigServerMessenger : IMessenger
|
||||||
{
|
{
|
@@ -1,4 +1,4 @@
|
|||||||
namespace linker.client.config.messenger
|
namespace linker.plugins.config.messenger
|
||||||
{
|
{
|
||||||
public enum ConfigMessengerIds : ushort
|
public enum ConfigMessengerIds : ushort
|
||||||
{
|
{
|
@@ -1,6 +1,5 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using linker.client.capi;
|
|
||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
@@ -8,9 +7,10 @@ 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.plugins.forward.messenger;
|
||||||
using linker.server;
|
|
||||||
using linker.client;
|
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.capi;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.forward
|
namespace linker.plugins.forward
|
||||||
{
|
{
|
||||||
|
@@ -12,7 +12,7 @@ namespace linker.plugins.forward
|
|||||||
public StartupLevel Level => StartupLevel.Normal;
|
public StartupLevel Level => StartupLevel.Normal;
|
||||||
public string Name => "forward";
|
public string Name => "forward";
|
||||||
public bool Required => false;
|
public bool Required => false;
|
||||||
public string[] Dependent => new string[] { "relay", "tunnel" };
|
public string[] Dependent => new string[] { "messenger", "relay", "tunnel", "signin", "serialize", "config" };
|
||||||
|
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
using linker.client;
|
using linker.client.config;
|
||||||
using linker.client.config;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.plugins.client;
|
||||||
using linker.plugins.forward.messenger;
|
using linker.plugins.forward.messenger;
|
||||||
using linker.plugins.forward.proxy;
|
using linker.plugins.forward.proxy;
|
||||||
using linker.server;
|
using linker.plugins.messenger;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
|
using linker.plugins.messenger;
|
||||||
using linker.plugins.signin.messenger;
|
using linker.plugins.signin.messenger;
|
||||||
using linker.server;
|
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.client.capi;
|
using linker.plugins.capi;
|
||||||
|
|
||||||
namespace linker.plugins.logger
|
namespace linker.plugins.logger
|
||||||
{
|
{
|
||||||
|
@@ -6,7 +6,7 @@ using System.Net.Security;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace linker.server
|
namespace linker.plugins.messenger
|
||||||
{
|
{
|
||||||
public interface IConnectionReceiveCallback
|
public interface IConnectionReceiveCallback
|
||||||
{
|
{
|
||||||
@@ -405,7 +405,7 @@ namespace linker.server
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await callback.Receive(this, packet, this.userToken).ConfigureAwait(false);
|
await callback.Receive(this, packet, userToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -422,7 +422,7 @@ namespace linker.server
|
|||||||
if (Environment.TickCount64 - ticks > 3000)
|
if (Environment.TickCount64 - ticks > 3000)
|
||||||
{
|
{
|
||||||
pingStart = Environment.TickCount64;
|
pingStart = Environment.TickCount64;
|
||||||
await SendPingPong(pingBytes).ConfigureAwait(false);
|
await SendPingPong(pingBytes).ConfigureAwait(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
await Task.Delay(3000).ConfigureAwait(false);
|
await Task.Delay(3000).ConfigureAwait(false);
|
||||||
@@ -442,7 +442,7 @@ namespace linker.server
|
|||||||
data.Length.ToBytes(heartData);
|
data.Length.ToBytes(heartData);
|
||||||
data.AsMemory().CopyTo(heartData.AsMemory(4));
|
data.AsMemory().CopyTo(heartData.AsMemory(4));
|
||||||
|
|
||||||
await semaphoreSlim.WaitAsync().ConfigureAwait(false);
|
await semaphoreSlim.WaitAsync().ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (SourceStream != null)
|
if (SourceStream != null)
|
||||||
@@ -451,7 +451,7 @@ namespace linker.server
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await SourceSocket.SendAsync(heartData.AsMemory(0, length), cancellationTokenSource.Token).ConfigureAwait(false);
|
await SourceSocket.SendAsync(heartData.AsMemory(0, length), cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -481,7 +481,7 @@ namespace linker.server
|
|||||||
if (SourceStream != null)
|
if (SourceStream != null)
|
||||||
await SourceStream.WriteAsync(data, cancellationTokenSourceWrite.Token).ConfigureAwait(false);
|
await SourceStream.WriteAsync(data, cancellationTokenSourceWrite.Token).ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await SourceSocket.SendAsync(data, cancellationTokenSourceWrite.Token).ConfigureAwait(false);
|
await SourceSocket.SendAsync(data, cancellationTokenSourceWrite.Token).ConfigureAwait(false);
|
||||||
SendBytes += data.Length;
|
SendBytes += data.Length;
|
||||||
ticks = Environment.TickCount64;
|
ticks = Environment.TickCount64;
|
||||||
}
|
}
|
||||||
@@ -505,7 +505,7 @@ namespace linker.server
|
|||||||
}
|
}
|
||||||
public override async Task<bool> SendAsync(byte[] data, int length)
|
public override async Task<bool> SendAsync(byte[] data, int length)
|
||||||
{
|
{
|
||||||
return await SendAsync(data.AsMemory(0, length)).ConfigureAwait(false);
|
return await SendAsync(data.AsMemory(0, length)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task RelayAsync(byte bufferSize)
|
public override async Task RelayAsync(byte bufferSize)
|
||||||
@@ -529,7 +529,7 @@ namespace linker.server
|
|||||||
TryLimit(ref length);
|
TryLimit(ref length);
|
||||||
while (length > 0)
|
while (length > 0)
|
||||||
{
|
{
|
||||||
await Task.Delay(30).ConfigureAwait(false);
|
await Task.Delay(30).ConfigureAwait(false);
|
||||||
TryLimit(ref length);
|
TryLimit(ref length);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
namespace linker.server
|
namespace linker.plugins.messenger
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 消息接口
|
/// 消息接口
|
@@ -1,8 +1,15 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using System.Net.Security;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Buffers;
|
||||||
|
using linker.libs.extends;
|
||||||
|
|
||||||
namespace linker.server
|
namespace linker.plugins.messenger
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 消息处理总线
|
/// 消息处理总线
|
||||||
@@ -17,12 +24,135 @@ namespace linker.server
|
|||||||
private readonly MessengerSender messengerSender;
|
private readonly MessengerSender messengerSender;
|
||||||
private readonly ServiceProvider serviceProvider;
|
private readonly ServiceProvider serviceProvider;
|
||||||
|
|
||||||
|
private X509Certificate serverCertificate;
|
||||||
public MessengerResolver(MessengerSender messengerSender, ServiceProvider serviceProvider)
|
public MessengerResolver(MessengerSender messengerSender, ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
this.messengerSender = messengerSender;
|
this.messengerSender = messengerSender;
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Init(string certificate, string password)
|
||||||
|
{
|
||||||
|
string path = Path.GetFullPath(certificate);
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
serverCertificate = new X509Certificate(path, password);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Error($"file {path} not found");
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task BeginReceiveServer(Socket socket)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (socket == null || socket.RemoteEndPoint == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socket.KeepAlive();
|
||||||
|
|
||||||
|
if (await ReceiveType(socket).ConfigureAwait(false) == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkStream networkStream = new NetworkStream(socket, false);
|
||||||
|
SslStream sslStream = new SslStream(networkStream, true);
|
||||||
|
await sslStream.AuthenticateAsServerAsync(serverCertificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false);
|
||||||
|
IConnection connection = CreateConnection(sslStream, networkStream, socket, socket.LocalEndPoint as IPEndPoint, socket.RemoteEndPoint as IPEndPoint);
|
||||||
|
|
||||||
|
connection.BeginReceive(this, null, true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
|
LoggerHelper.Instance.Error(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task<IConnection> BeginReceiveClient(Socket socket)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (socket == null || socket.RemoteEndPoint == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
socket.KeepAlive();
|
||||||
|
await socket.SendAsync(new byte[] { 1 }).ConfigureAwait(false);
|
||||||
|
NetworkStream networkStream = new NetworkStream(socket, false);
|
||||||
|
SslStream sslStream = new SslStream(networkStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
|
||||||
|
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
|
||||||
|
{
|
||||||
|
AllowRenegotiation = true,
|
||||||
|
EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
IConnection connection = CreateConnection(sslStream, networkStream, socket, socket.LocalEndPoint as IPEndPoint, socket.RemoteEndPoint as IPEndPoint);
|
||||||
|
|
||||||
|
connection.BeginReceive(this, null, true);
|
||||||
|
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
|
LoggerHelper.Instance.Error(ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private IConnection CreateConnection(SslStream stream, NetworkStream networkStream, Socket socket, IPEndPoint local, IPEndPoint remote)
|
||||||
|
{
|
||||||
|
return new TcpConnection(stream, networkStream, socket, local, remote)
|
||||||
|
{
|
||||||
|
ReceiveRequestWrap = new MessageRequestWrap(),
|
||||||
|
ReceiveResponseWrap = new MessageResponseWrap()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public Memory<byte> BuildSendData(byte[] data, IPEndPoint ep)
|
||||||
|
{
|
||||||
|
//给客户端返回他的IP+端口
|
||||||
|
data[0] = (byte)ep.AddressFamily;
|
||||||
|
ep.Address.TryWriteBytes(data.AsSpan(1), out int length);
|
||||||
|
((ushort)ep.Port).ToBytes(data.AsMemory(1 + length));
|
||||||
|
|
||||||
|
//防止一些网关修改掉它的外网IP
|
||||||
|
for (int i = 0; i < 1 + length + 2; i++)
|
||||||
|
{
|
||||||
|
data[i] = (byte)(data[i] ^ byte.MaxValue);
|
||||||
|
}
|
||||||
|
return data.AsMemory(0, 1 + length + 2);
|
||||||
|
}
|
||||||
|
private async Task<byte> ReceiveType(Socket socket)
|
||||||
|
{
|
||||||
|
byte[] sendData = ArrayPool<byte>.Shared.Rent(20);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await socket.ReceiveAsync(sendData.AsMemory(0, 1), SocketFlags.None).ConfigureAwait(false);
|
||||||
|
byte type = sendData[0];
|
||||||
|
if (type == 0)
|
||||||
|
{
|
||||||
|
Memory<byte> memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint);
|
||||||
|
await socket.SendAsync(memory, SocketFlags.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ArrayPool<byte>.Shared.Return(sendData);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载所有消息处理器
|
/// 加载所有消息处理器
|
||||||
/// </summary>
|
/// </summary>
|
@@ -1,7 +1,7 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace linker.server
|
namespace linker.plugins.messenger
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 消息发送器
|
/// 消息发送器
|
@@ -1,34 +1,31 @@
|
|||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.startup;
|
using linker.startup;
|
||||||
using linker.libs;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace linker.server
|
namespace linker.plugins.messenger
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 服务端插件
|
/// 服务端插件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ServerStartup : IStartup
|
public sealed class MessengerStartup : IStartup
|
||||||
{
|
{
|
||||||
public StartupLevel Level => StartupLevel.Normal;
|
public StartupLevel Level => StartupLevel.Normal;
|
||||||
public string Name => "server";
|
public string Name => "messenger";
|
||||||
public bool Required => true;
|
public bool Required => true;
|
||||||
public string[] Dependent => new string[] { "serialize", "firewall", "signin" };
|
public string[] Dependent => new string[] { };
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
||||||
{
|
{
|
||||||
serviceCollection.AddSingleton<MessengerSender>();
|
serviceCollection.AddSingleton<MessengerSender>();
|
||||||
serviceCollection.AddSingleton<MessengerResolver>();
|
serviceCollection.AddSingleton<MessengerResolver>();
|
||||||
serviceCollection.AddSingleton<TcpServer>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
||||||
{
|
{
|
||||||
serviceCollection.AddSingleton<MessengerSender>();
|
serviceCollection.AddSingleton<MessengerSender>();
|
||||||
serviceCollection.AddSingleton<MessengerResolver>();
|
serviceCollection.AddSingleton<MessengerResolver>();
|
||||||
serviceCollection.AddSingleton<TcpServer>();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +37,7 @@ namespace linker.server
|
|||||||
{
|
{
|
||||||
MessengerResolver messengerResolver = serviceProvider.GetService<MessengerResolver>();
|
MessengerResolver messengerResolver = serviceProvider.GetService<MessengerResolver>();
|
||||||
messengerResolver.LoadMessenger(assemblies);
|
messengerResolver.LoadMessenger(assemblies);
|
||||||
|
messengerResolver.Init(config.Data.Server.Certificate, config.Data.Server.Password);
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,26 +48,9 @@ namespace linker.server
|
|||||||
{
|
{
|
||||||
MessengerResolver messengerResolver = serviceProvider.GetService<MessengerResolver>();
|
MessengerResolver messengerResolver = serviceProvider.GetService<MessengerResolver>();
|
||||||
messengerResolver.LoadMessenger(assemblies);
|
messengerResolver.LoadMessenger(assemblies);
|
||||||
|
messengerResolver.Init(config.Data.Server.Certificate, config.Data.Server.Password);
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoggerHelper.Instance.Info($"start server");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//服务
|
|
||||||
TcpServer tcpServer = serviceProvider.GetService<TcpServer>();
|
|
||||||
tcpServer.Init(config.Data.Server.Certificate, config.Data.Server.Password);
|
|
||||||
if(config.Data.Server.ServicePort > 0)
|
|
||||||
{
|
|
||||||
tcpServer.Start(config.Data.Server.ServicePort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LoggerHelper.Instance.Error(ex);
|
|
||||||
}
|
|
||||||
LoggerHelper.Instance.Info($"server listen:{config.Data.Server.ServicePort}");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -2,7 +2,7 @@
|
|||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace linker.server
|
namespace linker.plugins.messenger
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求数据包
|
/// 请求数据包
|
@@ -1,11 +1,11 @@
|
|||||||
using linker.client;
|
using linker.config;
|
||||||
using linker.client.capi;
|
|
||||||
using linker.config;
|
|
||||||
using linker.plugins.relay.messenger;
|
using linker.plugins.relay.messenger;
|
||||||
using linker.server;
|
|
||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.capi;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.relay
|
namespace linker.plugins.relay
|
||||||
{
|
{
|
||||||
|
@@ -17,7 +17,7 @@ namespace linker.plugins.relay
|
|||||||
|
|
||||||
public bool Required => false;
|
public bool Required => false;
|
||||||
|
|
||||||
public string[] Dependent => new string[] { };
|
public string[] Dependent => new string[] { "messenger", "signin", "serialize", "config" };
|
||||||
|
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ using System.Collections.Concurrent;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using linker.client;
|
using linker.plugins.client;
|
||||||
|
|
||||||
namespace linker.plugins.relay
|
namespace linker.plugins.relay
|
||||||
{
|
{
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.plugins.relay.transport;
|
using linker.plugins.relay.transport;
|
||||||
using linker.plugins.signin.messenger;
|
using linker.plugins.signin.messenger;
|
||||||
using linker.server;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using linker.plugins.server;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.relay.messenger
|
namespace linker.plugins.relay.messenger
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.plugins.relay.messenger;
|
using linker.plugins.relay.messenger;
|
||||||
using linker.server;
|
|
||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
@@ -11,6 +10,8 @@ using System.Net.Security;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Security.Authentication;
|
using System.Security.Authentication;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using linker.plugins.server;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.relay.transport
|
namespace linker.plugins.relay.transport
|
||||||
{
|
{
|
||||||
@@ -20,15 +21,15 @@ namespace linker.plugins.relay.transport
|
|||||||
public RelayType Type => RelayType.Linker;
|
public RelayType Type => RelayType.Linker;
|
||||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
||||||
|
|
||||||
private readonly TcpServer tcpServer;
|
private readonly MessengerResolver messengerResolver;
|
||||||
private readonly MessengerSender messengerSender;
|
private readonly MessengerSender messengerSender;
|
||||||
|
|
||||||
private X509Certificate2 certificate;
|
private X509Certificate2 certificate;
|
||||||
|
|
||||||
|
|
||||||
public TransportSelfHost(TcpServer tcpServer, MessengerSender messengerSender, FileConfig config)
|
public TransportSelfHost(MessengerResolver messengerResolver, MessengerSender messengerSender, FileConfig config)
|
||||||
{
|
{
|
||||||
this.tcpServer = tcpServer;
|
this.messengerResolver = messengerResolver;
|
||||||
this.messengerSender = messengerSender;
|
this.messengerSender = messengerSender;
|
||||||
|
|
||||||
string path = Path.GetFullPath(config.Data.Client.Certificate);
|
string path = Path.GetFullPath(config.Data.Client.Certificate);
|
||||||
@@ -46,7 +47,7 @@ namespace linker.plugins.relay.transport
|
|||||||
socket.KeepAlive();
|
socket.KeepAlive();
|
||||||
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
|
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
|
||||||
|
|
||||||
IConnection connection = await tcpServer.BeginReceive(socket);
|
IConnection connection = await messengerResolver.BeginReceiveClient(socket);
|
||||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = connection,
|
Connection = connection,
|
||||||
@@ -114,7 +115,7 @@ namespace linker.plugins.relay.transport
|
|||||||
socket.KeepAlive();
|
socket.KeepAlive();
|
||||||
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
|
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
|
||||||
|
|
||||||
IConnection connection = await tcpServer.BeginReceive(socket);
|
IConnection connection = await messengerResolver.BeginReceiveClient(socket);
|
||||||
await messengerSender.SendOnly(new MessageRequestWrap
|
await messengerSender.SendOnly(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = connection,
|
Connection = connection,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
namespace linker.serializes
|
namespace linker.plugins.serializes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MemoryPack 的 IPAddress序列化扩展
|
/// MemoryPack 的 IPAddress序列化扩展
|
||||||
@@ -25,7 +25,7 @@ namespace linker.serializes
|
|||||||
span[0] = (byte)bytesWritten;
|
span[0] = (byte)bytesWritten;
|
||||||
|
|
||||||
writer.WriteCollectionHeader(bytesWritten + 4);
|
writer.WriteCollectionHeader(bytesWritten + 4);
|
||||||
writer.WriteSpan(span.Slice(0, bytesWritten+1));
|
writer.WriteSpan(span.Slice(0, bytesWritten + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Deserialize(ref MemoryPackReader reader, scoped ref IPAddress value)
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref IPAddress value)
|
@@ -2,7 +2,7 @@
|
|||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
namespace linker.serializes
|
namespace linker.plugins.serializes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MemoryPack 的 IPEndPoint序列化扩展
|
/// MemoryPack 的 IPEndPoint序列化扩展
|
@@ -4,7 +4,7 @@ using MemoryPack;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace linker.serializes
|
namespace linker.plugins.serializes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MemoryPack 序列化扩展加载插件
|
/// MemoryPack 序列化扩展加载插件
|
53
linker/plugins/server/ServerStartup.cs
Normal file
53
linker/plugins/server/ServerStartup.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using linker.config;
|
||||||
|
using linker.startup;
|
||||||
|
using linker.libs;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace linker.plugins.server
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 服务端插件
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ServerStartup : IStartup
|
||||||
|
{
|
||||||
|
public StartupLevel Level => StartupLevel.Normal;
|
||||||
|
public string Name => "server";
|
||||||
|
public bool Required => true;
|
||||||
|
public string[] Dependent => new string[] {"messenger", "serialize", "firewall", "signin", "config" };
|
||||||
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
|
public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddServer(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
|
||||||
|
{
|
||||||
|
serviceCollection.AddSingleton<TcpServer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UseClient(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UseServer(ServiceProvider serviceProvider, FileConfig config, Assembly[] assemblies)
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Info($"start server");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//服务
|
||||||
|
TcpServer tcpServer = serviceProvider.GetService<TcpServer>();
|
||||||
|
if (config.Data.Server.ServicePort > 0)
|
||||||
|
{
|
||||||
|
tcpServer.Start(config.Data.Server.ServicePort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Error(ex);
|
||||||
|
}
|
||||||
|
LoggerHelper.Instance.Info($"server listen:{config.Data.Server.ServicePort}");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
127
linker/plugins/server/TcpServer.cs
Normal file
127
linker/plugins/server/TcpServer.cs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
using linker.libs.extends;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace linker.plugins.server
|
||||||
|
{
|
||||||
|
public sealed class TcpServer
|
||||||
|
{
|
||||||
|
private Socket socket;
|
||||||
|
private Socket socketUdp;
|
||||||
|
private CancellationTokenSource cancellationTokenSource;
|
||||||
|
private readonly MessengerResolver messengerResolver;
|
||||||
|
|
||||||
|
public TcpServer(MessengerResolver messengerResolver)
|
||||||
|
{
|
||||||
|
this.messengerResolver = messengerResolver;
|
||||||
|
cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start(int port)
|
||||||
|
{
|
||||||
|
if (socket == null)
|
||||||
|
{
|
||||||
|
socket = BindAccept(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task BindUdp(int port)
|
||||||
|
{
|
||||||
|
socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||||
|
socketUdp.Bind(new IPEndPoint(IPAddress.Any, port));
|
||||||
|
socketUdp.WindowsUdpBug();
|
||||||
|
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
byte[] sendData = new byte[20];
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SocketReceiveFromResult result = await socketUdp.ReceiveFromAsync(buffer, SocketFlags.None, endPoint).ConfigureAwait(false);
|
||||||
|
IPEndPoint ep = result.RemoteEndPoint as IPEndPoint;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Memory<byte> memory = messengerResolver.BuildSendData(sendData, ep);
|
||||||
|
|
||||||
|
await socketUdp.SendToAsync(memory, ep).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Socket BindAccept(int port)
|
||||||
|
{
|
||||||
|
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
|
||||||
|
Socket socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
socket.IPv6Only(localEndPoint.AddressFamily, false);
|
||||||
|
socket.ReuseBind(localEndPoint);
|
||||||
|
socket.Listen(int.MaxValue);
|
||||||
|
|
||||||
|
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs
|
||||||
|
{
|
||||||
|
UserToken = socket,
|
||||||
|
SocketFlags = SocketFlags.None,
|
||||||
|
};
|
||||||
|
acceptEventArg.Completed += IO_Completed;
|
||||||
|
StartAccept(acceptEventArg);
|
||||||
|
|
||||||
|
_ = BindUdp(port);
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
|
||||||
|
{
|
||||||
|
acceptEventArg.AcceptSocket = null;
|
||||||
|
Socket token = (Socket)acceptEventArg.UserToken;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (token.AcceptAsync(acceptEventArg) == false)
|
||||||
|
{
|
||||||
|
ProcessAccept(acceptEventArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
token?.SafeClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void IO_Completed(object sender, SocketAsyncEventArgs e)
|
||||||
|
{
|
||||||
|
switch (e.LastOperation)
|
||||||
|
{
|
||||||
|
case SocketAsyncOperation.Accept:
|
||||||
|
ProcessAccept(e);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void ProcessAccept(SocketAsyncEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.AcceptSocket != null)
|
||||||
|
{
|
||||||
|
_ = messengerResolver.BeginReceiveServer(e.AcceptSocket);
|
||||||
|
StartAccept(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
cancellationTokenSource?.Cancel();
|
||||||
|
socket?.SafeClose();
|
||||||
|
socket = null;
|
||||||
|
}
|
||||||
|
public void Disponse()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,11 +1,11 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using linker.client.capi;
|
|
||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
using linker.client;
|
|
||||||
using linker.server;
|
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using linker.plugins.sforward.messenger;
|
using linker.plugins.sforward.messenger;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.capi;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.sforward
|
namespace linker.plugins.sforward
|
||||||
{
|
{
|
||||||
|
@@ -18,7 +18,7 @@ namespace linker.plugins.sforward
|
|||||||
|
|
||||||
public StartupLevel Level => StartupLevel.Normal;
|
public StartupLevel Level => StartupLevel.Normal;
|
||||||
|
|
||||||
public string[] Dependent => Array.Empty<string>();
|
public string[] Dependent => new string[] { "messenger", "signin", "serialize", "config" };
|
||||||
|
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
using linker.client;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.server;
|
|
||||||
using linker.plugins.sforward.messenger;
|
using linker.plugins.sforward.messenger;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using linker.plugins.sforward.config;
|
using linker.plugins.sforward.config;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.sforward
|
namespace linker.plugins.sforward
|
||||||
{
|
{
|
||||||
|
@@ -2,13 +2,13 @@
|
|||||||
using linker.plugins.sforward.config;
|
using linker.plugins.sforward.config;
|
||||||
using linker.plugins.sforward.validator;
|
using linker.plugins.sforward.validator;
|
||||||
using linker.plugins.signin.messenger;
|
using linker.plugins.signin.messenger;
|
||||||
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 LiteDB;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using linker.plugins.forward.messenger;
|
using linker.plugins.forward.messenger;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.sforward.messenger
|
namespace linker.plugins.sforward.messenger
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
using linker.plugins.sforward.config;
|
using linker.plugins.messenger;
|
||||||
using linker.server;
|
using linker.plugins.sforward.config;
|
||||||
|
|
||||||
namespace linker.plugins.sforward.validator
|
namespace linker.plugins.sforward.validator
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using linker.config;
|
using linker.config;
|
||||||
|
using linker.plugins.messenger;
|
||||||
using linker.plugins.sforward.config;
|
using linker.plugins.sforward.config;
|
||||||
using linker.server;
|
|
||||||
|
|
||||||
namespace linker.plugins.sforward.validator
|
namespace linker.plugins.sforward.validator
|
||||||
{
|
{
|
||||||
|
@@ -2,10 +2,10 @@
|
|||||||
using linker.plugins.signin.messenger;
|
using linker.plugins.signin.messenger;
|
||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using linker.client;
|
|
||||||
using linker.server;
|
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using linker.client.capi;
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.capi;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.signin
|
namespace linker.plugins.signin
|
||||||
{
|
{
|
||||||
|
@@ -13,7 +13,7 @@ namespace linker.plugins.signin
|
|||||||
|
|
||||||
public bool Required => false;
|
public bool Required => false;
|
||||||
|
|
||||||
public string[] Dependent => new string[] { };
|
public string[] Dependent => new string[] { "messenger", };
|
||||||
|
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
using linker.store;
|
using linker.store;
|
||||||
using linker.server;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.signin.messenger
|
namespace linker.plugins.signin.messenger
|
||||||
{
|
{
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
using linker.client;
|
using linker.config;
|
||||||
using linker.config;
|
|
||||||
using linker.server;
|
|
||||||
using linker.libs;
|
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.server;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.signin.messenger
|
namespace linker.plugins.signin.messenger
|
||||||
{
|
{
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
using linker.client;
|
using linker.client.config;
|
||||||
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.tunnel.adapter;
|
using linker.tunnel.adapter;
|
||||||
using linker.tunnel.transport;
|
using linker.tunnel.transport;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
@@ -11,6 +9,8 @@ using System.Net;
|
|||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using linker.tunnel.wanport;
|
using linker.tunnel.wanport;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.tunnel
|
namespace linker.plugins.tunnel
|
||||||
{
|
{
|
||||||
|
@@ -1,8 +1,5 @@
|
|||||||
using linker.client;
|
using linker.config;
|
||||||
using linker.client.capi;
|
|
||||||
using linker.config;
|
|
||||||
using linker.plugins.tunnel.messenger;
|
using linker.plugins.tunnel.messenger;
|
||||||
using linker.server;
|
|
||||||
using linker.tunnel.adapter;
|
using linker.tunnel.adapter;
|
||||||
using linker.tunnel.transport;
|
using linker.tunnel.transport;
|
||||||
using linker.libs.api;
|
using linker.libs.api;
|
||||||
@@ -11,6 +8,10 @@ using MemoryPack;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using linker.tunnel.wanport;
|
using linker.tunnel.wanport;
|
||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.server;
|
||||||
|
using linker.plugins.capi;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.tunnel
|
namespace linker.plugins.tunnel
|
||||||
{
|
{
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
using linker.client;
|
using linker.client.config;
|
||||||
using linker.client.config;
|
|
||||||
using linker.config;
|
using linker.config;
|
||||||
|
using linker.libs;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.messenger;
|
||||||
using linker.plugins.tunnel.messenger;
|
using linker.plugins.tunnel.messenger;
|
||||||
using linker.server;
|
|
||||||
using linker.tunnel.adapter;
|
using linker.tunnel.adapter;
|
||||||
using linker.tunnel.wanport;
|
using linker.tunnel.wanport;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Net.Quic;
|
||||||
|
|
||||||
namespace linker.plugins.tunnel
|
namespace linker.plugins.tunnel
|
||||||
{
|
{
|
||||||
@@ -35,20 +37,14 @@ namespace linker.plugins.tunnel
|
|||||||
this.runningConfigTransfer = runningConfigTransfer;
|
this.runningConfigTransfer = runningConfigTransfer;
|
||||||
this.tunnelAdapter = tunnelAdapter;
|
this.tunnelAdapter = tunnelAdapter;
|
||||||
|
|
||||||
clientSignInState.NetworkEnabledHandle += (times) =>
|
|
||||||
{
|
InitRouteLevel();
|
||||||
GetRemoveRouteLevel();
|
InitExcludeIP();
|
||||||
};
|
|
||||||
clientSignInState.NetworkFirstEnabledHandle += () =>
|
|
||||||
{
|
|
||||||
SyncExcludeIP();
|
|
||||||
};
|
|
||||||
InitConfig();
|
InitConfig();
|
||||||
|
|
||||||
runningConfigTransfer.Setter(exipConfigKey, SettExcludeIPs);
|
TestQuic();
|
||||||
runningConfigTransfer.Getter(exipConfigKey, () => MemoryPackSerializer.Serialize(GetExcludeIPs()));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitConfig()
|
private void InitConfig()
|
||||||
{
|
{
|
||||||
bool updateVersion = false;
|
bool updateVersion = false;
|
||||||
@@ -85,7 +81,7 @@ namespace linker.plugins.tunnel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RefreshConfig()
|
public void RefreshConfig()
|
||||||
{
|
{
|
||||||
GetRemoveRouteLevel();
|
GetRemoteRouteLevel();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 修改自己的网关层级信息
|
/// 修改自己的网关层级信息
|
||||||
@@ -95,7 +91,7 @@ namespace linker.plugins.tunnel
|
|||||||
{
|
{
|
||||||
running.Data.Tunnel.RouteLevelPlus = tunnelTransportFileConfigInfo.RouteLevelPlus;
|
running.Data.Tunnel.RouteLevelPlus = tunnelTransportFileConfigInfo.RouteLevelPlus;
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
GetRemoveRouteLevel();
|
GetRemoteRouteLevel();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 收到别人发给我的修改我的信息
|
/// 收到别人发给我的修改我的信息
|
||||||
@@ -108,7 +104,7 @@ namespace linker.plugins.tunnel
|
|||||||
Interlocked.Increment(ref version);
|
Interlocked.Increment(ref version);
|
||||||
return GetLocalRouteLevel();
|
return GetLocalRouteLevel();
|
||||||
}
|
}
|
||||||
private void GetRemoveRouteLevel()
|
private void GetRemoteRouteLevel()
|
||||||
{
|
{
|
||||||
TunnelTransportRouteLevelInfo config = GetLocalRouteLevel();
|
TunnelTransportRouteLevelInfo config = GetLocalRouteLevel();
|
||||||
messengerSender.SendReply(new MessageRequestWrap
|
messengerSender.SendReply(new MessageRequestWrap
|
||||||
@@ -138,11 +134,28 @@ namespace linker.plugins.tunnel
|
|||||||
{
|
{
|
||||||
MachineId = config.Data.Client.Id,
|
MachineId = config.Data.Client.Id,
|
||||||
RouteLevel = config.Data.Client.Tunnel.RouteLevel,
|
RouteLevel = config.Data.Client.Tunnel.RouteLevel,
|
||||||
RouteLevelPlus = running.Data.Tunnel.RouteLevelPlus
|
RouteLevelPlus = running.Data.Tunnel.RouteLevelPlus,
|
||||||
|
NeedReboot = reboot
|
||||||
|
};
|
||||||
|
}
|
||||||
|
private void InitRouteLevel()
|
||||||
|
{
|
||||||
|
clientSignInState.NetworkEnabledHandle += (times) =>
|
||||||
|
{
|
||||||
|
GetRemoteRouteLevel();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void InitExcludeIP()
|
||||||
|
{
|
||||||
|
clientSignInState.NetworkFirstEnabledHandle += () =>
|
||||||
|
{
|
||||||
|
SyncExcludeIP();
|
||||||
|
};
|
||||||
|
runningConfigTransfer.Setter(exipConfigKey, SettExcludeIPs);
|
||||||
|
runningConfigTransfer.Getter(exipConfigKey, () => MemoryPackSerializer.Serialize(GetExcludeIPs()));
|
||||||
|
}
|
||||||
private void SyncExcludeIP()
|
private void SyncExcludeIP()
|
||||||
{
|
{
|
||||||
runningConfigTransfer.Sync(exipConfigKey, MemoryPackSerializer.Serialize(running.Data.Tunnel.ExcludeIPs));
|
runningConfigTransfer.Sync(exipConfigKey, MemoryPackSerializer.Serialize(running.Data.Tunnel.ExcludeIPs));
|
||||||
@@ -163,5 +176,36 @@ namespace linker.plugins.tunnel
|
|||||||
running.Data.Tunnel.ExcludeIPs = MemoryPackSerializer.Deserialize<ExcludeIPItem[]>(data.Span);
|
running.Data.Tunnel.ExcludeIPs = MemoryPackSerializer.Deserialize<ExcludeIPItem[]>(data.Span);
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool reboot = false;
|
||||||
|
private void TestQuic()
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
if (QuicListener.IsSupported == false)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists("msquic-openssl.dll"))
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Warning($"copy msquic-openssl.dll -> msquic.dll,please restart linker");
|
||||||
|
File.Move("msquic.dll", "msquic.dll.temp", true);
|
||||||
|
File.Move("msquic-openssl.dll", "msquic.dll", true);
|
||||||
|
|
||||||
|
reboot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists("msquic.dll.temp"))
|
||||||
|
{
|
||||||
|
File.Delete("msquic.dll.temp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,7 @@ namespace linker.plugins.tunnel
|
|||||||
|
|
||||||
public bool Required => false;
|
public bool Required => false;
|
||||||
|
|
||||||
public string[] Dependent => new string[] { };
|
public string[] Dependent => new string[] { "messenger", "signin", "serialize", "config" };
|
||||||
|
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
|
@@ -72,6 +72,8 @@ namespace linker.config
|
|||||||
public string MachineId { get; set; }
|
public string MachineId { get; set; }
|
||||||
public int RouteLevel { get; set; } = 0;
|
public int RouteLevel { get; set; } = 0;
|
||||||
public int RouteLevelPlus { get; set; } = 0;
|
public int RouteLevelPlus { get; set; } = 0;
|
||||||
|
|
||||||
|
public bool NeedReboot { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.plugins.signin.messenger;
|
using linker.plugins.signin.messenger;
|
||||||
using linker.server;
|
|
||||||
using linker.tunnel;
|
using linker.tunnel;
|
||||||
using linker.tunnel.adapter;
|
using linker.tunnel.adapter;
|
||||||
using linker.tunnel.transport;
|
using linker.tunnel.transport;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.tunnel.messenger
|
namespace linker.plugins.tunnel.messenger
|
||||||
{
|
{
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
using linker.server;
|
using linker.libs.api;
|
||||||
using linker.libs.api;
|
|
||||||
using linker.plugins.tuntap.vea;
|
using linker.plugins.tuntap.vea;
|
||||||
using linker.client;
|
|
||||||
using linker.plugins.tuntap.messenger;
|
using linker.plugins.tuntap.messenger;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using linker.client.capi;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.plugins.forward.proxy;
|
|
||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
using linker.plugins.tuntap.proxy;
|
using linker.plugins.tuntap.proxy;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.server;
|
||||||
|
using linker.plugins.capi;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.tuntap
|
namespace linker.plugins.tuntap
|
||||||
{
|
{
|
||||||
|
@@ -16,7 +16,7 @@ namespace linker.plugins.tuntap
|
|||||||
public StartupLevel Level => StartupLevel.Normal;
|
public StartupLevel Level => StartupLevel.Normal;
|
||||||
public string Name => "tuntap";
|
public string Name => "tuntap";
|
||||||
public bool Required => false;
|
public bool Required => false;
|
||||||
public string[] Dependent => new string[] { "relay", "tunnel" };
|
public string[] Dependent => new string[] {"messenger", "relay", "tunnel", "signin", "serialize", "config" };
|
||||||
|
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
using linker.client;
|
using linker.client.config;
|
||||||
using linker.client.config;
|
|
||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.plugins.tuntap.messenger;
|
using linker.plugins.tuntap.messenger;
|
||||||
using linker.plugins.tuntap.proxy;
|
using linker.plugins.tuntap.proxy;
|
||||||
using linker.plugins.tuntap.vea;
|
using linker.plugins.tuntap.vea;
|
||||||
using linker.server;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
@@ -13,6 +11,8 @@ using System.Net;
|
|||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.tuntap
|
namespace linker.plugins.tuntap
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using linker.plugins.signin.messenger;
|
using linker.plugins.messenger;
|
||||||
|
using linker.plugins.signin.messenger;
|
||||||
using linker.plugins.tuntap.vea;
|
using linker.plugins.tuntap.vea;
|
||||||
using linker.server;
|
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
|
|
||||||
namespace linker.plugins.tuntap.messenger
|
namespace linker.plugins.tuntap.messenger
|
||||||
|
@@ -1,7 +1,4 @@
|
|||||||
using linker.server;
|
using linker.libs.api;
|
||||||
using linker.libs.api;
|
|
||||||
using linker.client;
|
|
||||||
using linker.client.capi;
|
|
||||||
using linker.config;
|
using linker.config;
|
||||||
using linker.plugins.updater.messenger;
|
using linker.plugins.updater.messenger;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
@@ -9,6 +6,9 @@ using System.Collections.Concurrent;
|
|||||||
using linker.plugins.updater.config;
|
using linker.plugins.updater.config;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using linker.client.config;
|
using linker.client.config;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.capi;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
|
||||||
namespace linker.plugins.updater
|
namespace linker.plugins.updater
|
||||||
{
|
{
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
using linker.client;
|
using linker.client.config;
|
||||||
using linker.client.config;
|
|
||||||
using linker.config;
|
using linker.config;
|
||||||
|
using linker.plugins.client;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
using linker.plugins.server;
|
||||||
using linker.plugins.updater.messenger;
|
using linker.plugins.updater.messenger;
|
||||||
using linker.server;
|
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
@@ -78,7 +79,6 @@ namespace linker.plugins.updater
|
|||||||
{
|
{
|
||||||
updaterHelper.Confirm(updateInfo, version);
|
updaterHelper.Confirm(updateInfo, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 来自别的客户端的更新信息
|
/// 来自别的客户端的更新信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -36,10 +36,11 @@ namespace linker.plugins.updater
|
|||||||
using HttpClient httpClient = new HttpClient();
|
using HttpClient httpClient = new HttpClient();
|
||||||
string str = await httpClient.GetStringAsync("http://gh.snltty.com:1808/https://github.com/snltty/linker/releases/latest").WaitAsync(TimeSpan.FromSeconds(15));
|
string str = await httpClient.GetStringAsync("http://gh.snltty.com:1808/https://github.com/snltty/linker/releases/latest").WaitAsync(TimeSpan.FromSeconds(15));
|
||||||
|
|
||||||
Match match = new Regex(@"/snltty/linker/tree/(v[\d.]+)").Match(str);
|
string datetime = DateTime.Parse(new Regex("datetime=\"(.+)\"").Match(str).Groups[1].Value).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
string tag = match.Groups[1].Value;
|
string tag = new Regex(@"/snltty/linker/tree/(v[\d.]+)").Match(str).Groups[1].Value;
|
||||||
string[] msg = new Regex(@"<li>(.+)</li>").Matches(str).Select(c => c.Groups[1].Value).ToArray();
|
string[] msg = new Regex(@"<li>(.+)</li>").Matches(str).Select(c => c.Groups[1].Value).ToArray();
|
||||||
|
|
||||||
|
updateInfo.DateTime = datetime;
|
||||||
updateInfo.Msg = msg;
|
updateInfo.Msg = msg;
|
||||||
updateInfo.Version = tag;
|
updateInfo.Version = tag;
|
||||||
|
|
||||||
@@ -243,6 +244,8 @@ namespace linker.plugins.updater
|
|||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
[MemoryPackIgnore]
|
[MemoryPackIgnore]
|
||||||
public string[] Msg { get; set; }
|
public string[] Msg { get; set; }
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public string DateTime { get; set; }
|
||||||
|
|
||||||
public string MachineId { get; set; }
|
public string MachineId { get; set; }
|
||||||
public UpdateStatus Status { get; set; } = UpdateStatus.None;
|
public UpdateStatus Status { get; set; } = UpdateStatus.None;
|
||||||
|
@@ -17,7 +17,7 @@ namespace linker.plugins.updater
|
|||||||
|
|
||||||
public StartupLevel Level => StartupLevel.Normal;
|
public StartupLevel Level => StartupLevel.Normal;
|
||||||
|
|
||||||
public string[] Dependent => Array.Empty<string>();
|
public string[] Dependent => new string[] { "messenger", "signin", "serialize", "config" };
|
||||||
|
|
||||||
public StartupLoadType LoadType => StartupLoadType.Normal;
|
public StartupLoadType LoadType => StartupLoadType.Normal;
|
||||||
|
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
using linker.config;
|
using linker.config;
|
||||||
|
using linker.plugins.messenger;
|
||||||
|
using linker.plugins.server;
|
||||||
using linker.plugins.signin.messenger;
|
using linker.plugins.signin.messenger;
|
||||||
using linker.plugins.updater.config;
|
using linker.plugins.updater.config;
|
||||||
using linker.server;
|
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
|
|
||||||
namespace linker.plugins.updater.messenger
|
namespace linker.plugins.updater.messenger
|
||||||
|
@@ -1,258 +0,0 @@
|
|||||||
using linker.libs;
|
|
||||||
using linker.libs.extends;
|
|
||||||
using System.Buffers;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Security;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Security.Authentication;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
|
|
||||||
namespace linker.server
|
|
||||||
{
|
|
||||||
public sealed class TcpServer
|
|
||||||
{
|
|
||||||
private Socket socket;
|
|
||||||
private Socket socketUdp;
|
|
||||||
private CancellationTokenSource cancellationTokenSource;
|
|
||||||
private X509Certificate serverCertificate;
|
|
||||||
|
|
||||||
private readonly IConnectionReceiveCallback connectionReceiveCallback;
|
|
||||||
public TcpServer(MessengerResolver connectionReceiveCallback)
|
|
||||||
{
|
|
||||||
cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
this.connectionReceiveCallback = connectionReceiveCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(string certificate, string password)
|
|
||||||
{
|
|
||||||
string path = Path.GetFullPath(certificate);
|
|
||||||
if (File.Exists(path))
|
|
||||||
{
|
|
||||||
serverCertificate = new X509Certificate(path, password);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LoggerHelper.Instance.Error($"file {path} not found");
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start(int port)
|
|
||||||
{
|
|
||||||
if (socket == null)
|
|
||||||
{
|
|
||||||
socket = BindAccept(port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private Socket BindAccept(int port)
|
|
||||||
{
|
|
||||||
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
|
|
||||||
Socket socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
|
||||||
socket.IPv6Only(localEndPoint.AddressFamily, false);
|
|
||||||
socket.ReuseBind(localEndPoint);
|
|
||||||
socket.Listen(int.MaxValue);
|
|
||||||
|
|
||||||
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs
|
|
||||||
{
|
|
||||||
UserToken = socket,
|
|
||||||
SocketFlags = SocketFlags.None,
|
|
||||||
};
|
|
||||||
acceptEventArg.Completed += IO_Completed;
|
|
||||||
StartAccept(acceptEventArg);
|
|
||||||
|
|
||||||
_ = BindUdp(port);
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Memory<byte> BuildSendData(byte[] data, IPEndPoint ep)
|
|
||||||
{
|
|
||||||
//给客户端返回他的IP+端口
|
|
||||||
data[0] = (byte)ep.AddressFamily;
|
|
||||||
ep.Address.TryWriteBytes(data.AsSpan(1), out int length);
|
|
||||||
((ushort)ep.Port).ToBytes(data.AsMemory(1 + length));
|
|
||||||
|
|
||||||
//防止一些网关修改掉它的外网IP
|
|
||||||
for (int i = 0; i < 1 + length + 2; i++)
|
|
||||||
{
|
|
||||||
data[i] = (byte)(data[i] ^ byte.MaxValue);
|
|
||||||
}
|
|
||||||
return data.AsMemory(0, 1 + length + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task BindUdp(int port)
|
|
||||||
{
|
|
||||||
socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|
||||||
socketUdp.Bind(new IPEndPoint(IPAddress.Any, port));
|
|
||||||
socketUdp.WindowsUdpBug();
|
|
||||||
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
byte[] sendData = new byte[20];
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
SocketReceiveFromResult result = await socketUdp.ReceiveFromAsync(buffer, SocketFlags.None, endPoint).ConfigureAwait(false);
|
|
||||||
IPEndPoint ep = result.RemoteEndPoint as IPEndPoint;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Memory<byte> memory = BuildSendData(sendData, ep);
|
|
||||||
|
|
||||||
await socketUdp.SendToAsync(memory, ep).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
|
|
||||||
{
|
|
||||||
acceptEventArg.AcceptSocket = null;
|
|
||||||
Socket token = (Socket)acceptEventArg.UserToken;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (token.AcceptAsync(acceptEventArg) == false)
|
|
||||||
{
|
|
||||||
ProcessAccept(acceptEventArg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
token?.SafeClose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void IO_Completed(object sender, SocketAsyncEventArgs e)
|
|
||||||
{
|
|
||||||
switch (e.LastOperation)
|
|
||||||
{
|
|
||||||
case SocketAsyncOperation.Accept:
|
|
||||||
ProcessAccept(e);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void ProcessAccept(SocketAsyncEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.AcceptSocket != null)
|
|
||||||
{
|
|
||||||
_ = BeginReceiveServer(e.AcceptSocket);
|
|
||||||
StartAccept(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<byte> ReceiveType(Socket socket)
|
|
||||||
{
|
|
||||||
byte[] sendData = ArrayPool<byte>.Shared.Rent(20);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await socket.ReceiveAsync(sendData.AsMemory(0, 1), SocketFlags.None).ConfigureAwait(false);
|
|
||||||
byte type = sendData[0];
|
|
||||||
if (type == 0)
|
|
||||||
{
|
|
||||||
Memory<byte> memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint);
|
|
||||||
await socket.SendAsync(memory, SocketFlags.None).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
ArrayPool<byte>.Shared.Return(sendData);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
private async Task BeginReceiveServer(Socket socket)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (socket == null || socket.RemoteEndPoint == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
socket.KeepAlive();
|
|
||||||
|
|
||||||
if (await ReceiveType(socket).ConfigureAwait(false) == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkStream networkStream = new NetworkStream(socket, false);
|
|
||||||
SslStream sslStream = new SslStream(networkStream, true);
|
|
||||||
await sslStream.AuthenticateAsServerAsync(serverCertificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false);
|
|
||||||
IConnection connection = CreateConnection(sslStream, networkStream, socket, socket.LocalEndPoint as IPEndPoint, socket.RemoteEndPoint as IPEndPoint);
|
|
||||||
|
|
||||||
|
|
||||||
connection.BeginReceive(connectionReceiveCallback, null, true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
|
||||||
LoggerHelper.Instance.Error(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public async Task<IConnection> BeginReceive(Socket socket)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (socket == null || socket.RemoteEndPoint == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
socket.KeepAlive();
|
|
||||||
await socket.SendAsync(new byte[] { 1 }).ConfigureAwait(false);
|
|
||||||
NetworkStream networkStream = new NetworkStream(socket, false);
|
|
||||||
SslStream sslStream = new SslStream(networkStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
|
|
||||||
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
|
|
||||||
{
|
|
||||||
AllowRenegotiation = true,
|
|
||||||
EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
IConnection connection = CreateConnection(sslStream, networkStream, socket, socket.LocalEndPoint as IPEndPoint, socket.RemoteEndPoint as IPEndPoint);
|
|
||||||
|
|
||||||
connection.BeginReceive(connectionReceiveCallback, null, true);
|
|
||||||
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
|
||||||
LoggerHelper.Instance.Error(ex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IConnection CreateConnection(SslStream stream, NetworkStream networkStream, Socket socket, IPEndPoint local, IPEndPoint remote)
|
|
||||||
{
|
|
||||||
return new TcpConnection(stream, networkStream, socket, local, remote)
|
|
||||||
{
|
|
||||||
ReceiveRequestWrap = new MessageRequestWrap(),
|
|
||||||
ReceiveResponseWrap = new MessageResponseWrap()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
cancellationTokenSource?.Cancel();
|
|
||||||
socket?.SafeClose();
|
|
||||||
socket = null;
|
|
||||||
}
|
|
||||||
public void Disponse()
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user