Example #1
0
        /// <summary>
        /// Creates a new Nonce value.
        /// </summary>
        /// <param name="ClientSender">If the client is the sender (true), or the server (false).</param>
        /// <param name="State">Endpoint state.</param>
        /// <returns>New nonce value.</returns>
        protected byte[] CreateNonce(bool ClientSender, EndpointState State)
        {
            // Nonce calculation defind in RFC 5288, §3.

            byte[] Nonce = new byte[12];

            if (ClientSender)
            {
                Array.Copy(State.client_write_IV, 0, Nonce, 0, this.fixedIvLength);
            }
            else
            {
                Array.Copy(State.server_write_IV, 0, Nonce, 0, this.fixedIvLength);
            }

            ulong c   = State.nonceCount++;
            int   Pos = 12;
            int   i;

            for (i = 0; i < 8; i++)
            {
                Nonce[--Pos] = (byte)c;
                c          >>= 8;
            }

            return(Nonce);
        }
Example #2
0
        /// <summary>
        /// Verifies the claims in a finished message.
        /// </summary>
        /// <param name="VerifyData">Verify data in finished message.</param>
        /// <param name="State">Endpoint state.</param>
        /// <returns>If the <paramref name="VerifyData"/> is valid or not.</returns>
        public virtual bool VerifyFinished(byte[] VerifyData, EndpointState State)
        {
            if (State.masterSecret == null)
            {
                return(false);
            }

            string Label;

            byte[] HandshakeHash;
            byte[] VerifyData0;

            if (State.isClient)
            {
                Label = "server finished";
                State.CalcServerHandshakeHash();
                HandshakeHash = State.serverHandshakeHash;
            }
            else
            {
                Label = "client finished";
                State.CalcClientHandshakeHash();
                HandshakeHash = State.clientHandshakeHash;
            }

            VerifyData0 = this.PRF(State.masterSecret, Label, HandshakeHash, 12);

            return(DtlsEndpoint.AreEqual(VerifyData0, VerifyData));
        }
Example #3
0
        private async Task WaitForStateAsync(EndpointState state, CancellationToken cancellationToken = default)
        {
            using var signal = new SemaphoreSlim(0);
            StateChanged    += OnStateChanged;
            try
            {
                if (_stateIterator.Current == state)
                {
                    return;
                }
                await signal.WaitAsync(cancellationToken)
                .ConfigureAwait(false);
            }
            finally
            {
                StateChanged -= OnStateChanged;
            }

            void OnStateChanged(
                EndpointState changedState)
            {
                if (changedState == state)
                {
                    signal.Release();
                }
            }
        }
        protected override Task PublishStatusAsync(CallbackEvent callbackEvent)
        {
            const EndpointState endpointState = EndpointState.Disconnected;
            var command = new UpdateEndpointStatusAndRoomCommand(SourceConference.Id, SourceEndpoint.Id, endpointState, null);

            return(CommandHandler.Handle(command));
        }
Example #5
0
        /// <summary>
        /// Encrypts data according to the cipher settings.
        /// </summary>
        /// <param name="Data">Data to encrypt.</param>
        /// <param name="Header">Record header.</param>
        /// <param name="Start">Start offset of header.</param>
        /// <param name="State">Endpoint state.</param>
        /// <returns>Encrypted data.</returns>
        public override byte[] Encrypt(byte[] Data, byte[] Header, int Start, EndpointState State)
        {
            lock (this.aesCcm)
            {
                byte[] AeadCipher;
                byte[] CipherText;
                byte[] Nonce;
                byte[] AD = this.GetAssociatedData(Header, Start);

                if (State.isClient)
                {
                    Nonce      = this.CreateNonce(true, State);
                    CipherText = this.aesCcm.Encrypt(Data, AD, Nonce, State.client_write_key);
                }
                else
                {
                    Nonce      = this.CreateNonce(false, State);
                    CipherText = this.aesCcm.Encrypt(Data, AD, Nonce, State.server_write_key);
                }

                // On AEAD ciphers, see RFC 5246, §6.2.3.3

                int RecordIvLength = Nonce.Length - this.fixedIvLength;
                int N = CipherText.Length;

                AeadCipher = new byte[RecordIvLength + N];

                Array.Copy(Nonce, this.fixedIvLength, AeadCipher, 0, RecordIvLength);
                Array.Copy(CipherText, 0, AeadCipher, RecordIvLength, N);

                return(AeadCipher);
            }
        }
Example #6
0
        private void CalcMasterSecret(EndpointState State)
        {
            if (State.credentials is PresharedKey Psk)
            {
                ushort N = (ushort)Psk.Key.Length;
                byte[] PremasterSecret = new byte[4 + (N << 1)];

                PremasterSecret[0]     = (byte)(N >> 8);
                PremasterSecret[1]     = (byte)N;
                PremasterSecret[N + 2] = (byte)(N >> 8);
                PremasterSecret[N + 3] = (byte)N;

                if (N > 0)
                {
                    Array.Copy(Psk.Key, 0, PremasterSecret, N + 4, N);
                }

                // RFC 5246, §8.1, Computing the Master Secret:

                this.SetMasterSecret(this.PRF(PremasterSecret, "master secret",
                                              Concat(State.clientRandom, State.serverRandom), 48), State);

                PremasterSecret.Initialize();
            }
            else
            {
                State.masterSecret         = null;
                State.client_write_MAC_key = null;
                State.server_write_MAC_key = null;
                State.client_write_key     = null;
                State.server_write_key     = null;
                State.client_write_IV      = null;
                State.server_write_IV      = null;
            }
        }
Example #7
0
 internal EndpointStateNode(
     EndpointState state,
     IReadOnlyDictionary <EndpointState, EndpointStateNode> branches)
 {
     _branches = branches;
     State     = state;
 }
Example #8
0
        /// <summary>
        /// Sends the Client Key Exchange message flight.
        /// </summary>
        /// <param name="Endpoint">Endpoint.</param>
        /// <param name="State">Endpoint state.</param>
        public override void SendClientKeyExchange(DtlsEndpoint Endpoint, EndpointState State)
        {
            this.CalcMasterSecret(State);

            // Sends the Client Key Exchange message for Pre-shared key ciphers,
            // as defined in §2 of RFC 4279: https://tools.ietf.org/html/rfc4279

            if (State.credentials is PresharedKey Psk)
            {
                ushort N = (ushort)Psk.Identity.Length;
                byte[] ClientKeyExchange = new byte[2 + N];

                ClientKeyExchange[0] = (byte)(N >> 8);
                ClientKeyExchange[1] = (byte)N;

                Array.Copy(Psk.Identity, 0, ClientKeyExchange, 2, N);

                Endpoint.SendHandshake(HandshakeType.client_key_exchange, ClientKeyExchange, true, true, State);

                // RFC 5246, §7.1, Change Cipher Spec Protocol:

                Endpoint.SendRecord(ContentType.change_cipher_spec, new byte[] { 1 }, true, true, State);
                Endpoint.ChangeCipherSpec(State, true);

                this.SendFinished(Endpoint, State, true);
            }
        }
Example #9
0
        protected internal void _endpoint_state_cb(EndpointState msg)
        {
            lock (this)
            {
                _last_endpoint_state = _stopwatch.ElapsedMilliseconds;

                if (!msg.valid)
                {
                    _endpoint_pose = null;
                    _endpoint_vel  = null;
                    return;
                }

                var p = new Pose();
                p.orientation.w = msg.pose.orientation.w;
                p.orientation.x = msg.pose.orientation.x;
                p.orientation.y = msg.pose.orientation.y;
                p.orientation.z = msg.pose.orientation.z;
                p.position.x    = msg.pose.position.x;
                p.position.y    = msg.pose.position.y;
                p.position.z    = msg.pose.position.z;

                var v = new SpatialVelocity();
                v.angular.x = msg.twist.angular.x;
                v.angular.y = msg.twist.angular.y;
                v.angular.z = msg.twist.angular.z;
                v.linear.x  = msg.twist.linear.x;
                v.linear.y  = msg.twist.linear.y;
                v.linear.z  = msg.twist.linear.z;

                _endpoint_pose = new Pose[] { p };
                _endpoint_vel  = new SpatialVelocity[] { v };
            }
        }
        public async Task Should_update_existing_endpoint_with_new_status_and_room()
        {
            var conference1 = new ConferenceBuilder()
                              .WithEndpoint("DisplayName", "*****@*****.**").Build();
            var seededConference = await TestDataManager.SeedConference(conference1);

            var endpointId             = conference1.Endpoints.First().Id;
            const EndpointState status = EndpointState.Connected;
            const RoomType      room   = RoomType.HearingRoom;

            TestContext.WriteLine($"New seeded conference id: {seededConference.Id}");
            _newConferenceId = seededConference.Id;

            var command = new UpdateEndpointStatusAndRoomCommand(_newConferenceId, endpointId, status, room);
            await _handler.Handle(command);

            Conference updatedConference;

            await using (var db = new VideoApiDbContext(VideoBookingsDbContextOptions))
            {
                updatedConference = await db.Conferences.Include(x => x.Endpoints)
                                    .AsNoTracking().SingleOrDefaultAsync(x => x.Id == _newConferenceId);
            }
            var updatedEndpoint = updatedConference.GetEndpoints().Single(x => x.Id == endpointId);

            updatedEndpoint.State.Should().Be(status);
            updatedEndpoint.GetCurrentRoom().Should().Be(room);
        }
Example #11
0
        /// <summary>
        /// Allows the cipher to process any client key information sent by the DTLS client.
        /// </summary>
        /// <param name="Data">Binary data.</param>
        /// <param name="Offset">Offset where data begins.</param>
        /// <param name="State">Endpoint state.</param>
        /// <returns>New offset after operation.</returns>
        public override async Task <int> ClientKeyExchange(byte[] Data, int Offset, EndpointState State)
        {
            ushort N = Data[Offset++];

            N <<= 8;
            N  |= Data[Offset++];

            byte[] Identity = new byte[N];
            Array.Copy(Data, Offset, Identity, 0, N);
            Offset += N;

            string UserId = Encoding.UTF8.GetString(Identity);
            IUser  User   = await State.localEndpoint.Users.TryGetUser(UserId);

            if (!(User is null) &&
                (State.localEndpoint.RequiredPrivilege is null ||
                 User.HasPrivilege(State.localEndpoint.RequiredPrivilege)))
            {
                string s;
                byte[] Key = null;

                if (!string.IsNullOrEmpty(s = User.PasswordHash))
                {
                    Key = Hashes.StringToBinary(s);
                }

                if (Key is null)
                {
                    Key = Encoding.UTF8.GetBytes(User.PasswordHash);
                }

                State.credentials = new PresharedKey(Identity, Key);

                this.CalcMasterSecret(State);
            }
Example #12
0
        /// <summary>
        /// Sets the master secret for the session.
        /// </summary>
        /// <param name="Value">Master secret.</param>
        /// <param name="State">Endpoint state.</param>
        public virtual void SetMasterSecret(byte[] Value, EndpointState State)
        {
            State.masterSecret = Value;

            // Key calculation: RFC 5246 §6.3:

            byte[] KeyBlock = this.PRF(State.masterSecret, "key expansion",
                                       Concat(State.serverRandom, State.clientRandom),
                                       (uint)((this.macKeyLength + this.encKeyLength + this.fixedIvLength) << 1));

            int Pos = 0;

            State.client_write_MAC_key = new byte[this.macKeyLength];
            Array.Copy(KeyBlock, Pos, State.client_write_MAC_key, 0, this.macKeyLength);
            Pos += this.macKeyLength;

            State.server_write_MAC_key = new byte[this.macKeyLength];
            Array.Copy(KeyBlock, Pos, State.server_write_MAC_key, 0, this.macKeyLength);
            Pos += this.macKeyLength;

            State.client_write_key = new byte[this.encKeyLength];
            Array.Copy(KeyBlock, Pos, State.client_write_key, 0, this.encKeyLength);
            Pos += this.encKeyLength;

            State.server_write_key = new byte[this.encKeyLength];
            Array.Copy(KeyBlock, Pos, State.server_write_key, 0, this.encKeyLength);
            Pos += this.encKeyLength;

            State.client_write_IV = new byte[this.fixedIvLength];
            Array.Copy(KeyBlock, Pos, State.client_write_IV, 0, this.fixedIvLength);
            Pos += this.fixedIvLength;

            State.server_write_IV = new byte[this.fixedIvLength];
            Array.Copy(KeyBlock, Pos, State.server_write_IV, 0, this.fixedIvLength);
        }
Example #13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="type"></param>
        private void Setup(BrowserType type)
        {
            if (state != EndpointState.Idle)
            {
                throw new EndpointException("Call Endpoint::Setup from an incompatible state : " + state.ToString());
            }

            Log.Debug("Endpoint Setting up ...");
            state = EndpointState.Setup;

            browserType = type;

            stopSignal = new ManualResetEvent(false);
            stopSignal.Reset();

            requestQueueWorker = new Thread(RequestQueueJob)
            {
                IsBackground = false,
                Name         = "Endpoint::requestQueueWorker"
            };

            responseQueueWorker = new Thread(ResponseQueueJob)
            {
                IsBackground = false,
                Name         = "Endpoint::responseQueueWorker"
            };

            mainWorker = new Thread(MainJob)
            {
                IsBackground = false,
                Name         = "Endpoint::mainWorker"
            };
        }
        public void should_update_status(EndpointState newState)
        {
            var endpoint = new Endpoint("old name", "*****@*****.**", "1234", "Defence Sol");

            endpoint.State.Should().Be(EndpointState.NotYetJoined);
            endpoint.UpdateStatus(newState);
            endpoint.State.Should().Be(newState);
        }
 public UpdateEndpointStatusAndRoomCommand(Guid conferenceId, Guid endpointId, EndpointState status,
                                           RoomType?room)
 {
     ConferenceId = conferenceId;
     EndpointId   = endpointId;
     Status       = status;
     Room         = room;
 }
Example #16
0
        protected override Task PublishStatusAsync(CallbackEvent callbackEvent)
        {
            const EndpointState endpointState = EndpointState.Connected;
            const RoomType      room          = RoomType.WaitingRoom;
            var command = new UpdateEndpointStatusAndRoomCommand(SourceConference.Id, SourceEndpoint.Id, endpointState, room);

            return(CommandHandler.Handle(command));
        }
        public void Should_throw_conference_not_found_exception_when_conference_does_not_exist()
        {
            var conferenceId           = Guid.NewGuid();
            var endpointId             = Guid.NewGuid();
            const EndpointState status = EndpointState.Connected;
            var command = new UpdateEndpointStatusAndRoomCommand(conferenceId, endpointId, status, null);

            Assert.ThrowsAsync <ConferenceNotFoundException>(() => _handler.Handle(command));
        }
        public async Task ThenTheEndpointsStateShouldBe(EndpointState state)
        {
            await using var db = new VideoApiDbContext(_context.VideoBookingsDbContextOptions);
            var conf = await db.Conferences.Include(x => x.Endpoints)
                       .SingleAsync(x => x.Id == _context.Test.Conference.Id);

            var endpoint = conf.GetEndpoints().First(x => x.Id == _context.Test.ParticipantId);

            endpoint.State.Should().Be(state);
        }
        public void Should_map_user_response_to_court_rooms_account(EndpointState apiState, VHEndpointStatus expected)
        {
            var endpoint = new EndpointsResponseBuilder().WithStatus(apiState).Build();
            var result   = _sut.Map(endpoint, 1);

            result.Should().NotBeNull();
            result.DisplayName.Should().Be(endpoint.DisplayName);
            result.Id.Should().Be(endpoint.Id);
            result.Status.ToString().Should().Be(endpoint.Status.ToString());
            result.DefenceAdvocateUsername.Should().Be(endpoint.DefenceAdvocate);
            result.PexipDisplayName.Should().Be($"PSTN;{endpoint.DisplayName};{endpoint.Id}");
        }
Example #20
0
        public bool TransitionTo(EndpointState state)
        {
            var current = _current;

            if (current.TryGetNext(state, out var next))
            {
                return(Interlocked.CompareExchange(
                           ref _current, next, current) == current);
            }

            return(false);
        }
        public async Task Should_throw_exception_when_endpoint_does_not_exist()
        {
            var seededConference = await TestDataManager.SeedConference();

            var endpointId             = Guid.NewGuid();
            const EndpointState status = EndpointState.Connected;

            TestContext.WriteLine($"New seeded conference id: {seededConference.Id}");
            _newConferenceId = seededConference.Id;
            var command = new UpdateEndpointStatusAndRoomCommand(_newConferenceId, endpointId, status, null);

            Assert.ThrowsAsync <EndpointNotFoundException>(async() => await _handler.Handle(command));
        }
Example #22
0
        /// <summary>
        /// Allows the cipher to process any server key information sent by the DTLS server.
        /// </summary>
        /// <param name="Data">Binary data.</param>
        /// <param name="Offset">Offset where data begins.</param>
        /// <param name="State">Endpoint state.</param>
        public override void ServerKeyExchange(byte[] Data, ref int Offset, EndpointState State)
        {
            // RFC 4279, §2:

            ushort Len = Data[Offset++];

            Len <<= 8;
            Len  |= Data[Offset++];

            State.psk_identity_hint = new byte[Len];
            Array.Copy(Data, Offset, State.psk_identity_hint, 0, Len);
            Offset += Len;
        }
Example #23
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="request"></param>
        public void Test(Messages.Request request)
        {
            state = EndpointState.Listening;

            // All exceptions until a valid request was read
            // causes a message to be sent
            try {
                HandleRequest(request);
            } catch (Exception e) {
                SendException(e);
            }

            state = EndpointState.Idle;
        }
Example #24
0
        /// <summary>
        /// In any case, signals in main thread that an exit is requested
        /// Enters in ExitPending state and signals to the main worker
        /// that an exit is required
        /// </summary>
        public void Stop(string reason)
        {
            Log.Debug("Endpoint will exist because '{0}'", reason);

            if (state == EndpointState.Listening)
            {
                state = EndpointState.ExitPending;
                stopSignal.Set();
            }
            else if (state == EndpointState.Idle)
            {
                Environment.Exit(0);
            }
        }
        protected internal void _endpoint_state_cb(EndpointState msg, int kin_chain)
        {
            lock (this)
            {
                _last_endpoint_state = _stopwatch.ElapsedMilliseconds;

                /*if (!msg.valid)
                 * {
                 *  _endpoint_pose = null;
                 *  _endpoint_vel = null;
                 *  return;
                 * }*/

                var p = new Pose();
                p.orientation.w = msg.pose.orientation.w;
                p.orientation.x = msg.pose.orientation.x;
                p.orientation.y = msg.pose.orientation.y;
                p.orientation.z = msg.pose.orientation.z;
                p.position.x    = msg.pose.position.x;
                p.position.y    = msg.pose.position.y;
                p.position.z    = msg.pose.position.z;

                var v = new SpatialVelocity();
                v.angular.x = msg.twist.angular.x;
                v.angular.y = msg.twist.angular.y;
                v.angular.z = msg.twist.angular.z;
                v.linear.x  = msg.twist.linear.x;
                v.linear.y  = msg.twist.linear.y;
                v.linear.z  = msg.twist.linear.z;

                if (_endpoint_pose == null)
                {
                    if (_arm_selection == BaxterRobotArmSelection.both)
                    {
                        _endpoint_pose = new Pose[2];
                    }
                    else
                    {
                        _endpoint_pose = new Pose[1];
                    }
                    _endpoint_pose[kin_chain] = p;
                }

                if (_endpoint_vel == null)
                {
                    _endpoint_vel            = new SpatialVelocity[2];
                    _endpoint_vel[kin_chain] = v;
                }
            }
        }
Example #26
0
        public IOrEndpointStateBuilder Then(
            EndpointState endpointState, Action <IEndpointStateBuilder>?configure = null)
        {
            var builder = new EndpointStateBuilder(endpointState);

            configure?.Invoke(builder);
            if (_branches.TryAdd(endpointState, builder.Node) == false)
            {
                throw new ArgumentException(
                          paramName: nameof(endpointState),
                          message:
                          $"{endpointState.GetType()} state have already been declared");
            }

            return(this);
        }
Example #27
0
        /// <summary>
        /// Decrypts data according to the cipher settings.
        /// </summary>
        /// <param name="Data">Data to decrypt.</param>
        /// <param name="Header">Record header.</param>
        /// <param name="Start">Start offset of header.</param>
        /// <param name="State">Endpoint state.</param>
        /// <returns>Decrypted data, or null if authentication failed.</returns>
        public override byte[] Decrypt(byte[] Data, byte[] Header, int Start, EndpointState State)
        {
            lock (this.aesCcm)
            {
                // On AEAD ciphers, see RFC 5246, §6.2.3.3

                int    RecordIvLength = 12 - this.fixedIvLength;
                int    N          = Data.Length - RecordIvLength;
                byte[] CipherText = new byte[N];
                byte[] Nonce      = new byte[12];
                byte[] AD         = this.GetAssociatedData(Header, Start);
                byte[] PlainText;
                ushort Len;

                Len   = AD[11];
                Len <<= 8;
                Len  |= AD[12];

                Len -= (ushort)(this.t + RecordIvLength);

                AD[11] = (byte)(Len >> 8);
                AD[12] = (byte)Len;

                Array.Copy(Data, 0, Nonce, this.fixedIvLength, RecordIvLength);
                Array.Copy(Data, RecordIvLength, CipherText, 0, N);

                if (State.isClient)
                {
                    Array.Copy(State.server_write_IV, 0, Nonce, 0, this.fixedIvLength);
                    PlainText = this.aesCcm.AuthenticateAndDecrypt(CipherText, AD, Nonce,
                                                                   State.server_write_key);
                }
                else
                {
                    Array.Copy(State.client_write_IV, 0, Nonce, 0, this.fixedIvLength);
                    PlainText = this.aesCcm.AuthenticateAndDecrypt(CipherText, AD, Nonce,
                                                                   State.client_write_key);
                }

                return(PlainText);
            }
        }
Example #28
0
        /// <summary>
        /// Sets up everything and starts listenning for request
        /// </summary>
        /// <param name="type"></param>
        public void Listen(BrowserType type)
        {
            Setup(type);

            Log.Debug("Endpoint enter listenning mode for {0} ...", browserType);
            state = EndpointState.Listening;

            requestQueueWorker.Start();
            responseQueueWorker.Start();
            mainWorker.Start();

            // All workers started, waiting here for stopSignal
            stopSignal.WaitOne();

            Log.Debug("Endpoint exit listenning mode ...");
            state = EndpointState.ExitPending;

            Teardown();
            state = EndpointState.Idle;
        }
Example #29
0
        /// <summary>
        /// Finishes the handshake.
        /// </summary>
        /// <param name="Endpoint">Endpoint.</param>
        /// <param name="State">Endpoint state.</param>
        /// <param name="Resendable">If flight of records is resendable.</param>
        public virtual void SendFinished(DtlsEndpoint Endpoint, EndpointState State, bool Resendable)
        {
            if (State.masterSecret == null)
            {
                Endpoint.SendAlert(AlertLevel.fatal, AlertDescription.handshake_failure, State);
            }
            else
            {
                string Label;
                byte[] HandshakeHash;
                byte[] VerifyData;

                if (State.isClient)
                {
                    State.clientFinished = true;
                    Label = "client finished";
                    State.CalcClientHandshakeHash();
                    HandshakeHash = State.clientHandshakeHash;
                }
                else
                {
                    State.serverFinished = true;
                    Label = "server finished";
                    State.CalcServerHandshakeHash();
                    HandshakeHash = State.serverHandshakeHash;
                }

                VerifyData = this.PRF(State.masterSecret, Label, HandshakeHash, 12);

                Endpoint.SendHandshake(HandshakeType.finished, VerifyData, false, Resendable, State);

                if (State.clientFinished && State.serverFinished)
                {
                    Endpoint.HandshakeSuccess(State);
                }
            }
        }
Example #30
0
        /// <summary>
        ///
        /// </summary>
        private void Teardown()
        {
            if (state != EndpointState.ExitPending)
            {
                throw new EndpointException("Call Endpoint::Teardown from an incompatible state : " + state.ToString());
            }

            if (state == EndpointState.Teardown)
            {
                return;
            }

            Log.Debug("Endpoint Tearing down ...");
            state = EndpointState.Teardown;

            stopSignal.Close();
            stopSignal = null;

            try {
                if (mainWorker.IsAlive)
                {
                    mainWorker.Abort();
                }

                if (requestQueueWorker.IsAlive)
                {
                    requestQueueWorker.Abort();
                }

                if (responseQueueWorker.IsAlive)
                {
                    responseQueueWorker.Abort();
                }
            } finally {
                Environment.Exit(0);
            }
        }
        private void ProcessInvMessage(EndpointState endpointState, InvMessage invMessage)
        {
            DateTime utcNow = SystemTime.UtcNow;

            GetDataMessage getDataMessage = null;

            lock (lockObject)
            {
                foreach (InventoryVector vector in invMessage.Inventory)
                {
                    if (vector.Type == InventoryVectorType.MsgBlock)
                    {
                        endpointState.AdvertisedBlocks.Add(vector.Hash, utcNow);
                    }
                }
                while (endpointState.AdvertisedBlocks.Count > MaxAdvertisedBlocksPerNode)
                {
                    endpointState.AdvertisedBlocks.Remove(endpointState.AdvertisedBlocks.First().Key);
                }

                int maxBlocksToRequest = MaxConcurrentBlockRequestsPerNode - endpointState.BlockRequests.Count;
                List<BlockState> blocksToRequest = new List<BlockState>();

                if (maxBlocksToRequest > 0)
                {
                    foreach (BlockState blockState in requiredBlocks.Values)
                    {
                        if (blockState.GetPendingRequestCount() >= MaxConcurrentBlockRequestsPerBlock)
                        {
                            continue;
                        }
                        if (!endpointState.AdvertisedBlocks.ContainsKey(blockState.Hash))
                        {
                            continue;
                        }
                        //todo: there are situations when request was sent, but timed out and should be requested again
                        if (endpointState.HasPendingRequest(blockState.Hash))
                        {
                            continue;
                        }
                        blocksToRequest.Add(blockState);
                        if (blocksToRequest.Count >= maxBlocksToRequest)
                        {
                            break;
                        }
                    }
                }

                if (blocksToRequest.Any())
                {
                    InventoryVector[] inventoryVectors = blocksToRequest.Select(b => new InventoryVector(InventoryVectorType.MsgBlock, b.Hash)).ToArray();
                    getDataMessage = new GetDataMessage(inventoryVectors);

                    foreach (BlockState blockState in blocksToRequest)
                    {
                        BlockRequest blockRequest = new BlockRequest(blockState, endpointState.Endpoint, utcNow);
                        endpointState.BlockRequests.Add(blockState.Hash, blockRequest);
                        blockState.Requests.Add(blockRequest);
                    }
                }
            }

            if (getDataMessage != null)
            {
                endpointState.Endpoint.WriteMessage(getDataMessage);
            }
        }
 public SSBIEndpoint(Endpoint ep)
 {
     _name = ep.Name;
       _state = ep.EndpointState;
       _isMsgFwd = ep.Payload.ServiceBroker.IsMessageForwardingEnabled;
       _fwdSize = ep.Payload.ServiceBroker.MessageForwardingSize;
       _auth = ep.Payload.ServiceBroker.EndpointAuthenticationOrder;
       _cert = ep.Payload.ServiceBroker.Certificate;
       _encrypt = ep.Payload.ServiceBroker.EndpointEncryption;
       _alg = ep.Payload.ServiceBroker.EndpointEncryptionAlgorithm;
       _port = ep.Protocol.Tcp.ListenerPort;
       _ep = ep;
 }