Skip to content

Commit

Permalink
Add URLLoader.close
Browse files Browse the repository at this point in the history
  • Loading branch information
hughsando committed Sep 21, 2024
1 parent 27e7d44 commit a6ce918
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 62 deletions.
15 changes: 15 additions & 0 deletions acadnme/src/Acadnme.hx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import nme.ui.Scale;
import nme.utils.Float32Array;
import nme.utils.UInt8Array;
import nme.events.KeyboardEvent;
import nme.utils.ByteArray;
import AllNme;
import Sys;

Expand Down Expand Up @@ -238,6 +239,13 @@ class Acadnme extends Sprite implements IScriptHandler
}
}

public function runBytes(bytes:ByteArray)
{
clearBoot();
trace("Run bytes " + bytes.length);
nme.script.Nme.runBytes(bytes);
}

public function runBoot()
{
if (nme.Assets.hasBytes("AcadnmeBoot.nme"))
Expand All @@ -262,6 +270,13 @@ class Acadnme extends Sprite implements IScriptHandler
instance.run(inScript);
}

@:keep // Used by boot
public static function runScriptBytes(inScript:ByteArray)
{
instance.runBytes(inScript);
}


@:keep // Used by boot
public static function getEngines() : Array< {name:String, version:String} >
{
Expand Down
1 change: 1 addition & 0 deletions include.nmml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

<haxedef name="nme_api_level=611"/>

<!-- you can 'unset' this if needed -->
<haxedef name="no_haxe_http" if="wasm" />

<section if="NME_HXTELEMETRY || telemetry">
Expand Down
1 change: 1 addition & 0 deletions project/include/URL.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class URLLoader : public Object

virtual ~URLLoader() { };
virtual URLState getState()=0;
virtual void close()=0;
virtual int bytesLoaded()=0;
virtual int bytesTotal()=0;
virtual int getHttpCode()=0;
Expand Down
26 changes: 20 additions & 6 deletions project/src/common/CURL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ class CURLLoader : public URLLoader
return ((CURLLoader *)userdata)->ReadFunc(ptr,size,nmemb);
}

void close()
{
}

void SetPutBuffer(const unsigned char *inBuffer, size_t inLen)
{
mPutBuffer = new unsigned char[inLen];
Expand All @@ -225,18 +229,28 @@ class CURLLoader : public URLLoader
processMultiMessages();
}

~CURLLoader()
void close()
{
delete [] mPutBuffer;
curl_easy_cleanup(mHandle);
sLoaders--;
if (sLoaders==0)
mPutBuffer = nullptr;
if (mHandle)
{
curl_multi_cleanup(sCurlM);
sCurlM = 0;
curl_easy_cleanup(mHandle);
mHandle = nullptr;
sLoaders--;
if (sLoaders==0)
{
curl_multi_cleanup(sCurlM);
sCurlM = 0;
}
}
}

~CURLLoader()
{
close();
}

size_t onData( void *inBuffer, size_t inItemSize, size_t inItems)
{
size_t size = inItemSize*inItems;
Expand Down
13 changes: 13 additions & 0 deletions project/src/common/ExternalInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5570,6 +5570,19 @@ value nme_curl_create(value inURLRequest)
}
DEFINE_PRIM(nme_curl_create,1);

value nme_curl_close(value inLoader)
{
#ifdef NME_CURL
URLLoader *loader;
if (AbstractToObject(inLoader,loader))
{
loader->close();
}
#endif
return alloc_null();
}
DEFINE_PRIM(nme_curl_close,1);


value nme_curl_process_loaders()
{
Expand Down
1 change: 1 addition & 0 deletions project/src/emscripten/CurlFetch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class CurlFetch : public URLLoader
close();
}


void onSuccess()
{
if (fetch)
Expand Down
60 changes: 59 additions & 1 deletion samples/AcadnmeBoot/src/AcadnmeBoot.hx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import gm2d.skin.Shape;
import gm2d.skin.Skin;
import gm2d.svg.Svg;
import gm2d.svg.SvgRenderer;
import gm2d.Game;
import sys.FileSystem;
import nme.net.SharedObject;
import nme.net.*;
import nme.events.*;
import sys.io.File;

using StringTools;
Expand Down Expand Up @@ -118,9 +120,65 @@ class AcadnmeBoot extends Screen implements IBoot
if (isWeb)
{
var q = nme.Lib.getWebpageParam("prog");
if (q!=null && q!="")
downloadAndRun(q);
}
}

function downloadAndRun(url:String)
{
var loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;

var status:String = null;
var progress = ProgressDialog.create("Download", url, status, 100.0, () -> {
if (loader!=null)
{
loader = null;
}
} );
progress.show(true,false);
loader.addEventListener( Event.COMPLETE, (_) -> {
Game.closeDialog();
if (loader!=null)
{
var bytes:ByteArray = loader.data;
if (bytes==null)
warn("Error Loading Data","No data.");
else
Acadnme.runScriptBytes(bytes);
}
});
var lastPct = 0;
loader.addEventListener(ProgressEvent.PROGRESS, (p) -> {
var pct = Std.int( 100 * p.bytesLoaded / Math.max(1,p.bytesTotal) );
if (pct!=lastPct)
{
lastPct = pct;
progress.update(pct);
}
} );
loader.addEventListener(IOErrorEvent.IO_ERROR, (e) -> {
Game.closeDialog();
warn("Error Loading Data", "Error: " + e.text );
} );

var req = new URLRequest(url);
req.preferHaxeHttp = true;
loader.load(req);
}

public function warn(title:String, message:String)
{
var panel = new Panel(title);
//Sys.println("Warning:" + message);
panel.addLabel(message);
panel.addTextButton("Ok", Game.closeDialog );
var dlg = new gm2d.ui.Dialog(panel.getPane());
Game.doShowDialog(dlg,true);
}


function onEnable(inValue:Bool)
{
serverEnabled = inValue;
Expand Down
129 changes: 79 additions & 50 deletions src/nme/net/HttpLoader.hx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ private class OutputWatcher extends haxe.io.BytesOutput
override public function prepare(nbytes:Int)
{
super.prepare(nbytes);
loader.checkClosed();
loader.onBytesTotal(nbytes);
}

override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int
{
loader.checkClosed();
var result = super.writeBytes(buf, pos, len);
loader.onBytesLoaded(b.length);
return result;
Expand All @@ -54,6 +56,7 @@ class HttpLoader
var errorMessage:String;
var code:Int;
var cookies:Array<String>;
var closed:Bool;

var byteData:ByteArray;
var stringData:String;
Expand All @@ -62,6 +65,9 @@ class HttpLoader
public var bytesTotal(default,null):Int;
public var state(default,null):Int;
var http:Http;
#if !js
var output:OutputWatcher;
#end

public function new(inLoader:URLLoader, inRequest:URLRequest)
{
Expand All @@ -71,6 +77,7 @@ class HttpLoader
bytesTotal = 0;
state = URLLoader.urlLoading;
code = 0;
closed = false;

http = new Http(inRequest.url);
http.onError = onError;
Expand All @@ -86,81 +93,103 @@ class HttpLoader
if (isPost)
http.setPostBytes(urlRequest.nmeBytes);

#if !js
#if wasm
run();
#elseif !js
runAsync(run);
#end
}

#if !js
public function run()
public function checkClosed()
{
var output = new OutputWatcher(this);
if (closed)
throw "closed by client";
}

var isPost = urlRequest.method==URLRequestMethod.POST;
http.customRequest(isPost, output);
public function close()
{
state = URLLoader.urlClosed;
closed = true;
}

if (state!=URLLoader.urlError)
#if !js
public function run()
{
try
{
var bytes = output.getBytes();
var output = new OutputWatcher(this);

bytesLoaded = bytesTotal = bytes.length;
var isPost = urlRequest.method==URLRequestMethod.POST;
http.customRequest(isPost, output);

var encoding = http.responseHeaders.get("Content-Encoding");
if (encoding=="gzip")
if (state!=URLLoader.urlError)
{
var decoded = false;
try
var bytes = output.getBytes();

bytesLoaded = bytesTotal = bytes.length;

var encoding = http.responseHeaders.get("Content-Encoding");
if (encoding=="gzip")
{
if (bytes.length>10 && bytes.get(0)==0x1f && bytes.get(1)==0x8b)
var decoded = false;
try
{
var u = new haxe.zip.Uncompress(15|32);
var tmp = haxe.io.Bytes.alloc(1<<16);
u.setFlushMode(haxe.zip.FlushMode.SYNC);
var b = new haxe.io.BytesBuffer();
var pos = 0;
while (true) {
var r = u.execute(bytes, pos, tmp, 0);
b.addBytes(tmp, 0, r.write);
pos += r.read;
if (r.done)
break;
if (bytes.length>10 && bytes.get(0)==0x1f && bytes.get(1)==0x8b)
{
var u = new haxe.zip.Uncompress(15|32);
var tmp = haxe.io.Bytes.alloc(1<<16);
u.setFlushMode(haxe.zip.FlushMode.SYNC);
var b = new haxe.io.BytesBuffer();
var pos = 0;
while (true) {
var r = u.execute(bytes, pos, tmp, 0);
b.addBytes(tmp, 0, r.write);
pos += r.read;
if (r.done)
break;
}
u.close();
bytes = b.getBytes();
decoded = bytes!=null;
}
u.close();
bytes = b.getBytes();
decoded = bytes!=null;
}
catch(e:Dynamic)
{
trace(e);
}

if (!decoded)
onError("Bad GZip data");
}
catch(e:Dynamic)

if (urlLoader.dataFormat== URLLoaderDataFormat.BINARY)
{
trace(e);
byteData = ByteArray.fromBytes(bytes);
}
else
{
#if neko
stringData = neko.Lib.stringReference(bytes);
#else
#if haxe4
stringData = bytes.getString(0, bytes.length, UTF8);
#else
stringData = bytes.getString(0, bytes.length);
#end
#end
}

if (!decoded)
onError("Bad GZip data");
}

if (urlLoader.dataFormat== URLLoaderDataFormat.BINARY)
{
byteData = ByteArray.fromBytes(bytes);
state = URLLoader.urlComplete;
}
else
{
#if neko
stringData = neko.Lib.stringReference(bytes);
#else
#if haxe4
stringData = bytes.getString(0, bytes.length, UTF8);
#else
stringData = bytes.getString(0, bytes.length);
#end
#end
//trace(" -> error");
}

state = URLLoader.urlComplete;
}
else
catch(e:Dynamic)
{
//trace(" -> error");
if (!closed)
onError(""+e);
}
}
#end
Expand Down
Loading

0 comments on commit a6ce918

Please sign in to comment.