// Subscription system structures and functions for C-Relay // This header defines subscription management functionality #ifndef SUBSCRIPTIONS_H #define SUBSCRIPTIONS_H #include #include #include #include "../nostr_core_lib/cjson/cJSON.h" #include "config.h" // For CLIENT_IP_MAX_LENGTH #include "websockets.h" // For validation constants // Forward declaration for libwebsockets struct struct lws; // Constants #define SUBSCRIPTION_ID_MAX_LENGTH 64 #define MAX_FILTERS_PER_SUBSCRIPTION 10 #define MAX_TOTAL_SUBSCRIPTIONS 5000 // Validation limits (shared with websockets.h) #define MAX_SEARCH_TERM_LENGTH 256 #define MIN_TIMESTAMP 0L #define MAX_TIMESTAMP 4102444800L // 2100-01-01 #define MIN_LIMIT 1 #define MAX_LIMIT 10000 // Forward declarations for typedefs typedef struct subscription_filter subscription_filter_t; typedef struct subscription subscription_t; typedef struct subscription_manager subscription_manager_t; // Subscription filter structure struct subscription_filter { // Filter criteria (all optional) cJSON* kinds; // Array of event kinds [1,2,3] cJSON* authors; // Array of author pubkeys cJSON* ids; // Array of event IDs long since; // Unix timestamp (0 = not set) long until; // Unix timestamp (0 = not set) int limit; // Result limit (0 = no limit) cJSON* tag_filters; // Object with tag filters: {"#e": ["id1"], "#p": ["pubkey1"]} // Linked list for multiple filters per subscription struct subscription_filter* next; }; // Active subscription structure struct subscription { char id[SUBSCRIPTION_ID_MAX_LENGTH]; // Subscription ID struct lws* wsi; // WebSocket connection handle subscription_filter_t* filters; // Linked list of filters (OR'd together) time_t created_at; // When subscription was created int events_sent; // Counter for sent events int active; // 1 = active, 0 = closed // Client info for logging char client_ip[CLIENT_IP_MAX_LENGTH]; // Client IP address // Linked list pointers struct subscription* next; // Next subscription globally struct subscription* session_next; // Next subscription for this session }; // Per-IP connection tracking typedef struct ip_connection_info { char ip_address[CLIENT_IP_MAX_LENGTH]; // IP address int active_connections; // Number of active connections from this IP int total_subscriptions; // Total subscriptions across all connections from this IP time_t first_connection; // When first connection from this IP was established time_t last_activity; // Last activity timestamp from this IP struct ip_connection_info* next; // Next in linked list } ip_connection_info_t; // Global subscription manager struct subscription_manager { subscription_t* active_subscriptions; // Head of global subscription list pthread_mutex_t subscriptions_lock; // Global thread safety int total_subscriptions; // Current count // Configuration int max_subscriptions_per_client; // Default: 20 int max_total_subscriptions; // Default: 5000 // Per-IP connection tracking ip_connection_info_t* ip_connections; // Head of per-IP connection list pthread_mutex_t ip_tracking_lock; // Thread safety for IP tracking // Statistics uint64_t total_created; // Lifetime subscription count uint64_t total_events_broadcast; // Lifetime event broadcast count }; // Function declarations subscription_filter_t* create_subscription_filter(cJSON* filter_json); void free_subscription_filter(subscription_filter_t* filter); subscription_t* create_subscription(const char* sub_id, struct lws* wsi, cJSON* filters_array, const char* client_ip); void free_subscription(subscription_t* sub); int add_subscription_to_manager(subscription_t* sub); int remove_subscription_from_manager(const char* sub_id, struct lws* wsi); int event_matches_filter(cJSON* event, subscription_filter_t* filter); int event_matches_subscription(cJSON* event, subscription_t* subscription); int broadcast_event_to_subscriptions(cJSON* event); // Per-IP connection tracking functions ip_connection_info_t* get_or_create_ip_connection(const char* client_ip); void update_ip_connection_activity(const char* client_ip); void remove_ip_connection(const char* client_ip); int get_total_subscriptions_for_ip(const char* client_ip); int get_active_connections_for_ip(const char* client_ip); // Database logging functions void log_subscription_created(const subscription_t* sub); void log_subscription_closed(const char* sub_id, const char* client_ip, const char* reason); void log_subscription_disconnected(const char* client_ip); void log_event_broadcast(const char* event_id, const char* sub_id, const char* client_ip); void update_subscription_events_sent(const char* sub_id, int events_sent); #endif // SUBSCRIPTIONS_H