started changing socket.rs to remove some buffers (not finished)
This commit is contained in:
parent
47e8ba586c
commit
4cb3736e56
@ -2,10 +2,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="/chat.js" defer></script>
|
||||
<style>
|
||||
#users_box {
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Chat</h1>
|
||||
<div id="users"></div>
|
||||
<div id="users_box">
|
||||
<h3>Online Users :</h3>
|
||||
<div id="users"></div>
|
||||
</div>
|
||||
<div id="msgs"></div>
|
||||
<form id="send">
|
||||
<input
|
||||
|
@ -26,7 +26,7 @@ ws.onmessage = (event) => {
|
||||
let elem = document.createElement("p");
|
||||
elem["data-id"] = msg.id;
|
||||
elem.innerHTML =
|
||||
"<span>" + users[msg.author] + " :</span> " + msg.content;
|
||||
"<strong>" + users[msg.author] + " :</strong> " + msg.content;
|
||||
for (c of msgs.children) {
|
||||
if (c["data-id"] > msg.id) {
|
||||
msgs.insertBefore(elem, c);
|
||||
|
276
src/socket.rs
276
src/socket.rs
@ -53,9 +53,137 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps:
|
||||
socket.remote_endpoint()
|
||||
);
|
||||
|
||||
let (mut rx, mut tx) = socket.split();
|
||||
let mut ws_path: Option<String<16>> = None;
|
||||
loop {
|
||||
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 {
|
||||
Ok(0) => {
|
||||
warn!("read EOF");
|
||||
@ -67,137 +195,6 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps:
|
||||
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 {
|
||||
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();
|
||||
res.extend_from_slice(&[0; 28]).unwrap();
|
||||
res.fill(0);
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(key.as_bytes());
|
||||
hasher.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||
let hash = hasher.finalize();
|
||||
BASE64_STANDARD.encode_slice(hash, &mut res)?;
|
||||
Ok(unwrap(String::from_utf8(res)).await)
|
||||
if let Err(e) = BASE64_STANDARD.encode_slice(hash, &mut res) {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user