sock = listensock.pending.shift();
newsock.stream.flags = listensock.stream.flags;
return newsock;
},
getname: function (sock, peer) {
var addr, port;
if (peer) {
if (sock.daddr === undefined || sock.dport === undefined) {
throw new FS.ErrnoError(53);
}
addr = sock.daddr;
port = sock.dport;
} else {
addr = sock.saddr || 0;
port = sock.sport || 0;
}
return { addr: addr, port: port };
},
sendmsg: function (sock, buffer, offset, length, addr, port) {
if (sock.type === 2) {
if (addr === undefined || port === undefined) {
addr = sock.daddr;
port = sock.dport;
}
if (addr === undefined || port === undefined) {
throw new FS.ErrnoError(17);
}
} else {
addr = sock.daddr;
port = sock.dport;
}
var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port);
if (sock.type === 1) {
if (
!dest ||
dest.socket.readyState === dest.socket.CLOSING ||
dest.socket.readyState === dest.socket.CLOSED
) {
throw new FS.ErrnoError(53);
}
}
if (ArrayBuffer.isView(buffer)) {
offset += buffer.byteOffset;
buffer = buffer.buffer;
}
var data;
data = buffer.slice(offset, offset + length);
if (!dest || dest.socket.readyState !== dest.socket.OPEN) {
if (sock.type === 2) {
if (
!dest ||
dest.socket.readyState === dest.socket.CLOSING ||
dest.socket.readyState === dest.socket.CLOSED
) {
dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
}
}
dest.msg_send_queue.push(data);
return length;
}
try {
dest.socket.send(data);
return length;
} catch (e) {
throw new FS.ErrnoError(28);
}
},
recvmsg: function (sock, length) {
if (sock.type === 1 && sock.server) {
throw new FS.ErrnoError(53);
}
var queued = sock.recv_queue.shift();
if (!queued) {
if (sock.type === 1) {
var dest = SOCKFS.websocket_sock_ops.getPeer(
sock,
sock.daddr,
sock.dport
);
if (!dest) {
throw new FS.ErrnoError(53);
}
if (
dest.socket.readyState === dest.socket.CLOSING ||
dest.socket.readyState === dest.socket.CLOSED
) {
return null;
}
throw new FS.ErrnoError(6);
}
throw new FS.ErrnoError(6);
}
var queuedLength = queued.data.byteLength || queued.data.length;
var queuedOffset = queued.data.byteOffset || 0;
var queuedBuffer = queued.data.buffer || queued.data;
var bytesRead = Math.min(length, queuedLength);
var res = {
buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead),
addr: queued.addr,
port: queued.port,
};
if (sock.type === 1 && bytesRead < queuedLength) {
var bytesRemaining = queuedLength - bytesRead;
queued.data = new Uint8Array(
queuedBuffer,
queuedOffset + bytesRead,
bytesRemaining
);
sock.recv_queue.unshift(queued);
}
return res;
},
},
};
function getSocketFromFD(fd) {
var socket = SOCKFS.getSocket(fd);
if (!socket) throw new FS.ErrnoError(8);
return socket;
}
function setErrNo(value) {
HEAP32[___errno_location() >> 2] = value;
return value;
}
function inetPton4(str) {
var b = str.split(".");
for (var i = 0; i < 4; i++) {
var tmp = Number(b[i]);
if (isNaN(tmp)) return null;
b[i] = tmp;
}
return (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0;
}
function jstoi_q(str) {
return parseInt(str);
}
function inetPton6(str) {
var words;
var w, offset, z;
var valid6regx =
/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;
var parts = [];
if (!valid6regx.test(str)) {
return null;
}
if (str === "::") {
return [0, 0, 0, 0, 0, 0, 0, 0];
}
if (str.startsWith("::")) {
str = str.replace("::", "Z:");
} else {
str = str.replace("::", ":Z:");
}
if (str.indexOf(".") > 0) {
str = str.replace(new RegExp("[.]", "g"), ":");
words = str.split(":");
words[words.length - 4] =
jstoi_q(words[words.length - 4]) +
jstoi_q(words[words.length - 3]) * 256;
words[words.length - 3] =
jstoi_q(words[words.length - 2]) +
jstoi_q(words[words.length - 1]) * 256;
words = words.slice(0, words.length - 2);
} else {
words = str.split(":");
}
offset = 0;
z = 0;
for (w = 0; w < words.length; w++) {
if (typeof words[w] == "string") {
if (words[w] === "Z") {
for (z = 0; z < 8 - words.length + 1; z++) {
parts[w + z] = 0;
}
offset = z - 1;
} else {
parts[w + offset] = _htons(parseInt(words[w], 16));
}
} else {
parts[w + offset] = words[w];
}
}
return [
(parts[1] << 16) | parts[0],
(parts[3] << 16) | parts[2],
(parts[5] << 16) | parts[4],
(parts[7] << 16) | parts[6],
];
}
function writeSockaddr(sa, family, addr, port, addrlen) {
switch (family) {
case 2:
addr = inetPton4(addr);
zeroMemory(sa, 16);
if (addrlen) {
HEAP32[addrlen >> 2] = 16;
}
HEAP16[sa >> 1] = family;
HEAP32[(sa + 4) >> 2] = addr;
HEAP16[(sa + 2) >> 1] = _htons(port);
break;
case 10:
addr = inetPton6(addr);
zeroMemory(sa, 28);
if (addrlen) {
HEAP32[addrlen >> 2] = 28;
}
HEAP32[sa >> 2] = family;
HEAP32[(sa + 8) >> 2] = addr[0];
HEAP32[(sa + 12) >> 2] = addr[1];
HEAP32[(sa + 16) >> 2] = addr[2];
HEAP32[(sa + 20) >> 2] = addr[3];
HEAP16[(sa + 2) >> 1] = _htons(port);
break;
default:
return 5;
}
return 0;
}
var DNS = {
address_map: { id: 1, addrs: {}, names: {} },
lookup_name: function (name) {
var res = inetPton4(name);
if (res !== null) {
return name;
}
res = inetPton6(name);
if (res !== null) {
return name;
}
var addr;
if (DNS.address_map.addrs[name]) {
addr = DNS.address_map.addrs[name];
} else {
var id = DNS.address_map.id++;
assert(id < 65535, "exceeded max address mappings of 65535");
addr = "172.29." + (id & 255) + "." + (id & 65280);
DNS.address_map.names[addr] = name;
DNS.address_map.addrs[name] = addr;
}
return addr;
},
lookup_addr: function (addr) {
if (DNS.address_map.names[addr]) {
return DNS.address_map.names[addr];
}
return null;
},
};
function ___syscall_accept4(fd, addr, addrlen, flags, d1, d2) {
try {
var sock = getSocketFromFD(fd);
var newsock = sock.sock_ops.accept(sock);
if (addr) {
var errno = writeSockaddr(
addr,
newsock.family,
DNS.lookup_name(newsock.daddr),
newsock.dport,
addrlen
);
}
return newsock.stream.fd;
} catch (e) {
if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
return -e.errno;
}
}
function inetNtop4(addr) {
return (
(addr & 255) +
"." +
((addr >> 8) & 255) +
"." +
((addr >> 16) & 255) +
"." +
((addr >> 24) & 255)
);
}
function inetNtop6(ints) {
var str = "";
var word = 0;
var longest = 0;
var lastzero = 0;
var zstart = 0;
var len = 0;
var i = 0;
var parts = [
ints[0] & 65535,
ints[0] >> 16,
ints[1] & 65535,
ints[1] >> 16,
ints[2] & 65535,
ints[2] >> 16,
ints[3] & 65535,
ints[3] >> 16,
];
var hasipv4 = true;
var v4part = "";
for (i = 0; i < 5; i++) {
if (parts[i] !== 0) {
hasipv4 = false;
break;
}
}
if (hasipv4) {
v4part = inetNtop4(parts[6] | (parts[7] << 16));
if (parts[5] === -1) {
str = "::ffff:";
str += v4part;
return str;
}
if (parts[5] === 0) {
str = "::";
if (v4part === "0.0.0.0") v4part = "";
if (v4part === "0.0.0.1") v4part = "1";
str += v4part;
return str;
}
}
for (word = 0; word < 8; word++) {
if (parts[word] === 0) {
if (word - lastzero > 1) {
len = 0;
}
lastzero = word;
len++;
}
if (len > longest) {
longest = len;
zstart = word - longest + 1;
}
}
for (word = 0; word < 8; word++) {
if (longest > 1) {
if (parts[word] = |