3个版本
0.6.2 | 2024年8月6日 |
---|---|
0.6.1 | 2024年8月5日 |
0.6.0 | 2024年7月31日 |
#1441 in 网络编程
每月348次下载
1MB
29K SLoC
Discret:使用受GraphQL启发的API创建本地优先的点对点应用(P2P)
Discret隐藏了点对点网络的复杂性,将其简化为数据访问问题。
该API允许您
- 使用GraphQL语法管理您的数据
- 为您的数据添加访问权限(在GraphQL中也是如此)
- 创建和接受其他节点的邀请
Discret将根据您授予其他节点的访问权限同步您的数据
更多详细信息和使用教程可在文档网站中找到
示例
以下示例创建了一个非常基本的聊天应用。如果您在不同的文件夹或本地网络设备上构建并运行此程序,您应该能够与自己聊天。
use std::{io, path::PathBuf};
use discret::{
derive_pass_phrase, zero_uid, Configuration, Discret,
Parameters, ParametersAdd, ResultParser,
};
use serde::Deserialize;
//the application unique identifier
const APPLICATION_KEY: &str = "github.com/discretlib/rust_example_simple_chat";
#[tokio::main]
async fn main() {
//define a datamodel
let model = "chat {
Message{
content:String
}
}";
//this struct is used to parse the query result
#[derive(Deserialize)]
struct Chat {
pub id: String,
pub mdate: i64,
pub content: String,
}
let path: PathBuf = "test_data".into(); //where data is stored
//used to derives all necessary secrets
let key_material: [u8; 32] = derive_pass_phrase("my login", "my password");
//start the discret application
let app: Discret = Discret::new(
model,
APPLICATION_KEY,
&key_material,
path,
Configuration::default(),
)
.await
.unwrap();
//listen for events
let mut events = app.subscribe_for_events().await;
let event_app: Discret = app.clone();
tokio::spawn(async move {
let mut last_date = 0;
let mut last_id = zero_uid();
let private_room: String = event_app.private_room();
while let Ok(event) = events.recv().await {
match event {
//triggered when data is modified
discret::Event::DataChanged(_) => {
let mut param = Parameters::new();
param.add("mdate", last_date).unwrap();
param.add("id", last_id.clone()).unwrap();
param.add("room_id", private_room.clone()).unwrap();
//get the latest data, the result is in the JSON format
let result: String = event_app
.query(
"query {
res: chat.Message(
order_by(mdate asc, id asc),
after($mdate, $id),
room_id = $room_id
) {
id
mdate
content
}
}",
Some(param),
)
.await
.unwrap();
let mut query_result = ResultParser::new(&result).unwrap();
let res: Vec<Chat> = query_result.take_array("res").unwrap();
for msg in res {
last_date = msg.mdate;
last_id = msg.id;
println!("you said: {}", msg.content);
}
}
_ => {} //ignores other events
}
}
});
//data is inserted in your private room
let private_room: String = app.private_room();
let stdin = io::stdin();
let mut line = String::new();
println!("{}", "Write Something!");
loop {
stdin.read_line(&mut line).unwrap();
if line.starts_with("/q") {
break;
}
line.pop();
let mut params = Parameters::new();
params.add("message", line.clone()).unwrap();
params.add("room_id", private_room.clone()).unwrap();
app.mutate(
"mutate {
chat.Message {
room_id:$room_id
content: $message
}
}",
Some(params),
)
.await
.unwrap();
line.clear();
}
}
功能
Discret提供了一个阻塞(DiscretBlocking)和一个非阻塞(Discret)API。
在本地网络中,节点连接不需要服务器。对于互联网上的点对点连接,需要一个发现服务器以允许节点相互发现。Discret库提供了一个名为Beacon的发现服务器的实现。
该库提供了一组强大的安全功能
- 数据在SQLCipher数据库中加密存储
- 使用QUIC协议进行加密通信
- 数据完整性:每一行都使用节点签名密钥进行签名,使其难以同步不良数据
- 通过房间进行访问控制
限制
由于数据存储在您的设备上,Discret仅适用于生成“真实人类”数据的、最多有数百个节点的应用程序。它不适合大规模应用程序和拥有数千人的社区。
它目前仅支持文本数据,但计划支持文件同步。
互联网连接不保证100%正常工作,因为某些类型的商业防火墙将阻止连接尝试。
请小心,P2P连接会泄露您的IP地址,并且只能与受信任的节点一起使用。这种泄露使您面临以下威胁
- 分布式拒绝服务(DDoS)
- 通过地理位置服务泄露您的“现实世界”位置。
- 国家支持的监视:监视网络的机构可以确定哪些节点连接到哪些节点,从而获得大量关于您社交网络的知识。
平台支持
- Linux:已测试
- Windows: 已测试
- macOS: 未测试,应能工作
- Android: 在 arch64 架构上工作。i686 和 x86_64 架构与 Flutter 一起使用时存在一些低级链接器问题。
- iOS: 未测试
依赖项
~44–77MB
~1.5M SLoC