resending peerconnection offer - javascript

I'm currently trying to rebroadcast my local stream to all my peer connections. options I tried:
1) Loop trough all my peer connection and recreate them with the new local stream. Problem that I encounter here is the fact that createOffer is asynchronous.
2) create 1 sdp and send it to all peers. Problem: no video
Would anyone have a way to resend an offer to a list of peers?

Each PC needs to recreate an offer (as bwrent said).
as you obviously are using a p2p multiparty (multiple peer connections) you might want to pass on the peerID to the createOffer success callback every time, then you don't have to worry about it being asynchronous. You need to make the full handshake (offer, answer, candidate) peerID dependent.
(Simplified) Example from our SDK
Skyway.prototype._doCall = function (targetMid) {
var pc = this._peerConnections[targetMid]; // this is thread / asynchronous safe
pc.createOffer(
function (offer) {
self._setLocalAndSendMessage(targetMid, offer); // pass the targetID down the callback chain
},
function (error) {this._onOfferOrAnswerError(targetMid, error);},
constraints
);
};
Skyway.prototype._setLocalAndSendMessage = function (targetMid, sessionDescription) {
var pc = this._peerConnections[targetMid]; // this is thread / asynchronous safe
pc.setLocalDescription(
sessionDescription,
self._sendMessage({ target: targetMid, ... }), // success callback
function () {} // error callback
);
};

If you mean async in a way that when a callback fires it has the wrong variable of who to send it to as the loop has ended and the variable contains the last 'person'? You could scope it to solve the asynchronous problem:
For(var i=0;i<peerConnections.length;i++){
(function(id){
//inside here you have the right id. Even if the loop ended and the i variable has changed to something else, the I'd variable still is the same.
})(i);
}
This is a bit like Alex' answer, as his anwer also describes an example of scoping the variable inside the function executing the .createOffer
Another way to handle this correctly is to use renegotiation. Whenever you change a stream, the on onnegotiation event handler is automatically fired. Inside this function you create a new offer and send that to the other person. As you mentioned you have multiple peer connect ions listening to the stream, you need to know whom to send the sdp to. If you would add the persons id to the rtc object, you can then get it back inside the onnegotioation event by calling this.id.

Related

How to throw a custom message using Dialogflow after three times of fallback

I am developing a chatbot using Dialogflow, I would like to throw a message to user when the chatbot doesn't understand the user input for three times in a row and for the forth time respond with a custom message (not the one of the options declared on the dialogflow interface)
One idea that I have is to make a counter within the input unknown action like this:
var counter = 1;
// The default fallback intent has been matched, try to recover (https://dialogflow.com/docs/intents#fallback_intents)
'input.unknown': () => {
// Use the Actions on Google lib to respond to Google requests; for other requests use JSON
if (requestSource === googleAssistantRequest) {
sendGoogleResponse('I\'m having trouble, can you try that again?'); // Send simple response to user
} else {
if (counter == 3) {
counter = 1;
sendResponse('Custom message');
} else {
counter++;
sendResponse('I\'m having trouble, can you try that again?'); // Send simple response to user
}
}
},
This would work, but idk if this will work for multiple user at the same time, I was thinking to create a storage for storing requests attached by a unique id and have a different counter for each request!
Do you have any better idea of achieving such thing in Dialogflow?
This will not work the way you've designed it. Not quite for the reason you think, but close.
You don't show the rest of your code (that's ok), but the counter variable is probably in a function that gets called each time it processes a message. When that function is finished, the counter variable goes out of scope - it is lost. Having multiple calls at the same time won't really be an issue since each call gets a different scope (I'm glossing over some technical details, but this should be good enough).
One solution is that you could store the variable in a global context - but then you do have the issue of multiple users ending up with the same counter. That is very very bad.
Your solution about keeping a counter in a database, keyed against the user, does make sense. But for this need, it is overkill. It is useful for saving data between conversations, but there are better ways to save information during the same conversation.
The easiest solution would be to use a Dialogflow Context. Contexts let you save state in between calls to your webhook fulfillment during the same conversation and for a specific number of messages received from the user (the lifespan).
In this case, it would be best if you created a context named something like unknown_counter with a lifespan of 1. In the parameters, you might set val to 1.
The lifespan of 1 would mean that you'll only see this context the next time your webhook is called. If they handle it through some other Intent (ie - you understood them), then the context would just vanish after your fulfillment runs.
But if your input.unknown handler is called again, then you would see the context was there and what the value is. If it doesn't meet the threshold, send the context again (with a lifespan of 1 again), but with the value being incremented by 1. If it did meet the threshold - you'd reply with some other answer and close the connection.
By "send the context", I mean that the context would be included as part of the reply. So instead of sending just a string to sendGoogleResponse() or sendResponse() you would send an object that included a speech property and an outputContexts property. Something like this:
var outputContexts = [
{
name: 'unknown_counter',
lifespan: 1,
parameters: {
'val': counterValue,
}
}
];
sendResponse({
speech: "I'm confused. What did you say?",
outputContexts: outputContexts
});

Firebase synchronisation of locally-modified data: handling errors & global status

I have two related questions regarding the Firebase web platform's
synchronisation of locally-modified data to the server:
Every client sharing a Firebase database maintains its own internal version of any active data.
When data is updated or saved, it is written to this local version of the database.
The Firebase client then synchronizes that data with the Firebase servers and with other clients on a 'best-effort' basis.
1. Handling sync errors
The data-modification methods
(set(),
remove(), etc)
can take an onComplete callback parameter:
A callback function that will be called when synchronization to the Firebase servers
has completed. The callback will be passed an Error object on failure; else null.
var onComplete = function(error) {
if (error) {
console.log('Synchronization failed');
} else {
console.log('Synchronization succeeded');
}
};
fredRef.remove(onComplete);
In the example above, what kind of errors should the fredRef.remove() callback expect to receive?
Temporary errors?
Client is offline (network connection lost) ?
Firebase server is temporarily overloaded or down for maintenance, but will be available again soon?
Permanent errors?
Permission denied (due to security rules) ?
Database location does not exist?
Is there a way to distinguish between temporary and permanent errors?
How should we handle / recover from these errors?
For temporary errors, do we need to call fredRef.remove() again after a short period of time, to retry the operation?
2. Global sync status
I realise that each call to set() and remove() will receive an individual sync success/failure
result in the onComplete callback.  But I'm looking for a way to determine the
global sync status of the whole Firebase client.
I'd like to use a beforeunload event listener
to warn the user when they attempt to leave the page before all modified data has been synced to the server,
and I'm looking for some function like firebase.isAllModifiedDataSynced().  Something like this:
window.addEventListener('beforeunload', function (event) {
if (!firebase.isAllModifiedDataSynced()) {
event.returnValue = 'Some changes have not yet been saved. If you ' +
'leave this page, your changes will be lost.';
}
});
Here's an example of the same functionality in Google Drive:
I'm aware of the special /.info/connected location:
it is useful for a client to know when it is online or offline.
Firebase clients provide a special location at /.info/connected which is updated every time the client's connection state changes.
Here is an example:
var connectedRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/.info/connected");
connectedRef.on("value", function(snap) {
if (snap.val() === true) {
alert("connected");
} else {
alert("not connected");
}
});
The special /.info/connected location can be connected to a beforeunload event listener like this:
var connectedRef = new Firebase('https://myapp.firebaseio.com/.info/connected');
var isConnected = true;
connectedRef.on('value', function (snap) {
isConnected = snap.val();
});
window.addEventListener('beforeunload', function (event) {
if (!isConnected) {
event.returnValue = 'Some changes have not yet been saved. If you ' +
'leave this page, your changes will be lost.';
}
});
My question is:
If isConnected is true, does this also mean that all modified data has been synced to the server?
i.e. Does "connected" also mean "synced"?
If not, how can the app determine the global sync status of the whole Firebase client?
Is there a special /.info/synchronized location?
Does the app need to manually keep track of the sync success/failure result of every onComplete callback?
In the example above, what kind of errors should the fredRef.remove() callback expect to receive?
Client is offline (network connection lost) ?
No, this will not cause an error to be passed to the completion listener. It will simply cause the completion listener to not be called (yet).
Firebase server is temporarily overloaded or down for maintenance, but will be available again soon?
No. This is essentially the same as being without a network connection.
Permission denied (due to security rules) ?
Yes, this is will indeed cause an error to be passed to the completion handler.
Database location does not exist?
No, this will not cause an error to be caused to the completion listener.
If isConnected is true, does this also mean that all modified data has been synced to the server? i.e. Does "connected" also mean "synced"?
No it does not. .info/connected will fire with true when a connection is made to the database.
If not, how can the app determine the global sync status of the whole Firebase client?
There is currently no way to determine whether your local data is up to date with the server.
Is there a special /.info/synchronized location?
No, such a location doesn't exist.
Does the app need to manually keep track of the sync success/failure result of every onComplete callback?
That depends on the use-case. But if you want to simply know when all your writes are executed, push a dummy value and wait for that to complete. Since Firebase executes the writes in order, you can be certain at that stage that you've gotten the other events.

Mongodb Tailable Cursor in nodejs, how to stop stream

I use below code to get the data from mongodb capped collection
function listen(conditions, callback) {
db.openConnectionsNew( [req.session.client_config.db] , function(err, conn){
if(err) {console.log({err:err}); return next(err);}
coll = db.opened[db_name].collection('messages');
latestCursor = coll.find(conditions).sort({$natural: -1}).limit(1)
latestCursor.nextObject(function(err, latest) {
if (latest) {
conditions._id = {$gt: latest._id}
}
options = {
tailable: true,
awaitdata: true,
numberOfRetries: -1
}
stream = coll.find(conditions, options).sort({$natural: -1}).stream()
stream.on('data', callback)
});
});
}
and then I use sockets.broadcast(roomName,'data',document);
on client side
io.socket.get('/get_messages/', function(resp){
});
io.socket.on('data', function notificationReceivedFromServer ( data ) {
console.log(data);
});
this works perfectly as I am able to see the any new document which is inserted in db.
I can see in mongod -verbose that after each 200ms there is query running with the query {$gt:latest_id} and this is fine, but I have no idea how can i close this query :( I am very new in nodejs and using the mongodb tailable option for the first time and am totally lost, any help or clue is highly appreciated
What is returned from the .stream() method from the Cursor object returned from .find() is an implementation of the node transform stream interface. Specifically this is a "readable" stream.
As such, it's "data" event is emitted whenever there is new data received and available in the stream to be read.
There are other methods such as .pause() and .resume() which can be used to control the flow of these events. Typically you would call these "inside" a "data" event callback, where you wanted to make sure the code in that callback was executed before the "next" data event was processed:
stream.on("data", function(data) {
// pause before processing
stream.pause();
// do some work, possibly with a callback
something(function(err,result) {
// Then resume when done
stream.resume();
});
});
But of course this is just a matter of "scoping". So as long as the "stream" variable is defined in a scope where another piece of code can access it, then you can call either method at any time.
Again, by the same token of scoping, you can just "undefine" the "stream" object at any point in the code, making the "event processing" redundant.
// Just overwrite the object
scope = undefined;
So worth knowing. In fact the newer "version 2.x" of the node driver wraps a "stream interface" directly into the standard Cursor object without the need to call .stream() to convert. Node streams are very useful and powerful things that it would be well worth while coming to terms with their usage.

Strange issue with socket.on method

I am facing a strange issue with calling socket.on methods from the Javascript client. Consider below code:
for(var i=0;i<2;i++) {
var socket = io.connect('http://localhost:5000/');
socket.emit('getLoad');
socket.on('cpuUsage',function(data) {
document.write(data);
});
}
Here basically I am calling a cpuUsage event which is emitted by socket server, but for each iteration I am getting the same value. This is the output:
0.03549148310035006
0.03549148310035006
0.03549148310035006
0.03549148310035006
Edit: Server side code, basically I am using node-usage library to calculate CPU usage:
socket.on('getLoad', function (data) {
usage.lookup(pid, function(err, result) {
cpuUsage = result.cpu;
memUsage = result.memory;
console.log("Cpu Usage1: " + cpuUsage);
console.log("Cpu Usage2: " + memUsage);
/*socket.emit('cpuUsage',result.cpu);
socket.emit('memUsage',result.memory);*/
socket.emit('cpuUsage',cpuUsage);
socket.emit('memUsage',memUsage);
});
});
Where as in the server side, I am getting different values for each emit and socket.on. I am very much feeling strange why this is happening. I tried setting data = null after each socket.on call, but still it prints the same value. I don't know what phrase to search, so I posted. Can anyone please guide me?
Please note: I am basically Java developer and have a less experience in Javascript side.
You are making the assumption that when you use .emit(), a subsequent .on() will wait for a reply, but that's not how socket.io works.
Your code basically does this:
it emits two getLoad messages directly after each other (which is probably why the returning value is the same);
it installs two handlers for a returning cpuUsage message being sent by the server;
This also means that each time you run your loop, you're installing more and more handlers for the same message.
Now I'm not sure what exactly it is you want. If you want to periodically request the CPU load, use setInterval or setTimeout. If you want to send a message to the server and want to 'wait' for a response, you may want to use acknowledgement functions (not very well documented, but see this blog post).
But you should assume that for each type of message, you should only call socket.on('MESSAGETYPE', ) once during the runtime of your code.
EDIT: here's an example client-side setup for a periodic poll of the data:
var socket = io.connect(...);
socket.on('connect', function() {
// Handle the server response:
socket.on('cpuUsage', function(data) {
document.write(data);
});
// Start an interval to query the server for the load every 30 seconds:
setInterval(function() {
socket.emit('getLoad');
}, 30 * 1000); // milliseconds
});
Use this line instead:
var socket = io.connect('iptoserver', {'force new connection': true});
Replace iptoserver with the actual ip to the server of course, in this case localhost.
Edit.
That is, if you want to create multiple clients.
Else you have to place your initiation of the socket variable before the for loop.
I suspected the call returns average CPU usage at the time of startup, which seems to be the case here. Checking the node-usage documentation page (average-cpu-usage-vs-current-cpu-usage) I found:
By default CPU Percentage provided is an average from the starting
time of the process. It does not correctly reflect the current CPU
usage. (this is also a problem with linux ps utility)
But If you call usage.lookup() continuously for a given pid, you can
turn on keepHistory flag and you'll get the CPU usage since last time
you track the usage. This reflects the current CPU usage.
Also given the example how to use it.
var pid = process.pid;
var options = { keepHistory: true }
usage.lookup(pid, options, function(err, result) {
});

Native Messaging postMessage with callback

So, I create a port
var port = chrome.runtime.connectNative("my.native.app");
And I'll define
port.onMessage.addListener(onNativeMessage);
port.onDisconnect.addListener(onDisconnect);
So when I call
port.postMessage({"text":"messsage"});
It goes to my native application using standard in/out and I get my response.
Here's my problem: I have several functions that expect a response, and others that do not. I want to be able to post a message and wait for a response from the native application (which is continually running). How is this done?
I am aware of "one time messaging" via sendMessageNative which works great, except I use my native application as a state machine, so it kills my application after it is done, which is no good.
You could add another listener to onNativeMessage to call your callback and then de-register.
Something like this, with closures:
function callbackOnId(ev, id, callback) {
var listener = ( function(port, id) {
var handler = function(msg) {
if(msg.id == id) {
ev.removeListener(handler);
callback(msg);
}
}
return handler;
})(ev, id, callback);
ev.addListener(listener);
}
/* ... */
callbackOnId(port.onMessage, "someRequestId", callback);
port.postMessage({"text":"message", "id": "someRequestId"});
Now, the first time your port receives a message containing "id": "someRequestId", callback will be called with that message, after which the listener will de-register itself.
If you need it, you can add an ability to remove the listener and/or modify the message checks.
My solution is to assign each message an unique id, and use a map to store the callback function for each message id (if there is a callback for the message).
When you receive a message from the host, check the message id and lookup the callback map. If there is a callback bound to that message, pass the response data and call it!

Categories

Resources