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.peer;
00032
00033 import java.io.IOException;
00034 import java.net.Socket;
00035 import java.net.UnknownHostException;
00036 import java.util.Iterator;
00037 import java.util.concurrent.TimeUnit;
00038
00039 import org.apache.log4j.Logger;
00040
00041 import de.fhg.fokus.diameter.DiameterPeer.data.AVP;
00042 import de.fhg.fokus.diameter.DiameterPeer.data.AVPDecodeException;
00043 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterCEA;
00044 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterCER;
00045 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterDPA;
00046 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterDPR;
00047 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterDWA;
00048 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterDWR;
00049 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterMessage;
00050 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterTask;
00051 import de.fhg.fokus.diameter.DiameterPeer.transport.Communicator;
00052
00059 public class StateMachine {
00060
00062 private static final Logger LOGGER = Logger.getLogger(StateMachine.class);
00063
00064
00066 public static final int Closed = 0;
00067
00069 public static final int Wait_Conn_Ack = 1;
00070
00072 public static final int Wait_I_CEA = 2;
00073
00075 public static final int Wait_Conn_Ack_Elect = 3;
00076
00078 public static final int Wait_Returns = 4;
00079
00081 public static final int R_Open = 5;
00082
00084 public static final int I_Open = 6;
00085
00087 public static final int Closing = 7;
00088
00089
00090
00091
00092
00094 public static final int Start = 101;
00095
00097 public static final int Stop = 102;
00098
00100 public static final int Timeout = 103;
00101
00103 public static final int Win_Election = 104;
00104
00106 public static final int R_Conn_CER = 105;
00107
00109 public static final int I_Rcv_Conn_Ack = 106;
00110
00112 public static final int I_Rcv_Conn_NAck = 107;
00113
00115 public static final int I_Rcv_CER = 108;
00116
00118 public static final int I_Rcv_CEA = 109;
00119
00121 public static final int R_Rcv_CER = 110;
00122
00124 public static final int R_Rcv_CEA = 111;
00125
00127 public static final int I_Rcv_Non_CEA = 112;
00128
00130 public static final int I_Rcv_DPR = 113;
00131
00133 public static final int I_Rcv_DPA = 114;
00134
00136 public static final int R_Rcv_DPR = 115;
00137
00139 public static final int R_Rcv_DPA = 116;
00140
00142 public static final int I_Rcv_DWR = 117;
00143
00145 public static final int I_Rcv_DWA = 118;
00146
00148 public static final int R_Rcv_DWR = 119;
00149
00151 public static final int R_Rcv_DWA = 120;
00152
00154 public static final int Send_Message = 121;
00155
00157 public static final int I_Rcv_Message = 122;
00158
00160 public static final int R_Rcv_Message = 123;
00161
00163 public static final int I_Peer_Disc = 124;
00164
00166 public static final int R_Peer_Disc = 125;
00167
00175 public static int process(Peer p, int event)
00176 {
00177 return process(p,event,null,null);
00178 }
00179
00180
00181
00190 public static int process(Peer p, int event, DiameterMessage msg)
00191 {
00192 return process(p,event,msg,null);
00193 }
00194
00195
00205 public static int process(Peer p, int event, DiameterMessage msg,Communicator comm)
00206 {
00207 int next_event,result_code;
00208 boolean msg_received=false;
00209
00210
00211 synchronized(p){
00212 switch (p.state){
00213 case Closed:
00214 switch (event){
00215 case Start:
00216 p.state = Wait_Conn_Ack;
00217 next_event = I_Snd_Conn_Req(p);
00218 StateMachine.process(p,next_event,null,p.I_comm);
00219 break;
00220 case R_Conn_CER:
00221 R_Accept(p,comm);
00222 result_code = Process_CER(p,msg);
00223 Snd_CEA(p,msg,result_code,p.R_comm);
00224 if (result_code>=2000 && result_code<3000)
00225 p.state = R_Open;
00226 else {
00227 R_Disc(p);
00228 p.state = Closed;
00229 }
00230 break;
00231 case Stop:
00232
00233 p.state = Closed;
00234 break;
00235 default:
00236 LOGGER.error("StateMachine: Invalid event "+event+" for state "+p.state);
00237 return 0;
00238 }
00239 break;
00240 case Wait_Conn_Ack:
00241 switch(event){
00242 case I_Rcv_Conn_Ack:
00243 I_Snd_CER(p);
00244 p.state = Wait_I_CEA;
00245 break;
00246 case I_Rcv_Conn_NAck:
00247 Cleanup(p,comm);
00248 p.state = Closed;
00249 break;
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 case Timeout:
00262 Error(p,p.I_comm);
00263 p.state = Closed;
00264 default:
00265 LOGGER.error("StateMachine: Invalid event "+event+" for state "+p.state);
00266 return 0;
00267 }
00268 break;
00269 case Wait_I_CEA:
00270 switch(event){
00271 case I_Rcv_CEA:
00272 result_code = Process_CEA(p,msg);
00273
00274 p.state = I_Open;
00275
00276
00277
00278
00279 break;
00280 case R_Conn_CER:
00281 R_Accept(p,comm);
00282 result_code = Process_CER(p,msg);
00283 p.state = Wait_Returns;
00284 if (Elect(p,msg))
00285 StateMachine.process(p,Win_Election,msg,comm);
00286 break;
00287 case I_Peer_Disc:
00288 I_Disc(p);
00289 p.state = Closed;
00290 break;
00291 case I_Rcv_Non_CEA:
00292 Error(p,p.I_comm);
00293 p.state = Closed;
00294 break;
00295 case Timeout:
00296 Error(p,p.I_comm);
00297 p.state = Closed;
00298 break;
00299 default:
00300 LOGGER.error("StateMachine: Invalid event "+event+" for state "+p.state);
00301 return 0;
00302 }
00303 break;
00304
00305
00306
00307
00308
00309
00310
00311
00312 case Wait_Returns:
00313 switch(event){
00314 case Win_Election:
00315 I_Disc(p);
00316 result_code = Process_CER(p,msg);
00317 Snd_CEA(p,msg,result_code,p.R_comm);
00318 if (result_code>=2000 && result_code<3000){
00319 p.state = R_Open;
00320 }else{
00321 R_Disc(p);
00322 p.state = Closed;
00323 }
00324 break;
00325 case I_Peer_Disc:
00326 I_Disc(p);
00327 result_code = Process_CER(p,msg);
00328 Snd_CEA(p,msg,result_code,p.R_comm);
00329 if (result_code>=2000 && result_code<3000){
00330 p.state = R_Open;
00331 }else{
00332 R_Disc(p);
00333 p.state = Closed;
00334 }
00335 break;
00336 case I_Rcv_CEA:
00337 R_Disc(p);
00338
00339
00340 p.state = I_Open;
00341
00342
00343
00344
00345 break;
00346 case R_Peer_Disc:
00347 R_Disc(p);
00348 p.state = Wait_I_CEA;
00349 break;
00350 case R_Conn_CER:
00351 R_Reject(p,comm);
00352 p.state = Wait_Returns;
00353 break;
00354 case Timeout:
00355 Error(p,comm);
00356 p.state = Closed;
00357 default:
00358 LOGGER.error("StateMachine: Invalid event "+event+" for state "+p.state);
00359 return 0;
00360 }
00361 break;
00362 case R_Open:
00363 switch (event){
00364 case Send_Message:
00365 Snd_Message(p,msg);
00366 p.state = R_Open;
00367 break;
00368 case R_Rcv_Message:
00369
00370
00371 msg_received = true;
00372 p.state = R_Open;
00373 break;
00374 case R_Rcv_DWR:
00375 result_code = Process_DWR(p,msg);
00376 Snd_DWA(p,msg,result_code,p.R_comm);
00377 p.state = R_Open;
00378 break;
00379 case R_Rcv_DWA:
00380 Process_DWA(p,msg);
00381 p.state = R_Open;
00382 break;
00383 case R_Conn_CER:
00384 R_Reject(p,comm);
00385 p.state = R_Open;
00386 break;
00387 case Stop:
00388 Snd_DPR(p);
00389 p.state = Closing;
00390 break;
00391 case R_Rcv_DPR:
00392 Snd_DPA(p,msg,DiameterMessage.DIAMETER_SUCCESS,p.R_comm);
00393 R_Disc(p);
00394 p.state = Closed;
00395 break;
00396 case R_Peer_Disc:
00397 R_Disc(p);
00398 p.state = Closed;
00399 break;
00400 case R_Rcv_CER:
00401 result_code = Process_CER(p,msg);
00402 Snd_CEA(p,msg,result_code,p.R_comm);
00403 if (result_code>=2000 && result_code<3000)
00404 p.state = R_Open;
00405 else {
00406
00407 p.state = R_Open;
00408 }
00409 break;
00410 case R_Rcv_CEA:
00411 result_code = Process_CEA(p,msg);
00412 if (result_code>=2000 && result_code<3000)
00413 p.state = R_Open;
00414 else {
00415
00416 p.state = R_Open;
00417 }
00418 break;
00419 default:
00420 LOGGER.error("StateMachine: Invalid event "+event+" for state "+p.state);
00421 return 0;
00422 }
00423 break;
00424 case I_Open:
00425 switch (event){
00426 case Send_Message:
00427 Snd_Message(p,msg);
00428 p.state = I_Open;
00429 break;
00430 case I_Rcv_Message:
00431
00432
00433 msg_received = true;
00434 p.state = I_Open;
00435 break;
00436 case I_Rcv_DWR:
00437 result_code = Process_DWR(p,msg);
00438 Snd_DWA(p,msg,result_code,p.I_comm);
00439 p.state =I_Open;
00440 break;
00441 case I_Rcv_DWA:
00442 Process_DWA(p,msg);
00443 p.state =I_Open;
00444 break;
00445 case R_Conn_CER:
00446 R_Reject(p,comm);
00447 p.state = I_Open;
00448 break;
00449 case Stop:
00450 Snd_DPR(p);
00451 p.state = Closing;
00452 break;
00453 case I_Rcv_DPR:
00454 Snd_DPA(p,msg,2001,p.I_comm);
00455 R_Disc(p);
00456 p.state = Closed;
00457 break;
00458 case I_Peer_Disc:
00459 I_Disc(p);
00460 p.state = Closed;
00461 break;
00462 case I_Rcv_CER:
00463 result_code = Process_CER(p,msg);
00464 Snd_CEA(p,msg,result_code,p.I_comm);
00465 if (result_code>=2000 && result_code<3000)
00466 p.state = I_Open;
00467 else {
00468
00469 p.state = I_Open;
00470 }
00471 break;
00472 case I_Rcv_CEA:
00473 result_code = Process_CEA(p,msg);
00474 if (result_code>=2000 && result_code<3000)
00475 p.state = I_Open;
00476 else {
00477
00478 p.state = I_Open;
00479 }
00480 break;
00481 default:
00482 LOGGER.error("StateMachine: Invalid event "+event+" for state "+p.state);
00483 return 0;
00484 }
00485 break;
00486 case Closing:
00487 switch(event){
00488 case I_Rcv_DPA:
00489 I_Disc(p);
00490 p.state = Closed;
00491 break;
00492 case R_Rcv_DPA:
00493 R_Disc(p);
00494 p.state = Closed;
00495 break;
00496 case Timeout:
00497 if (p.I_comm!=null) Error(p,p.I_comm);
00498 if (p.R_comm!=null) Error(p,p.R_comm);
00499 p.state = Closed;
00500 break;
00501 case I_Peer_Disc:
00502 I_Disc(p);
00503 p.state = Closed;
00504 break;
00505 case R_Peer_Disc:
00506 R_Disc(p);
00507 p.state = Closed;
00508 break;
00509 default:
00510 LOGGER.error("StateMachine: Invalid event "+event+" for state "+p.state);
00511 return 0;
00512 }
00513 break;
00514 default:
00515 LOGGER.error("StateMachine: Invalid state "+p.state);
00516 return 0;
00517
00518 }
00519
00520 }
00521 if (msg_received){
00522
00523 Rcv_Process(p,msg);
00524 }
00525
00526 return 1;
00527 }
00528
00529 private static int I_Snd_Conn_Req(Peer p)
00530 {
00531 Socket s;
00532 if (p.I_comm!=null) p.I_comm.shutdown();
00533 p.I_comm = null;
00534 try {
00535 s = new Socket(p.FQDN,p.port);
00536 } catch (UnknownHostException e1) {
00537 LOGGER.error("StateMachine: Peer "+p.FQDN+" can not be resolved.");
00538 return StateMachine.I_Rcv_Conn_NAck;
00539 } catch (IOException e1) {
00540 LOGGER.error("StateMachine: Peer "+p.FQDN+" not responding to connection attempt ");
00541 return StateMachine.I_Rcv_Conn_NAck;
00542 }
00543 Communicator r = new Communicator(s,p,Communicator.Initiator);
00544 p.I_comm = r;
00545 return StateMachine.I_Rcv_Conn_Ack;
00546 }
00547
00548 private static void R_Accept(Peer p,Communicator comm)
00549 {
00550 p.R_comm = comm;
00551 p.refreshTimer();
00552 }
00553
00554 private static void R_Reject(Peer p,Communicator comm)
00555 {
00556 comm.shutdown();
00557 }
00558
00559 private static void I_Snd_CER(Peer p)
00560 {
00561 DiameterCER cer = new DiameterCER();
00562
00563 cer.hopByHopID = p.diameterPeer.getNextHopByHopId();
00564 cer.endToEndID = p.diameterPeer.getNextEndToEndId();
00565 cer.origin_host.setData(p.diameterPeer.FQDN);
00566 cer.origin_realm.setData(p.diameterPeer.Realm);
00567 byte addr[] ,laddr[] = p.I_comm.socket.getLocalAddress().getAddress();
00568 switch (laddr.length) {
00569 case 16:
00570 addr = new byte[18];
00571 addr[0]=(byte)0;
00572 addr[1]=(byte)2;
00573 System.arraycopy(laddr,0,addr,2,laddr.length);
00574 break;
00575 default:
00576 case 4:
00577 addr = new byte[6];
00578 addr[0]=(byte)0;
00579 addr[1]=(byte)1;
00580 System.arraycopy(laddr,0,addr,2,laddr.length);
00581 break;
00582 }
00583 cer.host_ip_address.setData(addr);
00584 cer.vendor_id.setData(p.diameterPeer.Vendor_Id);
00585 cer.product_name.setData(p.diameterPeer.Product_Name);
00586
00587 Snd_CE_add_applications(cer,p);
00588
00589
00590 p.I_comm.sendDirect(cer);
00591 }
00592
00593
00594 private static void Cleanup(Peer p,Communicator comm)
00595 {
00596 if (comm==null) return;
00597 comm.shutdown();
00598 if (p.I_comm == comm) p.I_comm = null;
00599 if (p.R_comm == comm) p.R_comm = null;
00600 }
00601
00602 private static void Error(Peer p, Communicator comm)
00603 {
00604 Cleanup(p,comm);
00605 }
00606
00607 private static boolean Elect(Peer p,DiameterMessage cer)
00608 {
00609
00610 AVP avp;
00611 byte[] remote,local;
00612 int x,i;
00613 local = p.diameterPeer.FQDN.getBytes();
00614 avp = cer.findAVP(AVP.Origin_Host,true,0);
00615 if (avp==null) {
00616 return true;
00617 }else{
00618 remote = avp.data;
00619 for(i=0;i<remote.length&&i<local.length;i++){
00620 x = ((int) local[i]&0xFF)-((int) remote[i]&0xFF);
00621 if (x>0) return true;
00622 if (x<0) return false;
00623 }
00624 if (local.length>remote.length) return true;
00625 return false;
00626 }
00627 }
00628
00629 private static int Process_CER(Peer p,DiameterMessage cer)
00630 {
00631 int common_app=0;
00632 Iterator<AVP> i = cer.avps.iterator();
00633 Iterator<Application> i2;
00634 Application app;
00635 AVP avp,avp_vendor,avp2;
00636 p.AuthApp.clear();
00637 p.AcctApp.clear();
00638 while(i.hasNext()&& common_app==0){
00639 avp = (AVP) i.next();
00640 switch (avp.code){
00641 case AVP.Auth_Application_Id:
00642 p.AuthApp.add(new Application(avp.int_data,0,Application.Auth));
00643 i2 = p.diameterPeer.AuthApp.iterator();
00644 while(i2.hasNext()){
00645 app = i2.next();
00646 if (avp.int_data==Application.Relay ||
00647 (app.id==avp.int_data && app.vendor==0)){
00648 common_app++;
00649 break;
00650 }
00651 }
00652 break;
00653 case AVP.Acct_Application_Id:
00654 p.AcctApp.add(new Application(avp.int_data,0,Application.Acct));
00655 i2 = p.diameterPeer.AcctApp.iterator();
00656 while(i2.hasNext()){
00657 app = i2.next();
00658 if (avp.int_data==Application.Relay ||
00659 (app.id==avp.int_data && app.vendor==0)){
00660 common_app++;
00661 break;
00662 }
00663 }
00664 break;
00665 case AVP.Vendor_Specific_Application_Id:
00666 try {
00667 avp.ungroup();
00668 } catch (AVPDecodeException e) {
00669 e.printStackTrace();
00670 }
00671 avp_vendor = avp.findChildAVP(AVP.Vendor_Id,true,0);
00672 if (avp_vendor==null) break;
00673 avp2 = avp.findChildAVP(AVP.Auth_Application_Id,true,0);
00674 if (avp2!=null) {
00675 p.AuthApp.add(new Application(avp2.int_data,avp_vendor.int_data,Application.Auth));
00676 i2 = p.diameterPeer.AuthApp.iterator();
00677 while(i2.hasNext()){
00678 app = i2.next();
00679 if (avp2.int_data==Application.Relay ||
00680 (app.id==avp2.int_data && app.vendor==avp_vendor.int_data)){
00681 common_app++;
00682 break;
00683 }
00684 }
00685 }
00686 avp2 = avp.findChildAVP(AVP.Acct_Application_Id,true,0);
00687 if (avp2!=null) {
00688 p.AcctApp.add(new Application(avp2.int_data,avp_vendor.int_data,Application.Acct));
00689 i2 = p.diameterPeer.AcctApp.iterator();
00690 while(i2.hasNext()){
00691 app = (Application) i2.next();
00692 if (avp2.int_data==Application.Relay ||
00693 (app.id==avp2.int_data && app.vendor==avp_vendor.int_data)){
00694 common_app++;
00695 break;
00696 }
00697 }
00698 }
00699 break;
00700
00701 }
00702 }
00703
00704 if (common_app!=0)
00705 return