| Current File : /home/mmdealscpanel/yummmdeals.com/fstrm.tar |
unix_writer.h 0000644 00000005523 15042202636 0007301 0 ustar 00 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef FSTRM_UNIX_WRITER_H
#define FSTRM_UNIX_WRITER_H
/**
* \defgroup fstrm_unix_writer fstrm_unix_writer
*
* `fstrm_unix_writer` is an interface for opening an \ref fstrm_writer object
* that is backed by I/O on a stream-oriented (`SOCK_STREAM`) Unix socket.
*
* @{
*/
/**
* Initialize an `fstrm_unix_writer_options` object, which is needed to
* configure the socket path to be opened by the writer.
*
* \return
* `fstrm_unix_writer_options` object.
*/
struct fstrm_unix_writer_options *
fstrm_unix_writer_options_init(void);
/**
* Destroy an `fstrm_unix_writer_options` object.
*
* \param uwopt
* Pointer to `fstrm_unix_writer_options` object.
*/
void
fstrm_unix_writer_options_destroy(
struct fstrm_unix_writer_options **uwopt);
/**
* Set the `socket_path` option. This is a filesystem path that will be
* connected to as an `AF_UNIX` socket.
*
* \param uwopt
* `fstrm_unix_writer_options` object.
* \param socket_path
* The filesystem path to the `AF_UNIX` socket.
*/
void
fstrm_unix_writer_options_set_socket_path(
struct fstrm_unix_writer_options *uwopt,
const char *socket_path);
/**
* Initialize the `fstrm_writer` object. Note that the `AF_UNIX` socket will not
* actually be opened until a subsequent call to fstrm_writer_open().
*
* \param uwopt
* `fstrm_unix_writer_options` object. Must be non-NULL, and have the
* `socket_path` option set.
* \param wopt
* `fstrm_writer_options` object. May be NULL, in which chase default
* values will be used.
*
* \return
* `fstrm_writer` object.
* \retval
* NULL on failure.
*/
struct fstrm_writer *
fstrm_unix_writer_init(
const struct fstrm_unix_writer_options *uwopt,
const struct fstrm_writer_options *wopt);
/**@}*/
#endif /* FSTRM_UNIX_WRITER_H */
reader.h 0000644 00000017734 15042202636 0006173 0 ustar 00 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef FSTRM_READER_H
#define FSTRM_READER_H
/**
* \defgroup fstrm_reader fstrm_reader
*
* `fstrm_reader` is an interface for reading Frame Streams data from a byte
* stream. The underlying byte stream I/O operations are abstracted by the
* \ref fstrm_rdwr interface. Thus, the `fstrm_reader` interface can be used to
* read Frame Streams data from any source whose read/write operations are
* wrapped by an `fstrm_rdwr` object.
*
* Some basic `fstrm_reader` implementations are already provided in the `fstrm`
* library. See fstrm_file_reader_init() to create an `fstrm_reader` object that
* reads Frame Streams data from a regular file.
*
* @{
*/
/**
* The default `max_frame_size` value.
*/
#define FSTRM_READER_MAX_FRAME_SIZE_DEFAULT 1048576
/**
* Initialize an `fstrm_reader_options` object.
*
* \return
* `fstrm_reader_options` object.
*/
struct fstrm_reader_options *
fstrm_reader_options_init(void);
/**
* Destroy an `fstrm_reader_options` object.
*
* \param ropt
* Pointer to `fstrm_reader_options` object.
*/
void
fstrm_reader_options_destroy(
struct fstrm_reader_options **ropt);
/**
* Add a "Content Type" value to the set of content types accepted by the
* `fstrm_reader`. This function makes a copy of the provided string. This
* function may be called multiple times, in which case multiple "Content Type"
* values will be accepted by the reader.
*
* If the reader has no content types set, it will accept any content type.
*
* \param ropt
* `fstrm_reader_options` object.
* \param content_type
* The "Content Type" string to copy. Note that this string is not
* NUL-terminated and may contain embedded NULs.
* \param len_content_type
* The number of bytes in `content_type`.
*
* \retval #fstrm_res_success
* The "Content Type" field was successfully added.
* \retval #fstrm_res_failure
* The "Content Type" string is too long.
*/
fstrm_res
fstrm_reader_options_add_content_type(
struct fstrm_reader_options *ropt,
const void *content_type,
size_t len_content_type);
/**
* Set the maximum frame size that the reader is willing to accept. This
* enforces an upper limit on the amount of memory used to buffer incoming data
* from the reader's byte stream.
*
* If this option is not set, it defaults to
* #FSTRM_READER_MAX_FRAME_SIZE_DEFAULT.
*
* \param ropt
* `fstrm_reader_options` object.
* \param max_frame_size
* The maximum frame size value.
*
* \retval #fstrm_res_success
* The `max_frame_size` value was successfully set.
* \retval #fstrm_res_failure
* The `max_frame_size` value was too large or too small.
*/
fstrm_res
fstrm_reader_options_set_max_frame_size(
struct fstrm_reader_options *ropt,
size_t max_frame_size);
/**
* Initialize a new `fstrm_reader` object based on an underlying `fstrm_rdwr`
* object and an `fstrm_reader_options` object.
*
* The underlying `fstrm_rdwr` object MUST have a `read` method. It MAY
* optionally have a `write` method, in which case the stream will be treated as
* a bi-directional, handshaked stream. Otherwise, if there is no `write` method
* the stream will be treated as a uni-directional stream.
*
* This function is useful for implementing functions that return new types of
* `fstrm_reader` objects, such as fstrm_file_reader_init().
*
* After a successful call to this function, the ownership of the `fstrm_rdwr`
* object passes from the caller to the `fstrm_reader` object. The caller
* should perform no further calls on the `fstrm_rdwr` object. The `fstrm_rdwr`
* object will be cleaned up on a call to fstrm_reader_destroy().
*
* \param ropt
* `fstrm_reader_options` object. May be NULL, in which case default values
* will be used.
*
* \param rdwr
* Pointer to `fstrm_rdwr` object. Must be non-NULL. The `fstrm_rdwr`
* object must have a `read` method, and may optionally have a `write`
* method.
*
* \return
* `fstrm_reader` object.
* \retval
* NULL on failure.
*/
struct fstrm_reader *
fstrm_reader_init(
const struct fstrm_reader_options *ropt,
struct fstrm_rdwr **rdwr);
/**
* Destroy an `fstrm_reader` object. This implicitly calls fstrm_reader_close()
* if necessary.
*
* \param r
* Pointer to `fstrm_reader` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_destroy(struct fstrm_reader **r);
/**
* Open an `fstrm_reader` object and prepare it to read data.
*
* This checks that the content type in the byte stream, if specified, matches
* one of the content types specified in the `fstrm_reader_options` object used
* to initialize the `fstrm_reader` object.
*
* This function may fail if there was an underlying problem opening the input
* stream.
*
* \param r
* `fstrm_reader` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_open(struct fstrm_reader *r);
/**
* Close an `fstrm_reader` object. Once it has been closed, no data frames may
* subsequently be read.
*
* Calling this function is optional; it may be implicitly invoked by a call to
* fstrm_reader_destroy().
*
* \param r
* `fstrm_reader` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_close(struct fstrm_reader *r);
/**
* Read a data frame from an `fstrm_reader` object. This frame is held in an
* internal buffer owned by the `fstrm_reader` object and should not be modified
* by the caller. The contents of this buffer will be overwritten by a
* subsequent call to fstrm_reader_read().
*
* This function implicitly calls fstrm_reader_open() if necessary.
*
* \param r
* `fstrm_reader` object.
* \param[out] data
* Pointer to buffer containing the data frame payload.
* \param[out] len_data
* The number of bytes available in `data`.
*
* \retval #fstrm_res_success
* A data frame was successfully read.
* \retval #fstrm_res_stop
* The end of the stream has been reached.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_read(
struct fstrm_reader *r,
const uint8_t **data,
size_t *len_data);
/**
* Obtain a pointer to an `fstrm_control` object used during processing. Objects
* returned by this function are owned by the `fstrm_reader` object and must not
* be modified by the caller. After a call to fstrm_reader_destroy() these
* pointers will no longer be valid.
*
* For example, this function can be used to obtain a pointer to the START
* control frame, which can be queried to see which "Content Type" was
* negotiated during the opening of the reader.
*
* This function implicitly calls fstrm_reader_open() if necessary.
*
* \param r
* `fstrm_reader` object.
* \param type
* Which control frame to return.
* \param[out] control
* The `fstrm_control` object.
*
* \retval #fstrm_res_success
* If an `fstrm_control` object was returned.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_get_control(
struct fstrm_reader *r,
fstrm_control_type type,
const struct fstrm_control **control);
/**@}*/
#endif /* FSTRM_READER_H */
control.h 0000644 00000050207 15042202636 0006401 0 ustar 00 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef FSTRM_CONTROL_H
#define FSTRM_CONTROL_H
/**
* \defgroup fstrm_control fstrm_control
*
* `fstrm_control` is an interface for encoding and decoding Frame Streams
* control frames.
*
* Two types of frames are possible in a Frame Streams byte stream: **data
* frames** and **control frames**. Both are variable length byte sequences
* prefixed by a 32-bit big endian unsigned integer (the **frame length**)
* specifying the length of the following byte sequence. If this frame length
* value is greater than zero, the **frame length** specifies the **data frame
* length**, and a data frame follows it. If the frame length is zero (i.e., it
* is the four byte sequence `00 00 00 00`), this is an **escape sequence**,
* which means that a control frame follows. The control frame itself is
* prefixed by a 32-bit big endian unsigned integer (the **control frame
* length**) specifying the length of the following **control frame payload**.
*
* There are two types of control frames used for uni-directional streams:
* `START` and `STOP`. These control frame types bracket the stream of data
* frames. `START` indicates the beginning of the stream and communicates
* metadata about the stream to follow, and `STOP` indicates the end of the
* stream.
*
* Bi-directional streams make use of three additional control frame types:
* `READY`, `ACCEPT`, and `FINISH`. These control frame types are used in a
* simple handshake protocol between sender and receiver.
*
* A uni-directional Frame Streams byte stream normally consists of the
* following:
*
* 1. The `START` control frame.
* 2. A sequence of zero or more data frames or control frames that are not of
* the control frame types `START`, `STOP`, `ACCEPT`, `READY`, or
* `FINISH`.
* 3. The `STOP` control frame.
*
* The `START` and `STOP` control frames are not optional. The `START` control
* frame must appear at the beginning of the byte stream, and the `STOP` control
* frame must appear at the end of the byte stream. (If the byte stream has an
* end.) `START` control frames must not appear anywhere other than at the
* beginning of the byte stream, and `STOP` control frames must not appear
* anywhere other than at the end of the byte stream. Only one `START` control
* frame and only one `STOP` control frame may appear in a Frame Streams byte
* stream.
*
* Control frames may optionally include zero or more **control frame fields**.
* There is currently one type of control frame field defined: `CONTENT_TYPE`.
* This field specifies a variable length byte sequence describing the encoding
* of data frames that appear in the Frame Streams byte stream. This field is
* used by cooperating programs to unambiguously identify how to interpret the
* data frames in a particular Frame Streams byte stream. For instance, this
* field may specify a particular schema to use to interpret the data frames
* appearing in the byte stream. Zero, one, or more `CONTENT_TYPE` fields may
* appear in `READY` or `ACCEPT` control frames. Zero or one `CONTENT_TYPE`
* fields may appear in `START` control frames. No `CONTENT_TYPE` fields may
* appear in `STOP` or `FINISH` control frames.
*
* A uni-directional Frame Streams encoder would normally produce a byte stream
* as follows:
*
* 1. Write the `START` **control frame**.
* + At the start of the byte stream, write the four byte **escape
* sequence** `00 00 00 00` that precedes control frames.
* + Write the **control frame length** as a 32-bit big endian unsigned
* integer.
* + Write the **control frame payload**. It must be a `START` control
* frame. It may optionally specify a `CONTENT_TYPE` field.
* 2. Write zero or more **data frames**.
* 3. Write the `STOP` **control frame**.
* + At the start of the byte stream, write the four byte **escape
* sequence** `00 00 00 00` that precedes control frames.
* + Write the **control frame length** as a 32-bit big endian unsigned
* integer.
* + Write the **control frame payload**. It must be a `STOP` control
* frame.
*
* A uni-directional Frame Streams decoder would normally process the byte
* stream as follows:
*
* 1. Read the `START` control frame.
* + At the start of the byte stream, read the four byte **escape
* sequence** `00 00 00 00` that precedes control frames.
* + Read the 32-bit big endian unsigned integer specifying the **control
* frame length**.
* + Decode the **control frame payload**. It must be a `START` control
* frame. It may optionally specify a `CONTENT_TYPE` field.
* 2. Repeatedly read data frames or control frames following the `START`
* control frame.
* + Read the **frame length**, a 32-bit big endian unsigned integer.
* + If the **frame length** is zero, a control frame follows:
* + Read the 32-bit big endian unsigned integer specifying the
* **control frame length**.
* + Decode the **control frame payload**. If it is a `STOP`
* control frame, the end of the Frame Streams byte stream has
* occurred, and no frames follow. Break out of the decoding loop
* and halt processing. (`READY`, `ACCEPT`, `START`, and `FINISH`
* may not occur here. For forward compatibility, control frames of
* types other than the types `READY`, `ACCEPT`, `START`, `STOP`,
* and `FINISH` must be ignored here. No control frames specified
* in the future may alter the encoding of succeeding frames.)
* + If the **frame length** is non-zero, it specifies the number of bytes
* in the following **data frame**. Consume these bytes from the byte
* stream.
*
* The functions fstrm_control_encode() and fstrm_control_decode() are provided
* to encode and decode control frames. See the detailed descriptions of those
* functions for code examples showing their usage.
*
* @{
*/
/**
* The maximum length in bytes of an "Accept", "Start", or "Stop" control frame
* payload. This excludes the escape sequence and the control frame length.
*/
#define FSTRM_CONTROL_FRAME_LENGTH_MAX 512
/**
* The maximum length in bytes of a "Content Type" control frame field payload.
* This excludes the field type and payload length.
*/
#define FSTRM_CONTROL_FIELD_CONTENT_TYPE_LENGTH_MAX 256
/**
* Control frame types.
*/
typedef enum {
/** Control frame type value for "Accept" control frames. */
FSTRM_CONTROL_ACCEPT = 0x01,
/** Control frame type value for "Start" control frames. */
FSTRM_CONTROL_START = 0x02,
/** Control frame type value for "Stop" control frames. */
FSTRM_CONTROL_STOP = 0x03,
/** Control frame type value for "Ready" control frames. */
FSTRM_CONTROL_READY = 0x04,
/** Control frame type value for "Finish" control frames. */
FSTRM_CONTROL_FINISH = 0x05,
} fstrm_control_type;
/**
* Control frame field types. These are optional fields that can appear in
* control frames.
*/
typedef enum {
/**
* Control frame field type value for the "Content Type" control frame
* option.
*/
FSTRM_CONTROL_FIELD_CONTENT_TYPE = 0x01,
} fstrm_control_field;
/**
* Flags for controlling the behavior of the encoding and decoding functions.
*/
typedef enum {
/**
* Set to control whether to include the control frame header in
* encoding/decoding operations.
*
* Causes fstrm_control_encode() and fstrm_control_encoded_size() to
* include the control frame header containing the escape sequence and
* control frame payload length in the encoded output. Otherwise, only
* the control frame payload itself is encoded.
*
* Tells fstrm_control_decode() that the input buffer to be decoded
* begins with the control frame header containing the escape sequence
* and control frame payload length. (Note that this requires the caller
* to peek at the input buffer to calculate the right buffer length.)
* Otherwise, the input buffer begins with the control frame payload.
*/
FSTRM_CONTROL_FLAG_WITH_HEADER = (1 << 0),
} fstrm_control_flag;
/**
* Convert an `fstrm_control_type` enum value to a string representation.
* Unknown values are represented as `"FSTRM_CONTROL_UNKNOWN"`.
*
* \param type The `fstrm_control_type` enum value.
* \return The string representation of the enum value. (Always non-NULL.)
*/
const char *
fstrm_control_type_to_str(fstrm_control_type type);
/**
* Convert an `fstrm_control_field` enum value to a string representation.
* Unknown values are represented as `"FSTRM_CONTROL_FIELD_UNKNOWN"`.
*
* \param f_type The `fstrm_control_field` enum value.
* \return The string representation of the enum value. (Always non-NULL.)
*/
const char *
fstrm_control_field_type_to_str(fstrm_control_field f_type);
/**
* Initialize an `fstrm_control` object. This object represents Frame Streams
* control frames and is used for encoding and decoding control frames.
*
* \return
* An `fstrm_control` object.
*/
struct fstrm_control *
fstrm_control_init(void);
/**
* Destroy an `fstrm_control` object.
*
* \param[in] c
* Pointer to an `fstrm_control` object.
*/
void
fstrm_control_destroy(struct fstrm_control **c);
/**
* Reinitialize an `fstrm_control` object. This resets the internal state to
* default values.
*
* \param c
* `fstrm_control` object.
*/
void
fstrm_control_reset(struct fstrm_control *c);
/**
* Retrieve the type of the control frame.
*
* \param c
* `fstrm_control` object.
* \param[out] type
* Type of the control frame.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_get_type(
const struct fstrm_control *c,
fstrm_control_type *type);
/**
* Set the type of the control frame.
*
* \param c
* `fstrm_control` object.
* \param[in] type
* Type of the control frame.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_set_type(
struct fstrm_control *c,
fstrm_control_type type);
/**
* Retrieve the number of "Content Type" fields present in the control frame.
*
* \param c
* `fstrm_control` object.
* \param[out] n_content_type
* The number of "Content Type" fields.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_get_num_field_content_type(
const struct fstrm_control *c,
size_t *n_content_type);
/**
* Retrieve a "Content Type" field from the control frame. This function
* returns a reference which must not be modified. Control frames may contain
* zero, one, or more "Content Type" fields.
*
* \see fstrm_control_get_num_field_content_type()
*
* \param c
* `fstrm_control` object.
* \param[in] idx
* The index of the "Content Type" field to retrieve.
* \param[out] content_type
* Pointer to where the reference to the "Content Type" string will be
* stored. Note that this string is not NUL-terminated and may contain
* embedded NULs.
* \param[out] len_content_type
* The number of bytes in `content_type`.
*
* \retval #fstrm_res_success
* The control frame has a "Content Type" field.
* \retval #fstrm_res_failure
* The control frame does not have a "Content Type" field.
*/
fstrm_res
fstrm_control_get_field_content_type(
const struct fstrm_control *c,
const size_t idx,
const uint8_t **content_type,
size_t *len_content_type);
/**
* Add a "Content Type" field to the control frame. This function makes a copy
* of the provided string. This function may be called multiple times, in which
* case multiple "Content Type" fields will be added to the control frame.
*
* The "Content Type" fields are removed on a call to fstrm_control_reset().
*
* \param c
* `fstrm_control` object.
* \param[in] content_type
* The "Content Type" string to copy. Note that this string is not
* NUL-terminated and may contain embedded NULs.
* \param[in] len_content_type
* The number of bytes in `content_type`.
*
* \retval #fstrm_res_success
* The "Content Type" field was successfully added.
* \retval #fstrm_res_failure
* The "Content Type" string is too long.
*/
fstrm_res
fstrm_control_add_field_content_type(
struct fstrm_control *c,
const uint8_t *content_type,
size_t len_content_type);
/**
* Check if the control frame matches a particular content type value. That is,
* the content type given in the `match` and `len_match` parameters is checked
* for compatibility with the content types (if any) specified in the control
* frame.
*
* \param c
* `fstrm_control` object.
* \param match
* The "Content Type" string to match. Note that this string is not
* NUL-terminated and may contain embedded NULs. May be NULL, in which case
* the control frame must not have any content type fields in order to
* match.
* \param len_match
* The number of bytes in `match`.
*
* \retval #fstrm_res_success
* A match was found.
* \retval #fstrm_res_failure
* A match was not found.
*/
fstrm_res
fstrm_control_match_field_content_type(
const struct fstrm_control *c,
const uint8_t *match,
const size_t len_match);
/**
* Decode a control frame from a buffer. The buffer starts with either the
* escape sequence or the control frame payload depending on whether the
* `FSTRM_CONTROL_FLAG_WITH_HEADER` flag is set or not. In either case, the
* 'len_control_frame' parameter must be exact. Underflow or overflow is not
* permitted.
*
* The following code example shows a function that decodes a control frame
* payload:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static fstrm_res
decode_control_frame(const void *control_frame, size_t len_control_frame)
{
fstrm_res res;
fstrm_control_type c_type;
struct fstrm_control *c;
uint32_t flags = 0;
c = fstrm_control_init();
res = fstrm_control_decode(c, control_frame, len_control_frame, flags);
if (res != fstrm_res_success) {
puts("fstrm_control_decode() failed.");
fstrm_control_destroy(&c);
return res;
}
res = fstrm_control_get_type(c, &c_type);
if (res != fstrm_res_success) {
puts("fstrm_control_get_type() failed.");
fstrm_control_destroy(&c);
return res;
}
printf("The control frame is of type %s (%u).\n",
fstrm_control_type_to_str(c_type), c_type);
size_t n_content_type;
res = fstrm_control_get_num_field_content_type(c, &n_content_type);
if (res != fstrm_res_success) {
puts("fstrm_control_get_num_field_content_type() failed.");
fstrm_control_destroy(&c);
return res;
}
const uint8_t *content_type;
size_t len_content_type;
for (size_t idx = 0; idx < n_content_type; idx++) {
res = fstrm_control_get_field_content_type(c, idx,
&content_type, &len_content_type);
if (res == fstrm_res_success) {
printf("The control frame has a CONTENT_TYPE field of length %zd.\n",
len_content_type);
}
}
fstrm_control_destroy(&c);
return fstrm_res_success;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* \param c
* `fstrm_control` object. Its state will be overwritten.
* \param[in] control_frame
* Buffer containing the serialized control frame.
* \param[in] len_control_frame
* The number of bytes in `control_frame`. This parameter must specify the
* exact number of bytes in the control frame.
* \param flags
* Flags controlling the decoding process. See #fstrm_control_flag.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_decode(
struct fstrm_control *c,
const void *control_frame,
size_t len_control_frame,
const uint32_t flags);
/**
* Calculate the number of bytes needed to serialize the control frame.
*
* \param c
* `fstrm_control` object.
* \param[out] len_control_frame
* The number of bytes needed to encode `c`.
* \param flags
* Flags controlling the encoding process. See #fstrm_control_flag.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_encoded_size(
const struct fstrm_control *c,
size_t *len_control_frame,
const uint32_t flags);
/**
* Encode a control frame into a buffer. Since a Frame Streams control frame is
* a variable length byte sequence of up to #FSTRM_CONTROL_FRAME_LENGTH_MAX
* bytes, this function can be used in two different ways. The first way is to
* call fstrm_control_encoded_size() to obtain the exact number of bytes needed
* to encode the frame, and then pass a buffer of this exact size to
* fstrm_control_encode(). The following example shows this usage:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fstrm_res res;
struct fstrm_control *c;
uint8_t *control_frame;
size_t len_control_frame;
uint32_t flags = 0;
c = fstrm_control_init();
res = fstrm_control_set_type(c, FSTRM_CONTROL_START);
if (res != fstrm_res_success) {
// Error handling goes here.
}
// Calculate the number of bytes needed.
res = fstrm_control_encoded_size(c, &len_control_frame, flags);
if (res != fstrm_res_success) {
// Error handling goes here.
}
// 'len_control_frame' now specifies the number of bytes required for
// the control frame. Allocate the needed space.
control_frame = malloc(len_control_frame);
if (!control_frame) {
// Error handling goes here.
}
// Serialize the control frame into the allocated buffer.
res = fstrm_control_encode(c, control_frame, &len_control_frame, 0);
if (res != fstrm_res_success) {
// Error handling goes here.
}
// Do something with 'control_frame' and 'len_control_frame'.
// Clean up.
free(control_frame);
fstrm_control_destroy(&c);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* The second way to use fstrm_control_encode() is to allocate a statically
* sized buffer of #FSTRM_CONTROL_FRAME_LENGTH_MAX bytes. The exact number of
* bytes serialized by the encoder will be returned in the `len_control_frame`
* parameter. The following example shows this usage:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fstrm_res res;
struct fstrm_control *c;
uint8_t control_frame[FSTRM_CONTROL_FRAME_LENGTH_MAX];
size_t len_control_frame = sizeof(control_frame);
c = fstrm_control_init();
res = fstrm_control_set_type(c, FSTRM_CONTROL_START);
if (res != fstrm_res_success) {
// Error handling.
}
// Serialize the control frame.
res = fstrm_control_encode(c, control_frame, &len_control_frame, 0);
if (res != fstrm_res_success) {
// Error handling goes here.
}
// Do something with 'control_frame' and 'len_control_frame'.
// Clean up.
fstrm_control_destroy(&c);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* \param c
* `fstrm_control` object.
* \param[out] control_frame
* The buffer in which to serialize the control frame.
* \param[in,out] len_control_frame
* The size in bytes of `control_frame`. On a successful return, contains
* the number of bytes actually written into `control_frame`.
* \param flags
* Flags controlling the encoding process. See #fstrm_control_flag.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_encode(
const struct fstrm_control *c,
void *control_frame,
size_t *len_control_frame,
const uint32_t flags);
/**@}*/
#endif /* FSTRM_CONTROL_H */
tcp_writer.h 0000644 00000006370 15042202636 0007105 0 ustar 00 /*
* Copyright (c) 2014, 2018 by Farsight Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef FSTRM_TCP_WRITER_H
#define FSTRM_TCP_WRITER_H
/**
* \defgroup fstrm_tcp_writer fstrm_tcp_writer
*
* `fstrm_tcp_writer` is an interface for opening an \ref fstrm_writer object
* that is backed by I/O on a TCP socket.
*
* @{
*/
/**
* Initialize an `fstrm_tcp_writer_options` object, which is needed to
* configure the socket address and socket port to be opened by the writer.
*
* \return
* `fstrm_tcp_writer_options` object.
*/
struct fstrm_tcp_writer_options *
fstrm_tcp_writer_options_init(void);
/**
* Destroy an `fstrm_tcp_writer_options` object.
*
* \param twopt
* Pointer to `fstrm_tcp_writer_options` object.
*/
void
fstrm_tcp_writer_options_destroy(
struct fstrm_tcp_writer_options **twopt);
/**
* Set the `socket_address` option. This is the IPv4 or IPv6 address in
* presentation format to be connected by the TCP socket.
*
* \param twopt
* `fstrm_tcp_writer_options` object.
* \param socket_address
* The socket address.
*/
void
fstrm_tcp_writer_options_set_socket_address(
struct fstrm_tcp_writer_options *twopt,
const char *socket_address);
/**
* Set the `socket_port` option. This is the TCP port number to be connected by
* the TCP socket.
*
* \param twopt
* `fstrm_tcp_writer_options` object.
* \param socket_port
* The TCP socket port number provided as a character string.
* (When converted, the maximum allowed unsigned integer is 65535.)
*/
void
fstrm_tcp_writer_options_set_socket_port(
struct fstrm_tcp_writer_options *twopt,
const char *socket_port);
/**
* Initialize the `fstrm_writer` object. Note that the TCP socket will not
* actually be opened until a subsequent call to fstrm_writer_open().
*
* \param twopt
* `fstrm_tcp_writer_options` object. Must be non-NULL, and have the
* `socket_address` and `socket_port` options set.
* \param wopt
* `fstrm_writer_options` object. May be NULL, in which chase default
* values will be used.
*
* \return
* `fstrm_writer` object.
* \retval
* NULL on failure.
*/
struct fstrm_writer *
fstrm_tcp_writer_init(
const struct fstrm_tcp_writer_options *twopt,
const struct fstrm_writer_options *wopt);
/**@}*/
#endif /* FSTRM_TCP_WRITER_H */
rdwr.h 0000644 00000022513 15042202636 0005676 0 ustar 00 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef FSTRM_RDWR_H
#define FSTRM_RDWR_H
/**
* \defgroup fstrm_rdwr fstrm_rdwr
*
* `fstrm_rdwr` is an interface for abstracting the process of reading and
* writing data to byte streams. It allows extending the `fstrm` library to
* support reading and writing Frame Streams data to new kinds of byte stream
* transports. (It also allows building mock interfaces for testing the correct
* functioning of the library.)
*
* `fstrm_rdwr` is a low-level interface that is used in conjunction with the
* higher level \ref fstrm_reader and \ref fstrm_writer interfaces. The
* following methods need to be defined for `fstrm_rdwr` implementations:
*
* Method name | Method type | Method description
* ------------ | ----------------------------- | ------------------
* `destroy` | #fstrm_rdwr_destroy_func | Destroys the instance.
* `open` | #fstrm_rdwr_open_func | Opens the stream.
* `close` | #fstrm_rdwr_close_func | Closes the stream.
* `read` | #fstrm_rdwr_read_func | Reads bytes from the stream.
* `write` | #fstrm_rdwr_write_func | Writes bytes to the stream.
*
* The `destroy` method is optional. It cleans up any remaining resources
* associated with the instance.
*
* The `open` method is required. It should perform the actual opening of the
* byte stream and prepare it to read or write data.
*
* The `close` method is required. It should perform the actual closing of the
* byte stream.
*
* If the `fstrm_rdwr` object is to be used in an `fstrm_reader` object, it must
* have a `read` method. If the `fstrm_rdwr` object embedded in an
* `fstrm_reader` object also has a `write` method, the stream will be
* considered bi-directional (that is, it supports both reading and writing) and
* handshaking will be performed. If a `read` method is supplied but a `write`
* method is not, the reader's stream will instead be considered
* uni-directional. See \ref fstrm_reader for details.
*
* If the `fstrm_rdwr` object is to be used in an `fstrm_writer` object, it must
* have a `write` method. If the `fstrm_rdwr` object embedded in an
* `fstrm_writer` object also has a `read` method, the stream will be considered
* bi-directional and shaking will be performed. If a `write` method is supplied
* but a `read` method is not, the writer's stream will instead be considered
* uni-directional. See \ref fstrm_writer for details.
*
* An `fstrm_rdwr` instance is created with a call to `fstrm_rdwr_init()`,
* optionally passing a pointer to some state object associated with the
* instance. This pointer will be passed as the first argument to each of the
* methods described above. Then, the various `fstrm_rdwr_set_*()` functions
* should be used to configure the functions to be used to invoke the methods
* required for the `fstrm_rdwr` object.
*
* @{
*/
/**
* `destroy` method function type. This method is invoked to deallocate any
* per-stream resources used by an `fstrm_rdwr` implementation.
*
* \see fstrm_rdwr_set_destroy()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
typedef fstrm_res
(*fstrm_rdwr_destroy_func)(void *obj);
/**
* `open` method function type. This method is invoked to open the stream and
* prepare it for reading or writing. For example, if an `fstrm_rdwr`
* implementation is backed by file I/O, this method might be responsible for
* opening a file descriptor.
*
* \see fstrm_rdwr_set_open()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
typedef fstrm_res
(*fstrm_rdwr_open_func)(void *obj);
/**
* `close` method function type. This method is invoked to close the stream. For
* example, if an `fstrm_rdwr` implementation is backed by file I/O, this method
* might be responsible for closing a file descriptor.
*
* \see fstrm_rdwr_set_close()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
typedef fstrm_res
(*fstrm_rdwr_close_func)(void *obj);
/**
* `read` method function type. This method is used to read data from a stream.
* It must satisfy the full amount of data requested, unless the stream has
* ended.
*
* \see fstrm_rdwr_set_read()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
* \param data
* The buffer in which to place the data read.
* \param count
* The number of bytes requested.
*
* \retval #fstrm_res_success
* The data was read successfully.
* \retval #fstrm_res_failure
* An unexpected failure occurred.
* \retval #fstrm_res_stop
* The end of the stream has occurred.
*/
typedef fstrm_res
(*fstrm_rdwr_read_func)(void *obj, void *data, size_t count);
/**
* `write` method function type. This method is used to write data to a stream.
* It must perform the full write of all data, unless an error has occurred.
*
* \see fstrm_rdwr_set_write()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
* \param iov
* Array of `struct iovec` objects.
* \param iovcnt
* Number of `struct iovec` objects in `iov`.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
typedef fstrm_res
(*fstrm_rdwr_write_func)(void *obj, const struct iovec *iov, int iovcnt);
/**
* Initialize a new `fstrm_rdwr` object.
*
* \param obj
* Per-object state.
*
* \return
* `fstrm_rdwr` object.
* \retval
* NULL on failure.
*/
struct fstrm_rdwr *
fstrm_rdwr_init(void *obj);
/**
* Destroy an `fstrm_rdwr` object. This invokes the underlying `destroy` method
* as well.
*
* \param rdwr
* Pointer to an `fstrm_rdwr` object.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
fstrm_res
fstrm_rdwr_destroy(struct fstrm_rdwr **rdwr);
/**
* Invoke the `open` method on an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
fstrm_res
fstrm_rdwr_open(struct fstrm_rdwr *rdwr);
/**
* Invoke the `close` method on an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
fstrm_res
fstrm_rdwr_close(struct fstrm_rdwr *rdwr);
/**
* Invoke the `read` method on an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param data
* The buffer in which to place the data read.
* \param count
* The number of bytes to read.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
* \return #fstrm_res_stop
*/
fstrm_res
fstrm_rdwr_read(struct fstrm_rdwr *rdwr, void *data, size_t count);
/**
* Invoke the `write` method on an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param iov
* Array of `struct iovec` objects.
* \param iovcnt
* Number of `struct iovec` objects in `iov`.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
fstrm_res
fstrm_rdwr_write(struct fstrm_rdwr *rdwr, const struct iovec *iov, int iovcnt);
/**
* Set the `destroy` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_destroy(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_destroy_func fn);
/**
* Set the `open` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_open(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_open_func fn);
/**
* Set the `close` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_close(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_close_func fn);
/**
* Set the `read` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_read(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_read_func fn);
/**
* Set the `write` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_write(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_write_func fn);
/**@}*/
#endif /* FSTRM_RDWR_H */
file.h 0000644 00000006216 15042202636 0005641 0 ustar 00 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef FSTRM_FILE_H
#define FSTRM_FILE_H
/**
* \defgroup fstrm_file fstrm_file
*
* `fstrm_file` contains interfaces for opening \ref fstrm_reader or
* \ref fstrm_writer objects that are backed by file I/O.
*
* @{
*/
/**
* Initialize an `fstrm_file_options` object, which is needed to configure the
* file path to be opened by fstrm_file_reader_init() or
* fstrm_file_writer_init().
*
* \return
* `fstrm_file_options` object.
*/
struct fstrm_file_options *
fstrm_file_options_init(void);
/**
* Destroy an `fstrm_file_options` object.
*
* \param fopt
* Pointer to `fstrm_file_options` object.
*/
void
fstrm_file_options_destroy(struct fstrm_file_options **fopt);
/**
* Set the `file_path` option. This is a filesystem path to a regular file to be
* opened for reading or writing.
*
* \param fopt
* `fstrm_file_options` object.
* \param file_path
* The filesystem path for a regular file.
*/
void
fstrm_file_options_set_file_path(struct fstrm_file_options *fopt,
const char *file_path);
/**
* Open a file containing Frame Streams data for reading.
*
* \param fopt
* `fstrm_file_options` object. Must be non-NULL, and have the `file_path`
* option set.
* \param ropt
* `fstrm_reader_options` object. May be NULL, in which case default values
* will be used.
*
* \return
* `fstrm_reader` object.
* \retval
* NULL on failure.
*/
struct fstrm_reader *
fstrm_file_reader_init(const struct fstrm_file_options *fopt,
const struct fstrm_reader_options *ropt);
/**
* Open a file for writing Frame Streams data. The file will be truncated if it
* already exists.
*
* \param fopt
* `fstrm_file_options` object. Must be non-NULL, and have the `file_path`
* option set.
* \param wopt
* `fstrm_writer_options` object. May be NULL, in which case default values
* will be used.
*
* \return
* `fstrm_writer` object.
* \retval
* NULL on failure.
*/
struct fstrm_writer *
fstrm_file_writer_init(const struct fstrm_file_options *fopt,
const struct fstrm_writer_options *wopt);
/**@}*/
#endif /* FSTRM_FILE_H */
iothr.h 0000644 00000036170 15042202636 0006051 0 ustar 00 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef FSTRM_IOTHR_H
#define FSTRM_IOTHR_H
/**
* \defgroup fstrm_iothr fstrm_iothr
*
* The `fstrm_iothr` interface creates a background I/O thread which writes
* Frame Streams encapsulated data frames into an output stream specified by an
* \ref fstrm_writer object. It exposes non-blocking input queues that can be
* used by worker threads to asynchronously write data frames to the output
* stream. A deferred deallocation callback is invoked after the I/O thread has
* disposed of a queued data frame.
*
* In order to create an `fstrm_iothr` object, the caller must first configure
* and instantiate an `fstrm_writer` object and pass this instance to the
* fstrm_iothr_init() function. The `fstrm_iothr` object then takes ownership of
* the `fstrm_writer` object. It is responsible for serializing writes and will
* take care of destroying the captive `fstrm_writer` object at the same time
* the `fstrm_iothr` object is destroyed. The caller should not perform any
* operations on the captive `fstrm_writer` object after it has been passed to
* `fstrm_iothr_init()`.
*
* Parameters used to configure the I/O thread are passed through an
* `fstrm_iothr_options` object. These options have to be specified in advance
* and are mostly performance knobs which have reasonable defaults.
*
* Once the `fstrm_iothr` object has been created, handles to the input queues
* used to submit data frames can be obtained by calling
* `fstrm_iothr_get_input_queue()`. This function can be called up to
* **num_input_queues** times, and can be safely called concurrently. For
* instance, in an application with a fixed number of worker threads, an input
* queue can be dedicated to each worker thread by setting the
* **num_input_queues** option to the number of worker threads, and then calling
* `fstrm_iothr_get_input_queue()` from each worker thread's startup function to
* obtain a per-thread input queue.
*
* @{
*/
/**
* Initialize an `fstrm_iothr_options` object. This is needed to pass
* configuration parameters to fstrm_iothr_init().
*
* \return
* `fstrm_iothr_options` object.
*/
struct fstrm_iothr_options *
fstrm_iothr_options_init(void);
/**
* Destroy an `fstrm_iothr_options` object.
*
* \param opt
* Pointer to `fstrm_iothr_options` object.
*/
void
fstrm_iothr_options_destroy(struct fstrm_iothr_options **opt);
/**
* Set the `buffer_hint` parameter. This is the threshold number of bytes to
* accumulate in the output buffer before forcing a buffer flush.
*
* \param opt
* `fstrm_iothr_options` object.
* \param buffer_hint
* New `buffer_hint` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_buffer_hint(
struct fstrm_iothr_options *opt,
unsigned buffer_hint);
/** Minimum `buffer_hint` value. */
#define FSTRM_IOTHR_BUFFER_HINT_MIN 1024
/** Default `buffer_hint` value. */
#define FSTRM_IOTHR_BUFFER_HINT_DEFAULT 8192
/** Maximum `buffer_hint` value. */
#define FSTRM_IOTHR_BUFFER_HINT_MAX 65536
/**
* Set the `flush_timeout` parameter. This is the number of seconds to allow
* unflushed data to remain in the output buffer.
*
* \param opt
* `fstrm_iothr_options` object.
* \param flush_timeout
* New `flush_timeout` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_flush_timeout(
struct fstrm_iothr_options *opt,
unsigned flush_timeout);
/** Minimum `flush_timeout` value. */
#define FSTRM_IOTHR_FLUSH_TIMEOUT_MIN 1
/** Default `flush_timeout` value. */
#define FSTRM_IOTHR_FLUSH_TIMEOUT_DEFAULT 1
/** Maximum `flush_timeout` value. */
#define FSTRM_IOTHR_FLUSH_TIMEOUT_MAX 600
/**
* Set the `input_queue_size` parameter. This is the number of queue entries to
* allocate per each input queue. This option controls the number of outstanding
* data frames per input queue that can be outstanding for deferred processing
* by the `fstrm_iothr` object and thus affects performance and memory usage.
*
* This parameter must be a power-of-2.
*
* \param opt
* `fstrm_iothr_options` object.
* \param input_queue_size
* New `input_queue_size` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_input_queue_size(
struct fstrm_iothr_options *opt,
unsigned input_queue_size);
/** Minimum `input_queue_size` value. */
#define FSTRM_IOTHR_INPUT_QUEUE_SIZE_MIN 2
/** Default `input_queue_size` value. */
#define FSTRM_IOTHR_INPUT_QUEUE_SIZE_DEFAULT 512
/** Maximum `input_queue_size` value. */
#define FSTRM_IOTHR_INPUT_QUEUE_SIZE_MAX 16384
/**
* Set the `num_input_queues` parameter. This is the number of input queues to
* create and must match the number of times that fstrm_iothr_get_input_queue()
* is called on the corresponding `fstrm_iothr` object.
*
* \param opt
* `fstrm_iothr_options` object.
* \param num_input_queues
* New `num_input_queues` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_num_input_queues(
struct fstrm_iothr_options *opt,
unsigned num_input_queues);
/** Minimum `num_input_queues` value. */
#define FSTRM_IOTHR_NUM_INPUT_QUEUES_MIN 1
/** Default `num_input_queues` value. */
#define FSTRM_IOTHR_NUM_INPUT_QUEUES_DEFAULT 1
/**
* Set the `output_queue_size` parameter. This is the number of queue entries to
* allocate for the output queue. This option controls the maximum number of
* data frames that can be accumulated in the output queue before a buffer flush
* must occur and thus affects performance and memory usage.
*
* \param opt
* `fstrm_iothr_options` object.
* \param output_queue_size
* New `output_queue_size` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_output_queue_size(
struct fstrm_iothr_options *opt,
unsigned output_queue_size);
/** Minimum `output_queue_size` value. */
#define FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MIN 2
/** Default `output_queue_size` value. */
#define FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_DEFAULT 64
/** Maximum `output_queue_size` value. */
#define FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MAX IOV_MAX
/**
* Queue models.
* \see fstrm_iothr_options_set_queue_model()
*/
typedef enum {
/** Single Producer, Single Consumer. */
FSTRM_IOTHR_QUEUE_MODEL_SPSC,
/** Multiple Producer, Single Consumer. */
FSTRM_IOTHR_QUEUE_MODEL_MPSC,
} fstrm_iothr_queue_model;
/**
* Set the `queue_model` parameter. This controls what queueing semantics to use
* for `fstrm_iothr_queue` objects. Single Producer queues
* (#FSTRM_IOTHR_QUEUE_MODEL_SPSC) may only have a single thread at a time
* calling fstrm_iothr_submit() on a given `fstrm_iothr_queue` object, while
* Multiple Producer queues (#FSTRM_IOTHR_QUEUE_MODEL_MPSC) may have multiple
* threads concurrently calling fstrm_iothr_submit() on a given
* `fstrm_iothr_queue` object.
*
* \param opt
* `fstrm_iothr_options` object.
* \param queue_model
* New `queue_model` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_queue_model(
struct fstrm_iothr_options *opt,
fstrm_iothr_queue_model queue_model);
/** Default `queue_model` value. */
#define FSTRM_IOTHR_QUEUE_MODEL_DEFAULT FSTRM_IOTHR_QUEUE_MODEL_SPSC
/**
* Set the `queue_notify_threshold` parameter. This controls the number of
* outstanding queue entries to allow on an input queue before waking the I/O
* thread, which will cause the outstanding queue entries to begin draining.
*
* \param opt
* `fstrm_iothr_options` object.
* \param queue_notify_threshold
* New `queue_notify_threshold` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_queue_notify_threshold(
struct fstrm_iothr_options *opt,
unsigned queue_notify_threshold);
/** Minimum `queue_notify_threshold` value. */
#define FSTRM_IOTHR_QUEUE_NOTIFY_THRESHOLD_MIN 1
/** Default `queue_notify_threshold` value. */
#define FSTRM_IOTHR_QUEUE_NOTIFY_THRESHOLD_DEFAULT 32
/**
* Set the `reopen_interval` parameter. This controls the number of seconds to
* wait between attempts to reopen a closed `fstrm_writer` output stream.
*
* \param opt
* `fstrm_iothr_options` object.
* \param reopen_interval
* New `queue_notify_threshold` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_reopen_interval(
struct fstrm_iothr_options *opt,
unsigned reopen_interval);
/** Minimum `reopen_interval` value. */
#define FSTRM_IOTHR_REOPEN_INTERVAL_MIN 1
/** Default `reopen_interval` value. */
#define FSTRM_IOTHR_REOPEN_INTERVAL_DEFAULT 5
/** Maximum `reopen_interval` value. */
#define FSTRM_IOTHR_REOPEN_INTERVAL_MAX 600
/**
* Initialize an `fstrm_iothr` object. This creates a background I/O thread
* which asynchronously writes data frames submitted by other threads which call
* fstrm_iothr_submit().
*
* \param opt
* `fstrm_iothr_options` object. May be NULL, in which case default values
* will be used.
*
* \param writer
* Pointer to `fstrm_writer` object. Must be non-NULL.
*
* \return
* `fstrm_iothr` object.
* \retval
* NULL on failure.
*/
struct fstrm_iothr *
fstrm_iothr_init(
const struct fstrm_iothr_options *opt,
struct fstrm_writer **writer);
/**
* Destroy an `fstrm_iothr` object. This signals the background I/O thread to
* flush or discard any queued data frames and deallocates any resources used
* internally. This function blocks until the I/O thread has terminated.
*
* \param iothr
* Pointer to `fstrm_iothr` object.
*/
void
fstrm_iothr_destroy(struct fstrm_iothr **iothr);
/**
* Obtain an `fstrm_iothr_queue` object for submitting data frames to the
* `fstrm_iothr` object. `fstrm_iothr_queue` objects are child objects of their
* parent `fstrm_iothr` object and will be destroyed when fstrm_iothr_destroy()
* is called on the parent `fstrm_iothr` object.
*
* This function is thread-safe and may be called simultaneously from any
* thread. For example, in a program which employs a fixed number of worker
* threads to handle requests, fstrm_iothr_get_input_queue() may be called from
* a thread startup routine without synchronization.
*
* `fstrm_iothr` objects allocate a fixed total number of `fstrm_iothr_queue`
* objects during the call to fstrm_iothr_init(). To adjust this parameter, use
* fstrm_iothr_options_set_num_input_queues().
*
* This function will fail if it is called more than **num_input_queues** times.
* By default, only one input queue is initialized per `fstrm_iothr` object.
*
* For optimum performance in a threaded program, each worker thread submitting
* data frames should have a dedicated `fstrm_iothr_queue` object. This allows
* each worker thread to have its own queue which is processed independently by
* the I/O thread. If the queue model for the `fstrm_iothr` object is set to
* #FSTRM_IOTHR_QUEUE_MODEL_SPSC, this results in contention-free access to the
* input queue.
*
* \param iothr
* `fstrm_iothr` object.
*
* \return
* `fstrm_iothr_queue` object.
* \retval
* NULL on failure.
*/
struct fstrm_iothr_queue *
fstrm_iothr_get_input_queue(struct fstrm_iothr *iothr);
/**
* Obtain an `fstrm_iothr_queue` object for submitting data frames to the
* `fstrm_iothr` object. This function is like fstrm_iothr_get_input_queue()
* except it indexes into the `fstrm_iothr_queue`'s array of input queues.
*
* \param iothr
* `fstrm_iothr` object.
* \param idx
* Index of the `fstrm_iothr_queue` object to retrieve. This value is
* limited by the **num_input_queues** option.
*
* \return
* `fstrm_iothr_queue` object.
* \retval
* NULL on failure.
*/
struct fstrm_iothr_queue *
fstrm_iothr_get_input_queue_idx(struct fstrm_iothr *iothr, size_t idx);
/**
* Submit a data frame to the background I/O thread. If successfully queued and
* the I/O thread has an active output stream opened, the data frame will be
* asynchronously written to the output stream.
*
* When this function returns #fstrm_res_success, responsibility for
* deallocating the data frame specified by the `data` parameter passes to the
* `fstrm` library. The caller **MUST** ensure that the `data` object remains
* valid after fstrm_iothr_submit() returns. The callback function specified by
* the `free_func` parameter will be invoked once the data frame is no longer
* needed by the `fstrm` library. For example, if the data frame is dynamically
* allocated, the data frame may be deallocated in the callback function.
*
* Note that if this function returns #fstrm_res_failure, the responsibility for
* deallocating the data frame remains with the caller.
*
* As a convenience, if `data` is allocated with the system's `malloc()`,
* `fstrm_free_wrapper` may be provided as the `free_func` parameter with the
* `free_data` parameter set to `NULL`. This will cause the system's `free()` to
* be invoked to deallocate `data`.
*
* `free_func` may be NULL, in which case no callback function will be invoked
* to dispose of `buf`. This behavior may be useful if `data` is a global,
* statically allocated object.
*
* \param iothr
* `fstrm_iothr` object.
* \param ioq
* `fstrm_iothr_queue` object.
* \param data
* Data frame bytes.
* \param len
* Number of bytes in `data`.
* \param free_func
* Callback function to deallocate the data frame. The `data` and
* `free_data` parameters passed to this callback will be the same values
* originally supplied in the call to fstrm_iothr_submit().
* \param free_data
* Parameter to pass to `free_func`.
*
* \retval #fstrm_res_success
* The data frame was successfully queued.
* \retval #fstrm_res_again
* The queue is full.
* \retval #fstrm_res_failure
* Permanent failure.
*/
fstrm_res
fstrm_iothr_submit(
struct fstrm_iothr *iothr, struct fstrm_iothr_queue *ioq,
void *data, size_t len,
void (*free_func)(void *buf, void *free_data), void *free_data);
/**
* Wrapper function for the system's `free()`, suitable for use as the
* `free_func` callback for fstrm_iothr_submit().
*
* \param data
* Object to call `free()` on.
* \param free_data
* Unused.
*/
void
fstrm_free_wrapper(void *data, void *free_data);
/**@}*/
#endif /* FSTRM_IOTHR_H */
writer.h 0000644 00000020426 15042202636 0006235 0 ustar 00 /*
* Copyright (c) 2014, 2018 by Farsight Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef FSTRM_WRITER_H
#define FSTRM_WRITER_H
/**
* \defgroup fstrm_writer fstrm_writer
*
* `fstrm_writer` is an interface for writing Frame Streams data into a byte
* stream. The underlying byte stream I/O operations are abstracted by the
* \ref fstrm_rdwr interface. Thus, the `fstrm_writer` interface can be used to
* write Frame Streams data to any type of output whose read/write operations
* are wrapped by an `fstrm_rdwr` object.
*
* Some basic `fstrm_writer` implementations are already provided in the `fstrm`
* library. See fstrm_file_writer_init() for an implementation that writes to
* a regular file, fstrm_tcp_writer_init() for an implementation that writes to
* a TCP socket, and fstrm_unix_writer_init() for an implementation that writes
* to a Unix socket.
*
* @{
*/
/**
* Initialize an `fstrm_writer_options` object.
*
* \return
* `fstrm_writer_options` object.
*/
struct fstrm_writer_options *
fstrm_writer_options_init(void);
/**
* Destroy an `fstrm_writer_options` object.
*
* \param wopt
* Pointer to `fstrm_writer_options` object.
*/
void
fstrm_writer_options_destroy(
struct fstrm_writer_options **wopt);
/**
* Add a "Content Type" value to the set of content types that can be negotiated
* by the writer. This function makes a copy of the provided string. This
* function may be called multiple times, in which case multiple "Content Type"
* values will be accepted by the reader.
*
* For uni-directional streams like regular files, the negotiated content type
* will simply be the first content type provided to this function. For
* bi-directional streams like sockets, a handshake occurs and the remote end
* determines which content type should be sent. In the latter case, after the
* writer has been successfully opened with a call to fstrm_writer_open(), the
* fstrm_writer_get_control() function should be called with `type` set to
* `FSTRM_CONTROL_ACCEPT` and the control frame queried in order to determine
* the negotiated content type.
*
* \param wopt
* `fstrm_writer_options` object.
* \param content_type
* The "Content Type" string to copy. Note that this string is not
* NUL-terminated and may contain embedded NULs.
* \param len_content_type
* The number of bytes in `content_type`.
*
* \retval #fstrm_res_success
* The "Content Type" field was successfully added.
* \retval #fstrm_res_failure
* The "Content Type" string is too long.
*/
fstrm_res
fstrm_writer_options_add_content_type(
struct fstrm_writer_options *wopt,
const void *content_type,
size_t len_content_type);
/**
* Initialize a new `fstrm_writer` object based on an underlying `fstrm_rdwr`
* object and an `fstrm_writer_options` object.
*
* The underlying `fstrm_rdwr` object MUST have a `write` method. It MAY
* optionally have a `read` method, in which case the stream will be treated as
* a bi-directional, handshaked stream. Otherwise, if there is no `read` method
* the stream will be treated as a uni-directional stream.
*
* This function is useful for implementing functions that return new types of
* `fstrm_writer` objects, such as fstrm_file_writer_init() and
* fstrm_unix_writer_init().
*
* After a successful call to this function, the ownership of the `fstrm_rdwr`
* object passes from the caller to the `fstrm_writer` object. The caller
* should perform no further calls on the `fstrm_rdwr` object. The `fstrm_rdwr`
* object will be cleaned up on a call to fstrm_writer_destroy().
*
* \param wopt
* `fstrm_writer_options` object. May be NULL, in which case default values
* will be used.
*
* \param rdwr
* Pointer to `fstrm_rdwr` object. Must be non-NULL. The `fstrm_rdwr`
* object must have a `write` method, and may optionally have a `read`
* method.
*
* \return
* `fstrm_writer` object.
* \retval
* NULL on failure.
*/
struct fstrm_writer *
fstrm_writer_init(
const struct fstrm_writer_options *wopt,
struct fstrm_rdwr **rdwr);
/**
* Destroy an `fstrm_writer` object. This implicitly calls fstrm_writer_close()
* if necessary.
*
* \param w
* Pointer to `fstrm_writer` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_destroy(struct fstrm_writer **w);
/**
* Open an `fstrm_writer` object and prepare it to write data. For
* bi-directional writer implementations, this performs content type
* negotiation.
*
* This function may fail if there was an underlying problem opening the output
* stream.
*
* \param w
* `fstrm_writer` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_open(struct fstrm_writer *w);
/**
* Close an `fstrm_writer` object. Open it has been closed, no data frames may
* subsequently be written.
*
* Calling this function is optional; it may be implicitly invoked by a call to
* fstrm_writer_destroy().
*
* \param w
* `fstrm_writer` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_close(struct fstrm_writer *w);
/**
* Write a data frame to an `fstrm_writer` object.
*
* This function implicitly calls fstrm_writer_open() if necessary.
*
* \param w
* `fstrm_writer` object.
* \param[in] data
* Buffer containing the data frame payload.
* \param[in] len_data
* The number of bytes in `data`.
*
* \retval #fstrm_res_success
* The data frame was successfully written.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_write(
struct fstrm_writer *w,
const void *data,
size_t len_data);
/**
* Write multiple data frames to an `fstrm_writer` object.
*
* This function implicitly calls fstrm_writer_open() if necessary.
*
* Data frames are passed similarly to the `writev()` system call, with an array
* of `struct iovec` objects describing the data frame payloads and their
* lengths. The complete set of data frames will be written to the output
* stream after a successful call.
*
* \param w
* `fstrm_writer` object.
* \param iov
* Array of `struct iovec` objects.
* \param iovcnt
* Number of `struct iovec` objects in `iov`.
*
* \retval #fstrm_res_success
* The data frames were successfully written.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_writev(
struct fstrm_writer *w,
const struct iovec *iov,
int iovcnt);
/**
* Obtain a pointer to an `fstrm_control` object used during processing. Objects
* returned by this function are owned by the `fstrm_reader` object and must not
* be modified by the caller. After a call to fstrm_reader_destroy() these
* pointers will no longer be valid.
*
* For example, with bi-directional streams this function can be used to obtain
* a pointer to the ACCEPT control frame, which can be queried to see which
* "Content Type" was negotiated during the opening of the writer.
*
* This function implicitly calls fstrm_writer_open() if necessary.
*
* \param w
* `fstrm_writer` object.
* \param type
* Which control frame to return.
* \param[out] control
* The `fstrm_control` object.
*
* \retval #fstrm_res_success
* If an `fstrm_control` object was returned.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_get_control(
struct fstrm_writer *w,
fstrm_control_type type,
struct fstrm_control **control);
/**@}*/
#endif /* FSTRM_WRITER_H */