mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
dtsl: add some documentation
https://bugzilla.gnome.org/show_bug.cgi?id=760994
This commit is contained in:
parent
44ec245b48
commit
79f9c7671b
1 changed files with 153 additions and 0 deletions
153
ext/dtls/README
Normal file
153
ext/dtls/README
Normal file
|
@ -0,0 +1,153 @@
|
|||
INTRODUCTION
|
||||
============
|
||||
This document is an attempt to describe the basics of the DTLS element.
|
||||
It hasn't been written by the author(s) and so, besides being incomplete,
|
||||
*IT MIGHT ALSO BE INCORRECT*. So take it with a pinch of salt.
|
||||
|
||||
As always, if in doubt ask the #gstreamer IRC channel.
|
||||
|
||||
THE INTERNALS
|
||||
=============
|
||||
This plugin provides two main elements (dtlssrtpdec and dtlssrtpenc) and a few
|
||||
minor elements necessary to implement them. The two elements dtlssrtpdec and
|
||||
dtlssrtpenc are the only ones you are supposed to include in, respectively, the
|
||||
RX and TX pipelines of your DTLS-enabled application. This means you're not
|
||||
supposed to directly include those minor elements in your pipelines.
|
||||
|
||||
dtlssrtpenc
|
||||
-----------
|
||||
This element is to be included in the TX pipeline and will initiate the DTLS
|
||||
handshake if configured to be the client. Its main configuration parameters are:
|
||||
|
||||
- connection-id: a string that must match the connection-id in dtlssrtpdec;
|
||||
- is-client: a boolean that indicates whether this is going to be the client
|
||||
or the server during the DTLS handshake.
|
||||
|
||||
Internally this element comprises the standard srtpenc element, the dtlsenc
|
||||
element and a funnel to connect both these elements to one single output.
|
||||
The srtpenc can be used to encrypt SRTP/SRTCP packets while the dtlsenc can be
|
||||
used to encrypt generic data, e.g. for non-SRTP applications.
|
||||
|
||||
NB With the current implementation the TX pipeline containing the dtlssrtpenc
|
||||
must be created *AFTER* the RX pipeline.
|
||||
|
||||
dtlssrtpdec
|
||||
-----------
|
||||
It is to be included in the RX pipeline. Its main configuration parameters are:
|
||||
|
||||
- connection-id: a string that must match the connection-id in dtlssrtpenc;
|
||||
- pem: a string that can be used to provide your own certificate *AND* private
|
||||
key in PEM format. The private key is required to carry out the
|
||||
handshake so do not forget it or the DTLS negotiation will fail;
|
||||
- peer_pem: a read only parameter that can be used to retrieve the
|
||||
certificate sent from the other party in PEM format once the
|
||||
handshake is completed.
|
||||
|
||||
Internally this element comprises a dtlssrtpdemux, a standard srtpdec element
|
||||
and the dtlsdec element. The dtlssrtpdemux element switches SRT(C)P packets to
|
||||
the srtpdec element and DTLS packets to the dtlsdec element and discards any
|
||||
other unknown packet. So, similarly for the dtlssrtpenc case, DTLS-SRTP
|
||||
applications would exercise the srtpdec element and any other non-SRTP
|
||||
application would exercise the dtlsdec element.
|
||||
|
||||
NB With the current implementation the RX pipeline containing the dtlssrtpdec
|
||||
must be created *BEFORE* the TX pipeline.
|
||||
|
||||
EXAMPLE PIPELINE
|
||||
================
|
||||
The following is an example usage of the DTLS plugin. It is a python script that
|
||||
creates two endpoints that exchange encrypted audio using DTLS to exchange the
|
||||
encryption keys.
|
||||
|
||||
NB In theory we would show an example gst-launch command. However that would not
|
||||
be enough because you need two pairs of TX/RX pipelines for a proper
|
||||
handshake and you can't use gst-launch two start 4 different pipelines.
|
||||
This why there is a python script in here.
|
||||
|
||||
```
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# create two endpoints, each with tx and rx pipelines using the DTLS
|
||||
# elements and let audio flowing for a while to give time for a packet capture
|
||||
|
||||
import time
|
||||
from gi.repository import Gst, GObject, GLib
|
||||
GObject.threads_init()
|
||||
Gst.init(None)
|
||||
|
||||
|
||||
def _start_pipeline(pipeline):
|
||||
pipeline.set_state(Gst.State.PLAYING)
|
||||
pipeline.get_state(Gst.CLOCK_TIME_NONE)
|
||||
|
||||
|
||||
def _sleep_while_iterating_gloop(secs):
|
||||
""" block for secs seconds but iterate the gloop while you do """
|
||||
for _ in range(10 * secs):
|
||||
gloop = GLib.MainLoop()
|
||||
gloop_context = gloop.get_context()
|
||||
gloop_context.iteration(may_block=False)
|
||||
time.sleep(0.1)
|
||||
|
||||
def dtls_tx_pipeline_description(name, is_client, port):
|
||||
return ' ! '.join([
|
||||
'audiotestsrc is-live=true',
|
||||
'audio/x-raw, rate=8000, format=S16LE, channels=1',
|
||||
'opusenc frame-size=10',
|
||||
'rtpopuspay pt=103',
|
||||
'.rtp_sink_0 dtlssrtpenc connection-id={name} is-client={client} .src',
|
||||
'udpsink port={port}'
|
||||
]).format(name=name, client=is_client, port=port)
|
||||
|
||||
|
||||
def dtls_rx_pipeline_description(name, port):
|
||||
return ' ! '.join([
|
||||
'udpsrc port={port}',
|
||||
'.sink dtlssrtpdec connection-id={name} .rtp_src',
|
||||
'queue',
|
||||
'fakesink async=false'
|
||||
]).format(name=name, port=port)
|
||||
|
||||
|
||||
class Endpoint:
|
||||
def __init__(self, name, is_client, tx_port, rx_port):
|
||||
self.name = name
|
||||
tx_pipeline_description = dtls_tx_pipeline_description(
|
||||
name, is_client, tx_port
|
||||
)
|
||||
rx_pipeline_description = dtls_rx_pipeline_description(name, rx_port)
|
||||
print(rx_pipeline_description)
|
||||
print(tx_pipeline_description)
|
||||
|
||||
self.rx_pipeline = Gst.parse_launch(rx_pipeline_description)
|
||||
self.tx_pipeline = Gst.parse_launch(tx_pipeline_description)
|
||||
|
||||
def start(self):
|
||||
# Start RX first, otherwise it fails due to the current implementation
|
||||
self.start_rx_pipeline()
|
||||
self.start_tx_pipeline()
|
||||
|
||||
def start_rx_pipeline(self):
|
||||
_start_pipeline(self.rx_pipeline)
|
||||
|
||||
def start_tx_pipeline(self):
|
||||
_start_pipeline(self.tx_pipeline)
|
||||
|
||||
def stop(self):
|
||||
def stop_pipeline(p):
|
||||
p.set_state(Gst.State.NULL)
|
||||
p.get_state(Gst.CLOCK_TIME_NONE)
|
||||
stop_pipeline(self.tx_pipeline)
|
||||
stop_pipeline(self.rx_pipeline)
|
||||
|
||||
blue = Endpoint("blue", is_client=True, tx_port=23000, rx_port=23002)
|
||||
red = Endpoint("red", is_client=False, tx_port=23002, rx_port=23000)
|
||||
|
||||
red.start()
|
||||
blue.start()
|
||||
|
||||
_sleep_while_iterating_gloop(3)
|
||||
|
||||
red.stop()
|
||||
blue.stop()
|
||||
```
|
Loading…
Reference in a new issue