+/* parse @transport and return a valid transport in @tr. only transports
+ * from @supported are returned. Returns FALSE if no valid transport
+ * was found. */
+static gboolean
+parse_transport (const char *transport, GstRTSPLowerTrans supported,
+ GstRTSPTransport * tr)
+{
+ gint i;
+ gboolean res;
+ gchar **transports;
+
+ res = FALSE;
+ gst_rtsp_transport_init (tr);
+
+ GST_DEBUG ("parsing transports %s", transport);
+
+ transports = g_strsplit (transport, ",", 0);
+
+ /* loop through the transports, try to parse */
+ for (i = 0; transports[i]; i++) {
+ res = gst_rtsp_transport_parse (transports[i], tr);
+ if (res != GST_RTSP_OK) {
+ /* no valid transport, search some more */
+ GST_WARNING ("could not parse transport %s", transports[i]);
+ goto next;
+ }
+
+ /* we have a transport, see if it's RTP/AVP */
+ if (tr->trans != GST_RTSP_TRANS_RTP || tr->profile != GST_RTSP_PROFILE_AVP) {
+ GST_WARNING ("invalid transport %s", transports[i]);
+ goto next;
+ }
+
+ if (!(tr->lower_transport & supported)) {
+ GST_WARNING ("unsupported transport %s", transports[i]);
+ goto next;
+ }
+
+ /* we have a valid transport */
+ GST_INFO ("found valid transport %s", transports[i]);
+ res = TRUE;
+ break;
+
+ next:
+ gst_rtsp_transport_init (tr);
+ }
+ g_strfreev (transports);
+
+ return res;
+}
+
+static gboolean
+handle_blocksize (GstRTSPMedia * media, GstRTSPStream * stream,
+ GstRTSPMessage * request)
+{
+ gchar *blocksize_str;
+ gboolean ret = TRUE;
+
+ if (gst_rtsp_message_get_header (request, GST_RTSP_HDR_BLOCKSIZE,
+ &blocksize_str, 0) == GST_RTSP_OK) {
+ guint64 blocksize;
+ gchar *end;
+
+ blocksize = g_ascii_strtoull (blocksize_str, &end, 10);
+ if (end == blocksize_str) {
+ GST_ERROR ("failed to parse blocksize");
+ ret = FALSE;
+ } else {
+ /* we don't want to change the mtu when this media
+ * can be shared because it impacts other clients */
+ if (gst_rtsp_media_is_shared (media))
+ return TRUE;
+
+ if (blocksize > G_MAXUINT)
+ blocksize = G_MAXUINT;
+ gst_rtsp_stream_set_mtu (stream, blocksize);
+ }
+ }
+ return ret;
+}
+
+static gboolean
+configure_client_transport (GstRTSPClient * client, GstRTSPClientState * state,
+ GstRTSPTransport * ct)
+{
+ GstRTSPClientPrivate *priv = client->priv;
+
+ /* we have a valid transport now, set the destination of the client. */
+ if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
+ if (ct->destination && priv->use_client_settings) {
+ GstRTSPAddress *addr;
+
+ addr = gst_rtsp_stream_reserve_address (state->stream, ct->destination,
+ ct->port.min, ct->port.max - ct->port.min + 1, ct->ttl);
+
+ if (addr == NULL)
+ goto no_address;
+
+ gst_rtsp_address_free (addr);
+ } else {
+ GstRTSPAddress *addr;
+
+ addr = gst_rtsp_stream_get_address (state->stream);
+ if (addr == NULL)
+ goto no_address;
+
+ g_free (ct->destination);
+ ct->destination = g_strdup (addr->address);
+ ct->port.min = addr->port;
+ ct->port.max = addr->port + addr->n_ports - 1;
+ ct->ttl = addr->ttl;
+
+ gst_rtsp_address_free (addr);
+ }
+ } else {
+ GstRTSPUrl *url;
+
+ url = gst_rtsp_connection_get_url (priv->connection);
+ g_free (ct->destination);
+ ct->destination = g_strdup (url->host);
+
+ if (ct->lower_transport & GST_RTSP_LOWER_TRANS_TCP) {
+ /* check if the client selected channels for TCP */
+ if (ct->interleaved.min == -1 || ct->interleaved.max == -1) {
+ gst_rtsp_session_media_alloc_channels (state->sessmedia,
+ &ct->interleaved);
+ }
+ }
+ }
+ return TRUE;
+
+ /* ERRORS */
+no_address:
+ {
+ GST_ERROR_OBJECT (client, "failed to acquire address for stream");
+ return FALSE;
+ }
+}
+
+static GstRTSPTransport *
+make_server_transport (GstRTSPClient * client, GstRTSPClientState * state,
+ GstRTSPTransport * ct)
+{
+ GstRTSPTransport *st;
+
+ /* prepare the server transport */
+ gst_rtsp_transport_new (&st);
+
+ st->trans = ct->trans;
+ st->profile = ct->profile;
+ st->lower_transport = ct->lower_transport;
+
+ switch (st->lower_transport) {
+ case GST_RTSP_LOWER_TRANS_UDP:
+ st->client_port = ct->client_port;
+ gst_rtsp_stream_get_server_port (state->stream, &st->server_port);
+ break;
+ case GST_RTSP_LOWER_TRANS_UDP_MCAST:
+ st->port = ct->port;
+ st->destination = g_strdup (ct->destination);
+ st->ttl = ct->ttl;
+ break;
+ case GST_RTSP_LOWER_TRANS_TCP:
+ st->interleaved = ct->interleaved;
+ default:
+ break;
+ }
+
+ gst_rtsp_stream_get_ssrc (state->stream, &st->ssrc);
+
+ return st;
+}
+