public bool IsThisYourResponseSetIfItIs(STUNMessage msg) { bool bRet = SocketServer.TLS.ByteHelper.CompareArrays(RequestMessage.TransactionId, msg.TransactionId); if (bRet == true) { ResponseMessage = msg; try { if (WaitHandle != null) WaitHandle.Set(); } catch (Exception ex) { WaitHandle = null; } } return bRet; }
public void Reset(STUNMessage requestmessage) { RequestMessage = requestmessage; try { if (WaitHandle != null) WaitHandle.Close(); } catch (Exception ex) { } finally { WaitHandle = null; } WaitHandle = new System.Threading.ManualResetEvent(false); ResponseMessage = null; }
private static STUNErrorCode ProcessSTUNBindingErrorResponse(STUNMessage StunMessage) { // Error Code vorhanden? for (int i = 0; i < StunMessage.AttributeList.Count; i++) { if (StunMessage.AttributeList[i].Type == STUNAttribute.StunAttributeType.ErrorCode) { //return StunMessage.AttributeList[i].ErrorCode; ErrorCodeAttribute eca = (ErrorCodeAttribute)StunMessage.AttributeList[i]; return eca.ErrorCode; } } // kein Error Code Attribut return null; }
public STUNRequestResponse(STUNMessage requestmessage) { RequestMessage = requestmessage; }
private static STUNMessage FormSTUNIndication(String Software) { STUNMessage stunIndicationRequest = new STUNMessage(StunMessageType.BindingIndication); SoftwareAttribute software = SoftwareAttribute.CreateSoftware(Software); stunIndicationRequest.AddAttribute(software); stunIndicationRequest.Create(); return stunIndicationRequest; }
// Success und Error Responses werden nur vom Server erzeugt // Messages verarbeiten: // Requests werden nur vom Server verarbeitet // für Binding Methode werden keine Indications verarbeitet private static IPEndPoint ProcessSTUNBindingSuccessResponse(STUNMessage StunMessage) { // unknown comprehension-required attributes? //if(StunMessage.ContainsUnknownComprehensionRequiredAttributes) // return false; // XOR Mapped Address vorhanden? for (int i = 0; i < StunMessage.AttributeList.Count; i++) { if (StunMessage.AttributeList[i].Type == STUNAttribute.StunAttributeType.XorMappedAddress) { //return StunMessage.AttributeList[i].XorMappedAddress; XorMappedAddressAttribute xmaa = (XorMappedAddressAttribute)StunMessage.AttributeList[i]; return xmaa.XorMappedAddress; } } // falls nicht Mapped Address vorhanden? for (int i = 0; i < StunMessage.AttributeList.Count; i++) { if (StunMessage.AttributeList[i].Type == STUNAttribute.StunAttributeType.MappedAddress) { //return StunMessage.AttributeList[i].MappedAddress; MappedAddressAttribute maa = (MappedAddressAttribute)StunMessage.AttributeList[i]; return maa.MappedAddress; } } // keins von beiden Attributen vorhanden ist vorhanden return null; }
// Messages erzeugen: private static STUNMessage FormSTUNBindingRequest() { STUNMessage stunBindingRequest = new STUNMessage(StunMessageType.BindingRequest); // TEST Fingerprint FingerprintAttribute fingerprint = FingerprintAttribute.CreateFingerprint(); stunBindingRequest.AddAttribute(fingerprint); stunBindingRequest.Create(); return stunBindingRequest; }
private static STUNMessage FormSTUNIndication() { STUNMessage stunIndicationRequest = new STUNMessage(StunMessageType.BindingIndication); stunIndicationRequest.Create(); return stunIndicationRequest; }
private static STUNMessage SendOverTCP(String IP, int Port, STUNMessage StunMessage, IPEndPoint localEndpoint) { try { TcpClient tcpClient = new TcpClient(localEndpoint); tcpClient.Connect(IP, Port); // TimeOut Wert festlegen tcpClient.Client.ReceiveTimeout = TI; // Nachricht in Byte Array wandeln Byte[] message_buffer = StunMessage.ToByteArray(); // Netzwerkstream holen NetworkStream stream = tcpClient.GetStream(); // Message senden stream.Write(message_buffer, 0, message_buffer.Length); // zuerst Header (20 Byte) empfangen um Länge der Nachricht zu ermitteln Byte[] header = new Byte[20]; stream.Read(header, 0, 20); // Länge parsen (3. und 4. Byte im Header) Int16 msg_length = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(header, 2)); // Byte Array für Response Byte[] response = new Byte[20 + msg_length]; // Header in Response kopieren Array.Copy(header, 0, response, 0, header.Length); // Rest der Nachricht empfangen int bytesRead = stream.Read(response, 20, msg_length); // alles eingetroffen? if (bytesRead != msg_length) Console.WriteLine("Fehler beim empfangen!"); // parsen STUNMessage stunResponse = STUNMessage.Parse(response); // aufräumen //Thread.Sleep(2000); stream.Close(); tcpClient.Close(); return stunResponse; } catch (Exception e) { Console.WriteLine(e); throw e; } }
// Funktionen private static STUNMessage SendOverUDP(String IP, int Port, STUNMessage StunMessage) { IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Parse(IP), Port); IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, 0); UdpClient udpClient = null; // IPv4 oder IPv6 Adresse? if (remoteEndpoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) udpClient = new UdpClient(); else if (remoteEndpoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) udpClient = new UdpClient(System.Net.Sockets.AddressFamily.InterNetworkV6); // Nachricht in Byte Array wandeln Byte[] message_buffer = StunMessage.ToByteArray(); // initialen TimeOut Wert festlegen udpClient.Client.ReceiveTimeout = RTO; // Buffer für Empfang der Antwort Byte[] response_buffer = null; //Stopwatch stopwatch = new Stopwatch(); //stopwatch.Start(); // MessageType int type = (int)StunMessage.StunMessageType; // Indication? // 8.Bit(Maske 0x100) gelöscht? und 4.Bit(Maske 0x10) gesetzt? if (((type & 0x100) == 0) && ((type & 0x10) != 0)) { // Indication nur ein Sendeversuch //Console.WriteLine("Indication"); try { // Versuchen zu senden udpClient.Send(message_buffer, message_buffer.Length, remoteEndpoint); // auf Antwort warten => AUF INDICATION KOMMT KEINE ANTWORT !!! //response_buffer = udpClient.Receive(ref localEndpoint); } catch (Exception e) { Console.WriteLine(e.Message); throw e; } } else { // Request oder Response //Console.WriteLine("Request oder Response"); // RC Versuche for (int versuch = 1; versuch <= RC; versuch++) { try { // Versuchen zu senden //Console.WriteLine("Sende bei ({0} ms)", stopwatch.ElapsedMilliseconds); udpClient.Send(message_buffer, message_buffer.Length, remoteEndpoint); // auf Antwort warten response_buffer = udpClient.Receive(ref localEndpoint); // wenn Antwort erhalten springe aus Sende-Schleife break; } catch (SocketException e) { //stopwatch.Stop(); if (e.SocketErrorCode == SocketError.TimedOut) { // welcher Versuch ist gescheitert? if (versuch < RC - 1) udpClient.Client.ReceiveTimeout *= 2; // wenn vorletzter Versuch gescheitert ist => letzten Versuch mit ReceiveTimeOut = RM * RTO else if (versuch == RC - 1) udpClient.Client.ReceiveTimeout = RM * RTO; // letzter Versuch ebenfalls gescheitert else if (versuch == RC) { //stopwatch.Stop(); //Console.WriteLine("Sendevorgang nach {0} Versuchen und {1} ms abgebrochen!", RC, stopwatch.ElapsedMilliseconds); } } /* if (e.SocketErrorCode == SocketError.NetworkUnreachable) // trifft nicht ein { Console.WriteLine("unreachable"); } */ else { Console.WriteLine(e.Message); throw e; } } } } // UdpClient schließen udpClient.Close(); // Nachricht erhalten? if (response_buffer != null) { STUNMessage response = STUNMessage.Parse(response_buffer); return response; } else return null; }
private void ServerMethod() { // get Network Stream NetworkStream ns = m_client.GetStream(); while (IsSocketConnected(m_client.Client)) { // data available? if (ns.DataAvailable) { // 1. Receive STUN Message int bytesRead = 0; // read first 20 bytes (header) byte[] stunHeader = new byte[20]; int read = ns.Read(stunHeader, 0, stunHeader.Length); // parse length of message (3rd and 4th byte) ushort stunMsgLength = NetworkByteArray.ReadUInt16(stunHeader, 2); // Byte Array for request Byte[] stunRequest = new Byte[20 + stunMsgLength]; // copy header to request Array.Copy(stunHeader, 0, stunRequest, 0, stunHeader.Length); // is there more to read? if yes get the rest of the message if (stunMsgLength > 0) bytesRead = ns.Read(stunRequest, 20, stunMsgLength); // received entire message? if (bytesRead != stunMsgLength) Console.WriteLine("Error receiving Stun Message!"); // parse message STUNMessage request = STUNMessage.Parse(stunRequest); // contains Fingerprint? if (request.ContainsFingerprint()) // validate Fingerprint, in error case discard message if (!request.ValidateFingerprint()) return; // 2. Process STUN Message STUNMessage response = null; // Binding Request? if (request.StunMessageType == StunMessageType.BindingRequest) { // public Endpoint of Client IPEndPoint remoteEndPoint = (IPEndPoint)m_client.Client.RemoteEndPoint; // TransactionID of Request also for Response Byte[] reqTransID = request.TransactionID; response = new STUNMessage(StunMessageType.BindingSuccessResponse, reqTransID); // add Attributes and create message XorMappedAddressAttribute xmaa = XorMappedAddressAttribute.CreateXorMappedAddress(response.TransactionID, remoteEndPoint.Address.ToString(), (ushort)remoteEndPoint.Port); response.AddAttribute(xmaa); MappedAddressAttribute maa = MappedAddressAttribute.CreateMappedAddress(remoteEndPoint.Address.ToString(), (ushort)remoteEndPoint.Port); response.AddAttribute(maa); response.Create(); } else if (request.StunMessageType == StunMessageType.BindingIndication) { // No response is generated for an indication (RFC 5389, 7.3.2.) } byte[] stunResponse = response.ToByteArray(); ns.Write(stunResponse, 0, stunResponse.Length); ns.Flush(); } // no data available else Thread.Sleep(10); } }
private static IPEndPoint GetPublicMapping(Socket stunSocket) { STUNMessage stunBindingRequest = new STUNMessage(StunMessageType.BindingRequest); stunBindingRequest.Create(); stunSocket.Send(stunBindingRequest.ToByteArray()); // STUN Header 20 Byte byte[] stunHeader = new byte[20]; stunSocket.Receive(stunHeader, 20, SocketFlags.None); ushort stunBodyLength = NetworkByteArray.ReadUInt16(stunHeader, 2); byte[] stunBody = new byte[stunBodyLength]; stunSocket.Receive(stunBody, stunBodyLength, SocketFlags.None); byte[] stunBindResp = new byte[20 + stunBodyLength]; Array.Copy(stunHeader, 0, stunBindResp, 0, 20); Array.Copy(stunBody, 0, stunBindResp, 20, stunBodyLength); STUNMessage stunBindingResponse = STUNMessage.Parse(stunBindResp); // contains XOR Mapped Address? for (int i = 0; i < stunBindingResponse.AttributeList.Count; i++) { if (stunBindingResponse.AttributeList[i].Type == STUNAttribute.StunAttributeType.XorMappedAddress) { XorMappedAddressAttribute xmaa = (XorMappedAddressAttribute)stunBindingResponse.AttributeList[i]; return xmaa.XorMappedAddress; } } // contains Mapped Address for (int i = 0; i < stunBindingResponse.AttributeList.Count; i++) { if (stunBindingResponse.AttributeList[i].Type == STUNAttribute.StunAttributeType.MappedAddress) { MappedAddressAttribute maa = (MappedAddressAttribute)stunBindingResponse.AttributeList[i]; return maa.MappedAddress; } } // no attribute return null; }
private void OnPacketReceived(UdpReceiver receiver, int localPort, IPEndPoint remoteEndPoint, byte[] packet) { STUNMessage stunMessage = STUNMessage.ParseSTUNMessage(packet, packet.Length); switch (stunMessage.Header.MessageType) { case STUNMessageTypesEnum.Allocate: logger.LogDebug($"MockTurnServer received Allocate request from {remoteEndPoint}."); if (_relaySocket == null) { _clientEndPoint = remoteEndPoint; // Create a new relay socket. NetServices.CreateRtpSocket(false, _listenAddress, 0, out _relaySocket, out _); _relayEndPoint = _relaySocket.LocalEndPoint as IPEndPoint; logger.LogDebug($"MockTurnServer created relay socket on {_relayEndPoint}."); _relayListener = new UdpReceiver(_relaySocket); _relayListener.OnPacketReceived += OnRelayPacketReceived; _relayListener.OnClosed += (reason) => logger.LogDebug($"MockTurnServer relay on {_relayEndPoint} closed."); _relayListener.BeginReceiveFrom(); } STUNMessage allocateResponse = new STUNMessage(STUNMessageTypesEnum.AllocateSuccessResponse); allocateResponse.Header.TransactionId = stunMessage.Header.TransactionId; allocateResponse.AddXORMappedAddressAttribute(remoteEndPoint.Address, remoteEndPoint.Port); allocateResponse.AddXORAddressAttribute(STUNAttributeTypesEnum.XORRelayedAddress, _relayEndPoint.Address, _relayEndPoint.Port); _clientSocket.SendTo(allocateResponse.ToByteBuffer(null, false), remoteEndPoint); break; case STUNMessageTypesEnum.BindingRequest: logger.LogDebug($"MockTurnServer received Binding request from {remoteEndPoint}."); STUNMessage stunResponse = new STUNMessage(STUNMessageTypesEnum.BindingSuccessResponse); stunResponse.Header.TransactionId = stunMessage.Header.TransactionId; stunResponse.AddXORMappedAddressAttribute(remoteEndPoint.Address, remoteEndPoint.Port); _clientSocket.SendTo(stunResponse.ToByteBuffer(null, false), remoteEndPoint); break; case STUNMessageTypesEnum.CreatePermission: logger.LogDebug($"MockTurnServer received CreatePermission request from {remoteEndPoint}."); STUNMessage permResponse = new STUNMessage(STUNMessageTypesEnum.CreatePermissionSuccessResponse); permResponse.Header.TransactionId = stunMessage.Header.TransactionId; _clientSocket.SendTo(permResponse.ToByteBuffer(null, false), remoteEndPoint); break; case STUNMessageTypesEnum.SendIndication: logger.LogDebug($"MockTurnServer received SendIndication request from {remoteEndPoint}."); var buffer = stunMessage.Attributes.Single(x => x.AttributeType == STUNAttributeTypesEnum.Data).Value; var destEP = (stunMessage.Attributes.Single(x => x.AttributeType == STUNAttributeTypesEnum.XORPeerAddress) as STUNXORAddressAttribute).GetIPEndPoint(); logger.LogDebug($"MockTurnServer relaying {buffer.Length} bytes to {destEP}."); _relaySocket.SendTo(buffer, destEP); break; default: logger.LogDebug($"MockTurnServer received unknown STUN message from {remoteEndPoint}."); break; } }