Пример #1
0
        public IEnumerable <ushort> Encode(SmartConfigContext ctx, SmartConfigArguments args)
        {
            // Data = total len(1 byte) + apPwd len(1 byte) + SSID CRC(1 byte) +
            // BSSID CRC(1 byte) + TOTAL XOR(1 byte)+ ipAddress(4 byte) + apPwd + apSsid apPwdLen <=
            // 105 at the moment

            var senderIPAddress = args.LocalAddress.GetAddressBytes();

            var passwordBytes = args.Password != null?Encoding.ASCII.GetBytes(args.Password) : Constants.EmptyBuffer;

            var ssid     = Encoding.UTF8.GetBytes(args.Ssid);
            var ssidCrc8 = Crc8.ComputeOnceOnly(ssid);

            var bssid     = args.Bssid?.GetAddressBytes() ?? Constants.EmptyBuffer;
            var bssidCrc8 = Crc8.ComputeOnceOnly(bssid);

            var totalLength = (byte)(ExtraHeaderLength + senderIPAddress.Length + passwordBytes.Length + ssid.Length);

            byte totalXor = ComputeTotalXor(senderIPAddress, passwordBytes, ssid, ssidCrc8, bssidCrc8, totalLength);

            _framesBuilder.Clear();

            this.DoEncode(totalLength, (byte)passwordBytes.Length,
                          ssidCrc8, bssidCrc8, totalXor, senderIPAddress, passwordBytes, ssid, bssid);
            return(_framesBuilder);
        }
Пример #2
0
        private async Task BroadcastSegmentForeverAsync(
            SmartConfigContext context, Segment segment, byte[] broadcastBuffer, CancellationToken token)
        {
            var segmentInterval = context.GetOption <TimeSpan>(StandardOptionNames.SegmentInterval);

            while (true)
            {
                await this.BroadcastSingleSegmentAsync(segment, broadcastBuffer, segmentInterval, token);
            }
        }
Пример #3
0
        private async Task BroadcastSegmentByTimesAsync(
            SmartConfigContext context, Segment segment, byte[] broadcastBuffer, CancellationToken token)
        {
            var segmentInterval = context.GetOption <TimeSpan>(StandardOptionNames.FrameInterval);

            for (int i = 0; i < segment.BroadcastingMaxTimes; i++)
            {
                await this.BroadcastSingleSegmentAsync(segment, broadcastBuffer, segmentInterval, token);
            }
        }
Пример #4
0
        private async Task BroadcastSegmentUntilAsync(
            SmartConfigContext context, Segment segment, byte[] broadcastBuffer, CancellationToken token)
        {
            var segmentInterval = context.GetOption <TimeSpan>(StandardOptionNames.SegmentInterval);
            var endTime         = TimeSpan.FromMilliseconds(Environment.TickCount) + segment.BroadcastingPeriod;

            while ((TimeSpan.FromMilliseconds(Environment.TickCount) <= endTime) && !token.IsCancellationRequested)
            {
                await this.BroadcastSingleSegmentAsync(segment, broadcastBuffer, segmentInterval, token);
            }
        }
Пример #5
0
        public IEnumerable <Segment> Encode(SmartConfigContext context, SmartConfigArguments args)
        {
            var guideTimeout  = context.GetOption <TimeSpan>(StandardOptionNames.GuideCodeTimeout);
            var datumTimeout  = context.GetOption <TimeSpan>(EspOptionNames.DatumPeriodTimeout);
            var frameInterval = context.GetOption <TimeSpan>(StandardOptionNames.FrameInterval);

            var datumEncoder = new EspDatumFrameEncoder();
            var segFrames    = new Segment[]
            {
                new Segment(EspWellKnownConstants.GuideCodes, frameInterval, guideTimeout),
                new Segment(datumEncoder.Encode(context, args), frameInterval, datumTimeout)
            };

            return(segFrames);
        }
Пример #6
0
        private async Task BroadcastProcedureAsync(
            SmartConfigContext context,
            IEnumerable <Segment> segments,
            byte[] broadcastBuffer,
            CancellationToken userCancelToken)
        {
            var segmentInterval = context.GetOption <TimeSpan>(StandardOptionNames.SegmentInterval);

            while (true)
            {
                userCancelToken.ThrowIfCancellationRequested();

                foreach (var segment in segments)
                {
                    userCancelToken.ThrowIfCancellationRequested();

                    if (segment.BroadcastingMaxTimes > 0)
                    {
                        await this.BroadcastSegmentByTimesAsync(context, segment, broadcastBuffer, userCancelToken);
                    }
                    else
                    {
                        var timerTask = Task.Delay(segment.BroadcastingPeriod, userCancelToken);
                        using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(userCancelToken))
                        {
                            linkedCts.CancelAfter(segment.BroadcastingPeriod);
                            try
                            {
                                await this.BroadcastSegmentForeverAsync(context, segment, broadcastBuffer, linkedCts.Token);
                            }
                            catch (OperationCanceledException ocex)
                            {
                                if (userCancelToken.IsCancellationRequested)
                                {
                                    throw ocex;
                                }
                            }
                        }
                    }
                    await Task.Delay(segmentInterval, userCancelToken);
                }

                await Task.Delay(segmentInterval, userCancelToken);
            }
        }
Пример #7
0
        private async Task ListenUntilCancelledAsync(SmartConfigContext context)
        {
            var interpreter = context.Provider.CreateDevicePacketInterpreter();

            while (true)
            {
                var result = await _listeningSocket.ReceiveAsync();

                if (result.Buffer != null && result.Buffer.Length > 0)
                {
                    var remoteAddress = result.RemoteEndPoint.Address;
                    if (interpreter.Validate(context, result.Buffer) && _reportedDeviceIPAddresses.TryAdd(remoteAddress, 0))
                    {
                        var mac = interpreter.ParseMacAddress(result.Buffer);
                        context.ReportDevice(new SmartConfigDevice(mac, remoteAddress));
                    }
                }
            }
        }
Пример #8
0
        public IEnumerable <Segment> Encode(SmartConfigContext context, SmartConfigArguments args)
        {
            var frameInterval = context.GetOption <TimeSpan>(StandardOptionNames.FrameInterval);

            var builder = new List <Segment>(128);

            var ssid     = Encoding.UTF8.GetBytes(args.Ssid);
            var ssidCrc8 = Crc8.ComputeOnceOnly(ssid);
            var password = args.Password != null?Encoding.UTF8.GetBytes(args.Password) : Constants.EmptyBuffer;

            // Guide Segment
            var guidePeriod = context.GetOption <TimeSpan>(StandardOptionNames.GuideCodeTimeout);

            builder.Add(new Segment(AirkissWellknownConstants.GuideCodes, frameInterval, guidePeriod));

            // Magic Code Segment
            var magicCodeFrames  = AirkissMagicCodeFrameEncoder.Encode(password.Length + ssid.Length + 1, ssidCrc8);
            var magicCodeTimeout = context.GetOption <TimeSpan>(AirkissOptionNames.MagicCodeTimeout);

            builder.Add(new Segment(magicCodeFrames, frameInterval, magicCodeTimeout));

            // Prefix Code Segment
            var prefixCodeFrames  = AirkissPrefixCodeFrameEncoder.Encode(password.Length);
            var prefixCodeTimeout = context.GetOption <TimeSpan>(AirkissOptionNames.PrefixCodeTimeout);

            builder.Add(new Segment(prefixCodeFrames, frameInterval, prefixCodeTimeout));

            // Data(password/random/ssid) Segment
            var randValue  = context.GetOption <byte>(AirkissOptionNames.RandomNumber);
            var buf        = password.Append <byte>(randValue).Concat(ssid).ToList();
            var dataFrames = new List <ushort>(buf.Count * 2);
            var index      = 0;

            foreach (var bytes in buf.Partition(4))
            {
                var seqEntryFrames = AirkissSeqEntryFrameEncoder.Encode(index, bytes);
                dataFrames.AddRange(seqEntryFrames);
                index++;
            }
            builder.Add(new Segment(dataFrames, frameInterval, TimeSpan.FromSeconds(4)));

            return(builder);
        }
Пример #9
0
        public async Task ListenAsync(
            SmartConfigContext context, IPAddress localAddress, CancellationToken cancelToken)
        {
            if (_isStarted)
            {
                throw new InvalidOperationException("Already started.");
            }

            _isStarted = true;
            try
            {
                this.SetupSocket(context, localAddress);
                _reportedDeviceIPAddresses.Clear();
                await this.ListenUntilCancelledAsync(context).WithCancellation(cancelToken);
            }
            finally
            {
                _isStarted = false;
            }
        }
Пример #10
0
        public async Task BroadcastAsync(SmartConfigContext context, SmartConfigArguments args, CancellationToken cancelToken)
        {
            if (_isStarted)
            {
                throw new InvalidOperationException("Already started");
            }

            try
            {
                _broadcastTarget = new IPEndPoint(IPAddress.Broadcast, context.GetOption <int>(StandardOptionNames.BroadcastingTargetPort));
                var encoder         = context.Provider.CreateProcedureEncoder();
                var segments        = encoder.Encode(context, args);
                var broadcastBuffer = this.CreateBroadcastBuffer(segments.SelectMany(x => x.Frames));

                await this.BroadcastProcedureAsync(context, segments, broadcastBuffer, cancelToken);
            }
            finally
            {
                _isStarted = false;
            }
        }
Пример #11
0
        private async Task BroadcastProcedureAsync(
            SmartConfigContext context,
            IEnumerable <Segment> segments,
            byte[] broadcastBuffer,
            CancellationToken userCancelToken)
        {
            var segmentInterval = context.GetOption <TimeSpan>(StandardOptionNames.SegmentInterval);

            while (true)
            {
                userCancelToken.ThrowIfCancellationRequested();

                foreach (var segment in segments)
                {
                    userCancelToken.ThrowIfCancellationRequested();

                    if (segment.BroadcastingMaxTimes > 0)
                    {
                        await this.BroadcastSegmentByTimesAsync(context, segment, broadcastBuffer, userCancelToken);
                    }
                    else
                    {
                        await this.BroadcastSegmentUntilAsync(
                            context, segment, broadcastBuffer, userCancelToken);
                    }
                    if (segmentInterval > TimeSpan.Zero)
                    {
                        await Task.Delay(segmentInterval, userCancelToken);
                    }
                }

                if (segmentInterval > TimeSpan.Zero)
                {
                    await Task.Delay(segmentInterval, userCancelToken);
                }
            }
        }
Пример #12
0
        public bool Validate(SmartConfigContext context, byte[] packet)
        {
            var randomValue = context.GetOption <byte>(AirkissOptionNames.RandomNumber);

            return(packet.Length == AirkissWellknownConstants.DevicePacketLength && packet[0] == randomValue);
        }
Пример #13
0
        private void SetupSocket(SmartConfigContext context, IPAddress localAddress)
        {
            var listeningPort = context.GetOption <int>(StandardOptionNames.ListeningPort);

            _listeningSocket.Bind(new IPEndPoint(localAddress, listeningPort));
        }
Пример #14
0
 public bool Validate(SmartConfigContext context, byte[] packet)
 {
     return(packet.Length == EspWellKnownConstants.EspDevicePacketLength && packet[0] == EspWellKnownConstants.EspDevicePacketMagic);
 }