# PlainRtpTransport: Why require same source IP:port than connect() ?

**URL:** <https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403>\
**Category:** Integration\
**Created:** [November 13, 2019, 11:51am UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403 "2019-11-13T11:51:06Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![j1elo](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/j1elo/32/1010_2.png) [@j1elo](https://mediasoup.discourse.group/u/j1elo)\
**Post date:** [November 13, 2019, 11:51am UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/1 "2019-11-13T11:51:06Z")

</div>

Hi,

I’m finishing an integration demo with [Kurento](https://www.kurento.org/) filters, where the architecture is as follows:

```nohighlight
Browser >--(WebRTC)--> mediasoup >--(RTP)--> Kurento (applies a filter)
                                             |
Browser <--(WebRTC)--< mediasoup <--(RTP)--<--

```

Obviously, here “Kurento” could be any external 3rd-party RTP tool such as a custom GStreamer pipeline or a FFmpeg processor. It could even be that the tool receiving RTP is different from the one sending it back to mediasoup.

This setup could be theoretically accomplished with **a single PlainRtpTransport** that had both a Consumer to send video out, and a Producer to receive video in. However, it won’t work if the external tool doesn’t implement **symmetric RTP** ports, i.e. the tool needs to send from the very same port that it uses to receive data, which is the port where the PlainRtpTransport has been `connect()`ed. Or, in the case of two tools, they need to be coordinated to use the exact same port to receive and send data.

If this requirement is not satisfied, then the PlainRtpTransport will just drop the incoming data with the (debug) message `ignoring RTP packet from unknown IP:port`. For the curious, this check is done in [PlainRtpTransport.cpp:605](https://github.com/versatica/mediasoup/blob/d252f64c7edefd9ec7323764009045e23fc0023a/worker/src/RTC/PlainRtpTransport.cpp#L605).

My question is: **why shouldn’t PlainRtpTransport just listen for incoming data on the IP:port it binds to, regardless of where it comes from?** Why such a specific restriction on the source of the incoming packets?

[Symmetric RTP](https://tools.ietf.org/html/rfc4961) is understandably required in 3rd-party endpoints for mechanisms such as COMEDIA to work properly; this is also warned about in Kurento documentation for users that wish to use the COMEDIA mode in there. But for general purpose RTP transmission, it doesn’t look like neccessary. WebRTC doesn’t use it either. Furthermore, this is not a technical limitation: I just tried commenting out [that return](https://github.com/versatica/mediasoup/blob/d252f64c7edefd9ec7323764009045e23fc0023a/worker/src/RTC/PlainRtpTransport.cpp#L609), and everything works beautifully.

The easy way to avoid this problem was to just use 2 PlainRtpTransports, one to send and another to receive. It’s just that with a receive-only PlainRtpTransport, the _semantics_ of the `connect()` method are a bit strange (really you are just “`connect`ing” in order to “whitelist” a remote IP and port, to receive data from it).

I’m not saying you should change this, just would like some context to better understand the issue. Although if you see it fitting, then I’d propose removing that restriction 🙂

---

<div class="post-metadata">

**Author:** ![ibc](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/ibc/32/1540_2.png) [@ibc](https://mediasoup.discourse.group/u/ibc)\
**Post date:** [November 13, 2019, 12:10pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/2 "2019-11-13T12:10:17Z")

</div>

> [@j1elo](#):
>
> **why shouldn’t PlainRtpTransport just listen for incoming data on the IP:port it binds to, regardless of where it comes from?** Why such a specific restriction on the source of the incoming packets?

For security reasons. Otherwise anyone from anywhere could send RTP packets into the mediasoup plain transport binding port. Note that this cannot happen in WebRTC since those RTP packets must be encrypted with SRTP keys previously negotiated over DTLS after ICE procedures authenticated with user/pwd.

> [@j1elo](#):
>
> It’s just that with a receive-only PlainRtpTransport, the _semantics_ of the `connect()` method are a bit strange (really you are just “ `connect` ing” in order to “whitelist” a remote IP and port, to receive data from it).

I disagree here. `connect()` is just about connecting the transport, it’s not about sending media to it. This is, you must connect the transport before you can use it for sending or receiving. Yup, maybe we could have chosen other name instead of `connect()`, but it’s too late to change it 🙂

---

<div class="post-metadata">

**Author:** ![ibc](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/ibc/32/1540_2.png) [@ibc](https://mediasoup.discourse.group/u/ibc)\
**Post date:** [November 13, 2019, 12:11pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/3 "2019-11-13T12:11:17Z")

</div>

Said that, I strongly think that, in your scenario, creating two separate plain transport (one for sending and one for receiving) is perfectly elegant and appropriate.

---

<div class="post-metadata">

**Author:** ![j1elo](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/j1elo/32/1010_2.png) [@j1elo](https://mediasoup.discourse.group/u/j1elo)\
**Post date:** [November 13, 2019, 5:02pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/4 "2019-11-13T17:02:48Z")

</div>

> [@ibc](#):
>
> `connect()` is just about connecting the transport, it’s not about sending media to it. This is, you must connect the transport before you can use it for sending or receiving.

Actually in a receive-only case, when using UDP there is nothing to do after starting to listen on some IP and port… which is what creating the transport already does. Indeed once the transport is created, the C++ code is already listening and receiving data, just ignoring on purpose all incoming packets.

Requiring a further “connect” action (or “start” or whatever, I get the idea) is artificial, just a forced extra step of whitelisting the desired remote port, and getting this concept right, even after reading docs, was confusing at the beginning.

That’s “security through obscurity”, although I guess in practice it kinda works. But ultimately if an RTP stream is to be secured I believe it should rely on proper mechanisms to do so, i.e. using SRTP, instead on arbitrary port restrictions.

In any case the problematic part was sending RTP to mediasoup; it was possible to do thanks to the support for COMEDIA in mediasoup, otherwise it would have been impossible so thanks for adding that.

There is now a complete demo of sending RTP out from mediasoup to Kurento, applying a realtime video filter, and sending the modified video back to mediasoup, in here:

> <https://github.com/Kurento/mediasoup-demos/tree/master/mediasoup-kurento-filter>
>
> //github.com/Kurento/mediasoup-demos/tree/master/mediasoup-kurento-filter

(note that a diagram is supposed to explain the architecture but right now Github seems to have broken image rendering in README pages)

---

<div class="post-metadata">

**Author:** ![ibc](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/ibc/32/1540_2.png) [@ibc](https://mediasoup.discourse.group/u/ibc)\
**Post date:** [November 13, 2019, 5:31pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/5 "2019-11-13T17:31:34Z")

</div>

> [@j1elo](#):
>
> Requiring a further “connect” action (or “start” or whatever, I get the idea) is artificial, just a forced extra step of whitelisting the desired remote port, and getting this concept right, even after reading docs, was confusing at the beginning

Somehow the plain transport must told about which the remote IP and port(s) are. Since many times this involves SDP O/A and it’s not always clear who the SDP offerer is, we must hace `transport.connect()` as a separate method to be called once the remote has its port(s) ready.

> [@j1elo](#):
>
> That’s “security through obscurity”, although I guess in practice it kinda works. But ultimately if an RTP stream is to be secured I believe it should rely on proper mechanisms to do so, i.e. using SRTP, instead on arbitrary port restrictions.

We do not (yet) support SRTP (other than in WebRTC transport), so we do need a way to protect the transport from receiving malicious packets from anywhere.

> [@j1elo](#):
>
> There is now a complete demo of sending RTP out from mediasoup to Kurento, applying a realtime video filter, and sending the modified video back to mediasoup, in here:

Cool, congrats!

---

<div class="post-metadata">

**Author:** ![ibc](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/ibc/32/1540_2.png) [@ibc](https://mediasoup.discourse.group/u/ibc)\
**Post date:** [November 13, 2019, 5:38pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/6 "2019-11-13T17:38:31Z")

</div>

BTW I’ve added Kurento/mediasoup-demos project to the “Examples” section in mediasoup website. Well, actually it will be published once we release a new version of mediasoup with transport-cc and TypeScript, which will happen soon.

---

<div class="post-metadata">

**Author:** ![j1elo](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/j1elo/32/1010_2.png) [@j1elo](https://mediasoup.discourse.group/u/j1elo)\
**Post date:** [November 14, 2019, 12:16pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/7 "2019-11-14T12:16:12Z")

</div>

Nice!

So, I would like to summarize the observations I’ve done, and provide a short conclusion at the end, in case this is useful for some other users that might be searching for info about RTP; you might also find this useful for addition to the docs:

- For **sending RTP out** from mediasoup, when the other party has already communicated which port(s) it uses for listening, `transport.connect()` must be used to start sending RTP to those ports. Note however the SDP Offer/Answer model is a mechanism where each party states their **listen** (inbound) port(s), and AFAIK there is no standard method _at all_ to express their outbound port(s), so in the standard common case, `transport.connect()` will only be useful for sending RTP data out, but won’t accept the other party’s RTCP Receiver Reports data in - because the other party’s outbound ports with all probability will be random and won’t coincide with those indicated in `transport.connect()`.

- For **receiving RTP (and/or RTCP) in** to mediasoup, we have two scenarios:

Short-form conclusions from these observations are:

- If the remote program allows setting specific outbound bind ports and perform Symmetric RTP/RTCP, then both **send and receive** can be performed with a single PlainRtpTransport in mediasoup. RTP and RTCP packets will flow correctly.

- Otherwise, RTP can be made to work by managing two different PlainRtpTransports in the application, at the cost of a partially broken RTCP flow:

Cheers!

---

<div class="post-metadata">

**Author:** ![ibc](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/ibc/32/1540_2.png) [@ibc](https://mediasoup.discourse.group/u/ibc)\
**Post date:** [November 14, 2019, 2:40pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/8 "2019-11-14T14:40:21Z")

</div>

> [@j1elo](#):
>
> For **sending RTP out** from mediasoup, when the other party has already communicated which port(s) it uses for listening, `transport.connect()` must be used to start sending RTP to those ports. Note however the SDP Offer/Answer model is a mechanism where each party states their **listen** (inbound) port(s), and AFAIK there is no standard method _at all_ to express their outbound port(s), so in the standard common case, `transport.connect()` will only be useful for sending RTP data out, but won’t accept the other party’s RTCP Receiver Reports data in - because the other party’s outbound ports with all probability will be random and won’t coincide with those indicated in `transport.connect()` .

We assume symmetric RTP and symmetric RTCP (while RTCP-mux is optional, but if unset we do not use contiguous ports for RTP and RTCP). I strongly assume that all RTP engines nowadays do support symmetric RTP and RTCP, don’t they?

> [@j1elo](#):
>
> When it is not possible to choose outbound ports in the other party, it becomes mandatory to replace `transport.connect()` with COMEDIA in mediasoup.

Why? I mean, once the other party has generated its SDP offer you can parse its media port and RTCP port and pass them to `connect()`, am I wrong?

What it comes to my mind is that, in your scenario, you are not using a single “RTP stack instance” in your server but two, one for receiving media and another to send it back to mediasoup, so that’s why you cannot use a single plain transport. But I strongly consider that this is a legit scenario for having two plain transports, because the remote party is running two “RTP endpoints”.

---

<div class="post-metadata">

**Author:** ![j1elo](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/j1elo/32/1010_2.png) [@j1elo](https://mediasoup.discourse.group/u/j1elo)\
**Post date:** [November 14, 2019, 4:13pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/9 "2019-11-14T16:13:27Z")

</div>

> [@ibc](#):
>
> We assume symmetric RTP and symmetric RTCP (while RTCP-mux is optional, but if unset we do not use contiguous ports for RTP and RTCP). I strongly assume that all RTP engines nowadays do support symmetric RTP and RTCP, don’t they?

I’m… really not that sure. GStreamer is able to do so for sure, because you can configure the “[bind-port](https://gstreamer.freedesktop.org/documentation/udp/udpsink.html?gi-language=c#udpsink:bind-port)” property on the `udpsink` elements at the end of a pipeline. But I have my doubts about FFmpeg, couldn’t find anything although I saw there is a “localport” property that might do the trick. Also I lack experience with other industrial level software such as Adobe Media Server.

Overall though, I think it might be possible to assume that all major RTP implementations will support Symmetric RTP, although it introduces the additional problem of having to signal the bind ports through means different to SDP, because SDP messages cannot do it _per se_. Which brings us to the next question:

> [@ibc](#):
>
> > [@j1elo](#):
> >
> > When it is not possible to choose outbound ports in the other party, it becomes mandatory to replace `transport.connect()` with COMEDIA in mediasoup.
> 
> Why? I mean, once the other party has generated its SDP offer you can parse its media port and RTCP port and pass them to `connect()` , am I wrong?

Once the other party has generated an SDP message (either an Offer or an Answer), this SDP message contains the ports in which the other party is _listening for packets_. Not the ports that the other party will be using to _send packets_.

As said earlier, there is _no_ provision (that I know of) in the SDP message format to transmit the ports one party is binding to _for its outbound traffic_. The port in the `m=` line is a listening port, telling you that you should _send_ your data to that remote port. It doesn’t tell you anything about what remote port will be used to send data _to you_. The SDP O/A model assumes that each party will freely bind to a random port in order to send data. That of course goes against a strong assumption of symmetric RTP in mediasoup, but it can be worked around with the setup I described.

> [@ibc](#):
>
> you are not using a single “RTP stack instance” in your server but two, one for receiving media and another to send it back to mediasoup, so that’s why you cannot use a single plain transport.

The devil is in the details, and now I agree with you that it doesn’t hurt that much once the requirements for RTP are clearer. But the SDP Offer/Answer model had made me biased about what to expect, and in this model, a single RTP endpoint can be used to _both_ send and receive RTP, because the outbound port can be chosen freely by each party, thus each party only needs to know _where_ to send their data to the other one. The SDP messages can natively indicate bidirectional communication between endpoints with the media attribute `a=sendrecv`.

E.g. when you send this SDP Offer:

```plaintext
v=0
o=- 0 0 IN IP4 192.168.1.11
s=-
c=IN IP4 192.168.1.11
t=0 0
m=video 3310 RTP/AVP 120
a=rtcp:3311
a=sendrecv
a=rtpmap:120 VP8/90000
a=ssrc:11111111 cname:test

```

You are telling the other party:

Hi, I’m expecting to receive your VP8 RTP video at 192.168.1.11:3310 with Payload Type 120, and your RTCP messages at 192.168.1.11:3311; also I will send video to you with SSRC 11111111.

Then the other party would generate this SDP Answer:

```plaintext
v=0
o=- 0 0 IN IP4 192.168.1.22
s=-
c=IN IP4 192.168.1.22
t=0 0
m=video 3320 RTP/AVP 120
a=rtcp:3322
a=sendrecv
a=rtpmap:120 VP8/90000
a=ssrc:22222222 cname:test

```

Meaning: OK, I’ll be receiving your VP8 RTP video at 192.168.1.22:3320, and your RTCP messages at 192.168.1.22:3322; also I’ll send my video with SSRC 22222222.

With this SDP O/A exchange, both parties know:

- What destination IP:Port they must send their packets to.
- What SSRC they must expect from the other party.

Particularly, one thing _neither_ of the parties know is what is the source remote port that the other party will be using. Also there was no indication in the SDP messages about the other party wanting to use symmetric RTP. So, if symmetric RTP is to be used, it must be signaled out of the SDP band.

So, it can be worked around as I’ve explained, but it’s important that all these concepts are clear in order to prevent lots of confusion and head scratches 🙂

---

<div class="post-metadata">

**Author:** ![ibc](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/ibc/32/1540_2.png) [@ibc](https://mediasoup.discourse.group/u/ibc)\
**Post date:** [November 15, 2019, 10:33am UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/10 "2019-11-15T10:33:32Z")

</div>

Ok, so the only remaining topic here is symmetric RTP/RTCP. Here a thing:

- [RFC 4961](https://tools.ietf.org/html/rfc4961): _Symmetric RTP / RTP Control Protocol (RTCP)_

Somewhere in section 4:

> There are no known cases where symmetric RTP or symmetric RTCP are  
> harmful.
> 
> For these reasons, it is RECOMMENDED that symmetric RTP and symmetric  
> RTCP always be used for bidirectional RTP media streams.

Yep, indeed it’s not signalled in the SDP so endpoint A (mediasoup `PlainRtpTransport`) should be, in theory, ready to receive RTP/RTCP from the remote endpoint in the port(s) it has bound no matter where the incoming RTP/RTCP comes from. The problem here is about security. Without SRTP anyone could impersonate such a remote endpoint at any time.

However I do also understand your point. We could relax the `port` stuff and just require that incoming RTP/RTCP comes to the `PlainRtpTransport` from the `ip` given in `connect()`. Would it make sense?

And, however, we have a technical limitation. The [PlainRtpTranport](https://github.com/versatica/mediasoup/blob/v3/worker/src/RTC/PlainRtpTransport.cpp) just handles one or two tuples ([TransportTuple](https://github.com/versatica/mediasoup/blob/v3/worker/include/RTC/TransportTuple.hpp) C++ instances). Such a `TransportTuple`, when UDP, means a local IP:port and a remote IP:port. So here a question:

Are we definitely talking about **bidirectional** and **asymmetric** UDP plain RTP connections? This is, A and B exchanging RTP in both directions from random & unannounced ports? If that is really needed then we should change `PlainRtpTransport.cpp` internals and, instead of just having:

- `this->tuple`
- `this->rtcpTuple`

it should have:

- `this->sendTuple`
- `this->recvTuple`
- `this->sendRtcpTuple`
- `this->recvRtcpTuple`

That, in addition to just force the remote source IP to match (and not also the remote port) make make it work. However it introduces much more complexity in the code.

I just wonder whether it’s worth all this instead of just creating two separate `PlainRtpTransports`.

---

<div class="post-metadata">

**Author:** ![j1elo](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/j1elo/32/1010_2.png) [@j1elo](https://mediasoup.discourse.group/u/j1elo)\
**Post date:** [November 19, 2019, 12:34pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/11 "2019-11-19T12:34:37Z")

</div>

> [@ibc](#):
>
> We could relax the `port` stuff and just require that incoming RTP/RTCP comes to the `PlainRtpTransport` from the `ip` given in `connect()` . Would it make sense?

It would make sense for the case of an RTP peer that does not implement Symmetric RTP. However, we are nitpicking here; just have in mind that _technically_, it could perfectly happen (i.e. symmetric rtp is an optional feature and sooner or later someone will want to connect a RTP VoIP terminal which is not symmetric and it’s not possible to make it so, with mediasoup as a WebRTC gateway, and ports won’t match, etc).

For the more practical side of things, I’ve made some changes to Kurento’s RtpEndpoint to make sure it is both symmetric _and_ it supports the `a=rtcp:<PortNumber>` attribute, which wasn’t supported before. So right now we can already achieve perfect RTP integration with mediasoup 🙂

---

<div class="post-metadata">

**Author:** ![j1elo](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/j1elo/32/1010_2.png) [@j1elo](https://mediasoup.discourse.group/u/j1elo)\
**Post date:** [November 19, 2019, 12:50pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/12 "2019-11-19T12:50:47Z")

</div>

Just to make a last clarification in case you decide to tackle this in the future:

> [@ibc](#):
>
> I just wonder whether it’s worth all this instead of just creating two separate `PlainRtpTransports` .

Note that what you say doesn’t solve the issue for non-symmetric RTP endpoints; technically all RTP transports are always bidirectional, because RTP goes in one direction and RTCP goes in the opposite one:

- A consume-only (send-only) `PlainRtpTransport`…

- A produce-only (recv-only) `PlainRtpTransport`…

---

<div class="post-metadata">

**Author:** ![ibc](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/ibc/32/1540_2.png) [@ibc](https://mediasoup.discourse.group/u/ibc)\
**Post date:** [November 19, 2019, 2:17pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/13 "2019-11-19T14:17:34Z")

</div>

Mmmm, honestly I’m considering that requiring symmetric RTP is fair enough nowadays. It’s not in my mind the idea of supporting a “RTP VoIP terminal which is not symmetric” 🙂

After the whole discussion, the only important thing IMHO is whether FFmpeg and Gstreamer can consume RTP (without producing) from a `PlainRtpTransport` and still send RTCP to mediasoup. For that, `comedia: true` cannot be used (since there is no RTP from FFmpeg or Gstreamer to mediasoup) so we **do need** to know in advance the RTP and RTCP listening ports of FFmpeg or Gstreamer.

You said that this is possible in Gstreamer and, AFAIR, the same happens in FFmpeg by setting the something like `localRtpPort` and `localRtcpPort` somewhere in a URL. If confirmed we are done.

I really do not want to get into the pain of non symmetric RTP endpoints. By design, plain RTP is already insecure enough to even allow it to be more insecure. Thoughts?

---

<div class="post-metadata">

**Author:** ![j1elo](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/j1elo/32/1010_2.png) [@j1elo](https://mediasoup.discourse.group/u/j1elo)\
**Post date:** [November 19, 2019, 2:30pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/14 "2019-11-19T14:30:10Z")

</div>

> [@ibc](#):
>
> honestly I’m considering that requiring symmetric RTP is fair enough nowadays. It’s not in my mind the idea of supporting a “RTP VoIP terminal which is not symmetric”

Yeah I think it’s fair enough. Also it will keep your implementation simpler. Although don’t underestimate the kind of strange requirements that someone will come upon one day (the typical phrase “it’s a matter of _when_, not _if_” applies here).

I’d still suggest that you think of adding SRTP support at some point in the future, because the trick of expecting symmetric rtp while nice it is just a think layer of protection compared to proper security mechanisms.

> [@ibc](#):
>
> You said that this is possible in Gstreamer and, AFAIR, the same happens in FFmpeg by setting the something like `localRtpPort` and `localRtcpPort` somewhere in a URL

With GStreamer it is definitely possible if one builds the pipeline by hand. Not so sure if one uses the [sdpdemux](https://gstreamer.freedesktop.org/documentation/sdpelem/sdpdemux.html?gi-language=c) element, which abstracts the whole pipeline creation process and instead uses a single SDP message as the only method to configure the pipeline.

With FFmpeg, I’d need to study it closer. I found it, it’s a URL parameter named `localrtpport=n` and `localrtcpport=n`, documented in the [rtp section](https://www.ffmpeg.org/ffmpeg-protocols.html#rtp) of the FFmpeg formats page. I think that the URL “mode” of FFmpeg can only be used to **consume** RTP (i.e. send RTP to FFmpeg), but it cannot be used to **produce** RTP (i.e. send RTP from FFmpeg) so that might be only a partial solution. In any case, it also prevents from using the more standard method of sending an SDP message fo FFmpeg and let it configure itself as needed.

I’d need to look more into these modes of GStreamer and FFmpeg. Will let you know if there is any obvious issue there.

---

<div class="post-metadata">

**Author:** ![ibc](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/ibc/32/1540_2.png) [@ibc](https://mediasoup.discourse.group/u/ibc)\
**Post date:** [November 19, 2019, 3:50pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/15 "2019-11-19T15:50:30Z")

</div>

> [@j1elo](#):
>
> Yeah I think it’s fair enough. Also it will keep your implementation simpler. Although don’t underestimate the kind of strange requirements that someone will come upon one day (the typical phrase “it’s a matter of _when_ , not _if_ ” applies here).

Also money 🙂

> [@j1elo](#):
>
> I’d still suggest that you think of adding SRTP support at some point in the future, because the trick of expecting symmetric rtp while nice it is just a think layer of protection compared to proper security mechanisms.

Absolutely. SRTP will be eventually added to plain and pipe transports.

> [@j1elo](#):
>
> but it cannot be used to **produce** RTP (i.e. send RTP from FFmpeg) so that might be only a partial solution. In any case, it also prevents from using the more standard method of sending an SDP message fo FFmpeg and let it configure itself as needed.

Why not? After you “send” a SDP to FFmpeg, cannot you get a SDP response from FFmpeg and parse the RTP and RTCP ports in there? (of course assuming symmetric RTP).

---

<div class="post-metadata">

**Author:** ![j1elo](https://yyz2.discourse-cdn.com/free1/user_avatar/mediasoup.discourse.group/j1elo/32/1010_2.png) [@j1elo](https://mediasoup.discourse.group/u/j1elo)\
**Post date:** [November 19, 2019, 4:09pm UTC](https://mediasoup.discourse.group/t/plainrtptransport-why-require-same-source-ip-port-than-connect/403/16 "2019-11-19T16:09:52Z")

</div>

> [@ibc](#):
>
> Why not? After you “send” a SDP to FFmpeg, cannot you get a SDP response from FFmpeg and parse the RTP and RTCP ports in there? (of course assuming symmetric RTP).

I think that’s the problem. I believe FFmpeg won’t do symmetric rtp by default (neither will gstreamer), unless you explicitly tell it to do so, which the SDP cannot. But I need to study it further, to be 100% sure about how to do it.
