• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getInstance()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 
toHexString(byte b[])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      */
getQuotedString(String str)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      */
reduceString(String input)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      */
generateCallIdentifier(String address)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      */
generateTag()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      */
generateBranchId()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 
responseBelongsToUs(SIPResponse response)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 
getSignature()188     public static String getSignature() {
189         return signature;
190     }
191 
main(String[] args)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