public void ParseWebRTCSTUNResponseTestMethod() { Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name); byte[] stunResp = new byte[] { 0x01, 0x01, 0x00, 0x2c, 0x21, 0x12, 0xa4, 0x42, 0x6a, 0x45, 0x38, 0x2b, 0x4e, 0x5a, 0x4b, 0x50, 0x64, 0x31, 0x70, 0x38, 0x00, 0x20, 0x00, 0x08, 0x00, 0x01, 0xe0, 0xda, 0xe1, 0xba, 0x85, 0x3f, 0x00, 0x08, 0x00, 0x14, 0x24, 0x37, 0x24, 0xa0, 0x05, 0x2d, 0x88, 0x97, 0xce, 0xa6, 0x4e, 0x90, 0x69, 0xf6, 0x39, 0x07, 0x7d, 0xb1, 0x6e, 0x71, 0x80, 0x28, 0x00, 0x04, 0xde, 0x6a, 0x05, 0xac }; STUNv2Message stunMessage = STUNv2Message.ParseSTUNMessage(stunResp, stunResp.Length); STUNv2Header stunHeader = stunMessage.Header; Console.WriteLine("Request type = " + stunHeader.MessageType + "."); Console.WriteLine("Length = " + stunHeader.MessageLength + "."); Console.WriteLine("Transaction ID = " + BitConverter.ToString(stunHeader.TransactionId) + "."); foreach (STUNv2Attribute attribute in stunMessage.Attributes) { if (attribute.AttributeType == STUNv2AttributeTypesEnum.Username) { Console.WriteLine(" " + attribute.AttributeType + " " + Encoding.UTF8.GetString(attribute.Value) + "."); } else { Console.WriteLine(" " + attribute.AttributeType + " " + attribute.Value + "."); } } Assert.AreEqual(STUNv2MessageTypesEnum.BindingSuccessResponse, stunHeader.MessageType); Assert.AreEqual(44, stunHeader.MessageLength); Assert.AreEqual(3, stunMessage.Attributes.Count); }
public void TestMessageIntegrityAttributeForBindingRequest() { Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name); byte[] stunReq = new byte[] { 0x00, 0x01, 0x00, 0x60, 0x21, 0x12, 0xa4, 0x42, 0x69, 0x64, 0x38, 0x2b, 0x4c, 0x45, 0x44, 0x57, 0x4d, 0x31, 0x64, 0x30, 0x00, 0x06, 0x00, 0x21, 0x75, 0x4f, 0x35, 0x73, 0x69, 0x31, 0x75, 0x61, 0x37, 0x63, 0x59, 0x34, 0x74, 0x38, 0x4d, 0x4d, 0x3a, 0x4c, 0x77, 0x38, 0x2f, 0x30, 0x43, 0x31, 0x43, 0x72, 0x76, 0x68, 0x5a, 0x43, 0x31, 0x67, 0x62, 0x00, 0x00, 0x00, 0x80, 0x2a, 0x00, 0x08, 0xc0, 0x3d, 0xf5, 0x13, 0x40, 0xf4, 0x22, 0x46, 0x00, 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x6e, 0x7f, 0x1e, 0xff, 0x00, 0x08, 0x00, 0x14, 0x55, 0x82, 0x69, 0xde, 0x17, 0x55, 0xcc, 0x66, 0x29, 0x23, 0xe6, 0x7d, 0xec, 0x87, 0x6c, 0x07, 0x3a, 0xd6, 0x78, 0x15, 0x80, 0x28, 0x00, 0x04, 0x1c, 0xae, 0x89, 0x2e }; STUNv2Message stunMessage = STUNv2Message.ParseSTUNMessage(stunReq, stunReq.Length); STUNv2Header stunHeader = stunMessage.Header; Console.WriteLine("Request type = " + stunHeader.MessageType + "."); Console.WriteLine("Length = " + stunHeader.MessageLength + "."); Console.WriteLine("Transaction ID = " + BitConverter.ToString(stunHeader.TransactionId) + "."); Assert.AreEqual(STUNv2MessageTypesEnum.BindingRequest, stunHeader.MessageType); Assert.AreEqual(96, stunHeader.MessageLength); Assert.AreEqual(6, stunMessage.Attributes.Count); Assert.AreEqual("69-64-38-2B-4C-45-44-57-4D-31-64-30", BitConverter.ToString(stunMessage.Header.TransactionId)); stunMessage.Attributes.Remove(stunMessage.Attributes.Where(x => x.AttributeType == STUNv2AttributeTypesEnum.MessageIntegrity).Single()); stunMessage.Attributes.Remove(stunMessage.Attributes.Where(x => x.AttributeType == STUNv2AttributeTypesEnum.FingerPrint).Single()); byte[] buffer = stunMessage.ToByteBufferStringKey("r89XhWC9k2kW4Pns75vmwHIa", true); Assert.AreEqual(BitConverter.ToString(stunReq), BitConverter.ToString(buffer)); }
public void ParseWebRTCSTUNRequestTestMethod() { Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name); byte[] stunReq = new byte[] { 0x00, 0x01, 0x00, 0x60, 0x21, 0x12, 0xa4, 0x42, 0x66, 0x55, 0x55, 0x43, 0x4b, 0x48, 0x74, 0x73, 0x68, 0x4e, 0x71, 0x56, // Att1: 0x00, 0x06, 0x00, 0x21, 0x6d, 0x30, 0x71, 0x47, 0x77, 0x53, 0x71, 0x2f, 0x48, 0x56, 0x48, 0x71, 0x41, 0x62, 0x4b, 0x62, 0x3a, 0x73, 0x64, 0x43, 0x48, 0x59, 0x6b, 0x35, 0x6e, 0x46, 0x34, 0x79, 0x44, 0x77, 0x55, 0x39, 0x53, 0x00, 0x00, 0x00, // Att2 0x80, 0x2a, 0x00, 0x08, 0xa0, 0x36, 0xc9, 0x6c, 0x30, 0xc6, 0x2f, 0xd2, 0x00, 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x6e, 0x7f, 0x1e, 0xff, 0x00, 0x08, 0x00, 0x14, 0x81, 0x4a, 0x4f, 0xaf, 0x3d, 0x99, 0x30, 0x67, 0x66, 0xb9, 0x48, 0x67, 0x83, 0x72, 0xd5, 0xa0, 0x7a, 0x87, 0xb5, 0x3f, 0x80, 0x28, 0x00, 0x04, 0x49, 0x7e, 0x51, 0x17 }; STUNv2Message stunMessage = STUNv2Message.ParseSTUNMessage(stunReq, stunReq.Length); STUNv2Header stunHeader = stunMessage.Header; Console.WriteLine("Request type = " + stunHeader.MessageType + "."); Console.WriteLine("Length = " + stunHeader.MessageLength + "."); Console.WriteLine("Transaction ID = " + BitConverter.ToString(stunHeader.TransactionId) + "."); Assert.AreEqual(STUNv2MessageTypesEnum.BindingRequest, stunHeader.MessageType); Assert.AreEqual(96, stunHeader.MessageLength); Assert.AreEqual(6, stunMessage.Attributes.Count); }
public void ParseCoturnSTUNResponseTestMethod() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); byte[] stunResp = new byte[] { 0x01, 0x01, 0x00, 0x44, 0x21, 0x12, 0xa4, 0x42, 0x6b, 0x4c, 0xf3, 0x18, 0xd0, 0xa7, 0xf5, 0x40, 0x97, 0x30, 0x3a, 0x27, 0x00, 0x20, 0x00, 0x08, 0x00, 0x01, 0x9e, 0x90, 0x1a, 0xb5, 0x08, 0xf3, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0xbf, 0x82, 0x3b, 0xa7, 0xac, 0xb1, 0x80, 0x2b, 0x00, 0x08, 0x00, 0x01, 0x0d, 0x96, 0x67, 0x1d, 0x42, 0xf3, 0x80, 0x22, 0x00, 0x1a, 0x43, 0x6f, 0x74, 0x75, 0x72, 0x6e, 0x2d, 0x34, 0x2e, 0x35, 0x2e, 0x30, 0x2e, 0x33, 0x20, 0x27, 0x64, 0x61, 0x6e, 0x20, 0x45, 0x69, 0x64, 0x65, 0x72, 0x27, 0x77, 0x75 }; STUNv2Message stunMessage = STUNv2Message.ParseSTUNMessage(stunResp, stunResp.Length); STUNv2Header stunHeader = stunMessage.Header; logger.LogDebug("Request type = " + stunHeader.MessageType + "."); logger.LogDebug("Length = " + stunHeader.MessageLength + "."); logger.LogDebug("Transaction ID = " + BitConverter.ToString(stunHeader.TransactionId) + "."); foreach (STUNv2Attribute attribute in stunMessage.Attributes) { if (attribute.AttributeType == STUNv2AttributeTypesEnum.MappedAddress) { STUNv2AddressAttribute addressAttribute = new STUNv2AddressAttribute(attribute.Value); logger.LogDebug(" " + attribute.AttributeType + " " + addressAttribute.Address + ":" + addressAttribute.Port + "."); Assert.Equal("59.167.172.177", addressAttribute.Address.ToString()); Assert.Equal(49026, addressAttribute.Port); } else if (attribute.AttributeType == STUNv2AttributeTypesEnum.XORMappedAddress) { STUNv2XORAddressAttribute xorAddressAttribute = new STUNv2XORAddressAttribute(STUNv2AttributeTypesEnum.XORMappedAddress, attribute.Value); logger.LogDebug(" " + attribute.AttributeType + " " + xorAddressAttribute.Address + ":" + xorAddressAttribute.Port + "."); Assert.Equal("59.167.172.177", xorAddressAttribute.Address.ToString()); Assert.Equal(49026, xorAddressAttribute.Port); } else { logger.LogDebug(" " + attribute.AttributeType + " " + attribute.Value + "."); } } Assert.Equal(STUNv2MessageTypesEnum.BindingSuccessResponse, stunHeader.MessageType); }
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); } }