public ErrorCodes Authorize(SipMessageReader reader, ArraySegment <byte> content, AuthenticationKind kind)
        {
            //if (state.Message.Reader.Count.AuthorizationCount > 0)
            //	return ErrorCodes.NoResponse;

            // User-Agent: X-Lite release 1104o stamp 56125
            // It use old Authorization header from INVITE request to ACK request:
            //  1. Do NOT increment nc
            //  2. Uses INVITE method for response calculation
            // User-Agent: 3CXPhone 5.0.14900.0
            // Look like X-Lite clone -> disable auth for all ACK
            if (reader.CSeq.Method == Methods.Ackm)             // && reader.UserAgent.IsXLite)
            {
                return(ErrorCodes.Ok);
            }

            IAccount account;
            var      credentials = FindCredentials(reader, out account);

            // User-Agent: NCH Software Express Talk 4.15
            // Quotes message-qop value, qop="auth"
            //if (credentials.MessageQop.IsInvalid && reader.UserAgent.IsNch)
            //    credentials.MessageQop = ResponseCalculator.Auth;

            if (credentials.AuthScheme != AuthSchemes.Digest)
            {
                return(ErrorCodes.NoResponse);
            }

            if (credentials.AuthAlgorithm == AuthAlgorithms.Other)
            {
                return(ErrorCodes.NotSupportedAuthAlgorithm);
            }

            if (credentials.Username.IsInvalid)
            {
                return(ErrorCodes.UsernmaeNotFound);
            }

            if (credentials.Username.Equals(reader.From.AddrSpec.User) == false)
            {
                return(ErrorCodes.UsernamesNotMatch);
            }

            if (credentials.Realm.IsInvalid)
            {
                return(ErrorCodes.RealmNotFound);
            }

            if (credentials.Nonce.IsInvalid)
            {
                return(ErrorCodes.NonceNotFound);
            }

            if (credentials.MessageQop.IsValid)
            {
                if (credentials.Cnonce.IsInvalid)
                {
                    return(ErrorCodes.CnonceNotFound);
                }
            }

            if (credentials.DigestUri.IsInvalid)
            {
                return(ErrorCodes.DigestUriNotFound);
            }

            if (credentials.Response.IsInvalid)
            {
                return(ErrorCodes.ResponseNotFound);
            }

            //if (credentials.Realm.Equals(realm1) == false)
            //	return ErrorCodes.InvalidRealm;

            if (credentials.Nonce.Length != 32)
            {
                return(ErrorCodes.NonceInvalid);
            }

            Nonce nonce;

            if (Nonce.TryParse(credentials.Nonce.Bytes, credentials.Nonce.Begin, out nonce) == false)
            {
                return(ErrorCodes.FailedToParseNonce);
            }

            int opaque = nonce.DecodeOpaque();

            AuthState state;

            if (authStates.TryGetValue(opaque, out state) == false)
            {
                return(ErrorCodes.AuthStateNotFound);
            }

            if (state.Nonce.IsEqualValue(nonce) == false)
            {
                return(ErrorCodes.NonceStale);
            }

            if (state.NonceCount >= credentials.NonceCount && state.IsNonceCountExpected)
            {
                return(ErrorCodes.NonceCountExpected);
            }

            var password = GetPassword(account.Id, credentials.Username);

            if (password == null)
            {
                return(ErrorCodes.FailedToRetriveUserPassword);
            }

            if (responseCalculator == null)
            {
                responseCalculator = new ResponseCalculator();
            }
            //var responseCalculator = base.GetResponseCalculator();

            if (reader.Method == Methods.Extension || reader.Method == Methods.None)             // нужно исправить!!!!!!!!!!!!!!!!!!!
            {
                return(ErrorCodes.NotSupportedAuthAlgorithm);
            }

            //if (responseCalculator.IsResponseValid(credentials, reader.Method.ToByteArrayPart(), content, password.ToByteArrayPart()) == false)
            //    return ErrorCodes.WrongResponse;

            var response = responseCalculator.GetResponseHexChars(
                credentials.Username,
                credentials.Realm,
                credentials.AuthAlgorithm == AuthAlgorithms.Md5Sess,
                credentials.Nonce,
                credentials.Cnonce,
                credentials.MessageQop,
                credentials.DigestUri,
                credentials.NonceCountBytes,
                reader.Method.ToByteArrayPart(),
                content,
                password.ToByteArrayPart());

            if (credentials.Response.Equals(response) == false)
            {
                return(ErrorCodes.WrongResponse);
            }

            state.NonceCount = credentials.NonceCount;
            state.LastAccess = unchecked (Environment.TickCount - 10000);
            authStates.Replace(state.Opaque, state);

            return(ErrorCodes.Ok);
        }
        public ErrorCodes IsAuthorizedInternal(ISheduler sheduler, ShedulerState shedulerState, AuthenticationKind kind)
        {
            var reader  = shedulerState.Reader;
            var content = shedulerState.Content;

            IAccount account;
            var      credentials = FindCredentials(reader, out account);

            if (credentials.AuthScheme != AuthSchemes.Digest)
            {
                return(ErrorCodes.NoResponse);
            }

            if (credentials.AuthAlgorithm == AuthAlgorithms.Other)
            {
                return(ErrorCodes.NotSupportedAuthAlgorithm);
            }

            if (credentials.Realm.IsInvalid)
            {
                return(ErrorCodes.RealmNotFound);
            }

            if (credentials.Realm.Equals(shedulerState.Realm) == false)
            {
                return(ErrorCodes.InvalidRealm);
            }

            if (credentials.Nonce.IsInvalid)
            {
                return(ErrorCodes.NonceNotFound);
            }

            if (credentials.MessageQop.IsValid)
            {
                if (credentials.Cnonce.IsInvalid)
                {
                    return(ErrorCodes.CnonceNotFound);
                }
            }

            if (credentials.DigestUri.IsInvalid)
            {
                return(ErrorCodes.DigestUriNotFound);
            }

            if (credentials.Response.IsInvalid)
            {
                return(ErrorCodes.ResponseNotFound);
            }

            if (credentials.Nonce.Length != 32)
            {
                return(ErrorCodes.NonceInvalid);
            }

            if (credentials.Username.IsInvalid)
            {
                return(ErrorCodes.UsernmaeNotFound);
            }

            if (sheduler.ValidateAuthorization(reader, credentials.Username, shedulerState.Param) == false)
            {
                return(ErrorCodes.NotAuthorized);
            }

            Nonce nonce;

            if (Nonce.TryParse(credentials.Nonce.Bytes, credentials.Nonce.Begin, out nonce) == false)
            {
                return(ErrorCodes.FailedToParseNonce);
            }

            int opaque = nonce.DecodeOpaque();

            AuthState state;

            if (authStates.TryGetValue(opaque, out state) == false)
            {
                return(ErrorCodes.AuthStateNotFound);
            }

            if (state.Nonce.IsEqualValue(nonce) == false)
            {
                return(ErrorCodes.NonceStale);
            }

            if (state.NonceCount >= credentials.NonceCount && state.IsNonceCountExpected)
            {
                return(ErrorCodes.NonceCountExpected);
            }

            var password = GetPassword(account.Id, credentials.Username);

            if (password == null)
            {
                return(ErrorCodes.FailedToRetriveUserPassword);
            }

            if (responseCalculator == null)
            {
                responseCalculator = new ResponseCalculator();
            }

            var response = responseCalculator.GetResponseHexChars(
                credentials.Username,
                credentials.Realm,
                credentials.AuthAlgorithm == AuthAlgorithms.Md5Sess,
                credentials.Nonce,
                credentials.Cnonce,
                credentials.MessageQop,
                credentials.DigestUri,
                credentials.NonceCountBytes,
                reader.MethodBytes,
                content,
                new ByteArrayPart(password));

            if (credentials.Response.Equals(response) == false)
            {
                return(ErrorCodes.WrongResponse);
            }

            state.NonceCount = credentials.NonceCount;
            state.LastAccess = unchecked (Environment.TickCount - 10000);
            authStates.Replace(state.Opaque, state);

            return(ErrorCodes.Ok);
        }