diff options
Diffstat (limited to 'components/tollgate_core/src')
8 files changed, 662 insertions, 0 deletions
diff --git a/components/tollgate_core/src/tollgate_core_client.c b/components/tollgate_core/src/tollgate_core_client.c new file mode 100644 index 0000000..9e8508a --- /dev/null +++ b/components/tollgate_core/src/tollgate_core_client.c | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | #include "tollgate_core_client.h" | ||
| 2 | #include "cJSON.h" | ||
| 3 | #include <string.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | |||
| 6 | bool tollgate_core_client_parse_discovery(const char *json_str, tollgate_discovery_t *out) | ||
| 7 | { | ||
| 8 | cJSON *root = cJSON_Parse(json_str); | ||
| 9 | if (!root) return false; | ||
| 10 | |||
| 11 | cJSON *kind = cJSON_GetObjectItemCaseSensitive(root, "kind"); | ||
| 12 | if (!kind || !cJSON_IsNumber(kind) || kind->valueint != 10021) { | ||
| 13 | cJSON_Delete(root); | ||
| 14 | return false; | ||
| 15 | } | ||
| 16 | |||
| 17 | memset(out, 0, sizeof(tollgate_discovery_t)); | ||
| 18 | out->is_tollgate = true; | ||
| 19 | |||
| 20 | cJSON *tags = cJSON_GetObjectItemCaseSensitive(root, "tags"); | ||
| 21 | if (!tags || !cJSON_IsArray(tags)) { | ||
| 22 | cJSON_Delete(root); | ||
| 23 | return true; | ||
| 24 | } | ||
| 25 | |||
| 26 | int tag_count = cJSON_GetArraySize(tags); | ||
| 27 | for (int i = 0; i < tag_count; i++) { | ||
| 28 | cJSON *tag = cJSON_GetArrayItem(tags, i); | ||
| 29 | if (!tag || !cJSON_IsArray(tag)) continue; | ||
| 30 | |||
| 31 | int tag_len = cJSON_GetArraySize(tag); | ||
| 32 | if (tag_len < 2) continue; | ||
| 33 | |||
| 34 | cJSON *tag_name = cJSON_GetArrayItem(tag, 0); | ||
| 35 | if (!tag_name || !cJSON_IsString(tag_name)) continue; | ||
| 36 | |||
| 37 | if (strcmp(tag_name->valuestring, "metric") == 0) { | ||
| 38 | cJSON *val = cJSON_GetArrayItem(tag, 1); | ||
| 39 | if (val && cJSON_IsString(val)) { | ||
| 40 | strncpy(out->metric, val->valuestring, sizeof(out->metric) - 1); | ||
| 41 | } | ||
| 42 | } else if (strcmp(tag_name->valuestring, "step_size") == 0) { | ||
| 43 | cJSON *val = cJSON_GetArrayItem(tag, 1); | ||
| 44 | if (val && cJSON_IsString(val)) { | ||
| 45 | out->step_size_ms = atoi(val->valuestring); | ||
| 46 | } | ||
| 47 | } else if (strcmp(tag_name->valuestring, "price_per_step") == 0 && tag_len >= 4) { | ||
| 48 | cJSON *payment_type = cJSON_GetArrayItem(tag, 2); | ||
| 49 | |||
| 50 | if (cJSON_IsString(payment_type) && strcmp(payment_type->valuestring, "mining") == 0 && tag_len >= 5) { | ||
| 51 | out->mining_available = true; | ||
| 52 | cJSON *port_val = cJSON_GetArrayItem(tag, 3); | ||
| 53 | if (port_val && cJSON_IsString(port_val)) { | ||
| 54 | out->mining_port = (uint16_t)atoi(port_val->valuestring); | ||
| 55 | } | ||
| 56 | } else { | ||
| 57 | cJSON *amount = cJSON_GetArrayItem(tag, 2); | ||
| 58 | cJSON *mint = cJSON_GetArrayItem(tag, 4); | ||
| 59 | |||
| 60 | if (amount && cJSON_IsString(amount)) { | ||
| 61 | out->price_per_step = atoi(amount->valuestring); | ||
| 62 | } | ||
| 63 | if (mint && cJSON_IsString(mint)) { | ||
| 64 | strncpy(out->mint_url, mint->valuestring, sizeof(out->mint_url) - 1); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | cJSON_Delete(root); | ||
| 71 | return true; | ||
| 72 | } | ||
| 73 | |||
| 74 | bool tollgate_core_client_parse_session(const char *json_str, int64_t *allotment_ms_out) | ||
| 75 | { | ||
| 76 | cJSON *root = cJSON_Parse(json_str); | ||
| 77 | if (!root) return false; | ||
| 78 | |||
| 79 | cJSON *kind = cJSON_GetObjectItemCaseSensitive(root, "kind"); | ||
| 80 | if (!kind || !cJSON_IsNumber(kind)) { | ||
| 81 | cJSON_Delete(root); | ||
| 82 | return false; | ||
| 83 | } | ||
| 84 | |||
| 85 | if (kind->valueint != 1022) { | ||
| 86 | cJSON_Delete(root); | ||
| 87 | return false; | ||
| 88 | } | ||
| 89 | |||
| 90 | cJSON *tags = cJSON_GetObjectItemCaseSensitive(root, "tags"); | ||
| 91 | if (tags && cJSON_IsArray(tags)) { | ||
| 92 | int tag_count = cJSON_GetArraySize(tags); | ||
| 93 | for (int i = 0; i < tag_count; i++) { | ||
| 94 | cJSON *tag = cJSON_GetArrayItem(tags, i); | ||
| 95 | if (!tag || !cJSON_IsArray(tag)) continue; | ||
| 96 | cJSON *tag_name = cJSON_GetArrayItem(tag, 0); | ||
| 97 | if (tag_name && cJSON_IsString(tag_name) && strcmp(tag_name->valuestring, "allotment") == 0) { | ||
| 98 | cJSON *val = cJSON_GetArrayItem(tag, 1); | ||
| 99 | if (val && cJSON_IsString(val)) { | ||
| 100 | *allotment_ms_out = atoll(val->valuestring); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | cJSON_Delete(root); | ||
| 107 | return true; | ||
| 108 | } | ||
| 109 | |||
| 110 | bool tollgate_core_client_parse_usage(const char *resp, int64_t *remaining_out, int64_t *total_out) | ||
| 111 | { | ||
| 112 | char remaining_str[32] = {0}; | ||
| 113 | char total_str[32] = {0}; | ||
| 114 | const char *slash = strchr(resp, '/'); | ||
| 115 | if (!slash) return false; | ||
| 116 | |||
| 117 | size_t rlen = slash - resp; | ||
| 118 | if (rlen >= sizeof(remaining_str)) return false; | ||
| 119 | memcpy(remaining_str, resp, rlen); | ||
| 120 | strncpy(total_str, slash + 1, sizeof(total_str) - 1); | ||
| 121 | |||
| 122 | *remaining_out = atoll(remaining_str); | ||
| 123 | *total_out = atoll(total_str); | ||
| 124 | return true; | ||
| 125 | } | ||
| 126 | |||
| 127 | bool tollgate_core_client_should_renew(int64_t remaining_ms, int64_t allotment_ms, int threshold_pct) | ||
| 128 | { | ||
| 129 | if (threshold_pct <= 0) threshold_pct = 20; | ||
| 130 | if (allotment_ms <= 0 || remaining_ms < 0) return false; | ||
| 131 | |||
| 132 | int remaining_pct = (int)((remaining_ms * 100) / allotment_ms); | ||
| 133 | return remaining_pct <= threshold_pct; | ||
| 134 | } | ||
| 135 | |||
| 136 | int tollgate_core_client_calc_price_per_min(int price_per_step, int step_size_ms) | ||
| 137 | { | ||
| 138 | if (step_size_ms <= 0) step_size_ms = 1; | ||
| 139 | return price_per_step * 60000 / step_size_ms; | ||
| 140 | } | ||
| 141 | |||
| 142 | int tollgate_core_client_calc_steps(int steps_to_buy, int price_per_step, int discovery_price) | ||
| 143 | { | ||
| 144 | if (steps_to_buy <= 0) steps_to_buy = 1; | ||
| 145 | return steps_to_buy * discovery_price; | ||
| 146 | } | ||
diff --git a/components/tollgate_core/src/tollgate_core_client.h b/components/tollgate_core/src/tollgate_core_client.h new file mode 100644 index 0000000..32b90e6 --- /dev/null +++ b/components/tollgate_core/src/tollgate_core_client.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | #ifndef TOLLGATE_CORE_CLIENT_H | ||
| 2 | #define TOLLGATE_CORE_CLIENT_H | ||
| 3 | |||
| 4 | #include <stdint.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | |||
| 7 | #define TG_CLIENT_MAX_MINT_URL 256 | ||
| 8 | #define TG_CLIENT_MAX_METRIC 32 | ||
| 9 | #define TG_CLIENT_MAX_GW_IP_LEN 16 | ||
| 10 | |||
| 11 | typedef enum { | ||
| 12 | TG_CLIENT_IDLE, | ||
| 13 | TG_CLIENT_DETECTING, | ||
| 14 | TG_CLIENT_NO_TOLLGATE, | ||
| 15 | TG_CLIENT_NEEDS_PAY, | ||
| 16 | TG_CLIENT_PAYING, | ||
| 17 | TG_CLIENT_PAID, | ||
| 18 | TG_CLIENT_RENEWING, | ||
| 19 | TG_CLIENT_MINING, | ||
| 20 | TG_CLIENT_ERROR | ||
| 21 | } tollgate_client_state_t; | ||
| 22 | |||
| 23 | typedef struct { | ||
| 24 | bool is_tollgate; | ||
| 25 | int price_per_step; | ||
| 26 | int step_size_ms; | ||
| 27 | char mint_url[TG_CLIENT_MAX_MINT_URL]; | ||
| 28 | char metric[TG_CLIENT_MAX_METRIC]; | ||
| 29 | bool mining_available; | ||
| 30 | uint16_t mining_port; | ||
| 31 | } tollgate_discovery_t; | ||
| 32 | |||
| 33 | typedef struct { | ||
| 34 | const char *ssid; | ||
| 35 | int price_per_step; | ||
| 36 | uint32_t step_size; | ||
| 37 | } tollgate_client_market_entry_t; | ||
| 38 | |||
| 39 | bool tollgate_core_client_parse_discovery(const char *json_str, tollgate_discovery_t *out); | ||
| 40 | |||
| 41 | bool tollgate_core_client_parse_session(const char *json_str, int64_t *allotment_ms_out); | ||
| 42 | |||
| 43 | bool tollgate_core_client_parse_usage(const char *resp, int64_t *remaining_out, int64_t *total_out); | ||
| 44 | |||
| 45 | bool tollgate_core_client_should_renew(int64_t remaining_ms, int64_t allotment_ms, int threshold_pct); | ||
| 46 | |||
| 47 | int tollgate_core_client_calc_price_per_min(int price_per_step, int step_size_ms); | ||
| 48 | |||
| 49 | int tollgate_core_client_calc_steps(int steps_to_buy, int price_per_step, int discovery_price); | ||
| 50 | |||
| 51 | #endif | ||
diff --git a/components/tollgate_core/src/tollgate_core_mint_health.c b/components/tollgate_core/src/tollgate_core_mint_health.c new file mode 100644 index 0000000..c810003 --- /dev/null +++ b/components/tollgate_core/src/tollgate_core_mint_health.c | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | #include "tollgate_core_mint_health.h" | ||
| 2 | #include <string.h> | ||
| 3 | |||
| 4 | void tollgate_core_mint_health_init(const char urls[][256], int count) | ||
| 5 | { | ||
| 6 | } | ||
| 7 | |||
| 8 | void tollgate_core_mint_health_update(tollgate_mint_health_t *state, | ||
| 9 | int mint_index, | ||
| 10 | bool probe_ok, | ||
| 11 | int http_status, | ||
| 12 | int err_code, | ||
| 13 | int64_t probe_time_ms) | ||
| 14 | { | ||
| 15 | if (!state || mint_index < 0 || mint_index >= state->count) return; | ||
| 16 | |||
| 17 | tollgate_mint_status_t *m = &state->mints[mint_index]; | ||
| 18 | m->last_probe_ms = probe_time_ms; | ||
| 19 | m->last_http_status = probe_ok ? http_status : 0; | ||
| 20 | m->last_err = probe_ok ? 0 : err_code; | ||
| 21 | |||
| 22 | if (probe_ok) { | ||
| 23 | m->consecutive_successes++; | ||
| 24 | if (m->consecutive_successes >= TG_MINT_HEALTH_RECOVERY_THRESHOLD) { | ||
| 25 | m->reachable = true; | ||
| 26 | } | ||
| 27 | } else { | ||
| 28 | m->reachable = false; | ||
| 29 | m->consecutive_successes = 0; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | void tollgate_core_mint_health_update_initial(tollgate_mint_health_t *state, | ||
| 34 | int mint_index, | ||
| 35 | bool probe_ok, | ||
| 36 | int http_status, | ||
| 37 | int err_code, | ||
| 38 | int64_t probe_time_ms) | ||
| 39 | { | ||
| 40 | if (!state || mint_index < 0 || mint_index >= state->count) return; | ||
| 41 | |||
| 42 | tollgate_mint_status_t *m = &state->mints[mint_index]; | ||
| 43 | m->last_probe_ms = probe_time_ms; | ||
| 44 | m->last_http_status = probe_ok ? http_status : 0; | ||
| 45 | m->last_err = probe_ok ? 0 : err_code; | ||
| 46 | |||
| 47 | if (probe_ok) { | ||
| 48 | m->consecutive_successes = TG_MINT_HEALTH_RECOVERY_THRESHOLD; | ||
| 49 | m->reachable = true; | ||
| 50 | } else { | ||
| 51 | m->consecutive_successes = 0; | ||
| 52 | m->reachable = false; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | bool tollgate_core_mint_health_is_reachable(const tollgate_mint_health_t *state, | ||
| 57 | const char *url) | ||
| 58 | { | ||
| 59 | if (!state || !url) return false; | ||
| 60 | for (int i = 0; i < state->count; i++) { | ||
| 61 | if (strcmp(state->mints[i].url, url) == 0 || strstr(url, state->mints[i].url) != NULL) { | ||
| 62 | return state->mints[i].reachable; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | return false; | ||
| 66 | } | ||
| 67 | |||
| 68 | void tollgate_core_mint_health_mark_unreachable(tollgate_mint_health_t *state, | ||
| 69 | const char *url) | ||
| 70 | { | ||
| 71 | if (!state || !url) return; | ||
| 72 | for (int i = 0; i < state->count; i++) { | ||
| 73 | if (strcmp(state->mints[i].url, url) == 0 || strstr(url, state->mints[i].url) != NULL) { | ||
| 74 | if (state->mints[i].reachable) { | ||
| 75 | state->mints[i].reachable = false; | ||
| 76 | state->mints[i].consecutive_successes = 0; | ||
| 77 | } | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | int tollgate_core_mint_health_count_reachable(const tollgate_mint_health_t *state) | ||
| 84 | { | ||
| 85 | if (!state) return 0; | ||
| 86 | int count = 0; | ||
| 87 | for (int i = 0; i < state->count; i++) { | ||
| 88 | if (state->mints[i].reachable) count++; | ||
| 89 | } | ||
| 90 | return count; | ||
| 91 | } | ||
diff --git a/components/tollgate_core/src/tollgate_core_mint_health.h b/components/tollgate_core/src/tollgate_core_mint_health.h new file mode 100644 index 0000000..4435a14 --- /dev/null +++ b/components/tollgate_core/src/tollgate_core_mint_health.h | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | #ifndef TOLLGATE_CORE_MINT_HEALTH_H | ||
| 2 | #define TOLLGATE_CORE_MINT_HEALTH_H | ||
| 3 | |||
| 4 | #include <stdint.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | |||
| 7 | #define TG_MINT_HEALTH_MAX 8 | ||
| 8 | #define TG_MINT_HEALTH_RECOVERY_THRESHOLD 3 | ||
| 9 | |||
| 10 | typedef struct { | ||
| 11 | char url[256]; | ||
| 12 | bool reachable; | ||
| 13 | uint8_t consecutive_successes; | ||
| 14 | int64_t last_probe_ms; | ||
| 15 | int last_http_status; | ||
| 16 | int last_err; | ||
| 17 | } tollgate_mint_status_t; | ||
| 18 | |||
| 19 | typedef struct { | ||
| 20 | tollgate_mint_status_t mints[TG_MINT_HEALTH_MAX]; | ||
| 21 | int count; | ||
| 22 | } tollgate_mint_health_t; | ||
| 23 | |||
| 24 | typedef void (*tollgate_mint_health_changed_fn)(int old_reachable, int new_reachable); | ||
| 25 | |||
| 26 | void tollgate_core_mint_health_init(const char urls[][256], int count); | ||
| 27 | |||
| 28 | void tollgate_core_mint_health_update(tollgate_mint_health_t *state, | ||
| 29 | int mint_index, | ||
| 30 | bool probe_ok, | ||
| 31 | int http_status, | ||
| 32 | int err_code, | ||
| 33 | int64_t probe_time_ms); | ||
| 34 | |||
| 35 | void tollgate_core_mint_health_update_initial(tollgate_mint_health_t *state, | ||
| 36 | int mint_index, | ||
| 37 | bool probe_ok, | ||
| 38 | int http_status, | ||
| 39 | int err_code, | ||
| 40 | int64_t probe_time_ms); | ||
| 41 | |||
| 42 | bool tollgate_core_mint_health_is_reachable(const tollgate_mint_health_t *state, | ||
| 43 | const char *url); | ||
| 44 | |||
| 45 | void tollgate_core_mint_health_mark_unreachable(tollgate_mint_health_t *state, | ||
| 46 | const char *url); | ||
| 47 | |||
| 48 | int tollgate_core_mint_health_count_reachable(const tollgate_mint_health_t *state); | ||
| 49 | |||
| 50 | #endif | ||
diff --git a/components/tollgate_core/src/tollgate_core_portal.c b/components/tollgate_core/src/tollgate_core_portal.c new file mode 100644 index 0000000..ef2ae1e --- /dev/null +++ b/components/tollgate_core/src/tollgate_core_portal.c | |||
| @@ -0,0 +1,149 @@ | |||
| 1 | #include "tollgate_core_portal.h" | ||
| 2 | #include <string.h> | ||
| 3 | #include <stdio.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | |||
| 6 | static const char *CAPTIVE_URIS[] = { | ||
| 7 | "/generate_204", | ||
| 8 | "/hotspot-detect.html", | ||
| 9 | "/canonical.html", | ||
| 10 | "/success.txt", | ||
| 11 | "/ncsi.txt", | ||
| 12 | "/connecttest.txt", | ||
| 13 | "/wpad.dat", | ||
| 14 | NULL | ||
| 15 | }; | ||
| 16 | |||
| 17 | char *tollgate_core_portal_template_replace(const char *tpl, const char *key, const char *val) | ||
| 18 | { | ||
| 19 | const char *p; | ||
| 20 | size_t klen = strlen(key); | ||
| 21 | size_t vlen = strlen(val); | ||
| 22 | size_t tlen = strlen(tpl); | ||
| 23 | size_t extra = 0; | ||
| 24 | |||
| 25 | p = tpl; | ||
| 26 | while ((p = strstr(p, key)) != NULL) { | ||
| 27 | extra += vlen - klen; | ||
| 28 | p += klen; | ||
| 29 | } | ||
| 30 | |||
| 31 | size_t out_size = tlen + extra + 1; | ||
| 32 | char *out = malloc(out_size); | ||
| 33 | if (!out) return NULL; | ||
| 34 | |||
| 35 | char *dst = out; | ||
| 36 | p = tpl; | ||
| 37 | while (*p) { | ||
| 38 | const char *found = strstr(p, key); | ||
| 39 | if (found) { | ||
| 40 | memcpy(dst, p, found - p); | ||
| 41 | dst += found - p; | ||
| 42 | memcpy(dst, val, vlen); | ||
| 43 | dst += vlen; | ||
| 44 | p = found + klen; | ||
| 45 | } else { | ||
| 46 | strcpy(dst, p); | ||
| 47 | dst += strlen(p); | ||
| 48 | break; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | *dst = '\0'; | ||
| 52 | return out; | ||
| 53 | } | ||
| 54 | |||
| 55 | char *tollgate_core_portal_render(const char *tpl, | ||
| 56 | const tollgate_portal_sub_t *subs, | ||
| 57 | int nsubs) | ||
| 58 | { | ||
| 59 | size_t tpl_len = strlen(tpl); | ||
| 60 | |||
| 61 | size_t extra = 0; | ||
| 62 | for (int i = 0; i < nsubs; i++) { | ||
| 63 | const char *p = tpl; | ||
| 64 | size_t klen = strlen(subs[i].key); | ||
| 65 | while ((p = strstr(p, subs[i].key)) != NULL) { | ||
| 66 | extra += strlen(subs[i].val) - klen; | ||
| 67 | p += klen; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | size_t out_size = tpl_len + extra + 1; | ||
| 72 | char *html = malloc(out_size); | ||
| 73 | if (!html) return NULL; | ||
| 74 | |||
| 75 | char *out = html; | ||
| 76 | const char *src = tpl; | ||
| 77 | while (*src) { | ||
| 78 | const char *earliest = NULL; | ||
| 79 | int ei = -1; | ||
| 80 | for (int i = 0; i < nsubs; i++) { | ||
| 81 | const char *found = strstr(src, subs[i].key); | ||
| 82 | if (found && (earliest == NULL || found < earliest)) { | ||
| 83 | earliest = found; | ||
| 84 | ei = i; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | if (earliest) { | ||
| 88 | size_t vlen = strlen(subs[ei].val); | ||
| 89 | memcpy(out, src, earliest - src); | ||
| 90 | out += earliest - src; | ||
| 91 | memcpy(out, subs[ei].val, vlen); | ||
| 92 | out += vlen; | ||
| 93 | src = earliest + strlen(subs[ei].key); | ||
| 94 | } else { | ||
| 95 | strcpy(out, src); | ||
| 96 | out += strlen(src); | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | *out = '\0'; | ||
| 101 | return html; | ||
| 102 | } | ||
| 103 | |||
| 104 | bool tollgate_core_portal_calc_usage(const tg_session_t *session, | ||
| 105 | const char *metric, | ||
| 106 | int64_t now_ms, | ||
| 107 | int64_t *remaining_out, | ||
| 108 | int64_t *total_out) | ||
| 109 | { | ||
| 110 | if (!session || !session->active) return false; | ||
| 111 | |||
| 112 | bool is_bytes = (strcmp(metric, "bytes") == 0); | ||
| 113 | |||
| 114 | if (is_bytes) { | ||
| 115 | int64_t remaining = (int64_t)session->allotment_bytes - (int64_t)session->bytes_consumed; | ||
| 116 | if (remaining < 0) remaining = 0; | ||
| 117 | *remaining_out = remaining; | ||
| 118 | *total_out = (int64_t)session->allotment_bytes; | ||
| 119 | } else { | ||
| 120 | int64_t elapsed = now_ms - session->start_time_ms; | ||
| 121 | int64_t remaining = (int64_t)session->allotment_ms - elapsed; | ||
| 122 | if (remaining < 0) remaining = 0; | ||
| 123 | *remaining_out = remaining; | ||
| 124 | *total_out = (int64_t)session->allotment_ms; | ||
| 125 | } | ||
| 126 | return true; | ||
| 127 | } | ||
| 128 | |||
| 129 | int tollgate_core_portal_format_usage(const tg_session_t *session, | ||
| 130 | const char *metric, | ||
| 131 | int64_t now_ms, | ||
| 132 | char *buf, | ||
| 133 | size_t buf_size) | ||
| 134 | { | ||
| 135 | int64_t remaining = 0, total = 0; | ||
| 136 | if (!tollgate_core_portal_calc_usage(session, metric, now_ms, &remaining, &total)) { | ||
| 137 | return snprintf(buf, buf_size, "-1/-1"); | ||
| 138 | } | ||
| 139 | return snprintf(buf, buf_size, "%lld/%llu", (long long)remaining, (unsigned long long)total); | ||
| 140 | } | ||
| 141 | |||
| 142 | bool tollgate_core_portal_is_captive_uri(const char *uri) | ||
| 143 | { | ||
| 144 | if (!uri) return false; | ||
| 145 | for (int i = 0; CAPTIVE_URIS[i] != NULL; i++) { | ||
| 146 | if (strcmp(uri, CAPTIVE_URIS[i]) == 0) return true; | ||
| 147 | } | ||
| 148 | return false; | ||
| 149 | } | ||
diff --git a/components/tollgate_core/src/tollgate_core_portal.h b/components/tollgate_core/src/tollgate_core_portal.h new file mode 100644 index 0000000..20c0552 --- /dev/null +++ b/components/tollgate_core/src/tollgate_core_portal.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #ifndef TOLLGATE_CORE_PORTAL_H | ||
| 2 | #define TOLLGATE_CORE_PORTAL_H | ||
| 3 | |||
| 4 | #include "tollgate_core_session.h" | ||
| 5 | #include <stdint.h> | ||
| 6 | #include <stddef.h> | ||
| 7 | #include <stdbool.h> | ||
| 8 | |||
| 9 | typedef struct { | ||
| 10 | const char *key; | ||
| 11 | const char *val; | ||
| 12 | } tollgate_portal_sub_t; | ||
| 13 | |||
| 14 | char *tollgate_core_portal_template_replace(const char *tpl, const char *key, const char *val); | ||
| 15 | |||
| 16 | char *tollgate_core_portal_render(const char *tpl, | ||
| 17 | const tollgate_portal_sub_t *subs, | ||
| 18 | int nsubs); | ||
| 19 | |||
| 20 | bool tollgate_core_portal_calc_usage(const tg_session_t *session, | ||
| 21 | const char *metric, | ||
| 22 | int64_t now_ms, | ||
| 23 | int64_t *remaining_out, | ||
| 24 | int64_t *total_out); | ||
| 25 | |||
| 26 | int tollgate_core_portal_format_usage(const tg_session_t *session, | ||
| 27 | const char *metric, | ||
| 28 | int64_t now_ms, | ||
| 29 | char *buf, | ||
| 30 | size_t buf_size); | ||
| 31 | |||
| 32 | bool tollgate_core_portal_is_captive_uri(const char *uri); | ||
| 33 | |||
| 34 | #endif | ||
diff --git a/components/tollgate_core/src/tollgate_core_stratum_client.c b/components/tollgate_core/src/tollgate_core_stratum_client.c new file mode 100644 index 0000000..8cf22da --- /dev/null +++ b/components/tollgate_core/src/tollgate_core_stratum_client.c | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | #include "tollgate_core_stratum_client.h" | ||
| 2 | #include "cJSON.h" | ||
| 3 | #include <string.h> | ||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdlib.h> | ||
| 6 | |||
| 7 | void tollgate_core_stratum_hex_to_bytes(const char *hex, uint8_t *out, int len) | ||
| 8 | { | ||
| 9 | for (int i = 0; i < len && hex[i * 2] && hex[i * 2 + 1]; i++) { | ||
| 10 | char byte[3] = {hex[i * 2], hex[i * 2 + 1], 0}; | ||
| 11 | out[i] = (uint8_t)strtoul(byte, NULL, 16); | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | bool tollgate_core_stratum_parse_notify(const void *params_json, | ||
| 16 | tollgate_stratum_job_t *job, | ||
| 17 | uint32_t *out_nbits) | ||
| 18 | { | ||
| 19 | const cJSON *params = (const cJSON *)params_json; | ||
| 20 | if (!params || !cJSON_IsArray(params) || cJSON_GetArraySize(params) < 6) return false; | ||
| 21 | |||
| 22 | const cJSON *p_job_id = cJSON_GetArrayItem(params, 0); | ||
| 23 | const cJSON *p_prevhash = cJSON_GetArrayItem(params, 1); | ||
| 24 | const cJSON *p_version = cJSON_GetArrayItem(params, 5); | ||
| 25 | const cJSON *p_nbits = cJSON_GetArrayItem(params, 6); | ||
| 26 | const cJSON *p_ntime = cJSON_GetArrayItem(params, 7); | ||
| 27 | |||
| 28 | if (!p_job_id || !p_prevhash || !p_nbits) return false; | ||
| 29 | |||
| 30 | memset(job, 0, sizeof(*job)); | ||
| 31 | job->job_id = (uint32_t)atoi(p_job_id->valuestring); | ||
| 32 | job->valid = true; | ||
| 33 | |||
| 34 | tollgate_core_stratum_hex_to_bytes(p_prevhash->valuestring, job->prevhash, 32); | ||
| 35 | |||
| 36 | if (p_version && cJSON_IsString(p_version)) { | ||
| 37 | job->version = (uint32_t)strtoul(p_version->valuestring, NULL, 16); | ||
| 38 | } | ||
| 39 | if (p_nbits && cJSON_IsString(p_nbits)) { | ||
| 40 | job->nbits = (uint32_t)strtoul(p_nbits->valuestring, NULL, 16); | ||
| 41 | if (out_nbits) *out_nbits = job->nbits; | ||
| 42 | } | ||
| 43 | if (p_ntime && cJSON_IsString(p_ntime)) { | ||
| 44 | job->ntime = (uint32_t)strtoul(p_ntime->valuestring, NULL, 16); | ||
| 45 | } | ||
| 46 | |||
| 47 | memset(job->target, 0xFF, 32); | ||
| 48 | job->target_len = 32; | ||
| 49 | |||
| 50 | return true; | ||
| 51 | } | ||
| 52 | |||
| 53 | bool tollgate_core_stratum_parse_difficulty(const void *params_json, | ||
| 54 | uint64_t *difficulty_out) | ||
| 55 | { | ||
| 56 | const cJSON *params = (const cJSON *)params_json; | ||
| 57 | if (!params || !cJSON_IsArray(params) || cJSON_GetArraySize(params) < 1) return false; | ||
| 58 | |||
| 59 | const cJSON *diff = cJSON_GetArrayItem(params, 0); | ||
| 60 | if (diff && cJSON_IsNumber(diff)) { | ||
| 61 | *difficulty_out = (uint64_t)diff->valuedouble; | ||
| 62 | return true; | ||
| 63 | } | ||
| 64 | return false; | ||
| 65 | } | ||
| 66 | |||
| 67 | int tollgate_core_stratum_build_subscribe(char *buf, size_t buf_size, uint32_t req_id) | ||
| 68 | { | ||
| 69 | return snprintf(buf, buf_size, | ||
| 70 | "{\"id\":%lu,\"method\":\"mining.subscribe\",\"params\":[\"TollGate/1.0\"]}\n", | ||
| 71 | (unsigned long)req_id); | ||
| 72 | } | ||
| 73 | |||
| 74 | int tollgate_core_stratum_build_authorize(char *buf, size_t buf_size, uint32_t req_id, | ||
| 75 | const char *user, const char *pass) | ||
| 76 | { | ||
| 77 | return snprintf(buf, buf_size, | ||
| 78 | "{\"id\":%lu,\"method\":\"mining.authorize\",\"params\":[\"%s\",\"%s\"]}\n", | ||
| 79 | (unsigned long)req_id, user, pass); | ||
| 80 | } | ||
| 81 | |||
| 82 | int tollgate_core_stratum_build_submit(char *buf, size_t buf_size, uint32_t req_id, | ||
| 83 | const char *user, uint32_t job_id, | ||
| 84 | uint32_t ntime, uint32_t nonce, uint32_t version) | ||
| 85 | { | ||
| 86 | return snprintf(buf, buf_size, | ||
| 87 | "{\"id\":%lu,\"method\":\"mining.submit\",\"params\":[\"%s\",\"%lu\",\"%08lx\",\"%08lx\",\"%08lx\"]}\n", | ||
| 88 | (unsigned long)req_id, user, | ||
| 89 | (unsigned long)job_id, (unsigned long)ntime, | ||
| 90 | (unsigned long)nonce, (unsigned long)version); | ||
| 91 | } | ||
diff --git a/components/tollgate_core/src/tollgate_core_stratum_client.h b/components/tollgate_core/src/tollgate_core_stratum_client.h new file mode 100644 index 0000000..fdcce1c --- /dev/null +++ b/components/tollgate_core/src/tollgate_core_stratum_client.h | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | #ifndef TOLLGATE_CORE_STRATUM_CLIENT_H | ||
| 2 | #define TOLLGATE_CORE_STRATUM_CLIENT_H | ||
| 3 | |||
| 4 | #include <stdint.h> | ||
| 5 | #include <stddef.h> | ||
| 6 | #include <stdbool.h> | ||
| 7 | |||
| 8 | #define TG_STRATUM_MAX_JOB_ID_LEN 32 | ||
| 9 | |||
| 10 | typedef struct { | ||
| 11 | uint32_t job_id; | ||
| 12 | uint8_t prevhash[32]; | ||
| 13 | uint8_t merkle_root[32]; | ||
| 14 | uint32_t ntime; | ||
| 15 | uint32_t nbits; | ||
| 16 | uint32_t version; | ||
| 17 | uint8_t target[32]; | ||
| 18 | int target_len; | ||
| 19 | bool valid; | ||
| 20 | } tollgate_stratum_job_t; | ||
| 21 | |||
| 22 | typedef struct { | ||
| 23 | bool connected; | ||
| 24 | char pool_host[128]; | ||
| 25 | uint16_t pool_port; | ||
| 26 | uint32_t nbits; | ||
| 27 | uint64_t difficulty; | ||
| 28 | uint64_t shares_accepted; | ||
| 29 | uint64_t shares_rejected; | ||
| 30 | } tollgate_stratum_client_state_t; | ||
| 31 | |||
| 32 | void tollgate_core_stratum_hex_to_bytes(const char *hex, uint8_t *out, int len); | ||
| 33 | |||
| 34 | bool tollgate_core_stratum_parse_notify(const void *params_json, | ||
| 35 | tollgate_stratum_job_t *job, | ||
| 36 | uint32_t *out_nbits); | ||
| 37 | |||
| 38 | bool tollgate_core_stratum_parse_difficulty(const void *params_json, | ||
| 39 | uint64_t *difficulty_out); | ||
| 40 | |||
| 41 | int tollgate_core_stratum_build_subscribe(char *buf, size_t buf_size, uint32_t req_id); | ||
| 42 | |||
| 43 | int tollgate_core_stratum_build_authorize(char *buf, size_t buf_size, uint32_t req_id, | ||
| 44 | const char *user, const char *pass); | ||
| 45 | |||
| 46 | int tollgate_core_stratum_build_submit(char *buf, size_t buf_size, uint32_t req_id, | ||
| 47 | const char *user, uint32_t job_id, | ||
| 48 | uint32_t ntime, uint32_t nonce, uint32_t version); | ||
| 49 | |||
| 50 | #endif | ||