TokBox Republishing issue - Giving error when try to publishing after unpublish - tokbox

I am trying to create a one to one video streaming Ionic app. In the app I have a button "Connect", On click of "Connect" the publisher initialized and on click of "Disconnect" button I disconnect the session.What I want it to work like :
Click Connect - Publisher Initialized
Click Disconnect - Session Disconnect
Click Connect - Publisher Initialized (But here I get the error)
Tokbox Republishing issues
OpenTok:Publisher:error _connectivityAttemptPinger should have been cleaned up +0ms
OpenTok:Publisher:error OT.Publisher State Change Failed: +209ms 'PublishingToSession' cannot transition to 'PublishingToSession'
OpenTok:Publisher:error OT.Publisher.onPublishingTimeout +15s
OpenTok:GlobalExceptionHandler:error OT.exception :: title: Unable to Publish (1500) msg: ICEWorkflow +0ms
OpenTok:Session:error 1500 +0ms Session.publish :: Could not publish in a reasonable amount of time
OpenTok:Session:error 1500 +9ms Session.publish :: Session.publish :: Could not publish in a reasonable amount of time
The code is below:
tokBoxInit() {
if (OT.checkSystemRequirements() == 1) {
this.session = OT.initSession(this.apiKey, this.sessionId);
console.log(this.session);
this.session.connect(this.token, function(error) {
if (error) {
console.log("Error connecting: ", error.name, error.message);
} else {
console.log("Connected to the session.");
}
});
this.publisher = OT.initPublisher('publisher',{insertMode: 'append',width: '100%',height: '100%'});
this.publisher.on({
streamCreated: function (event) {},
streamDestroyed: function (event) {}
});
this.session.on({
sessionConnected: (event: any) => {
console.log("Session Connected Listener");
this.connected = true; // Status to show Connect/Disconnect Button
this.session.publish(this.publisher);
}
});
}
}

How do you handle the disconnect functionality? Do you clear the session after the connection is destroyed and unpublish the destroyed session?
And also check your token capabilities if it has the role of publisher or moderator as it could also be that the token does not have those properties. Or is missing when the session is regenerated.
1500 error message as quoted by opentok has the following description:
Unable to Publish. The client's token does not have the role set to publish or moderator. Once the client has connected to the session, the capabilities property of the Session object lists the client's capabilities.
But code is too simple to tell, because I can't see how you handle session disconnection so check if you handle it and clear session when disconnected.

Related

Chrome Extension - Migration to Manifest v3 - chrome.permissions user gesture issue

I have built a chrome extension in manifest version 2 and am now looking at migrating to version 3. As part of this migration I have come across an issue when trying to toggle an optional permission to use the chrome notifications api.
Since you can't request a new permission from a content script as the api is not accessible from a content script, you have to send a message to the background script to perform the request and return the response to the content script. This worked as expected with version 2, now I am receiving this error:
Unchecked runtime.lastError: This function must be called during a user gesture
This means that the extension wants the permission request to be initiated on the back of an event initiated by a user action, such as a click. This indicates that the extension wishes the permission request to be completed from the content script but as stated above this is impossible.
Could anyone illuminate me if I'm missing something?
Content Script:
chrome.runtime.sendMessage(
{message: 'requestPermissions', permissions: ['notifications']},
(res) => console.log(res)
);
Background Script:
export function requestPermissions(request, sender, sendResponse) {
const {permissions} = request;
new Promise((resolve) => {
chrome.permissions.request(
{
permissions
},
(granted) => resolve(granted)
);
}).then((res) => sendResponse(res));
return true;
}

Handling errors if no network is available

I just implemented my first backend file where I fetch some user data, messages and so on.
Now I wanted to include error handling if there is no network available.
I donĀ“t know if I did it right but this was my approach so far:
import axios from 'axios'
const host = process.env.VUE_APP_URL
export default {
person: async function (currentPerson) {
let params = {
currentPerson: localStorage.getItem("person"),
};
if (user) {
params['currentPerson'] = currentPerson;
}
return axios.get(`${host}/api/currentPerson`, {
params: params
})
//catching network errors
.catch (error => {
if (error.response) {
/*
* The request was made and the server responded with a
4xx/5xx error
*/
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
/*
* The request was made but no response was received
*/
console.log(error.request);
} else {
// Something happened in setting up the request and triggered an Error
console.log('Error', error.message);
}
console.log(error)
});
},
In my mounted() function of my main view I fetch the data from my backend file from above:
backend.matches().then(function (response) {
self.contacts = response.data.persons;
});
I tried to check in console if it is working but all I get is the following:
In the catch block I check for
response errors: like 4xx/5xx
request errors: if my network not responding in time
and any other errors
Would this be the right approach to check if a network is available or not? Or does it degrade the user experience when the user checks the error?
My backend file includes more methods.. do I have to write for each method these kind of requests?
In your backend file you don't react whether there is a network connection or not I think.
And only for reference: that is not the backend, but communicates with the backend - the backend is the part of your code what you communicate with, e.g. Laravel code, an API, ...
Try adding the following at the beginning of your catch part:
if (!error.response) {
//network error
console.log('No network connection');
} else if (error.response) {
//the rest of your code
This should print out No network connection in your console.
Run your application, turn off the internet connection and check the console.
These kind of code should always be located in your backend part.
My answer maybe different from your question.
When i create a .net core API with Angular i used three things to check is there network or not?
subscribe to windows's offline/online event
create signalR hub from layout component to API server
API request failed (it means lot of incident, but if 1. or 2. case is true i know what cause 3. case

Resolving audio broadcasting error: client join failed DYNAMIC_KEY_EXPIRED (Agora.io)

I'm a server side developer with rudimentary JS knowhow. I'm tinkering with Agora's audio broadcasting functionality (specifically for the web). For reference, I've been following this: https://docs.agora.io/en/Audio%20Broadcast/start_live_audio_web?platform=Web
I'm attempting to broadcast audio as a host. I have an HTML button which fires a JS function where I:
Initialize a client
Set the role
Join a predefined channel
Publish a local stream
My understanding is that accomplshing the aforementioned will enable me to broadcast audio. When I try this, I end up getting a client join failed DYNAMIC_KEY_EXPIRED error. I'm unable to find documentation regarding how to resolve this. Can you help me resolve this? An illustrative example would be nice.
My JS code is below. Note that I'm using a temp token to test this functionality on localhost.
// rtc object
var rtc = {
client: null,
joined: false,
published: false,
localStream: null,
remoteStreams: [],
params: {}
};
// Options for joining a channel
var option = {
appID: "anAppID",// from 'Project Management' dashboard
channel: "AudioLive",
uid: null,//The user ID should be unique in a channel. If you set the user ID as null or 0, the Agora server assigns a user ID and returns it in the onSuccess callback.
token: "aTempToken"// TEMP Token
}
function createBroadcast(role) {
console.log("entered createBroadcast");
// Create a client
rtc.client = AgoraRTC.createClient({mode: "live", codec: "h264"});
// Initialize the client
rtc.client.init(option.appID, function () {
console.log("init success");
// Note: in a live broadcast, only the host can be heard and seen. You can also call setClientRole() to change the user role after joining a channel.
rtc.client.setClientRole(role);
console.log("role is set");
// Call Client.join in the onSuccess callback of Client.init
rtc.client.join(option.token ? option.token : null, option.channel, option.uid ? +option.uid : null, function (uid) {
console.log("join channel: " + option.channel + " success, uid: " + uid);
rtc.params.uid = uid;
// Call AgoraRTC.createStream to create a stream in the onSuccess callback of Client.join
rtc.localStream = AgoraRTC.createStream({
streamID: rtc.params.uid,
audio: true,
video: false,
screen: false,
})
// Call Stream.init to initialize the stream after 'creating' the stream above
// Initialize the local stream
rtc.localStream.init(function () {
console.log("init local stream success");
// play stream with html element id "local_stream"
rtc.localStream.play("local_stream");
// Call Client.publish in the onSuccess callback of Stream.init to publish the local stream
// Publish the local stream
rtc.client.publish(rtc.localStream, function (err) {
console.log("publish failed");
console.error(err);
})
}, function (err) {
console.error("init local stream failed ", err);
});
}, function(err) {
console.error("client join failed", err)
})
}, (err) => {
console.error(err);
});
}
<div style="background:#f0f3f4;padding:20px">
<button id="broadast" style="height:40px;width:200px" onclick="createBroadcast('host')">Start Live Broadcast</button>
</div>
I've not added the actual values for appID and token in the code above.
Note: Please ask for more information in case you require it.
The error that you are facing is due to the expiry of the token generated for authentication purposes while generating an APP ID. To resolve this you will have to generate a new token as elaborated in the below given links:
Token-expired
renewToken
A token (or a temporary token) expires after a certain period of time. When the SDK notifies the client that the token is about to expire or has expired by the onTokenPrivilegeWillExpire or onTokenPrivilegeDidExpire callbacks, you need to generate a new token and call the renewToken method.
client.on("onTokenPrivilegeWillExpire", function(){
//After requesting a new token
client.renewToken(token);
});
client.on("onTokenPrivilegeDidExpire", function(){
//After requesting a new token
client.renewToken(token);
});
Include the above functions in your javascript code along with the rest of the eventListeners.
Incase your application doesn't require security you can opt to not use a token and generate an App ID without a certificate.
App ID without certificate
Do get back for further support incase the issue remains unresolved.

MFPPush.registerDevice wrapped by obtainAccessToken failed

I'm trying to run MFP8's push sample app of GitHub. But MFPPush.registerDevice method failed and error message "Failed to register device:" was shown.
function registerDevice() {
WLAuthorizationManager.obtainAccessToken("push.mobileclient").then(
MFPPush.registerDevice(
null,
function(successResponse) {
navigator.notification.alert("Successfully registered");
enableButtons();
},
function(failureResponse) {
navigator.notification.alert("Failed to register");
console.log("Failed to register device:" +
JSON.stringify(failureResponse));
}
)
);
}
I read the MFP8 document and found the note below.
Note: Authenticated notifications are currently not supported in Cordova applications due to a defect. However a workaround is provided: each MFPPush API call can be wrapped by WLAuthorizationManager.obtainAccessToken("push.mobileclient").then( ... );. The provided sample application uses this workround.
The sample code is wrapped by WLAuthorizationManager.obtainAccessToken indeed. But I think MFPPush.registerDevice may be called before 'obtainAccessToken' completes because return value of MFPPush.registerDevice's method is specified as Promise.then() parameter instead of function that call MFPPush.registerDevice.
So I think the sample should be written as bellow,
function registerDevice() {
WLAuthorizationManager.obtainAccessToken("push.mobileclient").then(
function() {
MFPPush.registerDevice(
null,
function(successResponse) {
navigator.notification.alert("Successfully registered");
enableButtons();
},
function(failureResponse) {
navigator.notification.alert("Failed to register");
console.log("Failed to register device:" +
JSON.stringify(failureResponse));
}
)
);
}
}
Could anyone give me some advice about that?
There is additional information. In device log these messages were logged.
Of course, I registered UserLogin security check to MobileFirst Server and UserLogin challengeHandler is created in UserLoginChallengeHandler.js
(I have not changed except bundleId)
2018-02-10 19:42:47.271015+0900 PushNotificationsCordova[1273:1500711] Failed to register device:"Error Domain=com.ibm.mfp.push Code=5 \"Error authenticating client. Error is 'Challenge handler does not exist. There is no registered challenge handler with key UserLogin'.\" UserInfo={networkMetadata={\n \"$bytesSent\" = 120;\n \"$category\" = network;\n \"$outboundTimestamp\" = 1518259366869;\n \"$path\" = \"http://192.168.0.105:9080/mfp/api/preauth/v1/preauthorize\";\n \"$requestMethod\" = POST;\n \"$trackingid\" = \"F8FD4A96-B046-4DAD-87F6-7441E8426C2E\";\n}, NSLocalizedDescription=Error authenticating client. Error is 'Challenge handler does not exist. There is no registered challenge handler with key UserLogin'.}"

Google Cloud Pub/Sub Node.js Sample: TypeError: Cannot read property 'on' of null

I'm using GCP and I want to use Cloud Pub/Sub. I got this error below when I tried Node.js sample. Does anyone knows how to fix it?
/private/tmp/pubsub/pubsubsample.js:26
subscription.on('error', onError);
^
TypeError: Cannot read property 'on' of null
at /private/tmp/pubsub/pubsubsample.js:26:15
at /private/tmp/pubsub/node_modules/gcloud/lib/pubsub/index.js:474:7
at Object.handleResp (/private/tmp/pubsub/node_modules/gcloud/lib/common/util.js:113:3)
at /private/tmp/pubsub/node_modules/gcloud/lib/common/util.js:422:12
at Request.onResponse [as _callback] (/private/tmp/pubsub/node_modules/gcloud/node_modules/retry-request/index.js:106:7)
at Request.self.callback (/private/tmp/pubsub/node_modules/gcloud/node_modules/request/request.js:198:22)
at emitTwo (events.js:87:13)
at Request.emit (events.js:172:7)
at Request.<anonymous> (/private/tmp/pubsub/node_modules/gcloud/node_modules/request/request.js:1035:10)
at emitOne (events.js:82:20)
https://github.com/GoogleCloudPlatform/gcloud-node
var gcloud = require('gcloud');
// Authenticating on a per-API-basis. You don't need to do this if you
// auth on a global basis (see Authentication section above).
var pubsub = gcloud.pubsub({
projectId: 'xxxxx',
keyFilename: 'xxx.json'
});
// Reference a topic that has been previously created.
var topic = pubsub.topic('info');
// Publish a message to the topic.
topic.publish({
data: 'New message!'
}, function(err) {});
// Subscribe to the topic.
topic.subscribe('new-subscription', function(err, subscription) {
// Register listeners to start pulling for messages.
function onError(err) {}
function onMessage(message) {}
subscription.on('error', onError);
subscription.on('message', onMessage);
// Remove listeners to stop pulling for messages.
subscription.removeListener('message', onMessage);
subscription.removeListener('error', onError);
});
... I'm using now PubSub but I'm thinking whether I can do same thing by using Google Cloud PubSub.
This post may be relevant. Node.js on Google Cloud Platform Pub/Sub tutorial worker is failing with "TypeError: Cannot call method 'on' of null"
Update 1
I changed to this code but same error was showed.
(error)
subscription.on('error', onError);
^
TypeError: Cannot read property 'on' of null
(code)
// Subscribe to the topic
topic.subscribe('new-subscription', function(err, subscription) {
if( err ) {
// something went wrong, react!
return;
}
// Register listeners to start pulling for messages.
function onError(err) {}
function onMessage(message) {}
subscription.on('error', onError);
subscription.on('message', onMessage);
// Remove listeners to stop pulling for messages.
subscription.removeListener('message', onMessage);
subscription.removeListener('error', onError);
});
Update 2
My expectation is this below.
execute "node pubsub.js"
I can see the sample message 'New message!'
When invoking topic.subscribe(), the method essentially invokes the pubsub.subscribe() method with a specific Topic instance as its context. This can be seen from the source code under Topic.prototype.subscribe.
Based on the PubSub index.js source code, PubSub.prototype.subscribe() issues a HTTP request to create a new subscription respecting the projects.subscriptions.create API format. If the response returns a 409 ALREADY_EXISTS error and you have not set the options.reuseExisting to true, the callback you provided will be invoked with the error and null as a subscription. According to the PubSub Nodejs documentation for topic.subscribe under options.reuseExisting, the default value if not specified is false and
If false, attempting to create a subscription that already exists will
fail.
To use this design more effectively, I would suggest the following:
var pubsub = require('gcloud').pubsub({
"projectId" : "project-id",
"keyFilename" : "key-file.json"
});
// This topic should already have been created
var topic = pubsub.topic("interesting-topic");
// The message that will be published
var message = {"data": "Welcome to this interesting thread"};
// Callback to throw an exception if publish was unsuccessful
// Will log published message IDs if successful
function publishedHandler(err, messageIds, responseBody) {
if (err) {
// Could not publish message(s)
throw err;
}
console.log(messagesIds);
}
// Callback to throw an exception if a subscription could not be found or created
// Will attach event listeners if successfully gets a subscription
function subscriptionHandler(err, subscription, responseBody) {
if (err) {
// Could not get or create a new subscription
throw err;
}
subscription.on("error", errorHandler);
subscription.on("message", messageHandler);
}
// Publish a message to the topic
topic.publish(message, publishedHandler);
// Create or get 'sub' and subcribe it to 'interesting-topic'
topic.subscribe("sub", {"reuseExisting": true}, subscriptionHandler);
Issue 696 may not refer exactly to this issue but does discuss some of the semantic choices made in designing the Node.js library for Cloud PubSub. It's not entirely clear if methods like topic.publish or topic.subscribe check for existence of a topic, existence of a subscription, create a new subscription or get an existing subscription. I would simply warn to add robust error handling.
Currently you do not check for errors, when subscribing, but just errors while being subscribed. To change that, you can use something like this:
// Subscribe to the topic.
topic.subscribe('new-subscription', function(err, subscription) {
// first check for errors
if( err ) {
// something went wrong, react!
return;
}
// rest of your code
});