started changing socket.rs to remove some buffers (not finished)
This commit is contained in:
parent
47e8ba586c
commit
4cb3736e56
@ -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
|
||||||
|
@ -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);
|
||||||
|
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()
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user