16. WebSocket Functions #
🔒 IMPLEMENTATION STATUS: WebSocket functions are implemented with security features but have critical design flaws that violate Osprey’s functional programming principles.
Table of Contents #
- 16. WebSocket Functions
- Table of Contents
- 16.1 WebSocket Core Types
- 16.2 WebSocket Security Implementation
- 16.3 WebSocket Client Functions
- 16.4 WebSocket Server Functions
websocketCreateServer(port: Int, address: String, path: String) -> Result<ServerID, String>
websocketServerListen(serverID: Int) -> Result<Success, String>
websocketServerBroadcast(serverID: Int, message: String) -> Result<Success, String>
websocketStopServer(serverID: Int) -> Result<Success, String>
- 16.5 Complete WebSocket Example
WebSockets provide real-time, bidirectional communication between client and server. Osprey implements WebSocket support following functional programming principles with comprehensive error handling through Result types.
All WebSocket functions comply with:
- RFC 6455: The WebSocket Protocol (https://tools.ietf.org/html/rfc6455)
- Result types for all operations that can fail
- Immutable message handling with functional callbacks
- Type safety through structured error handling
16.1 WebSocket Core Types #
type WebSocketID = Int
type ServerID = Int
type WebSocketMessage = {
type: String,
data: String,
timestamp: Int
}
type WebSocketConnection = {
id: WebSocketID,
url: String,
isConnected: Bool
}
16.2 WebSocket Security Implementation #
Osprey’s WebSocket implementation follows OWASP WebSocket Security Guidelines with multiple security layers:
🛡️ Cryptographic Security:
- OpenSSL SHA-1: RFC 6455 compliant WebSocket handshake
- Secure key validation: 24-character base64 key format validation
- Memory clearing: All sensitive data zeroed before deallocation
⚔️ Input Validation:
- WebSocket key format validation: Strict RFC 6455 compliance
- Buffer length validation: Maximum limits prevent DoS attacks
- Memory boundary checking: No buffer overruns possible
16.3 WebSocket Client Functions #
websocketConnect(url: String, messageHandler: fn(String) -> Result<Success, String>) -> Result<WebSocketID, String>
#
Establishes a WebSocket connection with a message handler callback.
Parameters:
url
: WebSocket URL (e.g., “ws://localhost:8080/chat”)messageHandler
: Callback function to handle incoming messages
Returns:
Success(wsID)
: WebSocket connection identifierErr(message)
: Connection error description
Implementation Status: ⚠️ INCORRECT - Current C runtime returns raw int64_t
instead of Result<WebSocketID, String>
and takes string handler instead of function pointer
Example:
fn handleMessage(message: String) -> Result<Success, String> = {
print("Received: ${message}")
Success()
}
let wsResult = websocketConnect(url: "ws://localhost:8080/chat", messageHandler: handleMessage)
match wsResult {
Success wsId => {
print("Connected with ID: ${wsId}")
// Use the connection
}
Err message => print("Failed to connect: ${message}")
}
websocketSend(wsID: Int, message: String) -> Result<Success, String>
#
Sends a message through the WebSocket connection.
Parameters:
wsID
: WebSocket identifier fromwebsocketConnect
message
: Message to send
Returns:
Success()
: Message sent successfullyErr(message)
: Send error description
Implementation Status: ⚠️ INCORRECT - Current C runtime returns raw int64_t
instead of Result<Success, String>
Example:
let sendResult = websocketSend(wsID: wsId, message: "Hello, WebSocket!")
match sendResult {
Success _ => print("Message sent successfully")
Err message => print("Failed to send: ${message}")
}
websocketClose(wsID: Int) -> Result<Success, String>
#
Closes the WebSocket connection and cleans up resources.
Parameters:
wsID
: WebSocket identifier to close
Returns:
Success()
: Connection closed successfullyErr(message)
: Close error description
Implementation Status: ⚠️ INCORRECT - Current C runtime returns raw int64_t
instead of Result<Success, String>
Example:
let closeResult = websocketClose(wsID: wsId)
match closeResult {
Success _ => print("Connection closed")
Err message => print("Failed to close: ${message}")
}
16.4 WebSocket Server Functions #
websocketCreateServer(port: Int, address: String, path: String) -> Result<ServerID, String>
#
Creates a WebSocket server bound to the specified port, address, and path.
Parameters:
port
: Port number (1-65535)address
: IP address to bind to (e.g., “127.0.0.1”, “0.0.0.0”)path
: WebSocket endpoint path (e.g., “/chat”, “/live”)
Returns:
Success(serverID)
: Unique WebSocket server identifierErr(message)
: Server creation error description
Implementation Status: ⚠️ INCORRECT - Current C runtime returns raw int64_t
instead of Result<ServerID, String>
. Also has critical runtime issues with port binding failures.
Example:
let serverResult = websocketCreateServer(port: 8080, address: "127.0.0.1", path: "/chat")
match serverResult {
Success serverId => print("WebSocket server created with ID: ${serverId}")
Err message => print("Failed to create server: ${message}")
}
websocketServerListen(serverID: Int) -> Result<Success, String>
#
Starts the WebSocket server listening for connections.
Parameters:
serverID
: Server identifier fromwebsocketCreateServer
Returns:
Success()
: Server started listening successfullyErr(message)
: Listen error description
Implementation Status: ⚠️ INCORRECT - Current C runtime returns raw int64_t
instead of Result<Success, String>
. Currently returns -4
(bind failed) due to port binding issues.
Example:
let listenResult = websocketServerListen(serverID: serverId)
match listenResult {
Success _ => print("Server listening on ws://127.0.0.1:8080/chat")
Err message => print("Failed to start listening: ${message}")
}
websocketServerBroadcast(serverID: Int, message: String) -> Result<Success, String>
#
Broadcasts a message to all connected WebSocket clients.
Parameters:
serverID
: Server identifiermessage
: Message to broadcast to all clients
Returns:
Success()
: Message broadcasted successfullyErr(message)
: Broadcast error description
Implementation Status: ⚠️ INCORRECT - Current C runtime returns raw int64_t
(number of clients sent to) instead of Result<Success, String>
Example:
let broadcastResult = websocketServerBroadcast(serverID: serverId, message: "Welcome to Osprey Chat!")
match broadcastResult {
Success _ => print("Message broadcasted to all clients")
Err message => print("Failed to broadcast: ${message}")
}
websocketStopServer(serverID: Int) -> Result<Success, String>
#
Stops the WebSocket server and closes all connections.
Parameters:
serverID
: Server identifier to stop
Returns:
Success()
: Server stopped successfullyErr(message)
: Stop error description
Implementation Status: ⚠️ INCORRECT - Current C runtime returns raw int64_t
instead of Result<Success, String>
Example:
let stopResult = websocketStopServer(serverID: serverId)
match stopResult {
Success _ => print("Server stopped successfully")
Err message => print("Failed to stop server: ${message}")
}
16.5 Complete WebSocket Example #
A practical WebSocket server and client implementation demonstrating real-time communication:
fn main() -> Int = {
print("Starting WebSocket chat server...")
// Create WebSocket server
let serverResult = websocketCreateServer(port: 8080, address: "127.0.0.1", path: "/chat")
match serverResult {
Success serverId => {
print("WebSocket server created with ID: ${serverId}")
// Start listening for connections
let listenResult = websocketServerListen(serverID: serverId)
match listenResult {
Success _ => {
print("Server listening on ws://127.0.0.1:8080/chat")
// Broadcast welcome message
let welcomeResult = websocketServerBroadcast(
serverID: serverId,
message: "Welcome to Osprey Chat!"
)
match welcomeResult {
Success _ => print("Welcome message broadcasted")
Err message => print("Failed to broadcast welcome: ${message}")
}
// Keep server alive for 10 seconds
sleep(10000)
// Clean shutdown
let stopResult = websocketStopServer(serverID: serverId)
match stopResult {
Success _ => print("Server stopped successfully")
Err message => print("Failed to stop server: ${message}")
}
}
Err message => print("Failed to start listening: ${message}")
}
}
Err message => print("Failed to create server: ${message}")
}
0
}
// WebSocket client example
fn connectToChat() -> Int = {
fn chatMessageHandler(message: String) -> Result<Success, String> = {
print("Chat: ${message}")
// Process different message types
match message {
"ping" => {
print("Received ping, responding with pong")
Success()
}
_ => {
print("Received message: ${message}")
Success()
}
}
}
let wsResult = websocketConnect(
url: "ws://127.0.0.1:8080/chat",
messageHandler: chatMessageHandler
)
match wsResult {
Success wsId => {
print("Connected to chat server with ID: ${wsId}")
// Send some messages
let sendResult1 = websocketSend(wsID: wsId, message: "Hello from Osprey!")
match sendResult1 {
Success _ => print("First message sent")
Err message => print("Failed to send first message: ${message}")
}
let sendResult2 = websocketSend(wsID: wsId, message: "How is everyone?")
match sendResult2 {
Success _ => print("Second message sent")
Err message => print("Failed to send second message: ${message}")
}
let pingResult = websocketSend(wsID: wsId, message: "ping")
match pingResult {
Success _ => print("Ping sent")
Err message => print("Failed to send ping: ${message}")
}
// Wait a bit before closing
sleep(2000)
// Close connection
let closeResult = websocketClose(wsID: wsId)
match closeResult {
Success _ => print("Disconnected from chat")
Err message => print("Failed to disconnect: ${message}")
}
}
Err message => print("Failed to connect: ${message}")
}
0
}
// Chat message processing with pattern matching
fn processMessage(message: String) -> Result<String, String> =
match message {
"{\"type\":\"join\"}" => Success("User joined the chat")
"{\"type\":\"leave\"}" => Success("User left the chat")
"{\"type\":\"message\"}" => Success("Regular chat message")
_ => Success("Unknown message type")
}
This example demonstrates:
- Result type error handling for all WebSocket operations
- Functional message handlers with proper callback signatures
- Pattern matching for different message types
- Resource management with proper connection cleanup
- Real-time communication patterns for chat applications
- Comprehensive error handling following Osprey’s functional principles
- Type-safe WebSocket operations with structured error messages
Key Differences from Current Implementation:
- All functions return Result types instead of raw integers
- Message handlers are proper function pointers instead of string identifiers
- Comprehensive error handling with descriptive error messages
- Functional programming patterns with immutable message processing
- Type safety through structured return types and pattern matching