src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerJabberImpl.java
/**
     * Starts transport candidate harvest. This method should complete rapidly
     * and, in case of lengthy procedures like STUN/TURN/UPnP candidate harvests
     * are necessary, they should be executed in a separate thread. Candidate
     * harvest would then need to be concluded in the
     * {@link #wrapupCandidateHarvest()} method which would be called once we
     * absolutely need the candidates.
     *
     * @param theirOffer a media description offer that we've received from the
     * remote party and that we should use in case we need to know what
     * transports our peer is using.
     * @param ourAnswer the content descriptions that we should be adding our
     * transport lists to (although not necessarily in this very instance).
     * @param transportInfoSender the <tt>TransportInfoSender</tt> to be used by
     * this <tt>TransportManagerJabberImpl</tt> to send <tt>transport-info</tt>
     * <tt>JingleIQ</tt>s from the local peer to the remote peer if this
     * <tt>TransportManagerJabberImpl</tt> wishes to utilize
     * <tt>transport-info</tt>. Local candidate addresses sent by this
     * <tt>TransportManagerJabberImpl</tt> in <tt>transport-info</tt> are
     * expected to not be included in the result of
     * {@link #wrapupCandidateHarvest()}.
     *
     * @throws OperationFailedException if we fail to allocate a port number.
     */
Starts transport candidate harvest. This method should complete rapidly
and, in case of lengthy procedures like STUN/TURN/UPnP candidate harvests
are necessary, they should be executed in a separate thread. Candidate
harvest would then need to be concluded in the
#wrapupCandidateHarvest() method which would be called once we
absolutely need the candidates.

@param theirOffer a media description offer that we've received from the
remote party and that we should use in case we need to know what
transports our peer is using.
@param ourAnswer the content descriptions that we should be adding our
transport lists to (although not necessarily in this very instance).
@param transportInfoSender the TransportInfoSender to be used by
this TransportManagerJabberImpl to send transport-info
JingleIQs from the local peer to the remote peer if this
TransportManagerJabberImpl wishes to utilize
transport-info. Local candidate addresses sent by this
TransportManagerJabberImpl in transport-info are
expected to not be included in the result of
#wrapupCandidateHarvest().

@throws OperationFailedException if we fail to allocate a port number.
Starts transport candidate harvest . This method should complete rapidly and in case of lengthy procedures like STUN / TURN / UPnP candidate harvests are necessary they should be executed in a separate thread . Candidate harvest would then need to be concluded in the #wrapupCandidateHarvest () method which would be called once we absolutely need the candidates . @param theirOffer a media description offer that we ' ve received from the remote party and that we should use in case we need to know what transports our peer is using . @param ourAnswer the content descriptions that we should be adding our transport lists to ( although not necessarily in this very instance ) . @param transportInfoSender the TransportInfoSender to be used by this TransportManagerJabberImpl to send transport - info JingleIQs from the local peer to the remote peer if this TransportManagerJabberImpl wishes to utilize transport - info . Local candidate addresses sent by this TransportManagerJabberImpl in transport - info are expected to not be included in the result of #wrapupCandidateHarvest () . @throws OperationFailedException if we fail to allocate a port number .
public void startCandidateHarvest(
            List<ContentPacketExtension> theirOffer,
            List<ContentPacketExtension> ourAnswer,
            TransportInfoSender transportInfoSender)
        throws OperationFailedException
    {
        CallPeerJabberImpl peer = getCallPeer();
        CallJabberImpl call = peer.getCall();
        boolean isJitsiVideobridge = call.getConference().isJitsiVideobridge();
        List<ContentPacketExtension> cpes
            = (theirOffer == null) ? ourAnswer : theirOffer;
        /*
         * If Jitsi Videobridge is to be used, determine which channels are to
         * be allocated and attempt to allocate them now.
         */
        if (isJitsiVideobridge)
        {
            Map<ContentPacketExtension,ContentPacketExtension> contentMap
                = new LinkedHashMap
                    <ContentPacketExtension,ContentPacketExtension>();
            for (ContentPacketExtension cpe : cpes)
            {
                MediaType mediaType = JingleUtils.getMediaType(cpe);
                /*
                 * The existence of a content for the mediaType and regardless
                 * of the existence of channels in it signals that a channel
                 * allocation request has already been sent for that mediaType.
                 */
                if ((colibri == null)
                        || (colibri.getContent(mediaType.toString()) == null))
                {
                    ContentPacketExtension local, remote;
                    if (cpes == ourAnswer)
                    {
                        local = cpe;
                        remote
                            = (theirOffer == null)
                                ? null
                                : findContentByName(theirOffer, cpe.getName());
                    }
                    else
                    {
                        local = findContentByName(ourAnswer, cpe.getName());
                        remote = cpe;
                    }
                    contentMap.put(local, remote);
                }
            }
            if (!contentMap.isEmpty())
            {
                /*
                 * We are about to request the channel allocations for the media
                 * types found in contentMap. Regardless of the response, we do
                 * not want to repeat these requests.
                 */
                if (colibri == null)
                    colibri = new ColibriConferenceIQ();
                for (Map.Entry<ContentPacketExtension,ContentPacketExtension> e
                        : contentMap.entrySet())
                {
                    ContentPacketExtension cpe = e.getValue();
                    if (cpe == null)
                        cpe = e.getKey();
                    colibri.getOrCreateContent(
                        JingleUtils.getMediaType(cpe).toString());
                }
                ColibriConferenceIQ conferenceResult
                    = call.createColibriChannels(peer, contentMap);
                if (conferenceResult != null)
                {
                    String videobridgeID = colibri.getID();
                    String conferenceResultID = conferenceResult.getID();
                    if (videobridgeID == null)
                        colibri.setID(conferenceResultID);
                    else if (!videobridgeID.equals(conferenceResultID))
                        throw new IllegalStateException("conference.id");
                    Jid videobridgeFrom = conferenceResult.getFrom();
                    if ((videobridgeFrom != null)
                            && (videobridgeFrom.length() != 0))
                    {
                        colibri.setFrom(videobridgeFrom);
                    }
                    for (ColibriConferenceIQ.Content contentResult
                            : conferenceResult.getContents())
                    {
                        ColibriConferenceIQ.Content content
                            = colibri.getOrCreateContent(
                                    contentResult.getName());
                        for (ColibriConferenceIQ.Channel channelResult
                                : contentResult.getChannels())
                        {
                            if (content.getChannel(channelResult.getID())
                                    == null)
                            {
                                content.addChannel(channelResult);
                            }
                        }
                    }
                }
                else
                {
                    /*
                     * The call fails if the createColibriChannels method fails
                     * which may happen if the conference packet times out or it
                     * can't be built.
                     */
                    ProtocolProviderServiceJabberImpl
                        .throwOperationFailedException(
                                "Failed to allocate colibri channel.",
                                OperationFailedException.GENERAL_ERROR,
                                null,
                                logger);
                }
            }
        }
        for (ContentPacketExtension cpe : cpes)
        {
            String contentName = cpe.getName();
            ContentPacketExtension ourContent
                = findContentByName(ourAnswer, contentName);
            if (ourContent != null)
            {
                ContentPacketExtension theirContent
                    = (theirOffer == null)
                        ? null
                        : findContentByName(theirOffer, contentName);
                RtpDescriptionPacketExtension rtpDesc
                    = ourContent.getFirstChildOfType(
                            RtpDescriptionPacketExtension.class);
                String media = rtpDesc.getMedia();
                ExtensionElement pe
                    = startCandidateHarvest(
                            theirContent,
                            ourContent,
                            transportInfoSender,
                            media);
                if (pe != null)
                    ourContent.addChildExtension(pe);
            }
        }
    }
public void startCandidateHarvest ( List < ContentPacketExtension > theirOffer , List < ContentPacketExtension > ourAnswer , TransportInfoSender transportInfoSender ) throws OperationFailedException { CallPeerJabberImpl peer = getCallPeer ( ) ; CallJabberImpl call = peer . getCall ( ) ; boolean isJitsiVideobridge = call . getConference ( ) . isJitsiVideobridge ( ) ; List < ContentPacketExtension > cpes = ( theirOffer == null ) ? ourAnswer : theirOffer ; /*
         * If Jitsi Videobridge is to be used, determine which channels are to
         * be allocated and attempt to allocate them now.
         */ if ( isJitsiVideobridge ) { Map < ContentPacketExtension , ContentPacketExtension > contentMap = new LinkedHashMap < ContentPacketExtension , ContentPacketExtension > ( ) ; for ( ContentPacketExtension cpe : cpes ) { MediaType mediaType = JingleUtils . getMediaType ( cpe ) ; /*
                 * The existence of a content for the mediaType and regardless
                 * of the existence of channels in it signals that a channel
                 * allocation request has already been sent for that mediaType.
                 */ if ( ( colibri == null ) || ( colibri . getContent ( mediaType . toString ( ) ) == null ) ) { ContentPacketExtension local , remote ; if ( cpes == ourAnswer ) { local = cpe ; remote = ( theirOffer == null ) ? null : findContentByName ( theirOffer , cpe . getName ( ) ) ; } else { local = findContentByName ( ourAnswer , cpe . getName ( ) ) ; remote = cpe ; } contentMap . put ( local , remote ) ; } } if ( ! contentMap . isEmpty ( ) ) { /*
                 * We are about to request the channel allocations for the media
                 * types found in contentMap. Regardless of the response, we do
                 * not want to repeat these requests.
                 */ if ( colibri == null ) colibri = new ColibriConferenceIQ ( ) ; for ( Map . Entry < ContentPacketExtension , ContentPacketExtension > e : contentMap . entrySet ( ) ) { ContentPacketExtension cpe = e . getValue ( ) ; if ( cpe == null ) cpe = e . getKey ( ) ; colibri . getOrCreateContent ( JingleUtils . getMediaType ( cpe ) . toString ( ) ) ; } ColibriConferenceIQ conferenceResult = call . createColibriChannels ( peer , contentMap ) ; if ( conferenceResult != null ) { String videobridgeID = colibri . getID ( ) ; String conferenceResultID = conferenceResult . getID ( ) ; if ( videobridgeID == null ) colibri . setID ( conferenceResultID ) ; else if ( ! videobridgeID . equals ( conferenceResultID ) ) throw new IllegalStateException ( "conference.id" ) ; Jid videobridgeFrom = conferenceResult . getFrom ( ) ; if ( ( videobridgeFrom != null ) && ( videobridgeFrom . length ( ) != 0 ) ) { colibri . setFrom ( videobridgeFrom ) ; } for ( ColibriConferenceIQ . Content contentResult : conferenceResult . getContents ( ) ) { ColibriConferenceIQ . Content content = colibri . getOrCreateContent ( contentResult . getName ( ) ) ; for ( ColibriConferenceIQ . Channel channelResult : contentResult . getChannels ( ) ) { if ( content . getChannel ( channelResult . getID ( ) ) == null ) { content . addChannel ( channelResult ) ; } } } } else { /*
                     * The call fails if the createColibriChannels method fails
                     * which may happen if the conference packet times out or it
                     * can't be built.
                     */ ProtocolProviderServiceJabberImpl . throwOperationFailedException ( "Failed to allocate colibri channel." , OperationFailedException . GENERAL_ERROR , null , logger ) ; } } } for ( ContentPacketExtension cpe : cpes ) { String contentName = cpe . getName ( ) ; ContentPacketExtension ourContent = findContentByName ( ourAnswer , contentName ) ; if ( ourContent != null ) { ContentPacketExtension theirContent = ( theirOffer == null ) ? null : findContentByName ( theirOffer , contentName ) ; RtpDescriptionPacketExtension rtpDesc = ourContent . getFirstChildOfType ( RtpDescriptionPacketExtension . class ) ; String media = rtpDesc . getMedia ( ) ; ExtensionElement pe = startCandidateHarvest ( theirContent , ourContent , transportInfoSender , media ) ; if ( pe != null ) ourContent . addChildExtension ( pe ) ; } } }
Starts transport candidate harvest.
Starts transport candidate harvest .
//it might be that we decided not to reply to this content