1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2009 Mike Cumings 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Licensed under the Apache License, Version 2.0 (the "License"); 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License. 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS, 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License. 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage com.kenai.jbosh; 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.security.SecureRandom; 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.atomic.AtomicLong; 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.locks.Lock; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.locks.ReentrantLock; 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Request ID sequence generator. This generator generates a random first 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * RID and then manages the sequence from there on out. 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenfinal class RequestIDSequence { 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Maximum number of bits available for representing request IDs, according 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to the XEP-0124 spec.s 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static final int MAX_BITS = 53; 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Bits devoted to incremented values. 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static final int INCREMENT_BITS = 32; 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Minimum number of times the initial RID can be incremented before 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * exceeding the maximum. 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static final long MIN_INCREMENTS = 1L << INCREMENT_BITS; 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Max initial value. 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static final long MAX_INITIAL = (1L << MAX_BITS) - MIN_INCREMENTS; 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Max bits mask. 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static final long MASK = ~(Long.MAX_VALUE << MAX_BITS); 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Random number generator. 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static final SecureRandom RAND = new SecureRandom(); 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Internal lock. 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static final Lock LOCK = new ReentrantLock(); 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The last reqest ID used, or <= 0 if a new request ID needs to be 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * generated. 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private AtomicLong nextRequestID = new AtomicLong(); 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /////////////////////////////////////////////////////////////////////////// 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Constructors: 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Prevent direct construction. 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen RequestIDSequence() { 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nextRequestID = new AtomicLong(generateInitialValue()); 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /////////////////////////////////////////////////////////////////////////// 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Public methods: 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Calculates the next request ID value to use. This number must be 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * initialized such that it is unlikely to ever exceed 2 ^ 53, according 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to XEP-0124. 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return next request ID value 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public long getNextRID() { 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return nextRequestID.getAndIncrement(); 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /////////////////////////////////////////////////////////////////////////// 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Private methods: 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Generates an initial RID value by generating numbers until a number is 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * found which is smaller than the maximum allowed value and greater 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * than zero. 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return random initial value 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private long generateInitialValue() { 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long result; 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen LOCK.lock(); 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen do { 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = RAND.nextLong() & MASK; 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } while (result > MAX_INITIAL); 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } finally { 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen LOCK.unlock(); 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return result; 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 121