package uk.co.mmscomputing.device.capi; import java.io.IOException; import uk.co.mmscomputing.concurrent.TimeUnit; import uk.co.mmscomputing.concurrent.Semaphore; import uk.co.mmscomputing.concurrent.ArrayBlockingQueue; import uk.co.mmscomputing.util.metadata.Metadata; import uk.co.mmscomputing.device.capi.ctrl.ListenReq; import uk.co.mmscomputing.device.capi.plc.*; import uk.co.mmscomputing.device.capi.ncc.ConnectB3ActiveInd; import uk.co.mmscomputing.device.capi.q931.BearerCapability; import uk.co.mmscomputing.device.capi.protocol.BProtocol; import uk.co.mmscomputing.device.capi.protocol.SpeechProtocol; import uk.co.mmscomputing.device.capi.exception.CapiException; public class CapiServerApplication extends CapiCallApplication{ protected ArrayBlockingQueue incoming = null; // set of undealt incoming calls public CapiServerApplication(Metadata md)throws CapiException{ super(md); incoming = new ArrayBlockingQueue(maxLogicalCon); } public void run( ){ // Runnable interface try{ int cipmask=md.getInt("capi.cipmask"); CapiController[] controllers = CapiEnumerator.getControllers(); for(int i=0;i<controllers.length;i++){ put(new ListenReq(appid,controllers[i].getId(),cipmask)); } }catch(IOException ioe){ md.fireListenerUpdate(ioe); ioe.printStackTrace(); } super.run(); } public void close(){ try{ CapiController[] controllers = CapiEnumerator.getControllers(); for(int i=0;i<controllers.length;i++){ put(new ListenReq(appid,controllers[i].getId(),0)); // stop listening } }catch(CapiException ie){} super.close(); try{ incoming.put(null); // unblock accept; interrupt }catch(InterruptedException ie){} } public CapiChannel accept()throws InterruptedException{ return (CapiChannel)incoming.take(); // main application server thread : wait for incoming calls } protected void received(CapiPLC plc, ConnectInd msg)throws CapiException{ new Thread(new Pickup(plc,msg)).start(); // incoming physical call } protected void received(CapiNCC ncc,ConnectB3ActiveInd msg)throws CapiException{ try{ super.received(ncc,msg); if(ncc.isIncoming()){ // logical incoming call is connected now incoming.put(ncc); // add to incoming list, so that main app server } // can 'accept' it. }catch(InterruptedException ie){ throw new CapiException(ie.getMessage()); } } private class Pickup implements Runnable{ CapiPLC plc; ConnectInd msg; public Pickup(CapiPLC plc, ConnectInd msg){ this.plc=plc; this.msg=msg; } private void indicateCall()throws IOException{ CapiMetadata.Indication mdi=new CapiMetadata.Indication(msg.lineid); mdi.setController(plc.getCtrlId()); mdi.localno=msg.getLocalNo(); mdi.remoteno=msg.getRemoteNo(); int sp=md.getInt("capi.bandwidth"); mdi.setProtocol(new SpeechProtocol(sp)); // use by default md.fireListenerUpdate(mdi); // main application needs to fill mdi struct BProtocol protocol=mdi.getProtocol(); if(protocol instanceof SpeechProtocol){ BearerCapability bc=msg.getBearerCapability(); // System.err.println(bc); int sc=bc.getSpeechCoding(); if(sc!=-1){ // if we receive a valid BC struct use its speech coding plc.setSpeechCoding(sc); } } plc.setProtocol(protocol); plc.setLocalNo(mdi.localno); plc.setRemoteNo(mdi.remoteno); if(mdi.accept){ Semaphore blocker=mdi.blocker; if(blocker!=null){ // program wants to wait for a bit plc.setPickupBlocker(blocker); // if peer disconnects plc can release this thread put(new AlertReq(msg.appid,msg.lineid)); // tell telecom network that we listen try{ // wait until time runs out or some other thread released blocker blocker.tryAcquire(mdi.waitformsecs,TimeUnit.MILLISECONDS); }catch(InterruptedException ie){} } } if(!plc.isOpen()){return;} // disconnected by remote plc.setPickedUp(mdi.gotPickedUp); // main app might want to know String localNo=mdi.localno; String localNoSub=""; String[] slno=localNo.split("-"); if(slno.length==2){ localNo=slno[0]; localNoSub=slno[1];} plc.setProtocol(mdi.getProtocol()); plc.setPlugin(mdi.getPlugin()); put(new ConnectResp( msg.appid, msg.lineid, mdi.rejectFlag, mdi.getProtocol(), localNo, localNoSub, StructOut.empty, StructOut.empty )); } public void run(){ Thread.currentThread().setName(getClass().getName()+".0x"+Integer.toHexString(plc.getLineID())); try{ indicateCall(); }catch(IOException ioe){ md.fireListenerUpdate(ioe); } } } }