gov.nist.javax.sip.Utils Maven / Gradle / Ivy
The newest version!
/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
*
*/
/*******************************************************************************
* Product of NIST/ITL Advanced Networking Technologies Division (ANTD). *
*******************************************************************************/
/*
* Contributions and bug fixes by Vladimir Ralev
*/
package android.gov.nist.javax.sip;
import android.gov.nist.javax.sip.header.Via;
import android.gov.nist.javax.sip.message.SIPResponse;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* A few utilities that are used in various places by the stack. This is used to
* convert byte arrays to hex strings etc. Generate tags and branch identifiers
* and odds and ends.
*
* @author mranga
* @version 1.2 $Revision: 1.24 $ $Date: 2010-10-28 03:20:31 $
*/
public class Utils implements UtilsExt {
private static int digesterPoolsSize = 20;
private static MessageDigest[] digesterPool = new MessageDigest[digesterPoolsSize];
private static java.util.Random rand;
private static long counter = 0;
private static int callIDCounter;
private static String signature ;
private static Utils instance = new Utils();
/**
* to hex converter
*/
private static final char[] toHex = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
static {
try {
for(int q=0; q> 4) & 0x0F];
c[pos++] = toHex[b[i] & 0x0f];
}
return new String(c);
}
/**
* Put quotes around a string and return it.
* Any " characters appearing in str are escaped
*
* @return a quoted string
* @param str
* string to be quoted
*/
public static String getQuotedString(String str) {
return '"' + str.replace( "\"", "\\\"" ) + '"';
}
/**
* Squeeze out all white space from a string and return the reduced string.
*
* @param input
* input string to sqeeze.
* @return String a reduced string.
*/
protected static String reduceString(String input) {
String newString = input.toLowerCase();
int len = newString.length();
String retval = "";
for (int i = 0; i < len; i++) {
if (newString.charAt(i) == ' ' || newString.charAt(i) == '\t')
continue;
else
retval += newString.charAt(i);
}
return retval;
}
/**
* Converts the characters in this String to upper case.
* @param str the String to convert. Using english as default
* as header strings are in English.
* Resolves a bug in parsing and uppercase when default locale is set
* to Turkish.
* @return the String, converted to uppercase.
*/
public static String toUpperCase(String str)
{
return str.toUpperCase(Locale.ENGLISH);
}
/**
* Generate a call identifier. This is useful when we want to generate a
* call identifier in advance of generating a message.
*/
public String generateCallIdentifier(String address) {
long random = rand.nextLong();
int hash = (int) Math.abs(random%digesterPoolsSize);
MessageDigest md = digesterPool[hash];
synchronized (md) {
String date = Long.toString(System.nanoTime() + System.currentTimeMillis() + callIDCounter++
+ random);
byte cid[] = md.digest(date.getBytes());
String cidString = Utils.toHexString(cid);
return cidString + "@" + address;
}
}
/**
* Generate a tag for a FROM header or TO header. Just return a random 4
* digit integer (should be enough to avoid any clashes!) Tags only need to
* be unique within a call.
*
* @return a string that can be used as a tag parameter.
*
* synchronized: needed for access to 'rand', else risk to generate same tag
* twice
*/
public synchronized String generateTag() {
return Integer.toHexString(rand.nextInt());
}
/**
* Generate a cryptographically random identifier that can be used to
* generate a branch identifier.
*
* @return a cryptographically random gloablly unique string that can be
* used as a branch identifier.
*/
public String generateBranchId() {
//
long num = rand.nextLong() + Utils.counter++ + System.currentTimeMillis() + System.nanoTime();
int hash = (int) Math.abs(num%digesterPoolsSize);
MessageDigest digester = digesterPool[hash];
synchronized(digester) {
byte bid[] = digester.digest(Long.toString(num).getBytes());
// prepend with a magic cookie to indicate we are bis09 compatible.
return SIPConstants.BRANCH_MAGIC_COOKIE + "-"
+ this.signature + "-" + Utils.toHexString(bid);
}
}
public boolean responseBelongsToUs(SIPResponse response) {
Via topmostVia = response.getTopmostVia();
String branch = topmostVia.getBranch();
return branch != null && branch.startsWith(
SIPConstants.BRANCH_MAGIC_COOKIE + "-" + this.signature);
}
public static String getSignature() {
return signature;
}
public static void main(String[] args) {
final HashSet branchIds = new HashSet();
Executor e = Executors.newFixedThreadPool(100);
for(int q=0; q<100; q++) {
e.execute(new Runnable() {
public void run() {
for (int b = 0; b < 1000000; b++) {
String bid = Utils.getInstance().generateBranchId();
if (branchIds.contains(bid)) {
throw new RuntimeException("Duplicate Branch ID");
} else {
branchIds.add(bid);
}
}
}
});
}
System.out.println("Done!!");
}
}