Line data Source code
1 : /* SPDX-License-Identifier: GPL-3.0-or-later */
2 : /* Copyright 2026 Peter Csaszar */
3 :
4 : /**
5 : * @file app/dc_config.c
6 : * @brief Hardcoded fallback DC endpoint table with runtime overrides (FEAT-38).
7 : */
8 :
9 : #include "app/dc_config.h"
10 :
11 : #include <stddef.h>
12 : #include <stdlib.h>
13 : #include <string.h>
14 :
15 : static const DcEndpoint ENDPOINTS[] = {
16 : { 1, "149.154.175.50", 443 },
17 : { 2, "149.154.167.50", 443 },
18 : { 3, "149.154.175.100", 443 },
19 : { 4, "149.154.167.91", 443 },
20 : { 5, "91.108.56.130", 443 },
21 : };
22 :
23 : #define ENDPOINT_COUNT (sizeof(ENDPOINTS) / sizeof(ENDPOINTS[0]))
24 : #define DC_ID_MAX 5
25 :
26 : /**
27 : * @brief Per-process redirect used by tests.
28 : *
29 : * When TG_CLI_DC_HOST and TG_CLI_DC_PORT are set in the environment every
30 : * dc_lookup() call returns a synthetic endpoint pointing at those
31 : * coordinates. This lets the PTY-based functional tests redirect the
32 : * production binary to a local stub server without modifying the binary or
33 : * the DC table.
34 : */
35 : static DcEndpoint g_env_override;
36 :
37 : /**
38 : * FEAT-38: Per-DC host overrides from config.ini.
39 : * Index 0 = DC1 … index 4 = DC5. NULL means use the compiled-in default.
40 : */
41 : static char *g_host_overrides[DC_ID_MAX]; /* heap-allocated or NULL */
42 : static DcEndpoint g_config_override; /* scratch space for the returned value */
43 :
44 62 : void dc_config_set_host_override(int dc_id, const char *host) {
45 62 : if (dc_id < 1 || dc_id > DC_ID_MAX) return;
46 62 : int idx = dc_id - 1;
47 :
48 62 : free(g_host_overrides[idx]);
49 62 : g_host_overrides[idx] = NULL;
50 :
51 62 : if (host && *host) {
52 2 : g_host_overrides[idx] = strdup(host);
53 : }
54 : }
55 :
56 58 : const DcEndpoint *dc_lookup(int dc_id) {
57 : /* Negative dc_id is used for Telegram test DCs: dc=-N maps to the same
58 : * endpoint as dc=N for connection purposes. The caller keeps the signed
59 : * value to embed it in p_q_inner_data_dc.
60 : * dc=0 is a wildcard accepted by Telegram test servers — connect to
61 : * DEFAULT_DC_ID's endpoint so the transport works. */
62 58 : int abs_id = (dc_id == 0) ? DEFAULT_DC_ID
63 58 : : (dc_id < 0) ? -dc_id
64 : : dc_id;
65 :
66 : /* Environment redirect takes highest priority (used by integration tests). */
67 58 : const char *env_host = getenv("TG_CLI_DC_HOST");
68 58 : const char *env_port = getenv("TG_CLI_DC_PORT");
69 58 : if (env_host && *env_host && env_port && *env_port) {
70 0 : g_env_override.id = dc_id;
71 0 : g_env_override.host = env_host;
72 0 : g_env_override.port = atoi(env_port);
73 0 : return &g_env_override;
74 : }
75 :
76 : /* config.ini override (FEAT-38) — applies only if the absolute DC id is valid. */
77 58 : if (abs_id >= 1 && abs_id <= DC_ID_MAX && g_host_overrides[abs_id - 1]) {
78 : /* Find the built-in entry to inherit the port. */
79 4 : for (size_t i = 0; i < ENDPOINT_COUNT; i++) {
80 4 : if (ENDPOINTS[i].id == abs_id) {
81 2 : g_config_override.id = dc_id;
82 2 : g_config_override.host = g_host_overrides[abs_id - 1];
83 2 : g_config_override.port = ENDPOINTS[i].port;
84 2 : return &g_config_override;
85 : }
86 : }
87 : }
88 :
89 : /* Fall back to compiled-in table (match on absolute id). */
90 192 : for (size_t i = 0; i < ENDPOINT_COUNT; i++) {
91 187 : if (ENDPOINTS[i].id == abs_id) {
92 51 : g_config_override.id = dc_id;
93 51 : g_config_override.host = ENDPOINTS[i].host;
94 51 : g_config_override.port = ENDPOINTS[i].port;
95 51 : return &g_config_override;
96 : }
97 : }
98 5 : return NULL;
99 : }
|