src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java
/**
     * Parses and handles the specified <tt>offer</tt> and returns a content
     * extension representing the current state of this media handler. This
     * method MUST only be called when <tt>offer</tt> is the first session
     * description that this <tt>MediaHandler</tt> is seeing.
     *
     * @param offer the offer that we'd like to parse, handle and get an answer
     * for.
     *
     * @throws OperationFailedException if we have a problem satisfying the
     * description received in <tt>offer</tt> (e.g. failed to open a device or
     * initialize a stream ...).
     * @throws IllegalArgumentException if there's a problem with
     * <tt>offer</tt>'s format or semantics.
     */
Parses and handles the specified offer and returns a content
extension representing the current state of this media handler. This
method MUST only be called when offer is the first session
description that this MediaHandler is seeing.

@param offer the offer that we'd like to parse, handle and get an answer
for.

@throws OperationFailedException if we have a problem satisfying the
description received in offer .
@throws IllegalArgumentException if there's a problem with
offer's format or semantics.
Parses and handles the specified offer and returns a content extension representing the current state of this media handler . This method MUST only be called when offer is the first session description that this MediaHandler is seeing . @param offer the offer that we ' d like to parse handle and get an answer for . @throws OperationFailedException if we have a problem satisfying the description received in offer . @throws IllegalArgumentException if there ' s a problem with offer ' s format or semantics .
public void processOffer(List<ContentPacketExtension> offer)
        throws OperationFailedException,
               IllegalArgumentException
    {
        List<ContentPacketExtension> answer = new ArrayList<>(offer.size());
        boolean atLeastOneValidDescription = false;
        for (ContentPacketExtension content : offer)
        {
            remoteContentMap.put(content.getName(), content);
            RtpDescriptionPacketExtension description
                = JingleUtils.getRtpDescription(content);
            MediaType mediaType
                = JingleUtils.getMediaType(content);
            List<MediaFormat> remoteFormats
                = JingleUtils.extractFormats(
                        description,
                        getDynamicPayloadTypes());
            MediaDevice dev = getDefaultDevice(mediaType);
            MediaDirection devDirection
                = (dev == null) ? MediaDirection.INACTIVE : dev.getDirection();
            devDirection
                = devDirection.and(getDirectionUserPreference(mediaType));
            MediaDirection remoteDirection = JingleUtils.getDirection(
                                            content, getPeer().isInitiator());
            MediaDirection direction
                = devDirection.getDirectionForAnswer(remoteDirection);
            List<MediaFormat> mutuallySupportedFormats
                = intersectFormats(
                        remoteFormats,
                        getLocallySupportedFormats(dev));
            List<RTPExtension> offeredRTPExtensions
                    = JingleUtils.extractRTPExtensions(
                            description, this.getRtpExtensionsRegistry());
            List<RTPExtension> supportedExtensions
                    = getExtensionsForType(mediaType);
            List<RTPExtension> rtpExtensions = intersectRTPExtensions(
                            offeredRTPExtensions, supportedExtensions);
            /*
             * RawUdpTransportPacketExtension extends
             * IceUdpTransportPacketExtension so getting
             * IceUdpTransportPacketExtension should suffice.
             */
            IceUdpTransportPacketExtension transport
                = content.getFirstChildOfType(
                        IceUdpTransportPacketExtension.class);
            MediaStreamTarget target = null;
            try
            {
                target = JingleUtils.extractDefaultTarget(content);
            }
            catch(IllegalArgumentException e)
            {
                logger.warn("Fail to extract default target", e);
            }
            int targetDataPort
                = (target == null && transport != null)
                    ? -1
                    : (target != null) ? target.getDataAddress().getPort() : 0;
            /*
             * TODO If the offered transport is not supported, attempt to fall
             * back to a supported one using transport-replace.
             */
            setTransportManager(transport.getNamespace());
            boolean rtcpmux = false;
            if (!transport.getChildExtensionsOfType(
                    RtcpmuxPacketExtension.class).isEmpty())
            {
                rtcpmux = true;
                getTransportManager().setRtcpmux(true);
            }
            if (mutuallySupportedFormats.isEmpty()
                    || (devDirection == MediaDirection.INACTIVE)
                    || (targetDataPort == 0))
            {
                closeStream(mediaType);
                continue;
            }
            SendersEnum senders = JingleUtils.getSenders(
                    direction,
                    !getPeer().isInitiator());
            ContentPacketExtension ourContent
                = JingleUtils.createDescription(
                        content.getCreator(),
                        content.getName(),
                        senders,
                        mutuallySupportedFormats,
                        rtpExtensions,
                        getDynamicPayloadTypes(),
                        getRtpExtensionsRegistry());
            /*
             * Sets ZRTP, SDES or DTLS-SRTP depending on the preferences for
             * this account.
             */
            setAndAddPreferredEncryptionProtocol(
                    mediaType,
                    ourContent,
                    content,
                    rtcpmux);
            if(content.getChildExtensionsOfType(InputEvtPacketExtension.class)
                    != null)
            {
                ourContent.addChildExtension(new InputEvtPacketExtension());
            }
            answer.add(ourContent);
            localContentMap.put(content.getName(), ourContent);
            atLeastOneValidDescription = true;
        }
        if (!atLeastOneValidDescription)
        {
            ProtocolProviderServiceJabberImpl.throwOperationFailedException(
                    "Offer contained no media formats"
                        + " or no valid media descriptions.",
                    OperationFailedException.ILLEGAL_ARGUMENT,
                    null,
                    logger);
        }
        TransportInfoSender infoSender = new TransportInfoSender()
        {
            @Override
            public void sendTransportInfo(
                Iterable<ContentPacketExtension> contents)
            {
                try
                {
                    getPeer().sendTransportInfo(contents);
                }
                catch (NotConnectedException | InterruptedException e)
                {
                    logger.error("Could not send transport info", e);
                }
            }
        };
        /*
         * In order to minimize post-pickup delay, start establishing the
         * connectivity prior to ringing.
         */
        harvestCandidates(offer, answer, infoSender);
        /*
         * While it may sound like we can completely eliminate the post-pickup
         * delay by waiting for the connectivity establishment to finish, it may
         * not be possible in all cases. We are the Jingle session responder so,
         * in the case of the ICE UDP transport, we are not the controlling ICE
         * Agent and we cannot be sure when the controlling ICE Agent will
         * perform the nomination. It could, for example, choose to wait for our
         * session-accept to perform the nomination which will deadlock us if we
         * have chosen to wait for the connectivity establishment to finish
         * before we begin ringing and send session-accept.
         */
        getTransportManager().startConnectivityEstablishment(offer);
    }
public void processOffer ( List < ContentPacketExtension > offer ) throws OperationFailedException , IllegalArgumentException { List < ContentPacketExtension > answer = new ArrayList < > ( offer . size ( ) ) ; boolean atLeastOneValidDescription = false ; for ( ContentPacketExtension content : offer ) { remoteContentMap . put ( content . getName ( ) , content ) ; RtpDescriptionPacketExtension description = JingleUtils . getRtpDescription ( content ) ; MediaType mediaType = JingleUtils . getMediaType ( content ) ; List < MediaFormat > remoteFormats = JingleUtils . extractFormats ( description , getDynamicPayloadTypes ( ) ) ; MediaDevice dev = getDefaultDevice ( mediaType ) ; MediaDirection devDirection = ( dev == null ) ? MediaDirection . INACTIVE : dev . getDirection ( ) ; devDirection = devDirection . and ( getDirectionUserPreference ( mediaType ) ) ; MediaDirection remoteDirection = JingleUtils . getDirection ( content , getPeer ( ) . isInitiator ( ) ) ; MediaDirection direction = devDirection . getDirectionForAnswer ( remoteDirection ) ; List < MediaFormat > mutuallySupportedFormats = intersectFormats ( remoteFormats , getLocallySupportedFormats ( dev ) ) ; List < RTPExtension > offeredRTPExtensions = JingleUtils . extractRTPExtensions ( description , this . getRtpExtensionsRegistry ( ) ) ; List < RTPExtension > supportedExtensions = getExtensionsForType ( mediaType ) ; List < RTPExtension > rtpExtensions = intersectRTPExtensions ( offeredRTPExtensions , supportedExtensions ) ; /*
             * RawUdpTransportPacketExtension extends
             * IceUdpTransportPacketExtension so getting
             * IceUdpTransportPacketExtension should suffice.
             */ IceUdpTransportPacketExtension transport = content . getFirstChildOfType ( IceUdpTransportPacketExtension . class ) ; MediaStreamTarget target = null ; try { target = JingleUtils . extractDefaultTarget ( content ) ; } catch ( IllegalArgumentException e ) { logger . warn ( "Fail to extract default target" , e ) ; } int targetDataPort = ( target == null && transport != null ) ? - 1 : ( target != null ) ? target . getDataAddress ( ) . getPort ( ) : 0 ; /*
             * TODO If the offered transport is not supported, attempt to fall
             * back to a supported one using transport-replace.
             */ setTransportManager ( transport . getNamespace ( ) ) ; boolean rtcpmux = false ; if ( ! transport . getChildExtensionsOfType ( RtcpmuxPacketExtension . class ) . isEmpty ( ) ) { rtcpmux = true ; getTransportManager ( ) . setRtcpmux ( true ) ; } if ( mutuallySupportedFormats . isEmpty ( ) || ( devDirection == MediaDirection . INACTIVE ) || ( targetDataPort == 0 ) ) { closeStream ( mediaType ) ; continue ; } SendersEnum senders = JingleUtils . getSenders ( direction , ! getPeer ( ) . isInitiator ( ) ) ; ContentPacketExtension ourContent = JingleUtils . createDescription ( content . getCreator ( ) , content . getName ( ) , senders , mutuallySupportedFormats , rtpExtensions , getDynamicPayloadTypes ( ) , getRtpExtensionsRegistry ( ) ) ; /*
             * Sets ZRTP, SDES or DTLS-SRTP depending on the preferences for
             * this account.
             */ setAndAddPreferredEncryptionProtocol ( mediaType , ourContent , content , rtcpmux ) ; if ( content . getChildExtensionsOfType ( InputEvtPacketExtension . class ) != null ) { ourContent . addChildExtension ( new InputEvtPacketExtension ( ) ) ; } answer . add ( ourContent ) ; localContentMap . put ( content . getName ( ) , ourContent ) ; atLeastOneValidDescription = true ; } if ( ! atLeastOneValidDescription ) { ProtocolProviderServiceJabberImpl . throwOperationFailedException ( "Offer contained no media formats" + " or no valid media descriptions." , OperationFailedException . ILLEGAL_ARGUMENT , null , logger ) ; } TransportInfoSender infoSender = new TransportInfoSender ( ) { @ Override public void sendTransportInfo ( Iterable < ContentPacketExtension > contents ) { try { getPeer ( ) . sendTransportInfo ( contents ) ; } catch ( NotConnectedException | InterruptedException e ) { logger . error ( "Could not send transport info" , e ) ; } } } ; /*
         * In order to minimize post-pickup delay, start establishing the
         * connectivity prior to ringing.
         */ harvestCandidates ( offer , answer , infoSender ) ; /*
         * While it may sound like we can completely eliminate the post-pickup
         * delay by waiting for the connectivity establishment to finish, it may
         * not be possible in all cases. We are the Jingle session responder so,
         * in the case of the ICE UDP transport, we are not the controlling ICE
         * Agent and we cannot be sure when the controlling ICE Agent will
         * perform the nomination. It could, for example, choose to wait for our
         * session-accept to perform the nomination which will deadlock us if we
         * have chosen to wait for the connectivity establishment to finish
         * before we begin ringing and send session-accept.
         */ getTransportManager ( ) . startConnectivityEstablishment ( offer ) ; }
Parses and handles the specified <tt>offer</tt> and returns a content
 extension representing the current state of this media handler.
Parses and handles the specified <tt > offer< / tt > and returns a content extension representing the current state of this media handler .
// prepare to generate answers to all the incoming descriptions // Take the preference of the user with respect to streaming // mediaType into account. // determine the direction that we need to announce. // intersect the MediaFormats of our device with remote ones // check whether we will be exchanging any RTP extensions. // transport // stream target // according to XEP-176, transport element in session-initiate // "MAY instead be empty (with each candidate to be sent as the // payload of a transport-info message)". // skip stream and continue. contrary to sip we don't seem to // need to send per-stream disabling answer and only one at the // end. //close the stream in case it already exists // create the answer description // Got a content which has inputevt. It means that the peer requests // a desktop sharing session so tell it we support inputevt.