/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package model; import controller.commands.CommandInvite; import gov.nist.javax.sip.DialogTimeoutEvent; import gov.nist.javax.sip.SipListenerExt; import gui.Hauptfenster; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.SecureRandom; import java.text.ParseException; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import javax.sip.DialogTerminatedEvent; import javax.sip.IOExceptionEvent; import javax.sip.InvalidArgumentException; import javax.sip.ListeningPoint; import javax.sip.RequestEvent; import javax.sip.ResponseEvent; import javax.sip.SipException; import javax.sip.SipFactory; import javax.sip.SipProvider; import javax.sip.SipStack; import javax.sip.TimeoutEvent; import javax.sip.TransactionTerminatedEvent; import javax.sip.address.*; import javax.sip.header.*; import javax.sip.message.*; import logger.OhmLogger; /** * * @author Jan komplettes Model für SIPmodel evtl. Vererbung und für jeden SIP * Response/Request eigene Klasse oder Interface da es langsam unübersichtlich * wird :( ACK schicken muss noch ergänzt werden BYE muss noch ergänzt werden. */ public class SIPmodel implements SipListenerExt { //Stringhilfen zum erzeugen von RandomString (Branch) private static final String TEST = "0123456789abcdefghijklmnopqrstuvwxyz";//für Random String private static final SecureRandom RANDOM = new SecureRandom(); //für Random String //Verbindungskonstanten private static final int MYSIPPORT = 5060; private static final int MYRTPPORT = 5004; private static final int MYRTCPPORT = 5005; private static final String PROTOCOLTYP = "UDP"; Hauptfenster view; //später entfernen wegen Zugriff public static final Logger lg = OhmLogger.getLogger(); public SipFactory sipFactory; // Used to access the SIP API. public SipStack sipStack; // The SIP stack. public SipProvider sipProvider; // Used to send SIP messages. public MessageFactory messageFactory; // Used to create SIP message factory. public HeaderFactory headerFactory; // Used to create SIP headers. public AddressFactory addressFactory; // Used to create SIP URIs. public ListeningPoint listeningPoint; // SIP listening IP address/port. public Properties properties; // Other properties. private AudioRinging audioRinging; //Hilfsbooleans private Boolean anrufer; //Hilfsvariable ob ich selbst anrufer bin private Boolean anrufAngenommen; private Boolean anrufCancel; private Boolean werdeAngerufen; //Variablen die im Laufe des Gespräches ermittelt werden //Eigene Daten private String myIPAddress; private String myName = "129"; private String myTag; private Address contactAddress; private ContactHeader contactHeader; //ProxyServer public String proxyAddress; private int proxyRTPPort; private String proxyTag; //CallDaten private String branch; public CallIdHeader callID; private long cSequenz; private String RTPCodec; public SIPmodel(Hauptfenster view) //Konstruktor für eigene Daten { this.view = view; anrufer = false; anrufAngenommen = false; anrufCancel = false; proxyAddress = ""; proxyTag = ""; cSequenz = 1; werdeAngerufen = false; audioRinging = new AudioRinging(); myTag = createString(8); //erzeugt Random Tag mit Länge 8 branch = createString(18);//erzeugt Random branch mit Länge 18 try { //wird an sich erstmal nicht gebraucht aber später sinnvoll um eigene Daten zu initialisieren this.myIPAddress = InetAddress.getLocalHost().getHostAddress(); this.sipFactory = SipFactory.getInstance(); this.sipFactory.setPathName("gov.nist"); this.properties = new Properties(); this.properties.setProperty("javax.sip.STACK_NAME", "stack"); this.sipStack = this.sipFactory.createSipStack(this.properties); this.messageFactory = this.sipFactory.createMessageFactory(); this.headerFactory = this.sipFactory.createHeaderFactory(); this.addressFactory = this.sipFactory.createAddressFactory(); this.listeningPoint = this.sipStack.createListeningPoint(this.myIPAddress, this.MYSIPPORT, this.PROTOCOLTYP); this.sipProvider = this.sipStack.createSipProvider(this.listeningPoint); this.sipProvider.addSipListener(this); this.contactAddress = this.addressFactory.createAddress("sip:" + this.myName + "@" + this.myIPAddress + ":" + this.MYSIPPORT); this.contactHeader = this.headerFactory.createContactHeader(contactAddress); } catch (Exception e) { System.out.println("Fehler bei Initialisierung eigener Addresse"); System.exit(-1); } } private String createString(int anzahl) //Erzeugt Random String in bestimmter länge für branch und Tag { StringBuilder sb = new StringBuilder(); for (int i = 0; i < anzahl; i++) { sb.append(TEST.charAt(RANDOM.nextInt(TEST.length()))); } return sb.toString(); } public void sendRegister(String serverIP, int serverPort) throws ParseException, InvalidArgumentException, SipException { proxyAddress = serverIP + ":" + serverPort; SIPRegister register = new SIPRegister(proxyAddress, myTag, myIPAddress, MYSIPPORT, branch, addressFactory, headerFactory, messageFactory, contactHeader, sipProvider.getNewCallId()); sipProvider.sendRequest(register.getRequest()); lg.info("Erfolgreiches Senden der Registrierung"); } public void sendInvitation(String sipaddresse, String proxyaddresse, int serverPort) throws SipException { //ServerPort wird nicht verwendet? resetCallParameter(); anrufer = true; callID = sipProvider.getNewCallId(); SIPSessionDescription sdp = new SIPSessionDescription(myName, myIPAddress, getMYRTPPORT(), null, anrufer); SIPInvite sipinvite = new SIPInvite(sipaddresse, proxyaddresse, myIPAddress, MYSIPPORT, myTag, branch, callID, cSequenz, addressFactory, sdp.getSessionDescription(), headerFactory, messageFactory, contactHeader); sipProvider.sendRequest(sipinvite.getInviterequest()); lg.info("Erfolgreiches Senden der Invitation"); } @Override public void processRequest(RequestEvent requestEvent) { lg.info("Bekomme Anfrage"); if ((Request.OPTIONS).equals(requestEvent.getRequest().getMethod())) //Options Anfrage von Server nach erfolgreicher Registrierung { lg.info("Option Request von Server, erstellen 200 OK zu Server"); try { SIP200Ok tempOk = new SIP200Ok(messageFactory, requestEvent, contactHeader, headerFactory); this.sipProvider.sendResponse(tempOk.getResponse()); view.getTxtArea().append("Server Option Request erfolgreich beantwortet\n"); lg.info("Erfolgreiches senden des 200Ok-Headers"); } catch (SipException ex) { lg.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex); } } //Aktive Kommunikation else if ((Request.INVITE).equals(requestEvent.getRequest().getMethod())) // Invite von anderem Benutzer { resetCallParameter(); anrufer = false; //Falls Anruf ankommt, wichtige Variablen Zwischenspeichern (Branch, Cseq, CallID, proxyTag) branch = ((ViaHeader) requestEvent.getRequest().getHeader("Via")).getBranch(); cSequenz = ((CSeqHeader) requestEvent.getRequest().getHeader("Cseq")).getSeqNumber(); proxyTag = ((FromHeader) requestEvent.getRequest().getHeader("From")).getTag(); callID = ((CallIdHeader) requestEvent.getRequest().getHeader("CallID")); //Standartabfolge sobald man angerufen wird try { //Trying Response erzeugen und abschicken SIP100Trying tempTrying = new SIP100Trying(messageFactory, requestEvent, headerFactory); sipProvider.sendResponse(tempTrying.getTryResponse()); view.getTxtArea().append("Trying geschickt\n"); lg.info("Trying ist raus"); //Ringing Response erzeugen und abschicken noch Schleife mit "Anruf annehmen" SIP180Ringing tempRinging = new SIP180Ringing(requestEvent, myTag, contactHeader, headerFactory, messageFactory); Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { int counter = 0; @Override public void run() { try { if (anrufAngenommen != true && counter % 4 == 0) //Falls man nicht abnimmt, klingeln + Ringing schicken { sipProvider.sendResponse(tempRinging.getResponseRing()); audioRinging.startRinging(); } else if (anrufAngenommen == true) //bei annehmen, klingeln aufhören, OK mit SDP schicken { audioRinging.endRinging(); audioRinging.endRinging(); SIP200Ok respcall = new SIP200Ok(messageFactory, requestEvent, contactHeader, headerFactory); SIPSessionDescription sdp = new SIPSessionDescription(myName, myIPAddress, getMYRTPPORT(), requestEvent, anrufer); respcall.addSDP(sdp.getSessionDescription(), myTag); sipProvider.sendResponse(respcall.getResponse()); view.getTxtArea().append("Telefonat beginnt\n"); timer.cancel(); } else if (anrufCancel == true) { timer.cancel(); } counter++; } catch (SipException ex) { } } }, 0, 1000); } catch (SipException ex) { lg.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex); } } else if ((Request.ACK).equals(requestEvent.getRequest().getMethod())) { } else if ((Request.CANCEL).equals(requestEvent.getRequest().getMethod())) { System.out.println("Anruf cancel"); view.getTxtArea().append("Anruf wurde gecancelt"); try { //Cancel Request -> Response 200 Ok + Response 487 Request Terminated //200 Ok anrufCancel = true; SIP200Ok tempOk = new SIP200Ok(messageFactory, requestEvent, contactHeader, headerFactory); sipProvider.sendResponse(tempOk.getResponse()); view.getTxtArea().append("Anrufender canceld Anfrage\n"); lg.info("Erfolgreiches senden des 200 OkHeaders auf CancelAnfrage"); //487 Request Terminated } catch (SipException ex) { Logger.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex); } } else if ((Request.BYE).equals(requestEvent.getRequest().getMethod())) { try { SIP200Ok tempOk = new SIP200Ok(messageFactory, requestEvent, contactHeader, headerFactory); this.sipProvider.sendResponse(tempOk.getResponse()); } catch (SipException ex) { Logger.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex); } } } @Override public void processResponse(ResponseEvent responseEvent) { if (responseEvent.getResponse().getStatusCode() == Response.UNAUTHORIZED) { try { cSequenz += 1L; branch += 10; SIPUnauthReq req2 = new SIPUnauthReq(myName, proxyAddress, myTag, myIPAddress, branch, cSequenz, MYSIPPORT, contactHeader, addressFactory, headerFactory, responseEvent, messageFactory); sipProvider.sendRequest(req2.getUnauthReq()); view.getTxtArea().append("Erfolgreich registriert\n"); } catch (SipException ex) { lg.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex); } } else if (responseEvent.getResponse().getStatusCode() == Response.OK) { //Überprüfen ob Ok Header mit SDP ist if ((((ContentTypeHeader) responseEvent.getResponse().getHeader("Content-Type")).getContentSubType()).equals("sdp")) { lg.info("Erfolgreichen Response 200 OK mit SDP bekommen"); getRTPParameters(responseEvent); // SIPACK ack = new SIPACK(); // sipProvider.sendResponse(rspns); /* System.out.println("Starte RTP Session"); //String[] s = null; SoundSenderDemo aDemo = null; // try { // aDemo = new SoundSenderDemo(true); // } catch (UnknownHostException | InterruptedException ex) { // Logger.getLogger(CommandInvite.class.getName()).log(Level.SEVERE, null, ex); // } try { aDemo.SendDemo(null); } catch (UnknownHostException | InterruptedException ex) { Logger.getLogger(CommandInvite.class.getName()).log(Level.SEVERE, null, ex); } System.out.println("Beende RTP Session"); */ } else { lg.info("Erfolgreichen Response (200 OK) bekommen"); } } else if (responseEvent.getResponse().getStatusCode() == Response.RINGING) { ToHeader temp = (ToHeader) responseEvent.getResponse().getHeader("To"); proxyTag = temp.getTag(); } } public void byecall(String calluser) throws ParseException, InvalidArgumentException, SipException { cSequenz++; SIPBye tempBye = new SIPBye(calluser, proxyAddress, myName, myIPAddress, myTag, proxyTag, MYSIPPORT, branch, callID, cSequenz, messageFactory, contactHeader, addressFactory, headerFactory); sipProvider.sendRequest(tempBye.getByeRequest()); lg.info("Erfolgreiches Senden des BYE Headers"); } public void getRTPParameters(ResponseEvent responseEvent) { int identifier = 0; String[] reqbody = (responseEvent.getResponse()).toString().split("\\s|" + System.getProperty("line.seperator")); for (String req : reqbody) { if (identifier == 1) { proxyRTPPort = Integer.valueOf(req); identifier = 0; } else if (identifier == 2) { RTPCodec = req; identifier = 0; } if (req.startsWith("m=audio")) { identifier = 1; } else if (req.startsWith("a=rtpmap:")) { identifier = 2; } } } public void resetCallParameter() { anrufAngenommen = false; anrufer = false; } public void anrufAnnehmen() { anrufAngenommen = true; } //Get Methoden falls man mal die Parameter braucht public String getmyName() { return myName; } public Integer getMyPort() { return MYSIPPORT; } public String getMyIPAdress() { return myIPAddress; } // Herausfinden bei welchen Events die unteren Funktionen aufgerufen werden -> evtl brauchbar @Override public void processTimeout(TimeoutEvent timeoutEvent) { //view.getTxtArea().append("processTimeout\n"); } @Override public void processIOException(IOExceptionEvent exceptionEvent) { //view.getTxtArea().append("processIOException\n"); } @Override public void processTransactionTerminated( TransactionTerminatedEvent transactionTerminatedEvent) { //view.getTxtArea().append("processTransactionTerminated\n"); } @Override public void processDialogTerminated( DialogTerminatedEvent dialogTerminatedEvent) { //view.getTxtArea().append("processDialogTerminated\n"); } @Override public void processDialogTimeout(DialogTimeoutEvent timeoutEvent) { //view.getTxtArea().append("processDialogTerminated\n"); } /** * @param myPort the MYSIPPORT to set */ /** * @return the myName */ public String getMyName() { return myName; } /** * @return the proxyTag */ public String getProxyTag() { return proxyTag; } /** * @param proxyTag the proxyTag to set */ public void setProxyTag(String proxyTag) { this.proxyTag = proxyTag; } /** * @return the myTag */ public String getMyTag() { return myTag; } /** * @param myTag the myTag to set */ public void setMyTag(String myTag) { this.myTag = myTag; } /** * @return the branch */ public String getBranch() { return branch; } /** * @param proxyRTPPort the proxyRTPPort to set */ public void setProxyRTPPort(int proxyRTPPort) { this.proxyRTPPort = proxyRTPPort; } /** * @param RTPCodec the RTPCodec to set */ public void setRTPCodec(String RTPCodec) { this.RTPCodec = RTPCodec; } /** * @return the proxyRTPPort */ public int getProxyRTPPort() { return proxyRTPPort; } /** * @return the RTPCodec */ public String getRTPCodec() { return RTPCodec; } /** * @return the MYRTPPORT */ public static int getMYRTPPORT() { return MYRTPPORT; } /** * @return the MYRTCPPORT */ public static int getMYRTCPPORT() { return MYRTCPPORT; } }