You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SIPmodel.java 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /*
  2. * To change this license header, choose License Headers in Project Properties.
  3. * To change this template file, choose Tools | Templates
  4. * and open the template in the editor.
  5. */
  6. package model;
  7. import controller.commands.CommandInvite;
  8. import gov.nist.javax.sip.DialogTimeoutEvent;
  9. import gov.nist.javax.sip.SipListenerExt;
  10. import gui.Hauptfenster;
  11. import java.net.InetAddress;
  12. import java.net.UnknownHostException;
  13. import java.security.SecureRandom;
  14. import java.text.ParseException;
  15. import java.util.*;
  16. import java.util.logging.Level;
  17. import java.util.logging.Logger;
  18. import javax.sip.DialogTerminatedEvent;
  19. import javax.sip.IOExceptionEvent;
  20. import javax.sip.InvalidArgumentException;
  21. import javax.sip.ListeningPoint;
  22. import javax.sip.RequestEvent;
  23. import javax.sip.ResponseEvent;
  24. import javax.sip.SipException;
  25. import javax.sip.SipFactory;
  26. import javax.sip.SipProvider;
  27. import javax.sip.SipStack;
  28. import javax.sip.TimeoutEvent;
  29. import javax.sip.TransactionTerminatedEvent;
  30. import javax.sip.address.*;
  31. import javax.sip.header.*;
  32. import javax.sip.message.*;
  33. import logger.OhmLogger;
  34. /**
  35. *
  36. * @author Jan komplettes Model für SIPmodel evtl. Vererbung und für jeden SIP
  37. * Response/Request eigene Klasse oder Interface da es langsam unübersichtlich
  38. * wird :( ACK schicken muss noch ergänzt werden BYE muss noch ergänzt werden.
  39. */
  40. public class SIPmodel implements SipListenerExt {
  41. //Stringhilfen zum erzeugen von RandomString (Branch)
  42. private static final String TEST = "0123456789abcdefghijklmnopqrstuvwxyz";//für Random String
  43. private static final SecureRandom RANDOM = new SecureRandom(); //für Random String
  44. //Verbindungskonstanten
  45. private static final int MYSIPPORT = 5060;
  46. private static final int MYRTPPORT = 5004;
  47. private static final int MYRTCPPORT = 5005;
  48. private static final String PROTOCOLTYP = "UDP";
  49. Hauptfenster view; //später entfernen wegen Zugriff
  50. public static final Logger lg = OhmLogger.getLogger();
  51. public SipFactory sipFactory; // Used to access the SIP API.
  52. public SipStack sipStack; // The SIP stack.
  53. public SipProvider sipProvider; // Used to send SIP messages.
  54. public MessageFactory messageFactory; // Used to create SIP message factory.
  55. public HeaderFactory headerFactory; // Used to create SIP headers.
  56. public AddressFactory addressFactory; // Used to create SIP URIs.
  57. public ListeningPoint listeningPoint; // SIP listening IP address/port.
  58. public Properties properties; // Other properties.
  59. private AudioRinging audioRinging;
  60. //Hilfsbooleans
  61. private Boolean anrufer; //Hilfsvariable ob ich selbst anrufer bin
  62. private Boolean anrufAngenommen;
  63. private Boolean anrufCancel;
  64. private Boolean werdeAngerufen;
  65. //Variablen die im Laufe des Gespräches ermittelt werden
  66. //Eigene Daten
  67. private String myIPAddress;
  68. private String myName = "129";
  69. private String myTag;
  70. private Address contactAddress;
  71. private ContactHeader contactHeader;
  72. //ProxyServer
  73. public String proxyAddress;
  74. private int proxyRTPPort;
  75. private String proxyTag;
  76. //CallDaten
  77. private String branch;
  78. public CallIdHeader callID;
  79. private long cSequenz;
  80. private String RTPCodec;
  81. public SIPmodel(Hauptfenster view) //Konstruktor für eigene Daten
  82. {
  83. this.view = view;
  84. anrufer = false;
  85. anrufAngenommen = false;
  86. anrufCancel = false;
  87. proxyAddress = "";
  88. proxyTag = "";
  89. cSequenz = 1;
  90. werdeAngerufen = false;
  91. audioRinging = new AudioRinging();
  92. myTag = createString(8); //erzeugt Random Tag mit Länge 8
  93. branch = createString(18);//erzeugt Random branch mit Länge 18
  94. try {
  95. //wird an sich erstmal nicht gebraucht aber später sinnvoll um eigene Daten zu initialisieren
  96. this.myIPAddress = InetAddress.getLocalHost().getHostAddress();
  97. this.sipFactory = SipFactory.getInstance();
  98. this.sipFactory.setPathName("gov.nist");
  99. this.properties = new Properties();
  100. this.properties.setProperty("javax.sip.STACK_NAME", "stack");
  101. this.sipStack = this.sipFactory.createSipStack(this.properties);
  102. this.messageFactory = this.sipFactory.createMessageFactory();
  103. this.headerFactory = this.sipFactory.createHeaderFactory();
  104. this.addressFactory = this.sipFactory.createAddressFactory();
  105. this.listeningPoint = this.sipStack.createListeningPoint(this.myIPAddress, this.MYSIPPORT, this.PROTOCOLTYP);
  106. this.sipProvider = this.sipStack.createSipProvider(this.listeningPoint);
  107. this.sipProvider.addSipListener(this);
  108. this.contactAddress = this.addressFactory.createAddress("sip:" + this.myName + "@" + this.myIPAddress + ":" + this.MYSIPPORT);
  109. this.contactHeader = this.headerFactory.createContactHeader(contactAddress);
  110. } catch (Exception e) {
  111. System.out.println("Fehler bei Initialisierung eigener Addresse");
  112. System.exit(-1);
  113. }
  114. }
  115. private String createString(int anzahl) //Erzeugt Random String in bestimmter länge für branch und Tag
  116. {
  117. StringBuilder sb = new StringBuilder();
  118. for (int i = 0; i < anzahl; i++) {
  119. sb.append(TEST.charAt(RANDOM.nextInt(TEST.length())));
  120. }
  121. return sb.toString();
  122. }
  123. public void sendRegister(String serverIP, int serverPort) throws ParseException, InvalidArgumentException, SipException {
  124. proxyAddress = serverIP + ":" + serverPort;
  125. SIPRegister register = new SIPRegister(proxyAddress, myTag, myIPAddress, MYSIPPORT, branch, addressFactory, headerFactory, messageFactory, contactHeader, sipProvider.getNewCallId());
  126. sipProvider.sendRequest(register.getRequest());
  127. lg.info("Erfolgreiches Senden der Registrierung");
  128. }
  129. public void sendInvitation(String sipaddresse, String proxyaddresse,
  130. int serverPort) throws SipException { //ServerPort wird nicht verwendet?
  131. resetCallParameter();
  132. anrufer = true;
  133. callID = sipProvider.getNewCallId();
  134. SIPSessionDescription sdp = new SIPSessionDescription(myName, myIPAddress, getMYRTPPORT(), null, anrufer);
  135. SIPInvite sipinvite = new SIPInvite(sipaddresse, proxyaddresse, myIPAddress, MYSIPPORT, myTag, branch, callID, cSequenz, addressFactory, sdp.getSessionDescription(), headerFactory, messageFactory, contactHeader);
  136. sipProvider.sendRequest(sipinvite.getInviterequest());
  137. lg.info("Erfolgreiches Senden der Invitation");
  138. }
  139. @Override
  140. public void processRequest(RequestEvent requestEvent) {
  141. lg.info("Bekomme Anfrage");
  142. if ((Request.OPTIONS).equals(requestEvent.getRequest().getMethod())) //Options Anfrage von Server nach erfolgreicher Registrierung
  143. {
  144. lg.info("Option Request von Server, erstellen 200 OK zu Server");
  145. try {
  146. SIP200Ok tempOk = new SIP200Ok(messageFactory, requestEvent, contactHeader, headerFactory);
  147. this.sipProvider.sendResponse(tempOk.getResponse());
  148. view.getTxtArea().append("Server Option Request erfolgreich beantwortet\n");
  149. lg.info("Erfolgreiches senden des 200Ok-Headers");
  150. } catch (SipException ex) {
  151. lg.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex);
  152. }
  153. } //Aktive Kommunikation
  154. else if ((Request.INVITE).equals(requestEvent.getRequest().getMethod())) // Invite von anderem Benutzer
  155. {
  156. resetCallParameter();
  157. anrufer = false;
  158. //Falls Anruf ankommt, wichtige Variablen Zwischenspeichern (Branch, Cseq, CallID, proxyTag)
  159. branch = ((ViaHeader) requestEvent.getRequest().getHeader("Via")).getBranch();
  160. cSequenz = ((CSeqHeader) requestEvent.getRequest().getHeader("Cseq")).getSeqNumber();
  161. proxyTag = ((FromHeader) requestEvent.getRequest().getHeader("From")).getTag();
  162. callID = ((CallIdHeader) requestEvent.getRequest().getHeader("CallID"));
  163. //Standartabfolge sobald man angerufen wird
  164. try {
  165. //Trying Response erzeugen und abschicken
  166. SIP100Trying tempTrying = new SIP100Trying(messageFactory, requestEvent, headerFactory);
  167. sipProvider.sendResponse(tempTrying.getTryResponse());
  168. view.getTxtArea().append("Trying geschickt\n");
  169. lg.info("Trying ist raus");
  170. //Ringing Response erzeugen und abschicken noch Schleife mit "Anruf annehmen"
  171. SIP180Ringing tempRinging = new SIP180Ringing(requestEvent, myTag, contactHeader, headerFactory, messageFactory);
  172. Timer timer = new Timer();
  173. timer.scheduleAtFixedRate(new TimerTask() {
  174. int counter = 0;
  175. @Override
  176. public void run() {
  177. try {
  178. if (anrufAngenommen != true && counter % 4 == 0) //Falls man nicht abnimmt, klingeln + Ringing schicken
  179. {
  180. sipProvider.sendResponse(tempRinging.getResponseRing());
  181. audioRinging.startRinging();
  182. } else if (anrufAngenommen == true) //bei annehmen, klingeln aufhören, OK mit SDP schicken
  183. {
  184. audioRinging.endRinging();
  185. audioRinging.endRinging();
  186. SIP200Ok respcall = new SIP200Ok(messageFactory, requestEvent, contactHeader, headerFactory);
  187. SIPSessionDescription sdp = new SIPSessionDescription(myName, myIPAddress, getMYRTPPORT(), requestEvent, anrufer);
  188. respcall.addSDP(sdp.getSessionDescription(), myTag);
  189. sipProvider.sendResponse(respcall.getResponse());
  190. view.getTxtArea().append("Telefonat beginnt\n");
  191. timer.cancel();
  192. } else if (anrufCancel == true) {
  193. timer.cancel();
  194. }
  195. counter++;
  196. } catch (SipException ex) {
  197. }
  198. }
  199. }, 0, 1000);
  200. } catch (SipException ex) {
  201. lg.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex);
  202. }
  203. } else if ((Request.ACK).equals(requestEvent.getRequest().getMethod())) {
  204. } else if ((Request.CANCEL).equals(requestEvent.getRequest().getMethod())) {
  205. System.out.println("Anruf cancel");
  206. view.getTxtArea().append("Anruf wurde gecancelt");
  207. try {
  208. //Cancel Request -> Response 200 Ok + Response 487 Request Terminated
  209. //200 Ok
  210. anrufCancel = true;
  211. SIP200Ok tempOk = new SIP200Ok(messageFactory, requestEvent, contactHeader, headerFactory);
  212. sipProvider.sendResponse(tempOk.getResponse());
  213. view.getTxtArea().append("Anrufender canceld Anfrage\n");
  214. lg.info("Erfolgreiches senden des 200 OkHeaders auf CancelAnfrage");
  215. //487 Request Terminated
  216. } catch (SipException ex) {
  217. Logger.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex);
  218. }
  219. } else if ((Request.BYE).equals(requestEvent.getRequest().getMethod())) {
  220. try {
  221. SIP200Ok tempOk = new SIP200Ok(messageFactory, requestEvent, contactHeader, headerFactory);
  222. this.sipProvider.sendResponse(tempOk.getResponse());
  223. } catch (SipException ex) {
  224. Logger.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex);
  225. }
  226. }
  227. }
  228. @Override
  229. public void processResponse(ResponseEvent responseEvent) {
  230. if (responseEvent.getResponse().getStatusCode() == Response.UNAUTHORIZED) {
  231. try {
  232. cSequenz += 1L;
  233. branch += 10;
  234. SIPUnauthReq req2 = new SIPUnauthReq(myName, proxyAddress, myTag, myIPAddress, branch, cSequenz, MYSIPPORT, contactHeader, addressFactory, headerFactory, responseEvent, messageFactory);
  235. sipProvider.sendRequest(req2.getUnauthReq());
  236. view.getTxtArea().append("Erfolgreich registriert\n");
  237. } catch (SipException ex) {
  238. lg.getLogger(SIPmodel.class.getName()).log(Level.SEVERE, null, ex);
  239. }
  240. } else if (responseEvent.getResponse().getStatusCode() == Response.OK) {
  241. //Überprüfen ob Ok Header mit SDP ist
  242. if ((((ContentTypeHeader) responseEvent.getResponse().getHeader("Content-Type")).getContentSubType()).equals("sdp")) {
  243. lg.info("Erfolgreichen Response 200 OK mit SDP bekommen");
  244. getRTPParameters(responseEvent);
  245. // SIPACK ack = new SIPACK();
  246. // sipProvider.sendResponse(rspns);
  247. /*
  248. System.out.println("Starte RTP Session");
  249. //String[] s = null;
  250. SoundSenderDemo aDemo = null;
  251. // try {
  252. // aDemo = new SoundSenderDemo(true);
  253. // } catch (UnknownHostException | InterruptedException ex) {
  254. // Logger.getLogger(CommandInvite.class.getName()).log(Level.SEVERE, null, ex);
  255. // }
  256. try {
  257. aDemo.SendDemo(null);
  258. } catch (UnknownHostException | InterruptedException ex) {
  259. Logger.getLogger(CommandInvite.class.getName()).log(Level.SEVERE, null, ex);
  260. }
  261. System.out.println("Beende RTP Session");
  262. */
  263. } else {
  264. lg.info("Erfolgreichen Response (200 OK) bekommen");
  265. }
  266. } else if (responseEvent.getResponse().getStatusCode() == Response.RINGING) {
  267. ToHeader temp = (ToHeader) responseEvent.getResponse().getHeader("To");
  268. proxyTag = temp.getTag();
  269. }
  270. }
  271. public void byecall(String calluser) throws ParseException, InvalidArgumentException, SipException {
  272. cSequenz++;
  273. SIPBye tempBye = new SIPBye(calluser, proxyAddress, myName, myIPAddress, myTag, proxyTag, MYSIPPORT, branch, callID, cSequenz, messageFactory, contactHeader, addressFactory, headerFactory);
  274. sipProvider.sendRequest(tempBye.getByeRequest());
  275. lg.info("Erfolgreiches Senden des BYE Headers");
  276. }
  277. public void getRTPParameters(ResponseEvent responseEvent) {
  278. int identifier = 0;
  279. String[] reqbody = (responseEvent.getResponse()).toString().split("\\s|" + System.getProperty("line.seperator"));
  280. for (String req : reqbody) {
  281. if (identifier == 1) {
  282. proxyRTPPort = Integer.valueOf(req);
  283. identifier = 0;
  284. } else if (identifier == 2) {
  285. RTPCodec = req;
  286. identifier = 0;
  287. }
  288. if (req.startsWith("m=audio")) {
  289. identifier = 1;
  290. } else if (req.startsWith("a=rtpmap:")) {
  291. identifier = 2;
  292. }
  293. }
  294. }
  295. public void resetCallParameter() {
  296. anrufAngenommen = false;
  297. anrufer = false;
  298. }
  299. public void anrufAnnehmen() {
  300. anrufAngenommen = true;
  301. }
  302. //Get Methoden falls man mal die Parameter braucht
  303. public String getmyName() {
  304. return myName;
  305. }
  306. public Integer getMyPort() {
  307. return MYSIPPORT;
  308. }
  309. public String getMyIPAdress() {
  310. return myIPAddress;
  311. }
  312. // Herausfinden bei welchen Events die unteren Funktionen aufgerufen werden -> evtl brauchbar
  313. @Override
  314. public void processTimeout(TimeoutEvent timeoutEvent) {
  315. //view.getTxtArea().append("processTimeout\n");
  316. }
  317. @Override
  318. public void processIOException(IOExceptionEvent exceptionEvent) {
  319. //view.getTxtArea().append("processIOException\n");
  320. }
  321. @Override
  322. public void processTransactionTerminated(
  323. TransactionTerminatedEvent transactionTerminatedEvent) {
  324. //view.getTxtArea().append("processTransactionTerminated\n");
  325. }
  326. @Override
  327. public void processDialogTerminated(
  328. DialogTerminatedEvent dialogTerminatedEvent) {
  329. //view.getTxtArea().append("processDialogTerminated\n");
  330. }
  331. @Override
  332. public void processDialogTimeout(DialogTimeoutEvent timeoutEvent) {
  333. //view.getTxtArea().append("processDialogTerminated\n");
  334. }
  335. /**
  336. * @param myPort the MYSIPPORT to set
  337. */
  338. /**
  339. * @return the myName
  340. */
  341. public String getMyName() {
  342. return myName;
  343. }
  344. /**
  345. * @return the proxyTag
  346. */
  347. public String getProxyTag() {
  348. return proxyTag;
  349. }
  350. /**
  351. * @param proxyTag the proxyTag to set
  352. */
  353. public void setProxyTag(String proxyTag) {
  354. this.proxyTag = proxyTag;
  355. }
  356. /**
  357. * @return the myTag
  358. */
  359. public String getMyTag() {
  360. return myTag;
  361. }
  362. /**
  363. * @param myTag the myTag to set
  364. */
  365. public void setMyTag(String myTag) {
  366. this.myTag = myTag;
  367. }
  368. /**
  369. * @return the branch
  370. */
  371. public String getBranch() {
  372. return branch;
  373. }
  374. /**
  375. * @param proxyRTPPort the proxyRTPPort to set
  376. */
  377. public void setProxyRTPPort(int proxyRTPPort) {
  378. this.proxyRTPPort = proxyRTPPort;
  379. }
  380. /**
  381. * @param RTPCodec the RTPCodec to set
  382. */
  383. public void setRTPCodec(String RTPCodec) {
  384. this.RTPCodec = RTPCodec;
  385. }
  386. /**
  387. * @return the proxyRTPPort
  388. */
  389. public int getProxyRTPPort() {
  390. return proxyRTPPort;
  391. }
  392. /**
  393. * @return the RTPCodec
  394. */
  395. public String getRTPCodec() {
  396. return RTPCodec;
  397. }
  398. /**
  399. * @return the MYRTPPORT
  400. */
  401. public static int getMYRTPPORT() {
  402. return MYRTPPORT;
  403. }
  404. /**
  405. * @return the MYRTCPPORT
  406. */
  407. public static int getMYRTCPPORT() {
  408. return MYRTCPPORT;
  409. }
  410. }