Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{EPOLL} Updated documentation after adding new API #873

Merged
merged 9 commits into from
Sep 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 145 additions & 12 deletions docs/API-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ SRT API Functions
* [srt_epoll_add_usock, srt_epoll_add_ssock, srt_epoll_update_usock, srt_epoll_update_ssock](#srt_epoll_add_usock-srt_epoll_add_ssock-srt_epoll_update_usock-srt_epoll_update_ssock)
* [srt_epoll_remove_usock, srt_epoll_remove_ssock](#srt_epoll_remove_usock-srt_epoll_remove_ssock)
* [srt_epoll_wait](#srt_epoll_wait)
* [srt_epoll_uwait](#srt_epoll_uwait)
* [srt_epoll_set](#srt_epoll_set)
* [srt_epoll_release](#srt_epoll_release)
- [**Logging control**](#Logging-control)
* [srt_setloglevel](#srt_setloglevel)
Expand Down Expand Up @@ -1194,16 +1196,44 @@ these two calls.
* `eid`: epoll container id
* `u`: SRT socket
* `s`: system socket
* `events`: points to a variable set to epoll flags, or NULL if
you want to subscribe a socket for all possible events
* `events`: points to
* a variable set to epoll flags (see below) to use only selected events
* NULL if you want to subscribe a socket for all events in level-triggered mode

Possible epoll flags are the following:

* `SRT_EPOLL_IN`: report readiness for reading or incoming connection on a listener socket
* `SRT_EPOLL_OUT`: report readiness for writing or a successful connection
* `SRT_EPOLL_ERR`: report errors on the socket
* `SRT_EPOLL_ET`: the event will be edge-triggered

The readiness states reported in by default are **level-triggered**.
If `SRT_EPOLL_ET` flag is specified, the reported states are
**edge-triggered**. Note that at this time the edge-triggered mode
is supported only for SRT sockets, not for system sockets.

In the **edge-triggered** mode the function will only return socket states that
have changed since the last call. All events reported in particular call of
the waiting function will be cleared in the internal flags and will not be
reported until the internal signaling logic clears this state and raises it
again.

In the **level-triggered** mode the function will always return the readiness
state as long as it lasts, until the internal signaling logic clear it.

Note that when you use `SRT_EPOLL_ET` flag in one subscription call, it defines
edge-triggered mode for all events passed together with it. However, if you
want to have some events reported as edge-triggered and others as
level-triggered, you can do two separate subscriptions for the same socket.


- Returns:

* 0 if successful, otherwise -1

- Errors:

* `SRT_EINVPOLLID`: `eid` designates no valid EID object
* `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container

**BUG?**: for `add_ssock` the system error results in an empty `CUDTException()`
call which actually results in `SRT_SUCCESS`. For cases like that the
Expand All @@ -1228,7 +1258,7 @@ The `_ssock` suffix refers to a system socket.

- Errors:

* `SRT_EINVPOLLID`: `eid` designates no valid EID object
* `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container

### srt_epoll_wait
```
Expand All @@ -1237,14 +1267,16 @@ int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds,
```

Blocks the call until any readiness state occurs in the epoll container.
Mind that the readiness states reported in epoll are **permanent, not
edge-triggered**.

Readiness can be on a socket in the container for the event type as per
subscription. The first readiness state causes this function to exit, but
all ready sockets are reported. This function blocks until the timeout.
If timeout is 0, it exits immediately after checking. If timeout is -1,
it blocks indefinitely until a readiness state occurs.
subscription. Note that in case when particular event was subscribed with
`SRT_EPOLL_ET` flag, this event, when once reported in this function, will
be cleared internally.

The first readiness state causes this function to exit, but all ready sockets
are reported. This function blocks until the timeout specified in `msTimeOut`
parameter. If timeout is 0, it exits immediately after checking. If timeout is
-1, it blocks indefinitely until a readiness state occurs.

* `eid`: epoll container
* `readfds` and `rnum`: A pointer and length of an array to write SRT sockets that are read-ready
Expand Down Expand Up @@ -1273,11 +1305,112 @@ of error has occurred on the socket.

- Errors:

* `SRT_EINVPOLLID`: `eid` designates no valid EID object
* `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container
* `SRT_ETIMEOUT`: Up to `msTimeOut` no sockets subscribed in `eid` were ready.
This is reported only if `msTimeOut` was \>=0, otherwise the function waits
indefinitely.

### srt_epoll_uwait
```
int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut);
```

This function blocks a call until any readiness state occurs in the epoll
container. Unlike `srt_epoll_wait`, it can only be used with `eid` subscribed
to user sockets (SRT sockets), not system sockets.

This function blocks until the timeout specified in `msTimeOut` parameter. If
timeout is 0, it exits immediately after checking. If timeout is -1, it blocks
indefinitely until a readiness state occurs.

* `eid`: epoll container
* `fdsSet` : A pointer to an array of `SRT_EPOLL_EVENT`
* `fdsSize` : The size of the fdsSet array
* `msTimeOut` : Timeout specified in milliseconds, or special values (0 or -1):
* 0: Don't wait, return immediately (report any sockets currently ready)
* -1: Wait indefinitely.

- Returns:

* The number of user socket (SRT socket) state changes that have been reported
in `fdsSet`, if this number isn't greater than `fdsSize`

* Otherwise the return value is `fdsSize` + 1. This means that there was not
enough space in the output array to report all events. For events subscribed with
`SRT_EPOLL_ET` flag only those will be cleared that were reported. Others will
wait for the next call.

* If no readiness state was found on any socket and the timeout has passed, 0
is returned (this is not possible when waiting indefinitely)

* -1 in case of error


- Errors:

* `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container
* `SRT_EINVPARAM`: One of possible usage errors:
* `fdsSize` is < 0
* `fdsSize` is > 0 and `fdsSet` is a null pointer
* `eid` was subscribed to any system socket

(IMPORTANT: this function reports timeout by returning 0, not by `SRT_ETIMEOUT` error.)

The `SRT_EPOLL_EVENT` structure:

```
typedef struct SRT_EPOLL_EVENT_
{
SRTSOCKET fd;
int events;
} SRT_EPOLL_EVENT;
```

* `fd` : the user socket (SRT socket)
* `events` : event flags that report readiness of this socket - a combination
of `SRT_EPOLL_IN`, `SRT_EPOLL_OUT` and `SRT_EPOLL_ERR` - see [srt_epoll_add_usock](#srt_epoll_add_usock)
for details

Note that when the `SRT_EPOLL_ERR` is set, the underlying socket error
can't be retrieved with `srt_getlasterror()`. The socket will be automatically
closed and its state can be verified with a call to `srt_getsockstate`.

### srt_epoll_set
```
int32_t srt_epoll_set(int eid, int32_t flags);
```

This function allows to set or retrieve flags that change the default
behavior of the epoll functions. All default values for these flags are 0.
The following flags are available:

* `SRT_EPOLL_ENABLE_EMPTY`: allows the `srt_epoll_wait` and `srt_epoll_uwait`
functions to be called with the EID not subscribed to any socket. The default
behavior of these function is to report error in this case.

* `SRT_EPOLL_ENABLE_OUTPUTCHECK`: Forces the `srt_epoll_wait` and `srt_epoll_uwait`
functions to check if the output array is not empty. For `srt_epoll_wait` it
is still allowed that either system or user array is empty, as long as EID
isn't subscribed to this type of socket/fd. `srt_epoll_uwait` only checks if
the general output array is not empty.

- Parameters:

* `eid`: the epoll container id
* `flags`: a nonzero set of the above flags, or special values:
* 0: clear all flags (set all defaults)
* -1: do not modify any flags

- Returns:

This function returns the state of the flags at the time before the call,
or a special value -1 in case when an error occurred.

- Errors:

* `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container


### srt_epoll_release
```
int srt_epoll_release(int eid);
Expand All @@ -1293,7 +1426,7 @@ Deletes the epoll container.
- Errors:


* `SRT_EINVPOLLID`: `eid` designates no valid EID object
* `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container

Logging control
---------------
Expand Down
85 changes: 78 additions & 7 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,11 @@ Synopsis

int srt_epoll_update_usock(int eid, SRTSOCKET u, const int* events = NULL);
int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL);

int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum,
int64_t msTimeOut,
SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum);
int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut);


SRT Usage
---------
Expand All @@ -340,14 +344,81 @@ user-level epoll that supports both SRT and system sockets.
The `srt_epoll_update_{u|s}sock()` API functions described here are SRT additions
to the UDT-derived `srt_epoll_add_{u|s}sock()` and `epoll_remove_{u|s}sock()`
functions to atomically change the events of interest. For example, to remove
EPOLLOUT but keep EPOLLIN for a given socket with the existing API, the socket
must be removed from epoll and re-added. This cannot be done atomically, the
thread protection (against the epoll thread) being applied within each function
but unprotected between the two calls. It is then possible to lose a POLLIN
event if it fires while the socket is not in the epoll list.
`SRT_EPOLL_OUT` but keep `SRT_EPOLL_IN` for a given socket with the existing
API, the socket must be removed from epoll and re-added. This cannot be done
atomically, the thread protection (against the epoll thread) being applied
within each function but unprotected between the two calls. It is then possible
to lose an `SRT_EPOLL_IN` event if it fires while the socket is not in the
epoll list.

Once the subscriptions are made, you can call an SRT polling function
(`srt_epoll_wait` or `srt_epoll_uwait`) that will block until an event
is raised on any of the subscribed sockets. This function will exit as
soon as st least one event is deteted or a timeout occurs. The timeout is
specified in `[ms]`, with two special values:

- 0: check and report immediately (don't wait)
- -1: wait indefinitely (not interruptable, even by a system signal)

There are some differences in the synopsis between these two:

1. `srt_epoll_wait`: Both system and SRT sockets can be subscribed. This
function reports events on both socket types according to subscriptions, in
these arrays:

- `readfds` and `lrfds`: subscribed for `IN` and `ERR`
- `writefds` and `lwfds`: subscribed for `OUT` and `ERR`

where:

- `readfds` and `writefds` report SRT sockets ("user" socket)
- `lrfds` and `lwfds` report system sockets

Note: this function provides no straightforward possibility to report
sockets with an error. If you want to distinguish a report of readiness
for operation from an error report, the only way is to subscribe the
socket in only one direction (either `SRT_EPOLL_IN` or `SRT_EPOLL_OUT`,
but not both) and `SRT_EPOLL_ERR`, and then check the socket's presence
in the array for which's direction the socket wasn't subscribed (for
example, when an SRT socket is subscribed for `SRT_EPOLL_OUT | SRT_EPOLL_ERR`,
its presence in `readfds` means that an error is reported for it).
This need not be a big problem because when an error is reported on
a socket, an appearance as if it were ready for an operation, followed
by doing this operation, will simply result in an error from that
operation, so you can use it also as an alternative error check method.

This function also reports error of type `SRT_ETIMEOUT` when no socket is
ready as the timeout elapses (including 0). This behavior is different in
`srt_epoll_uwait`.

Note that in this function there's a loop that checks for socket readiness
every 10ms. Thus, the minimum poll timeout the function can reliably support,
when system sockets are involved, is also 10ms. The return time from a poll
function can only be quicker when there is an event raised on one of the active
SRT sockets.


2. `srt_epoll_uwait`: In this function only the SRT sockets can be subscribed
(it reports error if you pass an epoll id that is subscribed to system sockets).
This function waits for the first event on subscribed SRT socket and reports all
events collected at this moment in an array of this structure:

```
typedef struct SRT_EPOLL_EVENT_
{
SRTSOCKET fd;
int events;
} SRT_EPOLL_EVENT;

```

Every item reports a single socket with all events as flags.

When the timeout is not -1, and no sockets are ready until the timeout time
passes, this function returns 0. This behavior is different in `srt_epoll_wait`.

The SRT EPoll system does not supports all features of Linux epoll. For
example, it only supports level-triggered events.
example, it only supports level-triggered events for system sockets.

Options
=======
Expand Down