package org.jerlang.erts.prim_inet; import static org.jerlang.erts.PrimInet.close; import static org.jerlang.erts.PrimInet.setopts; import static org.jerlang.type.List.nil; import org.jerlang.erts.Erlang; import org.jerlang.erts.erlang.Error; import org.jerlang.type.Atom; import org.jerlang.type.Integer; import org.jerlang.type.List; import org.jerlang.type.PortID; import org.jerlang.type.Str; import org.jerlang.type.Term; import org.jerlang.type.Tuple; public class PrimInetOpen extends AbstractPrimInetFunction { private static final Atom ok = Atom.of("ok"); private static final Atom tcp = Atom.of("tcp"); private static final Atom udp = Atom.of("udp"); private static final Atom sctp = Atom.of("sctp"); private PrimInetOpen() { } public static Term dispatch(List params) { Atom protocol = params.head().toAtom(); params = params.tail(); Atom family = params.head().toAtom(); params = params.tail(); Atom type = params.head().toAtom(); switch (params.length()) { case 3: return open_3(protocol, family, type); case 4: params = params.tail(); List opts = params.head().toList(); return open_4(protocol, family, type, opts); default: throw Error.badarg; } } public static Tuple open_3(Atom protocol, Atom family, Atom type) { return open_4(protocol, family, type, nil); } public static Tuple open_4(Atom protocol, Atom family, Atom type, List opts) { Str driver = protocol2drv(protocol); Integer af = enc_family(family); Integer t = enc_type(type); Tuple portName = Tuple.of(Atom.of("spawn_driver"), driver); List portSettings = List.of(Atom.of("binary")); PortID s = Erlang.open_port(portName, portSettings); Term r1 = setopts(s, opts); if (ok.equals(r1)) { Tuple r2 = ctl_cmd(s, InetRequest.INET_REQ_OPEN.value(), List.of(af, t, opts)); if (ok.equals(r2.element(1))) { return Tuple.of(ok, s); } else { close(s); return r2; } } else { close(s); return r1.toTuple(); } } private static Integer enc_family(Atom family) { InetAddressFamily inetAddressFamily = InetAddressFamily.byAtom(family); if (inetAddressFamily == null) { throw new Error("badmatch"); } return Integer.of(inetAddressFamily.value()); } private static Integer enc_type(Atom type) { InetType inetType = InetType.byAtom(type); if (inetType == null) { throw new Error("badmatch"); } return Integer.of(inetType.value()); } private static Str protocol2drv(Atom protocol) { if (tcp.equals(protocol)) { return Str.of("tcp_inet"); } if (udp.equals(protocol)) { return Str.of("udp_inet"); } if (sctp.equals(protocol)) { return Str.of("sctp_inet"); } throw new Error("badmatch"); } private static Tuple ctl_cmd(PortID socket, int req, List data) { return null; } }