private bool HandleRTSPRequestSetupOutbound(RtspProtocol @from, Variant requestHeaders, string requestContent)
{
//1. Minimal sanitize
if (requestHeaders[RTSP_HEADERS, RTSP_HEADERS_TRANSPORT] == null)
{
FATAL("RTSP %s request doesn't have %s header line",
RTSP_METHOD_SETUP,
RTSP_HEADERS_TRANSPORT);
return false;
}
//2. get the transport header line
string raw = requestHeaders[RTSP_HEADERS, RTSP_HEADERS_TRANSPORT];
Variant transport = Variant.Get();
if (!Rtsp.SDP.ParseTransportLine(raw, transport))
{
FATAL("Unable to parse transport line {0}", (raw));
return false;
}
bool forceTcp = false;
if (transport["client_port"]!=null && (transport["rtp/avp/udp"]!=null || transport["rtp/avp"]!=null))
{
forceTcp = false;
}
else if (transport["interleaved"]!=null && transport["rtp/avp/tcp"]!=null)
{
forceTcp = true;
}
else
{
FATAL("Invalid transport line: {0}", (transport.ToString()));
return false;
}
from.CustomParameters["forceTcp"] = forceTcp;
//3. Get the outbound connectivity
OutboundConnectivity pOutboundConnectivity = GetOutboundConnectivity(from, forceTcp);
if (pOutboundConnectivity == null)
{
FATAL("Unable to get the outbound connectivity");
return false;
}
//5. Find out if this is audio or video
bool isAudioTrack;
string rawUrl = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
string audioTrackId = "trackID=" + from.CustomParameters["audioTrackId"];
string videoTrackId = "trackID=" + from.CustomParameters["videoTrackId"];
/*FINEST("rawUrl: %s; audioTrackId: %s; videoTrackId: %s; fa: %d; fv: %d",
(rawUrl),
(audioTrackId),
(videoTrackId),
rawUrl.find(audioTrackId) != string::npos,
rawUrl.find(videoTrackId) != string::npos
);*/
if (rawUrl.Contains(audioTrackId))
{
isAudioTrack = true;
}
else if (rawUrl.Contains(videoTrackId))
{
isAudioTrack = false;
}
else
{
FATAL("Invalid track. Wanted: {0} or {1}; Got: {2}",
(from.CustomParameters["audioTrackId"]),
(from.CustomParameters["videoTrackId"]),
(requestHeaders[RTSP_FIRST_LINE,RTSP_URL]));
return false;
}
from.CustomParameters["isAudioTrack"] = isAudioTrack;
if (isAudioTrack)
{
if (forceTcp)
{
from.CustomParameters["audioDataChannelNumber"] = transport["interleaved","data"];
from.CustomParameters["audioRtcpChannelNumber"] = transport["interleaved","rtcp"];
from.CustomParameters["audioTrackUri"] = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
pOutboundConnectivity.HasAudio = true;
}
else
{
from.CustomParameters["audioDataPortNumber"] = transport["client_port","data"];
from.CustomParameters["audioRtcpPortNumber"] = transport["client_port","rtcp"];
from.CustomParameters["audioTrackUri"] = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
pOutboundConnectivity.HasAudio = true;
}
}
else
{
if (forceTcp)
{
from.CustomParameters["videoDataChannelNumber"] = transport["interleaved","data"];
from.CustomParameters["videoRtcpChannelNumber"] = transport["interleaved","rtcp"];
from.CustomParameters["videoTrackUri"] = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
pOutboundConnectivity.HasVideo = true;
}
else
{
from.CustomParameters["videoDataPortNumber"] = transport["client_port","data"];
from.CustomParameters["videoRtcpPortNumber"] = transport["client_port","rtcp"];
from.CustomParameters["videoTrackUri"] = requestHeaders[RTSP_FIRST_LINE,RTSP_URL];
pOutboundConnectivity.HasVideo = true;
}
}
//10. Create a session
from.GenerateSessionId();
//11 Compose the response
from.PushResponseFirstLine(RTSP_VERSION_1_0, 200, "OK");
@from.PushResponseHeader(RTSP_HEADERS_TRANSPORT,
forceTcp
? "RTP/AVP/TCP;unicast;interleaved="+ transport["interleaved","all"]
: $"RTP/AVP/UDP;unicast;source={((TCPCarrier) @from.IOHandler).NearIP};client_port={(string)(transport["client_port","all"])};server_port={(isAudioTrack ? (pOutboundConnectivity.AudioPorts) : (pOutboundConnectivity.VideoPorts))};ssrc={(isAudioTrack ? pOutboundConnectivity.AudioSSRC : pOutboundConnectivity.VideoSSRC)}");
//12. Done
return from.SendResponseMessage();
}