Update to use suzu library; update documentation.

This commit is contained in:
yukirij 2025-03-27 00:59:29 -07:00
parent 620abbf89f
commit 13308a0afd
31 changed files with 780 additions and 164 deletions

0
.cargo/config.toml Normal file
View File

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
/target
Cargo.lock
/config.suzu
/data

View File

@ -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" }

View 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
#
}
```

View 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 {
}
```

View 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"
]
```

View File

@ -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`

View 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>
}
```

View File

@ -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>
}
```

View 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"
}
]
```

View 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>;
```

View File

@ -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
}
```

View 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.

View File

@ -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

View File

@ -15,3 +15,14 @@ struct Participant {
user:usize,
}
```
# Content
## Text
## Audio
## Video
## File

View 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
}##
}
```

View File

@ -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(|_|())?;

View File

@ -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);
}

View File

@ -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 {
})
}
}

View File

@ -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" }

View 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"
]

View 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
View 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
View 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
View 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
View File

@ -0,0 +1,4 @@
pub fn init() -> Result<(),()>
{
}

View File

@ -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
View File

@ -0,0 +1 @@
pub mod net;

View File

@ -0,0 +1,3 @@
pub struct CertStore {
}

View File

@ -0,0 +1,7 @@
pub mod cert;
pub mod tls;
trait Server {
type Handle;
fn handle(&self) -> Self::Handle;
}

View File

@ -0,0 +1,13 @@
use super::Server;
pub struct TlsServer {
}
impl TlsServer {
}
impl Server for TlsServer {
type Handle = ();
fn handle(&self) -> Self::Handle { }
}