Пример #1
0
 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;
 }
Пример #2
0
 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;
 }
Пример #3
0
        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;

        }
Пример #4
0
 public STUNRequestResponse(STUNMessage requestmessage)
 {
     RequestMessage = requestmessage;
 }
Пример #5
0
        private static STUNMessage FormSTUNIndication(String Software)
        {
            STUNMessage stunIndicationRequest = new STUNMessage(StunMessageType.BindingIndication);
            SoftwareAttribute software = SoftwareAttribute.CreateSoftware(Software);
            stunIndicationRequest.AddAttribute(software);
            stunIndicationRequest.Create();

            return stunIndicationRequest;
        }
Пример #6
0
        // 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;
        }
Пример #7
0
        // 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;
        }
Пример #8
0
        private static STUNMessage FormSTUNIndication()
        {
            STUNMessage stunIndicationRequest = new STUNMessage(StunMessageType.BindingIndication);
            stunIndicationRequest.Create();

            return stunIndicationRequest;
        }
Пример #9
0
        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;

            }

        }
Пример #10
0
        // 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;

        }
Пример #11
0
            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);
                }

            }
Пример #12
0
        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;
        }
Пример #13
0
        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;
            }
        }