PageRenderTime 45ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/jain-sip-ha/jboss-5/src/test/java/org/mobicents/ha/javax/sip/SimpleB2BUAHandler.java

http://mobicents.googlecode.com/
Java | 620 lines | 462 code | 52 blank | 106 comment | 90 complexity | 8e21fcaebeb79db65fd5deb71ebfbfb3 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2011, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.mobicents.ha.javax.sip;
  23. import gov.nist.javax.sip.ListeningPointImpl;
  24. import gov.nist.javax.sip.RequestEventExt;
  25. import gov.nist.javax.sip.ResponseEventExt;
  26. import gov.nist.javax.sip.header.Route;
  27. import gov.nist.javax.sip.header.RouteList;
  28. import gov.nist.javax.sip.header.Via;
  29. import gov.nist.javax.sip.header.ViaList;
  30. import gov.nist.javax.sip.message.MessageExt;
  31. import gov.nist.javax.sip.message.SIPRequest;
  32. import java.text.ParseException;
  33. import java.util.Collections;
  34. import java.util.HashSet;
  35. import java.util.Iterator;
  36. import java.util.ListIterator;
  37. import java.util.Set;
  38. import java.util.concurrent.atomic.AtomicLong;
  39. import javax.sip.ClientTransaction;
  40. import javax.sip.Dialog;
  41. import javax.sip.InvalidArgumentException;
  42. import javax.sip.ListeningPoint;
  43. import javax.sip.RequestEvent;
  44. import javax.sip.ResponseEvent;
  45. import javax.sip.ServerTransaction;
  46. import javax.sip.SipException;
  47. import javax.sip.SipProvider;
  48. import javax.sip.SipStack;
  49. import javax.sip.address.SipURI;
  50. import javax.sip.address.URI;
  51. import javax.sip.header.CSeqHeader;
  52. import javax.sip.header.CallIdHeader;
  53. import javax.sip.header.ContactHeader;
  54. import javax.sip.header.ContentLengthHeader;
  55. import javax.sip.header.ContentTypeHeader;
  56. import javax.sip.header.EventHeader;
  57. import javax.sip.header.ExpiresHeader;
  58. import javax.sip.header.FromHeader;
  59. import javax.sip.header.Header;
  60. import javax.sip.header.HeaderFactory;
  61. import javax.sip.header.RecordRouteHeader;
  62. import javax.sip.header.RouteHeader;
  63. import javax.sip.header.SubscriptionStateHeader;
  64. import javax.sip.header.ToHeader;
  65. import javax.sip.header.ViaHeader;
  66. import javax.sip.message.MessageFactory;
  67. import javax.sip.message.Request;
  68. import javax.sip.message.Response;
  69. import org.jboss.cache.CacheException;
  70. import org.jboss.cache.Fqn;
  71. import org.mobicents.ha.javax.sip.cache.MobicentsSipCache;
  72. public class SimpleB2BUAHandler {
  73. private SipProvider sipProvider;
  74. private MessageFactory messageFactory;
  75. private HeaderFactory headerFactory;
  76. private ServerTransaction serverTransaction;
  77. private boolean createInviteOnAck = false;
  78. private SipStack sipStack;
  79. int myPort;
  80. String transport;
  81. private boolean sendAckOn2xx = true;
  82. public SimpleB2BUAHandler(SipProvider sipProvider, HeaderFactory headerFactory, MessageFactory messageFactory, int port, String transport) {
  83. // this.localTag = localTag;
  84. this.sipProvider = sipProvider;
  85. this.sipStack = sipProvider.getSipStack();
  86. this.messageFactory = messageFactory;
  87. this.headerFactory = headerFactory;
  88. myPort = port;
  89. this.transport = transport;
  90. }
  91. /**
  92. * @return the incomingDialog
  93. */
  94. public String getIncomingDialogId() {
  95. String incomingDialogId = null;
  96. try {
  97. incomingDialogId = (String) ((MobicentsSipCache)((ClusteredSipStack)sipProvider.getSipStack()).getSipCache()).getMobicentsCache().getJBossCache().get(Fqn.fromString("DIALOG_IDS"), "incomingDialogId");
  98. } catch (CacheException e) {
  99. // TODO Auto-generated catch block
  100. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  101. }
  102. return incomingDialogId;
  103. }
  104. /**
  105. * @return the outgoingDialog
  106. */
  107. public String getOutgoingDialogId() {
  108. String outgoingDialogId = null;
  109. try {
  110. outgoingDialogId = (String) ((MobicentsSipCache)((ClusteredSipStack)sipProvider.getSipStack()).getSipCache()).getMobicentsCache().getJBossCache().get(Fqn.fromString("DIALOG_IDS"), "outgoingDialogId");
  111. } catch (CacheException e) {
  112. // TODO Auto-generated catch block
  113. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  114. }
  115. return outgoingDialogId;
  116. }
  117. /**
  118. * @return the incomingDialog
  119. */
  120. public Dialog getIncomingDialog() {
  121. String incomingDialogId = null;
  122. try {
  123. incomingDialogId = (String) ((MobicentsSipCache)((ClusteredSipStack)sipProvider.getSipStack()).getSipCache()).getMobicentsCache().getJBossCache().get(Fqn.fromString("DIALOG_IDS"), "incomingDialogId");
  124. } catch (CacheException e) {
  125. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  126. }
  127. ((SipStackImpl)sipStack).getStackLogger().logInfo("Incoming Dialog Id " + incomingDialogId);
  128. if(incomingDialogId == null) {
  129. return null;
  130. }
  131. return ((ClusteredSipStack)sipProvider.getSipStack()).getDialog(incomingDialogId);
  132. }
  133. /**
  134. * @return the outgoingDialog
  135. */
  136. public Dialog getOutgoingDialog() {
  137. String outgoingDialogId = null;
  138. try {
  139. outgoingDialogId = (String) ((MobicentsSipCache)((ClusteredSipStack)sipProvider.getSipStack()).getSipCache()).getMobicentsCache().getJBossCache().get(Fqn.fromString("DIALOG_IDS"), "outgoingDialogId");
  140. } catch (CacheException e) {
  141. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  142. }
  143. ((SipStackImpl)sipStack).getStackLogger().logInfo("Outgoing Dialog Id " + outgoingDialogId);
  144. if(outgoingDialogId == null) {
  145. return null;
  146. }
  147. return ((ClusteredSipStack)sipProvider.getSipStack()).getDialog(outgoingDialogId);
  148. }
  149. private void storeOutgoingDialogId(String outgoingDialogId) {
  150. ((ClusteredSipStack)sipProvider.getSipStack()).getStackLogger().logDebug("Storing outgoing dialog Id " + outgoingDialogId);
  151. try {
  152. ((MobicentsSipCache)((ClusteredSipStack)sipProvider.getSipStack()).getSipCache()).getMobicentsCache().getJBossCache().put(Fqn.fromString("DIALOG_IDS"), "outgoingDialogId", outgoingDialogId);
  153. } catch (CacheException e) {
  154. // TODO Auto-generated catch block
  155. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  156. }
  157. }
  158. private void storeIncomingDialogId(String incomingDialogId) {
  159. ((ClusteredSipStack)sipProvider.getSipStack()).getStackLogger().logDebug("Storing incoming dialog Id " + incomingDialogId);
  160. try {
  161. ((MobicentsSipCache)((ClusteredSipStack)sipProvider.getSipStack()).getSipCache()).getMobicentsCache().getJBossCache().put(Fqn.fromString("DIALOG_IDS"), "incomingDialogId", incomingDialogId);
  162. } catch (CacheException e) {
  163. // TODO Auto-generated catch block
  164. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  165. }
  166. }
  167. private void storeServerTransactionId(String branchId) {
  168. ((ClusteredSipStack)sipProvider.getSipStack()).getStackLogger().logDebug("Storing transaction Id " + branchId);
  169. try {
  170. ((MobicentsSipCache)((ClusteredSipStack)sipProvider.getSipStack()).getSipCache()).getMobicentsCache().getJBossCache().put(Fqn.fromString("STX_IDS"), "serverTransactionId", branchId);
  171. } catch (CacheException e) {
  172. // TODO Auto-generated catch block
  173. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  174. }
  175. }
  176. /**
  177. * @return the outgoingDialog
  178. */
  179. public ServerTransaction getServerTransaction() {
  180. if(serverTransaction != null) {
  181. return serverTransaction;
  182. }
  183. String serverTransactionId = null;
  184. try {
  185. serverTransactionId = (String) ((MobicentsSipCache)((ClusteredSipStack)sipProvider.getSipStack()).getSipCache()).getMobicentsCache().getJBossCache().get(Fqn.fromString("STX_IDS"), "serverTransactionId");
  186. } catch (CacheException e) {
  187. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  188. }
  189. ((ClusteredSipStack)sipStack).getStackLogger().logInfo("server transaction Id " + serverTransactionId);
  190. if(serverTransactionId == null) {
  191. return null;
  192. }
  193. return (ServerTransaction) ((ClusteredSipStack)sipProvider.getSipStack()).findTransaction(serverTransactionId, true);
  194. }
  195. public void processInvite(RequestEvent requestEvent) {
  196. //System.out.println("Got invite: "+requestEvent.getRequest());
  197. try {
  198. serverTransaction = requestEvent.getServerTransaction();
  199. if (serverTransaction == null) {
  200. try {
  201. serverTransaction = sipProvider.getNewServerTransaction(requestEvent.getRequest());
  202. }
  203. catch (Exception e) {
  204. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  205. return;
  206. }
  207. }
  208. storeServerTransactionId(serverTransaction.getBranchId());
  209. //serverTransaction.sendResponse(messageFactory.createResponse(100, requestEvent.getRequest()));
  210. if(serverTransaction.getDialog() == null) {
  211. setupIncomingDialog();
  212. forwardInvite(5070);
  213. } else {
  214. Request request = getIncomingDialog().createRequest(Request.INVITE);
  215. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  216. getIncomingDialog().sendRequest(ct);
  217. }
  218. // not used in basic reinvite
  219. if(((FromHeader)serverTransaction.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI().toString().contains("ReInviteSubsNotify")) {
  220. createInviteOnAck = true;
  221. }
  222. } catch (Exception ex) {
  223. ex.printStackTrace();
  224. }
  225. }
  226. /**
  227. * @param serverTransaction2
  228. * @return
  229. * @throws SipException
  230. */
  231. private void setupIncomingDialog() throws SipException {
  232. Dialog incomingDialog = sipProvider.getNewDialog(serverTransaction);
  233. incomingDialog.setApplicationData(this);
  234. }
  235. /**
  236. * @param incomingDialog2
  237. * @return
  238. * @throws SipException
  239. */
  240. private void forwardInvite(int peerPort) throws SipException {
  241. Request request = createRequest(getServerTransaction().getRequest(), peerPort);
  242. ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  243. Dialog outgoingDialog = sipProvider.getNewDialog(ct);
  244. outgoingDialog.setApplicationData(this);
  245. ct.sendRequest();
  246. }
  247. @SuppressWarnings("unchecked")
  248. private Request createRequest(Request origRequest, int peerPort) throws SipException {
  249. final SIPRequest request = (SIPRequest) origRequest.clone();
  250. try {
  251. long l = new AtomicLong().incrementAndGet();
  252. request.getFromHeader().setTag(Long.toString(l));
  253. } catch (ParseException e1) {
  254. throw new SipException("failed to set local tag", e1);
  255. }
  256. final String transport = request.getTopmostViaHeader().getTransport();
  257. final ListeningPointImpl listeningPointImpl = (ListeningPointImpl) sipProvider.getListeningPoint(transport);
  258. final ViaList viaList = new ViaList();
  259. viaList.add((Via) listeningPointImpl.createViaHeader());
  260. request.setVia(viaList);
  261. try {
  262. request.setHeader(headerFactory.createMaxForwardsHeader(70));
  263. } catch (InvalidArgumentException e) {
  264. throw new SipException("Failed to create max forwards header",e);
  265. }
  266. request.setHeader((Header) sipProvider.getNewCallId());
  267. // note: cseq will be set by dialog when sending
  268. // set contact if the original response had it
  269. if (origRequest.getHeader(ContactHeader.NAME) != null) {
  270. request.setHeader(listeningPointImpl.createContactHeader());
  271. }
  272. /*
  273. * Route header fields of the upstream request MAY be copied in the
  274. * downstream request, except the topmost Route header if it is under
  275. * the responsibility of the B2BUA. Additional Route header fields MAY
  276. * also be added to the downstream request.
  277. */
  278. if (getOutgoingDialog() == null || getOutgoingDialog().getState() == null) {
  279. // first request, no route available
  280. final RouteList routeList = request.getRouteHeaders();
  281. if (routeList != null) {
  282. final RouteHeader topRoute = routeList.get(0);
  283. final URI topRouteURI = topRoute.getAddress().getURI();
  284. if (topRouteURI.isSipURI()) {
  285. final SipURI topRouteSipURI = (SipURI) topRouteURI;
  286. if (topRouteSipURI.getHost().equals(listeningPointImpl.getIPAddress())
  287. && topRouteSipURI.getPort() == listeningPointImpl.getPort()) {
  288. if (routeList.size() > 1) {
  289. routeList.remove(0);
  290. }
  291. else {
  292. request.removeHeader(RouteHeader.NAME);
  293. }
  294. }
  295. }
  296. }
  297. }
  298. else {
  299. // replace route in orig request with the one in dialog
  300. request.removeHeader(RouteHeader.NAME);
  301. final RouteList routeList = new RouteList();
  302. for (Iterator<Route> it = getOutgoingDialog().getRouteSet(); it.hasNext();) {
  303. Route route = it.next();
  304. routeList.add(route);
  305. }
  306. if (!routeList.isEmpty()) {
  307. request.addHeader(routeList);
  308. }
  309. }
  310. /*
  311. * Record-Route header fields of the upstream request are not copied in
  312. * the new downstream request, as Record-Route is only meaningful for
  313. * the upstream dialog.
  314. */
  315. request.removeHeader(RecordRouteHeader.NAME);
  316. ((SipURI)request.getRequestURI()).setPort(peerPort);
  317. return request;
  318. }
  319. public void processAck(RequestEvent requestEvent) {
  320. int remotePort = ((RequestEventExt)requestEvent).getRemotePort() ;
  321. if(ListeningPoint.TCP.equalsIgnoreCase(transport)) {
  322. remotePort = ((MessageExt)requestEvent.getRequest()).getTopmostViaHeader().getPort();
  323. }
  324. ((ClusteredSipStack)sipStack).getStackLogger().logDebug("remotePort = " + remotePort);
  325. try {
  326. if(!sendAckOn2xx) {
  327. Dialog dialog = null;
  328. if(remotePort == 5070) {
  329. dialog = getIncomingDialog();
  330. }
  331. if(remotePort == 5050 || remotePort == 5060 || remotePort == 5065) {
  332. storeIncomingDialogId(requestEvent.getDialog().getDialogId());
  333. dialog = getOutgoingDialog();
  334. }
  335. final Request ack = dialog.createAck(((MessageExt)requestEvent.getRequest()).getCSeqHeader().getSeqNumber());
  336. dialog.sendAck(ack);
  337. } else {
  338. if(myPort == 5080 && getIncomingDialogId() == null) {
  339. storeIncomingDialogId(requestEvent.getDialog().getDialogId());
  340. }
  341. if(remotePort == 5050 || remotePort == 5060 || remotePort == 5065) {
  342. storeIncomingDialogId(requestEvent.getDialog().getDialogId());
  343. }
  344. }
  345. if(createInviteOnAck) {
  346. createInviteOnAck = false;
  347. Request request = getIncomingDialog().createRequest("INVITE");
  348. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  349. getIncomingDialog().sendRequest(ct);
  350. }
  351. } catch (Exception e) {
  352. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  353. }
  354. }
  355. public void processBye(RequestEvent requestEvent) {
  356. try {
  357. int remotePort = ((RequestEventExt)requestEvent).getRemotePort() ;
  358. if(ListeningPoint.TCP.equalsIgnoreCase(transport)) {
  359. remotePort = ((MessageExt)requestEvent.getRequest()).getTopmostViaHeader().getPort();
  360. }
  361. ((ClusteredSipStack)sipStack).getStackLogger().logDebug("remotePort = " + remotePort);
  362. requestEvent.getServerTransaction().sendResponse(messageFactory.createResponse(200, requestEvent.getRequest()));
  363. Dialog dialog = getOutgoingDialog();
  364. if(remotePort == 5060 || remotePort == 5065) {
  365. dialog = getIncomingDialog();
  366. }
  367. Request request = dialog.createRequest(Request.BYE);
  368. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  369. dialog.sendRequest(ct);
  370. }
  371. catch (Exception e) {
  372. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  373. }
  374. }
  375. public void processSubscribe(RequestEvent requestEvent) {
  376. try {
  377. Response response = messageFactory.createResponse(200, requestEvent.getRequest());
  378. response.addHeader(headerFactory.createHeader(ExpiresHeader.NAME, "3600"));
  379. requestEvent.getServerTransaction().sendResponse(response);
  380. Dialog dialog = getOutgoingDialog();
  381. Request request = dialog.createRequest(Request.SUBSCRIBE);
  382. ((SipURI)request.getRequestURI()).setPort(5070);
  383. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  384. dialog.sendRequest(ct);
  385. }
  386. catch (Exception e) {
  387. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  388. }
  389. }
  390. public void processNotify(RequestEvent requestEvent) {
  391. try {
  392. requestEvent.getServerTransaction().sendResponse(messageFactory.createResponse(200, requestEvent.getRequest()));
  393. Dialog dialog = getIncomingDialog();
  394. Request request = dialog.createRequest(Request.NOTIFY);
  395. request.addHeader(headerFactory.createHeader(SubscriptionStateHeader.NAME, SubscriptionStateHeader.ACTIVE));
  396. request.addHeader(headerFactory.createHeader(EventHeader.NAME, "presence"));
  397. ((SipURI)request.getRequestURI()).setUser(null);
  398. // ((SipURI)request.getRequestURI()).setHost(IP_ADDRESS);
  399. ((SipURI)request.getRequestURI()).setPort(5050);
  400. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  401. dialog.sendRequest(ct);
  402. }
  403. catch (Exception e) {
  404. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  405. }
  406. }
  407. public void process180(ResponseEvent responseEvent) {
  408. try {
  409. forwardResponse(responseEvent.getResponse());
  410. }
  411. catch (Exception e) {
  412. ((SipStackImpl)sipStack).getStackLogger().logError("unexpected exception", e);
  413. }
  414. }
  415. /**
  416. * @param responseEvent
  417. * @throws InvalidArgumentException
  418. */
  419. @SuppressWarnings("unchecked")
  420. private void forwardResponse(Response receivedResponse) throws SipException, InvalidArgumentException {
  421. if(receivedResponse.getStatusCode() == 202){
  422. return;
  423. }
  424. System.out.println("Forwarding " + receivedResponse);
  425. final ServerTransaction origServerTransaction = this.getServerTransaction();
  426. Response forgedResponse = null;
  427. try {
  428. forgedResponse = messageFactory.createResponse(receivedResponse.getStatusCode(), origServerTransaction.getRequest());
  429. } catch (ParseException e) {
  430. throw new SipException("Failed to forge message", e);
  431. }
  432. // if ((getIncomingDialog() == null || getIncomingDialog().getState() == DialogState.EARLY) && localTag != null && getIncomingDialog() != null && getIncomingDialog().isServer()) {
  433. // // no tag set in the response, since the dialog creating transaction didn't had it
  434. // try {
  435. // ((ToHeader)forgedResponse.getHeader(ToHeader.NAME)).setTag(localTag);
  436. // } catch (ParseException e) {
  437. // throw new SipException("Failed to set local tag", e);
  438. // }
  439. // }
  440. // copy headers
  441. ListIterator<String> lit = receivedResponse.getHeaderNames();
  442. String headerName = null;
  443. ListIterator<Header> headersIterator = null;
  444. while (lit.hasNext()) {
  445. headerName = lit.next();
  446. if (SimpleB2BUAHandler.getHeadersToOmmitOnResponseCopy().contains(headerName)) {
  447. continue;
  448. } else {
  449. forgedResponse.removeHeader(headerName);
  450. headersIterator = receivedResponse.getHeaders(headerName);
  451. while (headersIterator.hasNext()) {
  452. forgedResponse.addLast((Header)headersIterator.next().clone());
  453. }
  454. }
  455. }
  456. // Copy content
  457. final byte[] rawOriginal = receivedResponse.getRawContent();
  458. if (rawOriginal != null && rawOriginal.length != 0) {
  459. final byte[] copy = new byte[rawOriginal.length];
  460. System.arraycopy(rawOriginal, 0, copy, 0, copy.length);
  461. try {
  462. forgedResponse.setContent(copy, (ContentTypeHeader) forgedResponse
  463. .getHeader(ContentTypeHeader.NAME));
  464. } catch (ParseException e) {
  465. throw new SipException("Failed to copy content.",e);
  466. }
  467. }
  468. // set contact if the received response had it
  469. if (receivedResponse.getHeader(ContactHeader.NAME) != null) {
  470. final String transport = ((ViaHeader) forgedResponse.getHeader(ViaHeader.NAME)).getTransport();
  471. forgedResponse.setHeader(((ListeningPointImpl)sipProvider.getListeningPoint(transport)).createContactHeader());
  472. }
  473. // set the to tag mandatory so that the dialog gets replicated
  474. if(((MessageExt)forgedResponse).getToHeader().getTag() == null) {
  475. try {
  476. ((MessageExt)forgedResponse).getToHeader().setTag("696");
  477. } catch (ParseException e) {
  478. e.printStackTrace();
  479. }
  480. }
  481. origServerTransaction.sendResponse(forgedResponse);
  482. }
  483. public void process200(ResponseEvent responseEvent) {
  484. boolean isRetransmission = ((ResponseEventExt)responseEvent).isRetransmission();
  485. ClientTransaction clientTransaction = ((ResponseEventExt)responseEvent).getClientTransaction();
  486. ((ClusteredSipStack)sipStack).getStackLogger().logDebug("clientTransaction = " + clientTransaction + ", isRetransmission " + isRetransmission);
  487. try {
  488. final CSeqHeader cSeqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
  489. if (cSeqHeader.getMethod().equals(Request.INVITE)) {
  490. processInvite200(responseEvent,cSeqHeader);
  491. }
  492. else if (cSeqHeader.getMethod().equals(Request.BYE) || cSeqHeader.getMethod().equals(Request.SUBSCRIBE) || cSeqHeader.getMethod().equals(Request.NOTIFY)) {
  493. processBye200(responseEvent);
  494. }
  495. else {
  496. System.err.println("Unexpected response: "+responseEvent.getResponse());
  497. }
  498. } catch (Exception ex) {
  499. ex.printStackTrace();
  500. }
  501. }
  502. /**
  503. * @param responseEvent
  504. * @throws SipException
  505. * @throws InvalidArgumentException
  506. */
  507. private void processInvite200(ResponseEvent responseEvent,CSeqHeader cseq) throws InvalidArgumentException, SipException {
  508. // lets ack it ourselves to avoid UAS retransmissions due to
  509. // forwarding of this response and further UAC Ack
  510. // note that the app does not handles UAC ACKs
  511. String outgoingDialogId = responseEvent.getDialog().getDialogId();
  512. int remotePort = ((ResponseEventExt)responseEvent).getRemotePort() ;
  513. if(ListeningPoint.TCP.equalsIgnoreCase(transport)) {
  514. remotePort = ((MessageExt)responseEvent.getResponse()).getTopmostViaHeader().getPort();
  515. }
  516. ((ClusteredSipStack)sipStack).getStackLogger().logDebug("remotePort = " + remotePort);
  517. if(remotePort == 5065 || remotePort == 5081) {
  518. storeOutgoingDialogId(outgoingDialogId);
  519. }
  520. if(myPort == 5080 && getOutgoingDialogId() == null) {
  521. storeOutgoingDialogId(outgoingDialogId);
  522. }
  523. if(sendAckOn2xx) {
  524. System.out.println("Generating ACK to 200");
  525. final Request ack = responseEvent.getDialog().createAck(cseq.getSeqNumber());
  526. responseEvent.getDialog().sendAck(ack);
  527. }
  528. forwardResponse(responseEvent.getResponse());
  529. }
  530. /**
  531. * @param responseEvent
  532. */
  533. private void processBye200(ResponseEvent responseEvent) {
  534. // nothing to do
  535. }
  536. private static Set<String> HEADERS_TO_OMMIT_ON_RESPONSE_COPY;
  537. private static Set<String> getHeadersToOmmitOnResponseCopy() {
  538. if (HEADERS_TO_OMMIT_ON_RESPONSE_COPY == null) {
  539. final Set<String> set = new HashSet<String>();
  540. set.add(RouteHeader.NAME);
  541. set.add(RecordRouteHeader.NAME);
  542. set.add(ViaHeader.NAME);
  543. set.add(CallIdHeader.NAME);
  544. set.add(CSeqHeader.NAME);
  545. set.add(ContactHeader.NAME);
  546. set.add(FromHeader.NAME);
  547. set.add(ToHeader.NAME);
  548. set.add(ContentLengthHeader.NAME);
  549. HEADERS_TO_OMMIT_ON_RESPONSE_COPY = Collections.unmodifiableSet(set);
  550. }
  551. return HEADERS_TO_OMMIT_ON_RESPONSE_COPY;
  552. }
  553. public void checkState() {
  554. // TODO Auto-generated method stub
  555. }
  556. /**
  557. * @param sendAckOn2xx the sendAckOn2xx to set
  558. */
  559. public void setSendAckOn2xx(boolean sendAckOn2xx) {
  560. this.sendAckOn2xx = sendAckOn2xx;
  561. }
  562. /**
  563. * @return the sendAckOn2xx
  564. */
  565. public boolean isSendAckOn2xx() {
  566. return sendAckOn2xx;
  567. }
  568. }