Line data Source code
1 : /* SPDX-License-Identifier: GPL-3.0-or-later */
2 : /* Copyright 2026 Peter Csaszar */
3 :
4 : /**
5 : * @file domain/write/forward.c
6 : * @brief messages.forwardMessages (US-P5-06).
7 : */
8 :
9 : #include "domain/write/forward.h"
10 :
11 : #include "tl_serial.h"
12 : #include "tl_registry.h"
13 : #include "mtproto_rpc.h"
14 : #include "crypto.h"
15 : #include "logger.h"
16 :
17 : #include <string.h>
18 :
19 : #define CRC_messages_forwardMessages 0xc661bbc4u
20 :
21 2 : static int write_input_peer(TlWriter *w, const HistoryPeer *p) {
22 2 : switch (p->kind) {
23 1 : case HISTORY_PEER_SELF:
24 1 : tl_write_uint32(w, TL_inputPeerSelf); return 0;
25 1 : case HISTORY_PEER_USER:
26 1 : tl_write_uint32(w, TL_inputPeerUser);
27 1 : tl_write_int64 (w, p->peer_id);
28 1 : tl_write_int64 (w, p->access_hash); return 0;
29 0 : case HISTORY_PEER_CHAT:
30 0 : tl_write_uint32(w, TL_inputPeerChat);
31 0 : tl_write_int64 (w, p->peer_id); return 0;
32 0 : case HISTORY_PEER_CHANNEL:
33 0 : tl_write_uint32(w, TL_inputPeerChannel);
34 0 : tl_write_int64 (w, p->peer_id);
35 0 : tl_write_int64 (w, p->access_hash); return 0;
36 0 : default: return -1;
37 : }
38 : }
39 :
40 1 : int domain_forward_messages(const ApiConfig *cfg,
41 : MtProtoSession *s, Transport *t,
42 : const HistoryPeer *from,
43 : const HistoryPeer *to,
44 : const int32_t *ids, int n_ids,
45 : RpcError *err) {
46 1 : if (!cfg || !s || !t || !from || !to || !ids || n_ids <= 0 || n_ids > 100)
47 0 : return -1;
48 :
49 1 : TlWriter w; tl_writer_init(&w);
50 1 : tl_write_uint32(&w, CRC_messages_forwardMessages);
51 1 : tl_write_uint32(&w, 0); /* flags = 0 */
52 1 : if (write_input_peer(&w, from) != 0) { tl_writer_free(&w); return -1; }
53 1 : tl_write_uint32(&w, TL_vector); /* id vector */
54 1 : tl_write_uint32(&w, (uint32_t)n_ids);
55 3 : for (int i = 0; i < n_ids; i++) tl_write_int32(&w, ids[i]);
56 1 : tl_write_uint32(&w, TL_vector); /* random_id vector */
57 1 : tl_write_uint32(&w, (uint32_t)n_ids);
58 3 : for (int i = 0; i < n_ids; i++) {
59 : uint8_t rnd[8];
60 2 : int64_t rid = 0;
61 2 : if (crypto_rand_bytes(rnd, 8) == 0) memcpy(&rid, rnd, 8);
62 2 : tl_write_int64(&w, rid);
63 : }
64 1 : if (write_input_peer(&w, to) != 0) { tl_writer_free(&w); return -1; }
65 :
66 : uint8_t query[2048];
67 1 : if (w.len > sizeof(query)) { tl_writer_free(&w); return -1; }
68 1 : memcpy(query, w.data, w.len);
69 1 : size_t qlen = w.len;
70 1 : tl_writer_free(&w);
71 :
72 1 : uint8_t resp[4096]; size_t resp_len = 0;
73 1 : if (api_call(cfg, s, t, query, qlen, resp, sizeof(resp), &resp_len) != 0) {
74 0 : logger_log(LOG_ERROR, "forward: api_call failed");
75 0 : return -1;
76 : }
77 1 : if (resp_len < 4) return -1;
78 :
79 : uint32_t top;
80 1 : memcpy(&top, resp, 4);
81 1 : if (top == TL_rpc_error) {
82 0 : if (err) rpc_parse_error(resp, resp_len, err);
83 0 : return -1;
84 : }
85 1 : if (top == TL_updates || top == TL_updatesCombined
86 0 : || top == TL_updateShort) {
87 1 : return 0;
88 : }
89 0 : logger_log(LOG_WARN, "forward: unexpected top 0x%08x", top);
90 0 : return 0;
91 : }
|