Update to use suzu library; update documentation.
This commit is contained in:
parent
620abbf89f
commit
13308a0afd
0
.cargo/config.toml
Normal file
0
.cargo/config.toml
Normal file
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
/config.suzu
|
||||
/data
|
||||
|
@ -6,4 +6,6 @@ edition = "2021"
|
||||
[dependencies]
|
||||
const_format = "0.2.32"
|
||||
|
||||
szun = { git = "https://git.tsukiyo.org/Suzu/szun" }
|
||||
suzu = { git = "https://git.tsukiyo.org/Suzu/suzu" }
|
||||
storage = { git = "https://git.tsukiyo.org/Utility/storage" }
|
||||
trie = { git = "https://git.tsukiyo.org/Utility/trie" }
|
||||
|
51
castle/docs/systems/calendar.md
Normal file
51
castle/docs/systems/calendar.md
Normal file
@ -0,0 +1,51 @@
|
||||
# Calendar
|
||||
|
||||
```
|
||||
Calendar {
|
||||
Title :sequence
|
||||
Detail :sequence
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Events
|
||||
|
||||
```
|
||||
Event {
|
||||
Title :sequence
|
||||
Detail :sequence
|
||||
|
||||
Occurrence :Occurrence
|
||||
}
|
||||
|
||||
Occurrence {
|
||||
#
|
||||
# - Specific Date
|
||||
# - Day of Month
|
||||
# - Day of Week (nth)
|
||||
# -
|
||||
#
|
||||
|
||||
Start :option<Date>
|
||||
Time :option<Time>
|
||||
}
|
||||
|
||||
Duration {
|
||||
Unit :block<1>
|
||||
Value :block<3>
|
||||
}
|
||||
|
||||
Date = block<4>
|
||||
Time = block<2>
|
||||
DateTime = block<8>
|
||||
|
||||
RSVP {
|
||||
User :USER_ID
|
||||
Response :natural
|
||||
# 0 - Pending
|
||||
# 1 - Yes
|
||||
# 2 - No
|
||||
# 3 - Maybe
|
||||
#
|
||||
}
|
||||
```
|
63
castle/docs/systems/channel.md
Normal file
63
castle/docs/systems/channel.md
Normal file
@ -0,0 +1,63 @@
|
||||
# Channel
|
||||
|
||||
`/domain/$DOMAIN/channel.block`
|
||||
```
|
||||
Channel {
|
||||
Type :block<1>
|
||||
|
||||
Name :sequence
|
||||
Detail :sequence
|
||||
}
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
### Document
|
||||
|
||||
```
|
||||
Ext_Document {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Chat
|
||||
|
||||
```
|
||||
Ext_Chat {
|
||||
Thread :THREAD_ID
|
||||
Time :TIMESTAMP
|
||||
}
|
||||
```
|
||||
|
||||
### Feed
|
||||
|
||||
```
|
||||
Ext_Feed {
|
||||
Thread :THREAD_ID
|
||||
Time :TIMESTAMP
|
||||
}
|
||||
```
|
||||
|
||||
### Message Board
|
||||
|
||||
```
|
||||
Ext_Board {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Calendar
|
||||
|
||||
```
|
||||
Ext_Calendar {
|
||||
Calendars :list<CALENDAR_ID>
|
||||
}
|
||||
```
|
||||
|
||||
### Stream
|
||||
|
||||
```
|
||||
Ext_Stream {
|
||||
|
||||
}
|
||||
```
|
15
castle/docs/systems/config.md
Normal file
15
castle/docs/systems/config.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Server Configuration
|
||||
|
||||
`/config.szun`
|
||||
```
|
||||
Service
|
||||
TLS_Port 38690
|
||||
TCP_Port 38696
|
||||
UDP_Port 38690
|
||||
HTTPS_Port 38691
|
||||
HTTP_Port 38697
|
||||
|
||||
Admin [
|
||||
"root@example.com"
|
||||
]
|
||||
```
|
@ -1,42 +0,0 @@
|
||||
# Feed
|
||||
|
||||
`/domain/$DOMAIN/feed.block`
|
||||
```
|
||||
Feed {
|
||||
Name :sequence
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
# Channel
|
||||
|
||||
`/domain/$DOMAIN/channel.block`
|
||||
```
|
||||
Channel {
|
||||
Name :sequence
|
||||
Thread :THREAD_ID
|
||||
Time :TIMESTAMP
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
# Conversation
|
||||
|
||||
`/domain/$DOMAIN/conversation.block`
|
||||
```
|
||||
Conversation {
|
||||
User :USER_ID
|
||||
Subject :sequence
|
||||
Thread :THREAD_ID
|
||||
Time :TIMESTAMP
|
||||
|
||||
Participants :list<USER_ID>
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
# Thread
|
||||
|
||||
Threads are series of messages, storing the content of conversations and channels.
|
||||
|
||||
`/domain/$DOMAIN/thread/$THREAD.block`
|
13
castle/docs/systems/conversation.md
Normal file
13
castle/docs/systems/conversation.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Conversation
|
||||
|
||||
`/domain/$DOMAIN/conversation.block`
|
||||
```
|
||||
Conversation {
|
||||
User :USER_ID
|
||||
Subject :sequence
|
||||
Thread :THREAD_ID
|
||||
Time :TIMESTAMP
|
||||
|
||||
Participants :list<USER_ID>
|
||||
}
|
||||
```
|
@ -4,10 +4,12 @@
|
||||
|
||||
Block file with identity information for each served domain.
|
||||
|
||||
`/domain.block`
|
||||
`/domain/header.block`
|
||||
```
|
||||
Domain {
|
||||
Name :sequence
|
||||
Name :sequence
|
||||
Detail :sequence
|
||||
|
||||
Contact :list<AdminContact>
|
||||
|
||||
Config :DomainConfig
|
||||
@ -19,18 +21,30 @@ Domain {
|
||||
|
||||
```
|
||||
DomainConfig {
|
||||
Isolated :boolean
|
||||
# Whether the domain rejects sessions from foreign servers.
|
||||
# This limits activity to resident users and registered applications.
|
||||
Isolation :natural
|
||||
# Level of restriction on inter-domain communications.
|
||||
#
|
||||
# 0 - Isolated
|
||||
# 1 - Same Server
|
||||
# 2 - Open
|
||||
#
|
||||
|
||||
Registration :natural
|
||||
# Specifies how users may create accounts on the domain.
|
||||
# Level of restriction on the creation of resident accounts.
|
||||
#
|
||||
# - No Registration
|
||||
# - Invitation Only
|
||||
# - By Approval
|
||||
# - Open Registration
|
||||
# 0 - Closed
|
||||
# 1 - Open
|
||||
# 2 - By Invitation
|
||||
# 3 - By Approval
|
||||
#
|
||||
|
||||
Join :natural
|
||||
# Level of restriction on foreign user access to the domain.
|
||||
#
|
||||
# 0 - Closed
|
||||
# 1 - Open
|
||||
# 2 - By Invitation
|
||||
# 3 - By Approval
|
||||
#
|
||||
}
|
||||
```
|
||||
@ -41,8 +55,8 @@ DomainConfig {
|
||||
Maps fully-qualified domain names onto domain identifiers.
|
||||
|
||||
Stored as an in-memory trie, with file-based trie offline storage.
|
||||
`/host.tree`
|
||||
|
||||
`/domain/host.tree`
|
||||
```rs
|
||||
let domain_map :Trie<usize>;
|
||||
```
|
||||
@ -53,9 +67,9 @@ let domain_map :Trie<usize>;
|
||||
`/domain/$DOMAIN/district.block`
|
||||
```
|
||||
District {
|
||||
Name :sequence
|
||||
Name :sequence
|
||||
Detail :sequence
|
||||
|
||||
Feeds :list<FEED_ID>
|
||||
Channels :list<CHANNEL_ID>
|
||||
}
|
||||
```
|
||||
|
28
castle/docs/systems/install.md
Normal file
28
castle/docs/systems/install.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Install Configuration
|
||||
|
||||
`install.szun`
|
||||
```
|
||||
Domains [
|
||||
{
|
||||
Name = "Example"
|
||||
Host = "example.com"
|
||||
Users [
|
||||
{
|
||||
Handle = "root"
|
||||
Secret = "<password>"
|
||||
Roles [
|
||||
Admin
|
||||
]
|
||||
Traits [
|
||||
Managed
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
Name = "Example2"
|
||||
Host = "2.example.com"
|
||||
|
||||
}
|
||||
]
|
||||
```
|
19
castle/docs/systems/label.md
Normal file
19
castle/docs/systems/label.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Label
|
||||
|
||||
Labels are hierarchical markers used to identify content.
|
||||
|
||||
`/domain/$DOMAIN/label.block`
|
||||
```
|
||||
Label {
|
||||
Name :TERM_ID
|
||||
Detail :sequence
|
||||
Parent :LABEL_ID
|
||||
Children :list<LABEL_ID>
|
||||
}
|
||||
```
|
||||
|
||||
```rs
|
||||
let terms :Dictionary;
|
||||
let labels :Pool<Label>;
|
||||
let hierarchy :Graph<usize>;
|
||||
```
|
@ -4,14 +4,19 @@ Messages make up the bulk of content on the platform, being used in feeds, chann
|
||||
|
||||
```
|
||||
Message {
|
||||
User :USER_ID
|
||||
Text :sequence
|
||||
Attachments :list<Attachment>
|
||||
Time :TIMESTAMP
|
||||
Ext :record
|
||||
Thread :THREAD_ID
|
||||
Next :Optional<MESSAGE_ID>
|
||||
User :USER_ID
|
||||
Text :sequence
|
||||
Time :TIMESTAMP
|
||||
}
|
||||
```
|
||||
|
||||
```rs
|
||||
let messages :BlockFile<512>;
|
||||
```
|
||||
|
||||
|
||||
## Extra Information
|
||||
|
||||
### Relay
|
||||
@ -38,7 +43,18 @@ Ext_Reply {
|
||||
```
|
||||
|
||||
|
||||
## Modifiers
|
||||
### Poll
|
||||
|
||||
```
|
||||
Ext_Poll {
|
||||
Options :list<sequence>
|
||||
Responses :list<{
|
||||
User :USER_ID
|
||||
Option :natural
|
||||
}>
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Censors
|
||||
|
||||
@ -52,11 +68,26 @@ Ext_Censor {
|
||||
```
|
||||
|
||||
|
||||
## Attachments
|
||||
### Thread
|
||||
|
||||
If a message originates a thread,
|
||||
|
||||
```
|
||||
Ext_Thread {
|
||||
Thread :THREAD_ID
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Attachments
|
||||
|
||||
One or more resources may be attached to a message, including uploaded files, media, and polls.
|
||||
|
||||
```
|
||||
Ext_Attachment {
|
||||
Attachments :list<record>
|
||||
}
|
||||
|
||||
Attachment_Media {
|
||||
Title :sequence
|
||||
Domain :sequence
|
||||
@ -71,24 +102,40 @@ Attachment_URL {
|
||||
```
|
||||
|
||||
|
||||
## Reactions
|
||||
### Reactions
|
||||
|
||||
```
|
||||
Reaction {
|
||||
|
||||
}
|
||||
Ext_Reactions = list<{
|
||||
Code :REACTION_ID
|
||||
User :USER_ID
|
||||
}>
|
||||
```
|
||||
|
||||
|
||||
## Labels
|
||||
### Labels
|
||||
|
||||
Labels may be applied to messages to aid in searching.
|
||||
|
||||
```
|
||||
Ext_Labels = list<LABEL_ID>
|
||||
```
|
||||
|
||||
|
||||
## Threads
|
||||
|
||||
A new thread may be spawned off of each message.
|
||||
|
||||
```
|
||||
Thread {
|
||||
Origin :{
|
||||
Source :block<1>
|
||||
Id :block<4>
|
||||
}
|
||||
Message :MESSAGE_ID
|
||||
Time :TIMESTAMP
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Mentions
|
||||
|
||||
@ -97,7 +144,17 @@ Users and groups may be mentioned in messages, giving special notification of th
|
||||
Mentioned users will always be able to see the contents of the message, regardless of context.
|
||||
|
||||
```
|
||||
@self (?)
|
||||
|
||||
@handle
|
||||
|
||||
@group
|
||||
|
||||
@district
|
||||
|
||||
@everyone
|
||||
|
||||
@here (?)
|
||||
```
|
||||
|
||||
Resources—such as districts, channels, and feeds—may also be mentioned, embedding a link to the resource in the message.
|
||||
@ -110,3 +167,41 @@ Resources—such as districts, channels, and feeds—may also be mentioned, embe
|
||||
## Text
|
||||
|
||||
Text content is encoded in a binary markup format, providing simple rich text.
|
||||
|
||||
|
||||
## Bookmarks
|
||||
|
||||
Users may bookmark messages for later access.
|
||||
|
||||
Bookmarks may be tagged.
|
||||
|
||||
```
|
||||
Bookmark {
|
||||
Message :MESSAGE_ID
|
||||
Labels :list<LABEL_ID>
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Pins
|
||||
|
||||
Each channel maintains its own list of bookmarked messages.
|
||||
|
||||
|
||||
## Implementation
|
||||
|
||||
### Messages File
|
||||
|
||||
`/domain/$DOMAIN/thread.block`
|
||||
```
|
||||
BLOCK {
|
||||
:Thread
|
||||
}
|
||||
```
|
||||
|
||||
`/domain/$DOMAIN/message.block`
|
||||
```
|
||||
BLOCK {
|
||||
:Message
|
||||
}
|
||||
```
|
||||
|
27
castle/docs/systems/role.md
Normal file
27
castle/docs/systems/role.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Roles
|
||||
|
||||
## Defaults
|
||||
|
||||
### System Administrator
|
||||
|
||||
Automatically assigned to domain users in the server administrators list.
|
||||
Allows user to modify server configuration and manage domains.
|
||||
Automatically compartmentalized.
|
||||
Not implemented as a formal role.
|
||||
|
||||
|
||||
### Administrator
|
||||
|
||||
Allows user to make changes to the domain configuration.
|
||||
Automatically compartmentalized.
|
||||
Privileges may not be modified.
|
||||
|
||||
|
||||
### Manager
|
||||
|
||||
Allows user to modify domain content, including districts and channels.
|
||||
|
||||
|
||||
### Moderator
|
||||
|
||||
Allows user to flag, hide, and archive domain content.
|
@ -6,10 +6,6 @@ Server {
|
||||
Contact :list<AdminContact>
|
||||
|
||||
Config :{
|
||||
Network :{
|
||||
Services :list<NetworkInterface>
|
||||
}
|
||||
|
||||
Upload :{
|
||||
MaxFileSize :natural
|
||||
}
|
||||
@ -18,17 +14,6 @@ Server {
|
||||
```
|
||||
|
||||
|
||||
## Network Protocols
|
||||
|
||||
```
|
||||
NetworkInterface {
|
||||
Protocol :block<1>
|
||||
Interface :block<16>
|
||||
Port :block<2>
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Domain Service
|
||||
|
||||
|
||||
|
@ -15,3 +15,14 @@ struct Participant {
|
||||
user:usize,
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
# Content
|
||||
|
||||
## Text
|
||||
|
||||
## Audio
|
||||
|
||||
## Video
|
||||
|
||||
## File
|
||||
|
@ -1,3 +1,10 @@
|
||||
# NOTES
|
||||
|
||||
- Profile/Banner/Background Image
|
||||
- Uploaded or Remote (cached?)
|
||||
- Profile Style/Colors
|
||||
|
||||
|
||||
# Users
|
||||
|
||||
`/domain/$DOMAIN/user.szn`
|
||||
@ -30,10 +37,6 @@ User {
|
||||
|
||||
Compartments :list<Compartment>
|
||||
}
|
||||
|
||||
##{
|
||||
Ext :User_Local|User_Remote
|
||||
}##
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -27,7 +27,7 @@ pub fn init() -> Result<(),()>
|
||||
fn create_filesystem() -> Result<(),()>
|
||||
{
|
||||
use crate::prelude::schema::*;
|
||||
use szun::*;
|
||||
use suzu::szun::*;
|
||||
|
||||
const D_DATA_TMP :&str = "data_tmp";
|
||||
const D_DATA :&str = "data";
|
||||
@ -39,6 +39,8 @@ pub fn init() -> Result<(),()>
|
||||
const F_DOMAIN :&str = formatcp!("{}/domain.block", D_DATA_TMP);
|
||||
const F_HOST :&str = formatcp!("{}/host.tree", D_DATA_TMP);
|
||||
const F_SESSION :&str = formatcp!("{}/session.block", D_DATA_TMP);
|
||||
const F_CERT_INDEX :&str = formatcp!("{}/index.tree", D_CERTS);
|
||||
const F_CERT_DATA :&str = formatcp!("{}/data.block", D_CERTS);
|
||||
const F_MEDIA_INDEX :&str = formatcp!("{}/index.tree", D_MEDIA);
|
||||
const F_MEDIA_DATA :&str = formatcp!("{}/data.block", D_MEDIA);
|
||||
|
||||
@ -52,34 +54,42 @@ pub fn init() -> Result<(),()>
|
||||
{
|
||||
use crate::protocol::Protocol;
|
||||
|
||||
let server = RecordExt::<SZ_SERVER>::make();
|
||||
let cfg = server.find_as::<Record>("Config");
|
||||
let server = make::<Record>(Record::descriptor(Schema::by_key(SZ_SERVER)));
|
||||
let cfg = server.find::<Record>("Config");
|
||||
|
||||
let cfg_network = cfg.find_as::<Record>("Network");
|
||||
let cfg_network = cfg.find::<Record>("Network");
|
||||
|
||||
let mut cfg_services = cfg_network.find_as::<List<Record>>("Services");
|
||||
let mut cfg_services = cfg_network.find::<List>("Services");
|
||||
|
||||
let service = RecordExt::<SZ_NET_INTERFACE>::make();
|
||||
let service = make::<Record>(Record::descriptor(Schema::by_key(SZ_NET_INTERFACE)));
|
||||
for (proto, _intf, port) in [
|
||||
(Protocol::RyTls, "0.0.0.0", 38690u16),
|
||||
(Protocol::RyTcp, "127.0.0.1", 38689u16),
|
||||
(Protocol::StUdp, "0.0.0.0", 38699u16),
|
||||
] {
|
||||
service.find_as::<Block<1>>("Protocol").set(&[proto as u8]);
|
||||
service.find::<Block>("Protocol").set(&[proto as u8]);
|
||||
//service.find_as::<Block<16>>("Interface").set(&[intf]);
|
||||
service.find_as::<Block<2>>("Port").set(&[(port >> 8) as u8, port as u8]);
|
||||
service.find::<Block>("Port").set(&[(port >> 8) as u8, port as u8]);
|
||||
cfg_services.push(&service);
|
||||
}
|
||||
|
||||
let cfg_upload = cfg.find_as::<Record>("Upload");
|
||||
cfg_upload.find_as::<Natural>("MaxFileSize").set(10 * 1024 * 1024);
|
||||
let cfg_upload = cfg.find::<Record>("Upload");
|
||||
cfg_upload.find::<Natural>("MaxFileSize").set(10 * 1024 * 1024);
|
||||
|
||||
fs::write(F_SERVER_CONFIG, &server.encode()).map_err(|_|())?;
|
||||
}
|
||||
|
||||
// Initialize certificate files.
|
||||
{
|
||||
storage::TrieFile::<8>::open(F_CERT_INDEX).map_err(|_|())?;
|
||||
storage::BlockFile::<4096>::open(F_CERT_DATA).map_err(|_|())?;
|
||||
}
|
||||
|
||||
// Initialize media files.
|
||||
{
|
||||
storage::TrieFile::<8>::open(F_MEDIA_INDEX).map_err(|_|())?;
|
||||
storage::BlockFile::<4096>::open(F_MEDIA_DATA).map_err(|_|())?;
|
||||
}
|
||||
|
||||
fs::rename("data_tmp", "data").map_err(|_|())?;
|
||||
|
||||
|
@ -2,76 +2,69 @@ use crate::prelude::schema::*;
|
||||
|
||||
pub fn init() -> Result<(),()>
|
||||
{
|
||||
use szun::*;
|
||||
|
||||
type UserId = Block<4>;
|
||||
type RoleId = Block<4>;
|
||||
|
||||
type UserPublicKey = Block<8>;
|
||||
type UserPrivateKey = Block<16>;
|
||||
type Color = Block<3>;
|
||||
use suzu::szun::*;
|
||||
|
||||
{ // Net Interface
|
||||
Schema::build()
|
||||
.add_named::<Block<1>>("Protocol")
|
||||
.add_named::<Block<16>>("Interface")
|
||||
.add_named::<Block<2>>("Port")
|
||||
.add_named("Protocol", Block!(1))
|
||||
.add_named("Interface", Block!(16))
|
||||
.add_named("Port", Block!(2))
|
||||
.bind_key(SZ_NET_INTERFACE);
|
||||
}
|
||||
|
||||
{ // Admin Contact
|
||||
let sz_method = Schema::build()
|
||||
.add_named::<Sequence>("Title")
|
||||
.add_named::<Sequence>("Value")
|
||||
.add_named("Title", Sequence!())
|
||||
.add_named("Value", Sequence!())
|
||||
.bind();
|
||||
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Role")
|
||||
.add_named::<Sequence>("Name")
|
||||
.add_named::<Sequence>("Title")
|
||||
.add_named::<Sequence>("Organization")
|
||||
.add_dsr_named("Methods", Record::of(sz_method))
|
||||
.add_named("Role", Sequence!())
|
||||
.add_named("Name", Sequence!())
|
||||
.add_named("Title", Sequence!())
|
||||
.add_named("Organization", Sequence!())
|
||||
.add_named("Methods", Record!(sz_method))
|
||||
.bind_key(SZ_ADMIN_CONTACT);
|
||||
}
|
||||
|
||||
{ // Server
|
||||
let sz_config_network = Schema::build()
|
||||
.add_named::<List<RecordExt<SZ_NET_INTERFACE>>>("Services")
|
||||
.add_named("Services", List!(RecordKey!(SZ_NET_INTERFACE)))
|
||||
.bind();
|
||||
|
||||
let sz_config_upload = Schema::build()
|
||||
.add_named::<Natural>("MaxFileSize")
|
||||
.add_named("MaxFileSize", Natural!())
|
||||
.bind();
|
||||
|
||||
let sz_config = Schema::build()
|
||||
.add_dsr_named("Network", Record::of(sz_config_network))
|
||||
.add_dsr_named("Upload", Record::of(sz_config_upload))
|
||||
.add_named("Network", Record!(sz_config_network))
|
||||
.add_named("Upload", Record!(sz_config_upload))
|
||||
.bind();
|
||||
|
||||
// Server
|
||||
Schema::build()
|
||||
.add_named::<List<RecordExt<SZ_ADMIN_CONTACT>>>("Contact")
|
||||
.add_dsr_named("Config", Record::of(sz_config))
|
||||
.add_named("Contact", List!(RecordKey!(SZ_ADMIN_CONTACT)))
|
||||
.add_named("Config", Record!(sz_config))
|
||||
.bind_key(SZ_SERVER);
|
||||
}
|
||||
|
||||
{ // Session
|
||||
let sz_auth = Schema::build()
|
||||
.add_named::<Block<1>>("Type")
|
||||
.add_named("Type", Block!(1))
|
||||
.bind();
|
||||
|
||||
Schema::build()
|
||||
.add_named::<Block<8>>("PublicKey")
|
||||
.add_named::<Block<16>>("PrivateKey")
|
||||
.add_dsr_named("Authentication", Record::of(sz_auth))
|
||||
.add_named("PublicKey", Block!(8))
|
||||
.add_named("PrivateKey", Block!(16))
|
||||
.add_named("Authentication", Record!(sz_auth))
|
||||
.bind_key(SZ_SESSION);
|
||||
}
|
||||
|
||||
{ // Module
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Name")
|
||||
.add_named::<Sequence>("Executable")
|
||||
.add_named::<Schema>("Config")
|
||||
.add_named("Name", Sequence!())
|
||||
.add_named("Executable", Sequence!())
|
||||
.add_named("Config", Schema!())
|
||||
.bind_key(SZ_MODULE);
|
||||
}
|
||||
|
||||
@ -81,54 +74,54 @@ pub fn init() -> Result<(),()>
|
||||
.bind();
|
||||
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Name")
|
||||
.add_named::<List<RecordExt<SZ_ADMIN_CONTACT>>>("Contact")
|
||||
.add_dsr_named("Config", Record::of(sz_config))
|
||||
.add_named("Name", Sequence!())
|
||||
.add_named("Contact", List!(RecordKey!(SZ_ADMIN_CONTACT)))
|
||||
.add_named("Config", Record!(sz_config))
|
||||
.bind_key(SZ_DOMAIN);
|
||||
}
|
||||
|
||||
{ // District
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Name")
|
||||
.add_named("Name", Sequence!())
|
||||
.bind_key(SZ_DISTRICT);
|
||||
}
|
||||
|
||||
{ // Role
|
||||
let sz_custom = Schema::build()
|
||||
.add_named::<Optional<Color>>("Color")
|
||||
.add_named::<Optional<Schema>>("Data")
|
||||
.add_named("Color", Optional!(Block!(3)))
|
||||
.add_named("Data", Optional!(Schema!()))
|
||||
.bind();
|
||||
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Name")
|
||||
.add_named::<Sequence>("Privileges")
|
||||
.add_dsr_named("Custom", Record::of(sz_custom))
|
||||
.add_named("Name", Sequence!())
|
||||
.add_named("Privileges", Sequence!())
|
||||
.add_named("Custom", Record!(sz_custom))
|
||||
.bind_key(SZ_ROLE);
|
||||
}
|
||||
|
||||
{ // Privilege
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Name")
|
||||
.add_named::<Sequence>("Detail")
|
||||
.add_named("Name", Sequence!())
|
||||
.add_named("Detail", Sequence!())
|
||||
.bind_key(SZ_PRIVILEGE);
|
||||
}
|
||||
|
||||
{ // Compartment
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Name")
|
||||
.add_named::<Optional<Natural>>("Challenge")
|
||||
.add_named("Name", Sequence!())
|
||||
.add_named("Challenge", Optional!(Natural!()))
|
||||
.bind_key(SZ_COMPARTMENT);
|
||||
}
|
||||
|
||||
{ // User
|
||||
let sz_profile = Schema::build()
|
||||
.add_named::<Sequence>("DisplayName")
|
||||
.add_named("DisplayName", Sequence!())
|
||||
.bind();
|
||||
|
||||
let sz_security_roles = Schema::build()
|
||||
.add_named::<RoleId>("Role")
|
||||
.add_named::<Natural>("Compartment")
|
||||
.add_named::<Record>("Data")
|
||||
.add_named("Role", Block!(4))
|
||||
.add_named("Compartment", Natural!())
|
||||
.add_named("Data", Record!(0))
|
||||
.bind();
|
||||
|
||||
let sz_authentication = Schema::build()
|
||||
@ -136,26 +129,26 @@ pub fn init() -> Result<(),()>
|
||||
.bind();
|
||||
|
||||
let sz_security = Schema::build()
|
||||
.add_dsr_named("Roles", List::<Any>::of(Record::of(sz_security_roles)))
|
||||
.add_dsr_named("Authentication", Record::of(sz_authentication))
|
||||
.add_named::<List<RecordExt<SZ_COMPARTMENT>>>("Compartments")
|
||||
.add_named("Roles", List!(Record!(sz_security_roles)))
|
||||
.add_named("Authentication", Record!(sz_authentication))
|
||||
.add_named("Compartments", List!(RecordKey!(SZ_COMPARTMENT)))
|
||||
.bind();
|
||||
|
||||
Schema::build()
|
||||
.add_named::<Block<1>>("Type")
|
||||
.add_named::<UserPublicKey>("PublicKey")
|
||||
.add_named::<Sequence>("Handle")
|
||||
.add_dsr_named("Profile", Record::of(sz_profile))
|
||||
.add_dsr_named("Security", Record::of(sz_security))
|
||||
.add_named("Type", Block!(1))
|
||||
.add_named("PublicKey", Block!(8))
|
||||
.add_named("Handle", Sequence!())
|
||||
.add_named("Profile", Record!(sz_profile))
|
||||
.add_named("Security", Record!(sz_security))
|
||||
.bind_key(SZ_USER);
|
||||
|
||||
Schema::build()
|
||||
.add_named::<UserPrivateKey>("PrivateKey")
|
||||
.add_named("PrivateKey", Block!(16))
|
||||
//.add_named::<>("Secret")
|
||||
.bind_key(SZ_USER_LOCAL);
|
||||
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Domain")
|
||||
.add_named("Domain", Sequence!())
|
||||
.bind_key(SZ_USER_REMOTE);
|
||||
}
|
||||
|
||||
@ -173,22 +166,22 @@ pub fn init() -> Result<(),()>
|
||||
.bind_key(SZ_SOCIAL_FOLLOWER);
|
||||
|
||||
Schema::build()
|
||||
.add_named::<List<RecordExt<SZ_SOCIAL_CONTACT>>>("Contacts")
|
||||
.add_named::<List<RecordExt<SZ_SOCIAL_LIST>>>("Lists")
|
||||
.add_named::<List<RecordExt<SZ_SOCIAL_FOLLOW>>>("Follows")
|
||||
.add_named::<List<RecordExt<SZ_SOCIAL_FOLLOWER>>>("Followers")
|
||||
.add_named("Contacts", List!(RecordKey!(SZ_SOCIAL_CONTACT)))
|
||||
.add_named("Lists", List!(RecordKey!(SZ_SOCIAL_LIST)))
|
||||
.add_named("Follows", List!(RecordKey!(SZ_SOCIAL_FOLLOW)))
|
||||
.add_named("Followers", List!(RecordKey!(SZ_SOCIAL_FOLLOWER)))
|
||||
.bind_key(SZ_SOCIAL);
|
||||
}
|
||||
|
||||
{ // Feed
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Name")
|
||||
.add_named("Name", Sequence!())
|
||||
.bind_key(SZ_FEED);
|
||||
}
|
||||
|
||||
{ // Channel
|
||||
Schema::build()
|
||||
.add_named::<Sequence>("Channel")
|
||||
.add_named("Channel", Sequence!())
|
||||
.bind_key(SZ_CHANNEL);
|
||||
}
|
||||
|
||||
|
@ -5,15 +5,23 @@ mod system;
|
||||
mod protocol;
|
||||
mod init;
|
||||
|
||||
use suzu::szun::*;
|
||||
|
||||
pub struct Castle {
|
||||
|
||||
// Server Info
|
||||
// Domains
|
||||
}
|
||||
impl Castle {
|
||||
pub fn init() -> Result<Self,()>
|
||||
{
|
||||
// Prepare resources.
|
||||
init::szun::init()?;
|
||||
init::filesystem::init()?;
|
||||
|
||||
Err(())
|
||||
// Setup
|
||||
|
||||
Ok(Self {
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -6,3 +6,6 @@ edition = "2021"
|
||||
[dependencies]
|
||||
tokio = { version = "1.41.1", features = ["full"] }
|
||||
crossbeam = "0.8.4"
|
||||
|
||||
castle = { path = "../castle" }
|
||||
suzu = { git = "https://git.tsukiyo.org/Suzu/suzu" }
|
||||
|
93
server/res/config_default.suzu
Normal file
93
server/res/config_default.suzu
Normal file
@ -0,0 +1,93 @@
|
||||
##
|
||||
# Ryouiki Configuration
|
||||
#
|
||||
# Documentation: https://ryouiki.org/configure
|
||||
# Syntax: https://suzu.studio
|
||||
##
|
||||
|
||||
|
||||
##
|
||||
# Server Settings
|
||||
##
|
||||
|
||||
###
|
||||
Settings :{
|
||||
#
|
||||
}
|
||||
###
|
||||
|
||||
|
||||
##
|
||||
# Storage
|
||||
# ---
|
||||
# Defines storage locations and quotas.
|
||||
##
|
||||
|
||||
###
|
||||
Storage :{
|
||||
# Maximum byte size of uploaded media.
|
||||
`Upload Size`: 4MB
|
||||
|
||||
# Paths of data directories.
|
||||
`Location` :{
|
||||
Data: "data"
|
||||
Media: "media"
|
||||
}
|
||||
|
||||
# Specify which file types may be uploaded.
|
||||
`File Types` |=|MIME {
|
||||
| MIME | Allow |
|
||||
| `text/javascript` | false |
|
||||
| `text` | true |
|
||||
| `application/json` | true |
|
||||
| `application` | false |
|
||||
| `image` | true |
|
||||
| `audio` | false |
|
||||
| `video` | false |
|
||||
| any | false |
|
||||
}
|
||||
}
|
||||
###
|
||||
|
||||
##
|
||||
# Network Interfaces
|
||||
# ---
|
||||
# Defines how API endpoints are exposed to the network.
|
||||
##
|
||||
|
||||
Interface |=|INTERFACE {
|
||||
| Protocol | Interface | Port |
|
||||
|
||||
# Public Interfaces
|
||||
| Tls | Any | 38690 |
|
||||
| Https | Any | 38691 |
|
||||
|
||||
# Private Interfaces
|
||||
| Tcp | Local | 38695 |
|
||||
| Http | Local | 38696 |
|
||||
#| Rpc | Local | 38669 |
|
||||
}
|
||||
|
||||
##
|
||||
# Network Permissions
|
||||
# ---
|
||||
# Specifies permitted connections to the server.
|
||||
##
|
||||
Firewall |=|FIREWALL {
|
||||
| Access | Type | Value | Allow |
|
||||
#| Domain | Domain | "example.com" | false |
|
||||
#| Client | Addr | "127.0.0.1" | false |
|
||||
| Any | Any | none | true |
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Administrative Users
|
||||
# ---
|
||||
# List of users permitted to manage server and hosted domains.
|
||||
#
|
||||
# Usage: "handle@domain"
|
||||
##
|
||||
Admin :[
|
||||
#"admin@example.com"
|
||||
]
|
83
server/res/config_prelude.suzu
Normal file
83
server/res/config_prelude.suzu
Normal file
@ -0,0 +1,83 @@
|
||||
print "Ryouiki, Directory Communication Server"
|
||||
print "© 2024 Yukiri Corporation"
|
||||
|
||||
INTERFACE {
|
||||
Protocol :natural
|
||||
Interface :sequence
|
||||
Port :natural
|
||||
}
|
||||
|
||||
FIREWALL {
|
||||
Access :natural
|
||||
Type :natural
|
||||
Value :any
|
||||
Allow :boolean
|
||||
}
|
||||
|
||||
MIME {
|
||||
MIME :natural
|
||||
Allow :boolean
|
||||
}
|
||||
|
||||
@Interface {
|
||||
@Protocol {
|
||||
enum {
|
||||
Tls
|
||||
Tcp
|
||||
Https
|
||||
Http
|
||||
Rtc
|
||||
}
|
||||
}
|
||||
|
||||
@Interface {
|
||||
Any: "0.0.0.0"
|
||||
Local: "127.0.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@Firewall {
|
||||
enum {
|
||||
Any
|
||||
Client
|
||||
Domain
|
||||
Addr
|
||||
}
|
||||
}
|
||||
|
||||
###
|
||||
@Storage {
|
||||
@`File Types` {
|
||||
|=|{
|
||||
|+ |- |
|
||||
| any | "" |
|
||||
| `text` | "text" |
|
||||
| `text/plain` | "text/plain" |
|
||||
| `text/csv` | "text/csv" |
|
||||
| `text/html` | "text/html" |
|
||||
| `text/css` | "text/css" |
|
||||
| `text/javascript` | "text/javascript" |
|
||||
| `application` | "application" |
|
||||
| `application/json` | "application/json" |
|
||||
| `application/pdf` | "application/pdf" |
|
||||
| `application/msword` | "application/msword" |
|
||||
| `application/octet-stream` | "application/octet-stream" |
|
||||
| `image` | "image" |
|
||||
| `image/bmp` | "image/bmp" |
|
||||
| `image/jpeg` | "image/jpeg" |
|
||||
| `image/gif` | "image/gif" |
|
||||
| `image/png` | "image/png" |
|
||||
| `image/svg` | "image/svg" |
|
||||
| `image/webp` | "image/webp" |
|
||||
| `audio` | "audio" |
|
||||
| `audio/midi` | "audio/midi" |
|
||||
| `audio/mpeg` | "audio/mpeg" |
|
||||
| `audio/wav` | "audio/wav" |
|
||||
| `video` | "video" |
|
||||
| `video/mp4` | "video/mp4" |
|
||||
| `video/mpeg` | "video/mpeg" |
|
||||
| `video/webm` | "video/webm" |
|
||||
}
|
||||
}
|
||||
}
|
||||
###
|
4
server/src/config.rs
Normal file
4
server/src/config.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub const FILE :&str = "config.suzu";
|
||||
|
||||
pub const DEFINE :&str = include_str!("../res/config_prelude.suzu");
|
||||
pub const DEFAULT_TEXT :&str = include_str!("../res/config_default.suzu");
|
19
server/src/core/mod.rs
Normal file
19
server/src/core/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use tokio::sync::mpsc::{Sender, Receiver};
|
||||
|
||||
mod query; pub use query::{Query, QueryData};
|
||||
|
||||
pub async fn thread(
|
||||
_tx:Sender<Query>,
|
||||
mut rx:Receiver<Query>,
|
||||
)
|
||||
{
|
||||
while let Some(query) = rx.recv().await {
|
||||
|
||||
// Forward queries to relevant controllers.
|
||||
match query.data {
|
||||
|
||||
|
||||
QueryData::None => { }
|
||||
}
|
||||
}
|
||||
}
|
10
server/src/core/query.rs
Normal file
10
server/src/core/query.rs
Normal file
@ -0,0 +1,10 @@
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
pub struct Query {
|
||||
pub cb:Option<Sender<Query>>,
|
||||
pub data:QueryData,
|
||||
}
|
||||
|
||||
pub enum QueryData {
|
||||
None,
|
||||
}
|
4
server/src/init/mod.rs
Normal file
4
server/src/init/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub fn init() -> Result<(),()>
|
||||
{
|
||||
|
||||
}
|
@ -1,4 +1,83 @@
|
||||
#![allow(dead_code, unused_imports)]
|
||||
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use castle::Castle;
|
||||
use config::DEFAULT_TEXT;
|
||||
use suzu::szun;
|
||||
|
||||
mod system;
|
||||
mod core; use core::Query;
|
||||
|
||||
mod config;
|
||||
|
||||
mod protocol {
|
||||
pub const TLS :usize = 0;
|
||||
pub const TCP :usize = 1;
|
||||
pub const HTTPS :usize = 2;
|
||||
pub const HTTP :usize = 3;
|
||||
pub const RTC :usize = 4;
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
||||
// Check startup conditions.
|
||||
if !fs::exists(config::FILE).unwrap_or_default() {
|
||||
// Initialize file system and exit.
|
||||
if let Err(e) = fs::write(config::FILE, DEFAULT_TEXT) {
|
||||
println!("failed to create config file: {}", e.to_string());
|
||||
}
|
||||
return;
|
||||
} else if let Ok(config_text) = fs::read_to_string(config::FILE) {
|
||||
// Read configuration.
|
||||
|
||||
match load_config(config_text) {
|
||||
Ok(config) => {
|
||||
// Get configuration properties.
|
||||
if let Some(interfaces) = config.get_as::<szun::List>(&["Interface"]) {
|
||||
for i in 0..interfaces.len() {
|
||||
let inf = interfaces.get::<szun::Record>(i);
|
||||
let protocol = inf.find::<szun::Natural>("Protocol");
|
||||
let interface = inf.find::<szun::Sequence>("Interface").get_str();
|
||||
let port = inf.find::<szun::Natural>("Port").get::<u16>();
|
||||
|
||||
match protocol.get() {
|
||||
protocol::TLS => {
|
||||
println!("TLS {}:{}", interface, port);
|
||||
}
|
||||
protocol::TCP => {
|
||||
println!("TCP {}:{}", interface, port);
|
||||
}
|
||||
protocol::HTTPS => {
|
||||
println!("HTTPS {}:{}", interface, port);
|
||||
}
|
||||
protocol::HTTP => {
|
||||
println!("HTTP {}:{}", interface, port);
|
||||
}
|
||||
protocol::RTC => {
|
||||
println!("RTC {}:{}", interface, port);
|
||||
}
|
||||
_ => {
|
||||
println!("error: encountered unknown protocol");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => println!("{}", e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_config(config_text:String) -> Result<suzu::Suzu,suzu::Cause>
|
||||
{
|
||||
let mut config = suzu::Suzu::new();
|
||||
config.syscall("print", suzu::syscall::Print{});
|
||||
|
||||
config.load(config::DEFINE)?;
|
||||
config.load(&config_text)?;
|
||||
|
||||
config.run()?;
|
||||
Ok(config)
|
||||
}
|
||||
|
1
server/src/system/mod.rs
Normal file
1
server/src/system/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod net;
|
3
server/src/system/net/cert/mod.rs
Normal file
3
server/src/system/net/cert/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub struct CertStore {
|
||||
|
||||
}
|
7
server/src/system/net/mod.rs
Normal file
7
server/src/system/net/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
pub mod cert;
|
||||
pub mod tls;
|
||||
|
||||
trait Server {
|
||||
type Handle;
|
||||
fn handle(&self) -> Self::Handle;
|
||||
}
|
13
server/src/system/net/tls/mod.rs
Normal file
13
server/src/system/net/tls/mod.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use super::Server;
|
||||
|
||||
pub struct TlsServer {
|
||||
|
||||
}
|
||||
impl TlsServer {
|
||||
|
||||
}
|
||||
impl Server for TlsServer {
|
||||
type Handle = ();
|
||||
|
||||
fn handle(&self) -> Self::Handle { }
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user