URLLoader fails randomly without throwing an error or dispatching any events - apache-flex

In Adobe AIR 1.5, I'm using URLLoader to upload a video in 1 MB chunks. It uploads 1 MB, waits for the Event.COMPLETE event, and then uploads the next chunk. The server-side code knows how to construct the video from these chunks.
Usually, it works fine. However, sometimes it just stops without throwing any errors or dispatching any events. This is an example of what is shown in a log that I create:
Uploading chunk of size: 1000000
HTTP_RESPONSE_STATUS dispatched: 200
HTTP_STATUS dispatched: 200
Completed chunk 1 of 108
Uploading chunk of size: 1000000
HTTP_RESPONSE_STATUS ...
etc...
Most of the time, it completes all of the chunks fine. However, sometimes, it just fails in the middle:
Completed chunk 2 of 108
Uploading chunk of size: 1000000
... and nothing else, and no network activity.
Through debugging, I can tell that it does successfully call urlLoader.load(). When it fails, it just seems to stall, calling load(), and then calling the UIComponent's callLaterDispatcher() and then nothing.
Does anyone have any idea why this could be happening? I'm setting up my URLLoader like this:
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener(Event.COMPLETE, chunkComplete);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
urlLoader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, responseStatusHandler);
urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, statusHandler);
urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
And I'm re-using it for each chunk. No events get called when it doesn't succeed, and urlLoader.load() doesn't throw any exceptions. When it succeeds, HTTP_RESPONSE_STATUS, HTTP_STATUS, and PROGRESS events are dispatched.
Thanks!
Edit: One thing that might be helpful is that, we have the same upload functionality implemented in .NET. In .NET, the request.GetResponse() method sometimes throws an exception, complaining that the connection was closed unexpectedly. We catch the exception if this happens, and try that chunk again, until it succeeds. I'm looking to implement something similar here, but there are no exceptions being thrown or error events being dispatched.
More detailed code example below. The URLLoader is setup as described above. The readAgain variable just makes it skip reading a new set of bytes in the file stream (ie: it tries to send the old one again) ... however, it never catches any exceptions, because none are ever thrown.
private function uploadSegment():void
{
.... prepare byte array, setup url ...
// Create a URL request
var urlRequest:URLRequest = new URLRequest();
urlRequest.url = _url + "?" + paramStr;
urlRequest.method = URLRequestMethod.POST;
urlRequest.data = byteArray;
urlRequest.useCache = false;
urlRequest.requestHeaders.push(new URLRequestHeader('Cache-Control', 'no-cache'));
try
{
urlLoader.load(urlRequest);
}
catch (e:Error)
{
Logger.error("Failed to upload chunk. Caught exception. Trying again.");
readAgain = true;
uploadSegment();
return;
}
readAgain = false;
}

Have you tried signing up for 'Event.OPEN' to see if the connection is opening correctly? If you're doing this per chunk - perhaps that event or lack thereof would help?
[Edit]
Can you also try setting useCache to false on your URLRequest?
[Edit]
I assume you're urlLoader is globally referenced... If not, while you're waiting for async behavior, something evil like GC might hurt you ... But - skipping that, if you call 'bytesTotal' while you're waiting for something to happen - does it always return zero?
[More]
Also - check the URL in the cases where NOTHING happens - because online I've found some mention that if the server is unreachable there are no events fired (though there is some argument around that)...

I encountered a similar problem in Flex, only with Safari.
The URLloader sometimes returned nothing, not even the OPEN event.
I made sure that this wasn't a cache problem.
After lots of trial
and error, the only remedy I found was to use https protocol in the url. I am not sure what this does to
Safari, but now the problem is gone.

Related

Google reCAPTCHA response success: false, no error codes

UPDATE: Google has recently updated their error message with an additional error code possibility: "timeout-or-duplicate".
This new error code seems to cover 99% of our previously mentioned mysterious
cases.
We are still left wondering why we get that many validation requests that are either timeouts or duplicates. Determinining this with certainty is likely to be impossible, but now I am just hoping that someone else has experienced something like it.
Disclaimer: I cross posted this to Google Groups, so apologies for spamming the ether for the ones of you who frequent both sites.
I am currently working on a page as part of a ASP.Net MVC application with a form that uses reCAPTCHA validation. The page currently has many daily users.
In my server side validation** of a reCAPTCHA response, for a while now, I have seen the case of the reCAPTCHA response having its success property set to false, but with an accompanying empty error code array.
Most of the requests pass validation, but some keep exhibiting this pattern.
So after doing some research online, I explored the two possible scenarios I could think of:
The validation has timed out and is no longer valid.
The user has already been validated using the response value, so they are rejected the second time.
After collecting data for a while, I have found that all cases of "Success: false, error codes: []" have either had the validation be rather old (ranging from 5 minutes to 10 days(!)), or it has been a case of a re-used response value, or sometimes a combination of the two.
Even after implementing client side prevention of double-clicking my submit-form button, a lot of double submits still seem to get through to the server side Google reCAPTCHA validation logic.
My data tells me that 1.6% (28) of all requests (1760) have failed with at least one of the above scenarios being true ("timeout" or "double submission").
Meanwhile, not a single request of the 1760 has failed where the error code array was not empty.
I just have a hard time imagining a practical use case where a ChallengeTimeStamp gets issued, and then after 10 days validation is attempted, server side.
My question is:
What could be the reason for a non-negligible percentage of all Google reCAPTCHA server side validation attempts to be either very old or a case of double submission?
**By "server side validation" I mean logic that looks like this:
public bool IsVerifiedUser(string captchaResponse, string endUserIp)
{
string apiUrl = ConfigurationManager.AppSettings["Google_Captcha_API"];
string secret = ConfigurationManager.AppSettings["Google_Captcha_SecretKey"];
using (var client = new HttpClient())
{
var parameters = new Dictionary<string, string>
{
{ "secret", secret },
{ "response", captchaResponse },
{ "remoteip", endUserIp },
};
var content = new FormUrlEncodedContent(parameters);
var response = client.PostAsync(apiUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
GoogleCaptchaResponse googleCaptchaResponse = JsonConvert.DeserializeObject<GoogleCaptchaResponse>(responseContent);
if (googleCaptchaResponse.Success)
{
_dal.LogGoogleRecaptchaResponse(endUserIp, captchaResponse);
return true;
}
else
{
//Actual code ommitted
//Try to determine the cause of failure
//Look at googleCaptchaResponse.ErrorCodes array (this has been empty in all of the 28 cases of "success: false")
//Measure time between googleCaptchaResponse.ChallengeTimeStamp (which is UTC) and DateTime.UtcNow
//Check reCAPTCHAresponse against local database of previously used reCAPTCHAresponses to detect cases of double submission
return false;
}
}
}
Thank you in advance to anyone who has a clue and can perhaps shed some light on the subject.
You will get timeout-or-duplicate problem if your captcha is validated twice.
Save logs in a file in append mode and check if you are validating a Captcha twice.
Here is an example
$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secret.'&response='.$_POST['g-recaptcha-response'])
file_put_contents( "logfile", $verifyResponse, FILE_APPEND );
Now read the content of logfile created above and check if captcha is verified twice
This is an interesting question, but it's going to be impossible to answer with any sort of certainly. I can give an educated guess about what's occurring.
As far as the old submissions go, that could simply be users leaving the page open in the browser and coming back later to finally submit. You can handle this scenario in a few different ways:
Set a meta refresh for the page, such that it will update itself after a defined period of time, and hopefully either get a new ReCAPTCHA validation code or at least prompt the user to verify the CAPTCHA again. However, this is less than ideal as it increases requests to your server and will blow out any work the user has done on the form. It's also very brute-force: it will simply refresh after a certain amount of time, regardless of whether the user is currently actively using the page or not.
Use a JavaScript timer to notify the user about the page timing out and then refresh. This is like #1, but with much more finesse. You can pop a warning dialog telling the user that they've left the page sitting too long and it will soon need to be refreshed, giving them time to finish up if they're actively using it. You can also check for user activity via events like onmousemove. If the user's not moving the mouse, it's very likely they aren't on the page.
Handle it server-side, by catching this scenario. I actually prefer this method the most as it's the most fluid, and honestly the easiest to achieve. When you get back success: false with no error codes, simply send the user back to the page, as if they had made a validation error in the form. Provide a message telling them that their CAPTCHA validation expired and they need to verify again. Then, all they have to do is verify and resubmit.
The double-submit issue is a perennial one that plagues all web developers. User behavior studies have shown that the vast majority occur because users have been trained to double-click icons, and as a result, think they need to double-click submit buttons as well. Some of it is impatience if something doesn't happen immediately on click. Regardless, the best thing you can do is implement JavaScript that disables the button on click, preventing a second click.

Memory leak while sending response from rebus handler

I saw a very strange behavior in my rebus handler which is self hosted in exe. Right after sending response using bus.send method it adds up some memory consumed by process. I tried to look up object graph using memory profile and found that rebus is holding response message in serialized format somewhere.
Object graph was showing below hierarchy to the root.
System.Message --> CachedBodyMessage --> stream
Give me some pointers if anybody is aware of this thing.
I understand that a memory leak is a grave concern, but my belief is that it is unlikely that Rebus should contain a memory leak.
This belief is rooted in the fact that I have been running Windows Service-hosted Rebus endpoints in production for 1,5 years now, and several of them (e.g. the timeout managers) have sometimes been running for several months without being restarted.
I'd like to be absolutely bulletproof sure though, so I'm willing to investigate the issue you're reporting.
You're mentioning "CachedBodyMessage" - judging by the names of fields inside System.Messaging.Message, it sounds like it's something within MSMQ. To try to reproduce your issue, I coded the following test:
[Test, Ignore("Only works in RELEASE mode because otherwise object references are held on to for the duration of the method")]
public void DoesNotLeakMessages()
{
// arrange
const string inputQueueName = "test.leak.input";
var queue = new MsmqMessageQueue(inputQueueName);
disposables.Add(queue);
var body = Encoding.UTF8.GetBytes(new string('*', 32768));
var message = new TransportMessageToSend
{
Headers = new Dictionary<string, object> { { Headers.MessageId, "msg-1" } },
Body = body
};
var weakMessageRef = new WeakReference(message);
var weakBodyRef = new WeakReference(body);
// act
queue.Send(inputQueueName, message, new NoTransaction());
message = null;
body = null;
GC.Collect();
GC.WaitForPendingFinalizers();
// assert
Assert.That(weakMessageRef.IsAlive, Is.False, "Expected the message to have been collected");
Assert.That(weakBodyRef.IsAlive, Is.False, "Expected the body bytes to have been collected");
}
which verifies that the sent transport message is collected as it should (will only do this in RELEASE mode though, because of the way DEBUG mode holds on to object references within scope)
I'll try and run the TimePrinter sample now and leave it running for a while to see if I can reproduce the issue. If you stumble upon more information about e.g. exactly which objects are leaking, it would be very helpful.
Thanks again for taking the time to report your worries to me :)
Followup:
I've modified the TimePrinter sample so that it sends 50 msg/s and includes a 64 KB random string payload with each message, and I've tracked the memory usage for almost four hours now. As you can see, it does not look like memory is being leaked.
I'll leave it running the rest of the day, just to be sure.
Maybe you can tell me some more about why you suspected there was a memory leak in the first place?
Update:
As you can see from the trace, it has now been running for 7 hours and thus more than 1,200,000 messages containing more than 70 GB of data has been sent and consumed by the same process. If cached message bodies were leaking, I am pretty sure that we would have been able to see something rising on the graph.

Loading Sound gives exception on Sound.id3

When loading a MP3 to a flash.media.Sound object the id3 property gives an error:
SecurityError: Error #2000: No active security context.
Offcourse, like many errors in Flex, the Flex documentation doesn't mention a thing about this, except that it exists...
The MP3 is valid (i've checked it with MediaPlayer and iTunes), the Sound object is in a good state (bytesTotal and bytesLoaded both reflect the correct amount of bytes).
Has anyone had this problem too? Any solutions or suggestions?
Your MP3 should be fine.
If you want to access more data about your mp3 file, rather than just play, you will need a policy file that allows it. Similar to loading an image, if you just add it to the display it and don't access the pixels, it's all good, but if you want to access the pixels you should have permission(a crossdomain xml).
For images, when you call the load image, you can pass a LoaderContext in which you explicitly say you want to check for a crossdomain.xml file and get access to the content.
Similarly you should create a SoundLoaderContext with the second parameter set to true(to check) and use that in the sound load call.
e.g.
var snd:Sound = new Sound();
var req:URLRequest = new URLRequest("yourSound.mp3");
var context:SoundLoaderContext = new SoundLoaderContext(0, true);
snd.load(req, context);
snd.play();
For ID3 data you should listen for the ID3 event:
sound.addEventListener(Event.ID3, onID3);
function onID3(event:Event) {
for(var i in sound.id3)
trace('prop: ' + i + ' value: ' + sound.id3[i]);
}
For more info, you might find the mp3infoutil library handy.
HTH,
George

as3 to .net, not receiving Event.COMPLETE callback

I created an image uploader for an app I am working on. I first used php for the server side script, and everything worked fine. I found out afterwards I had to use .net, so I created new serverside scripts. The problem I am having is that my event.COMPLETE listener is never firing. I can receive data back using a DATAEVENT listener, but then it stops at this error:
Error #2044: Unhandled IOErrorEvent:. text=Error #2036: Load Never Completed.
Here is how I am sending my file.
var fileRefReq:URLRequest = new URLRequest(FILE_UPLOAD_TEMP);
var fileReqVars:URLVariables = new URLVariables();
fileReqVars.subdir = "Temp";
fileRefReq.data = fileReqVars;
fileRefReq.method = URLRequestMethod.POST;
fileRef.upload(fileRefReq);
The file definitely gets uploaded to the first TEMP directory, but then it breaks with the above error.
Has anyone else had a similar problem or point me in the right direction for solving this?
This is an error produced by Flash. The most common causes are:
It could be a 404 Error you are getting somewhere in the Flash.
This error can occur if you close the browser while it is loading something.
By default, the calling SWF file and the URL you load must be in the same domain. For example, a SWF file at www.adobe.com can load data only from sources that are also at www.adobe.com. To load data from a different domain, place a URL policy file on the server hosting the data.
Number 3 is important because a common user problem with Flash is security issues - so it is just something to rule out. Most likely not the cause here.
I would test for these 3 causes and read over the URLRequest: http://livedocs.adobe.com/flex/3/langref/flash/net/URLRequest.html
After some additional thought I think it is timing out but that is just a theory. Add an event listener like so:
urlLoader.addEventListener("httpResponseStatus", function(event:HTTPStatusEvent):void
to see what is actually happening.
You have to handle the event such as:
// add the event listener
urlLoader.addEventListener( IOErrorEvent.IO_ERROR, onErrorHandler );
// handle the error event like this:
private function onErrorHandler( e: IOErrorEvent ): void {
trace( "An io error occurred." );
}
Hope that helps

Blackberry JDE HTTPConnection problems

So, I'm using the HTTPConnection Class, like so:
HttpConnection c =
(HttpConnection)Connector.open("http://147.117.66.165:8000/eggs.3gp");
Following what LOOKS like the right way to do things in the Blackberry JDE API.
However, my code crashes if I try to do just about anything with the variable 'c'.
.getType()
.getInputStream()
.getStatus()
all cause it to crash.
I can, however get the URL from it, and I can look at the variable 'c' itself to know that it did, in fact, get created.
Did I manage to create a broken Connection? Do I need to do something else to actually do things with the connection? Under what circumanstances will this happen (I know the link is good, I can use the blackberry's browser to visit it).
Am I just using HttpConnection wrong? How would I do things correctly?
What error is it throwing when it crashes? You may want to try adding the "Connector.READ_WRITE" as a second argument to your open call - even if it's just a "read only" connection like a GET, some OSes such as 4.6 will throw an exception unless you open it in read/write mode.
I figured out what was wrong by finding some sample code that was using HttpConnection, (at least, I think I did, at least, I can access all those variables, now). Before, I wasn't ever casting it as a "Stream Connection" (the examples I saw had it cast from Connector to HTTPConnection).
StreamConnection s = null;
s = (StreamConnection)Connector.open("http://10.252.9.15/eggs.3gp");
HttpConnection c = (HttpConnection)s;
InputStream i = c.openInputStream();
System.out.println("~~~~~I have a connection?~~~~~~" + c);
System.out.println("~~~~~I have a URL?~~~~" + c.getURL());
System.out.println("~~~~~I have a type?~~~~" + c.getType());
System.out.println("~~~~~I have a status?~~~~~~" + c.getResponseCode());
System.out.println("~~~~~I have a stream?~~~~~~" + i);
player = Manager.createPlayer(i, c.getType());
Even though the stream is now successfully being created, I'm still having problems USING it, but that might be because my connection is so slow.
The API documentation for HttpConnection suggests the first call should be to c.getResponseCode(), try that.
You should find everything you need in my blog post "An HttpRequest and HttpResponse library for BB OS5+"
And for invoking media within your application you can do either a browser invokation or directly from app. You would probably be best to use the browser like so:
BrowserSession invokeHighQuality = Browser.getDefaultSession();
invokeHighQuality.displayPage("URL goes here");
OR you can try this:
// CHAPI invocation
Invocation invoke = new Invocation(_data.getUrl(), null, BlackBerryContentHandler.ID_MEDIA_CONTENT_HANDLER, false,
null);
try {
Registry.getRegistry(YourAppClass.class.getName()).invoke(invoke);
} catch (Throwable t) {
}

Resources