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

ska-sa / spead2 / 6314725912

26 Sep 2023 03:12PM UTC coverage: 78.166% (-0.06%) from 78.228%
6314725912

Pull #285

github

web-flow
Merge 81f377ca7 into 5f29604f6
Pull Request #285: Allow stream to be explicitly started

68 of 68 new or added lines in 10 files covered. (100.0%)

5320 of 6806 relevant lines covered (78.17%)

56149.81 hits per line

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

0.0
/src/recv_udp_pcap.cpp
1
/* Copyright 2016-2017, 2019, 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 <spead2/common_features.h>
22
#if SPEAD2_USE_PCAP
23
#include <cassert>
24
#include <cstdint>
25
#include <string>
26
#include <functional>
27
#include <spead2/recv_stream.h>
28
#include <spead2/recv_udp_base.h>
29
#include <spead2/recv_udp_pcap.h>
30
#include <spead2/common_raw_packet.h>
31
#include <spead2/common_logging.h>
32

33
// These are defined in pcap/dlt.h for libpcap >= 1.8.0, but in pcap/bfp.h otherwise
34
// We define them here to avoid having to guess which file to include
35
#ifndef DLT_EN10MB
36
#define DLT_EN10MB 1
37
#endif
38
#ifndef DLT_LINUX_SLL
39
#define DLT_LINUX_SLL 113
40
#endif
41

42
namespace spead2::recv
43
{
44

45
void udp_pcap_file_reader::run(handler_context ctx, stream_base::add_packet_state &state)
×
46
{
47
    const int BATCH = 64;  // maximum number of packets to process in one go
×
48

49
    for (int pass = 0; pass < BATCH; pass++)
×
50
    {
51
        if (state.is_stopped())
×
52
            break;
×
53
        struct pcap_pkthdr *h;
54
        const u_char *pkt_data;
55
        int status = pcap_next_ex(handle, &h, &pkt_data);
×
56
        switch (status)
×
57
        {
58
        case 1:
×
59
            // Successful read
60
            if (h->caplen < h->len)
×
61
            {
62
                log_warning("Packet was truncated (%d < %d)", h->caplen, h->len);
×
63
            }
64
            else
65
            {
66
                try
67
                {
68
                    void *bytes = const_cast<void *>((const void *) pkt_data);
×
69
                    packet_buffer payload = udp_from_frame(bytes, h->len);
×
70
                    process_one_packet(state, payload.data(), payload.size(), payload.size());
×
71
                }
72
                catch (packet_type_error &e)
×
73
                {
74
                    log_warning(e.what());
×
75
                }
×
76
                catch (std::length_error &e)
×
77
                {
78
                    log_warning(e.what());
×
79
                }
×
80
            }
81
            break;
×
82
        case -1:
×
83
            log_warning("Error reading packet: %s", pcap_geterr(handle));
×
84
            break;
×
85
        case -2:
×
86
            // End of file
87
            state.stop();
×
88
            break;
×
89
        }
90
    }
91
    // Run ourselves again
92
    if (!state.is_stopped())
×
93
    {
94
        using namespace std::placeholders;
95
        boost::asio::post(get_io_service(), bind_handler(std::move(ctx), std::bind(&udp_pcap_file_reader::run, this, _1, _2)));
×
96
    }
97
}
×
98

99
udp_pcap_file_reader::udp_pcap_file_reader(stream &owner, const std::string &filename, const std::string &user_filter)
×
100
    : udp_reader_base(owner)
×
101
{
102
    // Open the file
103
    char errbuf[PCAP_ERRBUF_SIZE];
104
    handle = pcap_open_offline(filename.c_str(), errbuf);
×
105
    if (!handle)
×
106
        throw std::runtime_error(errbuf);
×
107
    // Set a filter to ensure that we only get UDP4 packets with no fragmentation
108
    bpf_program filter;
109
    std::string filter_expression = "ip proto \\udp and ip[6:2] & 0x3fff = 0";
×
110
    if (!user_filter.empty())
×
111
        filter_expression += " and (" + user_filter + ')';
×
112
    if (pcap_compile(handle, &filter,
×
113
                     filter_expression.c_str(),
114
                     1, PCAP_NETMASK_UNKNOWN) != 0)
×
115
        throw std::runtime_error(pcap_geterr(handle));
×
116
    if (pcap_setfilter(handle, &filter) != 0)
×
117
    {
118
        std::runtime_error error(pcap_geterr(handle));
×
119
        pcap_freecode(&filter);
×
120
        throw error;
×
121
    }
×
122
    pcap_freecode(&filter);
×
123
    // The link type used to record this file
124
    auto linktype = pcap_datalink(handle);
×
125
    assert(linktype != PCAP_ERROR_NOT_ACTIVATED);
×
126
    if (linktype != DLT_EN10MB && linktype != DLT_LINUX_SLL)
×
127
        throw packet_type_error("pcap linktype is neither ethernet nor linux sll");
×
128
    udp_from_frame = (linktype == DLT_EN10MB) ? udp_from_ethernet : udp_from_linux_sll;
×
129
}
×
130

131
void udp_pcap_file_reader::start()
×
132
{
133
    // Process the file
134
    using namespace std::placeholders;
135
    boost::asio::post(get_io_service(), bind_handler(std::bind(&udp_pcap_file_reader::run, this, _1, _2)));
×
136
}
×
137

138
udp_pcap_file_reader::~udp_pcap_file_reader()
×
139
{
140
    if (handle)
×
141
        pcap_close(handle);
×
142
}
×
143

144
bool udp_pcap_file_reader::lossy() const
×
145
{
146
    return false;
×
147
}
148

149
} // namespace spead2::recv
150

151
#endif // SPEAD2_USE_PCAP
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

© 2026 Coveralls, Inc