ice4j Documentation
repository·master·Indexed 19 days ago
https://github.com/jitsi/ice4jA Java-based implementation of the Interactive Connectivity Establishment (ICE) protocol. ice4j enables Offer/Answer based protocols like SIP and XMPP to traverse NATs using STUN and TURN. It includes features such as socket sharing, a Push API for reduced latency, mapping harvesters for srflx candidates (including AWS detection), and tools for candidate prioritization and connectivity checks.
What's inside ice4j
- ice4j is a Java implementation of the Interactive Connectivity Establishment (ICE) protocol. It is designed to enable Offer/Answer based protocols (such as SIP and XMPP) to traverse NATs by combining various NAT traversal utilities, including STUN and TURN. The library also provides features like socket sharing.
Configure mapping harvesters for srflx candidates
masterMapping harvesters allow an ICE Agent to obtain
srflx(server reflexive) candidates without dynamically querying a STUN server. They work by using pre-configured or dynamically discovered local/public IP address pairs.Note: Mapping harvesters preserve the original candidate's port number and should only be used when port numbers are preserved by the network.
# Pre-configured mapping harvester org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=192.168.1.5 org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=203.0.113.5 # AWS Harvester control org.ice4j.ice.harvest.DISABLE_AWS_HARVESTER=true org.ice4j.ice.harvest.FORCE_AWS_HARVESTER=false # STUN server addresses for mapping harvesters org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES=stun1.example.com:12345,stun2.example.com:23456Use the standalone Pseudo TCP project
masterThe pseudo TCP implementation is no longer part of the ice4j repository. If you require pseudo TCP functionality, you must use the dedicated project located athttps://github.com/jitsi/jitsi-pseudotcp.Enable and use the Push API in ice4j
masterThe Push API allows
ice4jto pass received payload packets directly to your application via a callback, bypassing the virtualDatagramSocketqueues. This reduces latency and CPU workload by avoiding unnecessary packet copying between threads.Setup Steps
- Enable the API: Set
AbstractUdpListener.USE_PUSH_APItotrue. This must be done before creating anySinglePortUdpHarvesterinstances. - Configure Callbacks: For every
Component, register a callback for payload packets usingsetBufferCallback(). - Send Data: Use
Component.send(byte[] data, int offset, int length)to transmit data instead of using virtual sockets.
Limitations
- The Push API is currently only supported when using
SinglePortUdpHarvester. - If your application uses regular
HostCandidates, you must continue reading packets from aDatagramSocket. However,Component.send()remains compatible with both modes.
// 1. Enable the API before harvester creation AbstractUdpListener.USE_PUSH_API = true; // 2. Configure the callback on a Component component.setBufferCallback(new PayloadCallback() { @Override public void onPayload(Component component, byte[] data, int offset, int length) { // Handle received packet } }); // 3. Send data via the component component.send(myData, 0, myData.length);- Enable the API: Set
Configure buffer allocation and padding for the Push API
masterWhen using the Push API, buffers for packets are managed via
BufferPool.getBuffer. By default, this allocates new memory on the Java heap, but you can provide a custom implementation.Buffer Ownership
- If your application does not consume the buffer, it is automatically returned to the pool via
BufferPool.returnBuffer. - If your application does consume the buffer, you are responsible for returning it to the pool.
Buffer Padding Options
You can configure specific offsets and trailing space in the buffers to optimize processing (e.g., for RTP). Use the following configuration options:
AbstractUdpListener.BYTES_TO_LEAVE_AT_START_OF_PACKETAbstractUdpListener.BYTES_TO_LEAVE_AT_END_OF_PACKET
- If your application does not consume the buffer, it is automatically returned to the pool via
How component socket merging works
masterThe
useComponentSocketconfiguration determines whether a per-component merging socket is enabled by default.- If enabled: You must use the socket instance provided by
Component.getSocket. - If disabled: You must use the socket instance from the desired
CandidatePair.
Note that this default behavior can be overridden via the
AgentAPI.- If enabled: You must use the socket instance provided by
Configure AWS mapping harvester behavior
masterIce4j can automatically detect if it is running in an AWS network and enable the AWS mapping harvester. You can override this behavior using the following properties:
org.ice4j.ice.harvest.DISABLE_AWS_HARVESTER: Set totrueto explicitly disable the AWS harvester.org.ice4j.ice.harvest.FORCE_AWS_HARVESTER: Set totrueto force the use of the AWS harvester even if AWS is not detected.
Configure UDP harvester receive buffer size
masterYou can set the receive buffer size for the single port UDP harvester (or other
AbstractUdpListenerimplementations) usingorg.ice4j.ice.harvest.AbstractUdpHarvester.SO_RCVBUF.If not specified, the system default is used (e.g.,
net.core.rmem_defaulton Linux). If you increase this value, ensure the system maximum (net.core.rmem_maxon Linux) is also increased to accommodate the setting.org.ice4j.ice.harvest.AbstractUdpHarvester.SO_RCVBUF=1048576Configure ICE Agent settings
masterThe
AgentConfigclass provides access to global configuration parameters for the ICE agent. These settings can be configured using two sets of keys: legacyorg.ice4j.*keys and the newerice4j.*keys. Many duration-based settings expect aLongvalue representing milliseconds in the configuration source.// Access the global configuration instance val config = org.ice4j.ice.AgentConfig.config // Example of accessing a property val softwareName = config.software val delay = config.terminationDelayFilter interfaces and IP addresses for candidate allocation
masterYou can restrict which network interfaces and IP addresses
ice4juses for candidate allocations using semicolon-separated lists. This is useful for controlling network exposure or ensuring only specific networks are used for ICE connectivity.# Allow only specific interfaces org.ice4j.ice.harvest.ALLOWED_INTERFACES=eth0;wlan0 # Block specific interfaces org.ice4j.ice.harvest.BLOCKED_INTERFACES=lo # Allow only specific IP addresses org.ice4j.ice.harvest.ALLOWED_ADDRESSES=192.168.1.10;10.0.0.5 # Block specific IP addresses org.ice4j.ice.harvest.BLOCKED_ADDRESSES=172.16.0.1 # Disable IPv6 binding org.ice4j.ipv6.DISABLED=trueReference: AbstractUdpListener Push API configuration keys
masterThe following configuration keys are used to control buffer behavior when the Push API is enabled in
AbstractUdpListener.AbstractUdpListener.BYTES_TO_LEAVE_AT_START_OF_PACKET AbstractUdpListener.BYTES_TO_LEAVE_AT_END_OF_PACKETMonitor connectivity check activity with isAlive()
masterThe
isAlive()method provides a debugging mechanism to check if theConnectivityCheckServerhas received any STUN request.Warning: This is strictly for debugging. A
truevalue does not mean ICE negotiation succeeded; it only indicates that the server received a STUN request, even if it was malformed or contained incorrect credentials (e.g., wrong username or ufrag).boolean isAlive()