| /* |
| * 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). * |
| *******************************************************************************/ |
| package gov.nist.javax.sip; |
| |
| import gov.nist.javax.sip.header.Via; |
| import gov.nist.javax.sip.message.SIPResponse; |
| |
| import java.security.MessageDigest; |
| import java.util.HashSet; |
| |
| /** |
| * 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.21 $ $Date: 2009/10/18 13:46:37 $ |
| */ |
| public class Utils implements UtilsExt { |
| |
| private static MessageDigest digester; |
| |
| 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 { |
| digester = MessageDigest.getInstance("MD5"); |
| } catch (Exception ex) { |
| throw new RuntimeException("Could not intialize Digester ", ex); |
| } |
| rand = new java.util.Random(); |
| signature = toHexString(Integer.toString(Math.abs( rand.nextInt() % 1000 )).getBytes()); |
| } |
| |
| |
| public static Utils getInstance() { |
| return instance; |
| } |
| |
| /** |
| * convert an array of bytes to an hexadecimal string |
| * |
| * @return a string |
| * @param b |
| * bytes array to convert to a hexadecimal string |
| */ |
| |
| public static String toHexString(byte b[]) { |
| int pos = 0; |
| char[] c = new char[b.length * 2]; |
| for (int i = 0; i < b.length; i++) { |
| c[pos++] = toHex[(b[i] >> 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; |
| } |
| |
| /** |
| * Generate a call identifier. This is useful when we want to generate a |
| * call identifier in advance of generating a message. |
| */ |
| public synchronized String generateCallIdentifier(String address) { |
| |
| String date = Long.toString(System.currentTimeMillis() + callIDCounter++ |
| + rand.nextLong()); |
| byte cid[] = digester.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 synchronized String generateBranchId() { |
| // |
| |
| |
| long num = rand.nextLong() + Utils.counter++ + System.currentTimeMillis(); |
| |
| byte bid[] = digester.digest(Long.toString(num).getBytes()); |
| // prepend with a magic cookie to indicate we are bis09 compatible. |
| return SIPConstants.BRANCH_MAGIC_COOKIE + Utils.toHexString(bid) + this.signature; |
| |
| |
| } |
| |
| public boolean responseBelongsToUs(SIPResponse response) { |
| Via topmostVia = response.getTopmostVia(); |
| String branch = topmostVia.getBranch(); |
| return branch != null && branch.endsWith(this.signature); |
| } |
| |
| public static String getSignature() { |
| return signature; |
| } |
| |
| public static void main(String[] args) { |
| HashSet branchIds = new HashSet(); |
| for (int b = 0; b < 100000; b++) { |
| String bid = Utils.getInstance().generateBranchId(); |
| if (branchIds.contains(bid)) { |
| throw new RuntimeException("Duplicate Branch ID"); |
| } else { |
| branchIds.add(bid); |
| } |
| } |
| System.out.println("Done!!"); |
| |
| } |
| |
| |
| |
| } |