• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ska-sa / spead2 / 5891294988

17 Aug 2023 01:03PM UTC coverage: 74.962% (-0.03%) from 74.99%
5891294988

push

github

bmerry
Fix a lingering reference to C++11

5422 of 7233 relevant lines covered (74.96%)

52656.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.15
/src/recv_packet.cpp
1
/* Copyright 2015, 2023 National Research Foundation (SARAO)
2
 *
3
 * This program is free software: you can redistribute it and/or modify it under
4
 * the terms of the GNU Lesser General Public License as published by the Free
5
 * Software Foundation, either version 3 of the License, or (at your option) any
6
 * later version.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
11
 * details.
12
 *
13
 * You should have received a copy of the GNU Lesser General Public License
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 */
16

17
/**
18
 * @file
19
 */
20

21
#include <cassert>
22
#include <cstring>
23
#include <spead2/recv_packet.h>
24
#include <spead2/recv_utils.h>
25
#include <spead2/common_defines.h>
26
#include <spead2/common_logging.h>
27
#include <spead2/common_endian.h>
28

29
namespace spead2::recv
30
{
31

32
/**
33
 * Retrieve bits [first, first+cnt) from a field.
34
 *
35
 * @pre 0 &lt;= @a first &lt; @a first + @a cnt &lt;= @a n and @a cnt &lt; @a n,
36
 * where @a n is the number of bits in T.
37
 */
38
template<typename T>
39
static inline T extract_bits(T value, int first, int cnt)
98,297✔
40
{
41
    assert(0 <= first && first + cnt <= 8 * sizeof(T));
284✔
42
    assert(cnt > 0 && cnt < 8 * sizeof(T));
284✔
43
    return (value >> first) & ((T(1) << cnt) - 1);
98,297✔
44
}
45

46
static bool decode_header(const uint8_t *data, int &heap_address_bits, int &n_items)
24,591✔
47
{
48
    std::uint64_t header = load_be<std::uint64_t>(data);
24,591✔
49
    if (extract_bits(header, 48, 16) != magic_version)
24,585✔
50
    {
51
        log_info("packet rejected because magic or version did not match");
1✔
52
        return false;
1✔
53
    }
54
    int item_id_bits = extract_bits(header, 40, 8) * 8;
24,582✔
55
    heap_address_bits = extract_bits(header, 32, 8) * 8;
24,578✔
56
    if (item_id_bits == 0 || heap_address_bits == 0)
24,579✔
57
    {
58
        log_info("packet rejected because flavour is invalid");
×
59
        return false;
×
60
    }
61
    if (item_id_bits + heap_address_bits != 8 * sizeof(item_pointer_t))
24,579✔
62
    {
63
        log_info("packet rejected because flavour is not SPEAD-64-*");
×
64
        return false;
×
65
    }
66

67
    n_items = extract_bits(header, 0, 16);
24,579✔
68
    return true;
24,566✔
69
}
70

71
s_item_pointer_t get_packet_size(const uint8_t *data, std::size_t length)
702✔
72
{
73
    if (length < 8)
702✔
74
        return 0;
1✔
75
    int heap_address_bits, n_items;
76
    if (!decode_header(data, heap_address_bits, n_items))
701✔
77
        return -1;
1✔
78
    if (std::size_t(n_items) * sizeof(item_pointer_t) + 8 > length)
700✔
79
        return 0;
1✔
80

81
    pointer_decoder decoder(heap_address_bits);
699✔
82
    s_item_pointer_t payload_length = -1;
699✔
83
    for (int i = 0; i < n_items; i++)
2,792✔
84
    {
85
        item_pointer_t pointer = load_be<item_pointer_t>(data + 8 + i * sizeof(item_pointer_t));
2,792✔
86
        if (decoder.is_immediate(pointer) && decoder.get_id(pointer) == PAYLOAD_LENGTH_ID)
2,792✔
87
        {
88
            payload_length = decoder.get_immediate(pointer);
699✔
89
            break;
699✔
90
        }
91
    }
92
    if (payload_length == -1)
699✔
93
        return -1;
×
94
    return payload_length + n_items * sizeof(item_pointer_t) + 8;
699✔
95
}
96

97
std::size_t decode_packet(packet_header &out, const uint8_t *data, std::size_t max_size)
23,904✔
98
{
99
    if (max_size < 8)
23,904✔
100
    {
101
        log_info("packet rejected because too small (%d bytes)", max_size);
×
102
        return 0;
×
103
    }
104
    if (!decode_header(data, out.heap_address_bits, out.n_items))
23,904✔
105
        return 0;
×
106
    if (std::size_t(out.n_items) * sizeof(item_pointer_t) + 8 > max_size)
23,865✔
107
    {
108
        log_info("packet rejected because the items overflow the packet");
×
109
        return 0;
×
110
    }
111

112
    // Mark specials as not found
113
    out.heap_cnt = -1;
23,865✔
114
    out.heap_length = -1;
23,865✔
115
    out.payload_offset = -1;
23,865✔
116
    out.payload_length = -1;
23,865✔
117
    // Look for special items
118
    pointer_decoder decoder(out.heap_address_bits);
23,865✔
119
    int first_regular = out.n_items;
23,864✔
120
    for (int i = 0; i < out.n_items; i++)
134,885✔
121
    {
122
        item_pointer_t pointer = load_be<item_pointer_t>(data + 8 + i * sizeof(item_pointer_t));
110,927✔
123
        bool special;
124
        if (decoder.is_immediate(pointer))
110,917✔
125
        {
126
            special = true;
100,994✔
127
            switch (decoder.get_id(pointer))
100,994✔
128
            {
129
            case HEAP_CNT_ID:
23,855✔
130
                out.heap_cnt = decoder.get_immediate(pointer);
23,855✔
131
                break;
23,855✔
132
            case HEAP_LENGTH_ID:
23,859✔
133
                out.heap_length = decoder.get_immediate(pointer);
23,859✔
134
                break;
23,860✔
135
            case PAYLOAD_OFFSET_ID:
23,863✔
136
                out.payload_offset = decoder.get_immediate(pointer);
23,863✔
137
                break;
23,868✔
138
            case PAYLOAD_LENGTH_ID:
23,778✔
139
                out.payload_length = decoder.get_immediate(pointer);
23,778✔
140
                break;
23,871✔
141
            default:
5,645✔
142
                special = false;
5,645✔
143
                break;
5,645✔
144
            }
145
        }
146
        else
147
            special = false;
9,922✔
148
        if (!special)
111,021✔
149
            first_regular = std::min(first_regular, i);
15,565✔
150
    }
151
    if (out.heap_cnt == -1 || out.payload_offset == -1 || out.payload_length == -1)
23,958✔
152
    {
153
        log_info("packet rejected because it does not have required items");
85✔
154
        return 0;
×
155
    }
156
    std::size_t size = out.payload_length + out.n_items * sizeof(item_pointer_t) + 8;
23,873✔
157
    if (size > max_size)
23,873✔
158
    {
159
        log_info("packet rejected because payload length overflows packet size (%d > %d)",
×
160
                  size, max_size);
161
        return 0;
×
162
    }
163
    if (out.heap_length >= 0 && out.payload_offset + out.payload_length > out.heap_length)
23,873✔
164
    {
165
        log_info("packet rejected because payload would overflow given heap length");
×
166
        return 0;
×
167
    }
168

169
    // Adjust the pointers to skip the specials, since live_heap::add_packet does not
170
    // need them
171
    out.pointers = data + 8 + first_regular * sizeof(item_pointer_t);
23,873✔
172
    out.n_items -= first_regular;
23,873✔
173
    out.payload = out.pointers + out.n_items * sizeof(item_pointer_t);
23,873✔
174
    out.packet = data;
23,873✔
175
    return size;
23,873✔
176
}
177

178
} // namespace spead2::recv
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc