128 lines
6.3 KiB
C
128 lines
6.3 KiB
C
// WebSocket protocol structures and constants for C-Relay
|
|
// This header defines structures shared between main.c and websockets.c
|
|
|
|
#ifndef WEBSOCKETS_H
|
|
#define WEBSOCKETS_H
|
|
|
|
#include <pthread.h>
|
|
#include <libwebsockets.h>
|
|
#include <time.h>
|
|
#include "../nostr_core_lib/cjson/cJSON.h"
|
|
#include "config.h" // For CLIENT_IP_MAX_LENGTH and MAX_SUBSCRIPTIONS_PER_CLIENT
|
|
|
|
// Constants
|
|
#define CHALLENGE_MAX_LENGTH 128
|
|
#define AUTHENTICATED_PUBKEY_MAX_LENGTH 65 // 64 hex + null
|
|
|
|
// Rate limiting constants for malformed requests
|
|
#define MAX_MALFORMED_REQUESTS_PER_HOUR 10
|
|
#define MALFORMED_REQUEST_BLOCK_DURATION 3600 // 1 hour in seconds
|
|
#define RATE_LIMIT_CLEANUP_INTERVAL 300 // 5 minutes
|
|
|
|
// Maximum number of messages allowed in a per-client write queue.
|
|
// When exceeded, new messages are dropped to prevent unbounded memory growth
|
|
// under high-traffic or slow-client conditions.
|
|
#define MAX_MESSAGE_QUEUE_SIZE 500
|
|
|
|
// Filter validation constants
|
|
#define MAX_FILTERS_PER_REQUEST 10
|
|
#define MAX_AUTHORS_PER_FILTER 1000
|
|
#define MAX_IDS_PER_FILTER 1000
|
|
#define MAX_KINDS_PER_FILTER 500
|
|
#define MAX_TAG_VALUES_PER_FILTER 1000
|
|
#define MAX_KIND_VALUE 65535
|
|
#define MAX_TIMESTAMP_VALUE 2147483647 // Max 32-bit signed int
|
|
#define MAX_LIMIT_VALUE 5000
|
|
#define MAX_SEARCH_LENGTH 256
|
|
#define MAX_TAG_VALUE_LENGTH 1024
|
|
|
|
// Message queue node for proper libwebsockets pattern
|
|
struct message_queue_node {
|
|
unsigned char* data; // Message data (with LWS_PRE space)
|
|
size_t length; // Message length (without LWS_PRE)
|
|
enum lws_write_protocol type; // LWS_WRITE_TEXT, etc.
|
|
struct message_queue_node* next; // Next node in queue
|
|
};
|
|
|
|
// Enhanced per-session data with subscription management, NIP-42 authentication, and rate limiting
|
|
struct per_session_data {
|
|
int authenticated;
|
|
struct subscription* subscriptions; // Head of this session's subscription list
|
|
pthread_mutex_t session_lock; // Per-session thread safety
|
|
char client_ip[CLIENT_IP_MAX_LENGTH]; // Client IP for logging
|
|
int subscription_count; // Number of subscriptions for this session
|
|
time_t connection_established; // When WebSocket connection was established
|
|
|
|
// NIP-42 Authentication State
|
|
char authenticated_pubkey[65]; // Authenticated public key (64 hex + null)
|
|
char active_challenge[65]; // Current challenge for this session (64 hex + null)
|
|
time_t challenge_created; // When challenge was created
|
|
time_t challenge_expires; // Challenge expiration time
|
|
int nip42_auth_required_events; // Whether NIP-42 auth is required for EVENT submission
|
|
int nip42_auth_required_subscriptions; // Whether NIP-42 auth is required for REQ operations
|
|
int auth_challenge_sent; // Whether challenge has been sent (0/1)
|
|
|
|
// Rate limiting for subscription attempts
|
|
int failed_subscription_attempts; // Count of failed subscription attempts
|
|
time_t last_failed_attempt; // Timestamp of last failed attempt
|
|
time_t rate_limit_until; // Time until rate limiting expires
|
|
int consecutive_failures; // Consecutive failed attempts for backoff
|
|
|
|
// Rate limiting for malformed requests
|
|
int malformed_request_count; // Count of malformed requests in current hour
|
|
time_t malformed_request_window_start; // Start of current hour window
|
|
time_t malformed_request_blocked_until; // Time until blocked for malformed requests
|
|
|
|
// Message queue for proper libwebsockets pattern (replaces single buffer)
|
|
struct message_queue_node* message_queue_head; // Head of message queue
|
|
struct message_queue_node* message_queue_tail; // Tail of message queue
|
|
int message_queue_count; // Number of messages in queue
|
|
int writeable_requested; // Flag: 1 if writeable callback requested
|
|
|
|
// Message reassembly for handling fragmented WebSocket messages
|
|
char* reassembly_buffer; // Buffer for accumulating message fragments (NULL when not reassembling)
|
|
size_t reassembly_size; // Current size of accumulated data
|
|
size_t reassembly_capacity; // Allocated capacity of reassembly buffer
|
|
int reassembly_active; // Flag: 1 if currently reassembling a message
|
|
|
|
// Database query tracking for abuse detection and monitoring
|
|
int db_queries_executed; // Total SELECT queries executed by this connection
|
|
int db_rows_returned; // Total rows returned across all queries
|
|
time_t query_tracking_start; // When connection was established (for rate calculation)
|
|
|
|
// Session activity tracking for idle connection banning
|
|
int session_active; // 1 if client sent REQ or EVENT, 0 otherwise
|
|
int idle_timeout_sec; // Timeout value for this session (copied from config)
|
|
int is_websocket; // 1 if this is a WebSocket connection, 0 for HTTP
|
|
};
|
|
|
|
// Get current active WebSocket connection count
|
|
int get_active_connection_count(void);
|
|
|
|
// Actual relay port bound by libwebsockets at runtime (after fallback/retry logic)
|
|
extern int g_relay_port;
|
|
|
|
// NIP-11 HTTP session data structure for managing buffer lifetime
|
|
struct nip11_session_data {
|
|
int type; // 0 for NIP-11
|
|
char* json_buffer;
|
|
size_t json_length;
|
|
int headers_sent;
|
|
int body_sent;
|
|
};
|
|
|
|
// Function declarations
|
|
int start_websocket_relay(int port_override, int strict_port);
|
|
|
|
// Message queue functions for proper libwebsockets pattern
|
|
int queue_message(struct lws* wsi, struct per_session_data* pss, const char* message, size_t length, enum lws_write_protocol type);
|
|
int process_message_queue(struct lws* wsi, struct per_session_data* pss);
|
|
|
|
// Zero-copy variant: caller allocates (LWS_PRE + length) bytes, writes message at buf+LWS_PRE,
|
|
// then passes ownership to the queue. The queue will free buf when done. No memcpy performed.
|
|
int queue_message_take_ownership(struct lws* wsi, struct per_session_data* pss, unsigned char* buf, size_t length, enum lws_write_protocol type);
|
|
|
|
// Auth rules checking function from request_validator.c
|
|
int check_database_auth_rules(const char *pubkey, const char *operation, const char *resource_hash);
|
|
|
|
#endif // WEBSOCKETS_H
|