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
d6099740
Commit
d6099740
authored
Jan 10, 2026
by
nanamicat
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update
parent
9d847083
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
38 additions
and
39 deletions
+38
-39
src/data.rs
src/data.rs
+21
-22
src/main.rs
src/main.rs
+2
-3
src/router.rs
src/router.rs
+15
-14
No files found.
src/data.rs
View file @
d6099740
...
...
@@ -95,23 +95,18 @@ pub struct Database {
pub
connections
:
BTreeMap
<
RouterID
,
BTreeMap
<
RouterID
,
Connection
>>
,
}
pub
static
DATABASE
:
std
::
sync
::
LazyLock
<
Database
>
=
std
::
sync
::
LazyLock
::
new
(||
Database
::
load
());
pub
static
DATABASE
:
std
::
sync
::
LazyLock
<
Database
>
=
std
::
sync
::
LazyLock
::
new
(||
Database
{
routers
:
register
(
load_file
(
"import/data/Router.json"
),
|
r
|
r
.id
.
0
,
|
r
|
r
.name
.clone
(),
&
ROUTER_ID_REGISTRY
),
gateways
:
load_file
(
"import/data/Gateway.json"
),
gateway_groups
:
load_file
(
"import/data/GatewayGroup.json"
),
regions
:
load_file
(
"import/data/Region.json"
),
connections
:
load_file
(
"import/connections.json"
),
});
static
ROUTER_ID_REGISTRY
:
OnceLock
<
StringInterner
<
StringBackend
<
RouterID
>>>
=
OnceLock
::
new
();
impl
Database
{
pub
fn
load
()
->
Self
{
Self
{
routers
:
register
(
Self
::
load_file
(
"import/data/Router.json"
),
|
r
|
r
.id
.
0
,
|
r
|
r
.name
.clone
(),
&
ROUTER_ID_REGISTRY
),
gateways
:
Self
::
load_file
(
"import/data/Gateway.json"
),
gateway_groups
:
Self
::
load_file
(
"import/data/GatewayGroup.json"
),
regions
:
Self
::
load_file
(
"import/data/Region.json"
),
connections
:
Self
::
load_file
(
"import/connections.json"
),
}
}
fn
load_file
<
T
:
serde
::
de
::
DeserializeOwned
>
(
path
:
&
str
)
->
T
{
serde_json
::
from_str
(
&
std
::
fs
::
read_to_string
(
path
)
.unwrap
())
.unwrap
()
}
fn
load_file
<
T
:
serde
::
de
::
DeserializeOwned
>
(
path
:
&
str
)
->
T
{
serde_json
::
from_str
(
&
std
::
fs
::
read_to_string
(
path
)
.unwrap
())
.unwrap
()
}
pub
fn
register
<
T
,
I
,
N
,
S
,
Sym
>
(
mut
data
:
Vec
<
T
>
,
num
:
N
,
str
:
S
,
registry
:
&
OnceLock
<
StringInterner
<
StringBackend
<
Sym
>>>
)
->
Vec
<
T
>
...
...
@@ -147,18 +142,22 @@ fn deserialize_router_id<'de, D>(deserializer: D) -> Result<RouterID, D::Error>
where
D
:
serde
::
Deserializer
<
'de
>
,
{
let
s
=
String
::
deserialize
(
deserializer
)
?
;
ROUTER_ID_REGISTRY
.get
()
.unwrap
()
.get
(
&
s
)
.ok_or_else
(||
serde
::
de
::
Error
::
custom
(
format!
(
"Unknown router: {s}"
)))
ROUTER_ID_REGISTRY
.get
()
.unwrap
()
.get
(
&
String
::
deserialize
(
deserializer
)
?
)
.ok_or_else
(||
serde
::
de
::
Error
::
custom
(
format!
(
"Unknown router"
)))
}
fn
serialize_router_id
<
S
>
(
id
:
&
RouterID
,
serializer
:
S
)
->
Result
<
S
::
Ok
,
S
::
Error
>
where
S
:
serde
::
Serializer
,
{
let
s
=
ROUTER_ID_REGISTRY
.get
()
.unwrap
()
.resolve
(
*
id
)
.ok_or_else
(||
serde
::
ser
::
Error
::
custom
(
format!
(
"Unknown id: {}"
,
id
.
0
)))
?
;
serializer
.serialize_str
(
s
)
serializer
.serialize_str
(
ROUTER_ID_REGISTRY
.get
()
.unwrap
()
.resolve
(
*
id
)
.ok_or_else
(||
serde
::
ser
::
Error
::
custom
(
format!
(
"Unknown id: {}"
,
id
.
0
)))
?
,
)
}
src/main.rs
View file @
d6099740
...
...
@@ -33,7 +33,6 @@ async fn main() -> Result<()> {
tracing_subscriber
::
fmt
::
init
();
let
config
:
Settings
=
Config
::
builder
()
.add_source
(
Environment
::
default
())
.build
()
?
.try_deserialize
()
?
;
let
regions
:
Vec
<
RegionID
>
=
DATABASE
.regions
.iter
()
.enumerate
()
.map
(|(
i
,
_
)|
RegionID
(
i
as
u8
))
.collect
();
let
gateways_group
:
BTreeMap
<
GatewayGroupID
,
Vec
<&
data
::
Gateway
>>
=
DATABASE
.gateway_groups
.iter
()
...
...
@@ -43,7 +42,7 @@ async fn main() -> Result<()> {
})
.collect
();
let
routers
:
BTreeMap
<
RouterID
,
Router
>
=
DATABASE
.routers
.iter
()
.map
(|
c
|
(
c
.id
,
Router
::
new
(
c
,
&
regions
,
&
gateways_group
)))
.collect
();
let
routers
:
BTreeMap
<
RouterID
,
Router
>
=
DATABASE
.routers
.iter
()
.map
(|
c
|
(
c
.id
,
Router
::
new
(
c
,
&
gateways_group
)))
.collect
();
let
routers
=
Arc
::
new
(
RwLock
::
new
(
routers
));
let
listener
=
tokio
::
net
::
TcpListener
::
bind
(
config
.http_bind
)
.await
?
;
...
...
@@ -88,7 +87,7 @@ async fn main() -> Result<()> {
&&
let
Some
(
router
)
=
routers
.get
(
&
uplink
.id
)
&&
router
.is_online
()
&&
router
.last_update
!=
now
&&
let
Some
(
downlink
)
=
router
.update
(
now
,
&
routers
,
&
regions
,
&
gateways_group
)
&&
let
Some
(
downlink
)
=
router
.update
(
now
,
&
routers
,
&
gateways_group
)
{
updating
.router_id
=
router
.id
;
updating
.message
=
downlink
;
...
...
src/router.rs
View file @
d6099740
...
...
@@ -34,7 +34,7 @@ impl PartialEq<Self> for Router {
impl
Eq
for
Router
{}
impl
Router
{
pub
fn
new
(
data
:
&
data
::
Router
,
regions
:
&
Vec
<
RegionID
>
,
gateway_groups
:
&
BTreeMap
<
GatewayGroupID
,
Vec
<&
data
::
Gateway
>>
)
->
Self
{
pub
fn
new
(
data
:
&
data
::
Router
,
gateway_groups
:
&
BTreeMap
<
GatewayGroupID
,
Vec
<&
data
::
Gateway
>>
)
->
Self
{
Self
{
id
:
data
.id
,
version
:
rand
::
random
(),
...
...
@@ -45,14 +45,16 @@ impl Router {
.map
(|(
&
from
,
_
)|
(
from
,
Default
::
default
()))
.collect
(),
via
:
DATABASE
.routers
.iter
()
.filter
(|
r
|
r
.id
!=
data
.id
)
.map
(|
r
|
(
r
.id
,
r
.id
))
.collect
(),
plan
:
regions
plan
:
DATABASE
.regions
.iter
()
.map
(|
&
region
|
{
.enumerate
()
.map
(|(
r
,
_
)|
{
(
region
,
RegionID
(
r
as
u8
)
,
gateway_groups
.iter
()
.map
(|(
&
gid
,
gws
)|
(
gid
,
gws
.iter
()
.min_by_key
(|
gw
|
Self
::
guess_metric
(
data
,
gw
,
&
region
))
.unwrap
()
.id
))
.map
(|(
&
gid
,
gws
)|
(
gid
,
gws
.iter
()
.min_by_key
(|
gw
|
Self
::
guess_metric
(
data
,
gw
,
r
))
.unwrap
()
.id
))
.collect
(),
)
})
...
...
@@ -63,10 +65,8 @@ impl Router {
}
}
fn
guess_metric
(
data
:
&
data
::
Router
,
gw
:
&
data
::
Gateway
,
region
:
&
RegionID
)
->
i32
{
gw
.metrics
[
region
.
0
as
usize
]
.saturating_add
(
gw
.cost_outbound
)
.saturating_add
(
if
gw
.router
==
data
.id
{
0
}
else
{
100
})
fn
guess_metric
(
data
:
&
data
::
Router
,
gw
:
&
data
::
Gateway
,
region
:
usize
)
->
i32
{
gw
.metrics
[
region
]
.saturating_add
(
gw
.cost_outbound
)
.saturating_add
(
if
gw
.router
==
data
.id
{
0
}
else
{
100
})
}
pub
fn
online
(
&
mut
self
,
addr
:
SocketAddr
,
now
:
Instant
)
{
...
...
@@ -144,7 +144,7 @@ impl Router {
}
}
pub
fn
update
(
&
self
,
now
:
Instant
,
routers
:
&
BTreeMap
<
RouterID
,
Router
>
,
regions
:
&
Vec
<
RegionID
>
,
gateway_groups
:
&
BTreeMap
<
GatewayGroupID
,
Vec
<&
data
::
Gateway
>>
)
->
Option
<
Downlink
>
{
pub
fn
update
(
&
self
,
now
:
Instant
,
routers
:
&
BTreeMap
<
RouterID
,
Router
>
,
gateway_groups
:
&
BTreeMap
<
GatewayGroupID
,
Vec
<&
data
::
Gateway
>>
)
->
Option
<
Downlink
>
{
let
penalty
=
PENALTY_MIN
+
(
PENALTY
as
f32
*
f32
::
exp2
(
-
now
.duration_since
(
self
.last_update
)
.div_duration_f32
(
HALF_LIFE
)))
as
i32
;
let
mut
changed_via
=
BTreeMap
::
new
();
let
mut
changed_plan
=
BTreeMap
::
new
();
...
...
@@ -179,14 +179,15 @@ impl Router {
}
// Plan updates (Gateways)
for
&
region
in
regions
{
for
(
r
,
_
)
in
DATABASE
.regions
.iter
()
.enumerate
()
{
let
region_id
=
RegionID
(
r
as
u8
);
for
(
&
gid
,
gateways
)
in
gateway_groups
{
let
current_gw
=
self
.plan
[
&
region
][
&
gid
];
let
current_gw
=
self
.plan
[
&
region
_id
][
&
gid
];
let
current_metric
=
metrics
[
&
DATABASE
.gateways
.iter
()
.find
(|
f
|
f
.id
==
current_gw
)
.unwrap
()
.router
];
let
(
best_gw
,
best_metric
)
=
gateways
.iter
()
.map
(|
g
|
(
g
,
metrics
[
&
g
.router
]
.saturating_add
(
g
.cost_outbound
)
.saturating_add
(
g
.metrics
[
r
egion
.
0
as
usize
])))
.map
(|
g
|
(
g
,
metrics
[
&
g
.router
]
.saturating_add
(
g
.cost_outbound
)
.saturating_add
(
g
.metrics
[
r
])))
.min_by_key
(|(
_
,
m
)|
*
m
)
.unwrap
();
...
...
@@ -194,7 +195,7 @@ impl Router {
if
best_metric
.saturating_add
(
penalty
)
<
current_metric
{
overcome
=
true
;
}
changed_plan
.entry
(
region
)
.or_insert_with
(
BTreeMap
::
new
)
.insert
(
gid
,
best_gw
.id
);
changed_plan
.entry
(
region
_id
)
.or_insert_with
(
BTreeMap
::
new
)
.insert
(
gid
,
best_gw
.id
);
}
}
}
...
...
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