/** * Indicates a user request to answer an incoming call from this <tt>CallPeer</tt>. * * <p>Sends an OK response to <tt>callPeer</tt>. Make sure that the call peer contains an SDP * description when you call this method. * * @throws OperationFailedException if we fail to create or send the response. */ public synchronized void answer() throws OperationFailedException { RtpDescriptionPacketExtension answer = null; try { getMediaHandler().getTransportManager().wrapupConnectivityEstablishment(); answer = getMediaHandler().generateSessionAccept(true); } catch (IllegalArgumentException e) { sessAcceptedWithNoCands = new SessionIQ(); // HACK apparently FreeSwitch need to have accept before answer = getMediaHandler().generateSessionAccept(false); SessionIQ response = GTalkPacketFactory.createSessionAccept( sessionInitIQ.getTo(), sessionInitIQ.getFrom(), getSID(), answer); getProtocolProvider().getConnection().sendPacket(response); return; } catch (Exception exc) { logger.info("Failed to answer an incoming call", exc); // send an error response String reasonText = "Error: " + exc.getMessage(); SessionIQ errResp = GTalkPacketFactory.createSessionTerminate( sessionInitIQ.getTo(), sessionInitIQ.getFrom(), sessionInitIQ.getID(), Reason.FAILED_APPLICATION, reasonText); setState(CallPeerState.FAILED, reasonText); getProtocolProvider().getConnection().sendPacket(errResp); return; } SessionIQ response = GTalkPacketFactory.createSessionAccept( sessionInitIQ.getTo(), sessionInitIQ.getFrom(), getSID(), answer); // send the packet first and start the stream later in case the media // relay needs to see it before letting hole punching techniques through. if (sessAcceptedWithNoCands == null) getProtocolProvider().getConnection().sendPacket(response); try { getMediaHandler().start(); } catch (UndeclaredThrowableException e) { Throwable exc = e.getUndeclaredThrowable(); logger.info("Failed to establish a connection", exc); // send an error response String reasonText = "Error: " + exc.getMessage(); SessionIQ errResp = GTalkPacketFactory.createSessionTerminate( sessionInitIQ.getTo(), sessionInitIQ.getFrom(), sessionInitIQ.getID(), Reason.GENERAL_ERROR, reasonText); getMediaHandler().getTransportManager().close(); setState(CallPeerState.FAILED, reasonText); getProtocolProvider().getConnection().sendPacket(errResp); return; } // tell everyone we are connecting so that the audio notifications would // stop setState(CallPeerState.CONNECTED); }