package com.voxeo.moho.sip; import javax.media.mscontrol.MediaEventListener; import javax.media.mscontrol.MsControlException; import javax.media.mscontrol.MsControlFactory; import javax.media.mscontrol.join.Joinable; import javax.media.mscontrol.join.Joinable.Direction; import javax.media.mscontrol.networkconnection.NetworkConnection; import javax.media.mscontrol.networkconnection.SdpPortManagerEvent; import org.apache.log4j.Logger; import com.voxeo.moho.ApplicationContext; import com.voxeo.moho.ApplicationContextImpl; import com.voxeo.moho.Call; import com.voxeo.moho.CallImpl; import com.voxeo.moho.NegotiateException; import com.voxeo.moho.Participant; import com.voxeo.moho.Participant.JoinType; import com.voxeo.moho.ParticipantContainer; import com.voxeo.moho.common.event.MohoJoinCompleteEvent; import com.voxeo.moho.event.JoinCompleteEvent; import com.voxeo.moho.event.JoinCompleteEvent.Cause; import com.voxeo.moho.remotejoin.RemoteParticipant; public class LocalRemoteJoinDelegate extends JoinDelegate implements MediaEventListener<SdpPortManagerEvent> { private static final Logger LOG = Logger.getLogger(LocalRemoteJoinDelegate.class); protected Participant _localParticipant; protected RemoteParticipantImpl _remoteParticipant; protected boolean waitAnswerProcessed; protected boolean notifyRemote; protected boolean started; public LocalRemoteJoinDelegate(final Participant local, final RemoteParticipant remoteParticipant, final Direction direction) { _localParticipant = local; _remoteParticipant = (RemoteParticipantImpl) remoteParticipant; _direction = direction; _joinType = JoinType.BRIDGE; } @Override public void doJoin() throws Exception { LOG.debug("LocalRemoteJoinDelegate is starting"); if (!started) { _remoteParticipant.startJoin(_localParticipant, this); ((ParticipantContainer) _localParticipant).startJoin(_remoteParticipant, this); } started = true; if(_localParticipant instanceof Call){ doDisengage((SIPCallImpl)_localParticipant, JoinType.BRIDGE); } if (_localParticipant.getMediaObject() == null && _localParticipant instanceof Call) { ((Call) _localParticipant).join(Direction.DUPLEX); return; } // 1 create network connection this.createNetworkConnection(_localParticipant.getApplicationContext(), _remoteParticipant); // 2 join network connection ((Joinable) _localParticipant.getMediaObject()).join(_direction, _remoteParticipant.getNetworkConnection()); // generate sdp offer. _remoteParticipant.getNetworkConnection().getSdpPortManager().generateSdpOffer(); } @Override public void onEvent(SdpPortManagerEvent event) { LOG.debug("LocalRemoteJoinDelegate received SdpPortManagerEvent"); if (event.getEventType().equals(SdpPortManagerEvent.OFFER_GENERATED)) { if (event.isSuccessful()) { waitAnswerProcessed = true; final byte[] sdp = event.getMediaServerSdp(); try { ((ApplicationContextImpl) _remoteParticipant.getApplicationContext()).getRemoteCommunication().join( _localParticipant.getId(), _remoteParticipant.getId(), _joinType, sdp); } catch (final Exception e) { LOG.error("", e); done(Cause.ERROR, e); } } else { Exception ex = new NegotiateException(event); done(Cause.ERROR, ex); } } else if (event.getEventType().equals(SdpPortManagerEvent.ANSWER_PROCESSED)) { if (event.isSuccessful()) { if (waitAnswerProcessed) { notifyRemote = true; done(JoinCompleteEvent.Cause.JOINED, null); return; } } Exception ex = new NegotiateException(event); notifyRemote = true; done(Cause.ERROR, ex); } } public void remoteJoinAnswer(byte[] sdp) throws Exception { try { _remoteParticipant.getNetworkConnection().getSdpPortManager().processSdpAnswer(sdp); } catch (Exception e) { LOG.error("Error when doing remote join:" + e.getMessage(), e); done(Cause.ERROR, e); throw e; } } protected synchronized void createNetworkConnection(ApplicationContext context, RemoteParticipantImpl remoteParticipant) throws MsControlException { MsControlFactory mf = context.getMSFactory(); remoteParticipant.setMediaSession(mf.createMediaSession()); NetworkConnection network = remoteParticipant.getMediaSession().createNetworkConnection(NetworkConnection.BASIC, null); remoteParticipant.setNetworkConnection(network); network.getSdpPortManager().addListener(this); } @Override public synchronized void done(final Cause cause, Exception exception) { if (done) { return; } _cause = cause; _exception = exception; ((ParticipantContainer) _localParticipant).joinDone(_remoteParticipant, this); JoinCompleteEvent joinCompleteEvent = new MohoJoinCompleteEvent(_localParticipant, _remoteParticipant, cause, exception, true); if (cause == Cause.JOINED) { ((ParticipantContainer) _localParticipant).addParticipant(_remoteParticipant, _joinType, _direction, null); } _remoteParticipant.joinDone(notifyRemote); _settableJoint.done(joinCompleteEvent); _localParticipant.dispatch(joinCompleteEvent); done = true; } }