Skip to content
Branch: master
Find file History
sdroege and GStreamer Merge Bot dtls: Keep track of the connection state and signal it through all th…
…e layers

This allows the application to keep track of the underlying DTLS
connection state and act accordingly.
Latest commit 7fcfb6c Jan 12, 2020
Permalink
Type Name Latest commit message Commit time
..
Failed to load latest commit information.
README dtsl: add some documentation Apr 18, 2016
gstdtlsagent.c dtlsagent: Clear the certificate upon finalize Jun 25, 2019
gstdtlsagent.h dtls: Re-namespace from Er to Gst Mar 16, 2015
gstdtlscertificate.c Run gst-indent through the files Nov 28, 2018
gstdtlscertificate.h dtls: Re-namespace from Er to Gst Mar 16, 2015
gstdtlsconnection.c dtls: Keep track of the connection state and signal it through all th… Jan 19, 2020
gstdtlsconnection.h dtls: Keep track of the connection state and signal it through all th… Jan 19, 2020
gstdtlsdec.c dtls: Keep track of the connection state and signal it through all th… Jan 19, 2020
gstdtlsdec.h dtlsdec: Fix critical warning "got data flow before stream-start event" Jun 3, 2015
gstdtlsenc.c dtls: Keep track of the connection state and signal it through all th… Jan 19, 2020
gstdtlsenc.h dtls: Propagate write errors backwards through dtlsenc/dtlsconnection Jan 19, 2020
gstdtlssrtpbin.c dtls: Re-namespace from Er to Gst Mar 16, 2015
gstdtlssrtpbin.h dtls: Re-namespace from Er to Gst Mar 16, 2015
gstdtlssrtpdec.c dtls: Keep track of the connection state and signal it through all th… Jan 19, 2020
gstdtlssrtpdec.h dtlssrtpdec: Don't merge RTP and RTCP streams that were just split by… May 7, 2015
gstdtlssrtpdemux.c bad: use new gst_element_class_add_static_pad_template() Mar 24, 2016
gstdtlssrtpdemux.h dtls: Re-namespace from Er to Gst Mar 16, 2015
gstdtlssrtpenc.c dtls: Keep track of the connection state and signal it through all th… Jan 19, 2020
gstdtlssrtpenc.h dtls: Fix some search & replace mistakes from renaming the elements Mar 18, 2015
meson.build docs: Build documentation with hotdoc May 13, 2019
plugin.c dtls: Re-namespace from Er to Gst Mar 16, 2015

README

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()
```
You can’t perform that action at this time.