How we can implement WebSockets connections? - iot-devkit

I would like to know if there is way into the lib to implement WebSocket connections on this device.
I am interested to use it in client mode.

The WebSocket client library for IoT DevKit will be coming soon (in next release).
We've already filed a GitHub issue to track this new feature. BTW, the WebSocket client we will release ONLY support unsecure WebSocket connection (not SSL), and the secure version(wss) will be coming in future.

Please install the latest version(1.3.3) and it contains the library and sample code on how to use Web Socket client. Currently, SSL web socket is not supported.
Some function we provided:
Constructor: WebSocketClient(char * url)
Connect: bool connect()
Send: int send(const char * data, long size, WS_Message_Type messageType = WS_Message_Text, bool isFinal = true);
Receive: WebSocketReceiveResult* receive(char * msgBuffer, int size)
Close: bool close()
This link provides the detailed guide and sample on how to use WebSocket client for IoT DevKit. https://microsoft.github.io/azure-iot-developer-kit/docs/apis/websocket-client/

Related

How to connect X.509 authenticated downstream device using azure python sdk version 2 to azure edge enabled gateway

With the now deprecated azure-iot-python-skd version 1 it was possible to connect a downstream device using X.509 authentication to a transparent iotedge enabled gateway by setting the connection string like this:
HostName=<edge device hostname>;DeviceId=<device_id>;x509=true
And then set the certificates by using set_option("TrustedCerts" ...), set_option("x509certificate", ...) and set_option("x509privatekey", ...)
How can this be done with the new version 2 sdk?
I could not figure out how to do it using create_from_x509_certificate(...) or create_from_connection_string(...).
please try the following where you pass in your root_ca_cert as a string:
Create instance of the device client using the connection string:
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string=YOUR CONNECTION STRING,server_verification_cert=YOUR ROOT CA AS STRING)
await device_client.connect()
create_from_connection_string will not work in this case. You need to use create_from_x509_certificate as below:-
self.device_client = IoTHubDeviceClient.create_from_x509_certificate(
x509=x509,
hostname=hostname,
device_id=device_id,
server_verification_cert=root_ca_cert,
gateway_hostname=gatewayHostname
)
Refer this ticket which is the bug fix done by MS team

Spring boot 1.3.1 with Tyrus websocket causes Authentication Exception

We recently migrated to Spring boot 1.3.1 from the traditional spring project.
Our existing clients use Tyrus 1.12 as a websocket client.
After the upgrade, we found that the clients no longer connect and throws AuthenticationException. Strangely, they are able to connect for the first time since server restart and soon after throws AuthenticationException.
Digging a bit more, I found that Tyrus receives a 401 initially and passes on credentials subsequently. The server logs indicate the same behaviour, by first assigning ROLE_ANONYMOUS and then the correct role, ROLE_GUEST there after.
It seems like after the negotiation, the server closes connection and disconnects.
I observed the same behaviour when using spring stomp websocket client with Tyrus.
ClientManager container = ClientManager.createClient();
container.getProperties().put("org.glassfish.tyrus.client.sharedContainer", true);
container.getProperties().put(ClientProperties.CREDENTIALS, new Credentials("guest", "guest"));
StandardWebSocketClient webSocketClient = new StandardWebSocketClient(container);
final CountDownLatch messageLatch = new CountDownLatch(10);
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
This same server setup works fine when the credentials are sent in the header.
stompClient.connect(url, getHandshakeHeaders("guest", "guest"), handler);
And this will NOT work since the credentials are not in the header
ListenableFuture<StompSession>session = stompClient.connect(url, handler, "localhost", "8080");
I am not understanding why it is working one way and not the other.
After upgrading to spring-boot, our software is no longer backwards compatible and will have to ask all our external clients to inject the authorization in the header before receiving a 401.
Can someone please help?
My earlier post with stacktrace

SignalR cannot connect to Azure Redis on SSL

I am currently hosting my redis cache server on Azure, and have signalR relying on it as the backbone using the following...
GlobalHost.DependencyResolver.UseRedis("Server",port,"password","eventKey");
This works find on port 6379 (non-SSL) but my chat app breaks when I try to connect to the SSL port (6380) of my Azure Redis server, and the hub is never started. What could be the cause of this issue? Or am I doing something wrong?
This is the error that appears on /signalr/connect in my browser
net::ERR_CONNECTION_RESET
You can try this:
GlobalHost.DependencyResolver.UseRedis(new RedisScaleoutConfiguration(connectionString, "YourServer"));
And connection string something like:
connectionString="yourNameHere.cache.windows.net,ssl=true,password=YourPasswordKey"
Make sure you are using SignalR built with StackExchange.Redis (latest is gratest ;)
I upgraded the signalr core library to version 2.2.3.0 and used the below syntax, works like a charm.
var redisServer = ConfigurationManager.AppSettings[Constants.RedisServer].ToString();
var redisServerPassword = ConfigurationManager.AppSettings[Constants.RedisServerPassword].ToString();
var connectionString = $"{redisServer},password={redisServerPassword},ssl=True,abortConnect=False";
GlobalHost.DependencyResolver.UseRedis(new RedisScaleoutConfiguration(connectionString, "APIIdentifierString"));
In case anyone else hits the issue, it seems that the default connection string provided by the Azure portal contains abortConnect=False.
Once I've removed that part, things started working for me.

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

WebRTC setup and related queries

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.