1 /*
2  * Created on Dec 30, 2005
3  * Created by Alon Rohter
4  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  */
19 package org.gudy.azureus2.core3.util;
20 
21 import java.security.SecureRandom;
22 import java.util.Random;
23 
24 import org.gudy.azureus2.core3.config.COConfigurationManager;
25 
26 /**
27  *	@author MjrTom
28  *		2006/Jan/02:	added various methods, including some java.util.Random method aliases
29  */
30 
31 public class
32 RandomUtils
33 {
34 	public static final Random RANDOM = new Random( System.currentTimeMillis() );
35 
36 	public static final String INSTANCE_ID;
37 
38 	static{
39 		byte[] bytes = new byte[3];
40 
41 		RANDOM.nextBytes( bytes );
42 
43 		INSTANCE_ID = Base32.encode( bytes ).toLowerCase();
44 	}
45 
46 	public static final SecureRandom SECURE_RANDOM = new SecureRandom();
47 
48 	/**
49 	 * Generate a random array of bytes.
50 	 * @param num_to_generate number of bytes to generate
51 	 * @return random byte array
52 	 */
generateRandomBytes( int num_to_generate )53 	public static byte[] generateRandomBytes( int num_to_generate ) {
54     byte[] id = new byte[ num_to_generate ];
55     RANDOM.nextBytes( id );
56     return id;
57   }
58 
59 
60 	/**
61 	 * Generate a random string of charactors.
62 	 * @param num_to_generate number of chars to generate
63 	 * @return random char string
64 	 */
generateRandomAlphanumerics( int num_to_generate )65 	public static String generateRandomAlphanumerics( int num_to_generate ) {
66 		String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
67 
68 		StringBuffer buff = new StringBuffer( num_to_generate );
69 
70     for( int i=0; i < num_to_generate; i++ ) {
71     	int pos = (int)( RANDOM.nextDouble() * alphabet.length() );
72     	buff.append( alphabet.charAt( pos ) );
73     }
74 
75     return buff.toString();
76   }
77 
78 
79 	public static final int LISTEN_PORT_MIN = 10000;
80 	public static final int LISTEN_PORT_MAX = 65535;
81 
82 
83 	/**
84 	 * Generate a random port number for binding a network IP listening socket to.
85 	 * NOTE: Will return a valid non-privileged port number >= LISTEN_PORT_MIN and <= LISTEN_PORT_MAX.
86 	 * @return random port number
87 	 */
88 
89 	public static int
generateRandomNetworkListenPort()90 	generateRandomNetworkListenPort()
91 	{
92 		return( generateRandomNetworkListenPort( LISTEN_PORT_MIN, LISTEN_PORT_MAX ));
93 	}
94 
95 	public static int
generateRandomNetworkListenPort( int min_port, int max_port )96 	generateRandomNetworkListenPort(
97 		int		min_port,
98 		int		max_port )
99 	{
100 		if ( min_port > max_port ){
101 			int temp 	= min_port;
102 			min_port	= max_port;
103 			max_port	= temp;
104 		}
105 
106 		if ( max_port > LISTEN_PORT_MAX ){
107 
108 			max_port = LISTEN_PORT_MAX;
109 		}
110 
111 		if ( max_port < 1 ){
112 
113 			max_port = 1;
114 		}
115 
116 		if ( min_port < 1 ){
117 
118 			min_port = 1;
119 		}
120 
121 		if ( min_port > max_port ){
122 
123 			min_port = max_port;
124 		}
125 
126 			// DON'T use NetworkManager methods to get the ports here else startup can hang
127 
128 		int	existing_tcp	= COConfigurationManager.getIntParameter( "TCP.Listen.Port" );
129 		int existing_udp	= COConfigurationManager.getIntParameter( "UDP.Listen.Port" );
130 		int existing_udp2	= COConfigurationManager.getIntParameter( "UDP.NonData.Listen.Port" );
131 
132 		int port = min_port;
133 
134 		for ( int i=0;i<100;i++ ){
135 			int min 	= min_port;
136 			port 		= min + RANDOM.nextInt( max_port + 1 - min );
137 
138 				// skip magnet ports
139 
140 			if ( port >= 45100 && port <= 45110 ){
141 
142 				continue;
143 			}
144 
145 			if ( port != existing_tcp && port != existing_udp && port != existing_udp2){
146 
147 				return port;
148 			}
149 		}
150 
151 		return( port );
152 	}
153 
154 	/**
155 	 * Generates a random +1 or -1
156 	 * @return +1 or -1
157 	 */
generateRandomPlusMinus1()158 	public static int generateRandomPlusMinus1()
159 	{
160 		return RANDOM.nextBoolean() ? -1:1;
161 	}
162 
nextFloat()163 	public static float nextFloat()
164 	{
165 		return RANDOM.nextFloat();
166 	}
167 
nextBytes(byte[] bytes)168     public static void nextBytes(byte[] bytes)
169 	{
170     	RANDOM.nextBytes(bytes);
171 	}
172 
nextSecureBytes( byte[] bytes )173     public static void nextSecureBytes( byte[] bytes )
174     {
175     	SECURE_RANDOM.nextBytes( bytes );
176     }
177 
nextSecureHash()178     public static byte[] nextSecureHash()
179     {
180     	byte[] hash = new byte[20];
181 
182     	SECURE_RANDOM.nextBytes( hash );
183 
184     	return( hash );
185     }
186 
nextHash()187     public static byte[] nextHash()
188     {
189     	byte[] hash = new byte[20];
190 
191     	RANDOM.nextBytes( hash );
192 
193     	return( hash );
194     }
195 
nextInt(int n)196     public static int nextInt(int n)
197 	{
198     	return RANDOM.nextInt(n);
199 	}
200 
nextByte()201     public static byte nextByte()
202     {
203         return (byte)RANDOM.nextInt();
204     }
205 
nextInt()206     public static int nextInt()
207     {
208         return RANDOM.nextInt();
209     }
210 
nextAbsoluteInt()211     public static int nextAbsoluteInt()
212     {
213     	return(( RANDOM.nextInt() << 1 ) >>> 1 );
214     }
215 
nextLong()216     public static long nextLong()
217     {
218         return RANDOM.nextLong();
219     }
220 
nextLong( long n )221     public static long nextLong( long n )
222     {
223     	if ( n > Integer.MAX_VALUE ){
224 
225     		while( true ){
226 
227     			long rand 	= nextAbsoluteLong();
228 
229     			long res	= rand % n;
230 
231     				// deal with non-uniformity as rand not generally divisible by n
232 
233     			if ( rand - res + (n-1) >= 0 ){
234 
235     				return( res );
236     			}
237     		}
238     	}
239 
240         return((long)RANDOM.nextInt((int)n));
241     }
242 
243 
nextAbsoluteLong()244     public static long nextAbsoluteLong()
245     {
246     	return(( RANDOM.nextLong() << 1 ) >>> 1 );
247     }
248 
nextSecureAbsoluteLong()249     public static long nextSecureAbsoluteLong()
250     {
251     	while( true ){
252 
253     		long val = Math.abs( SECURE_RANDOM.nextLong());
254 
255     		if ( val >= 0 ){
256 
257     			return( val );
258     		}
259     	}
260     }
261 
262 	/**
263 	 * @return random int between 0 and max-1. e.g. param of 10 returns 0->9
264 	 */
generateRandomIntUpto(int max)265 	public static int generateRandomIntUpto(int max)
266 	{
267 		return nextInt(max);
268 	}
269 
270 	/**
271 	 * @return random int between min and max, e.g params of [5,7] returns 5,6 or 7
272 	 */
generateRandomIntBetween(int min, int max)273 	public static int generateRandomIntBetween(int min, int max)
274 	{
275 		return min +generateRandomIntUpto(max + 1 - min);
276 	}
277 }
278