Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/act365/net/SocketUtils.java


1   /*
2    * JSocket Wrench
3    * 
4    * Copyright (C) act365.com October 2003
5    * 
6    * Web site: http://www.act365.com/wrench
7    * E-mail: developers@act365.com
8    * 
9    * The JSocket Wrench library adds support for low-level Internet protocols
10   * to the Java programming language.
11   * 
12   * This program is free software; you can redistribute it and/or modify it 
13   * under the terms of the GNU General Public License as published by the Free 
14   * Software Foundation; either version 2 of the License, or (at your option) 
15   * any later version.
16   *  
17   * This program is distributed in the hope that it will be useful, 
18   * but WITHOUT ANY WARRANTY; without even the implied warranty of 
19   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 
20   * Public License for more details.
21   * 
22   * You should have received a copy of the GNU General Public License along with 
23   * this program; if not, write to the Free Software Foundation, Inc., 
24   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25   */
26  
27  package com.act365.net;
28  
29  import com.act365.net.tcp.*;
30  
31  import java.io.*;
32  import java.net.*;
33  
34  /**
35   * 
36   * SocketUtils provides various utility functions e.g. checksum calculations,
37   * functions to read and write numbers from bytestreams and a bytestream
38   * dump printer.
39   */
40  
41  public class SocketUtils {
42    
43    /**
44     * The protocol in use in the current session.
45     */
46      
47    static int protocol = 0 ;
48    
49    static boolean includeheader = false ;
50    
51    /**
52     * Sets the <code>DatagramSocket</code> factory to be used in the program.
53     * The TCP, TCP/J, UDP and ICMP protocols are supported. TCP/J is a clone
54     * of TCP that uses the IP protocol code 152. The addition of the Raw 
55     * prefix to the protocol name indicates that the user wishes to write his 
56     * own IP headers for the socket. (The option is not supported on Windows).
57     * The <code>Socket</code> and <code>ServerSocket</code> factory objects 
58     * will be set for TCP-based protocols.
59     * 
60     * @param protocol protocol to be used by <code>DatagramSocket</code> objects in the app
61     */
62    
63    public static void setProtocol( String protocollabel ) throws IOException {
64      if( protocollabel.equals("") ){
65      } else if( protocollabel.equalsIgnoreCase("ICMP") ){
66      protocol = SocketConstants.IPPROTO_ICMP ;
67      includeheader = false ; 
68      DatagramSocket.setDatagramSocketImplFactory( new ICMPDatagramSocketImplFactory() );
69      } else if( protocollabel.equalsIgnoreCase("RawTCP") ){
70      protocol = SocketConstants.IPPROTO_TCP ;
71      includeheader = true ;
72      DatagramSocket.setDatagramSocketImplFactory( new RawTCPDatagramSocketImplFactory() );
73      Socket.setSocketImplFactory( new TCPSocketImplFactory() );
74      ServerSocket.setSocketFactory( new TCPSocketImplFactory() );
75      } else if( protocollabel.equalsIgnoreCase("RawTCPJ") ){
76      protocol = SocketConstants.IPPROTO_TCPJ ;
77      includeheader = true ;
78      DatagramSocket.setDatagramSocketImplFactory( new RawTCPJDatagramSocketImplFactory() );
79      Socket.setSocketImplFactory( new TCPJSocketImplFactory() );
80      ServerSocket.setSocketFactory( new TCPJSocketImplFactory() );        
81      } else if( protocollabel.equalsIgnoreCase("RawUDP") ){
82      protocol = SocketConstants.IPPROTO_UDP ;
83      includeheader = true ;
84      DatagramSocket.setDatagramSocketImplFactory( new RawUDPDatagramSocketImplFactory() );
85      } else if( protocollabel.equalsIgnoreCase("RawICMP") ){
86      protocol = SocketConstants.IPPROTO_ICMP ;
87      includeheader = true ;
88      DatagramSocket.setDatagramSocketImplFactory( new RawICMPDatagramSocketImplFactory() );
89      } else if( protocollabel.equalsIgnoreCase("TCP") ){
90      protocol = SocketConstants.IPPROTO_TCP ;
91      includeheader = false ;
92      DatagramSocket.setDatagramSocketImplFactory( new TCPDatagramSocketImplFactory() );
93      Socket.setSocketImplFactory( new TCPSocketImplFactory() );
94      ServerSocket.setSocketFactory( new TCPSocketImplFactory() );
95      } else if( protocollabel.equalsIgnoreCase("TCPJ") ){
96      protocol = SocketConstants.IPPROTO_TCPJ ;
97      includeheader = false ;
98      DatagramSocket.setDatagramSocketImplFactory( new TCPJDatagramSocketImplFactory() );
99      Socket.setSocketImplFactory( new TCPJSocketImplFactory() );
100     ServerSocket.setSocketFactory( new TCPJSocketImplFactory() );        
101     } else if( protocollabel.equalsIgnoreCase("UDP") ){
102     protocol = SocketConstants.IPPROTO_TCP ;
103     includeheader = false ;
104     DatagramSocket.setDatagramSocketImplFactory( new UDPDatagramSocketImplFactory() );
105     } else {
106     throw new IOException("Protocol" + protocollabel + " is not supported");
107     }
108   }
109     
110   /**
111    Returns the protocol associated with the current <code>DatagramSocketImpl</code>.
112   */
113 
114   public static int getProtocol() {
115 
116       return protocol ;
117   }
118 
119   /**
120    Indicates whether the chosen protocol requires the user to include the IP header.
121   */
122 
123   public static boolean includeHeader() {
124     
125       return includeheader ;
126   }  
127 
128   /**
129    Standard internet checksum algorithm shared by IP, ICMP, UDP and TCP.
130   */
131 
132   public static short checksum( byte[] message , int length , int offset ) {
133      
134     // Sum consecutive 16-bit words.
135 
136     int sum = 0 ;
137 
138     while( offset < length - 1 ){
139 
140     sum += (int) integralFromBytes( message , offset , 2 );
141 
142     offset += 2 ;
143     } 
144     
145     if( offset == length - 1 ){
146 
147     sum += ( message[offset] >= 0 ? message[offset] : message[offset] ^ 0xffffff00 ) << 8 ;
148     }
149 
150     // Add upper 16 bits to lower 16 bits.
151 
152     sum = ( sum >>> 16 ) + ( sum & 0xffff );
153 
154     // Add carry
155 
156     sum += sum >>> 16 ;
157 
158     // Ones complement and truncate.
159 
160     return (short) ~sum ;
161   } 
162 
163   /**
164    Specific checksum calculation used for the UDP and TCP pseudo-header.
165   */
166 
167   public static short checksum( byte[] source ,
168                   byte[] destination ,
169                   byte   protocol ,
170                   short  length ,
171                   byte[] message ,
172                   int    offset ) {
173 
174     int bufferlength = length + 12 ;
175 
176     boolean odd = length % 2 == 1 ;
177 
178     if( odd ){
179     ++ bufferlength ;
180     }
181 
182     byte[] buffer = new byte[ bufferlength ];
183 
184     buffer[0] = source[0];
185     buffer[1] = source[1];
186     buffer[2] = source[2];
187     buffer[3] = source[3];
188 
189     buffer[4] = destination[0];
190     buffer[5] = destination[1];
191     buffer[6] = destination[2];
192     buffer[7] = destination[3];
193 
194     buffer[8] = (byte) 0 ;
195     buffer[9] = protocol ;
196 
197     shortToBytes( length , buffer , 10 );
198 
199     int i = 11 ;
200 
201     while( ++ i < length + 12 ){
202     buffer[ i ] = message[ i + offset - 12 ] ;
203     }
204 
205     if( odd ){
206     buffer[ i ] = (byte) 0 ;
207     }
208 
209     return checksum( buffer , buffer.length , 0 );
210   }
211 
212   /**
213    Forms an integral type from consecutive bytes in a buffer
214   */
215 
216   static long integralFromBytes( byte[] buffer , int offset , int length ){
217    
218     long answer = 0 ;
219 
220     while( -- length >= 0 ) {
221     answer = answer << 8 ;
222     answer |= buffer[offset] >= 0 ? buffer[offset] : 0xffffff00 ^ buffer[offset] ;
223     ++ offset ;
224     }
225 
226     return answer ;
227   }
228 
229   /**
230    Converts consecutive bytes from a buffer into a short.
231   */
232 
233   public static short shortFromBytes( byte[] buffer , int offset ) {
234     return (short) integralFromBytes( buffer , offset , 2 );
235   }
236 
237   /**
238    Converts consecutive bytes from a buffer into an int.
239   */
240 
241   public static int intFromBytes( byte[] buffer , int offset ) {
242     return (int) integralFromBytes( buffer , offset , 4 );
243   }
244 
245   /**
246    Converts consecutive bytes from a buffer into a long.
247   */
248 
249   public static long longFromBytes( byte[] buffer , int offset ) {
250     return integralFromBytes( buffer , offset , 8 );
251   }
252 
253   /**
254    Writes a long into a buffer.
255   */
256 
257   public static void longToBytes( long value , byte[] buffer , int offset ) {
258     buffer[ offset + 7 ] = (byte)( value & 0xff ); 
259     value = value >>> 8 ;
260     buffer[ offset + 6 ] = (byte)( value & 0xff ); 
261     value = value >>> 8 ;
262     buffer[ offset + 5 ] = (byte)( value & 0xff ); 
263     value = value >>> 8 ;
264     buffer[ offset + 4 ] = (byte)( value & 0xff ); 
265     value = value >>> 8 ;
266     buffer[ offset + 3 ] = (byte)( value & 0xff ); 
267     value = value >>> 8 ;
268     buffer[ offset + 2 ] = (byte)( value & 0xff ); 
269     value = value >>> 8 ;
270     buffer[ offset + 1 ] = (byte)( value & 0xff ); 
271     value = value >>> 8 ;
272     buffer[ offset ] = (byte)( value ); 
273   }
274 
275   /**
276    Writes an int into a buffer.
277   */
278 
279   public static void intToBytes( int value , byte[] buffer , int offset ){
280     buffer[ offset + 3 ] = (byte)( value & 0xff ); 
281     value = value >> 8 ;
282     buffer[ offset + 2 ] = (byte)( value & 0xff ); 
283     value = value >> 8 ;
284     buffer[ offset + 1 ] = (byte)( value & 0xff ); 
285     value = value >> 8 ;
286     buffer[ offset ] = (byte)( value );
287   }
288 
289   /**
290    Writes a short into a buffer.
291   */
292 
293   public static void shortToBytes( short value , byte[] buffer , int offset ){
294     buffer[ offset + 1 ] = (byte)( value & 0xff ); 
295     value = (short)( value >> 8 );
296     buffer[ offset ] = (byte)( value );
297   }
298 
299   /**
300    Dumps a buffer in printable form.
301   */
302 
303   public static void dump( PrintStream printer , byte[] buffer , int offset , int count ){
304     
305     final int upper_bound = offset + ( count / 8 + 1 )* 8 ;
306 
307     int i = offset ;
308  
309     StringBuffer str = new StringBuffer();
310 
311     while( i <= upper_bound ){
312 
313     int j ;
314 
315     String tmpstr ;
316 
317     if( ( i - offset ) % 8 == 0 ){
318 
319       if( i > 0 ){
320 
321       str.append(' ');
322  
323       j = i - 9 ;
324 
325       while( ++ j < i ){
326 
327         if( j < offset + count ){
328         if( buffer[ j ] >= 32 ){
329           try {
330           tmpstr =  new String( buffer , j , 1 , "UTF8" );
331           } catch ( UnsupportedEncodingException e ){
332           tmpstr = null ;
333           }
334         } else {
335           tmpstr = null ;
336         }
337         } else {
338         tmpstr = " ";
339         }
340  
341         if( tmpstr != null ){
342         str.append( tmpstr );
343         } else {
344         str.append('.');
345         }
346       }
347 
348       printer.println( str.toString() );
349       }
350 
351       str = new StringBuffer( 38 );
352 
353       tmpstr = Integer.toHexString( i - offset );
354 
355       j = -1 ;
356 
357       while( ++ j < 4 - tmpstr.length() ){
358       str.append('0');
359       }
360 
361       str.append( tmpstr );
362     }
363 
364     str.append(' ');
365 
366     if( i < offset + count ){
367 
368       int unsigned = buffer[ i - offset ] >= 0 ? buffer[ i - offset ] : 0xffffff00 ^ buffer[ i - offset ] ;
369 
370       if( unsigned < 16 ){
371       str.append('0');
372       }
373 
374       str.append( Integer.toHexString( unsigned ) );
375     } else {
376       str.append("  ");
377     }
378 
379     ++ i ;
380     }
381   }
382 }