/// <summary> /// From RFC5764: /// +----------------+ /// | 127 < B< 192 -+--> forward to RTP /// | | /// packet --> | 19 < B< 64 -+--> forward to DTLS /// | | /// | B< 2 -+--> forward to STUN /// +----------------+ /// </summary> /// <paramref name="localPort">The local port on the RTP socket that received the packet.</paramref> /// <param name="remoteEP">The remote end point the packet was received from.</param> /// <param name="buffer">The data received.</param> private void OnRTPDataReceived(int localPort, IPEndPoint remoteEP, byte[] buffer) { //logger.LogDebug($"RTP channel received a packet from {remoteEP}, {buffer?.Length} bytes."); // By this pint the RTP ICE channel has already processed any STUN packets which means // it's only necessary to separate RTP/RTCP from DTLS. // Because DTLS packets can be fragmented and RTP/RTCP should never be use the RTP/RTCP // prefix to distinguish. if (buffer?.Length > 0) { try { if (buffer?.Length > RTPHeader.MIN_HEADER_LEN && buffer[0] >= 128 && buffer[0] <= 191) { // RTP/RTCP packet. base.OnReceive(localPort, remoteEP, buffer); } else //if (buffer[0] >= 20 && buffer[0] <= 63) { // DTLS packet. OnDtlsPacket?.Invoke(buffer); } } catch (Exception excp) { logger.LogError($"Exception RTCPeerConnection.OnRTPDataReceived {excp.Message}"); } } }
private void StartWebRtcRtpListener(IceCandidate iceCandidate) { string localEndPoint = "?"; try { localEndPoint = iceCandidate.LocalRtpSocket.LocalEndPoint.ToString(); logger.LogDebug("Starting WebRTC RTP listener for call " + CallID + " on socket " + localEndPoint + "."); IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); UdpClient localSocket = new UdpClient(); localSocket.Client = iceCandidate.LocalRtpSocket; while (!IsClosed) { try { //logger.LogDebug("ListenToReceiverWebRTCClient Receive."); byte[] buffer = localSocket.Receive(ref remoteEndPoint); iceCandidate.LastCommunicationAt = DateTime.Now; //logger.LogDebug(buffer.Length + " bytes read on Receiver Client media socket from " + remoteEndPoint.ToString() + "."); //if (buffer.Length > 3 && buffer[0] == 0x16 && buffer[1] == 0xfe) if (buffer[0] >= 20 && buffer[0] <= 64) { //OnMediaPacket(iceCandidate, buffer, remoteEndPoint); OnDtlsPacket?.Invoke(iceCandidate, buffer, remoteEndPoint); } //else if ((buffer[0] & 0x80) == 0) else if (buffer[0] == 0 || buffer[0] == 1) { STUNv2Message stunMessage = STUNv2Message.ParseSTUNMessage(buffer, buffer.Length); ProcessStunMessage(iceCandidate, stunMessage, remoteEndPoint); } else { OnMediaPacket?.Invoke(iceCandidate, buffer, remoteEndPoint); } } catch (Exception sockExcp) { _communicationFailureCount++; logger.LogWarning("Exception ListenToReceiverWebRTCClient Receive (" + localEndPoint + " and " + remoteEndPoint + ", failure count " + _communicationFailureCount + "). " + sockExcp.Message); // Need to be careful about deciding when the connection has failed. Sometimes the STUN requests we send will arrive before the remote peer is ready and cause a socket exception. // Only shutdown the peer if we are sure all ICE intialisation is complete and the socket exception occurred after the RTP had stated flowing. if (iceCandidate.IsStunLocalExchangeComplete && iceCandidate.IsStunRemoteExchangeComplete && iceCandidate.RemoteRtpEndPoint != null && remoteEndPoint != null && iceCandidate.RemoteRtpEndPoint.ToString() == remoteEndPoint.ToString() && DateTime.Now.Subtract(IceNegotiationStartedAt).TotalSeconds > 10) { logger.LogWarning("WebRtc peer communication failure on call " + CallID + " for local RTP socket " + localEndPoint + " and remote RTP socket " + remoteEndPoint + " ."); iceCandidate.DisconnectionMessage = sockExcp.Message; break; } else if (_communicationFailureCount > COMMUNICATION_FAILURE_COUNT_FOR_CLOSE) { logger.LogWarning("WebRtc peer communication failures on call " + CallID + " exceeded limit of " + COMMUNICATION_FAILURE_COUNT_FOR_CLOSE + " closing peer."); break; } //else if (DateTime.Now.Subtract(peer.IceNegotiationStartedAt).TotalSeconds > ICE_CONNECTION_LIMIT_SECONDS) //{ // logger.LogWarning("WebRTC peer ICE connection establishment timed out on call " + peer.CallID + " for " + iceCandidate.LocalRtpSocket.LocalEndPoint + "."); // break; //} } } Close(); } catch (Exception excp) { logger.LogError("Exception ListenForWebRTCClient (" + localEndPoint + "). " + excp); } }