Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 39 additions & 42 deletions src/macro/eval/evalStdLib.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*)
open Extlib_leftovers
open Globals
open EvalArray
open EvalValue
open EvalEncode
open EvalDecode
Expand Down Expand Up @@ -761,6 +762,30 @@ module StdDeque = struct
)
end

module StdDns = struct

let localhost = vfun0 (fun () ->
let hostname = catch_unix_error Unix.gethostname() in
create_unknown hostname
)

let reverse_sync = vfun1 (fun ip_str ->
let ip_str = decode_string ip_str in
let addr = catch_unix_error Unix.inet_addr_of_string ip_str in
try
let host_entry = catch_unix_error Unix.gethostbyaddr addr in
create_unknown host_entry.h_name
with Not_found -> exc_string (Printf.sprintf "Could not reverse lookup host %s" ip_str)
)

let resolve_sync = vfun1 (fun hostname ->
let hostname = decode_string hostname in
let host_entry = try Unix.gethostbyname hostname with Not_found -> exc_string (Printf.sprintf "Could not resolve host %s" hostname) in
let addresses_str = Array.map (fun addr -> create_unknown (catch_unix_error Unix.string_of_inet_addr addr)) host_entry.h_addr_list in
VArray (create addresses_str)
)
end

module StdEReg = struct
open Pcre2

Expand Down Expand Up @@ -1382,35 +1407,6 @@ module StdGc = struct
let stat = vfun0 (fun () -> encode_stats (Gc.stat()))
end

module StdHost = struct
let int32_addr h =
let base = Int32.to_int (Int32.logand h 0xFFFFFFl) in
let str = Printf.sprintf "%ld.%d.%d.%d" (Int32.shift_right_logical h 24) (base lsr 16) ((base lsr 8) land 0xFF) (base land 0xFF) in
catch_unix_error Unix.inet_addr_of_string str

let localhost = vfun0 (fun () ->
create_unknown (catch_unix_error Unix.gethostname())
)

let hostReverse = vfun1 (fun ip ->
let ip = decode_i32 ip in
try create_unknown (catch_unix_error Unix.gethostbyaddr (int32_addr ip)).h_name with Not_found -> exc_string "Could not reverse host"
)

let hostToString = vfun1 (fun ip ->
let ip = decode_i32 ip in
create_unknown (catch_unix_error Unix.string_of_inet_addr (int32_addr ip))
)

let resolve = vfun1 (fun name ->
let name = decode_string name in
let h = try Unix.gethostbyname name with Not_found -> exc_string (Printf.sprintf "Could not resolve host %s" name) in
let addr = catch_unix_error Unix.string_of_inet_addr h.h_addr_list.(0) in
let a, b, c, d = Scanf.sscanf addr "%d.%d.%d.%d" (fun a b c d -> a,b,c,d) in
vint32 (Int32.logor (Int32.shift_left (Int32.of_int a) 24) (Int32.of_int (d lor (c lsl 8) lor (b lsl 16))))
)
end

module StdLock = struct
let this vthis = match vthis with
| VInstance {ikind = ILock lock} -> lock
Expand Down Expand Up @@ -2039,11 +2035,12 @@ module StdSocket = struct
encode_instance key_eval_vm_NativeSocket ~kind:(ISocket socket)
)

let bind = vifun2 (fun vthis host port ->
let this = this vthis in
let host = decode_i32 host in
let bind = vifun2 (fun vthis ip_str port ->
let fd = this vthis in
let ip_str = decode_string ip_str in
let ip = catch_unix_error Unix.inet_addr_of_string ip_str in
let port = decode_int port in
catch_unix_error Unix.bind this (ADDR_INET (StdHost.int32_addr host,port));
catch_unix_error Unix.bind fd (ADDR_INET (ip, port));
vnull
)

Expand All @@ -2052,11 +2049,12 @@ module StdSocket = struct
vnull
)

let connect = vifun2 (fun vthis host port ->
let this = this vthis in
let host = decode_i32 host in
let connect = vifun2 (fun vthis ip_str port ->
let fd = this vthis in
let ip_str = decode_string ip_str in
let ip = catch_unix_error Unix.inet_addr_of_string ip_str in
let port = decode_int port in
catch_unix_error (Unix.connect this) (ADDR_INET (StdHost.int32_addr host,port));
catch_unix_error (Unix.connect fd) (ADDR_INET (ip, port));
vnull
)

Expand Down Expand Up @@ -3556,11 +3554,10 @@ let init_standard_library builtins =
"set",StdGc.set;
"stat",StdGc.stat;
] [];
init_fields builtins (["sys";"net"],"Host") [
"localhost",StdHost.localhost;
"hostReverse",StdHost.hostReverse;
"hostToString",StdHost.hostToString;
"resolve",StdHost.resolve;
init_fields builtins (["sys";"net"],"Dns") [
"getLocalHostnameImpl", StdDns.localhost;
"reverseSyncIpv4Impl", StdDns.reverse_sync;
"resolveSyncIpv4Impl", StdDns.resolve_sync;
] [];
init_fields builtins (["sys";"thread"],"Lock") [] [
"release",StdLock.release;
Expand Down
67 changes: 67 additions & 0 deletions std/cpp/_std/sys/net/Dns.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (C)2005-2024 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 cpp.NativeSocket;

@:coreApi
final class Dns {
private static function __init__():Void {
NativeSocket.socket_init();
}

public static function resolveSync(name:String):Array<IpAddress> {
final addresses:Array<IpAddress> = [];
try {
final ipv4 = NativeSocket.host_resolve(name);
addresses.push(Ipv4Address.fromNetworkOrderInt(ipv4));
} catch (_) {
// Host not found, ignore
}
try {
final ipv6 = NativeSocket.host_resolve_ipv6(name);
addresses.push(@:privateAccess Ipv6Address.fromNetworkOrderBytes(ipv6));
} catch (_) {
// Host not found, ignore
}
return addresses;
}

public static function reverseSync(address:IpAddress):Array<String> {
final name = switch (address) {
case V4(ipv4):
NativeSocket.host_reverse(@:privateAccess ipv4.asNetworkOrderInt());
case V6(ipv6):
NativeSocket.host_reverse_ipv6(@:privateAccess ipv6.asNetworkOrderBytes());
}
return if (name != null && name != "") {
[name];
} else {
[];
};
}

public static function getLocalHostname():String {
return NativeSocket.host_local();
}
}
44 changes: 26 additions & 18 deletions std/cpp/_std/sys/net/Socket.hx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@

package sys.net;

import haxe.io.Error;
import cpp.NativeSocket;
import cpp.NativeString;
import cpp.Pointer;
import haxe.io.Error;

private class SocketInput extends haxe.io.Input {
var __s:Dynamic;
Expand Down Expand Up @@ -168,18 +168,23 @@ class Socket {

public function connect(host:Host, port:Int):Void {
try {
if (host.ip == 0 && host.host != "0.0.0.0") {
// hack, hack, hack
var ipv6:haxe.io.BytesData = Reflect.field(host, "ipv6");
if (ipv6 != null) {
close();
__s = NativeSocket.socket_new_ip(false, true);
init();
NativeSocket.socket_connect_ipv6(__s, ipv6, port);
} else
throw "Unresolved host";
} else
NativeSocket.socket_connect(__s, host.ip, port);
final addresses = host.addresses;
if (addresses.length == 0) {
throw "Unresolved host";
}

final addr = addresses[0]; // TODO: family preferences?
switch (addr) {
case V4(ipv4):
final ip = @:privateAccess ipv4.asNetworkOrderInt();
NativeSocket.socket_connect(this.__s, ip, port);
case V6(ipv6):
this.close();
this.__s = NativeSocket.socket_new_ip(false, true);
this.init();
final ip = @:privateAccess ipv6.asNetworkOrderBytes();
NativeSocket.socket_connect_ipv6(this.__s, ip, port);
}
} catch (s:String) {
if (s == "Invalid socket handle")
throw "Failed to connect on " + host.toString() + ":" + port;
Expand Down Expand Up @@ -228,7 +233,7 @@ class Socket {
return null;
}
var h = new Host("127.0.0.1");
untyped h.ip = a[0];
@:privateAccess h.addresses = [V4(cast a[0])];
return {host: h, port: a[1]};
}

Expand All @@ -238,7 +243,7 @@ class Socket {
return null;
}
var h = new Host("127.0.0.1");
untyped h.ip = a[0];
@:privateAccess h.addresses = [V4(cast a[0])];
return {host: h, port: a[1]};
}

Expand Down Expand Up @@ -266,8 +271,11 @@ class Socket {
var neko_array = NativeSocket.socket_select(read, write, others, timeout);
if (neko_array == null)
throw "Select error";
return @:fixed {
read:neko_array[0], write:neko_array[1], others:neko_array[2]
};
return @:fixed
{
read: neko_array[0],
write: neko_array[1],
others: neko_array[2]
};
}
}
47 changes: 23 additions & 24 deletions std/cpp/_std/sys/net/Host.hx → std/eval/_std/sys/net/Dns.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
* Copyright (C)2005-2024 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
Expand All @@ -22,38 +22,37 @@

package sys.net;

import cpp.NativeSocket;
import haxe.Exception;

@:coreApi
class Host {
public var host(default, null):String;

public var ip(default, null):Int;

private var ipv6(default, null):haxe.io.BytesData;

public function new(name:String):Void {
host = name;
final class Dns {
public static function resolveSync(name:String):Array<IpAddress> {
try {
ip = NativeSocket.host_resolve(name);
} catch (e:Dynamic) {
ipv6 = NativeSocket.host_resolve_ipv6(name);
final addresses:Array<IpAddress> = [];
for (addressStr in resolveSyncIpv4Impl(name)) {
final ipAddr = IpAddress.tryParse(addressStr);
if (ipAddr != null) {
addresses.push(ipAddr);
}
}
return addresses;
} catch (e:Exception) {
trace(e.details());
return [];
}
}

public function toString():String {
return ipv6 == null ? NativeSocket.host_to_string(ip) : NativeSocket.host_to_string_ipv6(ipv6);
public static function reverseSync(address:IpAddress):Array<String> {
return [reverseSyncIpv4Impl(address.toString())];
}

public function reverse():String {
return ipv6 == null ? NativeSocket.host_reverse(ip) : NativeSocket.host_reverse_ipv6(ipv6);
public static function getLocalHostname():String {
return getLocalHostnameImpl();
}

public static function localhost():String {
return NativeSocket.host_local();
}
private static extern function resolveSyncIpv4Impl(name:String):Array<String>;

static function __init__():Void {
NativeSocket.socket_init();
}
private static extern function reverseSyncIpv4Impl(ipStr:String):String;

private static extern function getLocalHostnameImpl():String;
}
22 changes: 13 additions & 9 deletions std/eval/_std/sys/net/Socket.hx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@

package sys.net;

import haxe.io.Error;
import eval.vm.NativeSocket;
import haxe.io.Error;

private class SocketOutput extends haxe.io.Output {
var socket:NativeSocket;
Expand Down Expand Up @@ -132,7 +132,8 @@ class Socket {
}

public function connect(host:Host, port:Int):Void {
socket.connect(host.ip, port);
final address = @:privateAccess host.getAddressesSorted(PreferIPv4)[0];
socket.connect(address.toString(), port);
}

public function listen(connections:Int):Void {
Expand All @@ -144,7 +145,8 @@ class Socket {
}

public function bind(host:Host, port:Int):Void {
socket.bind(host.ip, port);
final address = @:privateAccess host.getAddressesSorted(PreferIPv4)[0];
socket.bind(address.toString(), port);
}

public function accept():Socket {
Expand All @@ -156,17 +158,19 @@ class 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);
final info = socket.peer();
final ipv4 = Ipv4Address.fromNetworkOrderInt(info.ip);
final host = new Host(ipv4.toString());
final port = info.port;
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);
final info = socket.host();
final ipv4 = Ipv4Address.fromNetworkOrderInt(info.ip);
final host = new Host(ipv4.toString());
final port = info.port;
return {host: host, port: info.port};
}

Expand Down
Loading