PageRenderTime 38ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 1ms

/servers/jain-slee/resources/sip11/ra/src/main/java/org/mobicents/slee/resource/sip11/SipResourceAdaptor.java

http://mobicents.googlecode.com/
Java | 1745 lines | 1191 code | 183 blank | 371 comment | 271 complexity | 2c2b4e94c4530cf889e4db7b1883a661 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

Large files files are truncated, but you can click here to view the full file

  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.slee.resource.sip11;
  23. import gov.nist.javax.sip.ResponseEventExt;
  24. import gov.nist.javax.sip.Utils;
  25. import gov.nist.javax.sip.message.SIPRequest;
  26. import gov.nist.javax.sip.message.SIPResponse;
  27. import gov.nist.javax.sip.stack.SIPClientTransaction;
  28. import gov.nist.javax.sip.stack.SIPServerTransaction;
  29. import gov.nist.javax.sip.stack.SIPTransaction;
  30. import java.net.DatagramSocket;
  31. import java.net.InetSocketAddress;
  32. import java.util.ArrayList;
  33. import java.util.Arrays;
  34. import java.util.HashSet;
  35. import java.util.List;
  36. import java.util.Properties;
  37. import java.util.Set;
  38. import javax.sip.ClientTransaction;
  39. import javax.sip.Dialog;
  40. import javax.sip.DialogState;
  41. import javax.sip.DialogTerminatedEvent;
  42. import javax.sip.IOExceptionEvent;
  43. import javax.sip.ListeningPoint;
  44. import javax.sip.ObjectInUseException;
  45. import javax.sip.RequestEvent;
  46. import javax.sip.ResponseEvent;
  47. import javax.sip.ServerTransaction;
  48. import javax.sip.SipFactory;
  49. import javax.sip.SipListener;
  50. import javax.sip.SipProvider;
  51. import javax.sip.TimeoutEvent;
  52. import javax.sip.Transaction;
  53. import javax.sip.TransactionState;
  54. import javax.sip.TransactionTerminatedEvent;
  55. import javax.sip.address.AddressFactory;
  56. import javax.sip.address.URI;
  57. import javax.sip.header.CSeqHeader;
  58. import javax.sip.header.CallIdHeader;
  59. import javax.sip.header.FromHeader;
  60. import javax.sip.header.Header;
  61. import javax.sip.header.HeaderFactory;
  62. import javax.sip.header.MaxForwardsHeader;
  63. import javax.sip.header.RouteHeader;
  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 javax.slee.Address;
  70. import javax.slee.SLEEException;
  71. import javax.slee.facilities.EventLookupFacility;
  72. import javax.slee.facilities.Tracer;
  73. import javax.slee.resource.ActivityAlreadyExistsException;
  74. import javax.slee.resource.ActivityFlags;
  75. import javax.slee.resource.ActivityHandle;
  76. import javax.slee.resource.ActivityIsEndingException;
  77. import javax.slee.resource.ConfigProperties;
  78. import javax.slee.resource.ConfigProperties.Property;
  79. import javax.slee.resource.EventFlags;
  80. import javax.slee.resource.FailureReason;
  81. import javax.slee.resource.FireEventException;
  82. import javax.slee.resource.FireableEventType;
  83. import javax.slee.resource.IllegalEventException;
  84. import javax.slee.resource.InvalidConfigurationException;
  85. import javax.slee.resource.Marshaler;
  86. import javax.slee.resource.ReceivableService;
  87. import javax.slee.resource.ResourceAdaptorContext;
  88. import javax.slee.resource.UnrecognizedActivityHandleException;
  89. import net.java.slee.resource.sip.CancelRequestEvent;
  90. import net.java.slee.resource.sip.DialogForkedEvent;
  91. import org.mobicents.ha.javax.sip.ClusteredSipStack;
  92. import org.mobicents.ha.javax.sip.LoadBalancerElector;
  93. import org.mobicents.ha.javax.sip.cache.SipResourceAdaptorMobicentsSipCache;
  94. import org.mobicents.slee.container.resource.SleeEndpoint;
  95. import org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptor;
  96. import org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext;
  97. import org.mobicents.slee.resource.sip11.wrappers.ACKDummyTransaction;
  98. import org.mobicents.slee.resource.sip11.wrappers.ClientDialogWrapper;
  99. import org.mobicents.slee.resource.sip11.wrappers.ClientTransactionWrapper;
  100. import org.mobicents.slee.resource.sip11.wrappers.DialogWrapper;
  101. import org.mobicents.slee.resource.sip11.wrappers.DialogWrapperAppData;
  102. import org.mobicents.slee.resource.sip11.wrappers.RequestEventWrapper;
  103. import org.mobicents.slee.resource.sip11.wrappers.ResponseEventWrapper;
  104. import org.mobicents.slee.resource.sip11.wrappers.ServerTransactionWrapper;
  105. import org.mobicents.slee.resource.sip11.wrappers.ServerTransactionWrapperAppData;
  106. import org.mobicents.slee.resource.sip11.wrappers.TimeoutEventWrapper;
  107. import org.mobicents.slee.resource.sip11.wrappers.TransactionWrapper;
  108. import org.mobicents.slee.resource.sip11.wrappers.TransactionWrapperAppData;
  109. import org.mobicents.slee.resource.sip11.wrappers.Wrapper;
  110. public class SipResourceAdaptor implements SipListener,FaultTolerantResourceAdaptor<SipActivityHandle, String> {
  111. // Config Properties Names -------------------------------------------
  112. private static final String SIP_BIND_ADDRESS = "javax.sip.IP_ADDRESS";
  113. private static final String SIP_PORT_BIND = "javax.sip.PORT";
  114. private static final String TRANSPORTS_BIND = "javax.sip.TRANSPORT";
  115. private static final String STACK_NAME_BIND = "javax.sip.STACK_NAME";
  116. private static final String LOAD_BALANCER_HEART_BEAT_SERVICE_CLASS = "org.mobicents.ha.javax.sip.LoadBalancerHeartBeatingServiceClassName";
  117. private static final String BALANCERS = "org.mobicents.ha.javax.sip.BALANCERS";
  118. private static final String LOOSE_DIALOG_VALIDATION = "org.mobicents.javax.sip.LOOSE_DIALOG_VALIDATION";
  119. // Config Properties Values -------------------------------------------
  120. private int port;
  121. private Set<String> transports = new HashSet<String>();
  122. private String transportsProperty;
  123. private String stackAddress;
  124. private String sipBalancerHeartBeatServiceClassName;
  125. private String balancers;
  126. private String loadBalancerElector;
  127. /**
  128. * default is true;
  129. */
  130. private boolean looseDialogSeqValidation = true;
  131. /**
  132. * allowed transports
  133. */
  134. private Set<String> allowedTransports = new HashSet<String>();
  135. /**
  136. * the real sip stack provider
  137. */
  138. private SipProvider provider;
  139. /**
  140. * the ra sip provider, which wraps the real one
  141. */
  142. private SleeSipProviderImpl providerWrapper;
  143. /**
  144. * manages the ra activities
  145. */
  146. private SipActivityManagement activityManagement;
  147. /**
  148. * caches the eventIDs, avoiding lookup in container
  149. */
  150. private final EventIDCache eventIdCache = new EventIDCache();
  151. /**
  152. * tells the RA if an event with a specified ID should be filtered or not
  153. */
  154. private final EventIDFilter eventIDFilter = new EventIDFilter();
  155. /**
  156. *
  157. */
  158. private ResourceAdaptorContext raContext;
  159. private SleeEndpoint sleeEndpoint;
  160. private EventLookupFacility eventLookupFacility;
  161. /**
  162. *
  163. */
  164. private Tracer tracer;
  165. /**
  166. *
  167. */
  168. private ClusteredSipStack sipStack = null;
  169. /**
  170. *
  171. */
  172. private SipFactory sipFactory = null;
  173. /**
  174. *
  175. */
  176. private Marshaler marshaler = new SipMarshaler();
  177. /**
  178. * for all events we are interested in knowing when the event failed to be processed
  179. */
  180. public static final int DEFAULT_EVENT_FLAGS = EventFlags.REQUEST_PROCESSING_FAILED_CALLBACK;
  181. public static final int UNREFERENCED_EVENT_FLAGS = EventFlags.setRequestEventReferenceReleasedCallback(DEFAULT_EVENT_FLAGS);
  182. public static final int NON_MARSHABLE_ACTIVITY_FLAGS = ActivityFlags.REQUEST_ENDED_CALLBACK;//.NO_FLAGS;
  183. public static final int MARSHABLE_ACTIVITY_FLAGS = ActivityFlags.setSleeMayMarshal(NON_MARSHABLE_ACTIVITY_FLAGS);
  184. public SipResourceAdaptor() {
  185. // Those values are defualt
  186. this.port = 5060;
  187. // this.transport = "udp";
  188. allowedTransports.add("udp");
  189. allowedTransports.add("tcp");
  190. transports.add("udp");
  191. // this.stackAddress = "127.0.0.1";
  192. // this.stackPrefix = "gov.nist";
  193. }
  194. // XXX -- SipListenerMethods - here we process incoming data
  195. /*
  196. * (non-Javadoc)
  197. * @see javax.sip.SipListener#processIOException(javax.sip.IOExceptionEvent)
  198. */
  199. public void processIOException(IOExceptionEvent arg0) {
  200. tracer.severe("processIOException event = "+arg0.toString());
  201. }
  202. /*
  203. * (non-Javadoc)
  204. * @see javax.sip.SipListener#processRequest(javax.sip.RequestEvent)
  205. */
  206. public void processRequest(RequestEvent req) {
  207. if (tracer.isInfoEnabled()) {
  208. tracer.info("Received Request:\n"+req.getRequest());
  209. }
  210. // get dialog wrapper
  211. final Dialog d = req.getDialog();
  212. final DialogWrapper dw = getDialogWrapper(d);
  213. if (dw != null && req.getServerTransaction() == null) {
  214. if (tracer.isInfoEnabled()) {
  215. tracer.info("No server tx found, for in dialog request, assuming it as retransmission and dropping...");
  216. }
  217. return;
  218. }
  219. if (req.getRequest().getMethod().equals(Request.CANCEL)) {
  220. processCancelRequest(req,dw);
  221. } else {
  222. processNotCancelRequest(req,dw);
  223. }
  224. }
  225. /**
  226. *
  227. * @param req
  228. */
  229. private void processCancelRequest(RequestEvent req, DialogWrapper dw) {
  230. // get server tx wrapper
  231. ServerTransactionWrapper cancelSTW = null;
  232. SIPServerTransaction cancelST = (SIPServerTransaction) req.getServerTransaction();
  233. if (cancelST == null) {
  234. // server tx not found
  235. try {
  236. cancelST = (SIPServerTransaction)provider.getNewServerTransaction(req.getRequest());
  237. cancelSTW = new ServerTransactionWrapper(cancelST,this);
  238. } catch (Throwable e) {
  239. tracer.severe("Failed to create server tx in provider",e);
  240. return;
  241. }
  242. }
  243. else {
  244. // server tx found
  245. final ServerTransactionWrapperAppData appData = (ServerTransactionWrapperAppData) cancelST.getApplicationData();
  246. if (appData != null) {
  247. cancelSTW = (ServerTransactionWrapper) appData.getTransactionWrapper(cancelST,this);
  248. }
  249. else {
  250. cancelSTW = new ServerTransactionWrapper(cancelST, this);
  251. }
  252. }
  253. // get canceled invite stw
  254. final SIPServerTransaction inviteST = ((SIPServerTransaction)cancelSTW.getWrappedServerTransaction()).getCanceledInviteTransaction();
  255. final ServerTransactionWrapper inviteSTW = (ServerTransactionWrapper) getTransactionWrapper(inviteST);
  256. // get dialog
  257. Wrapper activity = dw;
  258. if (activity == null) {
  259. if (inviteSTW != null) {
  260. activity = inviteSTW;
  261. }
  262. else {
  263. activity = cancelSTW;
  264. cancelSTW.setActivity(true);
  265. addActivity(activity);
  266. }
  267. }
  268. if (tracer.isFineEnabled()) {
  269. tracer.fine("Activity selected to fire CANCEL event: " + activity);
  270. }
  271. final CancelRequestEvent REW = new CancelRequestEvent(this.providerWrapper, cancelSTW,
  272. inviteSTW, dw, req.getRequest());
  273. final int eventsFlags = EventFlags.setRequestEventReferenceReleasedCallback(DEFAULT_EVENT_FLAGS);
  274. final FireableEventType eventType = eventIdCache.getEventId(eventLookupFacility, REW.getRequest(), activity.isDialog());
  275. if (eventIDFilter.filterEvent(eventType)) {
  276. if (tracer.isFineEnabled()) {
  277. tracer.fine("Event " + (eventType == null?"null":eventType.getEventType()) + " filtered");
  278. }
  279. // event filtered
  280. processCancelNotHandled(cancelSTW,req.getRequest());
  281. } else {
  282. try {
  283. fireEvent(activity.getActivityHandle(),eventType,REW,activity.getEventFiringAddress(),eventsFlags);
  284. } catch (Throwable e) {
  285. tracer.severe("Failed to fire event",e);
  286. // event not fired due to error
  287. processCancelNotHandled(cancelSTW,req.getRequest());
  288. }
  289. }
  290. }
  291. protected boolean endActivity(Wrapper activity) {
  292. try {
  293. activity.ending();
  294. if (!inLocalMode() && activity.getActivityHandle().isReplicated()) {
  295. sleeEndpoint.endReplicatedActivity(activity.getActivityHandle());
  296. }
  297. else {
  298. sleeEndpoint.endActivity(activity.getActivityHandle());
  299. }
  300. return true;
  301. } catch (Exception e) {
  302. tracer.severe(e.getMessage(),e);
  303. }
  304. return false;
  305. }
  306. protected void fireEvent(SipActivityHandle handle,FireableEventType eventType,
  307. Object event, Address address, int eventFlags)
  308. throws UnrecognizedActivityHandleException, IllegalEventException,
  309. ActivityIsEndingException, NullPointerException, SLEEException,
  310. FireEventException {
  311. if (!inLocalMode() && handle.isReplicated()) {
  312. sleeEndpoint.fireEventOnReplicatedActivity(handle, eventType, event, address, null, eventFlags);
  313. } else {
  314. sleeEndpoint.fireEvent(handle, eventType,
  315. event, address, null, eventFlags);
  316. }
  317. }
  318. /**
  319. * Retrieves the wrapper associated with a dialog, recreating if needed in a cluster env.
  320. * @param d
  321. * @return
  322. */
  323. public DialogWrapper getDialogWrapper(Dialog d) {
  324. if (d == null) {
  325. return null;
  326. }
  327. DialogWrapper dw = null;
  328. DialogWrapperAppData dwad = (DialogWrapperAppData) d.getApplicationData();
  329. if (dwad != null) {
  330. dw = dwad.getDialogWrapper(d, this);
  331. }
  332. if (dw == null && !inLocalMode()) {
  333. // may be a replicated dialog that locally has no wrapper yet
  334. DialogWithIdActivityHandle dialogWithIdActivityHandle = new DialogWithIdActivityHandle(d.getDialogId());
  335. if (sleeEndpoint.replicatedActivityExists(dialogWithIdActivityHandle)) {
  336. // if exists recreate wrapper
  337. dw = new DialogWrapper(dialogWithIdActivityHandle,this);
  338. dw.setWrappedDialog(d);
  339. }
  340. else {
  341. // does not exists try without remote tag, may be the master client dialog, which handle has no remote tag
  342. DialogWithoutIdActivityHandle dialogWithoutIdActivityHandle = new DialogWithoutIdActivityHandle(d.getCallId().getCallId(), d.getLocalTag());
  343. if (!sleeEndpoint.replicatedActivityExists(dialogWithoutIdActivityHandle)) {
  344. return null;
  345. }
  346. // exists
  347. ClientDialogWrapper cdw = new ClientDialogWrapper(dialogWithoutIdActivityHandle, this);
  348. cdw.setWrappedDialog(d);
  349. dw = cdw;
  350. }
  351. }
  352. return dw;
  353. }
  354. /**
  355. * Retrieves the wrapper associated with a tx, recreating if needed in a cluster env.
  356. * @param t
  357. * @return
  358. */
  359. public TransactionWrapper getTransactionWrapper(Transaction t) {
  360. if (t == null) {
  361. return null;
  362. }
  363. final TransactionWrapperAppData twad = (TransactionWrapperAppData) t.getApplicationData();
  364. return twad != null ? twad.getTransactionWrapper(t, this) : null;
  365. }
  366. private void processCancelNotHandled(ServerTransactionWrapper cancelSTW, Request request) {
  367. try {
  368. Response response = providerWrapper.getMessageFactory().createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST, request);
  369. // createResponse(..) method does not generate a To header tag
  370. ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
  371. if (toHeader.getTag() == null) {
  372. toHeader.setTag(Utils.getInstance().generateTag());
  373. }
  374. cancelSTW.getWrappedServerTransaction().sendResponse(response);
  375. } catch (Throwable e) {
  376. tracer.severe("Failed to reply to cancel not handled", e);
  377. try {
  378. cancelSTW.terminate();
  379. } catch (ObjectInUseException f) {
  380. tracer.severe("failed to terminate server tx", f);
  381. }
  382. processTransactionTerminated(cancelSTW);
  383. }
  384. // we may need to delete it manually, since the stack does not do it for early server dialogs
  385. final Dialog d = cancelSTW.getDialog();
  386. if (d != null) {
  387. d.delete();
  388. }
  389. }
  390. /**
  391. *
  392. * @param req
  393. * @param infoTrace
  394. */
  395. private void processNotCancelRequest(RequestEvent req, DialogWrapper dw) {
  396. // get server tx wrapper
  397. ServerTransactionWrapper stw = null;
  398. if (req.getServerTransaction() == null) {
  399. // server tx not found
  400. if (!req.getRequest().getMethod().equals(Request.ACK)) {
  401. try {
  402. stw = new ServerTransactionWrapper((SIPServerTransaction)provider.getNewServerTransaction(req.getRequest()),this);
  403. } catch (Throwable e) {
  404. if(tracer.isFineEnabled()) {
  405. tracer.fine("Failed to create server tx in provider",e);
  406. }
  407. return;
  408. }
  409. }
  410. else {
  411. // create fake ack server transaction
  412. stw = new ServerTransactionWrapper(new ACKDummyTransaction(req.getRequest()),this);
  413. if (tracer.isFineEnabled()) {
  414. tracer.fine("New ACK server transaction "+stw);
  415. }
  416. }
  417. }
  418. else {
  419. // server tx found
  420. final SIPServerTransaction st = (SIPServerTransaction) req.getServerTransaction();
  421. final ServerTransactionWrapperAppData appData = (ServerTransactionWrapperAppData) st.getApplicationData();
  422. if (appData != null) {
  423. stw = (ServerTransactionWrapper) appData.getTransactionWrapper(st, this);
  424. }
  425. else {
  426. stw = new ServerTransactionWrapper(st, this);
  427. }
  428. }
  429. Wrapper activity = dw;
  430. if (activity == null) {
  431. activity = stw;
  432. stw.setActivity(true);
  433. addActivity(activity);
  434. }
  435. int eventFlags = DEFAULT_EVENT_FLAGS;
  436. if (stw.isAckTransaction()) {
  437. // dummy ack txs are not terminated by stack, so we need to rely on the event release callback
  438. eventFlags = UNREFERENCED_EVENT_FLAGS;
  439. }
  440. final FireableEventType eventType = eventIdCache.getEventId(eventLookupFacility, req.getRequest(), dw != null);
  441. final RequestEventWrapper rew = new RequestEventWrapper(this.providerWrapper,stw,dw,req.getRequest());
  442. if (eventIDFilter.filterEvent(eventType)) {
  443. if (tracer.isFineEnabled()) {
  444. tracer.fine("Event " + (eventType==null?"null":eventType.getEventType()) + " filtered");
  445. }
  446. // event was filtered, let's clean up state
  447. try {
  448. stw.terminate();
  449. } catch (ObjectInUseException e) {
  450. tracer.severe("failed to terminate server tx", e);
  451. }
  452. processTransactionTerminated(stw);
  453. } else {
  454. try {
  455. fireEvent(activity.getActivityHandle(), eventType, rew, activity.getEventFiringAddress(), eventFlags);
  456. } catch (Throwable e) {
  457. // event not fired due to error, let's trace and cleanup state
  458. tracer.severe("Failed to fire event",e);
  459. try {
  460. stw.terminate();
  461. } catch (ObjectInUseException f) {
  462. tracer.severe("failed to terminate server tx", f);
  463. }
  464. processTransactionTerminated(stw);
  465. }
  466. }
  467. }
  468. /*
  469. * (non-Javadoc)
  470. * @see javax.sip.SipListener#processResponse(javax.sip.ResponseEvent)
  471. */
  472. public void processResponse(ResponseEvent responseEvent) {
  473. final ResponseEventExt responseEventExt = (ResponseEventExt)responseEvent;
  474. if (responseEventExt.isRetransmission() && responseEventExt.getDialog() != null) {
  475. if (tracer.isInfoEnabled()) {
  476. tracer.info("Dropping in dialog retransmission. Response:\n"+responseEventExt.getResponse());
  477. }
  478. return;
  479. }
  480. if(responseEventExt.isForkedResponse()) {
  481. processResponseEventForked(responseEventExt);
  482. }
  483. else {
  484. processResponseEventNotForked(responseEventExt);
  485. }
  486. }
  487. private void processResponseEventNotForked(ResponseEventExt responseEventExt) {
  488. final Response response = responseEventExt.getResponse();
  489. if (tracer.isInfoEnabled()) {
  490. tracer.info("Received Response:\n"+response);
  491. }
  492. ClientTransactionWrapper ctw = null;
  493. final Dialog d = responseEventExt.getDialog();
  494. DialogWrapper dw = getDialogWrapper(d);
  495. if (dw != null && dw.isClientDialog()) {
  496. final ClientDialogWrapper cdw = (ClientDialogWrapper) dw;
  497. if (cdw.getState() == DialogState.EARLY) {
  498. if (!inLocalMode()) {
  499. // ensure the the relation handle -> remote tag is replicated, otherwise it's impossible to get the dialog from stack in another node
  500. if (((ClusteredSipActivityManagement)activityManagement).replicateRemoteTag(dw.getActivityHandle(), d.getRemoteTag())) {
  501. if (tracer.isInfoEnabled()) {
  502. tracer.info("Replicating mapping of outgoing dialog handle "+dw.getActivityHandle()+" to remote tag "+d.getRemoteTag());
  503. }
  504. }
  505. }
  506. }
  507. else if (cdw.getState() == DialogState.CONFIRMED) {
  508. if (!cdw.stopForking(true)) {
  509. if (!cdw.isForkingWinner()) {
  510. if (tracer.isInfoEnabled()) {
  511. tracer.info("Confirmed original dialog "+dw.getDialogId()+", but another related fork dialog already confirmed, sending ack and bye.");
  512. }
  513. processLateDialogFork2xxResponse(response,d);
  514. return;
  515. }
  516. // else do nothing, the master dialog previously confirmed
  517. }
  518. else {
  519. if (tracer.isInfoEnabled()) {
  520. tracer.info("Original dialog "+dw.getDialogId()+" confirmed.");
  521. }
  522. if (!inLocalMode()) {
  523. // ensure the the relation handle -> remote tag is replicated, otherwise it's impossible to get the dialog from stack in another node
  524. if (((ClusteredSipActivityManagement)activityManagement).replicateRemoteTag(dw.getActivityHandle(), d.getRemoteTag())) {
  525. if (tracer.isInfoEnabled()) {
  526. tracer.info("Replicating mapping of outgoing dialog handle "+dw.getActivityHandle()+" to remote tag "+d.getRemoteTag());
  527. }
  528. }
  529. }
  530. }
  531. }
  532. }
  533. SipActivityHandle handle = null;
  534. Address address = null;
  535. FireableEventType eventType = null;
  536. Object event = null;
  537. boolean requestEventUnreferenced = false;
  538. final ClientTransaction ct = responseEventExt.getClientTransaction();
  539. if (ct == null) {
  540. // no client tx
  541. if (!inLocalMode()) {
  542. // ok, it may be a RTR sent to a cluster node after orig node went down
  543. if (dw != null) {
  544. // the dialog exists, thus confirmed, ignore the fact that there is no client tx
  545. event = new ResponseEventWrapper(this.providerWrapper, null, dw, response);
  546. eventType = eventIdCache.getEventId(eventLookupFacility, response);
  547. handle = dw.getActivityHandle();
  548. address = dw.getEventFiringAddress();
  549. }
  550. else {
  551. // no dialog in stack, at most it was a unconfirmed dialog, lets end the related activity if exists
  552. final String localTag = ((FromHeader) response.getHeader(FromHeader.NAME)).getTag();
  553. if (localTag != null) {
  554. // looks suspicious, we have a local tag, maybe it was a unconfirmed dialog, lets try to end the related activity
  555. // first lets search for a fork with full dialog id
  556. final SIPResponse sipResponse = (SIPResponse) response;
  557. final String dialogId = sipResponse.getDialogId(false);
  558. handle = new DialogWithIdActivityHandle(dialogId);
  559. try {
  560. if (sleeEndpoint.replicatedActivityExists(handle)) {
  561. sleeEndpoint.endReplicatedActivity(handle);
  562. }
  563. else {
  564. // ok now we search for an original dialog without id
  565. final String callId = ((CallIdHeader) response.getHeader(CallIdHeader.NAME)).getCallId();
  566. handle = new DialogWithoutIdActivityHandle(callId, localTag);
  567. if (sleeEndpoint.replicatedActivityExists(handle)) {
  568. sleeEndpoint.endReplicatedActivity(handle);
  569. }
  570. }
  571. }
  572. catch (UnrecognizedActivityHandleException e) {
  573. if (tracer.isFineEnabled()) {
  574. tracer.fine("failed to end client tx dialog "+handle+" that was not confirmed, probably from a dead node",e);
  575. }
  576. }
  577. catch (Exception e) {
  578. tracer.severe("failed to end client tx dialog "+handle+" that was not confirmed, probably from a dead node",e);
  579. }
  580. // and ack and bye if it's dialog confirmation
  581. if (isDialogConfirmation(response)) {
  582. processLateDialogFork2xxResponse(response,null);
  583. }
  584. }
  585. else {
  586. if (tracer.isInfoEnabled()) {
  587. tracer.info("Received response not forked, without tx, without dialog, can't proceed, dropping...");
  588. }
  589. }
  590. return;
  591. }
  592. }
  593. else {
  594. // no cluster
  595. if (dw != null) {
  596. // the dialog exists, thus confirmed, ignore the fact that there is no client tx
  597. event = new ResponseEventWrapper(this.providerWrapper, null, dw, response);
  598. eventType = eventIdCache.getEventId(eventLookupFacility, response);
  599. handle = dw.getActivityHandle();
  600. address = dw.getEventFiringAddress();
  601. }
  602. else {
  603. if (tracer.isInfoEnabled()) {
  604. tracer.info("Received response not forked, without tx, without dialog, can't proceed, dropping...");
  605. }
  606. return;
  607. }
  608. }
  609. }
  610. else {
  611. // ct found
  612. ctw = (ClientTransactionWrapper) getTransactionWrapper(ct);
  613. if (ctw == null) {
  614. if (tracer.isInfoEnabled()) {
  615. tracer.info("Dropping response without app data in client tx, probably due to late dialog fork confirmation ack and bye.");
  616. }
  617. return;
  618. }
  619. if (tracer.isFineEnabled()) {
  620. tracer.fine("Received "+response.getStatusCode()+" response on existent client transaction "+ctw.getActivityHandle());
  621. }
  622. // get address where to fire event
  623. address = ctw.getEventFiringAddress();
  624. // determine what is the handle
  625. if (dw != null) {
  626. handle = dw.getActivityHandle();
  627. // (client tx that has a final response and is not an activity must be
  628. // cleared on this callback, not on transaction terminated event)
  629. if (!ctw.isActivity()) {
  630. requestEventUnreferenced = response.getStatusCode() > 199;
  631. }
  632. }
  633. else {
  634. handle = ctw.getActivityHandle();
  635. }
  636. // create event and type
  637. event = new ResponseEventWrapper(this.providerWrapper, ctw, dw, response);
  638. eventType = eventIdCache.getEventId(eventLookupFacility, response);
  639. }
  640. int eventFlags = DEFAULT_EVENT_FLAGS;
  641. if (requestEventUnreferenced) {
  642. eventFlags = UNREFERENCED_EVENT_FLAGS;
  643. }
  644. if (eventIDFilter.filterEvent(eventType)) {
  645. if (tracer.isInfoEnabled()) {
  646. tracer.info("Event " + (eventType == null?"null":eventType.getEventType()) + " filtered");
  647. }
  648. // event filtered
  649. if (requestEventUnreferenced) {
  650. // event was filtered, consider it is unreferenced now
  651. processResponseEventUnreferenced((ResponseEventWrapper)event);
  652. }
  653. } else {
  654. try {
  655. fireEvent(handle, eventType, event, address,eventFlags);
  656. }
  657. catch (UnrecognizedActivityHandleException e) {
  658. tracer.warning("Failed to fire event "+eventType+", the activity "+handle+" does not exists in the SLEE");
  659. } catch (Throwable e) {
  660. tracer.severe("Failed to fire event",e);
  661. // event not fired due to error
  662. if (requestEventUnreferenced) {
  663. // consider event is unreferenced now
  664. processResponseEventUnreferenced((ResponseEventWrapper)event);
  665. }
  666. }
  667. }
  668. }
  669. private void processResponseEventForked(ResponseEventExt responseEventExt) {
  670. if (tracer.isInfoEnabled()) {
  671. tracer.info("Received Forked Dialog Response:\n"+responseEventExt.getResponse());
  672. }
  673. SipActivityHandle handle = null;
  674. FireableEventType eventType = null;
  675. Object event = null;
  676. final Dialog forkedDialog = responseEventExt.getDialog();
  677. DialogWrapper forkedDialogWrapper = getDialogWrapper(forkedDialog);
  678. final DialogState forkedDialogState = forkedDialog.getState();
  679. final SIPClientTransaction originalClientTransaction = (SIPClientTransaction) responseEventExt.getOriginalTransaction();
  680. final Dialog originalDialog = originalClientTransaction.getDefaultDialog();
  681. final ClientDialogWrapper originalDialogWrapper = (ClientDialogWrapper) getDialogWrapper(originalDialog);
  682. if (forkedDialogWrapper == null) {
  683. // new fork
  684. if (forkedDialogState == DialogState.CONFIRMED) {
  685. // confirmed right away
  686. if (originalDialogWrapper.stopForking(false)) {
  687. // and this dialog was the first one participating in this forking that was confirmed
  688. if (tracer.isInfoEnabled()) {
  689. tracer.info("New confirmed dialog fork "+forkedDialog.getDialogId());
  690. }
  691. // add new dialog activity
  692. final DialogWithIdActivityHandle forkedDialogHandle = new DialogWithIdActivityHandle(forkedDialog.getDialogId());
  693. forkedDialogWrapper = new DialogWrapper(forkedDialogHandle, this);
  694. forkedDialogWrapper.setWrappedDialog(forkedDialog);
  695. addActivity(forkedDialogWrapper);
  696. // fire dialog fork event in original dialog activity
  697. handle = originalDialogWrapper.getActivityHandle();
  698. event = new DialogForkedEvent(responseEventExt.getSource(), (ClientTransaction) getTransactionWrapper(originalClientTransaction), originalDialogWrapper, forkedDialogWrapper, responseEventExt.getResponse());
  699. eventType = eventIdCache.getDialogForkEventId(eventLookupFacility);
  700. }
  701. else {
  702. // forking is not allowed anymore
  703. // ack and bye
  704. if (tracer.isInfoEnabled()) {
  705. tracer.info("New confirmed dialog fork "+forkedDialog.getDialogId()+", but forking is not possible anymore, sending ack and bye.");
  706. }
  707. processLateDialogFork2xxResponse(responseEventExt.getResponse(),forkedDialog);
  708. return;
  709. }
  710. }
  711. else if (forkedDialogState == DialogState.EARLY) {
  712. if (originalDialogWrapper.isForkingPossible()) {
  713. if (tracer.isInfoEnabled()) {
  714. tracer.info("New unconfirmed dialog fork "+forkedDialog.getDialogId());
  715. }
  716. // add new dialog activity
  717. final DialogWithIdActivityHandle forkedDialogHandle = new DialogWithIdActivityHandle(forkedDialog.getDialogId());
  718. forkedDialogWrapper = new DialogWrapper(forkedDialogHandle, this);
  719. forkedDialogWrapper.setWrappedDialog(forkedDialog);
  720. addActivity(forkedDialogWrapper);
  721. // fire dialog fork event in original dialog activity
  722. handle = originalDialogWrapper.getActivityHandle();
  723. event = new DialogForkedEvent(responseEventExt.getSource(), (ClientTransaction) getTransactionWrapper(originalClientTransaction), originalDialogWrapper, forkedDialogWrapper, responseEventExt.getResponse());
  724. eventType = eventIdCache.getDialogForkEventId(eventLookupFacility);
  725. }
  726. else {
  727. // forking not allowed anymore
  728. // ignore
  729. if (tracer.isInfoEnabled()) {
  730. tracer.info("New unconfirmed dialog fork "+forkedDialog.getDialogId()+", but forking is not possible anymore, dropping.");
  731. }
  732. return;
  733. }
  734. }
  735. else {
  736. // new forks are not accepted in states other than early or confirmed
  737. if (tracer.isInfoEnabled()) {
  738. tracer.info("New dialog fork "+forkedDialog.getDialogId()+", but state "+forkedDialogState+" does not allows to create forked activity, dropping.");
  739. }
  740. return;
  741. }
  742. }
  743. else {
  744. // existent fork
  745. if (forkedDialogState == DialogState.CONFIRMED) {
  746. if (originalDialogWrapper.stopForking(false)) {
  747. // and this dialog was the first one participating in this forking that was confirmed
  748. if (tracer.isInfoEnabled()) {
  749. tracer.info("Dialog fork "+forkedDialog.getDialogId()+" confirmed.");
  750. }
  751. // fire normal event on forked dialog activity
  752. handle = forkedDialogWrapper.getActivityHandle();
  753. event = new ResponseEventWrapper(responseEventExt.getSource(),(ClientTransaction) getTransactionWrapper(originalClientTransaction),forkedDialogWrapper, responseEventExt.getResponse());
  754. eventType = eventIdCache.getEventId(eventLookupFacility, responseEventExt.getResponse());
  755. }
  756. else {
  757. // lost the forking race
  758. // ack and bye
  759. if (tracer.isInfoEnabled()) {
  760. tracer.info("Dialog fork "+forkedDialog.getDialogId()+" confirmed, but another related fork dialog already confirmed, sending ack and bye.");
  761. }
  762. processLateDialogFork2xxResponse(responseEventExt.getResponse(),forkedDialog);
  763. return;
  764. }
  765. }
  766. else {
  767. // not yet confirmed, fire normal event on forked dialog activity
  768. handle = forkedDialogWrapper.getActivityHandle();
  769. event = new ResponseEventWrapper(responseEventExt.getSource(),(ClientTransaction) getTransactionWrapper(originalClientTransaction),forkedDialogWrapper, responseEventExt.getResponse());
  770. eventType = eventIdCache.getEventId(eventLookupFacility, responseEventExt.getResponse());
  771. }
  772. }
  773. // address is common for both dialogs
  774. final Address address = forkedDialogWrapper.getEventFiringAddress();;
  775. if (eventIDFilter.filterEvent(eventType)) {
  776. if (tracer.isInfoEnabled()) {
  777. tracer.info("Event " + (eventType == null?"null":eventType.getEventType()) + " filtered");
  778. }
  779. } else {
  780. try {
  781. fireEvent(handle, eventType, event, address, DEFAULT_EVENT_FLAGS);
  782. }
  783. catch (UnrecognizedActivityHandleException e) {
  784. tracer.warning("Failed to fire event "+eventType+", the activity "+handle+" does not exists in the SLEE");
  785. }
  786. catch (Throwable e) {
  787. tracer.severe("Failed to fire event",e);
  788. }
  789. }
  790. }
  791. /**
  792. * @param response
  793. * @return
  794. */
  795. private boolean isDialogConfirmation(Response response) {
  796. final CSeqHeader cSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
  797. if (!cSeqHeader.getMethod().equals(Request.INVITE) && !cSeqHeader.getMethod().equals(Request.SUBSCRIBE)) {
  798. // not a dialog creating method
  799. return false;
  800. }
  801. if (cSeqHeader.getSeqNumber() != 1) {
  802. return false;
  803. }
  804. if (response.getStatusCode() < 300 && response.getStatusCode() > 199) {
  805. return true;
  806. }
  807. else {
  808. return false;
  809. }
  810. }
  811. /**
  812. * @param response
  813. */
  814. private void processLateDialogFork2xxResponse(Response response, Dialog dialog) {
  815. final CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
  816. try {
  817. if (dialog != null) {
  818. Request ack = dialog.createAck(cseq.getSeqNumber());
  819. if (tracer.isInfoEnabled()) {
  820. tracer.info("Sending request:\n"+ack);
  821. }
  822. dialog.sendAck(ack);
  823. Request bye = dialog.createRequest(Request.BYE);
  824. if (tracer.isInfoEnabled()) {
  825. tracer.info("Sending request:\n"+bye);
  826. }
  827. // NOTE: Do not use provider wrapper here, would create activity
  828. ClientTransaction clientTransaction = provider.getNewClientTransaction(bye);
  829. dialog.sendRequest(clientTransaction);
  830. }
  831. else {
  832. final SleeSipProviderImpl provider = getProviderWrapper();
  833. List<RouteHeader> routeSet = org.mobicents.slee.resource.sip11.Utils.getRouteList(response,provider.getHeaderFactory());
  834. //RFC3261 8.1.1.1
  835. URI requestURI = org.mobicents.slee.resource.sip11.Utils.getRequestUri(response, provider.getAddressFactory());
  836. String branch = ((ViaHeader)response.getHeaders(ViaHeader.NAME).next()).getBranch();
  837. long cseqNumber = cseq.getSeqNumber();
  838. if (requestURI == null) {
  839. tracer.severe("Cannot ack on request that has empty contact!!!!");
  840. return;
  841. }
  842. MaxForwardsHeader mf = provider.getHeaderFactory().createMaxForwardsHeader(70);
  843. List<ViaHeader> lst = new ArrayList<ViaHeader>(1);
  844. final ViaHeader localViaHeader = provider.getLocalVia();
  845. localViaHeader.setBranch(branch);
  846. lst.add(localViaHeader);
  847. Request forgedRequest = provider.getMessageFactory().createRequest(requestURI,Request.ACK,(CallIdHeader)response.getHeader(CallIdHeader.NAME),provider.getHeaderFactory().createCSeqHeader(cseqNumber, Request.ACK),
  848. (FromHeader)response.getHeader(FromHeader.NAME) ,(ToHeader)response.getHeader(ToHeader.NAME),lst,mf );
  849. for (Header h : routeSet) {
  850. forgedRequest.addLast(h);
  851. }
  852. if (tracer.isInfoEnabled()) {
  853. tracer.info("Sending request:\n"+forgedRequest);
  854. }
  855. provider.sendRequest(forgedRequest);
  856. lst = new ArrayList<ViaHeader>();
  857. lst.add(provider.getLocalVia());
  858. requestURI = org.mobicents.slee.resource.sip11.Utils.getRequestUri(response,provider.getAddressFactory());
  859. forgedRequest = provider.getMessageFactory().createRequest(requestURI,Request.BYE,(CallIdHeader)response.getHeader(CallIdHeader.NAME),provider.getHeaderFactory().createCSeqHeader(cseqNumber+1, Request.BYE),
  860. (FromHeader)response.getHeader(FromHeader.NAME) ,(ToHeader)response.getHeader(ToHeader.NAME),lst,mf );
  861. for (Header h : routeSet) {
  862. forgedRequest.addLast(h);
  863. }
  864. // ITS BUG....
  865. ((SIPRequest) forgedRequest).setMethod(Request.BYE);
  866. if (tracer.isInfoEnabled()) {
  867. tracer.info("Sending request:\n"+forgedRequest);
  868. }
  869. provider.sendRequest(forgedRequest);
  870. }
  871. // response.get
  872. } catch (Exception e) {
  873. tracer.severe(e.getMessage(),e);
  874. }
  875. }
  876. /*
  877. * (non-Javadoc)
  878. * @see javax.sip.SipListener#processTimeout(javax.sip.TimeoutEvent)
  879. */
  880. public void processTimeout(TimeoutEvent timeoutEvent) {
  881. SIPTransaction t = null;
  882. if (timeoutEvent.isServerTransaction()) {
  883. t = (SIPTransaction) timeoutEvent.getServerTransaction();
  884. }
  885. else {
  886. t = (SIPTransaction) timeoutEvent.getClientTransaction();
  887. }
  888. if (tracer.isInfoEnabled()) {
  889. tracer.info("Transaction "
  890. + t.getTransactionId()
  891. + " timer expired");
  892. }
  893. TransactionWrapper tw = getTransactionWrapper(t);
  894. if (tw == null) {
  895. if (tracer.isInfoEnabled()) {
  896. tracer.info("Received timeout event for tx "+t.getTransactionId()+" with null app data, dropping...");
  897. }
  898. return;
  899. }
  900. TimeoutEventWrapper tew = null;
  901. if (timeoutEvent.isServerTransaction()) {
  902. tew = new TimeoutEventWrapper(providerWrapper,(ServerTransaction)tw, timeoutEvent.getTimeout());
  903. }
  904. else {
  905. tew = new TimeoutEventWrapper(providerWrapper,(ClientTransaction)tw, timeoutEvent.getTimeout());
  906. }
  907. final Dialog d = tw.getWrappedTransaction().getDialog();
  908. final DialogWrapper dw = getDialogWrapper(d);
  909. final FireableEventType eventType = eventIdCache.getTransactionTimeoutEventId(
  910. eventLookupFacility, dw != null);
  911. if (!eventIDFilter.filterEvent(eventType)) {
  912. Wrapper activity = tw.isActivity() ? tw : dw;
  913. try {
  914. fireEvent(activity.getActivityHandle(), eventType, tew, activity.getEventFiringAddress(),DEFAULT_EVENT_FLAGS);
  915. }
  916. catch (UnrecognizedActivityHandleException e) {
  917. tracer.warning("Failed to fire event "+eventType+", the activity "+activity+" does not exists in the SLEE");
  918. }
  919. catch (Throwable e) {
  920. tracer.severe("Failed to fire event",e);
  921. }
  922. }
  923. else {
  924. if (tracer.isFineEnabled()) {
  925. tracer.fine("Event "+eventType+" filtered.");
  926. }
  927. }
  928. }
  929. /*
  930. * (non-Javadoc)
  931. * @see javax.sip.SipListener#processTransactionTerminated(javax.sip.TransactionTerminatedEvent)
  932. */
  933. public void processTransactionTerminated(
  934. TransactionTerminatedEvent txTerminatedEvent) {
  935. Transaction t = null;
  936. if (txTerminatedEvent.isServerTransaction()) {
  937. t = txTerminatedEvent.getServerTransaction();
  938. }
  939. else {
  940. t = txTerminatedEvent.getClientTransaction();
  941. }
  942. final TransactionWrapper tw = getTransactionWrapper(t);
  943. if (tw != null) {
  944. if (tracer.isInfoEnabled()) {
  945. tracer.info("SIP Transaction "+tw.getActivityHandle()+" terminated");
  946. }
  947. processTransactionTerminated(tw);
  948. }
  949. else {
  950. if (tracer.isInfoEnabled()) {
  951. tracer.info("SIP Transaction "+((SIPTransaction)t).getTransactionId()+" terminated");
  952. }
  953. }
  954. }
  955. private void processTransactionTerminated(TransactionWrapper tw) {
  956. tw.terminated();
  957. if (tw.isActivity()) {
  958. endActivity(tw);
  959. }
  960. else {
  961. if (!tw.isClientTransaction()) {
  962. // client txs which are not activity are cleared on event unreferenced callbacks
  963. tw.clear();
  964. }
  965. }
  966. }
  967. /*
  968. * (non-Javadoc)
  969. * @see javax.sip.SipListener#processDialogTerminated(javax.sip.DialogTerminatedEvent)
  970. */
  971. public void processDialogTerminated(DialogTerminatedEvent dte) {
  972. final Dialog d = dte.getDialog();
  973. if (d!= null) {
  974. DialogWrapper dw = getDialogWrapper(d);
  975. if (dw != null) {
  976. processDialogTerminated(dw);
  977. } else {
  978. if (tracer.isFineEnabled()) {
  979. tracer.fine("DialogTerminatedEvent dropped due to null app data.");
  980. }
  981. }
  982. }
  983. }
  984. /**
  985. *
  986. * @param dw
  987. */
  988. public void processDialogTerminated(DialogWrapper dw) {
  989. if (!dw.isEnding()) {
  990. if (tracer.isInfoEnabled()) {
  991. tracer.info("SIP Dialog " + dw.getActivityHandle() + " terminated");
  992. }
  993. if (!endActivity(dw)) {
  994. tracer.warning("Dialog activity that ended not found.");
  995. }
  996. dw.ending();
  997. }
  998. }
  999. // *************** Event Life cycle
  1000. /**
  1001. *
  1002. * @param wrapperActivity
  1003. * @param transacted
  1004. * @return
  1005. */
  1006. public boolean addActivity(Wrapper wrapperActivity) {
  1007. if (tracer.isFineEnabled()) {
  1008. tracer.fine("Adding sip activity handle " + wrapperActivity.getActivityHandle());
  1009. }
  1010. final int activityFlags = wrapperActivity.isDialog() ? MARSHABLE_ACTIVITY_FLAGS : NON_MARSHABLE_ACTIVITY_FLAGS;
  1011. try {
  1012. sleeEndpoint.startActivity(wrapperActivity.getActivityHandle(),wrapperActivity,activityFlags);
  1013. }
  1014. catch (ActivityAlreadyExistsException e) {
  1015. if(tracer.isFineEnabled()) {
  1016. tracer.fine("Skipping activity start",e);
  1017. }
  1018. return true;
  1019. }
  1020. catch (Throwable e) {
  1021. tracer.severe("Failed to start activity",e);
  1022. return false;
  1023. }
  1024. activityManagement.put(wrapperActivity.getActivityHandle(), wrapperActivity);
  1025. return true;
  1026. }
  1027. /**
  1028. *
  1029. * @param wrapperActivity
  1030. * @return
  1031. */
  1032. public boolean addSuspendedActivity(Wrapper wrapperActivity) {
  1033. if (tracer.isFineEnabled()) {
  1034. tracer.fine("Adding suspended sip activity handle " + wrapperActivity.getActivityHandle());
  1035. }
  1036. final int activityFlags = wrapperActivity.isDialog() ? MARSHABLE_ACTIVITY_FLAGS : NON_MARSHABLE_ACTIVITY_FLAGS;
  1037. try {
  1038. sleeEndpoint.startActivitySuspended(wrapperActivity.getActivityHandle(),wrapperActivity,activityFlags);
  1039. }
  1040. catch (ActivityAlreadyExistsException e) {
  1041. if(tracer.isFineEnabled()) {
  1042. tracer.fine("Skipping activity start",e);
  1043. }
  1044. return true;
  1045. }
  1046. catch (Throwable e) {
  1047. tracer.severe("Failed to start activity",e);
  1048. return false;
  1049. }
  1050. activityManagement.put(wrapperActivity.getActivityHandle(), wrapperActivity);
  1051. return true;
  1052. }
  1053. // LIFECYLE
  1054. /*
  1055. * (non-Javadoc)
  1056. * @see javax.slee.resource.ResourceAdaptor#raActive()
  1057. */
  1058. public void raActive() {
  1059. try {
  1060. final Properties properties = new Properties();
  1061. // load properties for the stack
  1062. properties.load(getClass().getResourceAsStream("sipra.properties"));
  1063. // now load config properties
  1064. properties.setProperty(SIP_BIND_ADDRESS, this.stackAddress);
  1065. // setting the ra entity name as the stack name
  1066. properties.setProperty(STACK_NAME_BIND, raContext.getEntityName());
  1067. properties.setProperty(TRANSPORTS_BIND, transportsProperty);
  1068. properties.setProperty(SIP_PORT_BIND, Integer.toString(this.port));
  1069. if (sipBalancerHeartBeatServiceClassName != null) {
  1070. properties.setProperty(LOAD_BALANCER_HEART_BEAT_SERVICE_CLASS, sipBalancerHeartBeatServiceClassName);
  1071. }
  1072. if (balancers != null) {
  1073. properties.setProperty(BALANCERS, balancers);
  1074. }
  1075. if (loadBalancerElector != null) {
  1076. properties.setProperty(LoadBalancerElector.IMPLEMENTATION_CLASS_NAME_PROPERTY, loadBalancerElector);
  1077. }
  1078. // define impl of the cache of the HA stack
  1079. properties.setProperty(ClusteredSipStack.CACHE_CLASS_NAME_PROPERTY,SipResourceAdaptorMobicentsSipCache.class.getName());
  1080. this.sipFactory = SipFactory.getInstance();
  1081. this.sipFactory.setPathName("org.mobicents.ha");
  1082. this.sipStack = (ClusteredSipStack) this.sipFactory.createSipStack(properties);
  1083. this.sipStack.start();
  1084. if (inLocalMode()) {
  1085. activityManagement = new LocalSipActivityManagement();
  1086. }
  1087. else {
  1088. activityManagement = new ClusteredSipActivityManagement(sipStack,ftRaContext.getReplicateData(true),raContext.getSleeTransactionManager(),this);
  1089. }
  1090. if (tracer.isFineEnabled()) {
  1091. tracer
  1092. .fine("---> START "
  1093. + Arrays.toString(transports.toArray()));
  1094. }
  1095. boolean created = false;
  1096. for (String trans : transports) {
  1097. ListeningPoint lp = this.sipStack.createListeningPoint(
  1098. this.stackAddress, this.port, trans);
  1099. if (!created) {
  1100. this.provider = this.sipStack.createSipProvider(lp);
  1101. this.provider.addSipListener(this);
  1102. created = true;
  1103. } else
  1104. this.provider.addListeningPoint(lp);
  1105. }
  1106. // LETS CREATE FP
  1107. // SipFactory sipFactory = SipFactory.getInstance();
  1108. AddressFactory addressFactory = sipFactory.createAddressFactory();
  1109. HeaderFactory headerFactory = sipFactory.createHeaderFactory();
  1110. MessageFactory messageFactory = sipFactory.createMessageFactory();
  1111. this.providerWrapper.raActive(addressFactory, headerFactory, messageFactory, sipStack, provider);
  1112. } catch (Throwable ex) {
  1113. String msg = "error in initializing resource adaptor";
  1114. tracer.severe(msg, ex);
  1115. throw new RuntimeException(msg,ex);
  1116. }
  1117. if (tracer.isFineEnabled()) {
  1118. tracer.fine("Sip Resource Adaptor entity active.");
  1119. }
  1120. }
  1121. /*
  1122. * (non-Javadoc)
  1123. * @see javax.slee.resource.ResourceAdaptor#raInactive()
  1124. */
  1125. public void raInactive() {
  1126. this.provider.removeSipListener(this);
  1127. ListeningPoint[] listeningPoints = this.provider.getListeningPoints();
  1128. for (int i = 0; i < listeningPoints.length; i++) {
  1129. ListeningPoint lp = listeningPoints[i];
  1130. for (int k = 0; k < 10; k++) {
  1131. try {
  1132. this.sipStack.deleteListeningPoint(lp);
  1133. this.sipStack.deleteSipProvider(this.provider);
  1134. break;
  1135. } catch (ObjectInUseException ex) {
  1136. tracer
  1137. .severe(
  1138. "Object in use -- retrying to delete listening point",
  1139. ex);
  1140. try {
  1141. Thread.sleep(100);
  1142. } catch (Exception e) {
  1143. }
  1144. }
  1145. }
  1146. }
  1147. this.providerWrapper.raInactive();
  1148. if (tracer.isFineEnabled()) {
  1149. tracer.fine("Sip Resource Adaptor entity inactive.");
  1150. }
  1151. }
  1152. /*
  1153. * (non-Javadoc)
  1154. * @see javax.slee.resource.ResourceAdaptor#raStopping()
  1155. */
  1156. public void raStopping() {
  1157. if (tracer.isFineEnabled()) {
  1158. tracer.fine("Object for entity named "+raContext.getEntityName()+" is stopping. "+activityManagement);
  1159. }
  1160. }
  1161. // EVENT PROCESSING CALLBACKS
  1162. /*
  1163. * (non-Javadoc)
  1164. * @see javax.slee.resource.ResourceAdaptor#eventProcessingFailed(javax.slee.resource.ActivityHandle, javax.slee.resource.FireableEventType, java.lang.Object, javax.slee.Address, javax.slee.resource.ReceivableService, int, javax.slee.resource.FailureReason)
  1165. */
  1166. public void eventProcessingFailed(ActivityHandle ah, FireableEventType arg1,
  1167. Object event, Address arg3, ReceivableService arg4, int arg5, FailureReason arg6) {
  1168. if (event.getClass() == CancelRequestEvent.class) {
  1169. // PROCESSING FAILED, WE HAVE TO SEND 481 response to CANCEL
  1170. try {
  1171. Response txDoesNotExistsResponse = this.providerWrapper.getMessageFactory().createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST,
  1172. ((CancelRequestEvent) event).getRequest());
  1173. // createResponse(..) method does not generate a To header tag,
  1174. // if there is no tag, we must generate it
  1175. ToHeader toHeader = (ToHeader) txDoesNotExistsResponse.getHeader(ToHeader.NAME);
  1176. if (toHeader.getTag() == null) {
  1177. toHeader.setTag(Utils.getInstance().generateTag());
  1178. }
  1179. ServerTransactionWrapper stw = (ServerTransactionWrapper) getActivity(ah);
  1180. // provider.sendResponse(txDoesNotExistsResponse);
  1181. stw.sendResponse(txDoesNotExistsResponse);
  1182. } catch (Exception e) {
  1183. e.printStackTrace();
  1184. }
  1185. }
  1186. }
  1187. /*
  1188. * (non-Javadoc)
  1189. * @see javax.slee.resource.ResourceAdaptor#eventProcessingSuccessful(javax.slee.resource.ActivityHandle, javax.slee.resource.FireableEventType, java.lang.Object, javax.slee.Address, javax.slee.resource.ReceivableService, int)
  1190. */
  1191. public void eventProcessingSuccessful(ActivityHandle arg0,
  1192. FireableEventType arg1, Object arg2, Address arg3,
  1193. ReceivableService arg4, int arg5) {
  1194. // not used
  1195. }
  1196. /*
  1197. * (non-Javadoc)
  1198. * @see javax.slee.resource.ResourceAdaptor#eventUnreferenced(javax.slee.resource.ActivityHandle, javax.slee.resource.FireableEventType, java.lang.Object, javax.slee.Address, javax.slee.resource.ReceivableService, int)
  1199. */
  1200. public void eventUnreferenced(ActivityHandle handle, FireableEventType eventType,
  1201. Object event, Address arg3, ReceivableService arg4, int arg5) {
  1202. if(tracer.isFineEnabled()) {
  1203. tracer.fine("Event Unreferenced. Handle = "+handle+", type = "+eventType.getEventType()+", event = "+event);
  1204. }
  1205. if(event instanceof ResponseEventWrapper) {
  1206. final ResponseEventWrapper rew = (ResponseEventWrapper) event;
  1207. processResponseEventUnreferenced(rew);
  1208. }
  1209. else if(event instanceof RequestEventWrapper) {
  1210. final RequestEventWrapper rew = (RequestEventWrapper) event;
  1211. final ServerTransactionWrapper stw = (ServerTransactionWrapper) rew.getServerTransaction();
  1212. if (stw.isAckTransaction()) {
  1213. processTransactionTerminated(stw);
  1214. }
  1215. else {
  1216. final Request r = rew.getRequest();
  1217. if (r.getMethod().equals(Request.CANCEL)) {
  1218. // lets be a good citizen and reply if no sbb has done
  1219. if (stw.getState() != TransactionState.TERMINATED) {
  1220. processCancelNotHandled(stw,r);
  1221. }
  1222. }
  1223. }
  1224. }
  1225. }
  1226. /**
  1227. * @param rew
  1228. */
  1229. private void processResponseEventUnreferenced(ResponseEventWrapper rew) {
  1230. final ClientTransactionWrapper ctw = (ClientTransactionWrapper) rew
  1231. .getClientTransaction();
  1232. if (!ctw.isActivity()) {
  1233. // a client tx that is not activity must be removed from dialog here
  1234. final DialogWrapper dw = ctw.getDialogWrapper();
  1235. if (dw != null) {
  1236. dw.removeOngoingTransaction(ctw);
  1237. } else {
  1238. if (tracer.isWarningEnabled()) {
  1239. tracer.warning(ctw
  1240. + " not able to remove itself from dialog, dialog reference does not exists");
  1241. }
  1242. }
  1243. ctw.clear();
  1244. } else {
  1245. // end the activity
  1246. endActivity(activityManagement.get(ctw.getActivityHandle()));
  1247. }
  1248. }
  1249. // RA CONFIG
  1250. /*
  1251. * (non-Javadoc)
  1252. * @see javax.slee.resource.ResourceAdaptor#raConfigurationUpdate(javax.slee.resource.ConfigProperties)
  1253. */
  1254. public void raConfigurationUpdate(ConfigProperties properties) {
  1255. raConfigure(properties);
  1256. }
  1257. /*
  1258. * (non-Javadoc)
  1259. * @see javax.slee.resource.ResourceAdaptor#raConfigure(javax.slee.resource.ConfigProperties)
  1260. */
  1261. public void raConfigure(ConfigProperties properties) {
  1262. if (tracer.isFineEnabled()) {
  1263. tracer.fine("Configuring RA.");
  1264. }
  1265. this.port = (Integer) properties.getProperty(SIP_PORT_BIND).getValue();
  1266. this.stackAddress = (String) properties.getProperty(SIP_BIND_ADDRESS).getValue();
  1267. if (this.stackAddress.equals("")) {
  1268. this.stackAddress = System.getProperty("jboss.bind.address");
  1269. }
  1270. this.balancers = (String) properties.getProperty(BALANCERS).getValue();
  1271. if (this.balancers.equ

Large files files are truncated, but you can click here to view the full file