/usr/include/fstrm/control.h is in libfstrm-dev 0.3.0-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 | /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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 */
|