Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View File

@ -0,0 +1,52 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys;
// This class is here so it re-shadows other FileSystem classes in macros,
// e.g. from hxnodejs.
@:coreApi
class FileSystem {
extern static public function exists(path:String):Bool;
extern static public function rename(path:String, newPath:String):Void;
extern static public function stat(path:String):FileStat;
extern static public function fullPath(relPath:String):String;
static public function absolutePath(relPath:String):String {
if (haxe.io.Path.isAbsolute(relPath))
return relPath;
return haxe.io.Path.join([Sys.getCwd(), relPath]);
}
extern static public function isDirectory(path:String):Bool;
extern static public function createDirectory(path:String):Void;
extern static public function deleteFile(path:String):Void;
extern static public function deleteDirectory(path:String):Void;
extern static public function readDirectory(path:String):Array<String>;
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.io;
@:coreApi
class File {
extern static public function getContent(path:String):String;
extern static public function saveContent(path:String, content:String):Void;
extern static public function getBytes(path:String):haxe.io.Bytes;
extern static public function saveBytes(path:String, bytes:haxe.io.Bytes):Void;
extern static public function read(path:String, binary:Bool = true):FileInput;
extern static public function write(path:String, binary:Bool = true):FileOutput;
extern static public function append(path:String, binary:Bool = true):FileOutput;
extern static public function update(path:String, binary:Bool = true):FileOutput;
static public function copy(srcPath:String, dstPath:String):Void {
var s = read(srcPath, true);
var d = write(dstPath, true);
d.writeInput(s);
s.close();
d.close();
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.io;
// This class is not extern because externs overriding non-externs messes with DCE
@:coreApi
class FileInput extends haxe.io.Input {
extern public override function close():Void;
extern public function eof():Bool;
extern public function seek(p:Int, pos:FileSeek):Void;
extern public function tell():Int;
extern public override function readByte():Int;
extern public override function readBytes(bytes:haxe.io.Bytes, pos:Int, len:Int):Int;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.io;
// This class is not extern because externs overriding non-externs messes with DCE
@:coreApi
class FileOutput extends haxe.io.Output {
extern public override function close():Void;
extern public override function flush():Void;
extern public function seek(p:Int, pos:FileSeek):Void;
extern public function tell():Int;
extern public override function writeByte(c:Int):Void;
extern public override function writeBytes(bytes:haxe.io.Bytes, pos:Int, len:Int):Int;
}

View File

@ -0,0 +1,133 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.io;
private extern class NativeProcess {
function new(cmd:String, ?args:Array<String>):Void;
function close():Void;
function exitCode():Int;
function getPid():Int;
function kill():Void;
function readStderr(bytes:haxe.io.Bytes, pos:Int, len:Int):Int;
function readStdout(bytes:haxe.io.Bytes, pos:Int, len:Int):Int;
function closeStdin():Void;
function writeStdin(bytes:haxe.io.Bytes, pos:Int, len:Int):Int;
}
private class Stdin extends haxe.io.Output {
var proc:NativeProcess;
var buf:haxe.io.Bytes;
public function new(proc:NativeProcess) {
this.proc = proc;
buf = haxe.io.Bytes.alloc(1);
}
public override function close() {
super.close();
proc.closeStdin();
}
public override function writeByte(c:Int) {
buf.set(0, c);
writeBytes(buf, 0, 1);
}
public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int) {
try {
return proc.writeStdin(buf, pos, len);
} catch (e:Dynamic) {
throw new haxe.io.Eof();
}
}
}
private class Stdout extends haxe.io.Input {
var proc:NativeProcess;
var out:Bool;
var buf:haxe.io.Bytes;
public function new(proc:NativeProcess, out:Bool) {
this.proc = proc;
this.out = out;
buf = haxe.io.Bytes.alloc(1);
}
public override function readByte() {
if (readBytes(buf, 0, 1) == 0)
throw haxe.io.Error.Blocked;
return buf.get(0);
}
public override function readBytes(bytes:haxe.io.Bytes, pos:Int, len:Int):Int {
try {
if (out) {
return proc.readStdout(bytes, pos, len);
} else {
return proc.readStderr(bytes, pos, len);
}
} catch (e:Dynamic) {
throw new haxe.io.Eof();
}
}
}
@:coreApi
class Process {
public var stdout(default, null):haxe.io.Input;
public var stderr(default, null):haxe.io.Input;
public var stdin(default, null):haxe.io.Output;
var proc:NativeProcess;
public function new(cmd:String, ?args:Array<String>, ?detached:Bool):Void {
if (detached) {
throw "Detached process is not supported on this platform";
}
proc = new NativeProcess(cmd, args);
stdout = new Stdout(proc, true);
stderr = new Stdout(proc, false);
stdin = new Stdin(proc);
}
public inline function getPid():Int {
return proc.getPid();
}
public function exitCode(block:Bool = true):Null<Int> {
if (block == false)
throw "Non blocking exitCode() not supported on this platform";
return proc.exitCode();
}
public inline function close():Void {
proc.close();
}
public inline function kill():Void {
proc.kill();
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.net;
class Host {
public var host(default, null):String;
public var ip(default, null):Int;
public function new(name:String) {
host = name;
init(resolve(name));
}
public function toString() {
return hostToString(ip);
}
public function reverse() {
return hostReverse(ip);
}
function init(ip:Int) {
this.ip = ip;
}
extern static public function localhost();
extern static function hostReverse(ip:Int);
extern static function hostToString(ip:Int);
extern static function resolve(name:String);
}

View File

@ -0,0 +1,191 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.net;
import haxe.io.Error;
import eval.vm.NativeSocket;
private class SocketOutput extends haxe.io.Output {
var socket:NativeSocket;
public function new(socket:NativeSocket) {
this.socket = socket;
}
public override function writeByte(c:Int) {
try {
socket.sendChar(c);
} catch (e:Dynamic) {
if (e == "Blocking")
throw Blocked;
else if (e == "EOF")
throw new haxe.io.Eof();
else
throw Custom(e);
}
}
public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int) {
return try {
socket.send(buf, pos, len);
} catch (e:Dynamic) {
if (e == "Blocking")
throw Blocked;
else
throw Custom(e);
}
}
public override function close() {
super.close();
socket.close();
}
}
private class SocketInput extends haxe.io.Input {
var socket:NativeSocket;
public function new(socket:NativeSocket) {
this.socket = socket;
}
public override function readByte() {
return try {
socket.receiveChar();
} catch (e:Dynamic) {
if (e == "Blocking")
throw Blocked;
else
throw new haxe.io.Eof();
}
}
public override function readBytes(buf:haxe.io.Bytes, pos:Int, len:Int) {
var r;
try {
r = socket.receive(buf, pos, len);
} catch (e:Dynamic) {
if (e == "Blocking")
throw Blocked;
else
throw Custom(e);
}
if (r == 0)
throw new haxe.io.Eof();
return r;
}
public override function close() {
super.close();
socket.close();
}
}
@:coreApi
class Socket {
public var input(default, null):haxe.io.Input;
public var output(default, null):haxe.io.Output;
public var custom:Dynamic;
@:ifFeature("sys.net.Socket.select") var socket:NativeSocket;
public function new() {
init(new NativeSocket());
}
private function init(socket:NativeSocket):Void {
this.socket = socket;
input = new SocketInput(socket);
output = new SocketOutput(socket);
}
public function close():Void {
socket.close();
}
public function read():String {
return input.readAll().toString();
}
public function write(content:String):Void {
output.writeString(content);
}
public function connect(host:Host, port:Int):Void {
socket.connect(host.ip, port);
}
public function listen(connections:Int):Void {
socket.listen(connections);
}
public function shutdown(read:Bool, write:Bool):Void {
socket.shutdown(read, write);
}
public function bind(host:Host, port:Int):Void {
socket.bind(host.ip, port);
}
public function accept():Socket {
var nativeSocket = socket.accept();
var socket:Socket = Type.createEmptyInstance(Socket);
socket.init(nativeSocket);
return socket;
}
@:access(sys.net.Host.init)
public function peer():{host:Host, port:Int} {
var info = socket.peer();
var host:Host = Type.createEmptyInstance(Host);
host.init(info.ip);
return {host: host, port: info.port};
}
@:access(sys.net.Host.init)
public function host():{host:Host, port:Int} {
var info = socket.host();
var host:Host = Type.createEmptyInstance(Host);
host.init(info.ip);
return {host: host, port: info.port};
}
public function setTimeout(timeout:Float):Void {
socket.setTimeout(timeout);
}
public function waitForRead():Void {
select([this], null, null, -1);
}
public function setBlocking(b:Bool):Void {} // TODO: Don't know how to implement this...
public function setFastSend(b:Bool):Void {
socket.setFastSend(b);
}
public static function select(read:Array<Socket>, write:Array<Socket>, others:Array<Socket>,
?timeout:Float):{read:Array<Socket>, write:Array<Socket>, others:Array<Socket>} {
return NativeSocket.select(read, write, others, timeout);
}
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.ssl;
import haxe.io.Bytes;
import sys.ssl.Mbedtls;
import mbedtls.X509Crt;
@:coreApi
class Certificate {
var native:X509Crt;
function new(native:X509Crt) {
this.native = native;
}
public static function loadFile(file:String):Certificate {
var cert = new X509Crt();
cert.parse_file(file);
return new Certificate(cert);
}
public static function loadPath(path:String):Certificate {
var cert = new X509Crt();
cert.parse_path(path);
return new Certificate(cert);
}
public static function fromString(str:String):Certificate {
var cert = new X509Crt();
trace(mbedtls.Error.strerror(cert.parse(Bytes.ofString(str))));
return new Certificate(cert);
}
public static function loadDefaults():Certificate {
var cert = new X509Crt();
Mbedtls.loadDefaultCertificates(cert);
return new Certificate(cert);
}
public var commonName(get, null):Null<String>;
public var altNames(get, null):Array<String>;
public var notBefore(get, null):Date;
public var notAfter(get, null):Date;
extern public function subject(field:String):Null<String>;
extern public function issuer(field:String):Null<String>;
public function next():Null<Certificate> {
var cert = native.next();
if (cert == null) {
return null;
}
return new Certificate(cert);
}
public function add(pem:String):Void {
native.parse(Bytes.ofString(pem));
}
public function addDER(der:Bytes):Void {
native.parse(der);
}
private function get_commonName():Null<String> {
return subject("CN");
}
extern private function get_altNames():Array<String>;
extern private function get_notBefore():Date;
extern private function get_notAfter():Date;
private inline function getNative():X509Crt {
return native;
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.ssl;
import haxe.io.Bytes;
import mbedtls.PkContext;
@:coreApi
class Key {
var native:PkContext;
function new() {
native = new PkContext();
}
static public function loadFile(file:String, ?isPublic:Bool, ?pass:String):Key {
var key = new Key();
var code = if (isPublic) {
key.native.parse_public_keyfile(file);
} else {
key.native.parse_keyfile(file, pass);
}
if (code != 0) {
throw(mbedtls.Error.strerror(code));
}
return key;
}
static function parse(data:Bytes, isPublic:Bool, ?pass:String):Key {
var key = new Key();
var code = if (isPublic) {
key.native.parse_public_key(data);
} else {
key.native.parse_key(data);
}
if (code != 0) {
throw(mbedtls.Error.strerror(code));
}
return key;
}
static public function readPEM(data:String, isPublic:Bool, ?pass:String):Key {
return parse(Bytes.ofString(data), isPublic, pass);
}
static public function readDER(data:haxe.io.Bytes, isPublic:Bool):Key {
return parse(data, isPublic);
}
}

View File

@ -0,0 +1,66 @@
package sys.ssl;
import eval.vm.NativeSocket;
import mbedtls.Ssl;
import mbedtls.Entropy;
import mbedtls.CtrDrbg;
import mbedtls.X509Crt;
class Mbedtls {
static var entropy:Null<Entropy>;
static var ctr:Null<CtrDrbg>;
static public function getDefaultEntropy() {
if (entropy == null) {
entropy = new Entropy();
}
return entropy;
}
static public function getDefaultCtrDrbg() {
if (ctr == null) {
ctr = new CtrDrbg();
ctr.seed(getDefaultEntropy());
}
return ctr;
}
static public function loadDefaultCertificates(certificate:X509Crt) {
if (loadDefaults(certificate) == 0) {
return;
}
var defPaths = switch (Sys.systemName()) {
case "Linux":
[
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/ssl/certs", // SLES10/SLES11
"/system/etc/security/cacerts" // Android
];
case "BSD":
[
"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
"/etc/ssl/cert.pem", // OpenBSD
"/etc/openssl/certs/ca-certificates.crt", // NetBSD
];
case "Android":
["/system/etc/security/cacerts"];
default:
[];
}
for (path in defPaths) {
if (sys.FileSystem.exists(path)) {
if (sys.FileSystem.isDirectory(path))
certificate.parse_path(path);
else
certificate.parse_file(path);
}
}
}
extern static public function setSocket(ssl:Ssl, socket:NativeSocket):Int;
extern static function loadDefaults(certificate:X509Crt):Int;
}

View File

@ -0,0 +1,206 @@
package sys.ssl;
import haxe.io.Bytes;
import eval.vm.NativeSocket;
import mbedtls.Config;
import mbedtls.Ssl;
private class SocketInput extends haxe.io.Input {
@:allow(sys.ssl.Socket) private var socket:Socket;
var readBuf:Bytes;
public function new(s:Socket) {
this.socket = s;
readBuf = Bytes.alloc(1);
}
public override function readByte() {
socket.handshake();
var r = @:privateAccess socket.ssl.read(readBuf, 0, 1);
if (r == -1)
throw haxe.io.Error.Blocked;
else if (r < 0)
throw new haxe.io.Eof();
return readBuf.get(0);
}
public override function readBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int {
if (pos < 0 || len < 0 || ((pos + len) : UInt) > (buf.length : UInt))
throw haxe.io.Error.OutsideBounds;
socket.handshake();
var r = @:privateAccess socket.ssl.read(buf, pos, len);
if (r == -1)
throw haxe.io.Error.Blocked;
else if (r <= 0)
throw new haxe.io.Eof();
return r;
}
public override function close() {
super.close();
if (socket != null)
socket.close();
}
}
private class SocketOutput extends haxe.io.Output {
@:allow(sys.ssl.Socket) private var socket:Socket;
var writeBuf:Bytes;
public function new(s:Socket) {
this.socket = s;
writeBuf = Bytes.alloc(1);
}
public override function writeByte(c:Int) {
socket.handshake();
writeBuf.set(0, c);
var r = @:privateAccess socket.ssl.write(writeBuf, 0, 1);
if (r == -1)
throw haxe.io.Error.Blocked;
else if (r < 0)
throw new haxe.io.Eof();
}
public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int {
if (pos < 0 || len < 0 || ((pos + len) : UInt) > (buf.length : UInt))
throw haxe.io.Error.OutsideBounds;
socket.handshake();
var r = @:privateAccess socket.ssl.write(buf, pos, len);
if (r == -1)
throw haxe.io.Error.Blocked;
else if (r < 0)
throw new haxe.io.Eof();
return r;
}
public override function close() {
super.close();
if (socket != null)
socket.close();
}
}
@:coreApi
class Socket extends sys.net.Socket {
public static var DEFAULT_VERIFY_CERT:Null<Bool> = true;
public static var DEFAULT_CA:Null<Certificate>;
private var conf:Config;
private var ssl:Ssl;
public var verifyCert:Null<Bool>;
private var caCert:Null<Certificate>;
private var hostname:String;
private var handshakeDone:Bool;
private var isBlocking:Bool = true;
override function init(socket:NativeSocket):Void {
this.socket = socket;
input = new SocketInput(this);
output = new SocketOutput(this);
if (DEFAULT_VERIFY_CERT && DEFAULT_CA == null) {
DEFAULT_CA = Certificate.loadDefaults();
}
verifyCert = DEFAULT_VERIFY_CERT;
caCert = DEFAULT_CA;
}
public override function connect(host:sys.net.Host, port:Int):Void {
conf = buildConfig(false);
ssl = new Ssl();
ssl.setup(conf);
Mbedtls.setSocket(ssl, socket);
handshakeDone = false;
if (hostname == null)
hostname = host.host;
if (hostname != null)
ssl.set_hostname(hostname);
socket.connect(host.ip, port);
if (isBlocking)
handshake();
}
public function handshake():Void {
if (!handshakeDone) {
var r = ssl.handshake();
if (r == 0)
handshakeDone = true;
else if (r == -1)
throw haxe.io.Error.Blocked;
else
throw mbedtls.Error.strerror(r);
}
}
override function setBlocking(b:Bool):Void {
super.setBlocking(b);
isBlocking = b;
}
public function setCA(cert:Certificate):Void {
caCert = cert;
}
public function setHostname(name:String):Void {
hostname = name;
}
public override function close():Void {
super.close();
var input:SocketInput = cast input;
var output:SocketOutput = cast output;
@:privateAccess input.socket = output.socket = null;
input.close();
output.close();
}
public override function bind(host:sys.net.Host, port:Int):Void {
conf = buildConfig(true);
socket.bind(host.ip, port);
}
public override function accept():Socket {
var c = socket.accept();
var cssl = new Ssl();
cssl.setup(conf);
Mbedtls.setSocket(cssl, c);
var s = Type.createEmptyInstance(sys.ssl.Socket);
s.socket = c;
s.ssl = cssl;
s.input = new SocketInput(s);
s.output = new SocketOutput(s);
s.handshakeDone = false;
return s;
}
public function addSNICertificate(cbServernameMatch:String->Bool, cert:Certificate, key:Key):Void {
throw new haxe.exceptions.NotImplementedException();
}
public function peerCertificate():Certificate {
return @:privateAccess new Certificate(ssl.get_peer_cert());
}
public function setCertificate(cert:Certificate, key:Key):Void {
throw new haxe.exceptions.NotImplementedException();
}
private function buildConfig(server:Bool):Config {
var conf = new Config();
conf.defaults(server ? SSL_IS_SERVER : SSL_IS_CLIENT, SSL_TRANSPORT_STREAM, SSL_PRESET_DEFAULT);
conf.rng(Mbedtls.getDefaultCtrDrbg());
if (caCert != null) {
conf.ca_chain(@:privateAccess caCert.getNative());
}
conf.authmode(if (verifyCert) SSL_VERIFY_REQUIRED else if (verifyCert == null) SSL_VERIFY_OPTIONAL else SSL_VERIFY_NONE);
return conf;
}
}

View File

@ -0,0 +1,140 @@
package sys.thread;
import eval.luv.Loop;
import eval.luv.Async;
import eval.luv.Timer as LuvTimer;
@:coreApi
enum NextEventTime {
Now;
Never;
AnyTime(time:Null<Float>);
At(time:Float);
}
abstract EventHandler(RegularEvent) from RegularEvent to RegularEvent {}
private class RegularEvent {
public var timer:Null<LuvTimer>;
public var event:()->Void;
public function new(e:()->Void) {
event = e;
}
public function run() {
event();
}
}
@:coreApi
class EventLoop {
@:allow(eval.luv.Loop)
final handle:Loop;
final mutex = new Mutex();
final oneTimeEvents = new Array<Null<()->Void>>();
var oneTimeEventsIdx = 0;
final wakeup:Async;
var promisedEventsCount = 0;
var pending:Array<()->Void> = [];
var looping = false;
public function new():Void {
handle = Loop.init().resolve();
wakeup = Async.init(handle, consumePending).resolve();
wakeup.unref();
}
public function repeat(event:()->Void, intervalMs:Int):EventHandler {
var e = new RegularEvent(event);
mutex.acquire();
pending.push(() -> {
e.timer = LuvTimer.init(handle).resolve();
e.timer.start(e.run, intervalMs, intervalMs < 1 ? 1 : intervalMs).resolve();
});
mutex.release();
wakeup.send();
return e;
}
public function cancel(eventHandler:EventHandler):Void {
mutex.acquire();
(eventHandler:RegularEvent).event = noop;
pending.push(() -> {
var timer = (eventHandler:RegularEvent).timer;
timer.stop().resolve();
timer.close(noop);
});
mutex.release();
wakeup.send();
}
static final noop = function() {}
public function promise():Void {
mutex.acquire();
++promisedEventsCount;
pending.push(refUnref);
mutex.release();
wakeup.send();
}
public function run(event:()->Void):Void {
mutex.acquire();
pending.push(event);
mutex.release();
wakeup.send();
}
public function runPromised(event:()->Void):Void {
mutex.acquire();
--promisedEventsCount;
pending.push(refUnref);
pending.push(event);
mutex.release();
wakeup.send();
}
function refUnref():Void {
if(promisedEventsCount > 0) {
wakeup.ref();
} else {
wakeup.unref();
}
}
public function progress():NextEventTime {
//TODO: throw if loop is already running
if((handle:Loop).run(NOWAIT)) {
return AnyTime(null);
} else {
return Never;
}
}
public function wait(?timeout:Float):Bool {
//TODO: throw if loop is already running
if(timeout == null) {
var timer = LuvTimer.init(handle).resolve();
timer.start(() -> {
timer.stop().resolve();
timer.close(() -> {});
}, Std.int(timeout * 1000));
return (handle:Loop).run(ONCE);
} else {
return (handle:Loop).run(ONCE);
}
}
public function loop():Void {
//TODO: throw if loop is already running
consumePending();
(handle:Loop).run(DEFAULT);
}
function consumePending(?_:Async):Void {
var p = pending;
pending = [];
for(fn in p) fn();
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.thread;
import eval.vm.NativeThread;
private typedef ThreadImpl = NativeThread;
abstract Thread(ThreadImpl) from ThreadImpl {
public var events(get,never):EventLoop;
static function __init__() {
NativeThread.self().events = new EventLoop();
}
inline function new(h:NativeThread):Void {
this = h;
}
public inline function sendMessage(msg:Dynamic):Void {
this.sendMessage(msg);
}
public static inline function current():Thread {
return new Thread(NativeThread.self());
}
public static inline function create(job:()->Void):Thread {
return new Thread(new NativeThread(job));
}
public static function runWithEventLoop(job:()->Void):Void {
var thread = NativeThread.self();
if(thread.events == null) {
thread.events = new EventLoop();
try {
job();
thread.events.loop();
thread.events = null;
} catch(e) {
thread.events = null;
throw e;
}
} else {
job();
}
}
public static inline function createWithEventLoop(job:()->Void):Thread {
return new Thread(new NativeThread(() -> {
var thread = NativeThread.self();
thread.events = new EventLoop();
job();
thread.events.loop();
}));
}
public static inline function readMessage(block:Bool):Dynamic {
return NativeThread.readMessage(block);
}
public static inline function yield():Void {
NativeThread.yield();
}
@:op(A == B)
public inline function equals(other:Thread):Bool {
return getHandle().id() == other.getHandle().id();
}
inline function getHandle():NativeThread {
return this;
}
function get_events():EventLoop {
if(this.events == null)
throw new NoEventLoopException();
return this.events;
}
@:keep
static function processEvents():Void {
NativeThread.self().events.loop();
}
}