Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
skhaz committed Dec 2, 2024
1 parent ebb2c51 commit 0911ad6
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 152 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
"-s ALLOW_MEMORY_GROWTH=1"
"-s INITIAL_MEMORY=134217728"
"-s EXPORTED_RUNTIME_METHODS=['callMain']"
"-s FETCH=1"
"-l websocket.js"
# Debugging
# "-s RUNTIME_DEBUG"
# "-s ASSERTIONS=2"
Expand Down
7 changes: 7 additions & 0 deletions src/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#ifdef EMSCRIPTEN
#include <emscripten.h>
#include <emscripten/websocket.h>
#endif

#include <AL/al.h>
Expand Down Expand Up @@ -44,9 +45,11 @@
#include <optional>
#include <random>
#include <ranges>
#include <sstream>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>

Expand Down Expand Up @@ -108,4 +111,8 @@ namespace math {
class vector2d;
}

namespace network {
class querybuilder;
}

using namespace std::literals;
131 changes: 112 additions & 19 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,28 +1,121 @@
#include "application.hpp"

#include "networkmanager.hpp"
#include "common.hpp"
#include "querybuilder.hpp"

int main(int argc, char **argv) {
#if 1
try {
network::networkmanager manager;

network::networkrequest request;
request.url = "http://ifconfig.me/";
request.method = "GET";
request.callback = [](const std::string &response, long status_code) {
if (status_code == 200) {
std::cout << "Public IP: " << response << std::endl;
} else {
std::cerr << "Failed to fetch IP. Status code: " << status_code << std::endl;
}
class socketio {
public:
explicit socketio(const std::string &url) {
if (!emscripten_websocket_is_supported()) {
throw std::runtime_error("WebSocket is not supported in this environment.");
}

std::cout << "url " << url << std::endl;

EmscriptenWebSocketCreateAttributes attributes = {
url.c_str(), nullptr, true
};
socket = emscripten_websocket_new(&attributes);
if (socket <= 0) {
throw std::runtime_error("Failed to create WebSocket.");
}

emscripten_websocket_set_onopen_callback(socket, this, [](int, const EmscriptenWebSocketOpenEvent *event, void *user_data) -> EM_BOOL {
UNUSED(event);
const auto self = static_cast<socketio *>(user_data);

std::string connectMessage = R"({"type":"connect"})"; // Exemplo de formato JSON
emscripten_websocket_send_utf8_text(event->socket, connectMessage.c_str());

if (self->on_open) self->on_open();
return true;
});

emscripten_websocket_set_onmessage_callback(socket, this, [](int, const EmscriptenWebSocketMessageEvent *event, void *user_data) -> EM_BOOL {
auto self = static_cast<socketio *>(user_data);
if (event->isText && self->on_message) {
std::string message(event->data, event->data + event->numBytes);
self->on_message(message);
}
return true;
});

emscripten_websocket_set_onclose_callback(socket, this, [](int, const EmscriptenWebSocketCloseEvent *event, void *user_data) -> EM_BOOL {
auto self = static_cast<socketio *>(user_data);
if (self->on_close) self->on_close(event->reason);
return true;
});

emscripten_websocket_set_onerror_callback(socket, this, [](int, const EmscriptenWebSocketErrorEvent *, void *user_data) -> EM_BOOL {
auto self = static_cast<socketio *>(user_data);
if (self->on_error) self->on_error();
return true;
});
}

~socketio() {
if (socket > 0) {
emscripten_websocket_close(socket, 1000, "Normal closure");
emscripten_websocket_delete(socket);
}
}

void emit(const std::string &event, const std::string &message) {
if (socket > 0) {
const auto packet = fmt::format("42[\"{}\",\"{}\"]", event, message);
emscripten_websocket_send_utf8_text(socket, packet.data());
}
}

manager.send(request);
} catch (const std::exception &e) {
std::cerr << "Error: " << e.what() << std::endl;
void set_on_open(const std::function<void()> &callback) {
on_open = callback;
}
#endif

void set_on_message(const std::function<void(const std::string &)> &callback) {
on_message = callback;
}

void set_on_close(const std::function<void(const std::string &)> &callback) {
on_close = callback;
}

void set_on_error(const std::function<void()> &callback) {
on_error = callback;
}

private:
EMSCRIPTEN_WEBSOCKET_T socket;
std::function<void()> on_open;
std::function<void(const std::string &)> on_message;
std::function<void(const std::string &)> on_close;
std::function<void()> on_error;
};

int main(int argc, char **argv) {
network::querybuilder qb;
const auto query = qb.add("EIO", "4")
.add("transport", "websocket")
.build();

socketio io(fmt::format("{}/{}/?{}", "ws://localhost:9000", "socket.io", query));

io.set_on_open([]() {
std::cout << "Connected to the server." << std::endl;
});

io.set_on_message([](const std::string &message) {
std::cout << "Message received: " << message << std::endl;
});

io.set_on_close([](const std::string &reason) {
std::cout << "Connection closed. Reason: " << reason << std::endl;
});

io.set_on_error([]() {
std::cerr << "An error occurred." << std::endl;
});

// io.emit("echo", "Hello, Server!");

framework::application app(argc, std::move(argv));

Expand Down
111 changes: 0 additions & 111 deletions src/networkmanager.cpp

This file was deleted.

21 changes: 0 additions & 21 deletions src/networkmanager.hpp

This file was deleted.

36 changes: 36 additions & 0 deletions src/querybuilder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "querybuilder.hpp"

using namespace network;

static std::string encode(std::string_view value) {
std::string encoded;
encoded.reserve(value.size());
for (char c : value) {
if (std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' || c == '.' || c == '~') {
encoded += c;
} else {
encoded += '%';
encoded += static_cast<char>((c >> 4) < 10 ? '0' + ((c >> 4) & 0xF) : 'A' + (((c >> 4) & 0xF) - 10));
encoded += static_cast<char>((c & 0xF) < 10 ? '0' + (c & 0xF) : 'A' + ((c & 0xF) - 10));
}
}
return encoded;
}

querybuilder &querybuilder::add(const std::string &key, const std::string &value) noexcept {
_parameters.emplace(std::string(key), std::string(value));
return *this;
}

std::string querybuilder::build() const noexcept {
if (_parameters.empty()) {
return {};
}

std::ostringstream query;
for (auto it = _parameters.begin(); it != _parameters.end(); ++it) {
query << it->first << '=' << encode(it->second);
if (std::next(it) != _parameters.end()) query << '&';
}
return query.str();
}
15 changes: 15 additions & 0 deletions src/querybuilder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include "common.hpp"

namespace network {
class querybuilder {
public:
querybuilder &add(const std::string &key, const std::string &value) noexcept;

[[nodiscard]] std::string build() const noexcept;

private:
std::unordered_map<std::string, std::string> _parameters;
};
}

0 comments on commit 0911ad6

Please sign in to comment.