mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00

This also triggers if there is one warning, which seems a little weird, but it seems mostly reasonable.
371 lines
12 KiB
C++
371 lines
12 KiB
C++
// See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
#pragma once
|
|
|
|
#include "zeek/ZeekString.h"
|
|
#include "zeek/input/Component.h"
|
|
#include "zeek/threading/MsgThread.h"
|
|
#include "zeek/threading/SerialTypes.h"
|
|
|
|
namespace zeek::detail {
|
|
class Location;
|
|
}
|
|
|
|
namespace zeek::input {
|
|
|
|
class ReaderFrontend;
|
|
|
|
/**
|
|
* The modes a reader can be in.
|
|
*/
|
|
enum ReaderMode {
|
|
/**
|
|
* Manual refresh reader mode. The reader will read the file once,
|
|
* and send all read data back to the manager. After that, no automatic
|
|
* refresh should happen. Manual refreshes can be triggered from the
|
|
* scripting layer using force_update.
|
|
*/
|
|
MODE_MANUAL,
|
|
|
|
/**
|
|
* Automatic rereading mode. The reader should monitor the
|
|
* data source for changes continually. When the data source changes,
|
|
* either the whole file has to be resent using the SendEntry/EndCurrentSend functions.
|
|
*/
|
|
MODE_REREAD,
|
|
|
|
/**
|
|
* Streaming reading mode. The reader should monitor the data source
|
|
* for new appended data. When new data is appended is has to be sent
|
|
* using the Put api functions.
|
|
*/
|
|
MODE_STREAM,
|
|
|
|
/** Internal dummy mode for initialization. */
|
|
MODE_NONE
|
|
};
|
|
|
|
/**
|
|
* Base class for reader implementation. When the input:Manager creates a new
|
|
* input stream, it instantiates a ReaderFrontend. That then in turn creates
|
|
* a ReaderBackend of the right type. The frontend then forwards messages
|
|
* over the backend as its methods are called.
|
|
*
|
|
* All methods must be called only from the corresponding child thread (the
|
|
* constructor is the one exception.)
|
|
*/
|
|
class ReaderBackend : public threading::MsgThread {
|
|
public:
|
|
// Silence a warning from clang about hidden overloaded functions and the
|
|
// Info() function that this class provides.
|
|
using threading::MsgThread::Error;
|
|
using threading::MsgThread::Info;
|
|
using threading::MsgThread::Warning;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param frontend The frontend reader that created this backend. The
|
|
* *only* purpose of this value is to be passed back via messages as
|
|
* an argument to callbacks. One must not otherwise access the
|
|
* frontend, it's running in a different thread.
|
|
*/
|
|
explicit ReaderBackend(ReaderFrontend* frontend);
|
|
|
|
/**
|
|
* Destructor.
|
|
*/
|
|
~ReaderBackend() override;
|
|
|
|
/**
|
|
* A struct passing information to the reader at initialization time.
|
|
*/
|
|
struct ReaderInfo {
|
|
// Structure takes ownership of the strings.
|
|
using config_map = std::map<const char*, const char*, util::CompareString>;
|
|
|
|
/**
|
|
* A string left to the interpretation of the reader
|
|
* implementation; it corresponds to the value configured on
|
|
* the script-level for the logging filter.
|
|
*
|
|
* Structure takes ownership of the string.
|
|
*/
|
|
const char* source;
|
|
|
|
/**
|
|
* The name of the input stream.
|
|
*/
|
|
const char* name;
|
|
|
|
/**
|
|
* A map of key/value pairs corresponding to the relevant
|
|
* filter's "config" table.
|
|
*/
|
|
config_map config;
|
|
|
|
/**
|
|
* The opening mode for the input source.
|
|
*/
|
|
ReaderMode mode;
|
|
|
|
ReaderInfo() {
|
|
source = nullptr;
|
|
name = nullptr;
|
|
mode = MODE_NONE;
|
|
}
|
|
|
|
ReaderInfo(const ReaderInfo& other) {
|
|
source = other.source ? util::copy_string(other.source) : nullptr;
|
|
name = other.name ? util::copy_string(other.name) : nullptr;
|
|
mode = other.mode;
|
|
|
|
for ( config_map::const_iterator i = other.config.begin(); i != other.config.end(); i++ )
|
|
config.insert(std::make_pair(util::copy_string(i->first), util::copy_string(i->second)));
|
|
}
|
|
|
|
~ReaderInfo() {
|
|
delete[] source;
|
|
delete[] name;
|
|
|
|
for ( config_map::iterator i = config.begin(); i != config.end(); i++ ) {
|
|
delete[] i->first;
|
|
delete[] i->second;
|
|
}
|
|
}
|
|
|
|
private:
|
|
const ReaderInfo& operator=(const ReaderInfo& other); // Disable.
|
|
};
|
|
|
|
/**
|
|
* One-time initialization of the reader to define the input source.
|
|
*
|
|
* @param info Meta information for the writer.
|
|
*
|
|
* @param num_fields Number of fields contained in \a fields.
|
|
*
|
|
* @param fields The types and names of the fields to be retrieved
|
|
* from the input source.
|
|
*
|
|
* @param config A string map containing additional configuration options
|
|
* for the reader.
|
|
*
|
|
* @return False if an error occurred.
|
|
*/
|
|
bool Init(int num_fields, const threading::Field* const* fields);
|
|
|
|
/**
|
|
* Force trigger an update of the input stream. The action that will
|
|
* be taken depends on the current read mode and the individual input
|
|
* backend.
|
|
*
|
|
* An backend can choose to ignore this.
|
|
*
|
|
* @return False if an error occurred.
|
|
*/
|
|
bool Update();
|
|
|
|
/**
|
|
* Disables the frontend that has instantiated this backend. Once
|
|
* disabled, the frontend will not send any further message over.
|
|
*/
|
|
void DisableFrontend();
|
|
|
|
/**
|
|
* Returns the log fields as passed into the constructor.
|
|
*/
|
|
const threading::Field* const* Fields() const { return fields; }
|
|
|
|
/**
|
|
* Returns the additional reader information into the constructor.
|
|
*/
|
|
const ReaderInfo& Info() const { return *info; }
|
|
|
|
/**
|
|
* Returns the number of log fields as passed into the constructor.
|
|
*/
|
|
int NumFields() const { return num_fields; }
|
|
|
|
/**
|
|
* Convenience function that calls Warning or Error, depending on the
|
|
* is_error parameter. In case of a warning, setting suppress_future to
|
|
* true will suppress all future warnings until StopWarningSuppression()
|
|
* is called.
|
|
*
|
|
* @param is_error If set to true, an error is generated. Else a warning
|
|
* is generate.
|
|
*
|
|
* @param msg The error/warning message.
|
|
*
|
|
* @param suppress_future If set to true, future warnings are suppressed
|
|
* until StopWarningSuppression is called.
|
|
*/
|
|
void FailWarn(bool is_error, const char* msg, bool suppress_future = false);
|
|
|
|
void StopWarningSuppression();
|
|
|
|
// Overridden from MsgThread.
|
|
bool OnHeartbeat(double network_time, double current_time) override;
|
|
bool OnFinish(double network_time) override;
|
|
|
|
void Info(const char* msg) override;
|
|
|
|
/**
|
|
* Reports a warning in the child thread. For input readers, warning suppression
|
|
* that is caused by calling FailWarn() is respected by the Warning function.
|
|
*/
|
|
void Warning(const char* msg) override;
|
|
|
|
/**
|
|
* Reports an error in the child thread. For input readers, it is assumed
|
|
* that Info and Warnings do not cause the read operation to fail (they might
|
|
* signal that, e.g., a single line was ignored).
|
|
*
|
|
* It is assumed that Errors are not recoverable. Calling the Error function
|
|
* will return the error back to scriptland and also *automatically* causes
|
|
* the current reader to be disabled and torn down.
|
|
*/
|
|
void Error(const char* msg) override;
|
|
|
|
protected:
|
|
// Methods that have to be overwritten by the individual readers
|
|
|
|
/**
|
|
* Reader-specific initialization method. Note that data may only be
|
|
* read from the input source after the Init() function has been
|
|
* called.
|
|
*
|
|
* A reader implementation must override this method. If it returns
|
|
* false, it will be assumed that a fatal error has occurred that
|
|
* prevents the reader from further operation; it will then be
|
|
* disabled and eventually deleted. When returning false, an
|
|
* implementation should also call Error() to indicate what happened.
|
|
*
|
|
* Arguments are the same as Init().
|
|
*
|
|
* Note that derived classes don't need to store the values passed in
|
|
* here if other methods need them to; the \a ReaderBackend class
|
|
* provides accessor methods to get them later, and they are passed
|
|
* in here only for convenience.
|
|
*/
|
|
virtual bool DoInit(const ReaderInfo& info, int arg_num_fields, const threading::Field* const* fields) = 0;
|
|
|
|
/**
|
|
* Reader-specific method implementing input finalization at
|
|
* termination.
|
|
*
|
|
* A reader implementation must override this method but it can just
|
|
* ignore calls if an input source can't actually be closed.
|
|
*
|
|
* After the method is called, the writer will be deleted. If an
|
|
* error occurs during shutdown, an implementation should also call
|
|
* Error() to indicate what happened.
|
|
*/
|
|
virtual void DoClose() = 0;
|
|
|
|
/**
|
|
* Reader-specific method implementing the forced update trigger.
|
|
*
|
|
* A reader implementation must override this method but it can just
|
|
* ignore calls if a forced update does not fit the input source or
|
|
* the current input reading mode.
|
|
*
|
|
* If it returns false, it will be assumed that a fatal error has
|
|
* occurred that prevents the reader from further operation; it will
|
|
* then be disabled and eventually deleted. When returning false, an
|
|
* implementation should also call Error to indicate what happened.
|
|
*/
|
|
virtual bool DoUpdate() = 0;
|
|
|
|
/**
|
|
* Triggered by regular heartbeat messages from the main thread.
|
|
*/
|
|
virtual bool DoHeartbeat(double network_time, double current_time) = 0;
|
|
|
|
// Content-sending-functions (simple mode). Include table-specific
|
|
// functionality that simply is not used if we have no table.
|
|
|
|
/**
|
|
* Method allowing a reader to send a list of values read from a
|
|
* specific stream back to the manager in simple mode.
|
|
*
|
|
* If the stream is a table stream, the values are inserted into the
|
|
* table; if it is an event stream, the event is raised.
|
|
*
|
|
* @param val Array of threading::Values expected by the stream. The
|
|
* array must have exactly NumEntries() elements.
|
|
*/
|
|
void Put(threading::Value** val);
|
|
|
|
/**
|
|
* Method allowing a reader to delete a specific value from a Zeek
|
|
* table.
|
|
*
|
|
* If the receiving stream is an event stream, only a removed event
|
|
* is raised.
|
|
*
|
|
* @param val Array of threading::Values expected by the stream. The
|
|
* array must have exactly NumEntries() elements.
|
|
*/
|
|
void Delete(threading::Value** val);
|
|
|
|
/**
|
|
* Method allowing a reader to clear a Zeek table.
|
|
*
|
|
* If the receiving stream is an event stream, this is ignored.
|
|
*
|
|
*/
|
|
void Clear();
|
|
|
|
/**
|
|
* Method telling the manager that we finished reading the current
|
|
* data source. Will trigger an end_of_data event.
|
|
*
|
|
* Note: When using SendEntry as the tracking mode this is triggered
|
|
* automatically by EndCurrentSend(). Only use if not using the
|
|
* tracking mode. Otherwise the event will be sent twice.
|
|
*/
|
|
void EndOfData();
|
|
|
|
// Content-sending-functions (tracking mode): Only changed lines are propagated.
|
|
|
|
/**
|
|
* Method allowing a reader to send a list of values read from
|
|
* specific stream back to the manager in tracking mode.
|
|
*
|
|
* If the stream is a table stream, the values are inserted into the
|
|
* table; if it is an event stream, the event is raised.
|
|
*
|
|
* @param val Array of threading::Values expected by the stream. The
|
|
* array must have exactly NumEntries() elements.
|
|
*/
|
|
void SendEntry(threading::Value** vals);
|
|
|
|
/**
|
|
* Method telling the manager, that the current list of entries sent
|
|
* by SendEntry is finished.
|
|
*
|
|
* For table streams, all entries that were not updated since the
|
|
* last EndCurrentSend will be deleted, because they are no longer
|
|
* present in the input source
|
|
*/
|
|
void EndCurrentSend();
|
|
|
|
private:
|
|
// Frontend that instantiated us. This object must not be accessed
|
|
// from this class, it's running in a different thread!
|
|
ReaderFrontend* frontend;
|
|
|
|
ReaderInfo* info;
|
|
unsigned int num_fields;
|
|
const threading::Field* const* fields; // raw mapping
|
|
|
|
bool disabled;
|
|
// this is an internal indicator in case the read is currently in a failed state
|
|
// it's used to suppress duplicate error messages.
|
|
bool suppress_warnings = false;
|
|
size_t warnings_suppressed = 0;
|
|
};
|
|
|
|
} // namespace zeek::input
|