Add proper API of SRT log data

This commit is contained in:
Ingo Oppermann
2022-07-01 15:31:07 +02:00
parent 1931782638
commit da039f4751
9 changed files with 936 additions and 38 deletions

View File

@@ -4,9 +4,9 @@
- Fix output address validation for tee outputs - Fix output address validation for tee outputs
- Fix updating process config - Fix updating process config
- Add experimental SRT connection stats and logs - Add experimental SRT connection stats and logs API
- Hide /config/reload endpoint in reade-only mode - Hide /config/reload endpoint in reade-only mode
- Add SRT server (datarhei/gosrt) - Add experimental SRT server (datarhei/gosrt)
- Create v16 in go.mod - Create v16 in go.mod
- Fix data races, tests, lint, and update dependencies - Fix data races, tests, lint, and update dependencies
- Add trailing slash for routed directories (datarhei/restreamer#340) - Add trailing slash for routed directories (datarhei/restreamer#340)

View File

@@ -1,5 +1,8 @@
# Core # Core
[![CodeQL](https://github.com/datarhei/core/workflows/CodeQL/badge.svg)](https://github.com/datarhei/core/actions?query=workflow%3ACodeQL)
![Docker Pulls](https://img.shields.io/docker/pulls/datarhei/core.svg?maxAge=604800&label=Docker%20Pulls)
The cloud-native audio/video processing API. The cloud-native audio/video processing API.
datarhei Core is management for FFmpeg processes without development effort. It is a central interface for mapping AV processes, is responsible for design and management, and provides all necessary interfaces to access the video content. The included control for FFmpeg can keep all used functions reliable and executable without the need for software developers to take care of it. In addition, process and resource limitation for all FFmpeg processes protects the host system from application overload. The overall system gives access to current process values (CPU, RAM) and complete control of system resources and loads with statistical access to process data and current and historical logs. datarhei Core is management for FFmpeg processes without development effort. It is a central interface for mapping AV processes, is responsible for design and management, and provides all necessary interfaces to access the video content. The included control for FFmpeg can keep all used functions reliable and executable without the need for software developers to take care of it. In addition, process and resource limitation for all FFmpeg processes protects the host system from application overload. The overall system gives access to current process values (CPU, RAM) and complete control of system resources and loads with statistical access to process data and current and historical logs.
@@ -44,8 +47,8 @@ docker run --name core -d
Native (linux/amd64,linux/arm64,linux/arm/v7) Native (linux/amd64,linux/arm64,linux/arm/v7)
- datarhei/base:alpine-core-latest - datarhei/base:core-alpine-latest
- datarhei/base:ubuntu-core-latest - datarhei/base:core-ubuntu-latest
Bundle with FFmpeg (linux/amd64,linux/arm64,linux/arm/v7) Bundle with FFmpeg (linux/amd64,linux/arm64,linux/arm/v7)
@@ -126,6 +129,10 @@ The currently known environment variables (but not all will be respected) are:
| CORE_RTMP_ADDRESS | `:1935` | RTMP server listen address. | | CORE_RTMP_ADDRESS | `:1935` | RTMP server listen address. |
| CORE_RTMP_APP | `/` | RTMP app for publishing. | | CORE_RTMP_APP | `/` | RTMP app for publishing. |
| CORE_RTMP_TOKEN | (not set) | RTMP token for publishing and playing. The token is the value of the URL query parameter `token`. | | CORE_RTMP_TOKEN | (not set) | RTMP token for publishing and playing. The token is the value of the URL query parameter `token`. |
| CORE_SRT_ENABLE | `false` | Enable SRT server. |
| CORE_SRT_ADDRESS | `:6000` | SRT server listen address. |
| CORE_SRT_PASSPHRASE | (not set) | SRT passphrase. |
| CORE_SRT_TOKEN | (not set) | SRT token for publishing and playing. The token is the value of the URL query parameter `token`. |
| CORE_FFMPEG_BINARY | `ffmpeg` | Path to FFmpeg binary. | | CORE_FFMPEG_BINARY | `ffmpeg` | Path to FFmpeg binary. |
| CORE_FFMPEG_MAXPROCESSES | `0` | Max. allowed simultaneously running FFmpeg instances. Any value <= 0 means unlimited. | | CORE_FFMPEG_MAXPROCESSES | `0` | Max. allowed simultaneously running FFmpeg instances. Any value <= 0 means unlimited. |
| CORE_FFMPEG_ACCESS_INPUT_ALLOW | (not set) | List of pattern for allowed input URI (space-separated), leave emtpy to allow any. | | CORE_FFMPEG_ACCESS_INPUT_ALLOW | (not set) | List of pattern for allowed input URI (space-separated), leave emtpy to allow any. |
@@ -251,6 +258,12 @@ All other values will be filled with default values and persisted on disk. The e
"app": "/", "app": "/",
"token": "" "token": ""
}, },
"srt": {
"enable": false,
"address": ":6000",
"passphrase": "",
"token": ""
},
"ffmpeg": { "ffmpeg": {
"binary": "ffmpeg", "binary": "ffmpeg",
"max_processes": 0, "max_processes": 0,
@@ -365,12 +378,32 @@ If you set a value for `CORE_STORAGE_DISK_CACHE_MAXSIZEMBYTES`, which is larger
## RTMP ## RTMP
The datarhei Core includes a simple RTMP server for publishing and playing streams. Set the environment variable `CORE_RTMP_ENABLE` to `true` to enable the RTMP server. It is listening on `CORE_RTMP_ADDRESS.` Use `CORE_RTMP_APP` to limit the app a stream can be published on, e.g. `/live` to require URLs to start with `/live`. To prevent anybody can publish streams, set `CORE_RTMP_TOKEN` to a secret only known to the publishers. The token has to be put in the query of the stream URL, e.g. `/live/stream?token=...`. The datarhei Core includes a simple RTMP server for publishing and playing streams. Set the environment variable `CORE_RTMP_ENABLE` to `true` to enable the RTMP server. It is listening on `CORE_RTMP_ADDRESS`. Use `CORE_RTMP_APP` to limit the app a stream can be published on, e.g. `/live` to require URLs to start with `/live`. To prevent anybody can publish streams, set `CORE_RTMP_TOKEN` to a secret only known to the publishers and subscribers. The token has to be put in the query of the stream URL, e.g. `/live/stream?token=...`.
| Method | Path | Description | | Method | Path | Description |
| ------ | ------------ | ------------------------------------- | | ------ | ------------ | ------------------------------------- |
| GET | /api/v3/rtmp | List all currently published streams. | | GET | /api/v3/rtmp | List all currently published streams. |
## SRT
The datarhei Core includes a simple SRT server for publishing and playing streams. Set the environment variable `CORE_SRT_ENABLE` to `true` to enable the SRT server. It is listening on `CORE_SRT_ADDRESS`.
The `streamid` is formatted according to Appendix B of the [SRT specs](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt#appendix-B). The following keys are supported:
| Key | Descriptions |
| ------- | ----------------------------------------------------------------------------------------------------------------- |
| `m` | The connection mode, either `publish` for publishing a stream or `request` for subscribing to a published stream. |
| `r` | Name of the resource. |
| `token` | A token to prevent anybody to publish or subscribe to a stream. This is set with `CORE_SRT_TOKEN`. |
An example publishing streamid: `#!:m=publish,r=12345,token=foobar`.
With your SRT client, connect to the SRT server always in `caller` mode.
| Method | Path | Description |
| ------ | ----------- | ------------------------------------- |
| GET | /api/v3/srt | List all currently published streams. |
## Playout ## Playout
FFmpeg processes with a `avstream:` (or `playout:`) input stream can expose an HTTP API to control the playout of that stream. With FFmpeg processes with a `avstream:` (or `playout:`) input stream can expose an HTTP API to control the playout of that stream. With

View File

@@ -701,7 +701,7 @@ func (a *api) start() error {
Token: cfg.SRT.Token, Token: cfg.SRT.Token,
Logger: a.log.logger.core.WithComponent("SRT").WithField("address", cfg.SRT.Address), Logger: a.log.logger.core.WithComponent("SRT").WithField("address", cfg.SRT.Address),
Collector: a.sessions.Collector("srt"), Collector: a.sessions.Collector("srt"),
SRTLogTopics: []string{"handshake", "connection"}, SRTLogTopics: []string{"listen", "handshake", "connection"},
} }
srtserver, err := srt.New(config) srtserver, err := srt.New(config)

View File

@@ -1918,7 +1918,7 @@ const docTemplate = `{
"ApiKeyAuth": [] "ApiKeyAuth": []
} }
], ],
"description": "List all currently publishing SRT streams", "description": "List all currently publishing SRT streams. This endpoint is EXPERIMENTAL and may change in future.",
"produces": [ "produces": [
"application/json" "application/json"
], ],
@@ -1930,7 +1930,7 @@ const docTemplate = `{
"schema": { "schema": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/api.SRTChannel" "$ref": "#/definitions/api.SRTChannels"
} }
} }
} }
@@ -3490,11 +3490,248 @@ const docTemplate = `{
} }
} }
}, },
"api.SRTChannel": { "api.SRTChannels": {
"type": "object", "type": "object",
"properties": { "properties": {
"name": { "connections": {
"type": "string" "type": "object",
"additionalProperties": {
"$ref": "#/definitions/api.SRTConnection"
}
},
"log": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"publisher": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"subscriber": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "integer"
}
}
}
}
},
"api.SRTConnection": {
"type": "object",
"properties": {
"log": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"stats": {
"$ref": "#/definitions/api.SRTStatistics"
}
}
},
"api.SRTStatistics": {
"type": "object",
"properties": {
"avail_recv_buf_bytes": {
"description": "The available space in the receiver's buffer, in bytes",
"type": "integer"
},
"avail_send_buf_bytes": {
"description": "The available space in the sender's buffer, in bytes",
"type": "integer"
},
"bandwidth_mbit": {
"description": "Estimated bandwidth of the network link, in Mbps",
"type": "number"
},
"flight_size_pkt": {
"description": "The number of packets in flight",
"type": "integer"
},
"flow_window_pkt": {
"description": "The maximum number of packets that can be \"in flight\"",
"type": "integer"
},
"max_bandwidth_mbit": {
"description": "Transmission bandwidth limit, in Mbps",
"type": "number"
},
"mss_bytes": {
"description": "Maximum Segment Size (MSS), in bytes",
"type": "integer"
},
"pkt_recv_avg_belated_time_ms": {
"description": "Accumulated difference between the current time and the time-to-play of a packet that is received late",
"type": "integer"
},
"pkt_send_period_us": {
"description": "Current minimum time interval between which consecutive packets are sent, in microseconds",
"type": "number"
},
"recv_ack_pkt": {
"description": "The total number of received ACK (Acknowledgement) control packets",
"type": "integer"
},
"recv_buf_bytes": {
"description": "Instantaneous (current) value of pktRcvBuf, expressed in bytes, including payload and all headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_buf_ms": {
"description": "The timespan (msec) of acknowledged packets in the receiver's buffer",
"type": "integer"
},
"recv_buf_pkt": {
"description": "The number of acknowledged packets in receiver's buffer",
"type": "integer"
},
"recv_bytes": {
"description": "Same as pktRecv, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_drop_bytes": {
"description": "Same as pktRcvDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_drop_pkt": {
"description": "The total number of dropped by the SRT receiver and, as a result, not delivered to the upstream application DATA packets",
"type": "integer"
},
"recv_km_pkt": {
"description": "The total number of received KM (Key Material) control packets",
"type": "integer"
},
"recv_loss__bytes": {
"description": "Same as pktRcvLoss, but expressed in bytes, including payload and all the headers (IP, TCP, SRT), bytes for the presently missing (either reordered or lost) packets' payloads are estimated based on the average packet size",
"type": "integer"
},
"recv_loss_pkt": {
"description": "The total number of SRT DATA packets detected as presently missing (either reordered or lost) at the receiver side",
"type": "integer"
},
"recv_nak_pkt": {
"description": "The total number of received NAK (Negative Acknowledgement) control packets",
"type": "integer"
},
"recv_pkt": {
"description": "The total number of received DATA packets, including retransmitted packets",
"type": "integer"
},
"recv_retran_pkts": {
"description": "The total number of retransmitted packets registered at the receiver side",
"type": "integer"
},
"recv_tsbpd_delay_ms": {
"description": "Timestamp-based Packet Delivery Delay value set on the socket via SRTO_RCVLATENCY or SRTO_LATENCY",
"type": "integer"
},
"recv_undecrypt_bytes": {
"description": "Same as pktRcvUndecrypt, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_undecrypt_pkt": {
"description": "The total number of packets that failed to be decrypted at the receiver side",
"type": "integer"
},
"recv_unique_bytes": {
"description": "Same as pktRecvUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_unique_pkt": {
"description": "The total number of unique original, retransmitted or recovered by the packet filter DATA packets received in time, decrypted without errors and, as a result, scheduled for delivery to the upstream application by the SRT receiver.",
"type": "integer"
},
"reorder_tolerance_pkt": {
"description": "Instant value of the packet reorder tolerance",
"type": "integer"
},
"rtt_ms": {
"description": "Smoothed round-trip time (SRTT), an exponentially-weighted moving average (EWMA) of an endpoint's RTT samples, in milliseconds",
"type": "number"
},
"send_buf_bytes": {
"description": "Instantaneous (current) value of pktSndBuf, but expressed in bytes, including payload and all headers (IP, TCP, SRT)",
"type": "integer"
},
"send_buf_ms": {
"description": "The timespan (msec) of packets in the sender's buffer (unacknowledged packets)",
"type": "integer"
},
"send_buf_pkt": {
"description": "The number of packets in the sender's buffer that are already scheduled for sending or even possibly sent, but not yet acknowledged",
"type": "integer"
},
"send_drop_bytes": {
"description": "Same as pktSndDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"send_drop_pkt": {
"description": "The total number of dropped by the SRT sender DATA packets that have no chance to be delivered in time",
"type": "integer"
},
"send_duration_us": {
"description": "The total accumulated time in microseconds, during which the SRT sender has some data to transmit, including packets that have been sent, but not yet acknowledged",
"type": "integer"
},
"send_km_pkt": {
"description": "The total number of sent KM (Key Material) control packets",
"type": "integer"
},
"send_loss_pkt": {
"description": "The total number of data packets considered or reported as lost at the sender side. Does not correspond to the packets detected as lost at the receiver side.",
"type": "integer"
},
"send_tsbpd_delay_ms": {
"description": "Timestamp-based Packet Delivery Delay value of the peer",
"type": "integer"
},
"sent_ack_pkt": {
"description": "The total number of sent ACK (Acknowledgement) control packets",
"type": "integer"
},
"sent_bytes": {
"description": "Same as pktSent, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"sent_nak_pkt": {
"description": "The total number of sent NAK (Negative Acknowledgement) control packets",
"type": "integer"
},
"sent_pkt": {
"description": "The total number of sent DATA packets, including retransmitted packets",
"type": "integer"
},
"sent_retrans_bytes": {
"description": "Same as pktRetrans, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"sent_retrans_pkt": {
"description": "The total number of retransmitted packets sent by the SRT sender",
"type": "integer"
},
"sent_unique__bytes": {
"description": "Same as pktSentUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"sent_unique_pkt": {
"description": "The total number of unique DATA packets sent by the SRT sender",
"type": "integer"
},
"timestamp_ms": {
"description": "The time elapsed, in milliseconds, since the SRT socket has been created",
"type": "integer"
} }
} }
}, },

View File

@@ -1910,7 +1910,7 @@
"ApiKeyAuth": [] "ApiKeyAuth": []
} }
], ],
"description": "List all currently publishing SRT streams", "description": "List all currently publishing SRT streams. This endpoint is EXPERIMENTAL and may change in future.",
"produces": [ "produces": [
"application/json" "application/json"
], ],
@@ -1922,7 +1922,7 @@
"schema": { "schema": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/api.SRTChannel" "$ref": "#/definitions/api.SRTChannels"
} }
} }
} }
@@ -3482,11 +3482,248 @@
} }
} }
}, },
"api.SRTChannel": { "api.SRTChannels": {
"type": "object", "type": "object",
"properties": { "properties": {
"name": { "connections": {
"type": "string" "type": "object",
"additionalProperties": {
"$ref": "#/definitions/api.SRTConnection"
}
},
"log": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"publisher": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"subscriber": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "integer"
}
}
}
}
},
"api.SRTConnection": {
"type": "object",
"properties": {
"log": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"stats": {
"$ref": "#/definitions/api.SRTStatistics"
}
}
},
"api.SRTStatistics": {
"type": "object",
"properties": {
"avail_recv_buf_bytes": {
"description": "The available space in the receiver's buffer, in bytes",
"type": "integer"
},
"avail_send_buf_bytes": {
"description": "The available space in the sender's buffer, in bytes",
"type": "integer"
},
"bandwidth_mbit": {
"description": "Estimated bandwidth of the network link, in Mbps",
"type": "number"
},
"flight_size_pkt": {
"description": "The number of packets in flight",
"type": "integer"
},
"flow_window_pkt": {
"description": "The maximum number of packets that can be \"in flight\"",
"type": "integer"
},
"max_bandwidth_mbit": {
"description": "Transmission bandwidth limit, in Mbps",
"type": "number"
},
"mss_bytes": {
"description": "Maximum Segment Size (MSS), in bytes",
"type": "integer"
},
"pkt_recv_avg_belated_time_ms": {
"description": "Accumulated difference between the current time and the time-to-play of a packet that is received late",
"type": "integer"
},
"pkt_send_period_us": {
"description": "Current minimum time interval between which consecutive packets are sent, in microseconds",
"type": "number"
},
"recv_ack_pkt": {
"description": "The total number of received ACK (Acknowledgement) control packets",
"type": "integer"
},
"recv_buf_bytes": {
"description": "Instantaneous (current) value of pktRcvBuf, expressed in bytes, including payload and all headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_buf_ms": {
"description": "The timespan (msec) of acknowledged packets in the receiver's buffer",
"type": "integer"
},
"recv_buf_pkt": {
"description": "The number of acknowledged packets in receiver's buffer",
"type": "integer"
},
"recv_bytes": {
"description": "Same as pktRecv, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_drop_bytes": {
"description": "Same as pktRcvDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_drop_pkt": {
"description": "The total number of dropped by the SRT receiver and, as a result, not delivered to the upstream application DATA packets",
"type": "integer"
},
"recv_km_pkt": {
"description": "The total number of received KM (Key Material) control packets",
"type": "integer"
},
"recv_loss__bytes": {
"description": "Same as pktRcvLoss, but expressed in bytes, including payload and all the headers (IP, TCP, SRT), bytes for the presently missing (either reordered or lost) packets' payloads are estimated based on the average packet size",
"type": "integer"
},
"recv_loss_pkt": {
"description": "The total number of SRT DATA packets detected as presently missing (either reordered or lost) at the receiver side",
"type": "integer"
},
"recv_nak_pkt": {
"description": "The total number of received NAK (Negative Acknowledgement) control packets",
"type": "integer"
},
"recv_pkt": {
"description": "The total number of received DATA packets, including retransmitted packets",
"type": "integer"
},
"recv_retran_pkts": {
"description": "The total number of retransmitted packets registered at the receiver side",
"type": "integer"
},
"recv_tsbpd_delay_ms": {
"description": "Timestamp-based Packet Delivery Delay value set on the socket via SRTO_RCVLATENCY or SRTO_LATENCY",
"type": "integer"
},
"recv_undecrypt_bytes": {
"description": "Same as pktRcvUndecrypt, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_undecrypt_pkt": {
"description": "The total number of packets that failed to be decrypted at the receiver side",
"type": "integer"
},
"recv_unique_bytes": {
"description": "Same as pktRecvUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"recv_unique_pkt": {
"description": "The total number of unique original, retransmitted or recovered by the packet filter DATA packets received in time, decrypted without errors and, as a result, scheduled for delivery to the upstream application by the SRT receiver.",
"type": "integer"
},
"reorder_tolerance_pkt": {
"description": "Instant value of the packet reorder tolerance",
"type": "integer"
},
"rtt_ms": {
"description": "Smoothed round-trip time (SRTT), an exponentially-weighted moving average (EWMA) of an endpoint's RTT samples, in milliseconds",
"type": "number"
},
"send_buf_bytes": {
"description": "Instantaneous (current) value of pktSndBuf, but expressed in bytes, including payload and all headers (IP, TCP, SRT)",
"type": "integer"
},
"send_buf_ms": {
"description": "The timespan (msec) of packets in the sender's buffer (unacknowledged packets)",
"type": "integer"
},
"send_buf_pkt": {
"description": "The number of packets in the sender's buffer that are already scheduled for sending or even possibly sent, but not yet acknowledged",
"type": "integer"
},
"send_drop_bytes": {
"description": "Same as pktSndDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"send_drop_pkt": {
"description": "The total number of dropped by the SRT sender DATA packets that have no chance to be delivered in time",
"type": "integer"
},
"send_duration_us": {
"description": "The total accumulated time in microseconds, during which the SRT sender has some data to transmit, including packets that have been sent, but not yet acknowledged",
"type": "integer"
},
"send_km_pkt": {
"description": "The total number of sent KM (Key Material) control packets",
"type": "integer"
},
"send_loss_pkt": {
"description": "The total number of data packets considered or reported as lost at the sender side. Does not correspond to the packets detected as lost at the receiver side.",
"type": "integer"
},
"send_tsbpd_delay_ms": {
"description": "Timestamp-based Packet Delivery Delay value of the peer",
"type": "integer"
},
"sent_ack_pkt": {
"description": "The total number of sent ACK (Acknowledgement) control packets",
"type": "integer"
},
"sent_bytes": {
"description": "Same as pktSent, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"sent_nak_pkt": {
"description": "The total number of sent NAK (Negative Acknowledgement) control packets",
"type": "integer"
},
"sent_pkt": {
"description": "The total number of sent DATA packets, including retransmitted packets",
"type": "integer"
},
"sent_retrans_bytes": {
"description": "Same as pktRetrans, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"sent_retrans_pkt": {
"description": "The total number of retransmitted packets sent by the SRT sender",
"type": "integer"
},
"sent_unique__bytes": {
"description": "Same as pktSentUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)",
"type": "integer"
},
"sent_unique_pkt": {
"description": "The total number of unique DATA packets sent by the SRT sender",
"type": "integer"
},
"timestamp_ms": {
"description": "The time elapsed, in milliseconds, since the SRT socket has been created",
"type": "integer"
} }
} }
}, },

View File

@@ -845,10 +845,220 @@ definitions:
name: name:
type: string type: string
type: object type: object
api.SRTChannel: api.SRTChannels:
properties: properties:
name: connections:
type: string additionalProperties:
$ref: '#/definitions/api.SRTConnection'
type: object
log:
additionalProperties:
items:
type: string
type: array
type: object
publisher:
additionalProperties:
type: integer
type: object
subscriber:
additionalProperties:
items:
type: integer
type: array
type: object
type: object
api.SRTConnection:
properties:
log:
additionalProperties:
items:
type: string
type: array
type: object
stats:
$ref: '#/definitions/api.SRTStatistics'
type: object
api.SRTStatistics:
properties:
avail_recv_buf_bytes:
description: The available space in the receiver's buffer, in bytes
type: integer
avail_send_buf_bytes:
description: The available space in the sender's buffer, in bytes
type: integer
bandwidth_mbit:
description: Estimated bandwidth of the network link, in Mbps
type: number
flight_size_pkt:
description: The number of packets in flight
type: integer
flow_window_pkt:
description: The maximum number of packets that can be "in flight"
type: integer
max_bandwidth_mbit:
description: Transmission bandwidth limit, in Mbps
type: number
mss_bytes:
description: Maximum Segment Size (MSS), in bytes
type: integer
pkt_recv_avg_belated_time_ms:
description: Accumulated difference between the current time and the time-to-play
of a packet that is received late
type: integer
pkt_send_period_us:
description: Current minimum time interval between which consecutive packets
are sent, in microseconds
type: number
recv_ack_pkt:
description: The total number of received ACK (Acknowledgement) control packets
type: integer
recv_buf_bytes:
description: Instantaneous (current) value of pktRcvBuf, expressed in bytes,
including payload and all headers (IP, TCP, SRT)
type: integer
recv_buf_ms:
description: The timespan (msec) of acknowledged packets in the receiver's
buffer
type: integer
recv_buf_pkt:
description: The number of acknowledged packets in receiver's buffer
type: integer
recv_bytes:
description: Same as pktRecv, but expressed in bytes, including payload and
all the headers (IP, TCP, SRT)
type: integer
recv_drop_bytes:
description: Same as pktRcvDrop, but expressed in bytes, including payload
and all the headers (IP, TCP, SRT)
type: integer
recv_drop_pkt:
description: The total number of dropped by the SRT receiver and, as a result,
not delivered to the upstream application DATA packets
type: integer
recv_km_pkt:
description: The total number of received KM (Key Material) control packets
type: integer
recv_loss__bytes:
description: Same as pktRcvLoss, but expressed in bytes, including payload
and all the headers (IP, TCP, SRT), bytes for the presently missing (either
reordered or lost) packets' payloads are estimated based on the average
packet size
type: integer
recv_loss_pkt:
description: The total number of SRT DATA packets detected as presently missing
(either reordered or lost) at the receiver side
type: integer
recv_nak_pkt:
description: The total number of received NAK (Negative Acknowledgement) control
packets
type: integer
recv_pkt:
description: The total number of received DATA packets, including retransmitted
packets
type: integer
recv_retran_pkts:
description: The total number of retransmitted packets registered at the receiver
side
type: integer
recv_tsbpd_delay_ms:
description: Timestamp-based Packet Delivery Delay value set on the socket
via SRTO_RCVLATENCY or SRTO_LATENCY
type: integer
recv_undecrypt_bytes:
description: Same as pktRcvUndecrypt, but expressed in bytes, including payload
and all the headers (IP, TCP, SRT)
type: integer
recv_undecrypt_pkt:
description: The total number of packets that failed to be decrypted at the
receiver side
type: integer
recv_unique_bytes:
description: Same as pktRecvUnique, but expressed in bytes, including payload
and all the headers (IP, TCP, SRT)
type: integer
recv_unique_pkt:
description: The total number of unique original, retransmitted or recovered
by the packet filter DATA packets received in time, decrypted without errors
and, as a result, scheduled for delivery to the upstream application by
the SRT receiver.
type: integer
reorder_tolerance_pkt:
description: Instant value of the packet reorder tolerance
type: integer
rtt_ms:
description: Smoothed round-trip time (SRTT), an exponentially-weighted moving
average (EWMA) of an endpoint's RTT samples, in milliseconds
type: number
send_buf_bytes:
description: Instantaneous (current) value of pktSndBuf, but expressed in
bytes, including payload and all headers (IP, TCP, SRT)
type: integer
send_buf_ms:
description: The timespan (msec) of packets in the sender's buffer (unacknowledged
packets)
type: integer
send_buf_pkt:
description: The number of packets in the sender's buffer that are already
scheduled for sending or even possibly sent, but not yet acknowledged
type: integer
send_drop_bytes:
description: Same as pktSndDrop, but expressed in bytes, including payload
and all the headers (IP, TCP, SRT)
type: integer
send_drop_pkt:
description: The total number of dropped by the SRT sender DATA packets that
have no chance to be delivered in time
type: integer
send_duration_us:
description: The total accumulated time in microseconds, during which the
SRT sender has some data to transmit, including packets that have been sent,
but not yet acknowledged
type: integer
send_km_pkt:
description: The total number of sent KM (Key Material) control packets
type: integer
send_loss_pkt:
description: The total number of data packets considered or reported as lost
at the sender side. Does not correspond to the packets detected as lost
at the receiver side.
type: integer
send_tsbpd_delay_ms:
description: Timestamp-based Packet Delivery Delay value of the peer
type: integer
sent_ack_pkt:
description: The total number of sent ACK (Acknowledgement) control packets
type: integer
sent_bytes:
description: Same as pktSent, but expressed in bytes, including payload and
all the headers (IP, TCP, SRT)
type: integer
sent_nak_pkt:
description: The total number of sent NAK (Negative Acknowledgement) control
packets
type: integer
sent_pkt:
description: The total number of sent DATA packets, including retransmitted
packets
type: integer
sent_retrans_bytes:
description: Same as pktRetrans, but expressed in bytes, including payload
and all the headers (IP, TCP, SRT)
type: integer
sent_retrans_pkt:
description: The total number of retransmitted packets sent by the SRT sender
type: integer
sent_unique__bytes:
description: Same as pktSentUnique, but expressed in bytes, including payload
and all the headers (IP, TCP, SRT)
type: integer
sent_unique_pkt:
description: The total number of unique DATA packets sent by the SRT sender
type: integer
timestamp_ms:
description: The time elapsed, in milliseconds, since the SRT socket has been
created
type: integer
type: object type: object
api.Session: api.Session:
properties: properties:
@@ -2715,7 +2925,8 @@ paths:
summary: Refresh FFmpeg capabilities summary: Refresh FFmpeg capabilities
/api/v3/srt: /api/v3/srt:
get: get:
description: List all currently publishing SRT streams description: List all currently publishing SRT streams. This endpoint is EXPERIMENTAL
and may change in future.
operationId: srt-3-list-channels operationId: srt-3-list-channels
produces: produces:
- application/json - application/json
@@ -2724,7 +2935,7 @@ paths:
description: OK description: OK
schema: schema:
items: items:
$ref: '#/definitions/api.SRTChannel' $ref: '#/definitions/api.SRTChannels'
type: array type: array
security: security:
- ApiKeyAuth: [] - ApiKeyAuth: []

View File

@@ -1,6 +1,164 @@
package api package api
// SRTChannel represents details about a currently connected SRT publisher import (
type SRTChannel struct { "github.com/datarhei/core/v16/srt"
Name string `json:"name" jsonschema:"minLength=1"`
gosrt "github.com/datarhei/gosrt"
)
// SRTStatistics represents the statistics of a SRT connection
type SRTStatistics struct {
MsTimeStamp uint64 `json:"timestamp_ms"` // The time elapsed, in milliseconds, since the SRT socket has been created
// Accumulated
PktSent uint64 `json:"sent_pkt"` // The total number of sent DATA packets, including retransmitted packets
PktRecv uint64 `json:"recv_pkt"` // The total number of received DATA packets, including retransmitted packets
PktSentUnique uint64 `json:"sent_unique_pkt"` // The total number of unique DATA packets sent by the SRT sender
PktRecvUnique uint64 `json:"recv_unique_pkt"` // The total number of unique original, retransmitted or recovered by the packet filter DATA packets received in time, decrypted without errors and, as a result, scheduled for delivery to the upstream application by the SRT receiver.
PktSndLoss uint64 `json:"send_loss_pkt"` // The total number of data packets considered or reported as lost at the sender side. Does not correspond to the packets detected as lost at the receiver side.
PktRcvLoss uint64 `json:"recv_loss_pkt"` // The total number of SRT DATA packets detected as presently missing (either reordered or lost) at the receiver side
PktRetrans uint64 `json:"sent_retrans_pkt"` // The total number of retransmitted packets sent by the SRT sender
PktRcvRetrans uint64 `json:"recv_retran_pkts"` // The total number of retransmitted packets registered at the receiver side
PktSentACK uint64 `json:"sent_ack_pkt"` // The total number of sent ACK (Acknowledgement) control packets
PktRecvACK uint64 `json:"recv_ack_pkt"` // The total number of received ACK (Acknowledgement) control packets
PktSentNAK uint64 `json:"sent_nak_pkt"` // The total number of sent NAK (Negative Acknowledgement) control packets
PktRecvNAK uint64 `json:"recv_nak_pkt"` // The total number of received NAK (Negative Acknowledgement) control packets
PktSentKM uint64 `json:"send_km_pkt"` // The total number of sent KM (Key Material) control packets
PktRecvKM uint64 `json:"recv_km_pkt"` // The total number of received KM (Key Material) control packets
UsSndDuration uint64 `json:"send_duration_us"` // The total accumulated time in microseconds, during which the SRT sender has some data to transmit, including packets that have been sent, but not yet acknowledged
PktSndDrop uint64 `json:"send_drop_pkt"` // The total number of dropped by the SRT sender DATA packets that have no chance to be delivered in time
PktRcvDrop uint64 `json:"recv_drop_pkt"` // The total number of dropped by the SRT receiver and, as a result, not delivered to the upstream application DATA packets
PktRcvUndecrypt uint64 `json:"recv_undecrypt_pkt"` // The total number of packets that failed to be decrypted at the receiver side
ByteSent uint64 `json:"sent_bytes"` // Same as pktSent, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
ByteRecv uint64 `json:"recv_bytes"` // Same as pktRecv, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
ByteSentUnique uint64 `json:"sent_unique__bytes"` // Same as pktSentUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
ByteRecvUnique uint64 `json:"recv_unique_bytes"` // Same as pktRecvUnique, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
ByteRcvLoss uint64 `json:"recv_loss__bytes"` // Same as pktRcvLoss, but expressed in bytes, including payload and all the headers (IP, TCP, SRT), bytes for the presently missing (either reordered or lost) packets' payloads are estimated based on the average packet size
ByteRetrans uint64 `json:"sent_retrans_bytes"` // Same as pktRetrans, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
ByteSndDrop uint64 `json:"send_drop_bytes"` // Same as pktSndDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
ByteRcvDrop uint64 `json:"recv_drop_bytes"` // Same as pktRcvDrop, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
ByteRcvUndecrypt uint64 `json:"recv_undecrypt_bytes"` // Same as pktRcvUndecrypt, but expressed in bytes, including payload and all the headers (IP, TCP, SRT)
// Instantaneous
UsPktSndPeriod float64 `json:"pkt_send_period_us"` // Current minimum time interval between which consecutive packets are sent, in microseconds
PktFlowWindow uint64 `json:"flow_window_pkt"` // The maximum number of packets that can be "in flight"
PktFlightSize uint64 `json:"flight_size_pkt"` // The number of packets in flight
MsRTT float64 `json:"rtt_ms"` // Smoothed round-trip time (SRTT), an exponentially-weighted moving average (EWMA) of an endpoint's RTT samples, in milliseconds
MbpsBandwidth float64 `json:"bandwidth_mbit"` // Estimated bandwidth of the network link, in Mbps
ByteAvailSndBuf uint64 `json:"avail_send_buf_bytes"` // The available space in the sender's buffer, in bytes
ByteAvailRcvBuf uint64 `json:"avail_recv_buf_bytes"` // The available space in the receiver's buffer, in bytes
MbpsMaxBW float64 `json:"max_bandwidth_mbit"` // Transmission bandwidth limit, in Mbps
ByteMSS uint64 `json:"mss_bytes"` // Maximum Segment Size (MSS), in bytes
PktSndBuf uint64 `json:"send_buf_pkt"` // The number of packets in the sender's buffer that are already scheduled for sending or even possibly sent, but not yet acknowledged
ByteSndBuf uint64 `json:"send_buf_bytes"` // Instantaneous (current) value of pktSndBuf, but expressed in bytes, including payload and all headers (IP, TCP, SRT)
MsSndBuf uint64 `json:"send_buf_ms"` // The timespan (msec) of packets in the sender's buffer (unacknowledged packets)
MsSndTsbPdDelay uint64 `json:"send_tsbpd_delay_ms"` // Timestamp-based Packet Delivery Delay value of the peer
PktRcvBuf uint64 `json:"recv_buf_pkt"` // The number of acknowledged packets in receiver's buffer
ByteRcvBuf uint64 `json:"recv_buf_bytes"` // Instantaneous (current) value of pktRcvBuf, expressed in bytes, including payload and all headers (IP, TCP, SRT)
MsRcvBuf uint64 `json:"recv_buf_ms"` // The timespan (msec) of acknowledged packets in the receiver's buffer
MsRcvTsbPdDelay uint64 `json:"recv_tsbpd_delay_ms"` // Timestamp-based Packet Delivery Delay value set on the socket via SRTO_RCVLATENCY or SRTO_LATENCY
PktReorderTolerance uint64 `json:"reorder_tolerance_pkt"` // Instant value of the packet reorder tolerance
PktRcvAvgBelatedTime uint64 `json:"pkt_recv_avg_belated_time_ms"` // Accumulated difference between the current time and the time-to-play of a packet that is received late
}
// Unmarshal converts the SRT statistics into API representation
func (s *SRTStatistics) Unmarshal(ss *gosrt.Statistics) {
s.MsTimeStamp = ss.MsTimeStamp
s.PktSent = ss.PktSent
s.PktRecv = ss.PktRecv
s.PktSentUnique = ss.PktSentUnique
s.PktRecvUnique = ss.PktRecvUnique
s.PktSndLoss = ss.PktSndLoss
s.PktRcvLoss = ss.PktRcvLoss
s.PktRetrans = ss.PktRetrans
s.PktRcvRetrans = ss.PktRcvRetrans
s.PktSentACK = ss.PktSentACK
s.PktRecvACK = ss.PktRecvACK
s.PktSentNAK = ss.PktSentNAK
s.PktRecvNAK = ss.PktRecvNAK
s.PktSentKM = ss.PktSentKM
s.PktRecvKM = ss.PktRecvKM
s.UsSndDuration = ss.UsSndDuration
s.PktSndDrop = ss.PktSndDrop
s.PktRcvDrop = ss.PktRcvDrop
s.PktRcvUndecrypt = ss.PktRcvUndecrypt
s.ByteSent = ss.ByteSent
s.ByteRecv = ss.ByteRecv
s.ByteSentUnique = ss.ByteSentUnique
s.ByteRecvUnique = ss.ByteRecvUnique
s.ByteRcvLoss = ss.ByteRcvLoss
s.ByteRetrans = ss.ByteRetrans
s.ByteSndDrop = ss.ByteSndDrop
s.ByteRcvDrop = ss.ByteRcvDrop
s.ByteRcvUndecrypt = ss.ByteRcvUndecrypt
}
type SRTLog struct {
Timestamp int64 `json:"ts"`
Message []string `json:"msg"`
}
// SRTConnection represents a SRT connection with statistics and logs
type SRTConnection struct {
Log map[string][]SRTLog `json:"log"`
Stats SRTStatistics `json:"stats"`
}
// Unmarshal converts the SRT connection into API representation
func (s *SRTConnection) Unmarshal(ss *srt.Connection) {
s.Log = make(map[string][]SRTLog)
s.Stats.Unmarshal(&ss.Stats)
for k, v := range ss.Log {
s.Log[k] = make([]SRTLog, len(v))
for i, l := range v {
s.Log[k][i].Timestamp = l.Timestamp.UnixMilli()
s.Log[k][i].Message = l.Message
}
}
}
// SRTChannels represents all current SRT connections
type SRTChannels struct {
Publisher map[string]uint32 `json:"publisher"`
Subscriber map[string][]uint32 `json:"subscriber"`
Connections map[uint32]SRTConnection `json:"connections"`
Log map[string][]SRTLog `json:"log"`
}
// Unmarshal converts the SRT channels into API representation
func (s *SRTChannels) Unmarshal(ss *srt.Channels) {
s.Publisher = make(map[string]uint32)
s.Subscriber = make(map[string][]uint32)
s.Connections = make(map[uint32]SRTConnection)
s.Log = make(map[string][]SRTLog)
for k, v := range ss.Publisher {
s.Publisher[k] = v
}
for k, v := range ss.Subscriber {
vv := make([]uint32, len(v))
copy(vv, v)
s.Subscriber[k] = vv
}
for k, v := range ss.Connections {
c := s.Connections[k]
c.Unmarshal(&v)
s.Connections[k] = c
}
for k, v := range ss.Log {
s.Log[k] = make([]SRTLog, len(v))
for i, l := range v {
s.Log[k][i].Timestamp = l.Timestamp.UnixMilli()
s.Log[k][i].Message = l.Message
}
}
} }

View File

@@ -3,6 +3,7 @@ package api
import ( import (
"net/http" "net/http"
"github.com/datarhei/core/v16/http/api"
"github.com/datarhei/core/v16/srt" "github.com/datarhei/core/v16/srt"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
@@ -13,7 +14,7 @@ type SRTHandler struct {
srt srt.Server srt srt.Server
} }
// NewRTMP returns a new SRT type. You have to provide a SRT server instance. // NewSRT returns a new SRT type. You have to provide a SRT server instance.
func NewSRT(srt srt.Server) *SRTHandler { func NewSRT(srt srt.Server) *SRTHandler {
return &SRTHandler{ return &SRTHandler{
srt: srt, srt: srt,
@@ -22,14 +23,17 @@ func NewSRT(srt srt.Server) *SRTHandler {
// ListChannels lists all currently publishing SRT streams // ListChannels lists all currently publishing SRT streams
// @Summary List all publishing SRT treams // @Summary List all publishing SRT treams
// @Description List all currently publishing SRT streams // @Description List all currently publishing SRT streams. This endpoint is EXPERIMENTAL and may change in future.
// @ID srt-3-list-channels // @ID srt-3-list-channels
// @Produce json // @Produce json
// @Success 200 {array} api.SRTChannel // @Success 200 {array} api.SRTChannels
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /api/v3/srt [get] // @Router /api/v3/srt [get]
func (srth *SRTHandler) ListChannels(c echo.Context) error { func (srth *SRTHandler) ListChannels(c echo.Context) error {
channels := srth.srt.Channels() channels := srth.srt.Channels()
return c.JSON(http.StatusOK, channels) srtchannels := api.SRTChannels{}
srtchannels.Unmarshal(&channels)
return c.JSON(http.StatusOK, srtchannels)
} }

View File

@@ -254,8 +254,13 @@ func (s *server) Close() {
s.srtloggerCancel() s.srtloggerCancel()
} }
type Log struct {
Timestamp time.Time
Message []string
}
type Connection struct { type Connection struct {
Log map[string][]string Log map[string][]Log
Stats srt.Statistics Stats srt.Statistics
} }
@@ -263,7 +268,7 @@ type Channels struct {
Publisher map[string]uint32 Publisher map[string]uint32
Subscriber map[string][]uint32 Subscriber map[string][]uint32
Connections map[uint32]Connection Connections map[uint32]Connection
Log map[string][]string Log map[string][]Log
} }
func (s *server) Channels() Channels { func (s *server) Channels() Channels {
@@ -271,7 +276,7 @@ func (s *server) Channels() Channels {
Publisher: map[string]uint32{}, Publisher: map[string]uint32{},
Subscriber: map[string][]uint32{}, Subscriber: map[string][]uint32{},
Connections: map[uint32]Connection{}, Connections: map[uint32]Connection{},
Log: map[string][]string{}, Log: map[string][]Log{},
} }
s.lock.RLock() s.lock.RLock()
@@ -281,7 +286,7 @@ func (s *server) Channels() Channels {
st.Connections[socketId] = Connection{ st.Connections[socketId] = Connection{
Stats: ch.publisher.conn.Stats(), Stats: ch.publisher.conn.Stats(),
Log: map[string][]string{}, Log: map[string][]Log{},
} }
for _, c := range ch.subscriber { for _, c := range ch.subscriber {
@@ -290,7 +295,7 @@ func (s *server) Channels() Channels {
st.Connections[socketId] = Connection{ st.Connections[socketId] = Connection{
Stats: c.conn.Stats(), Stats: c.conn.Stats(),
Log: map[string][]string{}, Log: map[string][]Log{},
} }
} }
} }
@@ -306,14 +311,17 @@ func (s *server) Channels() Channels {
ll := l.(srt.Log) ll := l.(srt.Log)
message := fmt.Sprintf("%s [%d] %s", ll.Time.Format("2006-01-02 15:04:05"), ll.SocketId, ll.Message) log := Log{
Timestamp: ll.Time,
st.Log[topic] = append(st.Log[topic], message) Message: strings.Split(ll.Message, "\n"),
}
if ll.SocketId != 0 { if ll.SocketId != 0 {
if _, ok := st.Connections[ll.SocketId]; ok { if _, ok := st.Connections[ll.SocketId]; ok {
st.Connections[ll.SocketId].Log[topic] = append(st.Connections[ll.SocketId].Log[topic], message) st.Connections[ll.SocketId].Log[topic] = append(st.Connections[ll.SocketId].Log[topic], log)
} }
} else {
st.Log[topic] = append(st.Log[topic], log)
} }
}) })
} }
@@ -420,11 +428,21 @@ func (s *server) handleConnect(req srt.ConnRequest) srt.ConnType {
return srt.REJECT return srt.REJECT
} }
if req.IsEncrypted() { if len(s.passphrase) != 0 {
if !req.IsEncrypted() {
s.log("CONNECT", "FORBIDDEN", si.resource, "connection has to be encrypted", client)
return srt.REJECT
}
if err := req.SetPassphrase(s.passphrase); err != nil { if err := req.SetPassphrase(s.passphrase); err != nil {
s.log("CONNECT", "FORBIDDEN", si.resource, err.Error(), client) s.log("CONNECT", "FORBIDDEN", si.resource, err.Error(), client)
return srt.REJECT return srt.REJECT
} }
} else {
if req.IsEncrypted() {
s.log("CONNECT", "INVALID", si.resource, "connection must not be encrypted", client)
return srt.REJECT
}
} }
// Check the token // Check the token