Home | History | Annotate | Download | only in sip
      1 /*
      2  * Conditions Of Use
      3  *
      4  * This software was developed by employees of the National Institute of
      5  * Standards and Technology (NIST), an agency of the Federal Government.
      6  * Pursuant to title 15 Untied States Code Section 105, works of NIST
      7  * employees are not subject to copyright protection in the United States
      8  * and are considered to be in the public domain.  As a result, a formal
      9  * license is not needed to use the software.
     10  *
     11  * This software is provided by NIST as a service and is expressly
     12  * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
     13  * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
     14  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
     15  * AND DATA ACCURACY.  NIST does not warrant or make any representations
     16  * regarding the use of the software or the results thereof, including but
     17  * not limited to the correctness, accuracy, reliability or usefulness of
     18  * the software.
     19  *
     20  * Permission to use this software is contingent upon your acceptance
     21  * of the terms of this agreement
     22  *
     23  * .
     24  *
     25  */
     26 /*******************************************************************************
     27  * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).       *
     28  *******************************************************************************/
     29 package gov.nist.javax.sip;
     30 
     31 import gov.nist.javax.sip.header.Via;
     32 import gov.nist.javax.sip.message.SIPResponse;
     33 
     34 import java.security.MessageDigest;
     35 import java.util.HashSet;
     36 
     37 /**
     38  * A few utilities that are used in various places by the stack. This is used to
     39  * convert byte arrays to hex strings etc. Generate tags and branch identifiers
     40  * and odds and ends.
     41  *
     42  * @author mranga
     43  * @version 1.2 $Revision: 1.21 $ $Date: 2009/10/18 13:46:37 $
     44  */
     45 public class Utils implements UtilsExt {
     46 
     47     private static MessageDigest digester;
     48 
     49     private static java.util.Random rand;
     50 
     51     private static long counter = 0;
     52 
     53     private static int callIDCounter;
     54 
     55     private static String signature ;
     56 
     57     private static Utils instance = new Utils();
     58 
     59 
     60     /**
     61      * to hex converter
     62      */
     63     private static final char[] toHex = { '0', '1', '2', '3', '4', '5', '6',
     64             '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
     65 
     66     static {
     67         try {
     68             digester = MessageDigest.getInstance("MD5");
     69         } catch (Exception ex) {
     70             throw new RuntimeException("Could not intialize Digester ", ex);
     71         }
     72         rand = new java.util.Random();
     73         signature = toHexString(Integer.toString(Math.abs( rand.nextInt() % 1000 )).getBytes());
     74     }
     75 
     76 
     77     public static Utils getInstance() {
     78         return instance;
     79     }
     80 
     81     /**
     82      * convert an array of bytes to an hexadecimal string
     83      *
     84      * @return a string
     85      * @param b
     86      *            bytes array to convert to a hexadecimal string
     87      */
     88 
     89     public static String toHexString(byte b[]) {
     90         int pos = 0;
     91         char[] c = new char[b.length * 2];
     92         for (int i = 0; i < b.length; i++) {
     93             c[pos++] = toHex[(b[i] >> 4) & 0x0F];
     94             c[pos++] = toHex[b[i] & 0x0f];
     95         }
     96         return new String(c);
     97     }
     98 
     99     /**
    100      * Put quotes around a string and return it.
    101      * Any " characters appearing in str are escaped
    102      *
    103      * @return a quoted string
    104      * @param str
    105      *            string to be quoted
    106      */
    107     public static String getQuotedString(String str) {
    108         return '"' + str.replace( "\"", "\\\"" ) + '"';
    109     }
    110 
    111     /**
    112      * Squeeze out all white space from a string and return the reduced string.
    113      *
    114      * @param input
    115      *            input string to sqeeze.
    116      * @return String a reduced string.
    117      */
    118     protected static String reduceString(String input) {
    119         String newString = input.toLowerCase();
    120         int len = newString.length();
    121         String retval = "";
    122         for (int i = 0; i < len; i++) {
    123             if (newString.charAt(i) == ' ' || newString.charAt(i) == '\t')
    124                 continue;
    125             else
    126                 retval += newString.charAt(i);
    127         }
    128         return retval;
    129     }
    130 
    131     /**
    132      * Generate a call identifier. This is useful when we want to generate a
    133      * call identifier in advance of generating a message.
    134      */
    135     public synchronized String generateCallIdentifier(String address) {
    136 
    137             String date = Long.toString(System.currentTimeMillis() + callIDCounter++
    138                     + rand.nextLong());
    139             byte cid[] = digester.digest(date.getBytes());
    140 
    141             String cidString = Utils.toHexString(cid);
    142             return cidString + "@" + address;
    143 
    144     }
    145 
    146     /**
    147      * Generate a tag for a FROM header or TO header. Just return a random 4
    148      * digit integer (should be enough to avoid any clashes!) Tags only need to
    149      * be unique within a call.
    150      *
    151      * @return a string that can be used as a tag parameter.
    152      *
    153      * synchronized: needed for access to 'rand', else risk to generate same tag
    154      * twice
    155      */
    156     public synchronized String generateTag() {
    157 
    158             return Integer.toHexString(rand.nextInt());
    159 
    160     }
    161 
    162     /**
    163      * Generate a cryptographically random identifier that can be used to
    164      * generate a branch identifier.
    165      *
    166      * @return a cryptographically random gloablly unique string that can be
    167      *         used as a branch identifier.
    168      */
    169     public synchronized String generateBranchId() {
    170         //
    171 
    172 
    173             long num = rand.nextLong() + Utils.counter++  + System.currentTimeMillis();
    174 
    175             byte bid[] = digester.digest(Long.toString(num).getBytes());
    176             // prepend with a magic cookie to indicate we are bis09 compatible.
    177             return SIPConstants.BRANCH_MAGIC_COOKIE + Utils.toHexString(bid) + this.signature;
    178 
    179 
    180     }
    181 
    182     public boolean responseBelongsToUs(SIPResponse response) {
    183         Via topmostVia = response.getTopmostVia();
    184         String branch = topmostVia.getBranch();
    185         return branch != null && branch.endsWith(this.signature);
    186     }
    187 
    188     public static String getSignature() {
    189         return signature;
    190     }
    191 
    192     public static void main(String[] args) {
    193         HashSet branchIds = new HashSet();
    194         for (int b = 0; b < 100000; b++) {
    195             String bid = Utils.getInstance().generateBranchId();
    196             if (branchIds.contains(bid)) {
    197                 throw new RuntimeException("Duplicate Branch ID");
    198             } else {
    199                 branchIds.add(bid);
    200             }
    201         }
    202         System.out.println("Done!!");
    203 
    204     }
    205 
    206 
    207 
    208 }
    209