started changing socket.rs to remove some buffers (not finished)

This commit is contained in:
Arkitu 2025-08-23 09:20:12 +02:00
parent 47e8ba586c
commit 4cb3736e56
3 changed files with 151 additions and 137 deletions

View File

@ -2,10 +2,18 @@
<html> <html>
<head> <head>
<script src="/chat.js" defer></script> <script src="/chat.js" defer></script>
<style>
#users_box {
float: right;
}
</style>
</head> </head>
<body> <body>
<h1>Chat</h1> <h1>Chat</h1>
<div id="users"></div> <div id="users_box">
<h3>Online Users :</h3>
<div id="users"></div>
</div>
<div id="msgs"></div> <div id="msgs"></div>
<form id="send"> <form id="send">
<input <input

View File

@ -26,7 +26,7 @@ ws.onmessage = (event) => {
let elem = document.createElement("p"); let elem = document.createElement("p");
elem["data-id"] = msg.id; elem["data-id"] = msg.id;
elem.innerHTML = elem.innerHTML =
"<span>" + users[msg.author] + " :</span> " + msg.content; "<strong>" + users[msg.author] + " :</strong> " + msg.content;
for (c of msgs.children) { for (c of msgs.children) {
if (c["data-id"] > msg.id) { if (c["data-id"] > msg.id) {
msgs.insertBefore(elem, c); msgs.insertBefore(elem, c);

View File

@ -53,9 +53,137 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps:
socket.remote_endpoint() socket.remote_endpoint()
); );
let (mut rx, mut tx) = socket.split();
let mut ws_path: Option<String<16>> = None; let mut ws_path: Option<String<16>> = None;
loop { loop {
Timer::after_secs(0).await; Timer::after_secs(0).await;
let mut cont = &[];
rx.read_with(|msg| {
let (headers, content) = match from_utf8(msg) {
Ok(b) => match b.split_once("\r\n\r\n") {
Some(t) => t,
None => (b, ""),
},
Err(_) => {
warn!("Non utf8 http request");
return (0, Err(()));
}
};
let mut hl = headers.lines();
let (request_type, path) = match hl.next() {
None => {
warn!("Empty request");
return (0, Err(()));
}
Some(l1) => {
let mut l1 = l1.split(' ');
(
match l1.next() {
Some("GET") => HttpRequestType::Get,
Some("POST") => HttpRequestType::Post,
Some(t) => {
warn!("Unknown request type : {}", t);
return (0, Err(()));
}
None => {
warn!("No request type");
return (0, Err(()));
}
},
match l1.next() {
Some(path) => path,
None => {
warn!("No path");
return (0, Err(()));
}
},
)
}
};
let mut host = None;
let mut ws_handshake = false;
let mut ws_key = None;
for h in hl {
let Some((name, val)) = h.split_once(':') else {
continue;
};
let name = name.trim();
let val = val.trim();
match (name, val) {
("Host", _) => host = Some(val),
("Upgrade", "websocket") => ws_handshake = true,
("Sec-WebSocket-Key", _) => ws_key = Some(val),
_ => {}
}
}
let Some(host) = host else {
warn!("No host");
return (0, Err(()));
};
info!(
"Socket {}: {:?}{} request for {}{}",
app.socket_name(),
request_type,
if ws_handshake { " websocket" } else { "" },
host,
path,
);
head_buf.clear();
let res_content: Result<Option<Content>, core::fmt::Error> = try {
if ws_handshake {
if !app.accept_ws(path) {
warn!("No ws there!");
write!(
&mut head_buf,
"{}\r\n\r\n",
Into::<&str>::into(HttpResCode::NotFound)
)?;
None
} else {
if path.len() > 16 {
warn!("Ws socket cannot have path longer than 16 chars!");
return (0, Err(()));
}
let Some(key) = ws_key else {
warn!("No ws key!");
return (0, Err(()));
};
let Ok(accept) = compute_ws_accept(key) else {
return (0, Err(()));
};
write!(
&mut head_buf,
"{}\r\n\
Upgrade: websocket\r\n\
Connection: Upgrade\r\n\
Sec-WebSocket-Accept: {}\r\n\r\n",
Into::<&str>::into(HttpResCode::SwitchingProtocols),
accept
)?;
None
}
} else {
let (code, res_type, res_content) =
app.handle_request(path, request_type, content).await;
write!(&mut head_buf, "{}", Into::<&str>::into(code))?;
if let Some(ref c) = res_content {
write!(
&mut head_buf,
"\r\n\
Content-Type: text/{}\r\n\
Content-Length: {}\r\n",
res_type,
c.len()
)?;
}
write!(&mut head_buf, "\r\n\r\n")?;
res_content
}
};
(msg.len(), Ok(()))
})
.await;
let n = match socket.read(&mut buf).await { let n = match socket.read(&mut buf).await {
Ok(0) => { Ok(0) => {
warn!("read EOF"); warn!("read EOF");
@ -67,137 +195,6 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps:
break; break;
} }
}; };
head_buf.clear();
let msg = unwrap_opt(buf.get(..n)).await;
let (headers, content) = match from_utf8(msg) {
Ok(b) => match b.split_once("\r\n\r\n") {
Some(t) => t,
None => (b, ""),
},
Err(_) => {
warn!("Non utf8 http request");
break;
}
};
let mut hl = headers.lines();
let (request_type, path) = match hl.next() {
None => {
warn!("Empty request");
break;
}
Some(l1) => {
let mut l1 = l1.split(' ');
(
match l1.next() {
Some("GET") => HttpRequestType::Get,
Some("POST") => HttpRequestType::Post,
Some(t) => {
warn!("Unknown request type : {}", t);
break;
}
None => {
warn!("No request type");
break;
}
},
match l1.next() {
Some(path) => path,
None => {
warn!("No path");
break;
}
},
)
}
};
let mut host = None;
let mut ws_handshake = false;
let mut ws_key = None;
for h in hl {
let Some((name, val)) = h.split_once(':') else {
continue;
};
let name = name.trim();
let val = val.trim();
match (name, val) {
("Host", _) => host = Some(val),
("Upgrade", "websocket") => ws_handshake = true,
("Sec-WebSocket-Key", _) => ws_key = Some(val),
_ => {}
}
}
let Some(host) = host else {
warn!("No host");
break;
};
info!(
"Socket {}: {:?}{} request for {}{}",
app.socket_name(),
request_type,
if ws_handshake { " websocket" } else { "" },
host,
path,
);
head_buf.clear();
let res_content: Result<Option<Content>, core::fmt::Error> = try {
if ws_handshake {
if !app.accept_ws(path) {
warn!("No ws there!");
write!(
&mut head_buf,
"{}\r\n\r\n",
Into::<&str>::into(HttpResCode::NotFound)
)?;
None
} else {
if path.len() > 16 {
warn!("Ws socket cannot have path longer than 16 chars!");
break;
}
let Some(key) = ws_key else {
warn!("No ws key!");
break;
};
let accept = match compute_ws_accept(key).await {
Ok(a) => a,
Err(e) => {
warn!("compute ws accept error : {:?}", e);
break;
}
};
write!(
&mut head_buf,
"{}\r\n\
Upgrade: websocket\r\n\
Connection: Upgrade\r\n\
Sec-WebSocket-Accept: {}\r\n\r\n",
Into::<&str>::into(HttpResCode::SwitchingProtocols),
accept
)?;
None
}
} else {
let (code, res_type, res_content) =
app.handle_request(path, request_type, content).await;
write!(&mut head_buf, "{}", Into::<&str>::into(code))?;
if let Some(ref c) = res_content {
write!(
&mut head_buf,
"\r\n\
Content-Type: text/{}\r\n\
Content-Length: {}\r\n",
res_type,
c.len()
)?;
}
write!(&mut head_buf, "\r\n\r\n")?;
res_content
}
};
let res_content = match res_content { let res_content = match res_content {
Ok(rc) => rc, Ok(rc) => rc,
@ -269,13 +266,22 @@ impl Into<&str> for HttpResCode {
} }
} }
async fn compute_ws_accept(key: &str) -> Result<String<28>, EncodeSliceError> { fn compute_ws_accept(key: &str) -> Result<String<28>, ()> {
let mut res = Vec::<u8, 28>::new(); let mut res = Vec::<u8, 28>::new();
res.extend_from_slice(&[0; 28]).unwrap(); res.fill(0);
let mut hasher = Sha1::new(); let mut hasher = Sha1::new();
hasher.update(key.as_bytes()); hasher.update(key.as_bytes());
hasher.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); hasher.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
let hash = hasher.finalize(); let hash = hasher.finalize();
BASE64_STANDARD.encode_slice(hash, &mut res)?; if let Err(e) = BASE64_STANDARD.encode_slice(hash, &mut res) {
Ok(unwrap(String::from_utf8(res)).await) warn!("Error while base64 encoding : {}", e);
return Err(());
};
match String::from_utf8(res) {
Ok(r) => Ok(r),
Err(e) => {
warn!("Ws accept is not utf8! ({})", e);
Err(())
}
}
} }