Using external TURN

We have OpenVidu enterprise on-premises installation with external TURN (coturn) running on a different VM in the same network segment.

This external TURN has been configured according to OpenVidu’s instructions and tested to work correctly with OpenVidu’s example call app, i.e. we have verified that with strict client side firewalls it solves the issue and allows video/audio to flow.

However, a partner has developed an app on top of OpenVidu APIs and for some reason our external TURN seems not be used in this case. Logs show that it tries to use OpenVidu’s built-in TURN, which is not active, since we have set up external TURN and want to use that.

My questions:

  1. Are there any additional steps that apps need to do to utilise an external (coturn) TURN server, or should they be able to use it automatically, similar to what OpenVidu’s example call app seems to do?

  2. We are aware that instructions have a short code example for apps, but seems that it is intended for cases where a commercial 3rd party TURN service is used, and not needed for simple coturn installations. Is this correct?

  3. Any tips from which direction to look for a missing or incorrect configuration?

Hello @trantako , thanks for reaching out via forum :slight_smile:

If I understand you correctly, you want all of your OpenVidu users and apps developed on top of OpenVidu to use the same external TURN, right?

To achieve this, you must configure the OPENVIDU_WEBRTC_ICE_SERVERS parameter in the OpenVidu configuration file. If this variable is present in the configuration, the default deployment of Coturn should not be used under any circumstances.

If you want to configure an external Coturn via API, you can do so, but your Coturn must be deployed with the static-auth-secret parameter or have fixed username and password. If you have the static-auth-secret parameter configured in Coturn, the API operation via openvidu-node-client would look like this:

let session = await this.openvidu.createSession({});
let connection = await session.createConnection({
    customIceServers: [
        {
            url: "turn:<your_turn_endpoint>:443",
            staticAuthSecret: "<your_static_auth>"
        }
    ]
});

The order of precedence for choosing a TURN is as follows:

  1. Turn configured using setAdvancedConfiguration in openvidu-browser: OpenViduAdvancedConfiguration | OpenVidu Browser - v2.27.0
  2. Turn configured by connection via API: Allow users behind firewalls - OpenVidu Docs
  3. Turn configured in the OPENVIDU_WEBRTC_ICE_SERVERS parameter.
  4. Default deployed Coturn.

If 1 is not available, 2 is used, followed by 3, and so on.

To summarize, use OPENVIDU_WEBRTC_ICE_SERVERS as a global parameter to configure an external TURN. If you believe the documentation is not very clear, please let us know.

Maybe this clarifies how Turn configuration works. Do you think this is not clear in the docs? I have no problem to change it to make it clear. Turn is one of the things of WebRTC that is hard to “abstract” for people searching for easy to use solutions, so any feedback with the documentation is welcome :slight_smile:

Regards.

Does this

affect only node-client or is this same default behaviour in use in openvidu-java-client and openvidu-browser? Or do these require configuring custom iceservers and can not use OPENVIDU_WEBRTC_ICE_SERVERS parameter?

To specify issue, OPENVIDU_WEBRTC_ICE_SERVERS is used when using node-client, but not when using java-client and openvidu server is defaulting to phase 4 and returning default COTURN.

1 Like

Hello @cruizba ,

We have OpenVidu (versions 2.24 and 2.25) configured with OPENVIDU_WEBRTC_ICE_SERVERS parameter.

We have tested both versions using openvidu-hello-world tutorial with Java and Node.js server application samples.

Executing openvidu-hello-world tutorial with Java sample (openvidu-tutorials/openvidu-basic-java) results in the default deployed Coturn returned as turn which is wrong and does not work.

Executing openvidu-hello-world tutorial with Node.js sample (openvidu-tutorials/openvidu-basic-node) results in the turn configured by OPENVIDU_WEBRTC_ICE_SERVERS to be returned which is correct and does work.

As @jkar was asking, should the Java sample return the correct turn configuration when OPENVIDU_WEBRTC_ICE_SERVERS parameter is set?

Hello @jkar and @emal. Are you both from the same project?

Yes, the behaviour is the same for openvidu-java-client, it uses the API Rest under the hood and should work in the same way.

@jkar are you saying that openvidu-java-client is not behaving correctly? I will check on my side

Regards

@cruizba We are all in the same project.

And yes, it appears that Java sample is not working correctly and returns wrong TURN configuration.

Please check and let us know if you can repeat this result.

@trantako, Yes, there is a bug in openvidu-java-client which is ignoring the parameter OPENVIDU_WEBRTC_ICE_SERVERS in all versions. Thank you for your reporting.

We will fix this for the next release 2.28.0. A possible workaround while you are using the previous versions until 2.28.0 is to configure the turn server in your backend, and pass it to your connection object like this:

	/**
	 * @param sessionId The Session in which to create the Connection
	 * @param params    The Connection properties
	 * @return The Token associated to the Connection
	 */
	@PostMapping("/api/sessions/{sessionId}/connections")
	public ResponseEntity<String> createConnection(@PathVariable("sessionId") String sessionId,
			@RequestBody(required = false) Map<String, Object> params)
			throws OpenViduJavaClientException, OpenViduHttpException {
		Session session = openvidu.getActiveSession(sessionId);
		if (session == null) {
			return new ResponseEntity<>(HttpStatus.NOT_FOUND);
		}

		/*
		 * Configure the Ice server from the java backend
		 * while creating the connection
		 */
		IceServerProperties iceServerProperties = new IceServerProperties.Builder()
			.url("turns:<YOUR_TOURN_DOMAIN>:<YOUR_TOURN_PORT>")
			.staticAuthSecret("<YOUR_SHARED_SECRET>")
			.build();
		ConnectionProperties.Builder propertiesBuilder = ConnectionProperties.fromJson(params);
		propertiesBuilder.addCustomIceServer(iceServerProperties);
		ConnectionProperties properties = propertiesBuilder.build();
		Connection connection = session.createConnection(properties);

		return new ResponseEntity<>(connection.getToken(), HttpStatus.OK);
	}

Where YOUR_TOURN_DOMAIN, YOUR_TOURN_PORT, YOUR_SHARED_SECRET should be configurable parameters in your backend.

Would it be possible in your side to use this workaround until version 2.28.0?

Regards.

@cruizba Thank you for confirming the bug.

We are able to continue with a workaround, and will revisit the issue when the update is released and we are ready to make the update to it.

Thank you.

1 Like