mirror of
https://github.com/chirpstack/chirpstack.git
synced 2025-06-17 14:58:15 +00:00
@ -298,6 +298,16 @@ pub fn run() {
|
|||||||
tls_key="{{ integration.mqtt.tls_key }}"
|
tls_key="{{ integration.mqtt.tls_key }}"
|
||||||
|
|
||||||
|
|
||||||
|
# Codec configuration.
|
||||||
|
[codec]
|
||||||
|
|
||||||
|
# JS codec configuration.
|
||||||
|
[codec.js]
|
||||||
|
|
||||||
|
# Maximum execution time.
|
||||||
|
max_execution_time="{{ codec.js.max_execution_time }}"
|
||||||
|
|
||||||
|
|
||||||
# User authentication configuration.
|
# User authentication configuration.
|
||||||
[user_authentication]
|
[user_authentication]
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rquickjs::IntoJs;
|
use rquickjs::IntoJs;
|
||||||
|
|
||||||
use super::convert;
|
use super::convert;
|
||||||
|
use crate::config;
|
||||||
|
|
||||||
pub async fn decode(
|
pub async fn decode(
|
||||||
f_port: u8,
|
f_port: u8,
|
||||||
@ -11,7 +13,12 @@ pub async fn decode(
|
|||||||
decode_config: &str,
|
decode_config: &str,
|
||||||
b: &[u8],
|
b: &[u8],
|
||||||
) -> Result<pbjson_types::Struct> {
|
) -> Result<pbjson_types::Struct> {
|
||||||
|
let conf = config::get();
|
||||||
|
let max_run_ts = SystemTime::now() + conf.codec.js.max_execution_time;
|
||||||
|
|
||||||
let rt = rquickjs::Runtime::new().unwrap();
|
let rt = rquickjs::Runtime::new().unwrap();
|
||||||
|
rt.set_interrupt_handler(Some(Box::new(move || SystemTime::now() > max_run_ts)));
|
||||||
|
|
||||||
let ctx = rquickjs::Context::full(&rt).unwrap();
|
let ctx = rquickjs::Context::full(&rt).unwrap();
|
||||||
|
|
||||||
let script = decode_config.to_string();
|
let script = decode_config.to_string();
|
||||||
@ -28,7 +35,7 @@ pub async fn decode(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
input.set("data", b.into_js(ctx).unwrap()).unwrap();
|
input.set("data", b.into_js(ctx).unwrap()).unwrap();
|
||||||
|
|
||||||
let res: rquickjs::Object = func.call((input,)).unwrap();
|
let res: rquickjs::Object = func.call((input,))?;
|
||||||
Ok(convert::rquickjs_to_struct(&res))
|
Ok(convert::rquickjs_to_struct(&res))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -39,7 +46,12 @@ pub async fn encode(
|
|||||||
encode_config: &str,
|
encode_config: &str,
|
||||||
s: &prost_types::Struct,
|
s: &prost_types::Struct,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
|
let conf = config::get();
|
||||||
|
let max_run_ts = SystemTime::now() + conf.codec.js.max_execution_time;
|
||||||
|
|
||||||
let rt = rquickjs::Runtime::new().unwrap();
|
let rt = rquickjs::Runtime::new().unwrap();
|
||||||
|
rt.set_interrupt_handler(Some(Box::new(move || SystemTime::now() > max_run_ts)));
|
||||||
|
|
||||||
let ctx = rquickjs::Context::full(&rt).unwrap();
|
let ctx = rquickjs::Context::full(&rt).unwrap();
|
||||||
|
|
||||||
let script = encode_config.to_string();
|
let script = encode_config.to_string();
|
||||||
@ -57,7 +69,7 @@ pub async fn encode(
|
|||||||
.set("object", convert::struct_to_rquickjs(ctx, s))
|
.set("object", convert::struct_to_rquickjs(ctx, s))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let res: Vec<u8> = func.call((input,)).unwrap();
|
let res: Vec<u8> = func.call((input,))?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -66,6 +78,22 @@ pub async fn encode(
|
|||||||
pub mod test {
|
pub mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
pub async fn test_decode_timeout() {
|
||||||
|
let decoder = r#"
|
||||||
|
export function Decode(input) {
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let vars: HashMap<String, String> = HashMap::new();
|
||||||
|
let out = decode(10, &vars, &decoder, &[0x01, 0x02, 0x03]).await;
|
||||||
|
assert!(out.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
pub async fn test_decode() {
|
pub async fn test_decode() {
|
||||||
let decoder = r#"
|
let decoder = r#"
|
||||||
@ -143,6 +171,27 @@ pub mod test {
|
|||||||
assert_eq!(expected, out);
|
assert_eq!(expected, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
pub async fn test_encode_timeout() {
|
||||||
|
let encoder = r#"
|
||||||
|
export function Encode(input) {
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let vars: HashMap<String, String> = HashMap::new();
|
||||||
|
|
||||||
|
let input = prost_types::Struct {
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let out = encode(10, &vars, &encoder, &input).await;
|
||||||
|
assert!(out.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
pub async fn test_encode() {
|
pub async fn test_encode() {
|
||||||
let encoder = r#"
|
let encoder = r#"
|
||||||
|
@ -24,6 +24,7 @@ pub struct Configuration {
|
|||||||
pub network: Network,
|
pub network: Network,
|
||||||
pub monitoring: Monitoring,
|
pub monitoring: Monitoring,
|
||||||
pub integration: Integration,
|
pub integration: Integration,
|
||||||
|
pub codec: Codec,
|
||||||
pub user_authentication: UserAuthentication,
|
pub user_authentication: UserAuthentication,
|
||||||
pub join_server: JoinServer,
|
pub join_server: JoinServer,
|
||||||
pub keks: Vec<Kek>,
|
pub keks: Vec<Kek>,
|
||||||
@ -41,6 +42,7 @@ impl Default for Configuration {
|
|||||||
network: Default::default(),
|
network: Default::default(),
|
||||||
monitoring: Default::default(),
|
monitoring: Default::default(),
|
||||||
integration: Default::default(),
|
integration: Default::default(),
|
||||||
|
codec: Default::default(),
|
||||||
user_authentication: Default::default(),
|
user_authentication: Default::default(),
|
||||||
join_server: Default::default(),
|
join_server: Default::default(),
|
||||||
keks: Vec::new(),
|
keks: Vec::new(),
|
||||||
@ -293,6 +295,27 @@ impl Default for MqttIntegrationClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Default)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct Codec {
|
||||||
|
pub js: CodecJs,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct CodecJs {
|
||||||
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub max_execution_time: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CodecJs {
|
||||||
|
fn default() -> Self {
|
||||||
|
CodecJs {
|
||||||
|
max_execution_time: Duration::from_millis(100),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Default)]
|
#[derive(Serialize, Deserialize, Clone, Default)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct UserAuthentication {
|
pub struct UserAuthentication {
|
||||||
|
Reference in New Issue
Block a user