00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 package de.fhg.fokus.diameter.DiameterPeer.data;
00032
00033 import java.util.Arrays;
00034 import java.util.Vector;
00035
00036
00037
00059 public class Codec {
00060
00069 public static AVP decodeAVP(byte[] from,int start) throws AVPDecodeException
00070 {
00071 AVP to = new AVP();
00072 int i,j,len;
00073
00074 if (from.length-start<8) throw new AVPDecodeException("Data is shorter than AVP Header");
00075
00076 to.code = ((int)from[start+0]&0xFF)<<24 |
00077 ((int)from[start+1]&0xFF)<<16 |
00078 ((int)from[start+2]&0xFF)<< 8 |
00079 ((int)from[start+3]&0xFF);
00080
00081 to.flag_vendor_specific = (from[start+4] & 0x80)!=0;
00082 to.flag_mandatory = (from[start+4] & 0x40)!=0;
00083 to.flag_protected = (from[start+4] & 0x20)!=0;
00084 len = ((int)from[start+5]&0xFF)<<16 |
00085 ((int)from[start+6]&0xFF)<< 8 |
00086 ((int)from[start+7]&0xFF);
00087
00088 if (to.flag_vendor_specific){
00089 to.vendor_id = ((int)from[start+ 8]&0xFF)<<24 |
00090 ((int)from[start+ 9]&0xFF)<<16 |
00091 ((int)from[start+10]&0xFF)<< 8 |
00092 ((int)from[start+11]&0xFF);
00093 j = 12;
00094 } else {
00095 to.vendor_id = 0;
00096 j = 8;
00097 }
00098
00099 if (len>from.length-start) len = from.length-start;
00100 to.data = new byte[len-j];
00101 System.arraycopy(from,start+j,to.data,0,len-j);
00102
00103 if (len!=0)
00104 for(i=0;i<4&&i<len-j;i++)
00105 to.int_data = (to.int_data<<8)| ((byte) to.data[i]&0xFF);
00106
00107 to.encoded_length = len;
00108 if (to.encoded_length%4!=0)
00109 to.encoded_length = (to.encoded_length/4+1)*4;
00110
00111 return to;
00112 }
00113
00119 public static byte[] encodeAVP(AVP from)
00120 {
00121 byte[] to = null;
00122 int total_len,send_len;
00123 int j;
00124
00125
00126 if (from.is_ungrouped)
00127 from.group();
00128
00129 total_len=4+4+from.data.length;
00130
00131 if (from.flag_vendor_specific) total_len+=4;
00132 send_len = total_len;
00133 if (total_len%4!=0)
00134 total_len = (total_len/4+1)*4;
00135 to = new byte[total_len];
00136 Arrays.fill(to,(byte)0);
00137
00138 to[0] = (byte) ((from.code >> 24) & 0xFF);
00139 to[1] = (byte) ((from.code >> 16) & 0xFF);
00140 to[2] = (byte) ((from.code >> 8) & 0xFF);
00141 to[3] = (byte) ( from.code & 0xFF);
00142
00143 if (from.flag_vendor_specific) to[4] |= 0x80;
00144 if (from.flag_mandatory) to[4] |= 0x40;
00145 if (from.flag_protected) to[4] |= 0x20;
00146 to[5] = (byte) ((send_len >> 16) & 0xFF);
00147 to[6] = (byte) ((send_len >> 8) & 0xFF);
00148 to[7] = (byte) ( send_len & 0xFF);
00149
00150 if (from.flag_vendor_specific){
00151 to[ 8] = (byte) ((from.vendor_id >> 24) & 0xFF);
00152 to[ 9] = (byte) ((from.vendor_id >> 16) & 0xFF);
00153 to[10] = (byte) ((from.vendor_id >> 8) & 0xFF);
00154 to[11] = (byte) ( from.vendor_id & 0xFF);
00155 j = 12;
00156 }
00157 else j = 8;
00158
00159 if (from.data.length!=0)
00160 System.arraycopy(from.data,0,to,j,from.data.length);
00161
00162 return to;
00163 }
00164
00171 public static int getEncodedAVPSize(AVP avp)
00172 {
00173 AVP avp2;
00174 int datalen=0;
00175 int i;
00176 if (avp.is_ungrouped&&avp.childs!=null){
00177 for(i=0;i<avp.childs.size();i++){
00178 avp2 = (AVP) avp.childs.get(i);
00179 datalen += getEncodedAVPSize(avp2);
00180 }
00181 }else{
00182 datalen += avp.data.length;
00183 if (datalen%4!=0) datalen = (datalen/4+1)*4;
00184 }
00185 if (avp.flag_vendor_specific) return 12+datalen;
00186 else return 8+datalen;
00187 }
00188
00197 public static DiameterMessage decodeDiameterMessage(byte[] from,int start) throws DiameterMessageDecodeException
00198 {
00199 DiameterMessage to = new DiameterMessage();
00200 int i,len;
00201 AVP avp;
00202
00203 if (from.length-start<20) throw new DiameterMessageDecodeException("Data is shorter than Diameter Message Header");
00204
00205 to.version = ((int)from[start+0]&0xFF);
00206 if (to.version!=1) throw new DiameterMessageDecodeException("Unknown Diameter Message Version "+to.version);
00207
00208 len = ((int)from[start+ 1]&0xFF)<<16 |
00209 ((int)from[start+ 2]&0xFF)<< 8 |
00210 ((int)from[start+ 3]&0xFF);
00211
00212 if (len>from.length-start) len=from.length-start;
00213
00214 to.flagRequest = (from[start+4] & 0x80)!=0;
00215 to.flagProxiable = (from[start+4] & 0x40)!=0;
00216 to.flagError = (from[start+4] & 0x20)!=0;
00217 to.flagRetransmission = (from[start+4] & 0x10)!=0;
00218
00219 to.commandCode = ((int)from[start+ 5]&0xFF)<<16 |
00220 ((int)from[start+ 6]&0xFF)<< 8 |
00221 ((int)from[start+ 7]&0xFF);
00222
00223 to.applicationID = ((int)from[start+ 8]&0xFF)<<24 |
00224 ((int)from[start+ 9]&0xFF)<<16 |
00225 ((int)from[start+10]&0xFF)<< 8 |
00226 ((int)from[start+11]&0xFF);
00227
00228 to.hopByHopID = ((int)from[start+12]&0xFF)<<24 |
00229 ((int)from[start+13]&0xFF)<<16 |
00230 ((int)from[start+14]&0xFF)<< 8 |
00231 ((int)from[start+15]&0xFF);
00232
00233 to.endToEndID = ((int)from[start+16]&0xFF)<<24 |
00234 ((int)from[start+17]&0xFF)<<16 |
00235 ((int)from[start+18]&0xFF)<< 8 |
00236 ((int)from[start+19]&0xFF);
00237
00238 i = start+20;
00239 while (i<start+len){
00240 try {
00241 avp = Codec.decodeAVP(from,i);
00242 } catch (AVPDecodeException e) {
00243 e.printStackTrace();
00244 throw new DiameterMessageDecodeException(e.getMessage());
00245 }
00246 to.avps.add(avp);
00247 i+=avp.encoded_length;
00248 }
00249 return to;
00250 }
00251
00257 public static byte[] encodeDiameterMessage(DiameterMessage from)
00258 {
00259 byte[] to = null;
00260 int total_len;
00261 int i,len=0;
00262 Vector<byte[]> temp;
00263 byte[] t;
00264
00265 temp = new Vector<byte[]>();
00266 for(i=0;i<from.avps.size();i++){
00267 t = Codec.encodeAVP((AVP)from.avps.get(i));
00268 temp.add(t);
00269 len += t.length;
00270 }
00271 total_len=20+len;
00272
00273 to = new byte[total_len];
00274 Arrays.fill(to,(byte)0);
00275
00276 to[0] = (byte) ( from.version & 0xFF);
00277 to[1] = (byte) ((total_len >> 16) & 0xFF);
00278 to[2] = (byte) ((total_len >> 8) & 0xFF);
00279 to[3] = (byte) ( total_len & 0xFF);
00280
00281 if (from.flagRequest) to[4] |= 0x80;
00282 if (from.flagProxiable) to[4] |= 0x40;
00283 if (from.flagError) to[4] |= 0x20;
00284 if (from.flagRetransmission) to[4] |= 0x10;
00285 to[5] = (byte) ((from.commandCode >> 16) & 0xFF);
00286 to[6] = (byte) ((from.commandCode >> 8) & 0xFF);
00287 to[7] = (byte) ( from.commandCode & 0xFF);
00288
00289 to[ 8] = (byte) ((from.applicationID >> 24) & 0xFF);
00290 to[ 9] = (byte) ((from.applicationID >> 16) & 0xFF);
00291 to[10] = (byte) ((from.applicationID >> 8) & 0xFF);
00292 to[11] = (byte) ( from.applicationID & 0xFF);
00293
00294 to[12] = (byte) ((from.hopByHopID >> 24) & 0xFF);
00295 to[13] = (byte) ((from.hopByHopID >> 16) & 0xFF);
00296 to[14] = (byte) ((from.hopByHopID >> 8) & 0xFF);
00297 to[15] = (byte) ( from.hopByHopID & 0xFF);
00298
00299 to[16] = (byte) ((from.endToEndID >> 24) & 0xFF);
00300 to[17] = (byte) ((from.endToEndID >> 16) & 0xFF);
00301 to[18] = (byte) ((from.endToEndID >> 8) & 0xFF);
00302 to[19] = (byte) ( from.endToEndID & 0xFF);
00303
00304 len = 20;
00305 for(i=0;i<temp.size();i++){
00306 t = temp.get(i);
00307 System.arraycopy(t,0,to,len,t.length);
00308 len += t.length;
00309 }
00310
00311 return to;
00312 }
00313
00314 }