mirror of
https://github.com/Mercantec-GHC/h5-projekt-mst.git
synced 2026-08-27 05:37:39 +02:00
connect server to game
This commit is contained in:
parent
1a6a59bc6f
commit
ace572d6c1
@ -31,25 +31,17 @@ int main(void)
|
|||||||
auto mqtt_client = mst::mqtt::Client(
|
auto mqtt_client = mst::mqtt::Client(
|
||||||
BACKEND_MQTT_HOST, BACKEND_MQTT_PORT, "test", "1234");
|
BACKEND_MQTT_HOST, BACKEND_MQTT_PORT, "test", "1234");
|
||||||
|
|
||||||
|
auto server = mst::server2::Server();
|
||||||
|
|
||||||
mqtt_client.subscribe("/skateboard/update", [&](std::string_view text) {
|
mqtt_client.subscribe("/skateboard/update", [&](std::string_view text) {
|
||||||
//
|
std::println("Skateboard sent: {}", text);
|
||||||
// std::println("Skateboard: {}", text);
|
try {
|
||||||
// auto result = mst::json::parse(text);
|
auto parsed = *mst::json::parse(text);
|
||||||
//
|
auto angle = parsed->query(".rotation").value()->get_f64();
|
||||||
// if (!result) {
|
server.notify_subscribers(angle);
|
||||||
// std::println(stderr,
|
} catch (std::runtime_error& ex) {
|
||||||
// "error: {} at {}",
|
std::println(stderr, "exception: {}", ex.what());
|
||||||
// result.error().message,
|
}
|
||||||
// result.error().loc.idx);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// try {
|
|
||||||
// auto parsed = std::move(result.value());
|
|
||||||
// std::println(".rotation = {}",
|
|
||||||
// parsed->query(".rotation").value()->get_f64());
|
|
||||||
// } catch (std::runtime_error& ex) {
|
|
||||||
// std::println(stderr, "exception: {}", ex.what());
|
|
||||||
// }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto mqtt_thread = std::thread([&]() {
|
auto mqtt_thread = std::thread([&]() {
|
||||||
@ -72,7 +64,6 @@ int main(void)
|
|||||||
// auto x = mgr.start();
|
// auto x = mgr.start();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
auto server = mst::server2::Server();
|
|
||||||
server.listen();
|
server.listen();
|
||||||
|
|
||||||
mqtt_thread.join();
|
mqtt_thread.join();
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <mutex>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <print>
|
#include <print>
|
||||||
@ -17,6 +18,18 @@
|
|||||||
namespace {
|
namespace {
|
||||||
using namespace mst::server2;
|
using namespace mst::server2;
|
||||||
|
|
||||||
|
struct ReqHeader {
|
||||||
|
enum ReqTy {
|
||||||
|
Subscribe = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
ReqTy ty;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Measurement {
|
||||||
|
double angle;
|
||||||
|
};
|
||||||
|
|
||||||
auto get_listener_socket() -> int
|
auto get_listener_socket() -> int
|
||||||
{
|
{
|
||||||
int listener; // Listening socket descriptor
|
int listener; // Listening socket descriptor
|
||||||
@ -29,7 +42,7 @@ auto get_listener_socket() -> int
|
|||||||
|
|
||||||
struct addrinfo* addr;
|
struct addrinfo* addr;
|
||||||
|
|
||||||
if ((status = ::getaddrinfo(NULL, "8881", &hints, &addr)) != 0)
|
if ((status = ::getaddrinfo(NULL, "8889", &hints, &addr)) != 0)
|
||||||
throw Error(std::format("getaddrinfo ({})", ::gai_strerror(status)));
|
throw Error(std::format("getaddrinfo ({})", ::gai_strerror(status)));
|
||||||
|
|
||||||
struct addrinfo* p;
|
struct addrinfo* p;
|
||||||
@ -67,9 +80,11 @@ auto get_listener_socket() -> int
|
|||||||
namespace mst::server2 {
|
namespace mst::server2 {
|
||||||
|
|
||||||
struct Server::State {
|
struct Server::State {
|
||||||
|
std::mutex mx;
|
||||||
std::vector<::pollfd> pollfds;
|
std::vector<::pollfd> pollfds;
|
||||||
std::vector<::pollfd> queued_insertions;
|
|
||||||
std::vector<std::size_t> queued_deletions;
|
std::vector<std::size_t> queued_deletions;
|
||||||
|
|
||||||
|
std::vector<int> subscriber_fds;
|
||||||
};
|
};
|
||||||
|
|
||||||
Server::Server()
|
Server::Server()
|
||||||
@ -90,12 +105,16 @@ void Server::listen()
|
|||||||
std::println("[mst::server2] listening for connections");
|
std::println("[mst::server2] listening for connections");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
std::println(
|
||||||
|
"[mst::server2] polling on {} fds", m_state->pollfds.size());
|
||||||
int poll_count
|
int poll_count
|
||||||
= ::poll(m_state->pollfds.data(), m_state->pollfds.size(), -1);
|
= ::poll(m_state->pollfds.data(), m_state->pollfds.size(), -1);
|
||||||
|
|
||||||
if (poll_count == -1)
|
if (poll_count == -1)
|
||||||
throw Error(std::format("poll (%s)", strerror(errno)));
|
throw Error(std::format("poll (%s)", strerror(errno)));
|
||||||
|
|
||||||
|
auto lock = std::lock_guard(m_state->mx);
|
||||||
|
|
||||||
for (size_t i = 0; i < m_state->pollfds.size(); ++i) {
|
for (size_t i = 0; i < m_state->pollfds.size(); ++i) {
|
||||||
auto& fd = m_state->pollfds[i];
|
auto& fd = m_state->pollfds[i];
|
||||||
if (!(fd.revents & (POLLIN | POLLHUP)))
|
if (!(fd.revents & (POLLIN | POLLHUP)))
|
||||||
@ -118,17 +137,41 @@ void Server::listen()
|
|||||||
|
|
||||||
auto& fds = m_state->pollfds;
|
auto& fds = m_state->pollfds;
|
||||||
auto& deletions = m_state->queued_deletions;
|
auto& deletions = m_state->queued_deletions;
|
||||||
|
auto& subs = m_state->subscriber_fds;
|
||||||
|
|
||||||
std::reverse(deletions.begin(), deletions.end());
|
std::reverse(deletions.begin(), deletions.end());
|
||||||
for (auto idx : deletions) {
|
for (auto idx : deletions) {
|
||||||
|
|
||||||
|
// hack to delete subscriber fds. subscribers should be handled
|
||||||
|
// in a better way.
|
||||||
|
for (auto iter = subs.begin(); iter != subs.end(); ++iter) {
|
||||||
|
if (fds[idx].fd == *iter) {
|
||||||
|
subs.erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::println("deleting {}", idx);
|
||||||
fds.erase(std::next(fds.begin(), static_cast<long>(idx)));
|
fds.erase(std::next(fds.begin(), static_cast<long>(idx)));
|
||||||
}
|
}
|
||||||
m_state->queued_deletions.clear();
|
m_state->queued_deletions.clear();
|
||||||
|
|
||||||
for (auto& fd : m_state->queued_insertions) {
|
|
||||||
m_state->pollfds.push_back(fd);
|
|
||||||
}
|
}
|
||||||
m_state->queued_insertions.clear();
|
}
|
||||||
|
|
||||||
|
void Server::notify_subscribers(double angle)
|
||||||
|
{
|
||||||
|
auto m = Measurement { angle };
|
||||||
|
|
||||||
|
auto lock = std::lock_guard(m_state->mx);
|
||||||
|
|
||||||
|
for (auto& fd : m_state->subscriber_fds) {
|
||||||
|
if (fd == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ssize_t bytes_send = ::send(fd, &m, sizeof(m), 0);
|
||||||
|
|
||||||
|
if (bytes_send == -1)
|
||||||
|
fd = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +188,7 @@ void Server::create_connection()
|
|||||||
|
|
||||||
std::println("[mst::server2] client {} connected", client_fd);
|
std::println("[mst::server2] client {} connected", client_fd);
|
||||||
|
|
||||||
m_state->queued_insertions.push_back(::pollfd {
|
m_state->pollfds.push_back(::pollfd {
|
||||||
.fd = client_fd,
|
.fd = client_fd,
|
||||||
.events = POLLIN,
|
.events = POLLIN,
|
||||||
.revents = { },
|
.revents = { },
|
||||||
@ -155,11 +198,12 @@ void Server::create_connection()
|
|||||||
void Server::handle_request(size_t i)
|
void Server::handle_request(size_t i)
|
||||||
{
|
{
|
||||||
auto& client_fd = m_state->pollfds[i].fd;
|
auto& client_fd = m_state->pollfds[i].fd;
|
||||||
auto buffer = std::vector<char>(512);
|
auto header = ReqHeader { };
|
||||||
|
|
||||||
ssize_t byte_count = ::recv(client_fd, buffer.data(), buffer.size(), 0);
|
std::println("[mst::server2] waiting to receive", client_fd);
|
||||||
|
ssize_t byte_count = ::recv(client_fd, &header, sizeof(header), 0);
|
||||||
|
|
||||||
if (byte_count <= 0)
|
if (byte_count < 0)
|
||||||
throw Error(std::format("recv: {}", strerror(errno)));
|
throw Error(std::format("recv: {}", strerror(errno)));
|
||||||
|
|
||||||
if (byte_count == 0) {
|
if (byte_count == 0) {
|
||||||
@ -169,7 +213,17 @@ void Server::handle_request(size_t i)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::println("[mst::server2] received: {:s}", buffer);
|
if (byte_count != sizeof(header))
|
||||||
|
throw Error(std::format("invalid request"));
|
||||||
|
|
||||||
|
switch (header.ty) {
|
||||||
|
case ReqHeader::Subscribe: {
|
||||||
|
m_state->subscriber_fds.push_back(client_fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw Error(std::format("invalid request"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ public:
|
|||||||
~Server();
|
~Server();
|
||||||
|
|
||||||
void listen();
|
void listen();
|
||||||
|
void notify_subscribers(double angle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct State;
|
struct State;
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
mod engine;
|
mod engine;
|
||||||
mod event_queue;
|
mod event_queue;
|
||||||
|
mod server2;
|
||||||
pub mod vermiparous;
|
pub mod vermiparous;
|
||||||
|
|
||||||
use core::panic;
|
use core::panic;
|
||||||
@ -9,12 +10,14 @@ use std::{
|
|||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
f64::consts::PI,
|
f64::consts::PI,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
|
thread,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::{Color, Key, Renderer, Scene, Shape, V2, V3},
|
engine::{Color, Key, Renderer, Scene, Shape, V2, V3},
|
||||||
event_queue::EventQueue,
|
event_queue::EventQueue,
|
||||||
|
server2::Server2,
|
||||||
vermiparous::Server,
|
vermiparous::Server,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -390,13 +393,19 @@ impl ShapeGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let t = thread::spawn(|| {
|
||||||
|
let mut server = Server2::new().unwrap();
|
||||||
|
server
|
||||||
|
.subscribe(|measurement| {
|
||||||
|
println!("angle = {}", measurement.angle);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
});
|
||||||
|
t.join().unwrap();
|
||||||
|
|
||||||
let mut sdl_io = engine::SdlIo::new()?;
|
let mut sdl_io = engine::SdlIo::new()?;
|
||||||
let event_queue = Arc::new(Mutex::new(EventQueue::new()));
|
let event_queue = Arc::new(Mutex::new(EventQueue::new()));
|
||||||
let mut game = Game::new(event_queue.clone());
|
let mut game = Game::new(event_queue.clone());
|
||||||
std::thread::spawn(move || {
|
|
||||||
let server = Server::bind("10.133.51.127:5000");
|
|
||||||
server.start(event_queue);
|
|
||||||
});
|
|
||||||
let segments: Vec<Segment> = vec![Segment::new(
|
let segments: Vec<Segment> = vec![Segment::new(
|
||||||
0,
|
0,
|
||||||
vec![Obstacle {
|
vec![Obstacle {
|
||||||
|
|||||||
52
game/src/server2.rs
Normal file
52
game/src/server2.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
use std::{
|
||||||
|
io::{self, BufReader, Read, Write},
|
||||||
|
net::TcpStream,
|
||||||
|
slice::{from_raw_parts, from_raw_parts_mut},
|
||||||
|
thread,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
enum ReqTy {
|
||||||
|
Subscribe = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct ReqHeader {
|
||||||
|
ty: ReqTy,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Measurement {
|
||||||
|
pub angle: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Server2 {
|
||||||
|
stream: TcpStream,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Server2 {
|
||||||
|
pub fn new() -> io::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
stream: TcpStream::connect("127.0.0.1:8889")?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subscribe(&mut self, cb: impl Fn(Measurement) -> ()) -> io::Result<()> {
|
||||||
|
let req = ReqHeader {
|
||||||
|
ty: ReqTy::Subscribe,
|
||||||
|
};
|
||||||
|
let req_as_bytes =
|
||||||
|
unsafe { from_raw_parts((&req as *const _) as *const u8, size_of::<ReqHeader>()) };
|
||||||
|
self.stream.write_all(req_as_bytes)?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut packet = Measurement { angle: 0.0 };
|
||||||
|
let packet_as_bytes = unsafe {
|
||||||
|
from_raw_parts_mut(&mut packet as *mut _ as *mut u8, size_of::<Measurement>())
|
||||||
|
};
|
||||||
|
self.stream.read_exact(packet_as_bytes)?;
|
||||||
|
cb(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user