Package com.xonami.javaBells

Source Code of com.xonami.javaBells.IceAgent

package com.xonami.javaBells;

import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.BindException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.CandidatePacketExtension;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.CandidateType;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.ContentPacketExtension;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.IceUdpTransportPacketExtension;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.JingleIQ;
import org.ice4j.Transport;
import org.ice4j.TransportAddress;
import org.ice4j.ice.Agent;
import org.ice4j.ice.Candidate;
import org.ice4j.ice.Component;
import org.ice4j.ice.IceMediaStream;
import org.ice4j.ice.IceProcessingState;
import org.ice4j.ice.NominationStrategy;
import org.ice4j.ice.RemoteCandidate;
import org.ice4j.ice.harvest.StunCandidateHarvester;
import org.ice4j.ice.harvest.TurnCandidateHarvester;
//import org.ice4j.security.LongTermCredential;


/**
* IceAgent is essentially a wrapper for org.ice4j.ice.Agent with some utilities
* to translate jingle iq data to and from that class.
*
* Note that you must call freeAgent when you are done to ensure proper garbage collection.
*
* @author bjorn
*
*/
public class IceAgent {
  static SecureRandom random ;
  static {
    try {
      // Create a secure random number generator
      random = SecureRandom.getInstance("SHA1PRNG");
    } catch(NoSuchAlgorithmException e) {
      throw new RuntimeException();
    }
  }
 
  private int candidateId = 0;
 
  static final int MIN_STREAM_PORT = 5000;
  static final int MAX_STREAM_PORT = 9000;
  static int streamPort = (int) ( random.nextFloat() * ( MAX_STREAM_PORT - MIN_STREAM_PORT ) + MIN_STREAM_PORT );

  private final Agent agent;
 
  /** creates an ice agent with the given parameters. */
  public IceAgent( final boolean controling, StunTurnAddress sta ) {
    this.agent = new Agent();
    agent.setControlling(controling);
    if( controling )
      agent.setNominationStrategy(NominationStrategy.NOMINATE_HIGHEST_PRIO);
   
    //stun and turn
    if( sta.stunAddresses != null )
      for( TransportAddress ta : sta.stunAddresses )
        agent.addCandidateHarvester(new StunCandidateHarvester(ta) );
   
    //LongTermCredential ltr = new LongTermCredential("1234", "abcd" ); //generateNonce(5), generateNonce(15));
    if( sta.turnAddresses != null )
      for( TransportAddress ta : sta.turnAddresses )
        agent.addCandidateHarvester(new TurnCandidateHarvester(ta) );
  }
  public void createStreams( Collection<String> streamnames ) throws IOException {
    for( String s : streamnames ) {
      createStream( s );
    }
  }
  /** returns the underlying agent object. */
  public Agent getAgent() {
    return agent;
  }
  /** returns the current processing state. */
  public IceProcessingState getState() {
    return agent.getState();
  }
  /** listens for changes in processing state */
  public void addAgentStateChangeListener( PropertyChangeListener pcl ) {
    agent.addStateChangeListener(pcl);
  }
  public void removeAgentStateChangeListener( PropertyChangeListener pcl ) {
    agent.removeStateChangeListener(pcl);
  }
  public List<String> getStreamNames() {
    return agent.getStreamNames();
  }
  public void freeAgent() {
    agent.free();
  }
  /** takes the remote candidates passed by the JingleIQ and incorporates that information into this ice agent. */
  public void addRemoteCandidates(JingleIQ jiq) {
    try {
      for (ContentPacketExtension contentpe : jiq.getContentList()) {
        String name = contentpe.getName();
        IceMediaStream ims = agent.getStream(name);
        if (ims != null) {
          for (IceUdpTransportPacketExtension tpe : contentpe.getChildExtensionsOfType(IceUdpTransportPacketExtension.class)) {
            System.out.println( "\t" + tpe );
            if (tpe.getPassword() != null)
              ims.setRemotePassword(tpe.getPassword());
            if (tpe.getUfrag() != null)
              ims.setRemoteUfrag(tpe.getUfrag());

            List<CandidatePacketExtension> candidates = tpe.getChildExtensionsOfType(CandidatePacketExtension.class);
            if (candidates == null || candidates.size() == 0)
              continue;
            // Sorts the remote candidates (host < reflexive <
            // relayed) in
            // order to create first host, then reflexive, the
            // relayed
            // candidates, to be able to set the relative-candidate
            // matching the rel-addr/rel-port attribute.
            Collections.sort(candidates);

            for (CandidatePacketExtension cpe : candidates) {
              if (cpe.getGeneration() != agent.getGeneration())
                continue;
              InetAddress ia;
              try {
                ia = InetAddress.getByName(cpe.getIP());
              } catch (UnknownHostException uhe) {
                continue;
              }

              TransportAddress relatedAddr = null;
              if (cpe.getRelAddr() != null && cpe.getRelPort() != -1) {
                relatedAddr = new TransportAddress(cpe.getRelAddr(), cpe.getRelPort(), Transport.parse(cpe.getProtocol().toLowerCase()));
              }

              Component component = ims.getComponent(cpe.getComponent());
              if (component != null) {
                // we should always be able to find this if there is one b/c of the sorting we did.
                RemoteCandidate relatedCandidate = relatedAddr != null ? component.findRemoteCandidate(relatedAddr) : null;
                TransportAddress ta = new TransportAddress(ia, cpe.getPort(), Transport.parse(cpe.getProtocol().toLowerCase()));
                RemoteCandidate rc = new RemoteCandidate( ta,
                    component,
                    convertType(cpe.getType()),
                    Integer.toString(cpe.getFoundation()),
                    cpe.getPriority(),
                    relatedCandidate);
                component.addRemoteCandidate(rc);
              }
            }
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(0);
    }
  }
 
  public void startConnectivityEstablishment() {
    agent.startConnectivityEstablishment();
  }
 
  /**
   * iterates through the content list and adds corresponding ICE transport packet extensions.
   *
   *
   * @param contentList the content list already containing the content descriptions generated by Jingle.
   * @throws IllegalArgumentException if the content list contains streams that are not found here.
   */
  public void addLocalCandidateToContents(List<ContentPacketExtension> contentList) throws IllegalArgumentException {
    for( ContentPacketExtension cpe : contentList ) {
      String streamName = cpe.getName();
      IceUdpTransportPacketExtension ext = getLocalCandidatePacketExtensionForStream( streamName );
      if( ext == null )
        throw new IllegalArgumentException("No Stream found for " + streamName );
      cpe.addChildExtension(ext);
    }
  }
  public IceUdpTransportPacketExtension getLocalCandidatePacketExtensionForStream( String streamName ) {
    IceUdpTransportPacketExtension transport = new IceUdpTransportPacketExtension();
    transport.setPassword( agent.getLocalPassword() );
    transport.setUfrag( agent.getLocalUfrag() );

    try {
      IceMediaStream ims = agent.getStream(streamName);
      if( ims == null )
        return null;
     
      for( Component c : ims.getComponents() ) {
        for( Candidate<?> can : c.getLocalCandidates() ) {
          CandidatePacketExtension candidate = new CandidatePacketExtension();
          candidate.setComponent(c.getComponentID());
          candidate.setFoundation(Integer.parseInt(can.getFoundation()));
          candidate.setGeneration(agent.getGeneration());
          candidate.setID(nextCandidateId());
          candidate.setNetwork(0); //FIXME: we need to identify the network card properly.
          TransportAddress ta = can.getTransportAddress();
          candidate.setIP( ta.getHostAddress() );
          candidate.setPort( ta.getPort() );
          candidate.setPriority(can.getPriority());
          candidate.setProtocol(can.getTransport().toString());
          if( can.getRelatedAddress() != null ) {
            candidate.setRelAddr(can.getRelatedAddress().getHostAddress());
            candidate.setRelPort(can.getRelatedAddress().getPort());
          }
          candidate.setType(convertType(can.getType()));
         
          transport.addCandidate(candidate);
        }
      }
    } catch( Exception e ) {
      e.printStackTrace();
      System.exit(0);
    }
    return transport;
  }
 
  private CandidateType convertType(org.ice4j.ice.CandidateType type) {
    String ts = type.toString();
    return CandidateType.valueOf(ts);
  }
  private org.ice4j.ice.CandidateType convertType(CandidateType type) {
    String ts = type.toString();
    return org.ice4j.ice.CandidateType.parse(ts);
  }

  public void createStream( String name ) throws BindException, IllegalArgumentException, IOException {
    IceMediaStream stream = agent.createMediaStream(name);
    int rtpPort = getStreamPort();
    agent.createComponent(stream, Transport.UDP, rtpPort, rtpPort, rtpPort+100);
    agent.createComponent(stream, Transport.UDP, rtpPort+1, rtpPort+1, rtpPort+101);
  }

  private static int getStreamPort() {
    if( ( streamPort & 0x01 ) == 0x01 )
      ++streamPort;
    if( streamPort >= MAX_STREAM_PORT )
      streamPort = MIN_STREAM_PORT;
    int r = streamPort;
    streamPort += 2;
    if( streamPort >= MAX_STREAM_PORT )
      streamPort = MIN_STREAM_PORT;
    return r;
  }
 
  private synchronized String nextCandidateId() {
    return String.valueOf(++candidateId);
  }
  public boolean hasCandidatesForAllStreams() {
    for( String nm : agent.getStreamNames() ) {
        if( agent.getStream(nm).getRemoteUfrag() == null )
          return false;
    }
    return true;
  }
 
//  public static String generateNonce(int length) {
//    StringBuilder s = new StringBuilder( length );
//    for( int i=0; i<length; ++i ) {
//      int r = random.nextInt( 26 + 26 + 10 );
//      char c;
//      if( r >= 26 + 26 ) {
//        c = (char) ( '0' + (r-26-26) );
//      } else if( r >= 26 ) {
//        c = (char) ( 'A' + (r-26) );
//      } else {
//        c = (char) ( 'a' + r );
//      }
//      s.append( c );
//    }
//    return s.toString();
//  }
}
TOP

Related Classes of com.xonami.javaBells.IceAgent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.