LCOV - code coverage report
Current view: top level - src/domain/read - contacts.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.6 % 44 39
Test Date: 2026-04-20 19:54:22 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /* SPDX-License-Identifier: GPL-3.0-or-later */
       2              : /* Copyright 2026 Peter Csaszar */
       3              : 
       4              : /**
       5              :  * @file domain/read/contacts.c
       6              :  */
       7              : 
       8              : #include "domain/read/contacts.h"
       9              : 
      10              : #include "tl_serial.h"
      11              : #include "tl_registry.h"
      12              : #include "mtproto_rpc.h"
      13              : #include "logger.h"
      14              : #include "raii.h"
      15              : 
      16              : #include <stdlib.h>
      17              : #include <string.h>
      18              : 
      19              : #define CRC_contacts_getContacts 0x5dd69e12u
      20              : #define CRC_contact              0x145ade0bu
      21              : 
      22            8 : int domain_get_contacts(const ApiConfig *cfg,
      23              :                          MtProtoSession *s, Transport *t,
      24              :                          ContactEntry *out, int max_entries, int *out_count) {
      25            8 :     if (!cfg || !s || !t || !out || !out_count || max_entries <= 0) return -1;
      26            6 :     *out_count = 0;
      27            6 :     if (max_entries > CONTACTS_MAX) max_entries = CONTACTS_MAX;
      28              : 
      29            6 :     TlWriter w; tl_writer_init(&w);
      30            6 :     tl_write_uint32(&w, CRC_contacts_getContacts);
      31            6 :     tl_write_int64 (&w, 0);  /* hash = 0 → server always returns full list */
      32              :     uint8_t query[32];
      33            6 :     if (w.len > sizeof(query)) { tl_writer_free(&w); return -1; }
      34            6 :     memcpy(query, w.data, w.len);
      35            6 :     size_t qlen = w.len;
      36            6 :     tl_writer_free(&w);
      37              : 
      38            6 :     RAII_STRING uint8_t *resp = (uint8_t *)malloc(65536);
      39            6 :     if (!resp) return -1;
      40            6 :     size_t resp_len = 0;
      41            6 :     if (api_call(cfg, s, t, query, qlen, resp, 65536, &resp_len) != 0) return -1;
      42            6 :     if (resp_len < 4) return -1;
      43              : 
      44              :     uint32_t top;
      45            6 :     memcpy(&top, resp, 4);
      46            6 :     if (top == TL_rpc_error) {
      47            1 :         RpcError err; rpc_parse_error(resp, resp_len, &err);
      48            1 :         logger_log(LOG_ERROR, "contacts: RPC error %d: %s",
      49              :                    err.error_code, err.error_msg);
      50            1 :         return -1;
      51              :     }
      52            5 :     if (top == TL_contacts_contactsNotModified) {
      53              :         /* Server thinks the client-provided hash matches its state.
      54              :          * We passed hash=0, so this shouldn't happen — treat as empty. */
      55            0 :         return 0;
      56              :     }
      57            5 :     if (top != TL_contacts_contacts) {
      58            0 :         logger_log(LOG_ERROR, "contacts: unexpected top 0x%08x", top);
      59            0 :         return -1;
      60              :     }
      61              : 
      62            5 :     TlReader r = tl_reader_init(resp, resp_len);
      63            5 :     tl_read_uint32(&r); /* top constructor */
      64              : 
      65            5 :     uint32_t vec = tl_read_uint32(&r);
      66            5 :     if (vec != TL_vector) return -1;
      67            5 :     uint32_t count = tl_read_uint32(&r);
      68            5 :     int written = 0;
      69           12 :     for (uint32_t i = 0; i < count && written < max_entries; i++) {
      70            7 :         if (!tl_reader_ok(&r)) break;
      71            7 :         uint32_t ccrc = tl_read_uint32(&r);
      72            7 :         if (ccrc != CRC_contact) {
      73            0 :             logger_log(LOG_WARN,
      74              :                        "contacts: unknown Contact 0x%08x — stopping", ccrc);
      75            0 :             break;
      76              :         }
      77            7 :         ContactEntry e = { .user_id = tl_read_int64(&r) };
      78            7 :         int b = tl_read_bool(&r);
      79            7 :         e.mutual = (b == 1) ? 1 : 0;
      80            7 :         out[written++] = e;
      81              :     }
      82            5 :     *out_count = written;
      83            5 :     return 0;
      84              : }
        

Generated by: LCOV version 2.0-1