upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/components/wisp_relay/router.c
diff options
context:
space:
mode:
Diffstat (limited to 'components/wisp_relay/router.c')
-rw-r--r--components/wisp_relay/router.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/components/wisp_relay/router.c b/components/wisp_relay/router.c
new file mode 100644
index 0000000..05aa7d4
--- /dev/null
+++ b/components/wisp_relay/router.c
@@ -0,0 +1,140 @@
1#include "router.h"
2#include "ws_server.h"
3#include "handlers.h"
4#include "sub_manager.h"
5#include "cJSON.h"
6#include "esp_log.h"
7#include <string.h>
8
9static const char *TAG = "router";
10
11esp_err_t router_send_notice(relay_ctx_t *ctx, int conn_fd, const char *message)
12{
13 cJSON *arr = cJSON_CreateArray();
14 cJSON_AddItemToArray(arr, cJSON_CreateString("NOTICE"));
15 cJSON_AddItemToArray(arr, cJSON_CreateString(message));
16 char *json = cJSON_PrintUnformatted(arr);
17 cJSON_Delete(arr);
18 esp_err_t ret = ws_server_send(&ctx->ws_server, conn_fd, json, strlen(json));
19 cJSON_free(json);
20 return ret;
21}
22
23esp_err_t router_send_ok(relay_ctx_t *ctx, int conn_fd, const char *event_id_hex,
24 bool accepted, const char *message)
25{
26 cJSON *arr = cJSON_CreateArray();
27 cJSON_AddItemToArray(arr, cJSON_CreateString("OK"));
28 cJSON_AddItemToArray(arr, cJSON_CreateString(event_id_hex));
29 cJSON_AddItemToArray(arr, cJSON_CreateBool(accepted));
30 cJSON_AddItemToArray(arr, cJSON_CreateString(message ? message : ""));
31 char *json = cJSON_PrintUnformatted(arr);
32 cJSON_Delete(arr);
33 esp_err_t ret = ws_server_send(&ctx->ws_server, conn_fd, json, strlen(json));
34 cJSON_free(json);
35 return ret;
36}
37
38esp_err_t router_send_eose(relay_ctx_t *ctx, int conn_fd, const char *sub_id)
39{
40 cJSON *arr = cJSON_CreateArray();
41 cJSON_AddItemToArray(arr, cJSON_CreateString("EOSE"));
42 cJSON_AddItemToArray(arr, cJSON_CreateString(sub_id));
43 char *json = cJSON_PrintUnformatted(arr);
44 cJSON_Delete(arr);
45 esp_err_t ret = ws_server_send(&ctx->ws_server, conn_fd, json, strlen(json));
46 cJSON_free(json);
47 return ret;
48}
49
50esp_err_t router_send_closed(relay_ctx_t *ctx, int conn_fd, const char *sub_id,
51 const char *message)
52{
53 cJSON *arr = cJSON_CreateArray();
54 cJSON_AddItemToArray(arr, cJSON_CreateString("CLOSED"));
55 cJSON_AddItemToArray(arr, cJSON_CreateString(sub_id));
56 cJSON_AddItemToArray(arr, cJSON_CreateString(message ? message : ""));
57 char *json = cJSON_PrintUnformatted(arr);
58 cJSON_Delete(arr);
59 esp_err_t ret = ws_server_send(&ctx->ws_server, conn_fd, json, strlen(json));
60 cJSON_free(json);
61 return ret;
62}
63
64esp_err_t router_send_event(relay_ctx_t *ctx, int conn_fd, const char *sub_id,
65 const char *event_json, size_t event_len)
66{
67 size_t buf_size = event_len + strlen(sub_id) + 32;
68 char *buf = malloc(buf_size);
69 if (!buf) return ESP_ERR_NO_MEM;
70 int n = snprintf(buf, buf_size, "[\"EVENT\",\"%s\",%.*s]", sub_id, (int)event_len, event_json);
71 esp_err_t ret = ws_server_send(&ctx->ws_server, conn_fd, buf, n);
72 free(buf);
73 return ret;
74}
75
76static void on_ws_message(int fd, const char *data, size_t len)
77{
78 extern relay_ctx_t g_relay_ctx;
79 router_dispatch(&g_relay_ctx, fd, data, len);
80}
81
82static void on_ws_disconnect(int fd)
83{
84 extern relay_ctx_t g_relay_ctx;
85 if (g_relay_ctx.sub_manager) {
86 sub_manager_remove_all(g_relay_ctx.sub_manager, fd);
87 }
88}
89
90void router_dispatch(relay_ctx_t *ctx, int conn_fd, const char *data, size_t len)
91{
92 cJSON *arr = cJSON_ParseWithLength(data, len);
93 if (!arr || !cJSON_IsArray(arr)) {
94 router_send_notice(ctx, conn_fd, "invalid JSON");
95 if (arr) cJSON_Delete(arr);
96 return;
97 }
98
99 int array_size = cJSON_GetArraySize(arr);
100 if (array_size < 2) {
101 router_send_notice(ctx, conn_fd, "array too short");
102 cJSON_Delete(arr);
103 return;
104 }
105
106 cJSON *cmd = cJSON_GetArrayItem(arr, 0);
107 if (!cmd || !cJSON_IsString(cmd)) {
108 router_send_notice(ctx, conn_fd, "invalid command");
109 cJSON_Delete(arr);
110 return;
111 }
112
113 const char *cmd_str = cmd->valuestring;
114
115 if (strcmp(cmd_str, "EVENT") == 0 && array_size >= 2) {
116 cJSON *event_obj = cJSON_GetArrayItem(arr, 1);
117 if (event_obj) {
118 char *event_json = cJSON_PrintUnformatted(event_obj);
119 handle_event(ctx, conn_fd, event_json, strlen(event_json));
120 cJSON_free(event_json);
121 }
122 } else if (strcmp(cmd_str, "REQ") == 0 && array_size >= 3) {
123 cJSON *sub_id_item = cJSON_GetArrayItem(arr, 1);
124 if (sub_id_item && cJSON_IsString(sub_id_item)) {
125 cJSON *filter_obj = cJSON_GetArrayItem(arr, 2);
126 char *filter_json = filter_obj ? cJSON_PrintUnformatted(filter_obj) : strdup("{}");
127 handle_req(ctx, conn_fd, sub_id_item->valuestring, filter_json);
128 free(filter_json);
129 }
130 } else if (strcmp(cmd_str, "CLOSE") == 0 && array_size >= 2) {
131 cJSON *sub_id_item = cJSON_GetArrayItem(arr, 1);
132 if (sub_id_item && cJSON_IsString(sub_id_item)) {
133 handle_close(ctx, conn_fd, sub_id_item->valuestring);
134 }
135 } else {
136 router_send_notice(ctx, conn_fd, "unknown command");
137 }
138
139 cJSON_Delete(arr);
140}