Welcome to the NEAT documentation!¶
Welcome to the NEAT tutorial¶
What is NEAT?¶
NEAT is a library for networked applications, intended to replace existing socket APIs with a simpler, more flexible API. Additionally, NEAT enables endpoints to make better decisions as to how to utilize the available network resources and adapts based on the current condition of the network.
With NEAT, applications are able to specify the service they want from the transport layer. NEAT will determine which of the available protocols fit the requirements of the application and tune all the relevant parameters to ensure that the application gets the desired service from the transport layer, based on knowledge about the current state of the network when this information is available.
NEAT enables applications to be written in a protocol-agnostic way, thus allowing applications to be future-proof, leveraging new protocols as they become available, with minimal to no change. Further, NEAT will try to connect with different protocols if possible, making it able to gracefully fall back to another protocol if it turns out that the most optimal protocol is unavailable, for example, because of a middlebox such as a firewall. A connection in the NEAT API will only fail if all protocols satisfying the requirements of the application are unable to connect, or if no available protocol can satisfy the requirements of the application.
Most operating systems support the same protocols. However, the same protocol may often have a slightly different API on different operating systems. NEAT provides the same API on all supported operating systems, which is currently Linux, FreeBSD, OpenBSD, NetBSD, and OS X. The availability of a protocol depends on whether the protocol is supported by the OS or if NEAT is compiled with support for a user-space stack that implements the protocol.
Contexts and flows¶
The most important concept in the NEAT API is that of the flow. A flow is similar to a socket in the traditional Berkely Socket API. It is a bidirectional link used to communicate between two applications, on which data may be written to or read from. Further, just like a socket, a flow uses some transport layer protocol to communicate.
However, one important difference is that a flow is not as strictly tied to the underlying transport protocol in the same way a socket is. In fact, a flow may be created without even specifying which transport protocol to use. This is not possible with a socket.
The same applies to modifying options on sockets. Setting the same kind of
option on two sockets with different protocols in the traditional socket API
requires setsockopt
calls with different protocol IDs, option names, and
sometimes even values with different units. The setsockopt
calls also vary
depending on what system you are on. This is not the case with NEAT. As long as
the desired option is available for the protocol in use, the API for setting
that option is the same for all protocols, and on all operating systems
supported by NEAT.
A context is a common environment for multiple flows. Along with flows, it contains several services that are used by the flows internally in NEAT, such as a DNS resolver and a Happy Eyeballs implementation. Flows within a context are polled together. A flow may only belong to the context in which it is created, and it cannot be transferred to a different context. Most applications need only one context.
Properties¶
Different types of applications have different requirements and desires to the services provided by the transport layer. An application for real-time communication may require the communication to have properties such as low latency, high bandwidth, quality of service, and have less strict requirements with regards to reliable delivery. Losing a packet or bit errors may be less critical to these applications. A web browser, on the other hand, might require communication that is (partially) ordered and error-free. A BitTorrent application might only require the ability to send packets to some destination with a minimum amount of effort, and not at the expense of other applications with stricter bandwidth requirements.
With the traditional socket API, the application requirements dictate the choice of which protocol to use. With NEAT, this is not the case. NEAT enables applications to specify the properties of the communication instead of specifying which protocol to use. Some properties may be required; other properties may be desired, but not mandatory. Based on the properties, NEAT will determine which protocols can support the requirements of the application and the options to set for each protocol. It will try to establish a connection by trying each of them until one connection succeeds, known as Happy Eyeballing.
The ability to specify properties instead of protocols allows applications to take advantage of available protocols where possible. By Happy Eyeballing, NEAT ensures that applications are able to cope with different network configurations, and gracefully fall back to another protocol if necessary should the most desirable protocol not be available for whatever reason.
Asynchronous API¶
The NEAT API is asynchronous and non-blocking. Once the execution is transferred to NEAT, it will poll the sockets internally, and, when an event happens, execute the appropriate callback in the application. This creates a more natural way of programming communicating applications than with the traditional socket API.
The three most important callbacks in the NEAT API are on_connected
,
on_readable
and on_writable
, which may be set per flow. The on_connected
callback will be executed once the flow has connected to a remote endpoint, or
a flow has connected to a server listening for incoming connections. The
on_writable
and on_readable
callbacks are executed once data may be written
to or read from the flow without blocking.
A minimal server¶
To get started using the NEAT API, we will write a small server that will send
Hello, this is NEAT!
to any client that connects to it. Later, we will write a
similar client, before modifying this server so that it works with the client.
We can summarize the functionality as follows:
- When a client connects, start writing when the flow is writable
- When a flow is writable, write
Hello, this is NEAT!
to it. - When the flow has finished writing, close it.
Pay close attention to how easily this natural description can be implemented using the NEAT API.
Here are the includes that should be put on top of the file:
#include <neat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
We will start writing the main function of our server. The first thing we need to do is to declare a few variables:
struct neat_ctx *ctx;
struct neat_flow *flow;
struct neat_flow_operations ops;
And initialize them:
ctx = neat_init_ctx();
if (!ctx) {
fprintf(stderr, "neat_init_ctx failed\n");
return EXIT_FAILURE;
We are already familiar with the flow and the context. neat_init_ctx
is used
to initialize the context, and neat_new_flow
creates a new flow withing the
context. The neat_flow_operations
struct is used to tell NEAT what to do
when certain events occur. We will use that next to tell which function we
want NEAT to call when a client connects:
}
flow = neat_new_flow(ctx);
if (!flow) {
The function on_connected
has not been defined yet, we will do that later.
Now that we have told NEAT what to do with a connecting client, we are ready
to accept incoming connections.
fprintf(stderr, "neat_new_flow failed\n");
return EXIT_FAILURE;
}
memset(&ops, 0, sizeof(ops));
This will instruct NEAT to start listening to incoming connections on port 5000.
The flow passed to neat_accept
is cloned for each accepted connection. The
last two parameters are used for optional arguments. This example does not use
them.
The last function call we will do in main will be the one that starts the show:
ops.on_readable = on_readable;
When this function is called, NEAT will start doing work behind the scenes.
When called with the NEAT_RUN_DEFAULT
parameter, this function will not
return until all flows have closed and all events have been handled. It is
also possible to run NEAT without having NEAT capture the main loop. Our final
main function looks like this:
int
main(int argc, char *argv[])
{
struct neat_ctx *ctx;
struct neat_flow *flow;
struct neat_flow_operations ops;
ctx = neat_init_ctx();
if (!ctx) {
fprintf(stderr, "neat_init_ctx failed\n");
return EXIT_FAILURE;
}
flow = neat_new_flow(ctx);
if (!flow) {
fprintf(stderr, "neat_new_flow failed\n");
return EXIT_FAILURE;
}
memset(&ops, 0, sizeof(ops));
ops.on_readable = on_readable;
ops.on_connected = on_connected;
neat_set_operations(ctx, flow, &ops);
We have now filled in the main function of our server application. It is time
to start working on the callbacks that NEAT will use. The first callback we
need is on_connected
.
static neat_error_code
on_connected(struct neat_flow_operations *opCB)
From the functional description above, we know that we need to write to
connecting clients when this becomes possible. The callback contains a
parameter that is a pointer to a neat_flow_operations
struct, which we can
use to update the active callbacks of the flow. We set the on_writable
callback so that we can start writing when the flow becomes writable:
opCB->on_writable = on_writable;
It is also good practice to set the on_all_written
callback when setting the
on_writable
callback:
opCB->on_all_written = on_all_written;
The change is applied by calling neat_set_operations
, just as in the main function:
neat_set_operations(opCB->ctx, opCB->flow, opCB);
Next, we write the on_writable
callback:
on_writable(struct neat_flow_operations *opCB)
{
Here, we call the function that will send our message:
neat_write(opCB->ctx, opCB->flow, message, 20, NULL, 0);
opCB->on_writable = NULL;
return NEAT_OK;
Here we specify the data to send and the length of the data.
As with the neat_accept
function, neat_write
takes optional parameters.
We do not need to set any optional parameters for this call either, so again we
pass NULL
and 0
.
The final callback we need to implement is the on_all_written
callback:
static neat_error_code
on_all_written(struct neat_flow_operations *opCB)
Here, we call neat_close
to close the flow:
neat_close(opCB->ctx, opCB->flow);
This is the final piece of our server. You may now compile and run the server.
You can use the tool socat
to test it. The following output should be observed:
$ socat STDIO TCP:localhost:5000
Hello, this is NEAT!
$ socat STDIO SCTP:localhost:5000
Hello, this is NEAT!
You may find the complete source for the server here.
A minimal client¶
Next, we want to implement a client that will send the message "Hi!"
after
connecting to a server, and then receive a reply from the server. A fair amount
of the code will be similar to the server we wrote above, so you may make a
copy of the code for the server and use that as a starting point for the client.
We will make two additions and one change to the main function. First, since we
are connecting to a server, we change the neat_accept
call to neat_open
instead:
}
flow = neat_new_flow(ctx);
if (!flow) {
Next, we will specify a few properties for the flow:
static char *properties = "{\n\
\"transport\": [\n\
{\n\
\"value\": \"SCTP\",\n\
\"precedence\": 1\n\
},\n\
{\n\
\"value\": \"TCP\",\n\
\"precedence\": 1\n\
}\n\
]\n\
}";
These properties will tell NEAT that it can select either SCTP or TCP as the
transport protocol. The properties are applied with neat_set_properties
, which
may be done at any point between neat_new_flow
and neat_open
.
Finally, we add neat_free_ctx
after neat_start_event_loop
, so that NEAT may
free any allocated resources and exit gracefully. The complete main function
of the client will look like this:
int
main(int argc, char *argv[])
{
struct neat_ctx *ctx;
struct neat_flow *flow;
struct neat_flow_operations ops;
ctx = neat_init_ctx();
if (!ctx) {
fprintf(stderr, "neat_init_ctx failed\n");
return EXIT_FAILURE;
}
flow = neat_new_flow(ctx);
if (!flow) {
fprintf(stderr, "neat_new_flow failed\n");
return EXIT_FAILURE;
}
memset(&ops, 0, sizeof(ops));
ops.on_connected = on_connected;
ops.on_close = on_close;
neat_set_operations(ctx, flow, &ops);
if (neat_set_property(ctx, flow, properties) != NEAT_OK) {
fprintf(stderr, "neat_set_property failed\n");
return EXIT_FAILURE;
Leave the on_connected
callback similar to the server.
We change the on_writable
callback to send "Hi!"
instead:
static neat_error_code
on_writable(struct neat_flow_operations *ops)
{
const unsigned char message[] = "Hi!";
neat_write(ops->ctx, ops->flow, message, 3, NULL, 0);
return NEAT_OK;
}
The on_all_written
callback should not close the flow, but instead stop
writing and set the on_readable
callback:
static neat_error_code
on_all_written(struct neat_flow_operations *ops)
{
ops->on_readable = on_readable;
ops->on_writable = NULL;
neat_set_operations(ops->ctx, ops->flow, ops);
return NEAT_OK;
}
Finally, we will write an on_readable
callback for the client. We allocate
some space on the stack to store the received data, and use a variable to store
the length of the received message. If the neat_read
call returns successfully,
we print the message. Finally, we stop the internal event loop in NEAT, which
will eventually cause the call to neat_start_event_loop
in the main function
to return. The on_readable
callback should look like this:
static neat_error_code
on_readable(struct neat_flow_operations *ops)
{
uint32_t bytes_read = 0;
unsigned char buffer[32];
if (neat_read(ops->ctx, ops->flow, buffer, 31, &bytes_read, NULL, 0) == NEAT_OK) {
buffer[bytes_read] = 0;
fprintf(stdout, "Read %u bytes:\n%s", bytes_read, buffer);
}
neat_close(ops->ctx, ops->flow);
return NEAT_OK;
}
And there we have our finished client! You can test it with socat
:
$ socat TCP-LISTEN:5000 STDIO
When you run the client, you should see Hi!
show up in the output from socat.
You can type a short message followed by pressing return, and it should show
up in the output on the client.
You may find the complete source for the client here.
Tying the client and server together¶
A few small changes are required on the server to make the client and server
work together. In the on_connected
callback, the server should set the
on_readable
callback instead of the on_writable
callback. An on_readable
callback should be added and read the incoming message from the client, and set
the on_writable
callback.
The callbacks for the updated server is as follows:
static neat_error_code
on_readable(struct neat_flow_operations *ops)
{
uint32_t bytes_read = 0;
unsigned char buffer[32];
if (neat_read(ops->ctx, ops->flow, buffer, 31, &bytes_read, NULL, 0) == NEAT_OK) {
buffer[bytes_read] = 0;
fprintf(stdout, "Read %u bytes:\n%s\n", bytes_read, buffer);
}
ops->on_readable = NULL;
ops->on_writable = on_writable;
ops->on_all_written = on_all_written;
neat_set_operations(ops->ctx, ops->flow, ops);
return NEAT_OK;
}
static neat_error_code
on_writable(struct neat_flow_operations *ops)
{
const unsigned char message[] = "Hello, this is NEAT!";
neat_write(ops->ctx, ops->flow, message, 20, NULL, 0);
ops->on_writable = NULL;
ops->on_readable = NULL;
ops->on_all_written = on_all_written;
neat_set_operations(ops->ctx, ops->flow, ops);
return NEAT_OK;
}
static neat_error_code
on_all_written(struct neat_flow_operations *ops)
{
ops->on_readable = NULL;
ops->on_writable = NULL;
ops->on_all_written = NULL;
neat_set_operations(ops->ctx, ops->flow, ops);
neat_close(ops->ctx, ops->flow);
return NEAT_OK;
}
static neat_error_code
on_connected(struct neat_flow_operations *ops)
{
ops->on_readable = on_readable;
neat_set_operations(ops->ctx, ops->flow, ops);
return NEAT_OK;
}
You may find the complete source for the updated server here. A minimal CMakeLists.txt for cmake can be found here.
Optional arguments¶
Some of the functions in the NEAT API, such as neat_open
, neat_read
and
neat_write
, take optional arguments. These are sometimes used to pass
optional arguments to functions, and sometimes used to return additional
values from the function. Optional arguments are passed as an array of the
struct neat_tlv
and an integer specifying the length of this array.
neat_tlv
is defined as follows:
struct neat_tlv {
neat_tlv_tag tag;
neat_tlv_type type;
union {
int integer;
char *string;
float real;
} value;
};
An optional argument takes the form of a tag name, a type, and a value of either a string, integer or a floating point number. The tag specifies which optional argument the value belongs to, and the type asserts the type of the value passed as this argument. An error will be raised of the type is different than what the function expects.
You may either work with this struct directly, or you may use the preprocessor macros explained later in this document.
Specifying no optional arguments¶
To specify no optional arguments, simply pass NULL
as the optargs
parameter
and 0
as the opt_count
parameter of the function.
Optional argument macros¶
- NEAT_OPTARGS_DECLARE(max) - Declare the necessary variables to use the
rest of these macros. Allocates (on the stack) an array of length max and
an integer for storing the number of optional arguments specified.
NEAT_OPTARGS_MAX
may be used as the default array size. - NEAT_OPTARGS_INIT() - Initializes the variables declared by
NEAT_OPTARGS_DECLARE
. May also be used to reset the (number of) optional arguments back to 0. - NEAT_OPTARG_INT(tag,value) - Specify the tag and the value of an optional argument that takes an integer.
- NEAT_OPTARG_FLOAT(tag,value) - Specify the tag and the value of an optional argument that takes a floating point number.
- NEAT_OPTARG_STRING(tag,value) - Specify the tag and the value of an optional argument that takes a string.
- NEAT_OPTARGS - Represents the array of optional arguments. Specify this
macro as the
optarg
parameter. - NEAT_OPTARG_COUNT - Stores the number of the optional arguments
specified so far with
NEAT_OPTARG_INT
,NEAT_OPTARG_FLOAT
orNEAT_OPTARG_STRING
. This count is reset byNEAT_OPTARGS_INIT()
. Specify this macro as theopt_count
argument.
Optional argument tags¶
- NEAT_TAG_STREAM_ID (integer) - Specifies the ID of the stream which the data should be written to, or which stream the data was read from.
- NEAT_TAG_STREAM_COUNT (integer) - Specifies the number of stream to create. Only used with protocols that support multiple streams.
- NEAT_TAG_FLOW_GROUP (int) - Specifies the flow group this flow belongs to.
- NEAT_TAG_PRIORITY (float) - Specifies the priority of this flow relative to other flows in the flow group.
- NEAT_TAG_CC_ALGORITHM (string) - Speficies the name of the (TCP) congestion control algorithm that will be used by this flow. A system default will be used if the specified algorithm is not available.
Currently unused tags:
- NEAT_TAG_LOCAL_NAME
- NEAT_TAG_SERVICE_NAME
- NEAT_TAG_CONTEXT
- NEAT_TAG_PARTIAL_RELIABILITY_METHOD
- NEAT_TAG_PARTIAL_RELIABILITY_VALUE
- NEAT_TAG_PARTIAL_MESSAGE_RECEIVED
- NEAT_TAG_PARTIAL_SEQNUM
- NEAT_TAG_UNORDERED
- NEAT_TAG_UNORDERED_SEQNUM
- NEAT_TAG_DESTINATION_IP_ADDRESS
Examples¶
NEAT_OPTARGS_DECLARE(NEAT_OPTARGS_MAX);
NEAT_OPTARGS_INIT();
NEAT_OPTARG_INT(NEAT_TAG_STREAM_COUNT, 5);
neat_open(ctx, flow, "127.0.0.1", 8000, NEAT_OPTARGS, NEAT_OPTARGS_COUNT);
Properties¶
A property in NEAT may either express a requirement or it may express a desire from the application with regards to the service provided by the transport layer.
Properties are represented as JSON objects. A set of properties may be contained within one JSON object. Below is an example of a JSON object with a single property:
{
"property_name": {
value: "property_value",
precedence: 1
}
}
Note that all examples of properties will be specified inside a JSON object.
Properties have a name, a value, and a precedence. A string is always used for the name of a property. The value of a property may be either a boolean, a string, an integer, a floating point number, an array, or an interval. Each property expects only one specific type.
The properties are sent to the Policy Manager (if present), which will return a list containing a list of candidates, which is ordered by how good the candidate matches the request from the application. Each candidate specifies a given setting for each property. NEAT will use the properties specified in each candidate when trying to set up a new connection.
Some properties are set by NEAT based on parameters to function calls. Other
properties must be set manually with the neat_set_property
function.
Application property reference¶
These are properties that may be set by the application.
transport¶
Type: Array
Specifies an array of transport protocols that may be used. An application may specify either one protocol with precedence 2, or multiple protocols with precedence 1.
Note: May not be queried with neat_get_property
before execution of the
on_connected
callback. When querying this property, the returned value is a
string describing the actual transport in use.
Note: Applications should avoid specifying the protocol(s) to use directly,
and instead rely on the Policy Manager to make a decision on what protocol(s)
to use based on other properties. The transport
property should only be used
for systems without a Policy Manager, or if the choice of transport protocol is
strictly mandated by the application protocol.
Example 1: Multiple protocols
{
"transport":
{
"value": [ "SCTP", "TCP" ]
"precedence": 1
}
}
Example 2: One protocol
{
"transport":
{
"value": "UDP",
"precedence": 2
}
}
Available protocols:
- SCTP
- SCTP/UDP (SCTP tunneled over UDP)
- TCP
- UDP
- UDP-Lite
security¶
Type: Boolean
Specifies whether the connection should be encrypted or not. With precedence 2, NEAT will only report the connection as established if it was able to connect and the (D)TLS handshake succeeds. With precedence 1, NEAT may still attempt to establish an unencrypted connection.
Inferred properties¶
These are properties that are inferred during connection setup and subsequently sent to the Policy Manager. Applications should not set these directly.
interfaces¶
Type: Array
Specifies a list of available interfaces that may be used for connections. The Policy Manager may not use all interfaces in this list.
This property is inferred during the neat_open
call. Do not set this property
manually.
domain_name¶
Type: String
Specifies the name of the remote endpoint to connect to with the neat_open
call.
This property is inferred from the name
parameter of neat_open
call. Do not
set this property manually.
port¶
Type: Integer
This property is inferred from the neat_open
and neat_accept
calls. Do not
set this property manually.
Architecture¶
Application¶
The application in NEAT terminology is the software using the transport layer to communicate with a remote endpoint.
NEAT API¶
The NEAT API is the public interface which applications may use to implement communication over the transport layer.
NEAT Core¶
The NEAT Core ties all the various components of the NEAT framework together, and handles communication over the transport layer once the connection has been established.
Connection setup in NEAT¶
The following is a description of how a connection is set up in NEAT:
The application specifies properties of the communication with
neat_set_property
.The application calls
neat_open
in the NEAT API.The NEAT Core sends application properties and inferred properties to the Policy Manager.
The Policy Manager replies with an initial set of candidates eligible for name resolution (e.g. DNS lookup).
The NEAT Core initiates one or more name resolution requests to the Name Resolver.
The Name Resolver replies with resolved addresses, and the NEAT Core inserts these into each candidate.
The NEAT Core makes a second call to the Policy Manager.
The Policy Manager returns a list of suitable candidates that the NEAT Core should use to establish a connection. A candidate consists of the following:
- Transport protocol
- Interface
- Port
- Local address
- Remote address
- Priority
- Application properties
If one or more of the application properties are specified as desired (precedence 1), multiple candidates may be generated with different settings for that property.
The NEAT Core generates a list of Happy Eyeball candidates and initiates the Happy Eyeballs algorithm.
The Happy Eyeballs module tries to connect each candidate in turn. The delay between each candidate is determined from the priority of the candidate. A lower value implies a higher priority. The connection may be handled by either the operating system using its own implementation of the protocol, or using a userspace implementation of the protocol.
The first connection that connects successfully and meets all required properties set by the application is returned to the NEAT Core.
NEAT starts polling the socket internally, and reports back to the application that a connection has been established using the
on_connected
callback if it has been specified usingneat_set_operations
.NEAT will report that the flow is readable or writable if the respective
on_readable
oron_writable
callbacks have been specified withneat_set_operations
.The application closes the flow with
neat_close
.
Callbacks¶
Callbacks are used in NEAT to signal events to the application. They are used to inform the application when a flow is readable, writable, or an error has occurred.
Most callbacks have the following syntax:
neat_error_code
on_event_name(neat_flow_operations *ops)
{
return NEAT_OK; // or some error code
}
The struct neat_flow_operations
is defined as follows:
struct neat_flow_operations
{
void *userData;
neat_error_code status;
int stream_id;
struct neat_ctx *ctx;
struct neat_flow *flow;
neat_flow_operations_fx on_connected;
neat_flow_operations_fx on_error;
neat_flow_operations_fx on_readable;
neat_flow_operations_fx on_writable;
neat_flow_operations_fx on_all_written;
neat_flow_operations_fx on_network_status_changed;
neat_flow_operations_fx on_aborted;
neat_flow_operations_fx on_timeout;
neat_flow_operations_fx on_close;
neat_cb_send_failure_t on_send_failure;
neat_cb_flow_slowdown_t on_slowdown;
neat_cb_flow_rate_hint_t on_rate_hint;
};
- userData: Applications may freely store a pointer in this field.
- status: Reports any errors associated with the flow.
- stream_id: For flows that use explicit multistreaming. Specifies which stream the event is related to, if any.
- ctx: Pointer to the context the flow belongs to.
- flow: Pointer to the flow on which the event happened.
Callbacks are set by assigning the function pointer to the struct passed to the
callback and then calling neat_set_operations
. A NULL
pointer may be used to
indicate that the callback should no longer be called.
Example callback flow¶
For most applications it will be sufficient to use the following callback flow:
+
|
|
|
+--------v---------+
| on_connected() |
+--------+---------+
|
+------------+-------------+
| |
+--------v---------+ +--------v---------+
| on_readable() | | on_writable() | <------+
+------------------+ +--------+---------+ |
| |
| |
| |
+--------v---------+ |
| on_all_written() | ------+
+------------------+
See the tutorial for more details.
Callback reference¶
on_connected¶
Called whenever an outgoing connection has been established with neat_open
,
or an incoming connection has been established with neat_accept
.
on_error¶
Called whenever an error occurs when processing the flow. Errors are considered critical.
on_readable¶
Called whenever the flow can be read from without blocking. NEAT does not permit blocking reads.
on_writable¶
Called whenever the flow can be written to without blocking. NEAT does not permit blocking writes.
on_all_written¶
Called when all previous data sent with neat_write
has been completely
written. Does not signal that the flow is writable. Applications may use this
callback to re-enable the on_writable
callback.
on_network_status_changed¶
Inform application that something has happened in the network. This also
includes flow endpoints going up, which will subsequently trigger
on_connected
if that callback is set.
Only available when using SCTP.
on_aborted¶
Called when the remote end aborts the flow. Available for flows using TCP or SCTP.
on_timeout¶
Called if sent data is not acknowledged within the time specified with
neat_change_timeout
.
Currently only available for TCP on Linux.
on_close¶
Called when the graceful connection shutdown has completed.
Only available when using SCTP or TCP. Note that when using TCP, this callback
is called when the close()
system call is made, as TCP implementations currently
does not provide any more accurate way of signalling this.
on_send_failure¶
Defined as:
void
on_send_failure(struct neat_flow_operations *flowops, int context, const unsigned char *unsent)
{
}
Called to inform the application that the returned message unsent
could not be
transmitted. The failure reason as reported by the transport protocol is
returned in the standard status code, as an abstracted NEAT error code. If the
message was tagged with a context number, it is returned in context.
Only available for SCTP. Flows using TCP may use timeouts instead.
on_slowdown¶
Not currently implemented.
Defined as:
void
on_slowdown(struct neat_flow_operations *ops, int ecn, uint32_t rate)
{
}
Inform the application that the flow has experienced congestion and that the
sending rate should be lowered. If rate
is non-zero, it is an estimate of the
new maximum sending rate. ecn
is a boolean indicating whether this
notification was triggered by an ECN mark.
on_rate_hint¶
Not currently implemented.
Defined as:
void
on_rate_hint(struct neat_flow_operations *ops, uint32_t new_rate)
{
}
Called to inform the application that it may increase its sending rate. If
new_rate
is non-zero, it is an estimate of the maximum sending rate.
Error codes¶
NEAT_OK¶
Signals that no error has occurred. Equals to 0
.
NEAT_ERROR_WOULD_BLOCK¶
Signals that the operation could not be performed because it would block the process. NEAT does not permit blocking operations.
NEAT_ERROR_BAD_ARGUMENT¶
Signals that one or more arguments given to the function was invalid or incorrect. This also includes optional arguments.
NEAT_ERROR_IO¶
Signals that an internal I/O operation in NEAT has failed.
NEAT_ERROR_DNS¶
Signals that there was an error performing DNS resolution.
NEAT_ERROR_INTERNAL¶
Signals that there was an error internally in NEAT.
NEAT_ERROR_SECURITY¶
Signals that there was an error setting up an encrypted flow.
NEAT_ERROR_UNABLE¶
Signals that NEAT is not able to perform the requested operation.
NEAT_ERROR_MESSAGE_TOO_BIG¶
Signals that the provided buffer space is not sufficient for the received message.
NEAT_ERROR_REMOTE¶
Signals that there was an error on the remote endpoint.
NEAT_ERROR_OUT_OF_MEMORY¶
Signals that NEAT is not able to allocate enough memory to complete the requested operation.
neat_init_ctx¶
Summary.
Syntax¶
struct neat_ctx *neat_init_ctx();
Parameters¶
None.
Return values¶
- Returns a pointer to a newly allocated and initialized NEAT context.
- Returns
NULL
if a context could not be allocated.
Remarks¶
None.
Examples¶
None.
See also¶
neat_free_ctx¶
Summary.
Syntax¶
void neat_free_ctx(struct neat_ctx *ctx);
Parameters¶
- ctx: Pointer to the NEAT context to free.
Return values¶
None.
Remarks¶
If there are any flows still kept in this context, those will be freed and closed as part of this operation.
Examples¶
None.
See also¶
neat_new_flow¶
Allocate and initialize a new NEAT flow.
Syntax¶
neat_flow *neat_new_flow(struct neat_ctx *ctx);
Parameters¶
- ctx: Pointer to a NEAT context.
Return values¶
Returns a pointer to a new flow. Returns NULL
on error.
Remarks¶
None.
Examples¶
None.
See also¶
neat_set_property¶
Set the properties of a NEAT flow.
Syntax¶
neat_error_code neat_set_property(
struct neat_ctx *ctx,
struct neat_flow *flow,
const char *properties);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- properties: Pointer to a JSON-encoded string containing the flow properties.
Return values¶
- Returns
NEAT_OK
if the properties were set successfully. - Returns
NEAT_ERROR_BAD_ARGUMENT
if the JSON-encoded string is malformed.
Remarks¶
Properties are applied when a flow connects.
Examples¶
None.
See also¶
None.
neat_get_property¶
Query the properties of a flow. Returns value only, not precedence.
Syntax¶
neat_error_code neat_get_property(struct neat_ctx *ctx,
struct neat_flow *flow,
const char *name,
void *ptr,
size_t *size);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- name: Name of the property to query.
- ptr: Pointer to a buffer where the property value may be stored.
- size: Pointer to an integer containing the size of the buffer pointed to
by
ptr
. Updated to contain the size of the property upon return.
Return values¶
- Returns
NEAT_OK
if the property existed and there was sufficient buffer space available. Thesize
parameter is updated to contain the actual size. - Returns
NEAT_ERROR_MESSAGE_TOO_BIG
if there was not sufficient buffer space. Thesize
parameter is updated to contain the required buffer size. - Returns
NEAT_ERROR_UNABLE
if the property does not exist.
Remarks¶
Applications may pass 0
as the size
parameter to query the size of the
property.
Examples¶
size_t bufsize = 0;
char buffer = NULL;
if (neat_get_property(ctx, flow, "transport", buffer, &bufsize) == NEAT_ERROR_MESSAGE_TOO_BIG) {
buffer = malloc(bufsize);
if (buffer && neat_get_property(ctx, flow, "transport", buffer, &bufsize) == NEAT_OK) {
printf("Transport: %s\n", buffer);
}
if (buffer)
free(buffer);
} else {
printf("\tTransport: Error: Could not find property \"transport\"\n");
}
See also¶
neat_open¶
Open a neat flow and connect it to a given remote name and port.
Syntax¶
neat_error_code neat_open(struct neat_ctx *ctx,
struct neat_flow *flow,
const char *name,
uint16_t port,
struct neat_tlv optional[],
unsigned int opt_count);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- name: The remote name to connect to.
- port: The remote port to connect to.
- optional: An array containing optional parameters.
- opt_count: The length of the array containing optional parameters.
Optional parameters¶
- NEAT_TAG_STREAM_COUNT (integer): The number of streams to open, for protocols that supports multistreaming. Note that NEAT may automatically make use of multi-streaming for multiple NEAT flows between the same endpoints when this parameter is not used.
- NEAT_TAG_FLOW_GROUP (integer): The group ID that this flow belongs to. For use with coupled congestion control.
- NEAT_TAG_PRIORITY (float): The priority of this flow relative to the other flows. Must be between 0.1 and 1.0.
- NEAT_TAG_CC_ALGORITHM (string): The congestion control algorithm to use for this flow.
Return values¶
- Returns
NEAT_OK
if the flow opened successfully. - Returns
NEAT_ERROR_OUT_OF_MEMORY
if the function was unable to allocate enough memory.
Remarks¶
Callbacks can be specified with neat_set_operations
. The on_connected
callback will be invoked if the connection established successfully. The
on_error
callback will be invoked if NEAT is unable to connect to the remote
endpoint.
Examples¶
neat_open(ctx, flow, "bsd10.fh-muenster.de", 80, NULL, 0);
See also¶
neat_accept¶
Listen to incoming connections on a given port on one or more protocols.
Syntax¶
neat_error_code neat_accept(struct neat_ctx *ctx,
struct neat_flow *flow,
uint16_t port,
struct neat_tlv optional[],
unsigned int opt_count);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- port: The local port to listen for incoming connections on.
- optional: An array containing optional parameters.
- opt_count: The length of the array containing optional parameters.
Optional parameters¶
- NEAT_TAG_STREAM_COUNT (integer): The number of streams to accept, for protocols that supports multistreaming.
Return values¶
- Returns
NEAT_OK
if NEAT is listening for incoming connections on at least one protocol. - Returns
NEAT_ERROR_UNABLE
if there is no appropriate protocol available for the flow properties that was specified. - Returns
NEAT_ERROR_BAD_ARGUMENT
if flow is pointing to a flow that is already opened or listening for incoming connections. - Returns
NEAT_ERROR_BAD_ARGUMENT
if NEAT_TAG_STREAM_COUNT is less than 1. - Returns
NEAT_ERROR_OUT_OF_MEMORY
if the function was unable to allocate enough memory.
Remarks¶
Callbacks can be specified with neat_set_operations
. The on_connected
callback will be invoked if the connection established successfully. The
on_error
callback will be invoked if NEAT is unable to connect to the remote
endpoint.
Which protocols to listen to is determined by the flow properties.
Examples¶
neat_accept(ctx, flow, 8080, NULL, 0);
See also¶
neat_read¶
Read data from a neat flow.
Should only be called from within the on_readable
callback specified with neat_set_operations
.
neat_error_code neat_read(struct neat_ctx *ctx,
struct neat_flow *flow,
unsigned char *buffer,
uint32_t amount,
uint32_t *actual_amount,
struct neat_tlv optional[],
unsigned int opt_count);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- buffer: Pointer to a buffer where read data may be stored.
- amount: The size of the buffer pointed to by buffer.
- actual_amount: The amount of data actually read from the transport layer.
- optional: An array containing optional parameters.
- opt_count: The length of the array containing optional parameters.
Optional parameters¶
This function uses optional parameters for some return values.
- NEAT_TAG_STREAM_ID (integer): The ID of the stream will be written to this parameter.
Return values¶
- Returns
NEAT_OK
if data was successfully read from the transport layer. - Returns
NEAT_ERROR_WOULD_BLOCK
if this call would block. - Returns
NEAT_ERROR_MESSAGE_TOO_BIG
if the buffer is not sufficiently large. This is only returned for protocols that are message based, such as UDP, UDP-Lite and SCTP. - Returns
NEAT_ERROR_IO
if the connection is reset.
Remarks¶
This function should only be called from within the on_readable
callback specified with neat_set_operations
, as this is the only way to guarantee that the call will not block. NEAT does not permit a blocking read operation.
The actual_amount value is set to 0 when the remote side has closed the connection.
Examples¶
None.
See also¶
neat_write¶
Write data to a neat flow. Should only be called from within the on_writable
callback specified with neat_set_operations
.
neat_error_code neat_write(struct neat_ctx *ctx,
struct neat_flow *flow,
const unsigned char *buffer,
uint32_t amount,
struct neat_tlv optional[],
unsigned int opt_count);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- buffer: Pointer to a buffer containing the data to be written.
- amount: The size of the buffer pointed to by buffer.
- optional: An array containing optional parameters.
- opt_count: The length of the array containing optional parameters.
Optional parameters¶
- NEAT_TAG_STREAM_ID (integer): The ID of the stream the data will be written to.
Return values¶
- Returns
NEAT_OK
if data was successfully written to the transport layer. - Returns
NEAT_ERROR_BAD_ARGUMENT
if the specified stream ID is negative. - Returns
NEAT_ERROR_OUT_OF_MEMORY
if NEAT is unable to allocate memory. - Returns
NEAT_ERROR_WOULD_BLOCK
if this call would block. - Returns
NEAT_ERROR_IO
if an I/O operation failed.
Remarks¶
This function should only be called from within the on_writable
callback
specified with neat_set_operations
, as this is the only way to guarantee
that the call will not block. NEAT does not permit a blocking write operation.
Invalid stream IDs are silently ignored.
Examples¶
None.
See also¶
neat_shutdown¶
Initiate a graceful shutdown of this flow.
- the receive buffer can still be read and
on_readable
gets fired like in normal operation - receiving new data from the peer may fail
- all data in the send buffer will be transmitted
neat_write
will fail andon_writable
will not be called
If the peer also has closed the connection, the on_close
callback gets fired.
Syntax¶
neat_error_code neat_shutdown(struct neat_ctx *ctx,
struct neat_flow *flow);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to the NEAT flow to be shut down.
Return values¶
- Returns
NEAT_OK
if the flow was shut down successfully. - Returns
NEAT_ERROR_IO
if NEAT was unable to shut the flow down successfully.
Remarks¶
None.
Examples¶
None.
See also¶
neat_close¶
Close this flow and free all associated data. If the peer still has data to send, it cannot be received anymore after this call. Data buffered by the NEAT layer which has not given to the network layer yet will be discarded.
Syntax¶
neat_error_code neat_close(struct neat_ctx *ctx,
struct neat_flow *flow);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to the NEAT flow to be closed.
Return values¶
- Returns
NEAT_OK
.
Remarks¶
None.
Examples¶
None.
See also¶
neat_abort¶
Abort this flow and free all associated data.
Syntax¶
neat_error_code neat_abort(struct neat_ctx *ctx,
struct neat_flow *flow);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to the NEAT flow to be aborted.
Return values¶
- Returns
NEAT_OK
.
Remarks¶
Calls neat_close
internally.
Examples¶
None.
See also¶
neat_set_operations¶
Summary.
Syntax¶
neat_error_code neat_set_operations(
struct neat_ctx *ctx,
struct neat_flow *flow,
struct neat_flow_operations *ops);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- ops: Pointer to a struct that defines the operations/callbacks for this flow.
Return values¶
- Returns
NEAT_OK
.
Remarks¶
struct neat_flow_operations
is defined as follows:
struct neat_flow_operations
{
void *userData;
neat_error_code status;
int stream_id;
neat_flow_operations_fx on_connected;
neat_flow_operations_fx on_error;
neat_flow_operations_fx on_readable;
neat_flow_operations_fx on_writable;
neat_flow_operations_fx on_all_written;
neat_flow_operations_fx on_network_status_changed;
neat_flow_operations_fx on_aborted;
neat_flow_operations_fx on_timeout;
neat_flow_operations_fx on_close;
neat_cb_send_failure_t on_send_failure;
neat_cb_flow_slowdown_t on_slowdown;
neat_cb_flow_rate_hint_t on_rate_hint;
struct neat_ctx *ctx;
struct neat_flow *flow;
};
The information in the ops struct will be copied by NEAT.
Examples¶
struct neat_flow_operations ops;
ops.on_readable = on_readable;
ops.on_writable = on_writable;
neat_set_operations(ctx, flow, ops);
See also¶
None.
neat_change_timeout¶
Change the timeout of the flow. Data that is sent may remain un-acked for up to a given number of seconds before the connection is terminated and a timeout is reported to the application.
Syntax¶
neat_error_code
neat_change_timeout(struct neat_ctx *ctx, struct neat_flow *flow,
unsigned int seconds);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- seconds: The number of seconds after which un-acked data will cause a timeout to be reported.
Return values¶
- Returns
NEAT_OK
if the timeout was successfully changed. - Returns
NEAT_ERROR_UNABLE
if attempting to use this function on a system other than Linux, or on flow that is not using TCP. - Returns
NEAT_ERROR_BAD_ARGUMENT
if the timeout value is too large or if the specified flow is not opened. - Returns
NEAT_ERROR_IO
if NEAT was unable to set the timeout.
Remarks¶
Only available on Linux for flows using TCP.
Examples¶
None.
See also¶
None.
neat_set_primary_dest¶
For multihomed flows, set the primary destination address.
Syntax¶
neat_error_code neat_set_primary_dest(struct neat_ctx *ctx,
struct neat_flow *flow,
const char* address);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- address: The remote address to use as the primary destination address.
Return values¶
- Returns
NEAT_OK
if the primary destination address was set successfully. - Returns
NEAT_ERROR_UNABLE
if the flow is not using SCTP as the transport protocol. - Returns
NEAT_ERROR_BAD_ARGUMENT
if the provided address is not a literal IP address.
Remarks¶
Currently only available for SCTP.
Examples¶
None.
See also¶
None.
neat_secure_identity¶
Specify a certificate and key to use for secure connections.
Syntax¶
neat_error_code neat_secure_identity(
struct neat_ctx *ctx,
struct neat_flow *flow,
const char *filename);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- filename: Path to the PEM file containing the certificate and key.
Return values¶
- Returns
NEAT_OK
.
Remarks¶
None.
Examples¶
None.
See also¶
None.
neat_set_checksum_coverage¶
Set the checksum coverage for messages sent or received on this flow.
Syntax¶
neat_error_code neat_set_checksum_coverage(
struct neat_ctx *ctx,
struct neat_flow *flow,
unsigned int send_coverage,
unsigned int receive_coverage);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- send_coverage: UDP-Lite: The number of bytes covered by the checksum when sending messages. UDP: Ignored.
- receive_coverage: UDP-Lite: The lowest number of bytes that must be covered by the checksum on a received message. UDP: See below.
Return values¶
- Returns
NEAT_OK
if the checksum coverage was set successfully. - Returns
NEAT_ERROR_UNABLE
if the checksum coverage cannot be set, either because the value is invalid, or because the protocol does not support it.
Remarks¶
Only available for flows using UDP or UDP-Lite.
Checksum verification may be enabled disabled on the receive side for flows using UDP.
Specifying a non-zero value for receive_coverage will enable it; specifying 0
will disable it.
Examples¶
None.
See also¶
None.
neat_set_qos¶
Set the Quality-of-Service class for this flow.
Syntax¶
neat_error_code neat_set_qos(struct neat_ctx *ctx,
struct neat_flow *flow,
uint8_t qos);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- qos: The QoS class to use for this flow.
Return values¶
- Returns
NEAT_OK
if the QoS class was set successfully. - Returns
NEAT_ERROR_UNABLE
if NEAT was not able to set the requested QoS class.
Remarks¶
None.
Examples¶
None.
See also¶
None.
neat_get_qos¶
Get the Quality-of-Service class for this flow.
Syntax¶
neat_error_code neat_get_qos(struct neat_ctx *ctx,
struct neat_flow *flow)
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
Return values¶
- Returns the used DiffServ Code Point(DSCP) used signal QoS for this flow.
Remarks¶
None.
Examples¶
None.
See also¶
None.
neat_set_ecn¶
Set the Explicit Congestion Notification value for this flow.
Syntax¶
neat_error_code neat_set_ecn(struct neat_ctx *ctx,
struct neat_flow *flow,
uint8_t ecn);
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- ecn: The ECN value to use for this flow.
Return values¶
- Returns
NEAT_OK
if the QoS class was set successfully. - Returns
NEAT_ERROR_UNABLE
if NEAT was not able to set the requested ECN value.
Remarks¶
None.
Examples¶
None.
See also¶
None.
neat_start_event_loop¶
Starts the internal event loop within NEAT.
Syntax¶
neat_error_code neat_start_event_loop(struct neat_ctx *ctx, neat_run_mode run_mode);
Parameters¶
- ctx: Pointer to a NEAT context.
- run_mode: The mode of which the event loop in NEAT should execute.
May be one of either
NEAT_RUN_DEFAULT
,NEAT_RUN_ONCE
, orNEAT_RUN_NOWAIT
.
Return values¶
- Returns
NEAT_OK
if the NEAT executed with no error. - Returns an error value if the internal event loop in NEAT was stopped due to an error.
Remarks¶
This function does not return when executed with NEAT_RUN_DEFAULT
.
When executed with NEAT_RUN_ONCE
, NEAT will poll for I/O, and then
block unless there are pending callbacks within NEAT that are ready to be
processed. These callbacks may be internal.
When executed with NEAT_RUN_NOWAIT
, NEAT will poll for I/O and execute
any pending callbacks. If there are no pending callbacks, it returns after
polling.
Examples¶
None.
See also¶
neat_stop_event_loop¶
Stops the internal NEAT event loop.
Syntax¶
int neat_stop_event_loop(struct neat_ctx *ctx);
Parameters¶
- ctx: Pointer to a NEAT context.
Return values¶
None.
Remarks¶
Once called, no further events will be processed and no callbacks will be called
until neat_start_event_loop
is called again.
Examples¶
None.
See also¶
neat_get_backend_fd¶
Stops the internal NEAT event loop.
Syntax¶
int neat_get_backend_fd(struct neat_ctx *ctx);
Parameters¶
- ctx: Pointer to a NEAT context.
Return values¶
Returns the file descriptor of the event loop used internally by NEAT. May be polled to check for any new events.
Remarks¶
Note that embedding this event loop inside another event loop may not be supported on all systems.
Examples¶
None.
See also¶
neat_get_backend_timeout¶
Return the timeout that should be used when polling the backend file descriptor.
Syntax¶
int neat_get_backend_timeout(struct neat_ctx *ctx);
Parameters¶
- ctx: Pointer to a NEAT context.
Return values¶
Returns the number of milliseconds on which a poll operation may at most be blocked on the backend file descriptor from libuv before the NEAT event loop should be executed again to take care of timer events within NEAT.
Remarks¶
The client_http_run_once
example demonstrates the use of this function.
Examples¶
None.
See also¶
neat_get_event_loop¶
Return the internal NEAT event loop pointer.
Syntax¶
uv_loop_t neat_get_event_loop(struct neat_ctx *ctx);
Parameters¶
- ctx: Pointer to a NEAT context.
Return values¶
Returns the the event loop used internally by NEAT.
Examples¶
None.
See also¶
neat_get_stats¶
Return statistics from a NEAT context.
Syntax¶
neat_error_code neat_get_stats(
struct neat_ctx *ctx,
char **json_stats);
Parameters¶
- ctx: Pointer to a NEAT context.
- json_stats: Pointer to an address where address of the statistics may be written.
Return values¶
- Returns
NEAT_OK
.
Remarks¶
The statistics is output in JSON format. The caller is responsible for freeing the buffer containing the statistics.
Examples¶
None.
See also¶
None.
neat_getlpaddrs¶
Obtains the local or peer addresses of a flow.
Syntax¶
int neat_getlpaddrs(struct neat_ctx* ctx,
struct neat_flow* flow,
struct sockaddr** addrs,
const int local)
Parameters¶
- ctx: Pointer to a NEAT context.
- flow: Pointer to a NEAT flow.
- addrs: Pointer to variable for storing pointer to addresses to.
- local: Set to non-zero value for obtaining local addresses, set to 0 to obtain peer addresses.
Return values¶
On success, neat_getlpaddrs() returns the number of addresses (local or remote). In case of having obtained at least one address, a pointer to a newly allocated memory area with the addresses will be stored into addrs. This memory area needs to be freed after usage.
Examples¶
struct struct sockaddr* addrs;
int n = neat_getlpaddrs(ctx, flow, &addrs, 1);
if(n > 0) {
struct sockaddr* a = addrs;
for(int i = 0; i < n; i++) {
switch(a->sa_family) {
case AF_INET:
printf("Address %d/%d: IPv4\n", i, n);
a = (struct sockaddr*)((long)a + (long)sizeof(sockaddr_in));
break;
case AF_INET6:
printf("Address %d/%d: IPv6\n", i, n);
a = (struct sockaddr*)((long)a + (long)sizeof(sockaddr_in6));
default:
assert(false);
break;
}
}
free(addrs);
}
neat_log_level¶
Set the log-level of the NEAT library.
Syntax¶
void neat_log_level(struct neat_ctx *ctx,
uint8_t level)
Parameters¶
- ctx: Pointer to a NEAT context.
- level: Log level of the log entry
- NEAT_LOG_OFF
- NEAT_LOG_ERROR
- NEAT_LOG_WARNING
- NEAT_LOG_ERROR
- NEAT_LOG_DEBUG
Return values¶
None.
Examples¶
neat_log_level(ctx, NEAT_LOG_ERROR);
See also¶
neat_log_file¶
Sets the name of the log file.
Syntax¶
uint8_t neat_log_file(struct neat_ctx *ctx,
const char* file_name)
Parameters¶
- ctx: Pointer to a NEAT context.
- file_name: Name of the NEAT logfile. If set to
NULL
, NEAT writes the log output tostderr
.
Return values¶
- RETVAL_SUCCESS: success
- RETVAL_FAILURE: failure
Examples¶
neat_log_file(ctx, "disaster.log");
See also¶
Coding Style¶
The coding style used in NEAT is based on the coding style used in the Linux kernel. There are, however, some differences between the kernel style and the style used in the NEAT project. This document details these differences.
Strictness¶
This coding style serves as a guideline. Adherence is not strictly required, but (new) code should still try to follow these guidelines as far as possible to ensure that the code in the NEAT library has a coherent style.
Disambiguation¶
If some piece of code does not follow these guidelines, try to match the surrounding code. Do not mix style changes into commits with a different purpose.
Indentation¶
4 spaces.
Line length¶
There is no strict limit on the length of a line. As a general guideline, try to keep it below 120 characters.
Placement of braces¶
Generally the same as the Linux kernel style.
Braces may be used for blocks containing only one statement. Be consistent in adjacent blocks.
Yes:
if (this) {
do_that();
} else {
something();
}
No:
if (this) {
do_that();
} else
something();
Naming¶
Use names separated by underscores, e.g. this_is_my_variable
.
Descriptive names are preferred, but short, well-known abbreviations are acceptable.
Functions¶
The return type is placed on a separate line preceding the function name:
void
my_function(int parameter1, int parameter2)
{
}
Align parameters on subsequent lines with the first parameter:
void
my_other_function(int parameter1, int parameter2, ...
int parameterN, int parameterM)
{
}
Tools¶
The .editorconfig
file in the NEAT repository can be used by most editors
with the help of a plugin. See www.editorconfig.org.
The uncrustify-neat.cfg
file can be used by the Uncrustify tool to format
source code in accordance with this NEAT style guide. See the Uncrustify
documentation for more information.