Add WebSocket support and enhance chat functionality

- Implement WebSocket handling in the FastCGI server, allowing for real-time communication.
- Introduce functions for managing WebSocket connections, broadcasting messages, and sending to specific connections.
- Create a chat interface in the `websockets.ws.uce` file, including message handling and user notifications.
- Refactor existing code to accommodate WebSocket integration, ensuring compatibility with HTTP requests.
- Update documentation to reflect new features and usage instructions for WebSocket functionality.
This commit is contained in:
udo
2026-04-18 15:10:15 +00:00
parent cd8f07aaa7
commit 86dc93864e
13 changed files with 794 additions and 110 deletions
+11 -60
View File
@@ -17,69 +17,20 @@ StringMap load_session_data(String session_id);
void save_session_data(String session_id, StringMap data);
String session_start(String session_name = "uce-session");
void session_destroy(String session_name = "uce-session");
String ws_make_accept_key(String client_key);
String ws_encode_frame(String payload, u8 opcode = 0x1, bool is_final_fragment = true);
String ws_close_frame(u16 status_code = 1000, String reason = "");
struct WSFrame {
u8 opcode;
u8 is_final_fragment;
u8 mask_bit;
u64 payload_length;
u64 offset;
u8* payload;
u8 opcode = 0;
bool is_final_fragment = false;
bool mask_bit = false;
u64 payload_length = 0;
u64 header_length = 0;
u64 frame_length = 0;
String payload;
WSFrame(String& bufstr)
{
const char* buffer = bufstr.c_str();
u64 buffer_size = bufstr.size();
opcode = buffer[0] & 0x0F;
is_final_fragment = buffer[0] & 0x80;
mask_bit = buffer[1] & 0x80;
payload_length = buffer[1] & 0x7F;
offset = 2;
if (payload_length == 126) {
payload_length = ((u64) buffer[2] << 8) | buffer[3];
offset = 4;
} else if (payload_length == 127) {
payload_length = ((u64) buffer[2] << 56) |
((u64) buffer[3] << 48) |
((u64) buffer[4] << 40) |
((u64) buffer[5] << 32) |
((u64) buffer[6] << 24) |
((u64) buffer[7] << 16) |
((u64) buffer[8] << 8) |
buffer[9];
offset = 10;
}
uint8_t* maskingKey = nullptr;
if (mask_bit) {
maskingKey = reinterpret_cast<uint8_t*>(const_cast<char*>(buffer + offset));
offset += 4;
}
// Parse the frame payload
payload = reinterpret_cast<uint8_t*>(const_cast<char*>(buffer + offset));
if (mask_bit) {
for (int i = 0; i < payload_length; i++) {
payload[i] = payload[i] ^ maskingKey[i % 4];
}
}
// Print the parsed frame
std::cout << "Parsed WebSocket frame:" << std::endl;
std::cout << " Opcode: " << (int) opcode << std::endl;
std::cout << " Is final fragment: " << (is_final_fragment ? "true" : "false") << std::endl;
std::cout << " Payload length: " << payload_length << std::endl;
if (mask_bit) {
std::cout << " Masking key: ";
for (int i = 0; i < 4; i++) {
std::cout << std::hex << (int) maskingKey[i] << " ";
}
std::cout << std::endl;
}
std::cout << " Payload: " << std::endl << std::string((const char*) payload, payload_length) << std::endl;
}
bool parse(const String& buffer, String& error);
};