Coverage Report

Created: 2026-11-11 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zeek/src/input/ReaderBackend.cc
Line
Count
Source
1
// See the file "COPYING" in the main distribution directory for copyright.
2
3
#include "zeek/input/ReaderBackend.h"
4
5
#include "zeek/input/Manager.h"
6
#include "zeek/input/ReaderFrontend.h"
7
8
using zeek::threading::Field;
9
using zeek::threading::Value;
10
11
namespace zeek::input {
12
13
class PutMessage final : public threading::OutputMessage<ReaderFrontend> {
14
public:
15
    PutMessage(ReaderFrontend* reader, Value** val)
16
0
        : threading::OutputMessage<ReaderFrontend>("Put", reader), val(val) {}
17
18
0
    bool Process() override {
19
0
        input_mgr->Put(Object(), val);
20
0
        return true;
21
0
    }
22
23
private:
24
    Value** val;
25
};
26
27
class DeleteMessage final : public threading::OutputMessage<ReaderFrontend> {
28
public:
29
    DeleteMessage(ReaderFrontend* reader, Value** val)
30
0
        : threading::OutputMessage<ReaderFrontend>("Delete", reader), val(val) {}
31
32
0
    bool Process() override { return input_mgr->Delete(Object(), val); }
33
34
private:
35
    Value** val;
36
};
37
38
class ClearMessage final : public threading::OutputMessage<ReaderFrontend> {
39
public:
40
0
    ClearMessage(ReaderFrontend* reader) : threading::OutputMessage<ReaderFrontend>("Clear", reader) {}
41
42
0
    bool Process() override {
43
0
        input_mgr->Clear(Object());
44
0
        return true;
45
0
    }
46
47
private:
48
};
49
50
class ReaderErrorMessage final : public threading::OutputMessage<ReaderFrontend> {
51
public:
52
    enum Type : uint8_t { INFO, WARNING, ERROR };
53
54
    ReaderErrorMessage(ReaderFrontend* reader, Type arg_type, const char* arg_msg)
55
0
        : threading::OutputMessage<ReaderFrontend>("ReaderErrorMessage", reader) {
56
0
        type = arg_type;
57
0
        msg = util::copy_string(arg_msg);
58
0
    }
59
60
0
    ~ReaderErrorMessage() override { delete[] msg; }
61
62
    bool Process() override;
63
64
private:
65
    const char* msg;
66
    Type type;
67
};
68
69
class SendEntryMessage final : public threading::OutputMessage<ReaderFrontend> {
70
public:
71
    SendEntryMessage(ReaderFrontend* reader, Value** val)
72
0
        : threading::OutputMessage<ReaderFrontend>("SendEntry", reader), val(val) {}
73
74
0
    bool Process() override {
75
0
        input_mgr->SendEntry(Object(), val);
76
0
        return true;
77
0
    }
78
79
private:
80
    Value** val;
81
};
82
83
class EndCurrentSendMessage final : public threading::OutputMessage<ReaderFrontend> {
84
public:
85
    EndCurrentSendMessage(ReaderFrontend* reader)
86
0
        : threading::OutputMessage<ReaderFrontend>("EndCurrentSend", reader) {}
87
88
0
    bool Process() override {
89
0
        input_mgr->EndCurrentSend(Object());
90
0
        return true;
91
0
    }
92
93
private:
94
};
95
96
class EndOfDataMessage final : public threading::OutputMessage<ReaderFrontend> {
97
public:
98
0
    EndOfDataMessage(ReaderFrontend* reader) : threading::OutputMessage<ReaderFrontend>("EndOfData", reader) {}
99
100
0
    bool Process() override {
101
0
        input_mgr->SendEndOfData(Object());
102
0
        return true;
103
0
    }
104
105
private:
106
};
107
108
class ReaderClosedMessage final : public threading::OutputMessage<ReaderFrontend> {
109
public:
110
0
    ReaderClosedMessage(ReaderFrontend* reader) : threading::OutputMessage<ReaderFrontend>("ReaderClosed", reader) {}
111
112
0
    bool Process() override {
113
0
        Object()->SetDisable();
114
0
        return input_mgr->RemoveStreamContinuation(Object());
115
0
    }
116
117
private:
118
};
119
120
class DisableMessage final : public threading::OutputMessage<ReaderFrontend> {
121
public:
122
0
    DisableMessage(ReaderFrontend* writer) : threading::OutputMessage<ReaderFrontend>("Disable", writer) {}
123
124
0
    bool Process() override {
125
0
        Object()->SetDisable();
126
        // And - because we do not need disabled objects any more -
127
        // there is no way to re-enable them, so simply delete them.
128
        // This avoids the problem of having to periodically check if
129
        // there are any disabled readers out there. As soon as a
130
        // reader disables itself, it deletes itself.
131
0
        input_mgr->RemoveStream(Object());
132
0
        return true;
133
0
    }
134
};
135
136
0
bool ReaderErrorMessage::Process() {
137
0
    switch ( type ) {
138
0
        case INFO: input_mgr->Info(Object(), msg); break;
139
140
0
        case WARNING: input_mgr->Warning(Object(), msg); break;
141
142
0
        case ERROR: input_mgr->Error(Object(), msg); break;
143
0
    }
144
145
0
    return true;
146
0
}
147
148
using namespace input;
149
150
0
ReaderBackend::ReaderBackend(ReaderFrontend* arg_frontend) : MsgThread() {
151
0
    disabled = true; // disabled will be set correctly in init.
152
0
    frontend = arg_frontend;
153
0
    info = new ReaderInfo(frontend->Info());
154
0
    num_fields = 0;
155
0
    fields = nullptr;
156
157
0
    SetName(frontend->Name());
158
0
}
159
160
0
ReaderBackend::~ReaderBackend() { delete info; }
161
162
0
void ReaderBackend::Put(Value** val) { SendOut(new PutMessage(frontend, val)); }
163
164
0
void ReaderBackend::Delete(Value** val) { SendOut(new DeleteMessage(frontend, val)); }
165
166
0
void ReaderBackend::Clear() { SendOut(new ClearMessage(frontend)); }
167
168
0
void ReaderBackend::EndCurrentSend() { SendOut(new EndCurrentSendMessage(frontend)); }
169
170
0
void ReaderBackend::EndOfData() { SendOut(new EndOfDataMessage(frontend)); }
171
172
0
void ReaderBackend::SendEntry(Value** vals) { SendOut(new SendEntryMessage(frontend, vals)); }
173
174
0
bool ReaderBackend::Init(const int arg_num_fields, const threading::Field* const* arg_fields) {
175
0
    if ( Failed() )
176
0
        return true;
177
178
0
    disabled = false;
179
180
0
    SetOSName(Fmt("zk.%s", Name()));
181
182
0
    num_fields = arg_num_fields;
183
0
    fields = arg_fields;
184
185
    // disable if DoInit returns error.
186
0
    int success = DoInit(*info, arg_num_fields, arg_fields);
187
188
0
    if ( ! success ) {
189
0
        Error("Init failed");
190
0
        DisableFrontend();
191
0
    }
192
193
0
    return success;
194
0
}
195
196
0
bool ReaderBackend::OnFinish(double network_time) {
197
0
    if ( ! Failed() )
198
0
        DoClose();
199
200
0
    disabled = true; // frontend disables itself when it gets the Close-message.
201
0
    SendOut(new ReaderClosedMessage(frontend));
202
203
0
    if ( fields ) {
204
0
        for ( unsigned int i = 0; i < num_fields; i++ )
205
0
            delete (fields[i]);
206
207
0
        delete[] (fields);
208
0
        fields = nullptr;
209
0
    }
210
211
0
    return true;
212
0
}
213
214
0
bool ReaderBackend::Update() {
215
0
    if ( disabled )
216
0
        return false;
217
218
0
    if ( Failed() )
219
0
        return true;
220
221
0
    bool success = DoUpdate();
222
0
    if ( ! success )
223
0
        DisableFrontend();
224
225
0
    return ! disabled; // always return failure if we have been disabled in the meantime
226
0
}
227
228
0
void ReaderBackend::DisableFrontend() {
229
    // We might already have been disabled - e.g., due to a call to
230
    // error. In that case, ignore this...
231
0
    if ( disabled )
232
0
        return;
233
234
    // We also set disabled here, because there still may be other
235
    // messages queued and we will dutifully ignore these from now.
236
0
    disabled = true;
237
0
    SendOut(new DisableMessage(frontend));
238
0
}
239
240
0
bool ReaderBackend::OnHeartbeat(double network_time, double current_time) {
241
0
    if ( Failed() )
242
0
        return true;
243
244
0
    return DoHeartbeat(network_time, current_time);
245
0
}
246
247
0
void ReaderBackend::Info(const char* msg) {
248
0
    SendOut(new ReaderErrorMessage(frontend, ReaderErrorMessage::INFO, msg));
249
0
    MsgThread::Info(msg);
250
0
}
251
252
0
void ReaderBackend::StopWarningSuppression() {
253
0
    suppress_warnings = false;
254
0
    if ( warnings_suppressed > 0 )
255
0
        Warning(Fmt("Suppressed %zu warning(s)", warnings_suppressed));
256
0
    warnings_suppressed = 0;
257
0
}
258
259
0
void ReaderBackend::FailWarn(bool is_error, const char* msg, bool suppress_future) {
260
0
    if ( is_error )
261
0
        Error(msg);
262
0
    else {
263
0
        Warning(msg);
264
265
0
        if ( suppress_future )
266
0
            suppress_warnings = true;
267
0
    }
268
0
}
269
0
void ReaderBackend::Warning(const char* msg) {
270
0
    if ( suppress_warnings ) {
271
0
        warnings_suppressed++;
272
0
        return;
273
0
    }
274
275
0
    SendOut(new ReaderErrorMessage(frontend, ReaderErrorMessage::WARNING, msg));
276
0
    MsgThread::Warning(msg);
277
0
}
278
279
0
void ReaderBackend::Error(const char* msg) {
280
0
    SendOut(new ReaderErrorMessage(frontend, ReaderErrorMessage::ERROR, msg));
281
0
    MsgThread::Error(msg);
282
283
    // Force errors to be fatal.
284
0
    DisableFrontend();
285
0
}
286
287
} // namespace zeek::input