WebRTC setup and related queries - webrtc

I am trying to setup a peer to peer connection for WebRTC application. I have read the forums and discussion groups which lead me to the point that STUN/TURN servers are required for the same. Here are the details:
I downloaded the open source implementation of the STUN/TURN server from https://code.google.com/p/rfc5766-turn-server/
Installed the server on my local Mac OS X machine and turned on the server on localhost:3478
When I tested the server using the client scripts, I was able to get back the remote address from the server.
However, when I try to hit the server from my JavaScript code while creating a peer to peer connection, it is not hitting the server itself.
Below is the code which I am using :
function createPeerConnection() {
var pc_config = {'iceServers': [{'url':'turn:127.0.0.1:3478', 'credential':'Apple123'}]};
try {
// Create an RTCPeerConnection via the polyfill (adapter.js).
pc = new webkitRTCPeerConnection(pc_config);
pc.onicecandidate = gotLocalCandidate;
trace("Created RTCPeerConnnection with config:\n" + " \"" +JSON.stringify(pc_config) + "\".");
} catch (e) {
trace("Failed to create PeerConnection, exception: " + e.message);
alert("Cannot create RTCPeerConnection object; WebRTC is not supported by this browser.");
return;
}
pc.onconnecting = onSessionConnecting;
pc.onopen = onSessionOpened;
pc.onaddstream = onRemoteStreamAdded;
pc.onremovestream = onRemoteStreamRemoved;
}
Appreciate any guidance in this matter as I am completely stuck at this point.
One more question: How to setup a peer to peer connection for WebRTC application where both peer A and B are present on an internal network? Is STUN/TURN servers required then?

First, TURN servers are something that are used only if failing to setup an p2p connection directly. About 86% of all calls can be made without relaying via a TURN server (according to this slide, which I by the way recomend to get a better understanding of TURN (from slide 44)).
TURN server should be outside your network since the purpose of it is to relay the stream when not possible to do so in other way.
I would recomend you to start with the case where both A and B are on the same network. Then you do not need to worry about using STUN/TURN. It's enough complicated as it is.

Related

WEBRTC, not working between different nets

I'm developing a simple app that uses webrtc for transmitting real-time video in one direction (one sender and one receiver). It uses socket.io and node.js for the signalling.
At this moment, it's albe to transmit real-time video when the sender and receiver are in the same net (the server is already online), but if I use mobile net or if the peers are connected in different wifis it doesn´t work.
Actually, I make a test using public library's wifi and my home wifi and when the sender was in the public wifi it worked.
The message I get in firefox when it fails is :
ICE failed, see about:webrtc for more details
As I've read, webrtc uses STUN/TURN servers to solve problems with net's NATS. I have introduced urls from a STUN and a TURN server but it seems it had no effect.
This is the way I'm 'using' the STUN/TURN servers:
var configuration = { iceServers: [
{
urls: "turn:numb.viagenie.ca",
username: "xxxxxxxx#hotmail.com",
credential: "********"
},
{
urls: "stun:stun.callwithus.com"
}
]};
var pc = new RTCPeerConnection(configuration);
For both sides the same and it seems the servers are up.
So, my final question is, I need to do something else to make sure webrtc is using STUN/Turn servers when it's needed?
Or, do you know any other possible cause for this behaviour?
Everything you know can help a lot, because i couldn't find how to use those servers.
if you need more information, please ask for it.
T
Yes, you need to listen to pc.onicecandidate and send each candidate over your signaling channel to the other side, where you call pc.addIceCandidate with it like this, if using adapter.js:
pc.addIceCandidate(candidate).catch(e => console.log(e))
or like this if not (older syntax):
pc.addIceCandidate(new RTCIceCandidate(candidate)).catch(e => console.log(e))
You can also dump the ICE candidates to see if your settings work (srflx = stun, relay = turn):
var PC = window.RTCPeerConnection || window.webkitRTCPeerConnection;
var server = { urls: "stun:stun.l.google.com:19302" };
var pc = new PC({ iceServers: [server] });
pc.onicecandidate = e => e.candidate && console.log(e.candidate.candidate);
pc.createDataChannel("dummy");
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(e => console.log(e));
You can modify that snippet to include your turn server.
console logs of failed comunication
That's an example of what I get in the console. It seems srflx and relay are used, but at some point I get a null candidate, the error on screenshot is because of i'm trying to log a 'candidate' property of a null object.
Finally, the problem was solved.
It seems that Turn server wasn't working fine. I made a trial account on xyrsis and changed the stun and turn servers and it was solved.
Thank you all.

Dart integration test with VM server and dartium browser

I'm making a library that implements both server and client parts that interacts between them via websockets:
Server use example (ran in CLI):
Server srv = await new Server("localhost:1234");
srv.onNewClientConnected.listen(print("client connected"));
Client use example (ran in browser):
Client cli = await new Cliente("localhost:1234");
cli.sendCommand(...);
(Just by creating the instances, the client should be connected and the server noticed about that connection.)
I'd like to know what would be the best way to test their interactions? Could I check both objects internals with that method?
I would like something like this:
test(".echo should receive same input from server", (){
cli.echo("message");
expect(srv.lastMessageReceived, equals("echo: message"));
expect(cli.lastResponseReceived, equals("echo: message"));
expect(srv.amountMessagesReceived, equals(1));
});
If I understand correctly, I'm guessing you are trying to encapsulate https://www.dartlang.org/dart-vm/dart-by-example#websockets into helpers so that you have only instances when connected. However both operations (server side binding/listening/upgrade, client side connection) is asynchronous so you will never reach the state you want by just creating the instances (or you will need an additional asynchronous methods to be notified). I would suggest creating asynchronous helpers.
Assuming you accept only one client in your server
Server server = await Server.accept("localhost:1234");
Client side:
Client client = await Client.connect("localhost:1234");
By doing so, you will have only server and client instances when connected
I like the https://pub.dartlang.org/packages/web_socket_channel package which provide a good abstraction and allow me to test my web socket client logic that will run in the browser in a simple io test.
As for testing recommendations, I personally start my web socket server in setUpAll and create my client in setUp and user a similar logic that you propose (don't forget the await though as you will need to wait for the echo response). Again the web_socket_channel package has some good testing example that you can look at (https://github.com/dart-lang/web_socket_channel/tree/master/test)

Simulate Access disable feature in Worklight , when worklight server itself is down.

I am trying show end users maintainence window such as "we are down please try later" and disable the application but my problem is what if my worklight server itself is down and not reachable and i cannot use the feature provided by worklight console,
Is there a way i make my app talk to a different server which returns back the below json data when a app is disabled , can i simulate this behaviour is this possible.
json recieved on access disabled in worklight :-
/*-secure-
{"WL-Authentication-Failure":{"wl_remoteDisableRealm":{"message”:”We are down, Please try again soon","downloadLink":null,"messageType":"BLOCK"}}}*/
I have some conceptual problems with this question.
Typically a production environment (simplified) would not consist of a single server serving your end-users... meaning, there would be a cluster of nodes, each node being a Worklight Server, and this cluster would be behind a load balancer that would direct the incoming requests. And so in a situation where a node is down for maintenance like in your scenario there would still be more servers able to serve - there would be no down time.
And thus at this point your suggestion to simulate a Remote Disable by sending it from another(?) Worklight Server seems not so much the correct path to take (it may even be simply wrong). Have you had this second Worklight Server, why wouldn't it just serve the apps business like usual? See again my first paragraph about clustering.
Now lets assume there is still a downtime, that affects all servers. The application's client logic should be able to handle failed connections to the Worklight Server. In such a case you should handle this in the WL.Client.connect()'s onFailure callback function to display a WL.SimpleDialog that looks just like a Remote Disable's dialog... or perhaps via the initOption.js's onConnectionFailure callback.
Bottom line: you cannot simulate the JSON that is sent back for the wl_RemoteDisable realm; it is part of a larger security mechanism.
Additionally though, perhaps a way to better handle maintenance mode on your server is to have the HTTP server return a specific HTTP status code, check for this code and display a proper message based on the returned HTTP status code.
To check for this code in a simple example:
Note: the getStatus method is available starting MobileFirst Platform Foundation 7.0 (formerly "Worklight").
function wlCommonInit(){
WL.Client.connect({onSuccess:success, onFailure:failure});
}
function success(response) {
// ...
}
function failure(response) {
if (response.getStatus() == "503") {
// site is down for maintenance - display a proper message.
} else if ...
}

Continuously sync changes from web server

I'm searching for a way to get my Files synchronized (task) from a web server (Ubuntu 14) to a local server (Windows Server). The web server creates small files, which the local Server needs. The web server is in a DMZ, accessible through SSH. Only the local server is able to access folders on web server. It tried using Programs like WinSCP, but I'm not able to set a "get"-Job.
Is there a way to do this with SSH on Windows server without login every few seconds? Or is there a better solution? In the Future Web-Services are possible, but at the moment I need a quick solution.
Either you need to schedule a regular frequent job, that connects and downloads changes.
Or you need to have continuously running process, that keeps the connection opened and regularly watches for changes.
There's hardly a better solution (that's still quick and easy to implement).
Example of continuous process implemented using WinSCP .NET assembly:
// Setup session options
SessionOptions sessionOptions = new SessionOptions {
Protocol = Protocol.Sftp,
HostName = "example.com",
UserName = "user",
Password = "mypassword",
SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxx...="
};
using (Session session = new Session())
{
// Connect
session.Open(sessionOptions);
while (true)
{
// Download changes
session.SynchronizeDirectories(
SynchronizationMode.Local, localPath, remotePath, false).Check();
// Wait 10 seconds
Thread.Sleep(10000);
}
}
You will need to add a better error handling and reconnect, if connection breaks.
If you do not want to implement this as (C#) application, you can use PowerShell script. For a complete solution, see
Keep local directory up to date (download changed files from remote SFTP/FTP server).

WCF callback (client not on DNS) There was no endpoint listening at

I was doing implementation of in-app chat, so I found very useful article made by
By Ger Hayden (A Beginner's Guide to Duplex WCF).
Following article, my chat started to work very quickly (server and client on same PC)
Everything went fine until I deployed chat server on test machine.
When enabling WCF system.diagnostics on server side I found that:
Client is establishing connection with server
Server is trying to execute callback but fails with exception:
There was no endpoint
listening at
http://a2200492.m022/Temporary_Listen_Addresses/00bc713c-e37c-4f98-adb6-4dff5b523126/25fb8f22-53dd-408e-8189-e1d3850344e6
that could accept the message. This is often caused by an incorrect
address or SOAP action. See InnerException, if present, for more
details.
The remote name could not be resolved: 'a2200492.m022'
Problem is that my PC (client) aka a2200492.m022 is not in DNS, so server cannot make resolution Computer Name -> IP.
I was looking for solution to configure WCF to use IP rather than computer name, but I did not found such configuration parameter. (If there is one please let me know)
Next I found from people having similar problems, idea to add PC to DNS, or add to server hosts file. But I wanted general solution.
So, solution (or better workaround) that worked is (from code behind put current client IP):
Client code:
//In method for connecting...
System.ServiceModel.Channels.Binding b = new WSDualHttpBinding("WSDualHttpBinding_Server");
string clientID = Guid.NewGuid().ToString().Replace("-", ""); //if 2 app on same IP
/////////////////////////////////////////
//here is line that solved my problem, let server make callback to my ip
(b as WSDualHttpBinding).ClientBaseAddress = new Uri(#"http://" + MyIp() + "/" + clientID);**
/////////////////////////////////////////
(b as WSDualHttpBinding).ReliableSession = new ReliableSession(){Ordered=true};
(b as WSDualHttpBinding).Security = new WSDualHttpSecurity() { Mode = WSDualHttpSecurityMode.None };
(b as WSDualHttpBinding).HostNameComparisonMode = HostNameComparisonMode.WeakWildcard;
//ServerIP
EndpointAddress serverIp = new EndpointAddress(System.Configuration.ConfigurationManager.AppSettings["ChatServer"].ToString());
//Instantiate service reference
chatServer = new ChatServerRef.ServerClient(new InstanceContext(this), b, serverIp);
//Next step is call method JoinTheConversation on chatServer
Solved by changing ClientBaseAddress at runtime