Suggestions

close search

Add Messaging, Voice, and Authentication to your apps with Vonage Communications APIs

Visit the Vonage API Developer Portal

Configurable TURN servers

Enterprise and Priority plan partners can configure the TURN servers used by an OpenTok client.

This feature is also available as an add-on feature.

This topic includes the following sections:

Overview

You can customize TURN server usage for each client in the session in the following ways:

Adding your own TURN servers can help users connect in restrictive network environments where OpenTok TURN servers might be blocked.

If you chose to override the OpenTok TURN servers and only use your own TURN servers, you can make sure that media streams never leave your network.

You can add your own TURN servers for each client connecting to the session, using OpenTok.js (for web clients), the OpenTok iOS SDK, or the OpenTok Android SDK. The custom TURN server API was added in version 2.13.0 of these client SDKs.

OpenTok.js (v2.13.0+)

The options parameter of the OT.initSession() method includes an undocumented iceConfig property. This property includes the following properties:

Note: To have the client only use the TURN servers you specify (and not use the OpenTok TURN servers): set the includeServers property to 'custom', set the transportPolicy property to 'relay', and set the customServers property to list your TURN servers.

JavaScript Example code

const session = OT.initSession(projectId, sessionId, {
  iceConfig: {
    includeServers: 'custom',
    transportPolicy: 'relay',
    customServers: [
      { 
        urls: [
          'turn:123.124.125.126?transport=udp’',
          'turns:123.124.125.126?transport=tcp'
        ],
        username: 'webrtc@example.com',
        credential: 'foO0Bar1'
      },
      {
          urls: [
            'turns:turntls.example.com'
          ],
          username: 'webrtc@example.com',
          credential: 'foO0Bar2',
      },
    ],
  },
});

Type definition

export function initSession(
  partnerId: string,
  sessionId: string,
  options?: {
    connectionEventsSuppressed?: boolean;
    iceConfig?: {
      includeServers: 'all' | 'custom';
      transportPolicy: 'all' | 'relay';
      customServers: {
        urls: string[];
        username?: string;
        credential?: string;
      }[];
    };
  }
): Session;

OpenTok Android SDK (v2.13.0+)

The Session.Builder class includes two methods for configuring TURN server usage for the client:

In addition to the two new methods, two new enums define TURN server options:

Note: To have the client only use the TURN servers you specify (and not use the OpenTok TURN servers), call the following methods of the Session.Builder object you use to create the Session object:

See the Java comments below.

OpenTok Android SDK API additions

public static Builder {
  // ...

  /**
   * Defines settings for whether to use only your custom TURN servers or to use 
   * those servers in addition to OpenTok TURN servers. Used in the setCustomIceServers()
   * method.
   */
  public enum IncludeServers {
    /**
     * The client will only use the custom TURN servers you provide.
     */
    Custom,

    /**
     * The client will OpenTok TURN servers in addition to the custom TURN servers you provide.
     */
    All
  };

  /**
   * Defines settings for whether to use all ICE transport types (such as host, srflx, and TURN)
   * to establish media connectivity or to only use TURN. Used in the setIceRouting() method.
   */
  public enum TransportPolicy {
    /**
     * The client will use all ICE routing types (such as host, srflx, and TURN)
     * to establish media connectivity.
     */
    All,

    /**
     * The client will force connectivity through TURN always and ignore all other ICE
     * candidates.
     */
    Relay
  };

  /**
   * Defines a custom TURN server used in the setCustomIceServers method.
   */
  public static class IceServer {
    /**
     * The URL for your custom TURN server.
     */
    public String url;
    /**
     * The username for the TURN server.
     */
    public String user;
    /**
     * The credential string for the TURN server.
     */
    public String credential;
    /**
     * The constructor.
     */
    public IceServer(String url, String user, String credential) {

  };

  /**
   * Set the list of custom TURN servers to be used by the client in this session.
   */
  public void setCustomIceServers(List<IceServer> serverList, 
                                  IncludeServers config) {
    // ...
  }

  /**
   * Set the the TURN server transport policy to be used by the client in this session.
   */
  public void setIceRouting(TransportPolicy routing) {
     // ...
  }
  ...
}

Android example code

List<IceServer> serverList = new IceServer(
  'turn:123.124.125.126:3478', // TURN server URL
  'foo', // Username
  'foO0Bar1' // Credential
);
mSession = new Session.Builder(this, apiKey, sessionId)
  .setCustomIceServers(serverList, IncludeServers.Custom)
  .setIceRouting(TransportPolicy.TURN)
  .build();
mSession.setSessionListener(this);
mSession.connect(token);

OpenTok iOS SDK (v2.13.0+)

When you initialize an OTSession object, set the OTSessionSettings.iceConfig property to define custom TURN server configuration for the client. The OTSessionICEConfig class defines the OTSessionSettings.iceConfig property.

Note: To have the client only use the TURN servers you specify (and not use the OpenTok TURN servers), call the [OTSessionSettings addICEServerWithURL:] method of the OTSessionSettings object you use to create the OTSession object. Then set the following properties of the OTSessionSettings object:

OpenTok iOS SDK API additions

/**
 * Defines settings for whether to use only your custom TURN servers or to use 
 * those servers in addition to OpenTok TURN servers. Defines values for the
 * OTSessionSettings.iceConfig property.
 */
typedef NS_ENUM(int32_t, OTSessionICEIncludeServers) {
    /**
     * Uses both OpenTok TURN servers and (if any added) custom TURN servers.
     */
    OTSessionICEIncludeServersAll,

    /**
     * Use only custom TURN servers.
     */
    OTSessionICEIncludeServersCustom,
};

/**
 * Defines settings for whether to use all ICE transport types (such as host, srflx, and TURN)
 * to establish media connectivity or to only use TURN. Used in the setIceRouting() method.
 */
typedef NS_ENUM(int32_t, OTSessionICETransportPolicy) {
    /**
     * The client will use all ICE routing types (such as host, srflx, and TURN)
     * to establish media connectivity.
     */
    OTSessionICETransportAll,

    /**
     * The client will force connectivity through TURN always and ignore all other ICE
     * candidates.
     */
    OTSessionICETransportRelay,
};

/**
 * Defines the `OTSessionSettings.iceConfig` property.
 * This defines the TURN servers to be used by the client in the OpenTok session.
 */
@interface OTSessionICEConfig : NSObject

    /**
     * Defines settings for whether to use only your custom TURN servers or to use 
     * those servers in addition to OpenTok TURN servers.
     */
    @property(nonatomic, assign) enum OTSessionICEIncludeServers includeServers;

    /**
     * Whether to use all ICE transport types (such as host, srflx, and TURN)
     * to establish media connectivity or to only use TURN.
     */
    @property(nonatomic, assign) enum OTSessionICETransportPolicy transportPolicy;

    /**
     * An NSArray of TURN servers added by addICEServerWithURL:
     * Each element in the array is an NSDictionary with turn_url, username, and credential
     * as keys.
     */
    @property(readonly) NSArray * _Nullable customIceServers;

/**
 * The maximum number of custom TURN servers allowed.
 */
+ (NSInteger) maxTURNServersLimit;

/** 
 * Adds a custom ICE server to be used by the session.
 *
 * @param turn_url The URL for the custom TURN server.
 *
 * @param user The username for the TURN server.
 *
 * @param credential The credential string for the TURN server.
 *
 * @param errorPtr This is set to an NSError when there is an error calling the method,
 *        such as:
 *
 *        * The URL is not valid
 *        * The user name or credential is empty
 *        * The maximum TURN servers limit was already reached (see maxUserTurnServersLimit).
 */
- (void) addICEServerWithURL:(NSString *_Nonnull)turn_url 
                    userName:(NSString *_Nonnull)user 
                    credential:(NSString *_Nonnull)credential
                    error:(NSError **_Nonnull)errorPtr;

@end

/**
 * The OTSessionSettings property includes an `iceConfig` property for
 * configuring TURN servers to be used by this client in the OpenTok session.
 */
@interface OTSessionSettings : NSObject

@property(nonatomic, assign) BOOL connectionEventsSuppressed;
@property(nonatomic, retain) OTSessionICEConfig * _Nullable iceConfig;

@end

iOS example code

OTSessionICEConfig *myICEServerConfiguration = [[OTSessionICEConfig alloc] init];
myICEServerConfiguration.includeServers = OTSessionICEIncludeServersCustom;
myICEServerConfiguration.transportPolicy = OTSessionICETransportForceTurn

NSError *error = nil;
[myICEServerConfiguration addICEServerWithURL:@"turn:123.124.125.126:3478"
                                     userName:@"fooUserName"
                                   credential:@"foO0Bar1"
                                        error:&error];

OTSessionSettings *settings = [[OTSessionSettings alloc] init];
settings.iceConfig = myICEServerConfiguration;

_session = [[OTSession alloc] initWithApiKey:kApiKey
                                   sessionId:kSessionId
                                    delegate:self
                                    settings:settings];

Known issue

If you set a client to always use TURN servers in a relayed session, it will not be able to subscribe to its own streams (streams it publishes).

FAQs

Does the configurable TURN API address the issue for HTTP traffic?

No. Configurable TURN allays customers’ concerns around connecting to trusted end-points for media traffic only.

For HTTP traffic, customers will have to do one of the following:

How is the media path being selected between the available TURN targets. Does it take into account the round-trip latency, or is it influenced by the order in which we list the targets, or is it random?

Order of TURN servers is not guaranteed based on the list provided. Instead, when the media starts flowing, WebRTC selects which candidate/server has the best connectivity and who successfully negotiated first. It looks for connection writable state, ICE (Interactive Connectivity Establishment) negotiation state, and RTT to decide the best connection.

If the TURN server URL maps to multiple IP addresses, how is the specific TURN server selected for the session? Is this random?

WebRTC selects the candidate/server with the best connectivity and who successfully negotiated first. It looks for connection writable state, ICE (Interactive Connectivity Establishment) negotiation state and RTT to decide the best connection.

If both TCP and UDP TURN servers are provided and are reachable, is it possible to prioritize UDP targets and only fall back to TCP if required?

There is no way to prefer UDP over TCP and use TCP only when UDP fails. WebRTC selects the TURN server with the best connectivity and this could be over UDP or TCP. The order of elements in the URLs is a suggestion that determines the order of connectivity checks, but the actual TURN server is based on the "best" connection, which is a function of connection writable state, ICE negotiation state, and RTT to decide the best connection.

Can a single client use different media paths for different streams?

Yes, this is expected behavior as WebRTC treats each individual media stream separately.

How much control does the Configurable TURN API have in the media path selection?

Media path selection is handled by ICE (Interactive Connectivity Establishment) inside WebRTC and we have no way to modify this behavior. The Configurable TURN API only helps modify the candidate list provided by the client to WebRTC and does not influence the selection process.

Is direct connection to OpenTok Media Server over UDP always preferred?

Yes, direct connection to OpenTok Media Server is always preferred. It fails over to using TURN if connection to the OpenTok Media Server is unsuccessful or if the "Force TURN" option is used in the Configurable TURN API.

If DNS name of the custom TURN server is used in the API, can the DNS name map to multiple IP addresses?

No. If the DNS name maps to multiple IP addresses WebRTC code picks only the first resolved IP address. If the intention is to add all the IP addresses corresponding to the DNS name to the ICE candidate list, then: