Example #1
0
        public void RequestAllocate()
        {
            if (++turnAllocateCount > 2)
            {
                return;
            }

            MessageSTUN message = CreateMessageSTUN(STUNMethod.AllocateRequest);

            //message.WriteString(STUNAttribute.ServerName, "Coturn-4.5.1.1 'dan Eider'");

            message.WriteString(STUNAttribute.Username, message.username);
            message.WriteString(STUNAttribute.Realm, message.realm);
            //message.WriteString(STUNAttribute.Password, message.password);

            message.WriteUInt(STUNAttribute.Lifetime, lifeTime);
            message.WriteEmpty(STUNAttribute.DontFragment);
            message.WriteUInt(STUNAttribute.RequestedTransport, (uint)(17 << 24));//(uint)(17 << 24)

            if (nonce != null)
            {
                message.WriteBytes(STUNAttribute.Nonce, nonce);
                message.WriteRequestIntegrity();
            }

            byte[] pkg = message.WriteRequest();
            sender.Send(pkg);
        }
Example #2
0
        public string GetAttributeKeys(MessageSTUN message)
        {
            string attrKeys = "";

            foreach (KeyValuePair <STUNAttribute, object> entry in message.response)
            {
                string key = Enum.GetName(typeof(STUNAttribute), entry.Key);
                int    id  = (int)entry.Key;
                if (attrKeys.Length > 0)
                {
                    attrKeys += "\n";
                }
                object value    = entry.Value;
                string valueStr = "";
                if (value is string v)
                {
                    valueStr = v;
                }
                else if (value is byte[] b)
                {
                    valueStr = NetworkSerializer.ByteArrayToHexString(b);
                }
                else
                {
                    valueStr = value.ToString();
                }
                attrKeys += key + "(" + id.ToString("X") + ") = " + valueStr;
            }
            return(attrKeys);
        }
Example #3
0
        private byte[] AddIndicationHeader(STUNAddress stunAddress, byte[] data)
        {
            // send indication
            MessageSTUN message = CreateMessageSTUN(STUNMethod.DataIndication);

            byte[] ret;
            if (stunAddress.IsIPv4)
            {
                ret    = new byte[8];
                ret[1] = (byte)(0x01); // family
            }
            else
            {
                ret    = new byte[16];
                ret[1] = (byte)(0x02); // family
            }
            ret[0] = (byte)(0x0);

            ret[3]  = (byte)(stunAddress.port & 0xff);
            ret[2]  = (byte)((stunAddress.port >> 8) & 0xff);
            ret[2] ^= transactionID[0];
            ret[3] ^= transactionID[1];

            for (int i = 0; i < stunAddress.address.Length; i++)
            {
                ret[4 + i] = (byte)(stunAddress.address[i] ^ transactionID[i]);
            }

            message.WriteBytes(STUNAttribute.XorPeerAddress, ret);
            message.WriteEmpty(STUNAttribute.DontFragment);
            message.WriteBytes(STUNAttribute.Data, data);
            return(message.WriteRequest());
        }
Example #4
0
        public void RequestChannelBind(STUNAddress stunAddress)
        {
            lock (_lock)
            {
                MessageSTUN message = CreateMessageSTUN(STUNMethod.ChannelBindRequest);
                // channel number [0x4000 through 0x4FFF](uint)random.Next(0x4001, 0x4FFF);
                uint channelNumber;
                if (!ip2ChannelNumber.ContainsKey(stunAddress.ToString()))
                {
                    GenerateChannelNumberForPeer(stunAddress);
                }
                channelNumber = ip2ChannelNumber[stunAddress.ToString()];
                Console.WriteLine("RequestChannelBind: {0} {1}:{2}", channelNumber, stunAddress.ToString(), stunAddress.port);
                channelNumber = (uint)(channelNumber << 16);
                message.WriteString(STUNAttribute.Username, message.username);
                message.WriteString(STUNAttribute.Realm, message.realm);

                message.WriteUInt(STUNAttribute.ChannelNumber, channelNumber);

                byte[] ret;
                if (stunAddress.IsIPv4)
                {
                    ret    = new byte[8];
                    ret[1] = (byte)(0x01); // family
                }
                else
                {
                    ret    = new byte[16];
                    ret[1] = (byte)(0x02); // family
                }
                ret[0] = (byte)(0x0);

                ret[3]  = (byte)(stunAddress.port & 0xff);
                ret[2]  = (byte)((stunAddress.port >> 8) & 0xff);
                ret[2] ^= transactionID[0];
                ret[3] ^= transactionID[1];

                for (int i = 0; i < stunAddress.address.Length; i++)
                {
                    ret[4 + i] = (byte)(stunAddress.address[i] ^ transactionID[i]);
                }

                message.WriteBytes(STUNAttribute.XorPeerAddress, ret);
                if (nonce != null)
                {
                    message.WriteBytes(STUNAttribute.Nonce, nonce);
                    message.WriteRequestIntegrity();
                }
                byte[] pkg = message.WriteRequest();
                sender.Send(pkg);
            }
        }
Example #5
0
        public virtual void OnAllocateResponse(MessageSTUN message)
        {
            lock (_lock)
            {
                ip2ChannelNumber.Clear();
                channelNumber2Peer.Clear();
            }
            GenerateChannelNumberForAllPeers();
            RequestRefreshAllBindingChannelLifeTime();
            StartRefreshTimer();
            StartCheckingConnectionTimer();

            STUNAddress sa = (STUNAddress)message.Get(STUNAttribute.XorRelayedAddress);

            //OnServerDataReceived?.BeginInvoke(this, new STUN_ServerDataReceivedEventArgs((int)responseChannelNumber, new ArraySegment<byte>(appData)), EndAsyncEvent, null);
            OnAllocateResponseEvent?.Invoke(this, new NATP_SignalingEventArgs(true, "", new IPEndPoint(new IPAddress(sa.address), sa.port)));
        }
Example #6
0
        public void RequestRefreshAllocationeLifeTime(uint lifetime)
        {
            MessageSTUN message = CreateMessageSTUN(STUNMethod.RefreshRequest);

            message.WriteString(STUNAttribute.Username, message.username);
            message.WriteString(STUNAttribute.Realm, message.realm);
            message.WriteUInt(STUNAttribute.Lifetime, lifetime);
            //message.WriteUInt(STUNAttribute.RequestedTransport, (uint)(17 << 24));

            if (nonce != null)
            {
                message.WriteBytes(STUNAttribute.Nonce, nonce);
                message.WriteRequestIntegrity();
            }

            byte[] pkg = message.WriteRequest();
            sender.Send(pkg);
        }
Example #7
0
        public void RequestCreatePermission(STUNAddress stunAddress)
        {
            lock (_lock)
            {
                MessageSTUN message = CreateMessageSTUN(STUNMethod.CreatePermissionRequest);
                message.WriteString(STUNAttribute.Username, message.username);
                message.WriteString(STUNAttribute.Realm, message.realm);

                byte[] ret;
                if (stunAddress.IsIPv4)
                {
                    ret    = new byte[8];
                    ret[1] = (byte)(0x01); // family
                }
                else
                {
                    ret    = new byte[16];
                    ret[1] = (byte)(0x02); // family
                }
                ret[0] = (byte)(0x0);
                ushort xorFlag16 = (ushort)(magicCookie >> 16);

                ret[3]  = 0;
                ret[2]  = 0;
                ret[2] ^= transactionID[0];
                ret[3] ^= transactionID[1];

                for (int i = 0; i < stunAddress.address.Length; i++)
                {
                    ret[4 + i] = (byte)(stunAddress.address[i] ^ transactionID[i]);
                }

                message.WriteBytes(STUNAttribute.XorPeerAddress, ret);
                if (nonce != null)
                {
                    message.WriteBytes(STUNAttribute.Nonce, nonce);
                    message.WriteRequestIntegrity();
                }
                byte[] pkg = message.WriteRequest();
                sender.Send(pkg);
            }
        }
Example #8
0
 public virtual void OnChannelBindError(MessageSTUN message)
 {
     Start();
 }
Example #9
0
 public virtual void OnAllocateError(MessageSTUN message)
 {
     RequestAllocate();
 }
Example #10
0
 public virtual void OnCreatePermissionResponse(MessageSTUN message)
 {
 }
Example #11
0
 public virtual void OnRefreshErrorResponse(MessageSTUN message)
 {
     RequestRefreshAllocationeLifeTime(this.lifeTime);
     RequestRefreshAllBindingChannelLifeTime();
     StartRefreshTimer();
 }
Example #12
0
 public virtual void OnRefreshResponse(MessageSTUN message)
 {
     OnRefreshLifeTimeResponseEvent?.Invoke();
 }
Example #13
0
 public virtual void OnChannelBindResponse(MessageSTUN message)
 {
 }
Example #14
0
 public virtual void OnBindingResponse(MessageSTUN message)
 {
 }
Example #15
0
        public virtual void OnResponse(byte[] buffer, long offset, long size)
        {
            byte[]      appData;
            MessageSTUN message = new MessageSTUN(buffer, offset, size, out appData);

            if (!message.IsSTUNMessage) // Normal Data Received
            {
                string ip;
                uint   responseChannelNumber;
                if (message.isIndicateData) // sender's ip and channel bind's ip are same, but port are different, so stun server send indicate data
                {
                    if (!autoUpdatePort)
                    {
                        // deal with it
                        return;
                    }

                    if (ChannelNumberMode)
                    {
                        AddPeer(message.indicateAddress);
                        RequestChannelBind(message.indicateAddress);
                        return;
                    }
                    else
                    {
                        ip = message.indicateAddress.ToString();
                        if (!ip2ChannelNumber.ContainsKey(ip))
                        {
                            AddPeer(message.indicateAddress);
                            return;
                        }
                    }
                    responseChannelNumber = ip2ChannelNumber[ip];
                }
                else
                {
                    responseChannelNumber = message.responseChannelNumber;
                }

                if (IsClientHeartbeat(appData))
                {
                    SendHeartBeatToClient(responseChannelNumber);
                }
                else if (IsClientDisconnectHeartbeat(appData))
                {
                    lock (_lockHeartbeat)
                    {
                        peerHeartbeat.Remove(responseChannelNumber);
                    }
                    DisconnectClient(responseChannelNumber);
                }
                else
                {
                    OnServerDataReceived?.Invoke(this, new NATP_STUN_ServerDataReceivedEventArgs((int)responseChannelNumber, new ArraySegment <byte>(appData)));
                    //OnServerDataReceived?.BeginInvoke(this, new STUN_ServerDataReceivedEventArgs((int)responseChannelNumber, new ArraySegment<byte>(appData)), EndAsyncEvent, null);
                }
            }
            else // Is STUN Server response
            {
                var newNonce = (byte[])message.Get(STUNAttribute.Nonce);
                if (newNonce != null)
                {
                    nonce = newNonce;
                }
                switch (message.method)
                {
                case STUNMethod.AllocateResponse:
                    OnAllocateResponse(message);
                    break;

                case STUNMethod.BindingResponse:
                    OnBindingResponse(message);
                    break;

                case STUNMethod.ChannelBindError:
                    OnChannelBindError(message);
                    break;

                case STUNMethod.ChannelBindResponse:
                    OnChannelBindResponse(message);
                    break;

                case STUNMethod.AllocateError:
                    OnAllocateError(message);
                    break;

                case STUNMethod.RefreshResponse:
                    OnRefreshResponse(message);
                    break;

                case STUNMethod.RefereshError:
                    OnRefreshErrorResponse(message);
                    break;

                case STUNMethod.CreatePermissionResponse:
                    OnCreatePermissionResponse(message);
                    break;
                }
            }
        }