package com.voxeo.moho.sip; import java.util.Map; import javax.media.mscontrol.join.Joinable.Direction; import javax.servlet.sip.SipServletRequest; import javax.servlet.sip.SipServletResponse; import org.apache.log4j.Logger; import com.voxeo.moho.ApplicationContextImpl; import com.voxeo.moho.Participant.JoinType; import com.voxeo.moho.ParticipantContainer; import com.voxeo.moho.common.event.MohoJoinCompleteEvent; import com.voxeo.moho.common.util.InheritLogContextRunnable; import com.voxeo.moho.event.JoinCompleteEvent; import com.voxeo.moho.event.JoinCompleteEvent.Cause; public class DirectRemoteLocalJoinDelegate extends JoinDelegate { private static final Logger LOG = Logger.getLogger(DirectRemoteLocalJoinDelegate.class); protected RemoteParticipantImpl _remoteParticipant; protected SIPCallImpl _localParticipant; protected byte[] _sdpOffer; protected boolean notifyRemote; public DirectRemoteLocalJoinDelegate(final RemoteParticipantImpl remoteParticipant, final SIPCallImpl localParticipant, final Direction direction, byte[] offer) { _localParticipant = localParticipant; _remoteParticipant = (RemoteParticipantImpl) remoteParticipant; _direction = direction; _joinType = JoinType.DIRECT; _sdpOffer = offer; } @Override public void doJoin() throws Exception { _remoteParticipant.startJoin(_localParticipant, this); ((ParticipantContainer) _localParticipant).startJoin(_remoteParticipant, this); doDisengage(_localParticipant, JoinType.DIRECT); final byte[] answerSDP = _localParticipant.processSDPOffer(_sdpOffer); if (answerSDP != null) { // avoid dead lock. Runnable run = new InheritLogContextRunnable() { @Override public void run() { try { ((ApplicationContextImpl) _remoteParticipant.getApplicationContext()).getRemoteCommunication().joinAnswer( _remoteParticipant.getId(), _localParticipant.getRemoteAddress(), answerSDP); } catch (final Exception e) { LOG.error("", e); notifyRemote = true; done(Cause.ERROR, e); } } }; ((ApplicationContextImpl) _localParticipant.getApplicationContext()).getExecutor().execute(run); } } @Override protected void doInviteResponse(final SipServletResponse res, SIPCallImpl call, Map<String, String> headers) throws Exception { if (SIPHelper.isErrorResponse(res)) { notifyRemote = true; done(getJoinCompleteCauseByResponse(res), getExceptionByResponse(res)); } else { if (SIPHelper.isSuccessResponse(res)) { ((ApplicationContextImpl) _localParticipant.getApplicationContext()).getExecutor().execute(new InheritLogContextRunnable() { @Override public void run() { try { res.createAck().send(); ((ApplicationContextImpl) _remoteParticipant.getApplicationContext()).getRemoteCommunication() .joinAnswer(_remoteParticipant.getId(), _localParticipant.getId(), SIPHelper.getRawContentWOException(res)); } catch (final Exception e) { LOG.error("", e); notifyRemote = true; done(Cause.ERROR, e); } } }); } } } @Override protected void doAck(SipServletRequest req, SIPCallImpl call) throws Exception { // TODO only for not answered incoming call, do nothing now. } @Override public synchronized void done(Cause cause, Exception exception) { if (done) { return; } _cause = cause; _exception = exception; ((ParticipantContainer) _localParticipant).joinDone(_remoteParticipant, this); JoinCompleteEvent joinCompleteEvent = new MohoJoinCompleteEvent(_localParticipant, _remoteParticipant, cause, exception, false); if (cause == Cause.JOINED) { ((ParticipantContainer) _localParticipant).addParticipant(_remoteParticipant, _joinType, _direction, null); } _remoteParticipant.joinDone(notifyRemote); if (_settableJoint != null) { _settableJoint.done(joinCompleteEvent); } _localParticipant.dispatch(joinCompleteEvent); done = true; } }