public void handleIncomingUpdate(Request msg) throws DialogStateException { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); if (!done.get()) { Logger.log("Remote party has sent update"); final Dialog dialog = getStackContext().getDialogStorage().findDialogForMessage(msg); assert dialog != null; checkUpdatePreconditions(dialog, msg); Logger.log(TAG, "mark dialog as update in progress"); dialog.markUpdateInProgress(InitiateParty.REMOTE); // TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction> // transactionType = SIP_REINVITE_SERVER; TransactionType<UpdateSrvTransaction, UpdateServerTransaction> transactionType = SIP_UPDATE_SERVER; doHandleIncomingUpdate(msg, dialog, transactionType); } }
/** Shutdowns the service */ public void shutdown() { Logger.log(getClass(), Logger.Tag.SHUTDOWN, "Shutdowning InviteService"); if (done.compareAndSet(false, true)) { unSubscribeFromTransactionManager(); } Logger.log(getClass(), Logger.Tag.SHUTDOWN, "InviteService shutdown successfully"); }
public void reject() throws RemoteException { Logger.log(TAG, "reject#started"); acceptable.reject(dialog, StatusCode.TEMPORARY_UNAVAILABLE, "TEMPORARY_UNAVAILABLE"); expire(); Logger.log(TAG, "reject#finish"); }
public void accept() throws RemoteException { Logger.log(TAG, "accept#started"); acceptable.accept(dialog); expire(); Logger.log(TAG, "accept#finish"); }
/** * Handles server noninvite message * * @param msg - noninvite message */ public void handleIncomingBye(final Request msg) { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); assert msg != null && MessageType.SIP_BYE == MessageType.parse(msg.getMethod()); Logger.log("Remote party has sent noninvite"); if (!done.get()) { final Dialog dialog = getStackContext().getDialogStorage().findDialogForMessage(msg); assert dialog != null; assert STATED == dialog.getState(); dialog.getMessageHistory().addMessage(msg, true); final TransactionManager transactionManager = getTransactionManager(); transactionManager.addListener( new FirstMessageResolver(SIP_BYE_SERVER.getName(), dialog, msg, transactionManager)); final Transaction transaction = transactionManager.lookUpTransaction(dialog, null, SIP_BYE_SERVER); runAsynchronously(transaction, TRANSACTION_TIMEOUT); } }
/** * Handles server invite message * * @param msg - invite message */ public void handleIncomingInvite(final Request msg) throws DialogStateException { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); assert msg != null && MessageType.SIP_INVITE == MessageType.parse(msg.getMethod()); if (!done.get()) { Logger.log("Remote party has sent invite"); // ClientIdentity localParty = // getStackContext().getStackClientRegistry().findAddressee(msg.getTo().getUriBuilder().getShortURI()); ClientIdentity localParty = getStackContext().getClientRouter().findAddressee(msg); if (localParty != null) { assert getStackContext().getDialogStorage().findDialogForMessage(msg) == null; final Dialog dialog = getStackContext().getDialogStorage().getDialogForIncomingMessage(localParty, msg); TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction> transactionType = SIP_INVITE_SERVER; doHandleIncomingInvite(msg, dialog, transactionType); } else { throw new DialogStateException(null, DialogStateException.Error.ADDRESSEE_NOT_FOUND, msg); } } }
public void reInvite(final Dialog dialog) throws DialogStateException { Logger.log(TAG, "reInvite#started"); assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); assert getStackContext().getDialogStorage().findDialogByCallId(dialog.getCallId()) != null : "DIALOG being re-invited is already terminated"; if (!done.get()) { checkReInvitePreconditions(dialog, null); dialog .getOutgoingSdpMessage() .setSessionVersion(dialog.getOutgoingSdpMessage().getSessionVersion() + 1); doReInvite(dialog, LONG_TRANSACTION_TIMEOUT); } Logger.log(TAG, "reInvite#finished"); }
public void onReceive(Context context, Intent intent) { Logger.log(TAG, "onReceive#" + intent + ", intent.getExtras()" + intent.getExtras()); if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { connectionManagerHandler.onConnectivity(); } else if (ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED.equals( intent.getAction())) { connectionManagerHandler.onConnectivity(); } }
private void preAccept(final Dialog dialog) { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); Logger.log(TAG, "preAccept"); if (!done.get()) { doPreAccept(dialog); } }
/** * Cancels establishing DIALOG * * @param dialog - DIALOG to cancel */ public void cancel(final Dialog dialog) { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); Logger.log("Canceling call"); if (!done.get()) { doCancel(dialog); } }
/** This method tries to invite remote party */ public void invite(final Dialog dialog) throws DialogStateException { Logger.log(TAG, "invite#started"); assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); if (!done.get()) { if (STATED == dialog.getState()) { throw new DialogStateException( dialog, INVITE_FOR_STATED_DIALOG, null, "Can not invite remote party. Dialog is already stated."); } if (getStackContext().getConfig().useInviteRefresh()) { addDialogStateListener(dialog, listenerForInviteRefresh); } doInvite(dialog, LONG_TRANSACTION_TIMEOUT); } Logger.log(TAG, "invite#finished"); }
public void handleIncomingCancel(Request msg) throws DialogStateException { assert !done.get(); assert msg != null && MessageType.SIP_CANCEL == MessageType.parse(msg.getMethod()); if (!done.get()) { Logger.log("Remote party has sent SIP_CANCEL"); final Dialog dialog = getStackContext().getDialogStorage().findDialogForMessage(msg); if (dialog != null) { dialog.getMessageHistory().addMessage(msg, true); final InviteSrvTransaction transaction = getTransactionManager().findTransaction(dialog, SIP_INVITE_SERVER); if (transaction != null) { final DialogStateEvent<BaseSipMessage> stateEvent = new DefaultDialogStateEvent<BaseSipMessage>( dialog, SessionState.SESSION_TERMINATED, msg); dialogStateListenerHolder.getNotifier().onSessionTerminated(stateEvent); dialogStateListenerHolder.getNotifier().onSessionEnded(stateEvent); // DIALOG.putCustomParameter(ParamKey.INITIAL_MESSAGE, ((Transaction) // transaction).getInitialMessage()); transaction.cancel(); } else { // assert false : "Transaction already terminated for msg: " + msg.shortDescription() + " // dialog: " + dialog; throw new DialogStateException( dialog, DialogStateException.Error.REQUEST_FOR_UNKNOWN_DIALOG, msg); } } else { // assert false : "Dialog is already terminated or never exist. Message :" + // msg.shortDescription(); throw new DialogStateException( dialog, DialogStateException.Error.REQUEST_FOR_UNKNOWN_DIALOG, msg); } } }
private void doHandleIncomingInvite( final Request msg, final Dialog dialog, final TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction> transactionType) { dialog.getMessageHistory().addMessage(msg, true); // DIALOG.putCustomParameter(ParamKey.LAST_MESSAGE, msg); Logger.log("doHandleIncomingInvite", ""); SdpMessage sdp = SipMessageUtils.getSdpFromMessage(msg); if (sdp != null) { dialog.setIncomingSdpMessage(sdp); } final TransactionManager transactionManager = getTransactionManager(); transactionManager.addListener( new FirstMessageResolver(transactionType.getName(), dialog, msg, transactionManager)); final InviteSrvTransaction transaction = transactionManager.lookUpTransaction(dialog, null, transactionType); runAsynchronously((Transaction<Boolean, BaseSipMessage>) transaction); }
public void handleIncomingReInvite(final Request msg) throws DialogStateException { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); assert msg != null && MessageType.SIP_INVITE == MessageType.parse(msg.getMethod()); if (!done.get()) { Logger.log("Remote party has sent ReInvite"); final Dialog dialog = getStackContext().getDialogStorage().findDialogForMessage(msg); assert dialog != null; checkReInvitePreconditions(dialog, msg); dialog.markReInviteInProgress(InitiateParty.REMOTE); TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction> transactionType = SIP_REINVITE_SERVER; doHandleIncomingInvite(msg, dialog, transactionType); } }
private void doRunFinalization( final AtomicReference<TransactionResult<T>> transactionId, final boolean innerCall, final TransactionResult.Reason reason, final T transactionResult, final ContextCallback<T> callback) { repetitiousTaskManager.cancelTask(transactionId); synchronized (mutex) { // this code may be called from three points: // 1. On latch TIMEOUT. In that case first coming thread sets the default return value, runs // finalization routine and awaits it finishes. // 2. On shutdown call. In that case calling thread set the default return value, runs // finalization routine and returns. // 3. On release call. In that case calling thread set the return value equals to the value // passed by calling thread, runs finalization routine and returns. final boolean trnsIdEmpty = transactionId.compareAndSet( null, transactionResult == null ? new TransactionResultImpl<T>(initialValue, reason) : new TransactionResultImpl<T>(transactionResult, reason)); if (trnsIdEmpty) { // flag whether we go through 1. scenario // create new finalization routine final FutureTask<Object> futureTask = new FutureTask<Object>( new Runnable() { public void run() { // run outer finalization routine // Thread.currentThread().setName("Transaction finalizator"); try { callback.finalizeTransaction(transactionId.get()); } catch (Exception e) { e.printStackTrace(); } finally { // let this iteration awaiting threads to be free and continue execution cleanUpFinalization(transactionId); } } }, null); // hold and execute new finalization routine finalizationMap.put(transactionId, futureTask); // TransactionUtils.getExecutorService().execute(futureTask); TransactionUtils.invokeLaterSmart( new TransactionRunnable("SynchronizationContext.doRunFinalization()") { public void run() { if (!futureTask.isCancelled() && !futureTask.isDone()) { futureTask.run(); futureTask.cancel(true); } } }); // set free waiting thread and initiate new iteration doReleaseThreads(); } } // here one more synchronization point for awaiting threads from this iteration // this time threads waiting till the end of finalization routine. // All outer threads (shutdown(), release()) do not block here if (innerCall) { boolean needCleanupFinalization = false; // for all separate transaction we have separate transactionId. //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (transactionId) { long startWait = System.currentTimeMillis(); // waiting here until finalization task is done. Finalization task clears the map by itself // threads do not wait more then FINALIZATION_TIMEOUT*2 while (finalizationMap.containsKey(transactionId)) { try { assert !TransactionUtils.isTransactionExecutionThread() : "Task queue blocking task detected"; transactionId.wait(FINALIZATION_TIMEOUT); } catch (InterruptedException e) { Thread.interrupted(); } if ((System.currentTimeMillis() - startWait) >= FINALIZATION_TIMEOUT) { needCleanupFinalization = true; break; } } } // if something happens to finalization routine (helper theread abruptly dead or something // like that) we make map clean up. // and try to notify all awaitng threads if (needCleanupFinalization) { Logger.log( "Warning!!! transaction finalization took too long time. More than " + FINALIZATION_TIMEOUT + " millis"); cleanUpFinalization(transactionId); } } }
private TransactionResult<T> doAppend(final TimeoutUnit timeoutUnit, final boolean block) { Logger.log( "ReentrantSynchronizationContext", "doAppend#timeoutUnit = " + timeoutUnit + ", block = " + block + ", done.get() = " + done.get()); TransactionResult<T> retValue = null; // possible to proceed only if there were no shutdown call on this instance if (!done.get()) { // latch for calling thread CountDownLatch localBarrier; // if the calling thread is a first on in this iteration the flag will get 'true' value boolean needInitiateTransaction; // each iteration has it's own instance of threadLocalTransactionId. Also it holds the current // iteration transaction value. // null means default value should be used final AtomicReference<TransactionResult<T>> threadLocalTransactionId; // nobody can go through if the same monitor is taken in other place. Probably in finalization // routine Logger.log("ReentrantSynchronizationContext", "doAppend#before sync"); synchronized (mutex) { Logger.log("ReentrantSynchronizationContext", "doAppend#after sync"); // each calling thread would have it's own latch. // It's supposed that some other awaking activity would countdown all the latches from list. localBarrier = new CountDownLatch(1); // list of all latches and associated threads. Used to release all threads at once for this // transaction iteration awaitingThreads.add(localBarrier); // barierList.add(localBarrier); // see description above needInitiateTransaction = false; if (transactionInProgress.compareAndSet(false, true)) { // if we first time in this iteration in this peace of code we mark that new transaction // shoud be started needInitiateTransaction = true; // also we prepare new transaction id. null means we don't have outer call to release() transactionId.set(new AtomicReference<TransactionResult<T>>(null)); } // each thread must hold transaction id it it's own heap threadLocalTransactionId = transactionId.get(); } // call outer initialization routine if (needInitiateTransaction) { Logger.log("ReentrantSynchronizationContext", "initiateTransaction#start"); callback.initiateTransaction(); Logger.log("ReentrantSynchronizationContext", "initiateTransaction#end"); } if (block) { TransactionResult.Reason reason = TransactionResult.Reason.OUTER_INTERRUPT; try { // make thread to wait until transaction finished or TIMEOUT EXPIRES if (timeoutUnit != null) { Logger.log( "ReentrantSynchronizationContext", "start await, timeoutUnit = " + timeoutUnit); localBarrier.await( timeoutUnit.getTimeout(), timeoutUnit.getTimeoutUnit() == null ? TimeUnit.MILLISECONDS : timeoutUnit.getTimeoutUnit()); } else { localBarrier.await(); } reason = localBarrier.getCount() > 0 ? TransactionResult.Reason.TIMEOUT : TransactionResult.Reason.OUTER_INTERRUPT; Logger.log("ReentrantSynchronizationContext", "end await, reason = " + reason); } catch (InterruptedException e) { // set thread flag Thread.interrupted(); reason = TransactionResult.Reason.OUTER_INTERRUPT; } finally { // try to run finalization routine final TransactionResult<T> transactionResult = threadLocalTransactionId.get(); Logger.log("ReentrantSynchronizationContext", "start tr. finalization"); runFinalization( threadLocalTransactionId, true, reason, transactionResult == null ? null : transactionResult.getValue(), callback); Logger.log("ReentrantSynchronizationContext", "end tr. finalization"); retValue = threadLocalTransactionId.get(); Logger.log( "ReentrantSynchronizationContext", "start tr. finalization, retValue = " + retValue); } } else { if (needInitiateTransaction) { boolean needTimeout = !(timeoutUnit == null || timeoutUnit.getTimeout() == null || timeoutUnit.getTimeoutUnit() == null); if (needTimeout) { long timeoutInMillis = timeoutUnit.getTimeoutUnit().toMillis(timeoutUnit.getTimeout()); repetitiousTaskManager.startDelayedTask( threadLocalTransactionId, new RepetitiousTaskManager.Repeater<AtomicReference<TransactionResult<T>>>() { @Override public void onRepeat( AtomicReference<TransactionResult<T>> key, Shutdownable shutdownable) { Logger.log(TAG, String.format("onRepeat")); final TransactionResult<T> transactionResult = key.get(); runFinalization( key, true, TransactionResult.Reason.TIMEOUT, transactionResult == null ? null : transactionResult.getValue(), callback); shutdownable.shutdown(); } }, timeoutInMillis); } } } } else { throw new IllegalStateException("Context already shutdown."); } return retValue; }