diff seobeo/docs/web_socket_client.md @ 120:cbbf78b17cfa

[Seobeo][Websocket] Created Web socket client logic.
author June Park <parkjune1995@gmail.com>
date Thu, 08 Jan 2026 03:19:59 -0800
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/seobeo/docs/web_socket_client.md	Thu Jan 08 03:19:59 2026 -0800
@@ -0,0 +1,270 @@
+# Seobeo WebSocket Client - Usage Guide
+
+A clean, easy-to-use WebSocket client library following RFC 6455.
+
+## Features
+
+1. **WebSocket Protocol Support**: Full RFC 6455 WebSocket implementation
+2. **Text and Binary Messages**: Send/receive both text and binary data
+3. **Automatic Ping/Pong**: Automatic pong responses to ping frames
+4. **Message Fragmentation**: Handles fragmented messages automatically
+5. **Secure WebSocket**: Supports both `ws://` and `wss://` (WebSocket over TLS)
+6. **Clean API**: Simple, intuitive API following seobeo coding standards
+
+## API Overview
+
+### Core Functions
+
+```c
+// Connect to WebSocket server
+Seobeo_WebSocket *Seobeo_WebSocket_Connect(const char *url);
+
+// Send messages
+int32 Seobeo_WebSocket_Send_Text(Seobeo_WebSocket *p_ws, const char *text);
+int32 Seobeo_WebSocket_Send_Binary(Seobeo_WebSocket *p_ws, const uint8 *data, size_t length);
+
+// Send control frames
+int32 Seobeo_WebSocket_Send_Ping(Seobeo_WebSocket *p_ws, const char *payload);
+int32 Seobeo_WebSocket_Send_Pong(Seobeo_WebSocket *p_ws, const char *payload);
+
+// Receive messages
+Seobeo_WebSocket_Message *Seobeo_WebSocket_Receive(Seobeo_WebSocket *p_ws);
+
+// Close connection
+int32 Seobeo_WebSocket_Close(Seobeo_WebSocket *p_ws, uint16 code, const char *reason);
+
+// Clean up
+void Seobeo_WebSocket_Message_Destroy(Seobeo_WebSocket_Message *p_msg);
+void Seobeo_WebSocket_Destroy(Seobeo_WebSocket *p_ws);
+```
+
+### Message Opcodes
+
+```c
+typedef enum {
+  SEOBEO_WS_OPCODE_CONTINUATION = 0x0,  // Continuation frame
+  SEOBEO_WS_OPCODE_TEXT = 0x1,          // Text message
+  SEOBEO_WS_OPCODE_BINARY = 0x2,        // Binary message
+  SEOBEO_WS_OPCODE_CLOSE = 0x8,         // Close connection
+  SEOBEO_WS_OPCODE_PING = 0x9,          // Ping frame
+  SEOBEO_WS_OPCODE_PONG = 0xA           // Pong frame
+} Seobeo_WebSocket_Opcode;
+```
+
+### Connection States
+
+```c
+typedef enum {
+  SEOBEO_WS_STATE_CONNECTING = 0,  // Handshake in progress
+  SEOBEO_WS_STATE_OPEN,            // Connection established
+  SEOBEO_WS_STATE_CLOSING,         // Close handshake initiated
+  SEOBEO_WS_STATE_CLOSED           // Connection closed
+} Seobeo_WebSocket_State;
+```
+
+## Examples
+
+### 1. Simple Text Echo
+
+```c
+// Connect to WebSocket server
+Seobeo_WebSocket *p_ws = Seobeo_WebSocket_Connect("wss://echo.websocket.org");
+if (!p_ws)
+{
+  printf("Failed to connect\n");
+  return;
+}
+
+// Send text message
+const char *message = "Hello, WebSocket!";
+Seobeo_WebSocket_Send_Text(p_ws, message);
+
+// Receive echo response
+Seobeo_WebSocket_Message *p_msg = Seobeo_WebSocket_Receive(p_ws);
+if (p_msg && p_msg->opcode == SEOBEO_WS_OPCODE_TEXT)
+{
+  printf("Received: %.*s\n", (int)p_msg->length, (char*)p_msg->data);
+  Seobeo_WebSocket_Message_Destroy(p_msg);
+}
+
+// Close connection
+Seobeo_WebSocket_Close(p_ws, 1000, "Normal closure");
+Seobeo_WebSocket_Destroy(p_ws);
+```
+
+### 2. Binary Data Transfer
+
+```c
+Seobeo_WebSocket *p_ws = Seobeo_WebSocket_Connect("wss://example.com/data");
+
+// Send binary data
+uint8 data[] = {0x01, 0x02, 0x03, 0xAA, 0xBB, 0xCC};
+Seobeo_WebSocket_Send_Binary(p_ws, data, sizeof(data));
+
+// Receive binary response
+Seobeo_WebSocket_Message *p_msg = Seobeo_WebSocket_Receive(p_ws);
+if (p_msg && p_msg->opcode == SEOBEO_WS_OPCODE_BINARY)
+{
+  printf("Received %zu bytes\n", p_msg->length);
+  // Process binary data...
+  Seobeo_WebSocket_Message_Destroy(p_msg);
+}
+
+Seobeo_WebSocket_Destroy(p_ws);
+```
+
+### 3. Chat Application
+
+```c
+Seobeo_WebSocket *p_ws = Seobeo_WebSocket_Connect("wss://chat.example.com");
+
+// Send chat message
+Seobeo_WebSocket_Send_Text(p_ws, "Hello everyone!");
+
+// Continuous receive loop
+while (1)
+{
+  Seobeo_WebSocket_Message *p_msg = Seobeo_WebSocket_Receive(p_ws);
+  if (p_msg)
+  {
+    if (p_msg->opcode == SEOBEO_WS_OPCODE_TEXT)
+    {
+      printf("Chat: %.*s\n", (int)p_msg->length, (char*)p_msg->data);
+    }
+    Seobeo_WebSocket_Message_Destroy(p_msg);
+  }
+
+  usleep(10000);  // 10ms sleep to avoid busy waiting
+}
+
+Seobeo_WebSocket_Destroy(p_ws);
+```
+
+### 4. Ping/Pong Keep-Alive
+
+```c
+Seobeo_WebSocket *p_ws = Seobeo_WebSocket_Connect("wss://api.example.com");
+
+// Send ping to keep connection alive
+Seobeo_WebSocket_Send_Ping(p_ws, "keep-alive");
+
+// Server will automatically receive pong responses
+// (pong responses are handled internally)
+
+Seobeo_WebSocket_Destroy(p_ws);
+```
+
+### 5. Handling Different Message Types
+
+```c
+Seobeo_WebSocket *p_ws = Seobeo_WebSocket_Connect("wss://example.com");
+
+while (1)
+{
+  Seobeo_WebSocket_Message *p_msg = Seobeo_WebSocket_Receive(p_ws);
+  if (p_msg)
+  {
+    switch (p_msg->opcode)
+    {
+      case SEOBEO_WS_OPCODE_TEXT:
+        printf("Text: %.*s\n", (int)p_msg->length, (char*)p_msg->data);
+        break;
+
+      case SEOBEO_WS_OPCODE_BINARY:
+        printf("Binary: %zu bytes\n", p_msg->length);
+        break;
+
+      default:
+        printf("Unknown opcode: 0x%X\n", p_msg->opcode);
+        break;
+    }
+
+    Seobeo_WebSocket_Message_Destroy(p_msg);
+  }
+
+  usleep(10000);
+}
+
+Seobeo_WebSocket_Destroy(p_ws);
+```
+
+### 6. Graceful Shutdown
+
+```c
+Seobeo_WebSocket *p_ws = Seobeo_WebSocket_Connect("wss://example.com");
+
+// Do work...
+
+// Close with custom status code and reason
+Seobeo_WebSocket_Close(p_ws, 1000, "Client shutting down");
+Seobeo_WebSocket_Destroy(p_ws);
+```
+
+## WebSocket Close Codes
+
+Common close status codes (RFC 6455):
+
+- **1000**: Normal closure
+- **1001**: Going away (e.g., server shutdown, browser navigation)
+- **1002**: Protocol error
+- **1003**: Unsupported data type
+- **1006**: Abnormal closure (no close frame received)
+- **1007**: Invalid frame payload data
+- **1008**: Policy violation
+- **1009**: Message too big
+- **1010**: Mandatory extension missing
+- **1011**: Internal server error
+
+## Building
+
+### Build the library:
+```bash
+bazel build //seobeo:seobeo_client
+```
+
+### Build and run the WebSocket test:
+```bash
+bazel test //seobeo:seobeo_websocket_test
+```
+
+## Message Structure
+
+```c
+typedef struct {
+  Seobeo_WebSocket_Opcode opcode;  // Message type
+  uint8  *data;                    // Message payload
+  size_t  length;                  // Payload length
+  boolean is_final;                // Final fragment flag
+} Seobeo_WebSocket_Message;
+```
+
+## Protocol Details
+
+The implementation follows RFC 6455:
+
+1. **Handshake**: HTTP Upgrade request with `Sec-WebSocket-Key`
+2. **Frame Format**: Proper FIN, opcode, mask, and payload length handling
+3. **Masking**: All client-to-server frames are masked (required by RFC)
+4. **Fragmentation**: Handles fragmented messages across multiple frames
+5. **Control Frames**: Proper handling of ping, pong, and close frames
+6. **TLS Support**: Supports secure WebSocket (wss://) via OpenSSL
+
+## Coding Standards
+
+The implementation follows your specified coding standards:
+- Naming: `Seobeo_WebSocket_Connect`, `Seobeo_WebSocket_Send_Text`
+- Two spaces for indentation
+- New line before `{` unless it's a struct
+- Single statement: no need for `{}`
+
+## Features
+
+✅ WebSocket handshake (HTTP Upgrade)
+✅ Text and binary message support
+✅ Automatic masking for client frames
+✅ Message fragmentation handling
+✅ Ping/Pong frames
+✅ Close handshake
+✅ TLS/SSL support (wss://)
+✅ Non-blocking receive
+✅ Proper memory management with arenas