private void RTPReceive()
{
try
{
Thread.CurrentThread.Name = "rtspsess-rtprecv";
byte[] buffer = new byte[2048];
while (!_closed)
{
try
{
EndPoint remoteEP = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
//int bytesRead = _rtpSocket.Receive(buffer);
int bytesRead = _rtpSocket.ReceiveFrom(buffer, ref remoteEP);
IPEndPoint remoteIPEndPoint = remoteEP as IPEndPoint;
//logger.Debug("RTPReceive from " + remoteEP + ".");
//if (((IPEndPoint)remoteEP).Address.ToString() != _remoteEndPoint.Address.ToString())
//{
// var oldEndPoint = _remoteEndPoint;
// _remoteEndPoint = remoteEP as IPEndPoint;
// logger.Warn("RtspSession " + _sessionID + " switched to new remote endpoint at " + _remoteEndPoint + " (old end point " + oldEndPoint + ").");
//}
if (bytesRead > 0)
{
_rtpLastActivityAt = DateTime.Now;
if (bytesRead > RTPHeader.MIN_HEADER_LEN)
{
if ((buffer[0] >= 20) && (buffer[0] <= 64))
{
// DTLS.
if(OnDtlsReceive != null)
{
try
{
OnDtlsReceive(buffer, bytesRead, SendRTPRaw);
}
catch(Exception dtlsExcp)
{
logger.Error("Exception RTSPSession.RTPReceive DTLS. " + dtlsExcp);
}
}
else
{
logger.Warn("RTSPSession.RTPReceive received a DTLS packet from " + _remoteEndPoint + "but bo DTLS handler has been set.");
}
}
else if ((buffer[0] == 0) || (buffer[0] == 1))
{
// STUN.
//if (_iceState != null)
//{
// try
// {
// STUNv2Message stunMessage = STUNv2Message.ParseSTUNMessage(buffer, bytesRead);
// //logger.Debug("STUN message received from Receiver Client @ " + stunMessage.Header.MessageType + ".");
// if (stunMessage.Header.MessageType == STUNv2MessageTypesEnum.BindingRequest)
// {
// //logger.Debug("Sending STUN response to Receiver Client @ " + remoteEndPoint + ".");
// STUNv2Message stunResponse = new STUNv2Message(STUNv2MessageTypesEnum.BindingSuccessResponse);
// stunResponse.Header.TransactionId = stunMessage.Header.TransactionId;
// stunResponse.AddXORMappedAddressAttribute(remoteIPEndPoint.Address, remoteIPEndPoint.Port);
// byte[] stunRespBytes = stunResponse.ToByteBufferStringKey(_iceState.SenderPassword, true);
// _rtpSocket.SendTo(stunRespBytes, remoteIPEndPoint);
// //logger.Debug("Sending Binding request to Receiver Client @ " + remoteEndPoint + ".");
// STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
// stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
// stunRequest.AddUsernameAttribute(_iceState.ReceiverUser + ":" + _iceState.SenderUser);
// stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
// stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null)); // Must send this to get DTLS started.
// byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(_iceState.ReceiverPassword, true);
// _rtpSocket.SendTo(stunReqBytes, remoteIPEndPoint);
// _iceState.LastSTUNMessageReceivedAt = DateTime.Now;
// }
// else if (stunMessage.Header.MessageType == STUNv2MessageTypesEnum.BindingSuccessResponse)
// {
// if (!_iceState.IsSTUNExchangeComplete)
// {
// _iceState.IsSTUNExchangeComplete = true;
// logger.Debug("WebRTC client STUN exchange complete for " + remoteIPEndPoint.ToString() + " and ICE ufrag " + _iceState.ReceiverUser + ".");
// _remoteEndPoint = remoteIPEndPoint;
// }
// }
// else if (stunMessage.Header.MessageType == STUNv2MessageTypesEnum.BindingErrorResponse)
// {
// //logger.Warn("A STUN binding error response was received from " + remoteIPEndPoint + ".");
// }
// else
// {
// //logger.Warn("An unrecognised STUN request was received from " + remoteIPEndPoint + ".");
// }
// }
// catch (SocketException sockExcp)
// {
// logger.Debug("RTPSession.RTPReceive STUN processing (" + remoteIPEndPoint + "). " + sockExcp.Message);
// continue;
// }
// catch (Exception stunExcp)
// {
// logger.Warn("Exception RTPSession.RTPReceive STUN processing (" + remoteIPEndPoint + "). " + stunExcp);
// continue;
// }
//}
//else
//{
// //logger.Warn("A STUN reponse was received on RTP socket from " + remoteIPEndPoint + " but no ICE state was set.");
//}
}
else if ((buffer[0] >= 128) && (buffer[0] <= 191))
{
if (buffer[1] == 0xC8 /* RTCP SR */ || buffer[1] == 0xC9 /* RTCP RR */)
{
// RTCP packet.
}
else
{
// RTP Packet.
RTPPacket rtpPacket = new RTPPacket(buffer.Take(bytesRead).ToArray());
//System.Diagnostics.Debug.WriteLine("RTPReceive ssrc " + rtpPacket.Header.SyncSource + ", seq num " + rtpPacket.Header.SequenceNumber + ", timestamp " + rtpPacket.Header.Timestamp + ", marker " + rtpPacket.Header.MarkerBit + ".");
//logger.Debug("RTPReceive remote " + remoteIPEndPoint + ", ssrc " + rtpPacket.Header.SyncSource + ", seq num " + rtpPacket.Header.SequenceNumber + ", timestamp " + rtpPacket.Header.Timestamp + ", bytes " + bytesRead + ", marker " + rtpPacket.Header.MarkerBit + ".");
lock (_packets)
{
if (_packets.Count > RTP_PACKETS_MAX_QUEUE_LENGTH)
{
System.Diagnostics.Debug.WriteLine("RTSPSession.RTPReceive packets queue full, clearing.");
logger.Warn("RTSPSession.RTPReceive packets queue full, clearing.");
_packets.Clear();
if (OnRTPQueueFull != null)
{
OnRTPQueueFull();
}
}
else
{
_packets.Enqueue(rtpPacket);
}
}
}
}
}
else
{
logger.Warn("RTSPSession.RTPReceive an unrecognised packet was received for session ID " + SessionID + " and " + remoteIPEndPoint + ".");
}
}
else
{
logger.Warn("Zero bytes read from RTSPSession RTP socket for session ID " + SessionID + " and " + remoteIPEndPoint + ".");
break;
}
}
catch (SocketException sockExcp)
{
if (!_closed)
{
_rtpSocketError = sockExcp.SocketErrorCode;
if (_rtpSocketError == SocketError.Interrupted)
{
// If the receive has been interrupted it means the socket has been closed most likely as a result of an RTSP TEARDOWN request.
if (OnRTPSocketDisconnected != null)
{
OnRTPSocketDisconnected(_sessionID);
}
break;
}
else
{
throw;
}
}
}
catch (Exception excp)
{
if (!_closed)
{
logger.Error("Exception RTSPSession.RTPReceive receiving. " + excp);
}
}
}
}
catch (Exception excp)
{
if (!_closed)
{
logger.Error("Exception RTSPSession.RTPReceive. " + excp);
if (OnRTPSocketDisconnected != null)
{
OnRTPSocketDisconnected(_sessionID);
}
}
}
}