How can I ensure the writable flag is true before send()? - websocket

I am creating an abstraction layer for Dart WebSocket who is also protocol compatible with Socket.IO, but it has a problem I can not solve.
The follow code convert the HttpRequest into a WebSocket and save the socket instance on the Transport... Here you can see I change the value of the writable flag to true in order to inform the socket is open.
WebSocketTransformer.upgrade(req).then((socket) {
this._socket = socket;
this.writable = true;
this._socket.handleError(() {
this.onClose();
});
// start listen the socket;
socket.listen((packet) {
this.onData(packet);
});
}).catchError((Exception e) {
this.onError('Can\'t conenct with the socket.', e.toString());
});
(The full code can be founded here.)
When I debug the code first the debugger stops inside that closure and only then stops here, where the check is make but writable still false :/
void flush([_]) {
if (this._readyState != SocketStates.closed && this.transport.writable &&
!this._writeBuffer.isEmpty) {
(The full code can be founded here)
I really need help...

Your constructor makes an async call but doesn't return a future (not possible in a constructor)
WebSocketTransformer.upgrade(req).then
Use a static method instead which returns Future<WebSocketTransformer> or use an init method where you initiaize your class after creation.
There might be other problems but yor code does not show how you use your class therefore its hard to tell.

Related

How do I call a javascript function from Go/WASM using Invoke that acts upon a js.Value?

I need to check for fullscreen support with my Go WASM Canvas project, before switching to fullscreen mode. I have the following code so far:
var fullscreenFunc js.Value
var fullscreenNotSupported bool
set with the following logic:
fullscreenFunc = app.Get("requestFullscreen")
if fullscreenFunc.IsUndefined() {
fullscreenFunc = app.Get("mozRequestFullScreen")
if fullscreenFunc.IsUndefined() {
fullscreenFunc = app.Get("webkitRequestFullscreen")
if fullscreenFunc.IsUndefined() {
fullscreenFunc = app.Get("msRequestFullscreen")
if fullscreenFunc.IsUndefined() {
fullscreenNotSupported = true
println("Fullscreen not supported")
}
}
}
}
I was expecting to be able to call the correct function with js.Invoke, but I see no way to tell the Invoke upon which object the call should be made. My 'app' value is being interpreted just as a param.
func Fullscreen(app js.Value) {
if fullscreenNotSupported {
return
}
fullscreenFunc.Invoke(app)
}
resulting in:
panic: JavaScript error: 'mozRequestFullScreen' called on an object that does not implement interface Element.
So am I correct in my thinking that the only way I can call the correct method, is not to store the Function, but to store a string of the function name, and then 'invoke' / 'call' it using the following approach?
app.Call(fullscreenFunctionNameString)
It feels like I misunderstood the purpose of Invoke. Is it only for js.Global() type calls?
[edit] Using 'Call', at least it seems possible to derive the function name without having to repeat the above browser specifics:
fullscreenFunctionName = fullscreenFunc.Get("name").String()
app.Call(fullscreenFunctionNameString)
It doesn't answer the question, but is probably of help to someone trying to do the same.
The arguments to invoke get turned into arguments for the javascript function it wraps. Since those fullscreen functions don't need any arguments, I think you might just need to change:
fullscreenFunc.Invoke(app)
To:
fullscreenFunc.Invoke()
...assuming app is the same JS element in both places. If not your Call solution is probably your best bet.

class instance wont save socket inside itself

Whenever a new user connects to socket.io an event handler will create a new class for that user called Events
const eventHandler = socket => {
new Events(socket);
};
and Events constructor will set its socket to the socket its been given upon creation
class Events {
constructor(socket) {
this.socket = socket;
this.socket.on('test', this.test)
}
test() {
console.log(this.socket); // logs undefined
}
}
the issue is why this.socket returns undefined? I think I'm missing how something in socket.io works, help is appreciated
I got my own answer, It actually has nothing to do with socket.io but rather how this works, further reading: How to access the correct `this` inside a callback?

How to implement message passing callbacks in an all-in-one (Edge/Firefox/Chrome) browser extension's content script?

Development Environment OS: Windows 7 Enterprise LTS
Browser compatibility minimum requirements: Should support all Edge, Firefox, Chrome browsers, as of 2018.
Current ongoing issue: Unable to run VM on dev workstation; Cannot run Windows 10 VMs to debug Microsoft Edge extensions.
To explain:
An "all-in-one browser extension" refers to a browser extension code that uses the same code with minor differences to work on various WebExtensions / Chrome Extensions supported browsers. At bare minimum, the same codebase should work and run on Edge, Firefox, and Chrome with very minor changes.
Callbacks on the content scripts for Edge/Firefox/Chrome extensions are handled differently.
For unknown reasons, I cannot run VM on my workstation machine. When VM is running, VM client is black. This is a localized issue on my end that I cannot resolve, so I'm forced to find a different solution/alternative.
How are they handled differently on the content scripts:
Edge: browser.runtime.sendMessage uses callbacks, and returns undefined.
Firefox: browser.runtime.sendMessage uses Promises, and returns a Promise.
Chrome: chrome.runtime.sendMessage uses callbacks, and returns undefined.
According to various references:
Firefox / Chrome / MS Edge extensions using chrome.* or browser.*
https://www.smashingmagazine.com/2017/04/browser-extension-edge-chrome-firefox-opera-brave-vivaldi/
On the content scripts, you can declare the following JavaScript snippet at the top in order to create a global variable that can be referenced everywhere else:
//Global "browser" namespace definition.
window.browser = (function() {
return window.msBrowser || window.browser || window.chrome;
})();
Unfortunately, because of the issue I'm experiencing (VM not running), I cannot tell if window.msBrowser is still being used. And this solution is not helpful for me when handling message callbacks when using namespace.runtime.sendMessage.
With all that said, my main question is: How to write a message passing function that can handle callbacks properly?
Currently, I'm using the following code:
function sendGlobalMessage(messageRequest, callback) {
if (chrome && window.openDatabase) {
//This is Chrome browser
chrome.runtime.sendMessage(messageRequest, callback);
}
else if (browser) {
try {
//Edge will error out because of a quirk in Edge IndexedDB implementation.
//See https://gist.github.com/nolanlawson/a841ee23436410f37168
let db = window.indexedDB.open("edge", (Math.pow(2, 30) + 1));
db.onerror = function(e) {
throw new Error("edge is found");
};
db.onsuccess = function(e) {
//This is Firefox browser.
browser.runtime.sendMessage(messageRequest).then(callback);
};
}
catch (e) {
//This is Edge browser
browser.runtime.sendMessage(messageRequest, callback);
}
}
}
I truly felt this is a hacky solution, because the code is based off of browser platform exclusive quirks in order to separate chrome.runtime.sendMessage and browser.runtime.sendMessage API calls, so as to handle callbacks in their respective platforms. I really wanted to change this.
So I'm asking what better ways are there, out there, that is useful to detect the different platforms, and handle message passing callbacks properly at the same time?
Thanks in advance.
I believed I solved it.
EDIT: The FINAL final version (updated and more stable, less message passing):
//Global "browser" namespace definition, defined as "namespace". Can be renamed to anything else.
window.namespace = (function() {
return window.browser || window.chrome;
})();
function sendGlobalResponse(message, callback){
if (window.namespace === window.chrome) {
//Chrome
window.namespace.runtime.sendMessage(message, callback);
}
else if (window.namespace === window.browser) {
//Using instanceof to check for object type, and use the returned evaluation as a truthy value.
let supportPromises = false;
try {
supportPromises = window.namespace.runtime.getPlatformInfo() instanceof Promise;
}
catch(e) { }
if (supportPromises){
//Firefox
window.namespace.runtime.sendMessage(message).then(callback);
}
else {
//Edge
window.namespace.runtime.sendMessage(message, callback);
}
}
}
(Original Post):
The final version (Now obsoleted):
//Global "browser" namespace definition.
window.namespace = (function() {
return window.browser || window.chrome;
})();
function sendGlobalResponse(message, callback){
if (window.namespace === window.chrome) {
//Chrome
window.namespace.runtime.sendMessage(message, callback);
}
else if (window.namespace === window.browser) {
let returnValue = window.namespace.runtime.sendMessage({});
if (typeof returnValue === "undefined"){
//Edge
window.namespace.runtime.sendMessage(message, callback);
}
else {
//Firefox
window.namespace.runtime.sendMessage(message).then(callback);
}
}
}
In the second if statement, by checking to see if the return value of a window.browser.runtime.sendMessage is a Promise or undefined, we can detect if the platform is Firefox or Edge.
I think this is the only solution to handle message passing callbacks/message responses on the content scripts.
I really couldn't think of a better solution than this. So I'll be using this from now on.
But if anyone else knows a better way, a way where you don't need to send out 1 extra dummy message for Firefox and Edge per function call, that would be great!
It sucks that anything inside the content script is not persistent, and even if you store information about what platform the code is being run on, you still have to fetch the information from the background script before filtering out which runtime.sendMessage function to call on, so it doesn't really save much time.

Amazon IAP Plugin for Xamarin - crash when using TaskCompletionSource

I'm trying to implement a wrapper for the Amazon IAP Plugin for Xamarin. It uses an event based system in the following way:
You can initiate method calls and listen for events. Method calls initiate requests, some of which return a response. Events are asynchronous system-generated messages that are sent in response to method calls to return the requested data to you.
See more here
My goal is to wrap this event based system into some API which allows me to use the plugin with tasks, so I can use the async-await syntax. To achieve that I'm using the TaskCompletionSource like in the following example:
public async Task<bool> GetProductInfoAsync(params string[] productIds)
{
var iapService = AmazonIapV2Impl.Instance;
var tcs = new TaskCompletionSource<bool>();
var skus = new SkusInput { Skus = productIds.ToList() };
var requestId = iapService.GetProductData(skus).RequestId;
GetProductDataResponseDelegator delegator = null;
delegator = new GetProductDataResponseDelegator(response =>
{
if(response.Id == requestId) {
var result = GetResultFromResponse(response);
tcs.SetResult(result);
//iapService.RemoveGetProductDataResponseListener(delegator.responseDelegate);
}
});
iapService.AddGetProductDataResponseListener(delegator.responseDelegate);
return await tcs.Task;
}
This code seems to work fine if the method gets called once, but if it gets called two times in a row the app crashes immediately and the only thing printed to the console is the following message..
[mono] Unhandled Exception:
[mono] System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
..which kinda makes no sense at all.
So is there something obvious I'm missing here? Or could it be a bug from the plugin?
I have created a repository with the code above so you can reproduce the problem. It's my playground, so please ignore the whole structure of the project and just focus on the classes AmazonIAPService and MainActivity.
Hint 1:
The commented line //iapService.RemoveGetProductDataResponseListener(delegator.responseDelegate); causes also a crash with the same message but already at the first call of the method.
Hint 2:
The AmazonIAPService contains a commented method which uses await Task.Delay(TimeSpan.FromMilliseconds(1)) and solves the problem from above in a very hacky way which I really don't like.
Problem seems to be that those functions have to run asynchronously. Also mentioned here in the doc. So once you run those functions synchronously somehow they throw exception, i dont what is happening in the library but your hacky solution is the actual solution for that. If you write the function as below. it also works.
PurchaseResponseDelegator delegator = null;
delegator = new PurchaseResponseDelegator(async response =>
{
await Task.Run(() =>
{
if (response.RequestId == requestId)
{
var result = GetPurchaseEventHandler(response);
var sucess = taskCompletionSource.TrySetResult(result);
context.RemovePurchaseResponseListener(delegator.responseDelegate);
}
} );
});
// Register for an event
context.AddPurchaseResponseListener(delegator.responseDelegate);
One other exception I had despite the async-await solution, somehow, it always throws exception for the line taskCompletionSource.SetResult(result); for PurchaseUpdates functions only. if i use instead this line var sucess = taskCompletionSource.TrySetResult(result); it works fine

exit() method entered without exit command

I have Processing 3 code that is exhibiting some odd behavior. I have a void exit() method defined that is being executed at random times without the user actually telling the code to exit. Here is the method:
void exit()
{
println("clearing buffer and closing file");
if (output != null) {
print("output is not null");
try {
output.close();
}
catch (IOException e) {
println("Error while closing the writer");
}
}
super.exit();
}
As you can see, the only thing that it does is attempt to close a buffered writer called output. Flushing this writer is not critical, so for now I am just removing it from my sketch. But long term, I am curious how this can be happening. Nowhere else in my code is the exit method explicitly called. IE, the code cannot decide to exit. It is only when the user closes the problem using the X.
Note: I cannot upload the entire code this method is attached too because it is too long. I think perhaps a better way to phrase my questions would be something like:
"Hi, I am a noob that doesn't know anything about the exit method. Is there anyway that this method could somehow get called without me explicitly calling it or hitting the exit button?"
Add this at the beginning of your exit() method.
new Exception().printStackTrace();
The resulting stacktrace should allow you to figure out what is calling your exit() method.
Or if you can't tweak the code, you can run the application using a debugger and set a breakpoint at the start of the exit() method.
To answer your question about whether it is possible, the answer depends on what you mean by "without me explicitly calling". There are various ways to call a method, some of which are quite obscure; e.g.
You can use reflection to get the Method object for the exit method from the declaring class, and then call invoke(...) on it.
You can call a Java method from native code via the JNI or JNA apis.
You can generate Java source code that contains an exit() call, compile it, load it, and run it.
You can insert an exit() call into an "innocent" method using BCEL or similar.
And ...
If there is a debug agent attached to the JVM, the debugger can call exit() on some thread in the JVM.
In short, the answer to your question is Yes.
Your method could be found and invoked dynamically using reflection by any class in the same classloader or any other that is below in the hierarchy.
Also, it has a default access. So it could be invoked statically by any class in the same package.
+1 for #Andres, reflection is one possibility.
Have you tried using a breakpoint on the method and looking at the thread's stacktrace?
Personally I don't use breakpoints (just my style) and would try and look at the thread programmatically. Maybe some of the following code can help you look at the thread and get an idea of what's going on:
public class ThreadUtil {
/** Blocked constructor **/
private ThreadUtil() {
}
/**
* Get the stackstrace of the current {#link Thread}.
* The stacktrace will be returned in the form of a string.
*/
public static String getStackTrace() {
return getStackTrace(Thread.currentThread());
}
/**
* Get the stackstrace of a {#link Thread}.
* The stacktrace will be returned in the form of a string.
*/
public static String getStackTrace(Thread thread) {
StringBuilder sb = new StringBuilder();
StackTraceElement[] currThreadStackTraceElementList = thread.getStackTrace();
appendStackTrace(sb, currThreadStackTraceElementList);
return sb.toString();
}
public static String getAllStackTraces() {
StringBuilder sb = new StringBuilder();
Map<Thread, StackTraceElement[]> threadList = Thread.getAllStackTraces();
for (StackTraceElement[] currThreadStackTraceElementList : threadList.values()) {
appendStackTrace(sb, currThreadStackTraceElementList);
}
return sb.toString();
}
private static void appendStackTrace(StringBuilder sb,
StackTraceElement[] currThreadStackTraceElementList) {
sb.append("Thread stack trace: \n");
for (StackTraceElement currThreadStackTraceElement : currThreadStackTraceElementList) {
sb.append("\t" + currThreadStackTraceElement + "\n");
}
sb.append("\n");
}
}
It's a Processing-specific thing.
void exit() is a method already defined by processing in PApplet.java
As explained in the reference:
Rather than terminating immediately, exit() will cause the sketch to
exit after draw() has completed (or after setup() completes if called
during the setup() function).
For Java programmers, this is not the same as System.exit(). Further,
System.exit() should not be used because closing out an application
while draw() is running may cause a crash (particularly with P3D).
exit() it is expected to be used something like this:
void draw() {
line(mouseX, mouseY, 50, 50);
}
void mousePressed() {
exit();
}
It is called within PApplet.java in a few places, notably in handleKeyEvent to close the sketch when ESC is pressed, or when ⌘w is pressed.
Just rename your method to something other than exit()

Resources