reestablish WAMP subscriptions after reconnect - wamp

I'm using autobahn-js (0.11.2) in a web browser and the crossbar message router (v17.2.1) in the backend.
In case of a network disconnect (e.g. due to poor network) the autobahn-js client can be configured to try to reconnect periodically.
Now in my web app powered by autobahn subscriptions to different WAMP topics are created session.subscribe('my.topic', myhandleevent) dynamically.
Is there a best practice on how to reregister all active subscriptions upon reconnect? Is that maybe configurable even?

I think resubscriptions are not configurable out-of-box. But onopen is fired after reconnect, so placing subscriptions initialization inside it, will do the thing:
var ses;
var onOpenFunctions = [];
function addOnOpenFunction(name) {
onOpenFunctions.push(name);
if (ses !== null) {
window[name]();
}
}
connection.onopen = function (session, details) {
ses = session;
for (var i = 0; i < onOpenFunctions.length; i++) {
window[onOpenFunctions[i]]();
}
};
Then if you want subscribe dynamically you have to do this:
function subscribeTopic() {
session.subscribe('my.topic', myhandleevent)
}
addOnOpenFunction('subscribeTopic');

Related

Session Timeout on Application level in Oracle Apex

In my Application ID I changed in security attributes -> Maximum Session Idle Time in Seconds as 900 seconds, but issue is if I am on same page number it gives me session timeout message.
I want session timeout on user's movement over the page or other tabs it should not be restricted because all my application work is in mostly one page.
Session timeout is managed by the web application server and it needs a request or form submission to tell him, hey I'm alive, dude please don't kill the session, so for that reason you need to create an ajax request to tell web server you are still there.
You can use this script to detect user inactivity
var IDLE_TIMEOUT = 60; //seconds
var _idleSecondsCounter = 0;
document.onclick = function() {
_idleSecondsCounter = 0;
};
document.onmousemove = function() {
_idleSecondsCounter = 0;
};
document.onkeypress = function() {
_idleSecondsCounter = 0;
};
window.setInterval(CheckIdleTime, 1000);
function CheckIdleTime() {
_idleSecondsCounter++;
var oPanel = document.getElementById("SecondsUntilExpire");
if (oPanel)
oPanel.innerHTML = (IDLE_TIMEOUT - _idleSecondsCounter) + "";
if (_idleSecondsCounter >= IDLE_TIMEOUT) {
alert("Time expired!");
document.location.href = "logout.html";
}
}
Check this post Detecting user inactivity over a browser - purely through javascript

C++ program service

I have a personal server and I want to add some new functions to it.It is a Windows server running Windows Server 2019.The core program is wrote by me in c++,but it is just a core and can't access the Internet.It should receive a string from a webpage and return a string to it.My old way is using ASP create a file to storage the string from webpage and use my c++ program to overwrite it.But if the server get two tasks at same time,the result will become a mess.My ISP blocked port 80 so I'm using port 8012 to run my website.My router can't map to many port outside (There also a FTP service and a mail service in the server.) so I can only use the port 8012.What should I do?Should I write a C++ HTTP server?
Server Info:
Service port-inside port-outside software
WEB 80 8012 IIS
FTP 21 21 Serv-U
FTP-pasv 6000-6009 6000-6009 Serv-U
POP3 110 9110
SMTP 25 9025
RemoteDesktop 3389 3389 Windows
I have solved my questions.I am using some AJAX code to add a time sign and random numbers to avoid request crash.
Here are the AJAX code:
function GetValue(id)
{
return document.getElementById(id).value;
}
function SetValue(id,val)
{
document.getElementById(id).value=val;
return;
}
function GetTRValue() //Time-Random value,avoid messing up request
{
var rdm=Math.Random().toString(16);
var dt=new Date();
var time=dt.getTime().toString(10);
var tr=rdm+time;
return tr;
}
function EncodeRequest()
{
var req=new XMLHttpRequest();
req.onreadystatechange=function(){
if(req.readyState==4 && req.status==200)
{
SetValue('code',req.responseText);
}
else if(req.readyState==4 && req.status!=200)
{
alert('Server error:'+req.status);
}
}
req.open('POST','/base/base.asp',true);
req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
req.send('type=encode&code='+GetValue('base')+'&srcstr='+GetValue('str')+'&rdm='+GetTRValue());
return;
}
function DecodeRequest()
{
var qer=new XMLHttpRequest();
qer.onreadystatechange=function(){
if(qer.readyState==4 && qer.status==200)
{
SetValue('str',qer.responseText);
}
else if(qer.readyState==4 && qer.status!=200)
{
alert('Server error:'+qer.status);
}
}
qer.open('POST','/base/base.asp',true);
qer.setRequestHeader('Content-type','application/x-www-form-urlencoded');
qer.send('type=decode&code='+GetValue('base')+'&srcstr='+GetValue('code')+'&rdm='+GetTRValue());
return;
}
In my ASP file,I simply create a folder named the "Time-Random Value",and put request file here.Then wait for responses from C++ program,read it and delete the folder.
In my C++ program, I scan for folders and write responses into the same folder.

Google IOT per device heartbeat alert using Stackdriver

I'd like to alert on the lack of a heartbeat (or 0 bytes received) from any one of large number of Google IOT core devices. I can't seem to do this in Stackdriver. It instead appears to let me alert on the entire device registry which does not give me what I'm looking for (How would I know that a particular device is disconnected?)
So how does one go about doing this?
I have no idea why this question was downvoted as 'too broad'.
The truth is Google IOT doesn't have per device alerting, but instead offers only alerting on an entire device registry. If this is not true, please reply to this post. The page that clearly states this is here:
Cloud IoT Core exports usage metrics that can be monitored
programmatically or accessed via Stackdriver Monitoring. These metrics
are aggregated at the device registry level. You can use Stackdriver
to create dashboards or set up alerts.
The importance of having per device alerting is built into the promise assumed in this statement:
Operational information about the health and functioning of devices is
important to ensure that your data-gathering fabric is healthy and
performing well. Devices might be located in harsh environments or in
hard-to-access locations. Monitoring operational intelligence for your
IoT devices is key to preserving the business-relevant data stream.
So its not easy today to get an alert if one among many, globally dispersed devices, loses connectivity. One needs to build that, and depending on what one is trying to do, it would entail different solutions.
In my case I wanted to alert if the last heartbeat time or last event state publish was older than 5 minutes. For this I need to run a looping function that scans the device registry and performs this operation regularly. The usage of this API is outlined in this other SO post: Google iot core connection status
For reference, here's a Firebase function I just wrote to check a device's online status, probably needs some tweaks and further testing, but to help anybody else with something to start with:
// Example code to call this function
// const checkDeviceOnline = functions.httpsCallable('checkDeviceOnline');
// Include 'current' key for 'current' online status to force update on db with delta
// const isOnline = await checkDeviceOnline({ deviceID: 'XXXX', current: true })
export const checkDeviceOnline = functions.https.onCall(async (data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError('failed-precondition', 'You must be logged in to call this function!');
}
// deviceID is passed in deviceID object key
const deviceID = data.deviceID
const dbUpdate = (isOnline) => {
if (('wasOnline' in data) && data.wasOnline !== isOnline) {
db.collection("devices").doc(deviceID).update({ online: isOnline })
}
return isOnline
}
const deviceLastSeen = () => {
// We only want to use these to determine "latest seen timestamp"
const stamps = ["lastHeartbeatTime", "lastEventTime", "lastStateTime", "lastConfigAckTime", "deviceAckTime"]
return stamps.map(key => moment(data[key], "YYYY-MM-DDTHH:mm:ssZ").unix()).filter(epoch => !isNaN(epoch) && epoch > 0).sort().reverse().shift()
}
await dm.setAuth()
const iotDevice: any = await dm.getDevice(deviceID)
if (!iotDevice) {
throw new functions.https.HttpsError('failed-get-device', 'Failed to get device!');
}
console.log('iotDevice', iotDevice)
// If there is no error status and there is last heartbeat time, assume device is online
if (!iotDevice.lastErrorStatus && iotDevice.lastHeartbeatTime) {
return dbUpdate(true)
}
// Add iotDevice.config.deviceAckTime to root of object
// For some reason in all my tests, I NEVER receive anything on lastConfigAckTime, so this is my workaround
if (iotDevice.config && iotDevice.config.deviceAckTime) iotDevice.deviceAckTime = iotDevice.config.deviceAckTime
// If there is a last error status, let's make sure it's not a stale (old) one
const lastSeenEpoch = deviceLastSeen()
const errorEpoch = iotDevice.lastErrorTime ? moment(iotDevice.lastErrorTime, "YYYY-MM-DDTHH:mm:ssZ").unix() : false
console.log('lastSeen:', lastSeenEpoch, 'errorEpoch:', errorEpoch)
// Device should be online, the error timestamp is older than latest timestamp for heartbeat, state, etc
if (lastSeenEpoch && errorEpoch && (lastSeenEpoch > errorEpoch)) {
return dbUpdate(true)
}
// error status code 4 matches
// lastErrorStatus.code = 4
// lastErrorStatus.message = mqtt: SERVER: The connection was closed because MQTT keep-alive check failed.
// will also be 4 for other mqtt errors like command not sent (qos 1 not acknowledged, etc)
if (iotDevice.lastErrorStatus && iotDevice.lastErrorStatus.code && iotDevice.lastErrorStatus.code === 4) {
return dbUpdate(false)
}
return dbUpdate(false)
})
I also created a function to use with commands, to send a command to the device to check if it's online:
export const isDeviceOnline = functions.https.onCall(async (data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError('failed-precondition', 'You must be logged in to call this function!');
}
// deviceID is passed in deviceID object key
const deviceID = data.deviceID
await dm.setAuth()
const dbUpdate = (isOnline) => {
if (('wasOnline' in data) && data.wasOnline !== isOnline) {
console.log( 'updating db', deviceID, isOnline )
db.collection("devices").doc(deviceID).update({ online: isOnline })
} else {
console.log('NOT updating db', deviceID, isOnline)
}
return isOnline
}
try {
await dm.sendCommand(deviceID, 'alive?', 'alive')
console.log('Assuming device is online after succesful alive? command')
return dbUpdate(true)
} catch (error) {
console.log("Unable to send alive? command", error)
return dbUpdate(false)
}
})
This also uses my version of a modified DeviceManager, you can find all the example code on this gist (to make sure using latest update, and keep post on here small):
https://gist.github.com/tripflex/3eff9c425f8b0c037c40f5744e46c319
All of this code, just to check if a device is online or not ... which could be easily handled by Google emitting some kind of event or adding an easy way to handle this. COME ON GOOGLE GET IT TOGETHER!

Which do i need Sendgrid or Mailkit - to send emails from azure webjob

Can i use Mailkit to send emails from an azure webjob using an organizational smtp server? Or do i need to use Sendgrid?
Mine is a .net core 1.1 console application which i then hosted as azure webjob.
For some reason, I am not able to get my webjob working with Mailkit using an organizational Smtp server. The job runs successfully, does not log any errors. BUT not able to send mails out..
here is my code that uses mailkit
using (var client = new SmtpClient())
{
try {
// For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
Logger.LogInformation("Ready to connect to smtp server");
client.Connect(Constants.SMTP_HOST, 25, false);
Logger.LogInformation("connected to smtp server");
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
Logger.LogInformation("Ready to send email");
client.Send(message);
}
catch (Exception ex) {
Logger.LogError("An error occurred");
Logger.LogError(ex.StackTrace);
}
finally {
client.Disconnect(true);
}
}
Can i use Mailkit to send emails from an azure webjob using an organizational smtp server?
If you use the organizational smtp server, then should make sure that your email server policy allowed to that.
I test Mailkit in the Azure WebJob with google email. It works correctly on my side. Before that I turn Allow less secure apps: ON for my gmail account
The following is the demo code.
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Tom Gmail", "xx#gmail.com"));
message.To.Add(new MailboxAddress("Tom Hotmail", "xxx#hotmail.com"));
message.Subject = "I am a mail subject";
message.Body = new TextPart("plain")
{
Text = "I am a mail body."
};
using (var client = new SmtpClient())
{
client.Connect("smtp.gmail.com", 587);
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
// Note: only needed if the SMTP server requires authentication
client.Authenticate("sunguiguan#gmail.com", "#WSX3edc");
client.Send(message);
client.Disconnect(true);
}
Console.WriteLine("send mail successful");
Console.Read();
Or do i need to use Sendgrid?
On my opinon, SendGrid also is a good choice, we also could use the free price tier on the Azure. I also test it on myside. it also works correctly. We also could get more detail info from azure official document.
var apiKey ="ApiKey";//System.Environment.GetEnvironmentVariable("SENDGRID_APIKEY");
var client = new SendGridClient(apiKey);
var msg = new SendGridMessage()
{
From = new EmailAddress("xxx#hotmail.com", "Send Grid"),
Subject = "Hello World from the SendGrid CSharp SDK!",
PlainTextContent = "Hello, Email!",
HtmlContent = "<strong>Hello, Email!</strong>"
};
msg.AddTo(new EmailAddress("xxxx#gmail.com", "Test User"));
client.SendEmailAsync(msg).Wait();
}

Google Apps Script and cookies

I am trying to Post and get a cookie. I am a newbie and this is a learning project for me. My impression is that if you use 'set-cookie' one should be able to see an additional 'set-cookie' in the .toSource. (I am trying to accomplish this on Google Apps Site if that makes a difference.) Am I missing something? Here is my code:
function setGetCookies() {
var payload = {'set-cookie' : 'test'};
var opt2 = {'headers':payload, "method":"post"};
UrlFetchApp.fetch("https://sites.google.com/a/example.com/blacksmith", opt2);
var response = UrlFetchApp.fetch("https://sites.google.com/a/example.com/blacksmith")
var openId = response.getAllHeaders().toSource();
Logger.log(openId)
var AllHeaders = response.getAllHeaders();
for (var prop in AllHeaders) {
if (prop.toLowerCase() == "set-cookie") {
// if there's only one cookie, convert it into an array:
var myArray = [];
if ( Array.isArray(AllHeaders[prop]) ) {
myArray=AllHeaders[prop];
} else {
myArray[0]=AllHeaders[prop];
}
// now process the cookies
myArray.forEach(function(cookie) {
Logger.log(cookie);
});
break;
}
}
}
Thanks in advance! I referenced this to develop the code: Cookie handling in Google Apps Script - How to send cookies in header?
Open to any advice.
When you aren't logged in Google Sites won't set any cookies in the response. UrlFetchApp doesn't pass along your Google cookies, so it will behave as if you are logged out.
First the cookie you want to send whose name is 'test' does not have a value. You should send 'test=somevalue'.
Second I am wondering if you are trying to send the cookie to the googlesite server and ask it to reply with the same cookie you previously sent... ?
I am thinking you are trying to act as a HTTP server beside you are a HTTP client.
As a HTTP client your role is only to send back any cookies that the HTTP server have previously sent to you (respecting the domain, expiration... params).