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.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; public class RemoteLocalJoinDelegate extends JoinDelegate implements MediaEventListener<SdpPortManagerEvent> { private static final Logger LOG = Logger.getLogger(LocalRemoteJoinDelegate.class); protected RemoteParticipantImpl _remoteParticipant; protected Participant _localParticipant; protected byte[] sdpOffer; protected boolean waitAnswerProcessed = false; protected boolean notifyRemote; protected boolean started; public RemoteLocalJoinDelegate(final RemoteParticipantImpl remoteParticipant, final Participant localParticipant, final Direction direction, byte[] offer) { _localParticipant = localParticipant; _remoteParticipant = (RemoteParticipantImpl) remoteParticipant; // TODO set direction. _direction = Direction.DUPLEX; _joinType = JoinType.BRIDGE; sdpOffer = offer; } @Override public void doJoin() throws Exception { try { LOG.debug("RemoteLocalJoinDelegate 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) { notifyRemote = true; ((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()); // process sdp offer. _remoteParticipant.getNetworkConnection().getSdpPortManager().processSdpOffer(sdpOffer); } catch (Exception ex) { done(Cause.ERROR, ex); throw ex; } } @Override public void onEvent(SdpPortManagerEvent event) { if (event.getEventType().equals(SdpPortManagerEvent.ANSWER_GENERATED)) { if (event.isSuccessful()) { final byte[] sdp = event.getMediaServerSdp(); try { ((ApplicationContextImpl) _remoteParticipant.getApplicationContext()).getRemoteCommunication().joinAnswer( _remoteParticipant.getId(), _localParticipant.getRemoteAddress(), sdp); } catch (final Exception e) { LOG.error("", e); notifyRemote = false; done(Cause.ERROR, e); } } else { Exception ex = new NegotiateException(event); notifyRemote = true; done(Cause.ERROR, ex); } } else { Exception ex = new NegotiateException(event); notifyRemote = true; done(Cause.ERROR, ex); } } 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(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; } }