Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
R
railgun-routing-server
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Railgun
railgun-routing-server
Commits
4011c4b8
Commit
4011c4b8
authored
Aug 28, 2022
by
神楽坂玲奈
Committed by
铃兰
Aug 28, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix
parent
c7fba0e4
Pipeline
#16078
passed with stages
in 2 minutes and 8 seconds
Changes
4
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
79 additions
and
89 deletions
+79
-89
README.md
README.md
+7
-9
server/protocol.ts
server/protocol.ts
+8
-8
server/src/Router.ts
server/src/Router.ts
+59
-64
server/src/main.ts
server/src/main.ts
+5
-8
No files found.
README.md
View file @
4011c4b8
...
...
@@ -50,8 +50,8 @@ interface Change {
}
```
如果报文的 seq 为 0,重置状态和路由表
如果报文的 seq 跟自己的
report seq
不同,忽略。
seq自增,按照要求修改路由表,改完之后立即
额外发送一次 Report 报文 (可以不带 peers)
如果报文的 seq 跟自己的
ack
不同,忽略。
按照要求修改路由表,seq 自增,
额外发送一次 Report 报文 (可以不带 peers)
## 服务器行为
...
...
@@ -62,20 +62,18 @@ seq自增,按照要求修改路由表,改完之后立即额外发送一次 R
-
非 正在变更 状态:
为每个路由器检查,目标到每个路由器,下一跳哪个路由器最优。
只假设这台路由器的下一跳会变化,其他路由表用旧的不考虑改变。
如果发现有比现在更优的,就为这个路由器 下发 Change 报文。之后进入正在变更状态,跳过其他路由器的检查
如果发现有比现在更优的,就为这个路由器
seq++ 并
下发 Change 报文。之后进入正在变更状态,跳过其他路由器的检查
-
正在变更 状态:
向路由器发送 Change 报文
若正在变更的客户端被标记为下线,退出正在变更状态
### 收到客户端 Report 报文时
如果报文
顺序号为 0,重置状态并立即发送 Change(seq=0)
如果报文
顺序号不为0而服务器顺序号为
0,立即发送 Change
如果报文
顺序号
不为 change seq +1,忽略。
如果报文
ack 为 0,重置状态并立即发送 Change
如果报文
ack 不为 0 而服务器 seq 为
0,立即发送 Change
如果报文
ack
不为 change seq +1,忽略。
如果携带了 peers 信息,存下来。
-
如果这个路由器正在变更
seq 自增
退出正在变更状态
如果这个路由器正在变更,退出正在变更状态
## 关于顺序号,断线、重启的一些解释:
### 客户端跟客户端之间
...
...
server/protocol.ts
View file @
4011c4b8
...
...
@@ -7,22 +7,22 @@ export interface PeerQuality {
}
// 路由器向中心服务器发送的消息
export
interface
UploadMessage
{
id
:
number
;
// router id
export
interface
Report
{
id
:
number
;
ack
:
number
;
peers
?:
Record
<
number
,
PeerQuality
>
;
}
// 中心服务器向路由器发送的消息
export
interface
DownloadMessa
ge
{
export
interface
Chan
ge
{
seq
:
number
,
via
:
Record
<
number
,
number
>
,
plan
:
Record
<
number
,
number
>
//
plan: Record<number, number>
}
// 路由器向路由器发送的消息
export
interface
PeerMessage
{
id
:
number
;
seq
:
number
;
time
:
number
;
export
interface
Hello
{
id
:
number
;
// 自己的id
seq
:
number
;
// 这个报文的顺序号,每次发送自增
time
:
number
;
// 自己的系统时间,EPOCH 以来的毫秒数
}
server/src/Router.ts
View file @
4011c4b8
import
{
RemoteInfo
,
Socket
}
from
'
dgram
'
;
import
{
DownloadMessage
,
PeerQuality
,
UploadMessage
}
from
'
../protocol
'
;
import
{
Change
,
PeerQuality
,
Report
}
from
'
../protocol
'
;
import
routers
from
'
../import/data/Router.json
'
;
// import plans from '../config/plans.json';
import
assert
from
'
assert
'
;
...
...
@@ -12,24 +12,19 @@ import _connections from '../import/connections.json';
const
connections
:
Record
<
number
,
Record
<
number
,
{
metric
:
number
,
protocol
:
string
}
>>
=
_connections
;
export
class
Router
{
static
updating
?:
Router
;
static
updating_timer
:
any
;
static
timeout_timer
:
any
;
static
all
:
Router
[]
=
routers
.
map
(
s
=>
new
Router
(
s
.
id
));
// config
// id!: number;
static
updating
?:
Router
;
seq
=
0
;
peers
:
Record
<
number
,
PeerQuality
>
=
{};
via
:
Map
<
Router
,
Router
>
=
new
Map
();
// plan: Record<number, number> = {};
time
:
number
=
0
;
rinfo
?:
RemoteInfo
;
constructor
(
public
id
:
number
)
{
// Object.assign(this, config
);
this
.
reset
(
);
}
reset
()
{
...
...
@@ -38,59 +33,39 @@ export class Router {
for
(
const
router
of
Router
.
all
.
filter
(
r
=>
r
.
id
!==
this
.
id
))
{
this
.
via
.
set
(
router
,
router
);
}
if
(
Router
.
updating
==
this
)
Router
.
updating
=
undefined
;
// for (const plan of plans.filter(plan => !plan.routers.includes(this.id))) {
// this.plan[plan.id] = this.id;
// }
}
lost
()
{
this
.
seq
=
0
;
this
.
rinfo
=
undefined
;
return
console
.
log
(
`router
${
this
.
id
}
lost connection.`
);
}
route_quality
(
to
:
Router
,
via
:
Router
=
this
.
via
.
get
(
to
)
!
)
{
assert
(
via
!==
undefined
);
assert
(
this
!==
via
);
assert
(
this
!==
to
);
const
result
=
new
Quality
();
let
current
:
Router
=
this
;
let
next
=
via
;
const
route
=
[
current
,
next
];
while
(
true
)
{
const
quality
=
next
.
peers
[
current
.
id
];
if
(
!
quality
||
quality
.
reliability
<=
0
)
return
Quality
.
unreachable
;
// 不通
result
.
concat
(
quality
.
delay
,
quality
.
jitter
,
quality
.
reliability
,
connections
[
current
.
id
][
next
.
id
].
metric
);
if
(
next
===
to
)
return
result
;
// 到达
// 寻找下一跳
current
=
next
;
next
=
current
.
via
.
get
(
to
)
!
;
assert
(
next
);
//to server_id 型路由,由于 server 两两相连,下一跳一定是存在的,至少能直达
if
(
route
.
includes
(
next
))
{
// 环路
return
Quality
.
unreachable
;
}
else
{
route
.
push
(
next
);
}
onMessage
(
socket
:
Socket
,
data
:
Report
)
{
// 客户端重启
if
(
data
.
ack
===
0
)
{
this
.
reset
();
this
.
time
=
Date
.
now
();
this
.
send
(
socket
,
{},
{});
// 服务器重启或客户端下线
}
else
if
(
this
.
seq
==
0
)
{
this
.
time
=
Date
.
now
();
this
.
send
(
socket
,
{},
{});
}
else
if
(
data
.
ack
==
this
.
seq
+
1
)
{
this
.
time
=
Date
.
now
();
if
(
data
.
peers
)
this
.
peers
=
data
.
peers
;
if
(
Router
.
updating
===
this
)
Router
.
updating
=
undefined
;
}
}
onMessage
(
hello
:
UploadMessage
)
{
if
(
hello
.
ack
===
0
)
this
.
reset
();
if
(
hello
.
peers
)
this
.
peers
=
hello
.
peers
;
if
(
Router
.
updating
===
this
&&
hello
.
ack
===
this
.
seq
+
1
)
{
clearInterval
(
Router
.
updating_timer
);
clearTimeout
(
Router
.
timeout_timer
);
Router
.
updating
=
undefined
;
this
.
seq
++
;
}
update
(
socket
:
Socket
)
{
if
(
!
this
.
rinfo
)
return
;
if
(
Date
.
now
()
-
this
.
time
>
config
.
timeout
)
{
console
.
log
(
`router
${
this
.
id
}
lost connection.`
);
this
.
rinfo
=
undefined
;
this
.
reset
();
return
;
}
if
(
Router
.
updating
)
return
;
update
(
socket
:
Socket
)
{
const
changedVia
:
Record
<
number
,
number
>
=
{};
const
metric
:
Record
<
number
,
number
>
=
{};
for
(
const
to
of
Router
.
all
.
filter
(
r
=>
r
.
id
!==
this
.
id
))
{
...
...
@@ -130,25 +105,45 @@ export class Router {
// }
if
(
!
_
.
isEmpty
(
changedVia
)
||
!
_
.
isEmpty
(
changedPlan
))
{
this
.
seq
++
;
Router
.
updating
=
this
;
Router
.
updating_timer
=
setInterval
(()
=>
this
.
send
(
socket
,
changedVia
,
changedPlan
),
config
.
interval
);
this
.
send
(
socket
,
changedVia
,
changedPlan
);
Router
.
timeout_timer
=
setTimeout
(()
=>
{
this
.
lost
();
clearInterval
(
Router
.
updating_timer
);
Router
.
updating
=
undefined
;
},
config
.
timeout
*
config
.
interval
);
}
}
send
(
socket
:
Socket
,
via
:
Record
<
number
,
number
>
,
plan
:
Record
<
number
,
number
>
)
{
if
(
!
this
.
rinfo
)
return
;
const
message
:
DownloadMessage
=
{
seq
:
this
.
seq
,
via
,
plan
};
const
message
:
Change
=
{
seq
:
this
.
seq
,
via
};
console
.
log
(
this
.
id
,
message
);
return
socket
.
send
(
JSON
.
stringify
(
message
),
this
.
rinfo
.
port
,
this
.
rinfo
.
address
);
return
socket
.
send
(
JSON
.
stringify
(
message
),
this
.
rinfo
!
.
port
,
this
.
rinfo
!
.
address
);
}
}
for
(
const
router
of
Router
.
all
)
{
router
.
reset
();
route_quality
(
to
:
Router
,
via
:
Router
=
this
.
via
.
get
(
to
)
!
)
{
assert
(
via
!==
undefined
);
assert
(
this
!==
via
);
assert
(
this
!==
to
);
const
result
=
new
Quality
();
let
current
:
Router
=
this
;
let
next
=
via
;
const
route
=
[
current
,
next
];
while
(
true
)
{
const
quality
=
next
.
peers
[
current
.
id
];
if
(
!
quality
||
quality
.
reliability
<=
0
)
return
Quality
.
unreachable
;
// 不通
result
.
concat
(
quality
.
delay
,
quality
.
jitter
,
quality
.
reliability
,
connections
[
current
.
id
][
next
.
id
].
metric
);
if
(
next
===
to
)
return
result
;
// 到达
// 寻找下一跳
current
=
next
;
next
=
current
.
via
.
get
(
to
)
!
;
assert
(
next
);
//to server_id 型路由,由于 server 两两相连,下一跳一定是存在的,至少能直达
if
(
route
.
includes
(
next
))
{
// 环路
return
Quality
.
unreachable
;
}
else
{
route
.
push
(
next
);
}
}
}
}
server/src/main.ts
View file @
4011c4b8
import
dgram
from
'
dgram
'
;
import
{
UploadMessage
}
from
'
../protocol
'
;
import
{
Report
}
from
'
../protocol
'
;
import
assert
from
'
assert
'
;
import
{
Router
}
from
'
./Router
'
;
import
config
from
'
../config/config.json
'
;
...
...
@@ -20,16 +20,16 @@ const socket = dgram
const
address
=
socket
.
address
();
console
.
log
(
`listening
${
address
.
address
}
:
${
address
.
port
}
`
);
})
.
on
(
'
message
'
,
function
(
message
,
rinfo
)
{
.
on
(
'
message
'
,
function
(
message
,
rinfo
)
{
try
{
const
hello
:
UploadMessage
=
JSON
.
parse
(
message
.
toString
());
const
hello
:
Report
=
JSON
.
parse
(
message
.
toString
());
assert
(
hello
.
id
);
const
router
:
Router
=
Router
.
all
.
find
((
r
)
=>
r
.
id
===
hello
.
id
)
!
;
assert
(
router
);
router
.
rinfo
=
rinfo
;
router
.
onMessage
(
hello
);
router
.
onMessage
(
socket
,
hello
);
}
catch
(
e
)
{
console
.
warn
(
e
);
}
...
...
@@ -37,8 +37,5 @@ const socket = dgram
socket
.
bind
(
config
.
port
);
setInterval
(()
=>
{
for
(
const
from
of
Router
.
all
)
{
if
(
Router
.
updating
)
return
;
from
.
update
(
socket
);
}
for
(
const
from
of
Router
.
all
)
from
.
update
(
socket
);
},
config
.
interval
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment