Add support for handling HomeNSReq requests.

In this case, we return the (primary) NetID of the ChirpStack instance.
Supporting the HomeNSReq is useful in the case the roaming ChirpStack
instances are setup to resolve the servers using DNS. In case of OTAA,
the fNS resolves the JoinEUI to a hostname to which it must make the
HomeNSReq. This returns the HNetID, which then can be used to resolve
the hostname of the hNS to which the join-request must be forwarded.
This commit is contained in:
Orne Brocaar 2024-05-07 15:51:05 +01:00
parent 26832f3a5f
commit 99dbefdfec
3 changed files with 111 additions and 0 deletions

View File

@ -252,6 +252,10 @@ impl Client {
Ok(ans)
}
pub async fn home_ns_ans(&self, target_role: Role, pl: &HomeNSAnsPayload) -> Result<()> {
self.response_request(Some(target_role), pl).await
}
pub async fn xmit_data_req(
&self,
target_role: Role,

View File

@ -163,6 +163,7 @@ pub async fn _handle_request(bp: BasePayload, b: Vec<u8>) -> http::Response<hype
MessageType::PRStartReq => handle_pr_start_req(sender_client, bp, &b).await,
MessageType::PRStopReq => handle_pr_stop_req(sender_client, bp, &b).await,
MessageType::XmitDataReq => handle_xmit_data_req(sender_client, bp, &b).await,
MessageType::HomeNSReq => handle_home_ns_req(sender_client, bp, &b).await,
// Unknown message
_ => warp::reply::with_status(
"Handler for {:?} is not implemented",
@ -523,6 +524,68 @@ async fn _handle_xmit_data_req(
})
}
async fn handle_home_ns_req(
sender_client: Arc<backend::Client>,
bp: backend::BasePayload,
b: &[u8],
) -> http::Response<hyper::Body> {
let pl: backend::HomeNSReqPayload = match serde_json::from_slice(b) {
Ok(v) => v,
Err(e) => {
let ans = err_to_response(anyhow::Error::new(e), &bp);
log_request_response(&bp, b, &ans).await;
return warp::reply::json(&ans).into_response();
}
};
if sender_client.is_async() {
let b = b.to_vec();
task::spawn(async move {
let ans = match _handle_home_ns_req(pl).await {
Ok(v) => v,
Err(e) => {
let msg = e.to_string();
backend::HomeNSAnsPayload {
base: bp.to_base_payload_result(err_to_result_code(e), &msg),
h_net_id: Vec::new(),
}
}
};
log_request_response(&bp, &b, &ans).await;
if let Err(e) = sender_client.home_ns_ans(backend::Role::FNS, &ans).await {
error!(error = %e.full(), "Send async HomeNSAns error");
}
});
warp::reply::with_status("", StatusCode::OK).into_response()
} else {
match _handle_home_ns_req(pl).await {
Ok(ans) => {
log_request_response(&bp, b, &ans).await;
warp::reply::json(&ans).into_response()
}
Err(e) => {
let ans = err_to_response(e, &bp);
log_request_response(&bp, b, &ans).await;
warp::reply::json(&ans).into_response()
}
}
}
}
async fn _handle_home_ns_req(pl: backend::HomeNSReqPayload) -> Result<backend::HomeNSAnsPayload> {
let conf = config::get();
Ok(backend::HomeNSAnsPayload {
base: pl
.base
.to_base_payload_result(backend::ResultCode::Success, ""),
h_net_id: conf.network.net_id.to_vec(),
})
}
async fn handle_async_ans(bp: &BasePayload, b: &[u8]) -> Result<http::Response<hyper::Body>> {
let transaction_id = bp.transaction_id;

View File

@ -785,6 +785,50 @@ pub fn run() {
# Resolve NetID domain suffix.
resolve_net_id_domain_suffix="{{ backend_interfaces.resolve_net_id_domain_suffix }}"
# Default roaming server.
[roaming.default]
# Enable default roaming server.
enabled={{roaming.default.enabled}}
# Async timeout (set to 0 to disable async interface).
async_timeout="{{roaming.default.async_timeout}}"
# Passive-roaming session lifetime (set to 0 for stateless).
passive_roaming_lifetime="{{roaming.default.passive_roaming_lifetime}}"
# Passive-roaming KEK label (optional).
#
# If set, the session-keys will be encrypted using the given KEK.
passive_roaming_kek_label="{{roaming.default.passive_roaming_kek_label}}"
# Server.
#
# If set, this will bypass the DNS resolving of the server.
server="{{roaming.default.server}}"
# Use target role suffix.
#
# Depending the context of the remote server, this will add
# the /sns or /fns path to the server endpoint.
use_target_role_suffix={{roaming.default.use_target_role_suffix}}
# CA certificate (path).
ca_cert="{{roaming.default.ca_cert}}"
# TLS certificate (path).
tls_cert="{{roaming.default.tls_cert}}"
# TLS key (PKCS#8) (path).
tls_key="{{roaming.default.tls_key}}"
# Authorization header.
#
# Optional value of the Authorization header, e.g. token or password.
authorization_header="{{roaming.default.authorization_header}}"
# Per server roaming configuration (this can be repeated).
# Example:
# [[roaming.servers]]