IceLink 3 Advanced Guides

XirSys Integration

IceLink comes with its own fully-featured STUN and TURN server but it requires some infrastructure to setup and run it. This is not usually a problem, as most applications already have a server component. However, there are advantages to letting someone else manage your infrastructure and global server distribution. To facilitate this, IceLink provides a wrapper around XirSys, a WebRTC platform that provides cloud-based STUN and TURN servers. Their service is self-scaling, redundant and supported by expert customer service staff. It's a great option if you don't want to manage your own TURN service.

Visit their site at xirsys.com to sign up for an account. They offer a free tier, which you can use to try out their service and get your application up running.

Retrieving ICE Servers

Before you can use the XirSys integration, you must include the XirSys extension. This is bundled with all IceLink 3 distributions, beginning with 3.0.12. For .NET, use the FM.IceLink.XirSys.dll library. For other platforms use the similarly named library file. Once the extension is loaded, the next step is to retrieve your ICE servers from XirSys. Normally, you would create an array of FM.IceLink.IceServer instances manually, as shown in the following code snippet, taken from our Getting Started guide.

var connection = new FM.IceLink.Connection();
var iceServers = new[] {
    new FM.IceLink.IceServer("stun:my.stun.server"),
    new FM.IceLink.IceServer("turn:my.turn.server", "username", "password")
};

connection.IceServers = iceServers;
fm.icelink.Connection connection = new fm.icelink.Connection();
fm.icelink.IceServer[] iceServers = new fm.icelink.IceServer[] {
    new fm.icelink.IceServer("stun:my.stun.server"),
    new fm.icelink.IceServer("turn:my.turn.server, "username", "password")
};

connection.setIceServers(iceServers);
FMIceLinkConnection* connection = [FMIceLinkConnection connection];
NSMutableArray* iceServers = [NSMutableArray arrayWithObjects:
    [FMIceLinkIceServer iceServerWithUrl:@"stun:my.stun.server"],
    [FMIceLinkIceServer iceServerWithUrl:@"turn:my.turn.server" username:@"username" password:@"password"],
    nil    
];

[connection setIceServers: iceServers];
var connection = FMIceLinkConnection()
var iceServers = [
    FMIceLinkIceServer(url: "stun:my.stun.server"),
    FMIceLinkIceServer(url: "turn:my.turn.server")
]

connection.setIceServers(iceServers)
var connection = new fm.icelink.Connection();
var iceServers = [
    new fm.icelink.IceServer("stun:my.stun.server"),
    new fm.icelink.IceServer("turn:my.turn.server", "username", "password")
];

connection.setIceServers(iceServers);

When using XirSys as your STUN/TURN provider, the implementation is slightly different. First, create a XirSys client. This will be an instance of either FM.IceLink.XirSys.V2.Client or FM.IceLink.XirSys.V3.Client, depending on which version of the XirSys API you are using. You must specify your API access details when creating this client. These are available from the XirSys dashboard.

After you create the client instance, invoke the GetIceServers method. This makes a call to the XirSys API that requests your unique set of ICE servers. Because this is an asynchronous operation, the method returns a promise. The promise instance wraps a set of FM.IceLink.IceServer instances, which you should assign to your Connection instance. The easiest way to handle the promise is to invoke its WaitForResult method, which will wait until the request completes. The following code samples demonstrate this.

var xirsys = new FM.IceLink.XirSys.V2.Client("ident", "secret", "domain", "application", "room");
// or
var xirsys = new FM.IceLink.XirSys.V3.Client("ident", "secret", "channel");

var connection = new FM.IceLink.Connection();
var iceServers = xirsys.GetIceServers().WaitForResult();
connection.IceServers = iceServers;
fm.icelink.xirsys.v2.Client xirsys = new fm.icelink.xirsys.Client("ident", "secret", "domain", "application", "room");
// or
fm.icelink.xirsys.v3.Client xirsys = new fm.icelink.xirsys.Client("ident", "secret", "channel");

fm.icelink.Connection connection = new fm.icelink.Connection();
fm.icelink.IceServer[] iceServers = xirsys.getIceServers().waitForResult();
connection.setIceServers(iceServers);
FMIceLinkXirSysV2Client* xirsys = [FMIceLinkXirSysV2Client clientWithIdent:@"ident" secret:@"secret" domain:@"domain" application:@"application" room:@"room"];
// or
FMIceLinkXirSysV3Client* xirsys = [FMIceLinkXirSysV3Client clientWithIdent:@"ident" secret:@"secret" channel:@"channel"];

FMIceLinkConnection* connection = [FMIceLinkConnection connection];
NSMutableArray* iceServers = [[xirsys getIceServers] waitForResult];
[connection setIceServers: iceServers];
var xirsys = FMIceLinkXirSysV2Client(ident: "ident", secret: "secret", domain: "domain", application: "application", room: "room")
// or
var xirsys = FMIceLinkXirSysV3Client(ident: "ident", secret: "secret", channel: "channel")

var connection = FMIceLinkConnection()
var iceServers = xirsys.getIceServers().waitForResult()
connection.setIceServers(iceServers)
var xirsys = new fm.icelink.xirsys.v2.Client("ident", "secret", "domain", "application", "room");
// or
var xirsys = new fm.icelink.xirsys.v3.Client("ident", "secret", "channel");

var connection = new fm.icelink.Connection();
var iceServers = xirsys.getIceServers().waitForResult();
connection.setIceServers(iceServers);s

If you do not want to block the thread, you can also specify a resolve action for the promise. You should not do this with the WebSync extension. The extension assumes that when an FM.IceLink.Connection is returned from the OnRemoteClient instance, that the FM.IceLink.IceServer instances are already assigned. If you return the Connection instance before the promise resolves, this will cause an exception in the extension. With that said, in other cases, you can use the following pattern.

var xirsys = new FM.IceLink.XirSys.V2.Client("ident", "secret", "domain", "application", "room");
// or
var xirsys = new FM.IceLink.XirSys.V3.Client("ident", "secret", "channel");

var connection = new FM.IceLink.Connection();
xirsys.GetIceServers().Then((FM.IceLink.IceServer[] iceServers) => {
    connection.IceServes = iceServers;
});
fm.icelink.xirsys.v2.Client xirsys = new fm.icelink.xirsys.Client("ident", "secret", "domain", "application", "room");
// or
fm.icelink.xirsys.v3.Client xirsys = new fm.icelink.xirsys.Client("ident", "secret", "channel");

final fm.icelink.Connection connection = new fm.icelinkConnection();
xirsys.getIceServers.then((fm.icelink.IceServer[] iceServers) -> {
    connection.setIceServers(iceServers);
});
FMIceLinkXirSysV2Client* xirsys = [FMIceLinkXirSysV2Client clientWithIdent:@"ident" secret:@"secret" domain:@"domain" application:@"application" room:@"room"];
// or
FMIceLinkXirSysV3Client* xirsys = [FMIceLinkXirSysV3Client clientWithIdent:@"ident" secret:@"secret" channel:@"channel"];

FMIceLinkConnection* connection = [FMIceLinkConnection connection];
[[xirsys getIceServers] thenWithResolveActionBlock: ^(NSMutableArray* iceServers) {
    [connection setIceServers: iceServers];
];
var xirsys = FMIceLinkXirSysV2Client(ident: "ident", secret: "secret", domain: "domain", application: "application", room: "room")
// or
var xirsys = FMIceLinkXirSysV3Client(ident: "ident", secret: "secret", channel: "channel")

var connection = FMIceLinkConnection()
xirsys.getIceServers().then(resolveActionBlock: { (iceServers:[FMIceLinkIceServer]) in
    connection.setIceServers(iceServers)
})
var xirsys = new fm.icelink.xirsys.v2.Client("ident", "secret", "domain", "application", "room");
// or
var xirsys = new fm.icelink.xirsys.v3.Client("ident", "secret", "channel");

var connection = new fm.icelink.Connection();
xirsys.getIceServers.then(function(iceServers) {
    connection.setIceServres(iceServers);
});

Wrapping Up

You now know how to use the IceLink API to connect to XirSys, and retrieve a list of STUN and TURN servers to use for your application. You can, of course, still use the TURN server included in the IceLink SDK. You can review that in the Starting the TURN Server section. Whichever option you choose will depend on the specific needs of your application. If you're not sure, once again, you can try out XirSys's service for free by visiting xirsys.com.