Flutter cannot connect to AWS with Web Socket Channel - amazon-web-services

I'm writing a program that required connecting to a Web Server using the Web Socket Channel package. I am following the guide https://flutter.dev/docs/cookbook/networking/web-sockets to connect to an AWS Server. The link is something like this:
wss://xxxxxxx.execute-api.ap-southeast-1.amazonaws.com/dev/
Using the package I was able to connect and get the connectionState.waiting, but I cannot seem to listen to any data from the server nor send data to the server. For the data send, the format is below:
Map message = {
"action": 'subscribe',
"channel": 'contentTest',
};
channel.sink.add(jsonEncode(message));
The rest of my code is similar to the guide, however the server does not seem to receive any data and neither can my client. Can anyone share a working example for above problem? Thank you in advance.

I have a working example to share, you can see how the connection is done and the message is sent, this example is using the WebSocket class in dart:io. When I was coding this I had some issues with Web Socket Channel, can't remember why, so I opted for Dart WebSocket class.
Future<WatchResponse> WatchCollection(
CollectionRequest collectionRequest, String token) async {
try {
WebSocket ws = await WebSocket.connect(
"ws://${this.authority}/gapi/collection/watch?token=$token");
if (ws.readyState == WebSocket.open) {
ws.add(jsonEncode(collectionRequest.toMap()));
return WatchResponse(ok: true, streamSubscription: ws.listen(null));
}
} on WebSocketException catch (err) {
return WatchResponse(ok: false, webSocketExecption: err);
}
return WatchResponse(ok: false, webSocketExecption: null);
}

Related

Cesanta Mongoose - problems when connecting to localhost

I'm having issues building an HTTP server using the Cesanta Mongoose web server library. The issue that I'm having occurs when I have an HTTP server built to listen on port 8080, and a client sending an HTTP request to localhost:8080. The problem is that the server processes the request fine and sends back a response, but the client only processes and prints the response after I kill the server process. Basically Mongoose works where you create connections which take an event handler function, ev_handler(). This event handler function is called whenever an
"event" occurs, such as the receiving of a request or a reply. On the server side, the event handler function is called fine when it receives a request from the client on 8080. However, the client-side event handler function is not called when the response sends the reply, but is called only after the server process is killed. I suspected that this may have something to do with the fact that the connection is on localhost, and I was right - this issue does not occur when the client sends requests to addresses other than localhost. The event handler function is called fine. Here is the ev_handler function on the client-side for reference:
static void ev_handler(struct mg_connection *c, int ev, void *p) {
if (ev == MG_EV_HTTP_REPLY) {
struct http_message *hm = (struct http_message *)p;
c->flags |= MG_F_CLOSE_IMMEDIATELY;
fwrite(hm->message.p, 1, (int)hm->message.len, stdout);
putchar('\n');
exit_flag = 1;
} else if (ev == MG_EV_CLOSE) {
exit_flag = 1;
};
}
Is this a common issue when trying to establish a connection on localhost with a server on the same computer?
The cause of such behavior is the fact that client connection does not fire an event until all data is read. How client knows the all data is read? There are 3 possibilities:
Server has sent Content-Length: XXX header and client has read XXX bytes of the message body, so it knows it received everything.
Server has sent Transfer-Encoding: chunked header, and sent all data chunks followed by an empty chunk. When client receives an empty chunk, it knows it received everything.
Server set neither Content-Lenth, nor Transfer-Encoding. Client does not know in this case what is the size of the body, and it keeps reading until server closes the connection.
What you see is (3). Solution: set Content-Length in your server code.

Is it possible to connect to the Google IOTCore MQTT Bridge via Javascript?

I've been trying to use the javacscript version of the Eclipse Paho MQTT client to access the Google IOTCore MQTT Bridge, as suggested here:
https://cloud.google.com/iot/docs/how-tos/mqtt-bridge
However, whatever I do, any attempt to connect with known good credentials (working with other clients) results in this connection error:
errorCode: 7, errorMessage: "AMQJS0007E Socket error:undefined."
Not much to go on there, so I'm wondering if anyone has ever been successful connecting to the MQTT Bridge via Javascript with Eclipse Paho, the client implementation suggested by Google in their documentation.
I've gone through their troubleshooting steps, and things seem to be on the up and up, so no help there either.
https://cloud.google.com/iot/docs/troubleshooting
I have noticed that in their docs they have sample code for Java/Python, etc, but not Javascript, so I'm wondering if it's simply not supported and their documentation just fails to mention as such.
I've simplified my code to just use the 'Hello World' example in the Paho documentation, and as far as I can tell I've done things correctly (including using my device path as the ClientID, the JWT token as the password, specifying an 'unused' userName field and explicitly requiring MQTT v3.1.1).
In the meantime I'm falling back to polling via their HTTP bridge, but that has obvious latency and network traffic shortcomings.
// Create a client instance
client = new Paho.MQTT.Client("mqtt.googleapis.com", Number(8883), "projects/[my-project-id]/locations/us-central1/registries/[my registry name]/devices/[my device id]");
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// connect the client
client.connect({
mqttVersion: 4, // maps to MQTT V3.1.1, required by IOTCore
onSuccess:onConnect,
onFailure: onFailure,
userName: 'unused', // suggested by Google for this field
password: '[My Confirmed Working JWT Token]' // working JWT token
function onFailure(resp) {
console.log(resp);
}
// called when the client connects
function onConnect() {
// Once a connection has been made, make a subscription and send a message.
console.log("onConnect");
client.subscribe("World");
message = new Paho.MQTT.Message("Hello");
message.destinationName = "World";
client.send(message);
}
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage);
}
}
// called when a message arrives
function onMessageArrived(message) {
console.log("onMessageArrived:"+message.payloadString);
}
I'm a Googler (but I don't work in Cloud IoT).
Your code looks good to me and it should work. I will try it for myself this evening or tomorrow and report back to you.
I've spent the past day working on a Golang version of the samples published on Google's documentation. Like you, I was disappointed to not see all Google's regular languages covered by samples.
Are you running the code from a browser or is it running on Node.JS?
Do you have a package.json (if Node) that you would share too please?
Update
Here's a Node.JS (JavaScript but non-browser) that connects to Cloud IoT, subscribes to /devices/${DEVICE}/config and publishes to /devices/${DEVICE}/events.
https://gist.github.com/DazWilkin/65ad8890d5f58eae9612632d594af2de
Place all the files in the same directory
Replace values in index.js of the location of Google's CA and your key
Replaces [[YOUR-X]] values in config.json
Use "npm install" to pull the packages
Use node index.js
You should be able to pull messages from the Pub/Sub subscription and you should be able to send config messages to the device.
Short answer is no. Google Cloud IoT Core doesn't support WebSockets.
All the JavaScript MQTT libraries use WebSocket because JavaScript is restricted to perform HTTP requests and WebSocket connections only.

why is the ping on localhost so high when i use websockets?

I am using a simple node.js server to broadcast messages:
var ws = require('websocket.io');
var server = ws.listen(3000);
server.on('connection', function(socket) {
socket.on('message', function(data) {
server.clients.forEach(function(client) {
client.send(data);
});
});
});
The client is written in c++ (cocos2dx framework) and it's working like this:
_websocket = new WebSocket();
_websocket->init(*this, "ws://localhost:3000");
....
_websocket->send(message);
When I measure the latency by sending something to the server and waiting for the response: it's around 80-100ms. The node.js server runs on localhost and I would expect the ping to be around 0-10ms max.
Do you know the reason why the ping is so high? Do I have to flush something or is something wrong with the server setup?
Thanks!

How to redirect messages from one endpoint to another using java websockets (jsr 356)

I am doing a personal project to learn about java websockets. Basically my HTML clients sends messages to my server through JSR 356 websockets. The endpoint #ServerEndpoint("/wsServer") receives all messages from the clients and I would like to see those messages in another portal/endpoint #ServerEndpoint("/wsDashboard") as a dashboard in real time.
I would appreciate any idea, documentation or piece of code to start with as I really have no idea, I have seen solutions like apache kafka, but I am not sure if this is what I need.
thanks
Create Java Web Socket Client for /wsDashboard on onmessage method of a #ServerEndpoint("/wsServer") end point and keep it in user properties. wher you receive a message just forward the message to /wsServer web socket.
#ServerEndpoint("/wsServer")
public class MyWSServerEndPoint{
#OnOpen
public void open( Session session) {
// Open java client websocket connection to /wsDashboard and keep the object in
session.getUserProperties().put("wsDashboard ", websocket);
}
#OnMessage
public void onMessage(String message,Session session){
//forwarding the message
session.getUserProperties().get("wsDashboard ").getRemote().send(message);
}
#OnClose
public void onClose(Session session){
session.getUserProperties().get("wsDashboard ").close();
}
}
To create a client end point here is good example
http://www.hascode.com/2014/11/creating-different-websocket-chat-clients-in-java/

C++, Mongoose: How to make a POST request?

I'm working on a project that uses Mongoose, and I need to make a POST request to another server. I don't see an example of how to do this in their examples list, does anyone know how to do this?
EDIT to add more detail:
I'm working within a larger C++ app and need to create a simple server such that a user can query the app for information. Right now, I start the server like this:
Status sampleCmd::startServer()
{
Status stat = MS::kSuccess;
struct mg_server *server;
// Create and configure the server
server = mg_create_server(NULL, ev_handler);
mg_set_option(server, "listening_port", "8080");
stopServer = false;
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
while (!stopServer) //for (;;)
{
mg_poll_server(server, 1000);
}
// Cleanup, and free server instance
mg_destroy_server(&server);
return stat;
}
In my event handler, I parse the provided URI for a particular one and then run some commands with the application's API. I need to send these results back to a server for the user to see. It's this latter step that is unclear to me. It seems odd that a web server library wouldn't have some client functionality, don't servers need to talk to other servers?
Okay, it turns out I was thinking about this wrong. I needed to respond to the POST request I was getting. So using mg_printf_data(...) with the connection object worked for me.