@ai-ecoverse/wasm-gawk 5.3.2-3 → 5.4.1-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/THIRD-PARTY-NOTICES.md +619 -0
- package/bin/gawk +224 -1395
- package/bin/gawk.wasm +0 -0
- package/package.json +3 -2
package/bin/gawk
CHANGED
|
@@ -263,8 +263,7 @@ function initRuntime() {
|
|
|
263
263
|
runtimeInitialized = true;
|
|
264
264
|
|
|
265
265
|
// Begin ATINITS hooks
|
|
266
|
-
|
|
267
|
-
if (!Module['noFSInit'] && !FS.initialized) FS.init();
|
|
266
|
+
if (!Module['noFSInit'] && !FS.initialized) FS.init();
|
|
268
267
|
TTY.init();
|
|
269
268
|
PIPEFS.root = FS.mount(PIPEFS, {}, null);
|
|
270
269
|
// End ATINITS hooks
|
|
@@ -570,6 +569,83 @@ async function createWasm() {
|
|
|
570
569
|
|
|
571
570
|
|
|
572
571
|
|
|
572
|
+
var UTF8Decoder = globalThis.TextDecoder && new TextDecoder();
|
|
573
|
+
|
|
574
|
+
var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
|
|
575
|
+
var maxIdx = idx + maxBytesToRead;
|
|
576
|
+
if (ignoreNul) return maxIdx;
|
|
577
|
+
// TextDecoder needs to know the byte length in advance, it doesn't stop on
|
|
578
|
+
// null terminator by itself.
|
|
579
|
+
// As a tiny code save trick, compare idx against maxIdx using a negation,
|
|
580
|
+
// so that maxBytesToRead=undefined/NaN means Infinity.
|
|
581
|
+
while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx;
|
|
582
|
+
return idx;
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
|
|
587
|
+
* array that contains uint8 values, returns a copy of that string as a
|
|
588
|
+
* Javascript String object.
|
|
589
|
+
* heapOrArray is either a regular array, or a JavaScript typed array view.
|
|
590
|
+
* @param {number=} idx
|
|
591
|
+
* @param {number=} maxBytesToRead
|
|
592
|
+
* @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
|
|
593
|
+
* @return {string}
|
|
594
|
+
*/
|
|
595
|
+
var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => {
|
|
596
|
+
|
|
597
|
+
var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul);
|
|
598
|
+
|
|
599
|
+
// When using conditional TextDecoder, skip it for short strings as the overhead of the native call is not worth it.
|
|
600
|
+
if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
|
|
601
|
+
return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
|
|
602
|
+
}
|
|
603
|
+
var str = '';
|
|
604
|
+
while (idx < endPtr) {
|
|
605
|
+
// For UTF8 byte structure, see:
|
|
606
|
+
// http://en.wikipedia.org/wiki/UTF-8#Description
|
|
607
|
+
// https://www.ietf.org/rfc/rfc2279.txt
|
|
608
|
+
// https://tools.ietf.org/html/rfc3629
|
|
609
|
+
var u0 = heapOrArray[idx++];
|
|
610
|
+
if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
|
|
611
|
+
var u1 = heapOrArray[idx++] & 63;
|
|
612
|
+
if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
|
|
613
|
+
var u2 = heapOrArray[idx++] & 63;
|
|
614
|
+
if ((u0 & 0xF0) == 0xE0) {
|
|
615
|
+
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
|
|
616
|
+
} else {
|
|
617
|
+
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
if (u0 < 0x10000) {
|
|
621
|
+
str += String.fromCharCode(u0);
|
|
622
|
+
} else {
|
|
623
|
+
var ch = u0 - 0x10000;
|
|
624
|
+
str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return str;
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
|
|
632
|
+
* emscripten HEAP, returns a copy of that string as a Javascript String object.
|
|
633
|
+
*
|
|
634
|
+
* @param {number} ptr
|
|
635
|
+
* @param {number=} maxBytesToRead - An optional length that specifies the
|
|
636
|
+
* maximum number of bytes to read. You can omit this parameter to scan the
|
|
637
|
+
* string until the first 0 byte. If maxBytesToRead is passed, and the string
|
|
638
|
+
* at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
|
|
639
|
+
* string will cut short at that byte index.
|
|
640
|
+
* @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
|
|
641
|
+
* @return {string}
|
|
642
|
+
*/
|
|
643
|
+
var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => {
|
|
644
|
+
return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : '';
|
|
645
|
+
};
|
|
646
|
+
var ___assert_fail = (condition, filename, line, func) =>
|
|
647
|
+
abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
|
|
648
|
+
|
|
573
649
|
var wasmTableMirror = [];
|
|
574
650
|
|
|
575
651
|
|
|
@@ -583,20 +659,6 @@ async function createWasm() {
|
|
|
583
659
|
};
|
|
584
660
|
var ___call_sighandler = (fp, sig) => getWasmTableEntry(fp)(sig);
|
|
585
661
|
|
|
586
|
-
var initRandomFill = () => {
|
|
587
|
-
// This block is not needed on v19+ since crypto.getRandomValues is builtin
|
|
588
|
-
if (ENVIRONMENT_IS_NODE) {
|
|
589
|
-
var nodeCrypto = require('crypto');
|
|
590
|
-
return (view) => nodeCrypto.randomFillSync(view);
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
return (view) => crypto.getRandomValues(view);
|
|
594
|
-
};
|
|
595
|
-
var randomFill = (view) => {
|
|
596
|
-
// Lazily init on the first invocation.
|
|
597
|
-
(randomFill = initRandomFill())(view);
|
|
598
|
-
};
|
|
599
|
-
|
|
600
662
|
var PATH = {
|
|
601
663
|
isAbs:(path) => path.charAt(0) === '/',
|
|
602
664
|
splitPath:(filename) => {
|
|
@@ -658,6 +720,21 @@ async function createWasm() {
|
|
|
658
720
|
join2:(l, r) => PATH.normalize(l + '/' + r),
|
|
659
721
|
};
|
|
660
722
|
|
|
723
|
+
var initRandomFill = () => {
|
|
724
|
+
// This block is not needed on v19+ since crypto.getRandomValues is builtin
|
|
725
|
+
if (ENVIRONMENT_IS_NODE) {
|
|
726
|
+
var nodeCrypto = require('crypto');
|
|
727
|
+
return (view) => nodeCrypto.randomFillSync(view);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
return (view) => crypto.getRandomValues(view);
|
|
731
|
+
};
|
|
732
|
+
var randomFill = (view) => {
|
|
733
|
+
// Lazily init on the first invocation.
|
|
734
|
+
(randomFill = initRandomFill())(view);
|
|
735
|
+
};
|
|
736
|
+
|
|
737
|
+
|
|
661
738
|
|
|
662
739
|
var PATH_FS = {
|
|
663
740
|
resolve:(...args) => {
|
|
@@ -714,63 +791,6 @@ async function createWasm() {
|
|
|
714
791
|
};
|
|
715
792
|
|
|
716
793
|
|
|
717
|
-
var UTF8Decoder = globalThis.TextDecoder && new TextDecoder();
|
|
718
|
-
|
|
719
|
-
var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
|
|
720
|
-
var maxIdx = idx + maxBytesToRead;
|
|
721
|
-
if (ignoreNul) return maxIdx;
|
|
722
|
-
// TextDecoder needs to know the byte length in advance, it doesn't stop on
|
|
723
|
-
// null terminator by itself.
|
|
724
|
-
// As a tiny code save trick, compare idx against maxIdx using a negation,
|
|
725
|
-
// so that maxBytesToRead=undefined/NaN means Infinity.
|
|
726
|
-
while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx;
|
|
727
|
-
return idx;
|
|
728
|
-
};
|
|
729
|
-
|
|
730
|
-
/**
|
|
731
|
-
* Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
|
|
732
|
-
* array that contains uint8 values, returns a copy of that string as a
|
|
733
|
-
* Javascript String object.
|
|
734
|
-
* heapOrArray is either a regular array, or a JavaScript typed array view.
|
|
735
|
-
* @param {number=} idx
|
|
736
|
-
* @param {number=} maxBytesToRead
|
|
737
|
-
* @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
|
|
738
|
-
* @return {string}
|
|
739
|
-
*/
|
|
740
|
-
var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => {
|
|
741
|
-
|
|
742
|
-
var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul);
|
|
743
|
-
|
|
744
|
-
// When using conditional TextDecoder, skip it for short strings as the overhead of the native call is not worth it.
|
|
745
|
-
if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
|
|
746
|
-
return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
|
|
747
|
-
}
|
|
748
|
-
var str = '';
|
|
749
|
-
while (idx < endPtr) {
|
|
750
|
-
// For UTF8 byte structure, see:
|
|
751
|
-
// http://en.wikipedia.org/wiki/UTF-8#Description
|
|
752
|
-
// https://www.ietf.org/rfc/rfc2279.txt
|
|
753
|
-
// https://tools.ietf.org/html/rfc3629
|
|
754
|
-
var u0 = heapOrArray[idx++];
|
|
755
|
-
if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
|
|
756
|
-
var u1 = heapOrArray[idx++] & 63;
|
|
757
|
-
if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
|
|
758
|
-
var u2 = heapOrArray[idx++] & 63;
|
|
759
|
-
if ((u0 & 0xF0) == 0xE0) {
|
|
760
|
-
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
|
|
761
|
-
} else {
|
|
762
|
-
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
if (u0 < 0x10000) {
|
|
766
|
-
str += String.fromCharCode(u0);
|
|
767
|
-
} else {
|
|
768
|
-
var ch = u0 - 0x10000;
|
|
769
|
-
str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
return str;
|
|
773
|
-
};
|
|
774
794
|
|
|
775
795
|
var FS_stdin_getChar_buffer = [];
|
|
776
796
|
|
|
@@ -3051,1047 +3071,76 @@ async function createWasm() {
|
|
|
3051
3071
|
return node;
|
|
3052
3072
|
},
|
|
3053
3073
|
};
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3074
|
+
|
|
3075
|
+
var SYSCALLS = {
|
|
3076
|
+
calculateAt(dirfd, path, allowEmpty) {
|
|
3077
|
+
if (PATH.isAbs(path)) {
|
|
3078
|
+
return path;
|
|
3079
|
+
}
|
|
3080
|
+
// relative path
|
|
3081
|
+
var dir;
|
|
3082
|
+
if (dirfd === -100) {
|
|
3083
|
+
dir = FS.cwd();
|
|
3084
|
+
} else {
|
|
3085
|
+
var dirstream = SYSCALLS.getStreamFromFD(dirfd);
|
|
3086
|
+
dir = dirstream.path;
|
|
3087
|
+
}
|
|
3088
|
+
if (path.length == 0) {
|
|
3089
|
+
if (!allowEmpty) {
|
|
3090
|
+
throw new FS.ErrnoError(44);;
|
|
3091
|
+
}
|
|
3092
|
+
return dir;
|
|
3093
|
+
}
|
|
3094
|
+
return dir + '/' + path;
|
|
3061
3095
|
},
|
|
3062
|
-
|
|
3063
|
-
|
|
3096
|
+
writeStat(buf, stat) {
|
|
3097
|
+
HEAPU32[((buf)>>2)] = stat.dev;
|
|
3098
|
+
HEAPU32[(((buf)+(4))>>2)] = stat.mode;
|
|
3099
|
+
HEAPU32[(((buf)+(8))>>2)] = stat.nlink;
|
|
3100
|
+
HEAPU32[(((buf)+(12))>>2)] = stat.uid;
|
|
3101
|
+
HEAPU32[(((buf)+(16))>>2)] = stat.gid;
|
|
3102
|
+
HEAPU32[(((buf)+(20))>>2)] = stat.rdev;
|
|
3103
|
+
HEAP64[(((buf)+(24))>>3)] = BigInt(stat.size);
|
|
3104
|
+
HEAP32[(((buf)+(32))>>2)] = 4096;
|
|
3105
|
+
HEAP32[(((buf)+(36))>>2)] = stat.blocks;
|
|
3106
|
+
var atime = stat.atime.getTime();
|
|
3107
|
+
var mtime = stat.mtime.getTime();
|
|
3108
|
+
var ctime = stat.ctime.getTime();
|
|
3109
|
+
HEAP64[(((buf)+(40))>>3)] = BigInt(Math.floor(atime / 1000));
|
|
3110
|
+
HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000 * 1000;
|
|
3111
|
+
HEAP64[(((buf)+(56))>>3)] = BigInt(Math.floor(mtime / 1000));
|
|
3112
|
+
HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000 * 1000;
|
|
3113
|
+
HEAP64[(((buf)+(72))>>3)] = BigInt(Math.floor(ctime / 1000));
|
|
3114
|
+
HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000 * 1000;
|
|
3115
|
+
HEAP64[(((buf)+(88))>>3)] = BigInt(stat.ino);
|
|
3116
|
+
return 0;
|
|
3064
3117
|
},
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
(
|
|
3073
|
-
|
|
3074
|
-
|
|
3118
|
+
writeStatFs(buf, stats) {
|
|
3119
|
+
HEAPU32[(((buf)+(4))>>2)] = stats.bsize;
|
|
3120
|
+
HEAPU32[(((buf)+(60))>>2)] = stats.bsize;
|
|
3121
|
+
HEAP64[(((buf)+(8))>>3)] = BigInt(stats.blocks);
|
|
3122
|
+
HEAP64[(((buf)+(16))>>3)] = BigInt(stats.bfree);
|
|
3123
|
+
HEAP64[(((buf)+(24))>>3)] = BigInt(stats.bavail);
|
|
3124
|
+
HEAP64[(((buf)+(32))>>3)] = BigInt(stats.files);
|
|
3125
|
+
HEAP64[(((buf)+(40))>>3)] = BigInt(stats.ffree);
|
|
3126
|
+
HEAPU32[(((buf)+(48))>>2)] = stats.fsid;
|
|
3127
|
+
HEAPU32[(((buf)+(64))>>2)] = stats.flags; // ST_NOSUID
|
|
3128
|
+
HEAPU32[(((buf)+(56))>>2)] = stats.namelen;
|
|
3075
3129
|
},
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
throw new FS.ErrnoError(5);
|
|
3080
|
-
}
|
|
3081
|
-
type &= ~526336; // Some applications may pass it; it makes no sense for a single process.
|
|
3082
|
-
// Emscripten only supports SOCK_STREAM and SOCK_DGRAM
|
|
3083
|
-
if (type != 1 && type != 2) {
|
|
3084
|
-
throw new FS.ErrnoError(28);
|
|
3130
|
+
doMsync(addr, stream, len, flags, offset) {
|
|
3131
|
+
if (!FS.isFile(stream.node.mode)) {
|
|
3132
|
+
throw new FS.ErrnoError(43);
|
|
3085
3133
|
}
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3134
|
+
if (flags & 2) {
|
|
3135
|
+
// MAP_PRIVATE calls need not to be synced back to underlying fs
|
|
3136
|
+
return 0;
|
|
3089
3137
|
}
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
var sock = {
|
|
3093
|
-
family,
|
|
3094
|
-
type,
|
|
3095
|
-
protocol,
|
|
3096
|
-
server: null,
|
|
3097
|
-
error: null, // Used in getsockopt for SOL_SOCKET/SO_ERROR test
|
|
3098
|
-
peers: {},
|
|
3099
|
-
pending: [],
|
|
3100
|
-
recv_queue: [],
|
|
3101
|
-
sock_ops: SOCKFS.websocket_sock_ops
|
|
3102
|
-
};
|
|
3103
|
-
|
|
3104
|
-
// create the filesystem node to store the socket structure
|
|
3105
|
-
var name = SOCKFS.nextname();
|
|
3106
|
-
var node = FS.createNode(SOCKFS.root, name, 49152, 0);
|
|
3107
|
-
node.sock = sock;
|
|
3108
|
-
|
|
3109
|
-
// and the wrapping stream that enables library functions such
|
|
3110
|
-
// as read and write to indirectly interact with the socket
|
|
3111
|
-
var stream = FS.createStream({
|
|
3112
|
-
path: name,
|
|
3113
|
-
node,
|
|
3114
|
-
flags: 2,
|
|
3115
|
-
seekable: false,
|
|
3116
|
-
stream_ops: SOCKFS.stream_ops
|
|
3117
|
-
});
|
|
3118
|
-
|
|
3119
|
-
// map the new stream to the socket structure (sockets have a 1:1
|
|
3120
|
-
// relationship with a stream)
|
|
3121
|
-
sock.stream = stream;
|
|
3122
|
-
|
|
3123
|
-
return sock;
|
|
3138
|
+
var buffer = HEAPU8.slice(addr, addr + len);
|
|
3139
|
+
FS.msync(stream, buffer, offset, len, flags);
|
|
3124
3140
|
},
|
|
3125
|
-
|
|
3126
|
-
var stream = FS.
|
|
3127
|
-
|
|
3128
|
-
return null;
|
|
3129
|
-
}
|
|
3130
|
-
return stream.node.sock;
|
|
3131
|
-
},
|
|
3132
|
-
stream_ops:{
|
|
3133
|
-
poll(stream) {
|
|
3134
|
-
var sock = stream.node.sock;
|
|
3135
|
-
return sock.sock_ops.poll(sock);
|
|
3136
|
-
},
|
|
3137
|
-
ioctl(stream, request, varargs) {
|
|
3138
|
-
var sock = stream.node.sock;
|
|
3139
|
-
return sock.sock_ops.ioctl(sock, request, varargs);
|
|
3140
|
-
},
|
|
3141
|
-
read(stream, buffer, offset, length, position /* ignored */) {
|
|
3142
|
-
var sock = stream.node.sock;
|
|
3143
|
-
var msg = sock.sock_ops.recvmsg(sock, length);
|
|
3144
|
-
if (!msg) {
|
|
3145
|
-
// socket is closed
|
|
3146
|
-
return 0;
|
|
3147
|
-
}
|
|
3148
|
-
buffer.set(msg.buffer, offset);
|
|
3149
|
-
return msg.buffer.length;
|
|
3150
|
-
},
|
|
3151
|
-
write(stream, buffer, offset, length, position /* ignored */) {
|
|
3152
|
-
var sock = stream.node.sock;
|
|
3153
|
-
return sock.sock_ops.sendmsg(sock, buffer, offset, length);
|
|
3154
|
-
},
|
|
3155
|
-
close(stream) {
|
|
3156
|
-
var sock = stream.node.sock;
|
|
3157
|
-
sock.sock_ops.close(sock);
|
|
3158
|
-
},
|
|
3159
|
-
},
|
|
3160
|
-
nextname() {
|
|
3161
|
-
if (!SOCKFS.nextname.current) {
|
|
3162
|
-
SOCKFS.nextname.current = 0;
|
|
3163
|
-
}
|
|
3164
|
-
return `socket[${SOCKFS.nextname.current++}]`;
|
|
3165
|
-
},
|
|
3166
|
-
websocket_sock_ops:{
|
|
3167
|
-
createPeer(sock, addr, port) {
|
|
3168
|
-
var ws;
|
|
3169
|
-
|
|
3170
|
-
if (typeof addr == 'object') {
|
|
3171
|
-
ws = addr;
|
|
3172
|
-
addr = null;
|
|
3173
|
-
port = null;
|
|
3174
|
-
}
|
|
3175
|
-
|
|
3176
|
-
if (ws) {
|
|
3177
|
-
// for sockets that've already connected (e.g. we're the server)
|
|
3178
|
-
// we can inspect the _socket property for the address
|
|
3179
|
-
if (ws._socket) {
|
|
3180
|
-
addr = ws._socket.remoteAddress;
|
|
3181
|
-
port = ws._socket.remotePort;
|
|
3182
|
-
}
|
|
3183
|
-
// if we're just now initializing a connection to the remote,
|
|
3184
|
-
// inspect the url property
|
|
3185
|
-
else {
|
|
3186
|
-
var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);
|
|
3187
|
-
if (!result) {
|
|
3188
|
-
throw new Error('WebSocket URL must be in the format ws(s)://address:port');
|
|
3189
|
-
}
|
|
3190
|
-
addr = result[1];
|
|
3191
|
-
port = parseInt(result[2], 10);
|
|
3192
|
-
}
|
|
3193
|
-
} else {
|
|
3194
|
-
// create the actual websocket object and connect
|
|
3195
|
-
try {
|
|
3196
|
-
// The default value is 'ws://' the replace is needed because the compiler replaces '//' comments with '#'
|
|
3197
|
-
// comments without checking context, so we'd end up with ws:#, the replace swaps the '#' for '//' again.
|
|
3198
|
-
var url = 'ws://'.replace('#', '//');
|
|
3199
|
-
// Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set.
|
|
3200
|
-
var subProtocols = 'binary'; // The default value is 'binary'
|
|
3201
|
-
// The default WebSocket options
|
|
3202
|
-
var opts = undefined;
|
|
3203
|
-
|
|
3204
|
-
// Fetch runtime WebSocket URL config.
|
|
3205
|
-
if (SOCKFS.websocketArgs['url']) {
|
|
3206
|
-
url = SOCKFS.websocketArgs['url'];
|
|
3207
|
-
}
|
|
3208
|
-
// Fetch runtime WebSocket subprotocol config.
|
|
3209
|
-
if (SOCKFS.websocketArgs['subprotocol']) {
|
|
3210
|
-
subProtocols = SOCKFS.websocketArgs['subprotocol'];
|
|
3211
|
-
} else if (SOCKFS.websocketArgs['subprotocol'] === null) {
|
|
3212
|
-
subProtocols = 'null'
|
|
3213
|
-
}
|
|
3214
|
-
|
|
3215
|
-
if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it.
|
|
3216
|
-
var parts = addr.split('/');
|
|
3217
|
-
url = url + parts[0] + ":" + port + "/" + parts.slice(1).join('/');
|
|
3218
|
-
}
|
|
3219
|
-
|
|
3220
|
-
if (subProtocols !== 'null') {
|
|
3221
|
-
// The regex trims the string (removes spaces at the beginning and end), then splits the string by
|
|
3222
|
-
// <any space>,<any space> into an Array. Whitespace removal is important for Websockify and ws.
|
|
3223
|
-
subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */);
|
|
3224
|
-
|
|
3225
|
-
opts = subProtocols;
|
|
3226
|
-
}
|
|
3227
|
-
|
|
3228
|
-
// If node we use the ws library.
|
|
3229
|
-
var WebSocketConstructor;
|
|
3230
|
-
if (ENVIRONMENT_IS_NODE) {
|
|
3231
|
-
WebSocketConstructor = /** @type{(typeof WebSocket)} */(require('ws'));
|
|
3232
|
-
} else
|
|
3233
|
-
{
|
|
3234
|
-
WebSocketConstructor = WebSocket;
|
|
3235
|
-
}
|
|
3236
|
-
ws = new WebSocketConstructor(url, opts);
|
|
3237
|
-
ws.binaryType = 'arraybuffer';
|
|
3238
|
-
} catch (e) {
|
|
3239
|
-
throw new FS.ErrnoError(23);
|
|
3240
|
-
}
|
|
3241
|
-
}
|
|
3242
|
-
|
|
3243
|
-
var peer = {
|
|
3244
|
-
addr,
|
|
3245
|
-
port,
|
|
3246
|
-
socket: ws,
|
|
3247
|
-
msg_send_queue: []
|
|
3248
|
-
};
|
|
3249
|
-
|
|
3250
|
-
SOCKFS.websocket_sock_ops.addPeer(sock, peer);
|
|
3251
|
-
SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer);
|
|
3252
|
-
|
|
3253
|
-
// if this is a bound dgram socket, send the port number first to allow
|
|
3254
|
-
// us to override the ephemeral port reported to us by remotePort on the
|
|
3255
|
-
// remote end.
|
|
3256
|
-
if (sock.type === 2 && typeof sock.sport != 'undefined') {
|
|
3257
|
-
peer.msg_send_queue.push(new Uint8Array([
|
|
3258
|
-
255, 255, 255, 255,
|
|
3259
|
-
'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0),
|
|
3260
|
-
((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff)
|
|
3261
|
-
]));
|
|
3262
|
-
}
|
|
3263
|
-
|
|
3264
|
-
return peer;
|
|
3265
|
-
},
|
|
3266
|
-
getPeer(sock, addr, port) {
|
|
3267
|
-
return sock.peers[addr + ':' + port];
|
|
3268
|
-
},
|
|
3269
|
-
addPeer(sock, peer) {
|
|
3270
|
-
sock.peers[peer.addr + ':' + peer.port] = peer;
|
|
3271
|
-
},
|
|
3272
|
-
removePeer(sock, peer) {
|
|
3273
|
-
delete sock.peers[peer.addr + ':' + peer.port];
|
|
3274
|
-
},
|
|
3275
|
-
handlePeerEvents(sock, peer) {
|
|
3276
|
-
var first = true;
|
|
3277
|
-
|
|
3278
|
-
var handleOpen = function () {
|
|
3279
|
-
|
|
3280
|
-
sock.connecting = false;
|
|
3281
|
-
SOCKFS.emit('open', sock.stream.fd);
|
|
3282
|
-
|
|
3283
|
-
try {
|
|
3284
|
-
var queued = peer.msg_send_queue.shift();
|
|
3285
|
-
while (queued) {
|
|
3286
|
-
peer.socket.send(queued);
|
|
3287
|
-
queued = peer.msg_send_queue.shift();
|
|
3288
|
-
}
|
|
3289
|
-
} catch (e) {
|
|
3290
|
-
// not much we can do here in the way of proper error handling as we've already
|
|
3291
|
-
// lied and said this data was sent. shut it down.
|
|
3292
|
-
peer.socket.close();
|
|
3293
|
-
}
|
|
3294
|
-
};
|
|
3295
|
-
|
|
3296
|
-
function handleMessage(data) {
|
|
3297
|
-
if (typeof data == 'string') {
|
|
3298
|
-
var encoder = new TextEncoder(); // should be utf-8
|
|
3299
|
-
data = encoder.encode(data); // make a typed array from the string
|
|
3300
|
-
} else {
|
|
3301
|
-
if (data.byteLength == 0) {
|
|
3302
|
-
// An empty ArrayBuffer will emit a pseudo disconnect event
|
|
3303
|
-
// as recv/recvmsg will return zero which indicates that a socket
|
|
3304
|
-
// has performed a shutdown although the connection has not been disconnected yet.
|
|
3305
|
-
return;
|
|
3306
|
-
}
|
|
3307
|
-
data = new Uint8Array(data); // make a typed array view on the array buffer
|
|
3308
|
-
}
|
|
3309
|
-
|
|
3310
|
-
// if this is the port message, override the peer's port with it
|
|
3311
|
-
var wasfirst = first;
|
|
3312
|
-
first = false;
|
|
3313
|
-
if (wasfirst &&
|
|
3314
|
-
data.length === 10 &&
|
|
3315
|
-
data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 &&
|
|
3316
|
-
data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) {
|
|
3317
|
-
// update the peer's port and its key in the peer map
|
|
3318
|
-
var newport = ((data[8] << 8) | data[9]);
|
|
3319
|
-
SOCKFS.websocket_sock_ops.removePeer(sock, peer);
|
|
3320
|
-
peer.port = newport;
|
|
3321
|
-
SOCKFS.websocket_sock_ops.addPeer(sock, peer);
|
|
3322
|
-
return;
|
|
3323
|
-
}
|
|
3324
|
-
|
|
3325
|
-
sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data });
|
|
3326
|
-
SOCKFS.emit('message', sock.stream.fd);
|
|
3327
|
-
};
|
|
3328
|
-
|
|
3329
|
-
if (ENVIRONMENT_IS_NODE) {
|
|
3330
|
-
peer.socket.on('open', handleOpen);
|
|
3331
|
-
peer.socket.on('message', function(data, isBinary) {
|
|
3332
|
-
if (!isBinary) {
|
|
3333
|
-
return;
|
|
3334
|
-
}
|
|
3335
|
-
handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer
|
|
3336
|
-
});
|
|
3337
|
-
peer.socket.on('close', function() {
|
|
3338
|
-
SOCKFS.emit('close', sock.stream.fd);
|
|
3339
|
-
});
|
|
3340
|
-
peer.socket.on('error', function(error) {
|
|
3341
|
-
// Although the ws library may pass errors that may be more descriptive than
|
|
3342
|
-
// ECONNREFUSED they are not necessarily the expected error code e.g.
|
|
3343
|
-
// ENOTFOUND on getaddrinfo seems to be node.js specific, so using ECONNREFUSED
|
|
3344
|
-
// is still probably the most useful thing to do.
|
|
3345
|
-
sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test.
|
|
3346
|
-
SOCKFS.emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']);
|
|
3347
|
-
// don't throw
|
|
3348
|
-
});
|
|
3349
|
-
} else {
|
|
3350
|
-
peer.socket.onopen = handleOpen;
|
|
3351
|
-
peer.socket.onclose = function() {
|
|
3352
|
-
SOCKFS.emit('close', sock.stream.fd);
|
|
3353
|
-
};
|
|
3354
|
-
peer.socket.onmessage = function peer_socket_onmessage(event) {
|
|
3355
|
-
handleMessage(event.data);
|
|
3356
|
-
};
|
|
3357
|
-
peer.socket.onerror = function(error) {
|
|
3358
|
-
// The WebSocket spec only allows a 'simple event' to be thrown on error,
|
|
3359
|
-
// so we only really know as much as ECONNREFUSED.
|
|
3360
|
-
sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test.
|
|
3361
|
-
SOCKFS.emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']);
|
|
3362
|
-
};
|
|
3363
|
-
}
|
|
3364
|
-
},
|
|
3365
|
-
poll(sock) {
|
|
3366
|
-
if (sock.type === 1 && sock.server) {
|
|
3367
|
-
// listen sockets should only say they're available for reading
|
|
3368
|
-
// if there are pending clients.
|
|
3369
|
-
return sock.pending.length ? (64 | 1) : 0;
|
|
3370
|
-
}
|
|
3371
|
-
|
|
3372
|
-
var mask = 0;
|
|
3373
|
-
var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets
|
|
3374
|
-
SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) :
|
|
3375
|
-
null;
|
|
3376
|
-
|
|
3377
|
-
if (sock.recv_queue.length ||
|
|
3378
|
-
!dest || // connection-less sockets are always ready to read
|
|
3379
|
-
(dest && dest.socket.readyState === dest.socket.CLOSING) ||
|
|
3380
|
-
(dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed
|
|
3381
|
-
mask |= (64 | 1);
|
|
3382
|
-
}
|
|
3383
|
-
|
|
3384
|
-
if (!dest || // connection-less sockets are always ready to write
|
|
3385
|
-
(dest && dest.socket.readyState === dest.socket.OPEN)) {
|
|
3386
|
-
mask |= 4;
|
|
3387
|
-
}
|
|
3388
|
-
|
|
3389
|
-
if ((dest && dest.socket.readyState === dest.socket.CLOSING) ||
|
|
3390
|
-
(dest && dest.socket.readyState === dest.socket.CLOSED)) {
|
|
3391
|
-
// When an non-blocking connect fails mark the socket as writable.
|
|
3392
|
-
// Its up to the calling code to then use getsockopt with SO_ERROR to
|
|
3393
|
-
// retrieve the error.
|
|
3394
|
-
// See https://man7.org/linux/man-pages/man2/connect.2.html
|
|
3395
|
-
if (sock.connecting) {
|
|
3396
|
-
mask |= 4;
|
|
3397
|
-
} else {
|
|
3398
|
-
mask |= 16;
|
|
3399
|
-
}
|
|
3400
|
-
}
|
|
3401
|
-
|
|
3402
|
-
return mask;
|
|
3403
|
-
},
|
|
3404
|
-
ioctl(sock, request, arg) {
|
|
3405
|
-
switch (request) {
|
|
3406
|
-
case 21531:
|
|
3407
|
-
var bytes = 0;
|
|
3408
|
-
if (sock.recv_queue.length) {
|
|
3409
|
-
bytes = sock.recv_queue[0].data.length;
|
|
3410
|
-
}
|
|
3411
|
-
HEAP32[((arg)>>2)] = bytes;
|
|
3412
|
-
return 0;
|
|
3413
|
-
case 21537:
|
|
3414
|
-
var on = HEAP32[((arg)>>2)];
|
|
3415
|
-
if (on) {
|
|
3416
|
-
sock.stream.flags |= 2048;
|
|
3417
|
-
} else {
|
|
3418
|
-
sock.stream.flags &= ~2048;
|
|
3419
|
-
}
|
|
3420
|
-
return 0;
|
|
3421
|
-
default:
|
|
3422
|
-
return 28;
|
|
3423
|
-
}
|
|
3424
|
-
},
|
|
3425
|
-
close(sock) {
|
|
3426
|
-
// if we've spawned a listen server, close it
|
|
3427
|
-
if (sock.server) {
|
|
3428
|
-
try {
|
|
3429
|
-
sock.server.close();
|
|
3430
|
-
} catch (e) {
|
|
3431
|
-
}
|
|
3432
|
-
sock.server = null;
|
|
3433
|
-
}
|
|
3434
|
-
// close any peer connections
|
|
3435
|
-
for (var peer of Object.values(sock.peers)) {
|
|
3436
|
-
try {
|
|
3437
|
-
peer.socket.close();
|
|
3438
|
-
} catch (e) {
|
|
3439
|
-
}
|
|
3440
|
-
SOCKFS.websocket_sock_ops.removePeer(sock, peer);
|
|
3441
|
-
}
|
|
3442
|
-
return 0;
|
|
3443
|
-
},
|
|
3444
|
-
bind(sock, addr, port) {
|
|
3445
|
-
if (typeof sock.saddr != 'undefined' || typeof sock.sport != 'undefined') {
|
|
3446
|
-
throw new FS.ErrnoError(28); // already bound
|
|
3447
|
-
}
|
|
3448
|
-
sock.saddr = addr;
|
|
3449
|
-
sock.sport = port;
|
|
3450
|
-
// in order to emulate dgram sockets, we need to launch a listen server when
|
|
3451
|
-
// binding on a connection-less socket
|
|
3452
|
-
// note: this is only required on the server side
|
|
3453
|
-
if (sock.type === 2) {
|
|
3454
|
-
// close the existing server if it exists
|
|
3455
|
-
if (sock.server) {
|
|
3456
|
-
sock.server.close();
|
|
3457
|
-
sock.server = null;
|
|
3458
|
-
}
|
|
3459
|
-
// swallow error operation not supported error that occurs when binding in the
|
|
3460
|
-
// browser where this isn't supported
|
|
3461
|
-
try {
|
|
3462
|
-
sock.sock_ops.listen(sock, 0);
|
|
3463
|
-
} catch (e) {
|
|
3464
|
-
if (!(e.name === 'ErrnoError')) throw e;
|
|
3465
|
-
if (e.errno !== 138) throw e;
|
|
3466
|
-
}
|
|
3467
|
-
}
|
|
3468
|
-
},
|
|
3469
|
-
connect(sock, addr, port) {
|
|
3470
|
-
if (sock.server) {
|
|
3471
|
-
throw new FS.ErrnoError(138);
|
|
3472
|
-
}
|
|
3473
|
-
|
|
3474
|
-
// TODO autobind
|
|
3475
|
-
// if (!sock.addr && sock.type == 2) {
|
|
3476
|
-
// }
|
|
3477
|
-
|
|
3478
|
-
// early out if we're already connected / in the middle of connecting
|
|
3479
|
-
if (typeof sock.daddr != 'undefined' && typeof sock.dport != 'undefined') {
|
|
3480
|
-
var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
|
|
3481
|
-
if (dest) {
|
|
3482
|
-
if (dest.socket.readyState === dest.socket.CONNECTING) {
|
|
3483
|
-
throw new FS.ErrnoError(7);
|
|
3484
|
-
} else {
|
|
3485
|
-
throw new FS.ErrnoError(30);
|
|
3486
|
-
}
|
|
3487
|
-
}
|
|
3488
|
-
}
|
|
3489
|
-
|
|
3490
|
-
// add the socket to our peer list and set our
|
|
3491
|
-
// destination address / port to match
|
|
3492
|
-
var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
|
|
3493
|
-
sock.daddr = peer.addr;
|
|
3494
|
-
sock.dport = peer.port;
|
|
3495
|
-
|
|
3496
|
-
// because we cannot synchronously block to wait for the WebSocket
|
|
3497
|
-
// connection to complete, we return here pretending that the connection
|
|
3498
|
-
// was a success.
|
|
3499
|
-
sock.connecting = true;
|
|
3500
|
-
},
|
|
3501
|
-
listen(sock, backlog) {
|
|
3502
|
-
if (!ENVIRONMENT_IS_NODE) {
|
|
3503
|
-
throw new FS.ErrnoError(138);
|
|
3504
|
-
}
|
|
3505
|
-
if (sock.server) {
|
|
3506
|
-
throw new FS.ErrnoError(28); // already listening
|
|
3507
|
-
}
|
|
3508
|
-
var WebSocketServer = require('ws').Server;
|
|
3509
|
-
var host = sock.saddr;
|
|
3510
|
-
sock.server = new WebSocketServer({
|
|
3511
|
-
host,
|
|
3512
|
-
port: sock.sport
|
|
3513
|
-
// TODO support backlog
|
|
3514
|
-
});
|
|
3515
|
-
SOCKFS.emit('listen', sock.stream.fd); // Send Event with listen fd.
|
|
3516
|
-
|
|
3517
|
-
sock.server.on('connection', function(ws) {
|
|
3518
|
-
if (sock.type === 1) {
|
|
3519
|
-
var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol);
|
|
3520
|
-
|
|
3521
|
-
// create a peer on the new socket
|
|
3522
|
-
var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws);
|
|
3523
|
-
newsock.daddr = peer.addr;
|
|
3524
|
-
newsock.dport = peer.port;
|
|
3525
|
-
|
|
3526
|
-
// push to queue for accept to pick up
|
|
3527
|
-
sock.pending.push(newsock);
|
|
3528
|
-
SOCKFS.emit('connection', newsock.stream.fd);
|
|
3529
|
-
} else {
|
|
3530
|
-
// create a peer on the listen socket so calling sendto
|
|
3531
|
-
// with the listen socket and an address will resolve
|
|
3532
|
-
// to the correct client
|
|
3533
|
-
SOCKFS.websocket_sock_ops.createPeer(sock, ws);
|
|
3534
|
-
SOCKFS.emit('connection', sock.stream.fd);
|
|
3535
|
-
}
|
|
3536
|
-
});
|
|
3537
|
-
sock.server.on('close', function() {
|
|
3538
|
-
SOCKFS.emit('close', sock.stream.fd);
|
|
3539
|
-
sock.server = null;
|
|
3540
|
-
});
|
|
3541
|
-
sock.server.on('error', function(error) {
|
|
3542
|
-
// Although the ws library may pass errors that may be more descriptive than
|
|
3543
|
-
// ECONNREFUSED they are not necessarily the expected error code e.g.
|
|
3544
|
-
// ENOTFOUND on getaddrinfo seems to be node.js specific, so using EHOSTUNREACH
|
|
3545
|
-
// is still probably the most useful thing to do. This error shouldn't
|
|
3546
|
-
// occur in a well written app as errors should get trapped in the compiled
|
|
3547
|
-
// app's own getaddrinfo call.
|
|
3548
|
-
sock.error = 23; // Used in getsockopt for SOL_SOCKET/SO_ERROR test.
|
|
3549
|
-
SOCKFS.emit('error', [sock.stream.fd, sock.error, 'EHOSTUNREACH: Host is unreachable']);
|
|
3550
|
-
// don't throw
|
|
3551
|
-
});
|
|
3552
|
-
},
|
|
3553
|
-
accept(listensock) {
|
|
3554
|
-
if (!listensock.server || !listensock.pending.length) {
|
|
3555
|
-
throw new FS.ErrnoError(28);
|
|
3556
|
-
}
|
|
3557
|
-
var newsock = listensock.pending.shift();
|
|
3558
|
-
newsock.stream.flags = listensock.stream.flags;
|
|
3559
|
-
return newsock;
|
|
3560
|
-
},
|
|
3561
|
-
getname(sock, peer) {
|
|
3562
|
-
var addr, port;
|
|
3563
|
-
if (peer) {
|
|
3564
|
-
if (sock.daddr === undefined || sock.dport === undefined) {
|
|
3565
|
-
throw new FS.ErrnoError(53);
|
|
3566
|
-
}
|
|
3567
|
-
addr = sock.daddr;
|
|
3568
|
-
port = sock.dport;
|
|
3569
|
-
} else {
|
|
3570
|
-
// TODO saddr and sport will be set for bind()'d UDP sockets, but what
|
|
3571
|
-
// should we be returning for TCP sockets that've been connect()'d?
|
|
3572
|
-
addr = sock.saddr || 0;
|
|
3573
|
-
port = sock.sport || 0;
|
|
3574
|
-
}
|
|
3575
|
-
return { addr, port };
|
|
3576
|
-
},
|
|
3577
|
-
sendmsg(sock, buffer, offset, length, addr, port) {
|
|
3578
|
-
if (sock.type === 2) {
|
|
3579
|
-
// connection-less sockets will honor the message address,
|
|
3580
|
-
// and otherwise fall back to the bound destination address
|
|
3581
|
-
if (addr === undefined || port === undefined) {
|
|
3582
|
-
addr = sock.daddr;
|
|
3583
|
-
port = sock.dport;
|
|
3584
|
-
}
|
|
3585
|
-
// if there was no address to fall back to, error out
|
|
3586
|
-
if (addr === undefined || port === undefined) {
|
|
3587
|
-
throw new FS.ErrnoError(17);
|
|
3588
|
-
}
|
|
3589
|
-
} else {
|
|
3590
|
-
// connection-based sockets will only use the bound
|
|
3591
|
-
addr = sock.daddr;
|
|
3592
|
-
port = sock.dport;
|
|
3593
|
-
}
|
|
3594
|
-
|
|
3595
|
-
// find the peer for the destination address
|
|
3596
|
-
var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port);
|
|
3597
|
-
|
|
3598
|
-
// early out if not connected with a connection-based socket
|
|
3599
|
-
if (sock.type === 1) {
|
|
3600
|
-
if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
|
|
3601
|
-
throw new FS.ErrnoError(53);
|
|
3602
|
-
}
|
|
3603
|
-
}
|
|
3604
|
-
|
|
3605
|
-
// create a copy of the incoming data to send, as the WebSocket API
|
|
3606
|
-
// doesn't work entirely with an ArrayBufferView, it'll just send
|
|
3607
|
-
// the entire underlying buffer
|
|
3608
|
-
if (ArrayBuffer.isView(buffer)) {
|
|
3609
|
-
offset += buffer.byteOffset;
|
|
3610
|
-
buffer = buffer.buffer;
|
|
3611
|
-
}
|
|
3612
|
-
|
|
3613
|
-
var data = buffer.slice(offset, offset + length);
|
|
3614
|
-
|
|
3615
|
-
// if we don't have a cached connectionless UDP datagram connection, or
|
|
3616
|
-
// the TCP socket is still connecting, queue the message to be sent upon
|
|
3617
|
-
// connect, and lie, saying the data was sent now.
|
|
3618
|
-
if (!dest || dest.socket.readyState !== dest.socket.OPEN) {
|
|
3619
|
-
// if we're not connected, open a new connection
|
|
3620
|
-
if (sock.type === 2) {
|
|
3621
|
-
if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
|
|
3622
|
-
dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
|
|
3623
|
-
}
|
|
3624
|
-
}
|
|
3625
|
-
dest.msg_send_queue.push(data);
|
|
3626
|
-
return length;
|
|
3627
|
-
}
|
|
3628
|
-
|
|
3629
|
-
try {
|
|
3630
|
-
// send the actual data
|
|
3631
|
-
dest.socket.send(data);
|
|
3632
|
-
return length;
|
|
3633
|
-
} catch (e) {
|
|
3634
|
-
throw new FS.ErrnoError(28);
|
|
3635
|
-
}
|
|
3636
|
-
},
|
|
3637
|
-
recvmsg(sock, length) {
|
|
3638
|
-
// http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html
|
|
3639
|
-
if (sock.type === 1 && sock.server) {
|
|
3640
|
-
// tcp servers should not be recv()'ing on the listen socket
|
|
3641
|
-
throw new FS.ErrnoError(53);
|
|
3642
|
-
}
|
|
3643
|
-
|
|
3644
|
-
var queued = sock.recv_queue.shift();
|
|
3645
|
-
if (!queued) {
|
|
3646
|
-
if (sock.type === 1) {
|
|
3647
|
-
var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
|
|
3648
|
-
|
|
3649
|
-
if (!dest) {
|
|
3650
|
-
// if we have a destination address but are not connected, error out
|
|
3651
|
-
throw new FS.ErrnoError(53);
|
|
3652
|
-
}
|
|
3653
|
-
if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
|
|
3654
|
-
// return null if the socket has closed
|
|
3655
|
-
return null;
|
|
3656
|
-
}
|
|
3657
|
-
// else, our socket is in a valid state but truly has nothing available
|
|
3658
|
-
throw new FS.ErrnoError(6);
|
|
3659
|
-
}
|
|
3660
|
-
throw new FS.ErrnoError(6);
|
|
3661
|
-
}
|
|
3662
|
-
|
|
3663
|
-
// queued.data will be an ArrayBuffer if it's unadulterated, but if it's
|
|
3664
|
-
// requeued TCP data it'll be an ArrayBufferView
|
|
3665
|
-
var queuedLength = queued.data.byteLength || queued.data.length;
|
|
3666
|
-
var queuedOffset = queued.data.byteOffset || 0;
|
|
3667
|
-
var queuedBuffer = queued.data.buffer || queued.data;
|
|
3668
|
-
var bytesRead = Math.min(length, queuedLength);
|
|
3669
|
-
var res = {
|
|
3670
|
-
buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead),
|
|
3671
|
-
addr: queued.addr,
|
|
3672
|
-
port: queued.port
|
|
3673
|
-
};
|
|
3674
|
-
|
|
3675
|
-
// push back any unread data for TCP connections
|
|
3676
|
-
if (sock.type === 1 && bytesRead < queuedLength) {
|
|
3677
|
-
var bytesRemaining = queuedLength - bytesRead;
|
|
3678
|
-
queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining);
|
|
3679
|
-
sock.recv_queue.unshift(queued);
|
|
3680
|
-
}
|
|
3681
|
-
|
|
3682
|
-
return res;
|
|
3683
|
-
},
|
|
3684
|
-
},
|
|
3685
|
-
};
|
|
3686
|
-
|
|
3687
|
-
var getSocketFromFD = (fd) => {
|
|
3688
|
-
var socket = SOCKFS.getSocket(fd);
|
|
3689
|
-
if (!socket) throw new FS.ErrnoError(8);
|
|
3690
|
-
return socket;
|
|
3691
|
-
};
|
|
3692
|
-
|
|
3693
|
-
var inetPton4 = (str) => {
|
|
3694
|
-
var b = str.split('.');
|
|
3695
|
-
for (var i = 0; i < 4; i++) {
|
|
3696
|
-
var tmp = Number(b[i]);
|
|
3697
|
-
if (isNaN(tmp)) return null;
|
|
3698
|
-
b[i] = tmp;
|
|
3699
|
-
}
|
|
3700
|
-
return (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0;
|
|
3701
|
-
};
|
|
3702
|
-
|
|
3703
|
-
var inetPton6 = (str) => {
|
|
3704
|
-
var words;
|
|
3705
|
-
var w, offset, z, i;
|
|
3706
|
-
/* http://home.deds.nl/~aeron/regex/ */
|
|
3707
|
-
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
|
|
3708
|
-
var parts = [];
|
|
3709
|
-
if (!valid6regx.test(str)) {
|
|
3710
|
-
return null;
|
|
3711
|
-
}
|
|
3712
|
-
if (str === "::") {
|
|
3713
|
-
return [0, 0, 0, 0, 0, 0, 0, 0];
|
|
3714
|
-
}
|
|
3715
|
-
// Z placeholder to keep track of zeros when splitting the string on ":"
|
|
3716
|
-
if (str.startsWith("::")) {
|
|
3717
|
-
str = str.replace("::", "Z:"); // leading zeros case
|
|
3718
|
-
} else {
|
|
3719
|
-
str = str.replace("::", ":Z:");
|
|
3720
|
-
}
|
|
3721
|
-
|
|
3722
|
-
if (str.indexOf(".") > 0) {
|
|
3723
|
-
// parse IPv4 embedded address
|
|
3724
|
-
str = str.replace(new RegExp('[.]', 'g'), ":");
|
|
3725
|
-
words = str.split(":");
|
|
3726
|
-
words[words.length-4] = Number(words[words.length-4]) + Number(words[words.length-3])*256;
|
|
3727
|
-
words[words.length-3] = Number(words[words.length-2]) + Number(words[words.length-1])*256;
|
|
3728
|
-
words = words.slice(0, words.length-2);
|
|
3729
|
-
} else {
|
|
3730
|
-
words = str.split(":");
|
|
3731
|
-
}
|
|
3732
|
-
|
|
3733
|
-
offset = 0; z = 0;
|
|
3734
|
-
for (w=0; w < words.length; w++) {
|
|
3735
|
-
if (typeof words[w] == 'string') {
|
|
3736
|
-
if (words[w] === 'Z') {
|
|
3737
|
-
// compressed zeros - write appropriate number of zero words
|
|
3738
|
-
for (z = 0; z < (8 - words.length+1); z++) {
|
|
3739
|
-
parts[w+z] = 0;
|
|
3740
|
-
}
|
|
3741
|
-
offset = z-1;
|
|
3742
|
-
} else {
|
|
3743
|
-
// parse hex field to 16-bit value and write it in network byte-order
|
|
3744
|
-
parts[w+offset] = _htons(parseInt(words[w],16));
|
|
3745
|
-
}
|
|
3746
|
-
} else {
|
|
3747
|
-
// parsed IPv4 words
|
|
3748
|
-
parts[w+offset] = words[w];
|
|
3749
|
-
}
|
|
3750
|
-
}
|
|
3751
|
-
return [
|
|
3752
|
-
(parts[1] << 16) | parts[0],
|
|
3753
|
-
(parts[3] << 16) | parts[2],
|
|
3754
|
-
(parts[5] << 16) | parts[4],
|
|
3755
|
-
(parts[7] << 16) | parts[6]
|
|
3756
|
-
];
|
|
3757
|
-
};
|
|
3758
|
-
|
|
3759
|
-
var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size);
|
|
3760
|
-
|
|
3761
|
-
/** @param {number=} addrlen */
|
|
3762
|
-
var writeSockaddr = (sa, family, addr, port, addrlen) => {
|
|
3763
|
-
switch (family) {
|
|
3764
|
-
case 2:
|
|
3765
|
-
addr = inetPton4(addr);
|
|
3766
|
-
zeroMemory(sa, 16);
|
|
3767
|
-
if (addrlen) {
|
|
3768
|
-
HEAP32[((addrlen)>>2)] = 16;
|
|
3769
|
-
}
|
|
3770
|
-
HEAP16[((sa)>>1)] = family;
|
|
3771
|
-
HEAP32[(((sa)+(4))>>2)] = addr;
|
|
3772
|
-
HEAP16[(((sa)+(2))>>1)] = _htons(port);
|
|
3773
|
-
break;
|
|
3774
|
-
case 10:
|
|
3775
|
-
addr = inetPton6(addr);
|
|
3776
|
-
zeroMemory(sa, 28);
|
|
3777
|
-
if (addrlen) {
|
|
3778
|
-
HEAP32[((addrlen)>>2)] = 28;
|
|
3779
|
-
}
|
|
3780
|
-
HEAP32[((sa)>>2)] = family;
|
|
3781
|
-
HEAP32[(((sa)+(8))>>2)] = addr[0];
|
|
3782
|
-
HEAP32[(((sa)+(12))>>2)] = addr[1];
|
|
3783
|
-
HEAP32[(((sa)+(16))>>2)] = addr[2];
|
|
3784
|
-
HEAP32[(((sa)+(20))>>2)] = addr[3];
|
|
3785
|
-
HEAP16[(((sa)+(2))>>1)] = _htons(port);
|
|
3786
|
-
break;
|
|
3787
|
-
default:
|
|
3788
|
-
return 5;
|
|
3789
|
-
}
|
|
3790
|
-
return 0;
|
|
3791
|
-
};
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
var DNS = {
|
|
3795
|
-
address_map:{
|
|
3796
|
-
id:1,
|
|
3797
|
-
addrs:{
|
|
3798
|
-
},
|
|
3799
|
-
names:{
|
|
3800
|
-
},
|
|
3801
|
-
},
|
|
3802
|
-
lookup_name(name) {
|
|
3803
|
-
// If the name is already a valid ipv4 / ipv6 address, don't generate a fake one.
|
|
3804
|
-
var res = inetPton4(name);
|
|
3805
|
-
if (res !== null) {
|
|
3806
|
-
return name;
|
|
3807
|
-
}
|
|
3808
|
-
res = inetPton6(name);
|
|
3809
|
-
if (res !== null) {
|
|
3810
|
-
return name;
|
|
3811
|
-
}
|
|
3812
|
-
|
|
3813
|
-
// See if this name is already mapped.
|
|
3814
|
-
var addr;
|
|
3815
|
-
|
|
3816
|
-
if (DNS.address_map.addrs[name]) {
|
|
3817
|
-
addr = DNS.address_map.addrs[name];
|
|
3818
|
-
} else {
|
|
3819
|
-
var id = DNS.address_map.id++;
|
|
3820
|
-
|
|
3821
|
-
addr = '172.29.' + (id & 0xff) + '.' + (id & 0xff00);
|
|
3822
|
-
|
|
3823
|
-
DNS.address_map.names[addr] = name;
|
|
3824
|
-
DNS.address_map.addrs[name] = addr;
|
|
3825
|
-
}
|
|
3826
|
-
|
|
3827
|
-
return addr;
|
|
3828
|
-
},
|
|
3829
|
-
lookup_addr(addr) {
|
|
3830
|
-
if (DNS.address_map.names[addr]) {
|
|
3831
|
-
return DNS.address_map.names[addr];
|
|
3832
|
-
}
|
|
3833
|
-
|
|
3834
|
-
return null;
|
|
3835
|
-
},
|
|
3836
|
-
};
|
|
3837
|
-
function ___syscall_accept4(fd, addr, addrlen, flags, d1, d2) {
|
|
3838
|
-
try {
|
|
3839
|
-
|
|
3840
|
-
var sock = getSocketFromFD(fd);
|
|
3841
|
-
var newsock = sock.sock_ops.accept(sock);
|
|
3842
|
-
if (addr) {
|
|
3843
|
-
var errno = writeSockaddr(addr, newsock.family, DNS.lookup_name(newsock.daddr), newsock.dport, addrlen);
|
|
3844
|
-
}
|
|
3845
|
-
return newsock.stream.fd;
|
|
3846
|
-
} catch (e) {
|
|
3847
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
3848
|
-
return -e.errno;
|
|
3849
|
-
}
|
|
3850
|
-
}
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
var inetNtop4 = (addr) =>
|
|
3854
|
-
(addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff);
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
var inetNtop6 = (ints) => {
|
|
3858
|
-
// ref: http://www.ietf.org/rfc/rfc2373.txt - section 2.5.4
|
|
3859
|
-
// Format for IPv4 compatible and mapped 128-bit IPv6 Addresses
|
|
3860
|
-
// 128-bits are split into eight 16-bit words
|
|
3861
|
-
// stored in network byte order (big-endian)
|
|
3862
|
-
// | 80 bits | 16 | 32 bits |
|
|
3863
|
-
// +-----------------------------------------------------------------+
|
|
3864
|
-
// | 10 bytes | 2 | 4 bytes |
|
|
3865
|
-
// +--------------------------------------+--------------------------+
|
|
3866
|
-
// + 5 words | 1 | 2 words |
|
|
3867
|
-
// +--------------------------------------+--------------------------+
|
|
3868
|
-
// |0000..............................0000|0000| IPv4 ADDRESS | (compatible)
|
|
3869
|
-
// +--------------------------------------+----+---------------------+
|
|
3870
|
-
// |0000..............................0000|FFFF| IPv4 ADDRESS | (mapped)
|
|
3871
|
-
// +--------------------------------------+----+---------------------+
|
|
3872
|
-
var str = "";
|
|
3873
|
-
var word = 0;
|
|
3874
|
-
var longest = 0;
|
|
3875
|
-
var lastzero = 0;
|
|
3876
|
-
var zstart = 0;
|
|
3877
|
-
var len = 0;
|
|
3878
|
-
var i = 0;
|
|
3879
|
-
var parts = [
|
|
3880
|
-
ints[0] & 0xffff,
|
|
3881
|
-
(ints[0] >> 16),
|
|
3882
|
-
ints[1] & 0xffff,
|
|
3883
|
-
(ints[1] >> 16),
|
|
3884
|
-
ints[2] & 0xffff,
|
|
3885
|
-
(ints[2] >> 16),
|
|
3886
|
-
ints[3] & 0xffff,
|
|
3887
|
-
(ints[3] >> 16)
|
|
3888
|
-
];
|
|
3889
|
-
|
|
3890
|
-
// Handle IPv4-compatible, IPv4-mapped, loopback and any/unspecified addresses
|
|
3891
|
-
|
|
3892
|
-
var hasipv4 = true;
|
|
3893
|
-
var v4part = "";
|
|
3894
|
-
// check if the 10 high-order bytes are all zeros (first 5 words)
|
|
3895
|
-
for (i = 0; i < 5; i++) {
|
|
3896
|
-
if (parts[i] !== 0) { hasipv4 = false; break; }
|
|
3897
|
-
}
|
|
3898
|
-
|
|
3899
|
-
if (hasipv4) {
|
|
3900
|
-
// low-order 32-bits store an IPv4 address (bytes 13 to 16) (last 2 words)
|
|
3901
|
-
v4part = inetNtop4(parts[6] | (parts[7] << 16));
|
|
3902
|
-
// IPv4-mapped IPv6 address if 16-bit value (bytes 11 and 12) == 0xFFFF (6th word)
|
|
3903
|
-
if (parts[5] === -1) {
|
|
3904
|
-
str = "::ffff:";
|
|
3905
|
-
str += v4part;
|
|
3906
|
-
return str;
|
|
3907
|
-
}
|
|
3908
|
-
// IPv4-compatible IPv6 address if 16-bit value (bytes 11 and 12) == 0x0000 (6th word)
|
|
3909
|
-
if (parts[5] === 0) {
|
|
3910
|
-
str = "::";
|
|
3911
|
-
// special case IPv6 addresses
|
|
3912
|
-
if (v4part === "0.0.0.0") v4part = ""; // any/unspecified address
|
|
3913
|
-
if (v4part === "0.0.0.1") v4part = "1";// loopback address
|
|
3914
|
-
str += v4part;
|
|
3915
|
-
return str;
|
|
3916
|
-
}
|
|
3917
|
-
}
|
|
3918
|
-
|
|
3919
|
-
// Handle all other IPv6 addresses
|
|
3920
|
-
|
|
3921
|
-
// first run to find the longest contiguous zero words
|
|
3922
|
-
for (word = 0; word < 8; word++) {
|
|
3923
|
-
if (parts[word] === 0) {
|
|
3924
|
-
if (word - lastzero > 1) {
|
|
3925
|
-
len = 0;
|
|
3926
|
-
}
|
|
3927
|
-
lastzero = word;
|
|
3928
|
-
len++;
|
|
3929
|
-
}
|
|
3930
|
-
if (len > longest) {
|
|
3931
|
-
longest = len;
|
|
3932
|
-
zstart = word - longest + 1;
|
|
3933
|
-
}
|
|
3934
|
-
}
|
|
3935
|
-
|
|
3936
|
-
for (word = 0; word < 8; word++) {
|
|
3937
|
-
if (longest > 1) {
|
|
3938
|
-
// compress contiguous zeros - to produce "::"
|
|
3939
|
-
if (parts[word] === 0 && word >= zstart && word < (zstart + longest) ) {
|
|
3940
|
-
if (word === zstart) {
|
|
3941
|
-
str += ":";
|
|
3942
|
-
if (zstart === 0) str += ":"; //leading zeros case
|
|
3943
|
-
}
|
|
3944
|
-
continue;
|
|
3945
|
-
}
|
|
3946
|
-
}
|
|
3947
|
-
// converts 16-bit words from big-endian to little-endian before converting to hex string
|
|
3948
|
-
str += Number(_ntohs(parts[word] & 0xffff)).toString(16);
|
|
3949
|
-
str += word < 7 ? ":" : "";
|
|
3950
|
-
}
|
|
3951
|
-
return str;
|
|
3952
|
-
};
|
|
3953
|
-
|
|
3954
|
-
var readSockaddr = (sa, salen) => {
|
|
3955
|
-
// family / port offsets are common to both sockaddr_in and sockaddr_in6
|
|
3956
|
-
var family = HEAP16[((sa)>>1)];
|
|
3957
|
-
var port = _ntohs(HEAPU16[(((sa)+(2))>>1)]);
|
|
3958
|
-
var addr;
|
|
3959
|
-
|
|
3960
|
-
switch (family) {
|
|
3961
|
-
case 2:
|
|
3962
|
-
if (salen !== 16) {
|
|
3963
|
-
return { errno: 28 };
|
|
3964
|
-
}
|
|
3965
|
-
addr = HEAP32[(((sa)+(4))>>2)];
|
|
3966
|
-
addr = inetNtop4(addr);
|
|
3967
|
-
break;
|
|
3968
|
-
case 10:
|
|
3969
|
-
if (salen !== 28) {
|
|
3970
|
-
return { errno: 28 };
|
|
3971
|
-
}
|
|
3972
|
-
addr = [
|
|
3973
|
-
HEAP32[(((sa)+(8))>>2)],
|
|
3974
|
-
HEAP32[(((sa)+(12))>>2)],
|
|
3975
|
-
HEAP32[(((sa)+(16))>>2)],
|
|
3976
|
-
HEAP32[(((sa)+(20))>>2)]
|
|
3977
|
-
];
|
|
3978
|
-
addr = inetNtop6(addr);
|
|
3979
|
-
break;
|
|
3980
|
-
default:
|
|
3981
|
-
return { errno: 5 };
|
|
3982
|
-
}
|
|
3983
|
-
|
|
3984
|
-
return { family: family, addr: addr, port: port };
|
|
3985
|
-
};
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
var getSocketAddress = (addrp, addrlen) => {
|
|
3989
|
-
var info = readSockaddr(addrp, addrlen);
|
|
3990
|
-
if (info.errno) throw new FS.ErrnoError(info.errno);
|
|
3991
|
-
info.addr = DNS.lookup_addr(info.addr) || info.addr;
|
|
3992
|
-
return info;
|
|
3993
|
-
};
|
|
3994
|
-
function ___syscall_bind(fd, addr, addrlen, d1, d2, d3) {
|
|
3995
|
-
try {
|
|
3996
|
-
|
|
3997
|
-
var sock = getSocketFromFD(fd);
|
|
3998
|
-
var info = getSocketAddress(addr, addrlen);
|
|
3999
|
-
sock.sock_ops.bind(sock, info.addr, info.port);
|
|
4000
|
-
return 0;
|
|
4001
|
-
} catch (e) {
|
|
4002
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
4003
|
-
return -e.errno;
|
|
4004
|
-
}
|
|
4005
|
-
}
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
/**
|
|
4011
|
-
* Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
|
|
4012
|
-
* emscripten HEAP, returns a copy of that string as a Javascript String object.
|
|
4013
|
-
*
|
|
4014
|
-
* @param {number} ptr
|
|
4015
|
-
* @param {number=} maxBytesToRead - An optional length that specifies the
|
|
4016
|
-
* maximum number of bytes to read. You can omit this parameter to scan the
|
|
4017
|
-
* string until the first 0 byte. If maxBytesToRead is passed, and the string
|
|
4018
|
-
* at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
|
|
4019
|
-
* string will cut short at that byte index.
|
|
4020
|
-
* @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
|
|
4021
|
-
* @return {string}
|
|
4022
|
-
*/
|
|
4023
|
-
var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => {
|
|
4024
|
-
return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : '';
|
|
4025
|
-
};
|
|
4026
|
-
var SYSCALLS = {
|
|
4027
|
-
calculateAt(dirfd, path, allowEmpty) {
|
|
4028
|
-
if (PATH.isAbs(path)) {
|
|
4029
|
-
return path;
|
|
4030
|
-
}
|
|
4031
|
-
// relative path
|
|
4032
|
-
var dir;
|
|
4033
|
-
if (dirfd === -100) {
|
|
4034
|
-
dir = FS.cwd();
|
|
4035
|
-
} else {
|
|
4036
|
-
var dirstream = SYSCALLS.getStreamFromFD(dirfd);
|
|
4037
|
-
dir = dirstream.path;
|
|
4038
|
-
}
|
|
4039
|
-
if (path.length == 0) {
|
|
4040
|
-
if (!allowEmpty) {
|
|
4041
|
-
throw new FS.ErrnoError(44);;
|
|
4042
|
-
}
|
|
4043
|
-
return dir;
|
|
4044
|
-
}
|
|
4045
|
-
return dir + '/' + path;
|
|
4046
|
-
},
|
|
4047
|
-
writeStat(buf, stat) {
|
|
4048
|
-
HEAPU32[((buf)>>2)] = stat.dev;
|
|
4049
|
-
HEAPU32[(((buf)+(4))>>2)] = stat.mode;
|
|
4050
|
-
HEAPU32[(((buf)+(8))>>2)] = stat.nlink;
|
|
4051
|
-
HEAPU32[(((buf)+(12))>>2)] = stat.uid;
|
|
4052
|
-
HEAPU32[(((buf)+(16))>>2)] = stat.gid;
|
|
4053
|
-
HEAPU32[(((buf)+(20))>>2)] = stat.rdev;
|
|
4054
|
-
HEAP64[(((buf)+(24))>>3)] = BigInt(stat.size);
|
|
4055
|
-
HEAP32[(((buf)+(32))>>2)] = 4096;
|
|
4056
|
-
HEAP32[(((buf)+(36))>>2)] = stat.blocks;
|
|
4057
|
-
var atime = stat.atime.getTime();
|
|
4058
|
-
var mtime = stat.mtime.getTime();
|
|
4059
|
-
var ctime = stat.ctime.getTime();
|
|
4060
|
-
HEAP64[(((buf)+(40))>>3)] = BigInt(Math.floor(atime / 1000));
|
|
4061
|
-
HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000 * 1000;
|
|
4062
|
-
HEAP64[(((buf)+(56))>>3)] = BigInt(Math.floor(mtime / 1000));
|
|
4063
|
-
HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000 * 1000;
|
|
4064
|
-
HEAP64[(((buf)+(72))>>3)] = BigInt(Math.floor(ctime / 1000));
|
|
4065
|
-
HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000 * 1000;
|
|
4066
|
-
HEAP64[(((buf)+(88))>>3)] = BigInt(stat.ino);
|
|
4067
|
-
return 0;
|
|
4068
|
-
},
|
|
4069
|
-
writeStatFs(buf, stats) {
|
|
4070
|
-
HEAPU32[(((buf)+(4))>>2)] = stats.bsize;
|
|
4071
|
-
HEAPU32[(((buf)+(60))>>2)] = stats.bsize;
|
|
4072
|
-
HEAP64[(((buf)+(8))>>3)] = BigInt(stats.blocks);
|
|
4073
|
-
HEAP64[(((buf)+(16))>>3)] = BigInt(stats.bfree);
|
|
4074
|
-
HEAP64[(((buf)+(24))>>3)] = BigInt(stats.bavail);
|
|
4075
|
-
HEAP64[(((buf)+(32))>>3)] = BigInt(stats.files);
|
|
4076
|
-
HEAP64[(((buf)+(40))>>3)] = BigInt(stats.ffree);
|
|
4077
|
-
HEAPU32[(((buf)+(48))>>2)] = stats.fsid;
|
|
4078
|
-
HEAPU32[(((buf)+(64))>>2)] = stats.flags; // ST_NOSUID
|
|
4079
|
-
HEAPU32[(((buf)+(56))>>2)] = stats.namelen;
|
|
4080
|
-
},
|
|
4081
|
-
doMsync(addr, stream, len, flags, offset) {
|
|
4082
|
-
if (!FS.isFile(stream.node.mode)) {
|
|
4083
|
-
throw new FS.ErrnoError(43);
|
|
4084
|
-
}
|
|
4085
|
-
if (flags & 2) {
|
|
4086
|
-
// MAP_PRIVATE calls need not to be synced back to underlying fs
|
|
4087
|
-
return 0;
|
|
4088
|
-
}
|
|
4089
|
-
var buffer = HEAPU8.slice(addr, addr + len);
|
|
4090
|
-
FS.msync(stream, buffer, offset, len, flags);
|
|
4091
|
-
},
|
|
4092
|
-
getStreamFromFD(fd) {
|
|
4093
|
-
var stream = FS.getStreamChecked(fd);
|
|
4094
|
-
return stream;
|
|
3141
|
+
getStreamFromFD(fd) {
|
|
3142
|
+
var stream = FS.getStreamChecked(fd);
|
|
3143
|
+
return stream;
|
|
4095
3144
|
},
|
|
4096
3145
|
varargs:undefined,
|
|
4097
3146
|
getStr(ptr) {
|
|
@@ -4111,20 +3160,6 @@ async function createWasm() {
|
|
|
4111
3160
|
}
|
|
4112
3161
|
}
|
|
4113
3162
|
|
|
4114
|
-
|
|
4115
|
-
function ___syscall_connect(fd, addr, addrlen, d1, d2, d3) {
|
|
4116
|
-
try {
|
|
4117
|
-
|
|
4118
|
-
var sock = getSocketFromFD(fd);
|
|
4119
|
-
var info = getSocketAddress(addr, addrlen);
|
|
4120
|
-
sock.sock_ops.connect(sock, info.addr, info.port);
|
|
4121
|
-
return 0;
|
|
4122
|
-
} catch (e) {
|
|
4123
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
4124
|
-
return -e.errno;
|
|
4125
|
-
}
|
|
4126
|
-
}
|
|
4127
|
-
|
|
4128
3163
|
function ___syscall_dup(fd) {
|
|
4129
3164
|
try {
|
|
4130
3165
|
|
|
@@ -4346,18 +3381,6 @@ async function createWasm() {
|
|
|
4346
3381
|
}
|
|
4347
3382
|
}
|
|
4348
3383
|
|
|
4349
|
-
function ___syscall_listen(fd, backlog) {
|
|
4350
|
-
try {
|
|
4351
|
-
|
|
4352
|
-
var sock = getSocketFromFD(fd);
|
|
4353
|
-
sock.sock_ops.listen(sock, backlog);
|
|
4354
|
-
return 0;
|
|
4355
|
-
} catch (e) {
|
|
4356
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
4357
|
-
return -e.errno;
|
|
4358
|
-
}
|
|
4359
|
-
}
|
|
4360
|
-
|
|
4361
3384
|
function ___syscall_lstat64(path, buf) {
|
|
4362
3385
|
try {
|
|
4363
3386
|
|
|
@@ -4645,36 +3668,6 @@ async function createWasm() {
|
|
|
4645
3668
|
}
|
|
4646
3669
|
}
|
|
4647
3670
|
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) {
|
|
4651
|
-
try {
|
|
4652
|
-
|
|
4653
|
-
var sock = getSocketFromFD(fd);
|
|
4654
|
-
var msg = sock.sock_ops.recvmsg(sock, len);
|
|
4655
|
-
if (!msg) return 0; // socket is closed
|
|
4656
|
-
if (addr) {
|
|
4657
|
-
var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(msg.addr), msg.port, addrlen);
|
|
4658
|
-
}
|
|
4659
|
-
HEAPU8.set(msg.buffer, buf);
|
|
4660
|
-
return msg.buffer.byteLength;
|
|
4661
|
-
} catch (e) {
|
|
4662
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
4663
|
-
return -e.errno;
|
|
4664
|
-
}
|
|
4665
|
-
}
|
|
4666
|
-
|
|
4667
|
-
function ___syscall_socket(domain, type, protocol) {
|
|
4668
|
-
try {
|
|
4669
|
-
|
|
4670
|
-
var sock = SOCKFS.createSocket(domain, type, protocol);
|
|
4671
|
-
return sock.stream.fd;
|
|
4672
|
-
} catch (e) {
|
|
4673
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
4674
|
-
return -e.errno;
|
|
4675
|
-
}
|
|
4676
|
-
}
|
|
4677
|
-
|
|
4678
3671
|
function ___syscall_stat64(path, buf) {
|
|
4679
3672
|
try {
|
|
4680
3673
|
|
|
@@ -4812,36 +3805,6 @@ async function createWasm() {
|
|
|
4812
3805
|
return BigInt(ret);
|
|
4813
3806
|
};
|
|
4814
3807
|
|
|
4815
|
-
function __poll_js(fds, nfds, timeout, ctx, arg) {
|
|
4816
|
-
try {
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
var count = 0;
|
|
4820
|
-
for (var i = 0; i < nfds; i++) {
|
|
4821
|
-
var pollfd = fds + 8 * i;
|
|
4822
|
-
var fd = HEAP32[((pollfd)>>2)];
|
|
4823
|
-
var events = HEAP16[(((pollfd)+(4))>>1)];
|
|
4824
|
-
var flags = 32;
|
|
4825
|
-
var stream = FS.getStream(fd);
|
|
4826
|
-
if (stream) {
|
|
4827
|
-
if (stream.stream_ops.poll) {
|
|
4828
|
-
flags = stream.stream_ops.poll(stream, -1);
|
|
4829
|
-
} else {
|
|
4830
|
-
flags = 5;
|
|
4831
|
-
}
|
|
4832
|
-
}
|
|
4833
|
-
flags &= events | 8 | 16;
|
|
4834
|
-
if (flags) count++;
|
|
4835
|
-
HEAP16[(((pollfd)+(6))>>1)] = flags;
|
|
4836
|
-
}
|
|
4837
|
-
|
|
4838
|
-
return count;
|
|
4839
|
-
} catch (e) {
|
|
4840
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
4841
|
-
return -e.errno;
|
|
4842
|
-
}
|
|
4843
|
-
}
|
|
4844
|
-
|
|
4845
3808
|
var __timegm_js = function(tmPtr) {
|
|
4846
3809
|
|
|
4847
3810
|
var ret = (() => {
|
|
@@ -5227,182 +4190,6 @@ async function createWasm() {
|
|
|
5227
4190
|
}
|
|
5228
4191
|
}
|
|
5229
4192
|
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
var _getaddrinfo = (node, service, hint, out) => {
|
|
5239
|
-
// Note getaddrinfo currently only returns a single addrinfo with ai_next defaulting to NULL. When NULL
|
|
5240
|
-
// hints are specified or ai_family set to AF_UNSPEC or ai_socktype or ai_protocol set to 0 then we
|
|
5241
|
-
// really should provide a linked list of suitable addrinfo values.
|
|
5242
|
-
var addrs = [];
|
|
5243
|
-
var canon = null;
|
|
5244
|
-
var addr = 0;
|
|
5245
|
-
var port = 0;
|
|
5246
|
-
var flags = 0;
|
|
5247
|
-
var family = 0;
|
|
5248
|
-
var type = 0;
|
|
5249
|
-
var proto = 0;
|
|
5250
|
-
var ai, last;
|
|
5251
|
-
|
|
5252
|
-
function allocaddrinfo(family, type, proto, canon, addr, port) {
|
|
5253
|
-
var sa, salen, ai;
|
|
5254
|
-
var errno;
|
|
5255
|
-
|
|
5256
|
-
salen = family === 10 ?
|
|
5257
|
-
28 :
|
|
5258
|
-
16;
|
|
5259
|
-
addr = family === 10 ?
|
|
5260
|
-
inetNtop6(addr) :
|
|
5261
|
-
inetNtop4(addr);
|
|
5262
|
-
sa = _malloc(salen);
|
|
5263
|
-
errno = writeSockaddr(sa, family, addr, port);
|
|
5264
|
-
|
|
5265
|
-
ai = _malloc(32);
|
|
5266
|
-
HEAP32[(((ai)+(4))>>2)] = family;
|
|
5267
|
-
HEAP32[(((ai)+(8))>>2)] = type;
|
|
5268
|
-
HEAP32[(((ai)+(12))>>2)] = proto;
|
|
5269
|
-
HEAPU32[(((ai)+(24))>>2)] = canon;
|
|
5270
|
-
HEAPU32[(((ai)+(20))>>2)] = sa;
|
|
5271
|
-
if (family === 10) {
|
|
5272
|
-
HEAP32[(((ai)+(16))>>2)] = 28;
|
|
5273
|
-
} else {
|
|
5274
|
-
HEAP32[(((ai)+(16))>>2)] = 16;
|
|
5275
|
-
}
|
|
5276
|
-
HEAP32[(((ai)+(28))>>2)] = 0;
|
|
5277
|
-
|
|
5278
|
-
return ai;
|
|
5279
|
-
}
|
|
5280
|
-
|
|
5281
|
-
if (hint) {
|
|
5282
|
-
flags = HEAP32[((hint)>>2)];
|
|
5283
|
-
family = HEAP32[(((hint)+(4))>>2)];
|
|
5284
|
-
type = HEAP32[(((hint)+(8))>>2)];
|
|
5285
|
-
proto = HEAP32[(((hint)+(12))>>2)];
|
|
5286
|
-
}
|
|
5287
|
-
if (type && !proto) {
|
|
5288
|
-
proto = type === 2 ? 17 : 6;
|
|
5289
|
-
}
|
|
5290
|
-
if (!type && proto) {
|
|
5291
|
-
type = proto === 17 ? 2 : 1;
|
|
5292
|
-
}
|
|
5293
|
-
|
|
5294
|
-
// If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for
|
|
5295
|
-
// now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints.
|
|
5296
|
-
if (proto === 0) {
|
|
5297
|
-
proto = 6;
|
|
5298
|
-
}
|
|
5299
|
-
if (type === 0) {
|
|
5300
|
-
type = 1;
|
|
5301
|
-
}
|
|
5302
|
-
|
|
5303
|
-
if (!node && !service) {
|
|
5304
|
-
return -2;
|
|
5305
|
-
}
|
|
5306
|
-
if (flags & ~(1|2|4|
|
|
5307
|
-
1024|8|16|32)) {
|
|
5308
|
-
return -1;
|
|
5309
|
-
}
|
|
5310
|
-
if (hint !== 0 && (HEAP32[((hint)>>2)] & 2) && !node) {
|
|
5311
|
-
return -1;
|
|
5312
|
-
}
|
|
5313
|
-
if (flags & 32) {
|
|
5314
|
-
// TODO
|
|
5315
|
-
return -2;
|
|
5316
|
-
}
|
|
5317
|
-
if (type !== 0 && type !== 1 && type !== 2) {
|
|
5318
|
-
return -7;
|
|
5319
|
-
}
|
|
5320
|
-
if (family !== 0 && family !== 2 && family !== 10) {
|
|
5321
|
-
return -6;
|
|
5322
|
-
}
|
|
5323
|
-
|
|
5324
|
-
if (service) {
|
|
5325
|
-
service = UTF8ToString(service);
|
|
5326
|
-
port = parseInt(service, 10);
|
|
5327
|
-
|
|
5328
|
-
if (isNaN(port)) {
|
|
5329
|
-
if (flags & 1024) {
|
|
5330
|
-
return -2;
|
|
5331
|
-
}
|
|
5332
|
-
// TODO support resolving well-known service names from:
|
|
5333
|
-
// http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
|
|
5334
|
-
return -8;
|
|
5335
|
-
}
|
|
5336
|
-
}
|
|
5337
|
-
|
|
5338
|
-
if (!node) {
|
|
5339
|
-
if (family === 0) {
|
|
5340
|
-
family = 2;
|
|
5341
|
-
}
|
|
5342
|
-
if ((flags & 1) === 0) {
|
|
5343
|
-
if (family === 2) {
|
|
5344
|
-
addr = _htonl(2130706433);
|
|
5345
|
-
} else {
|
|
5346
|
-
addr = [0, 0, 0, _htonl(1)];
|
|
5347
|
-
}
|
|
5348
|
-
}
|
|
5349
|
-
ai = allocaddrinfo(family, type, proto, null, addr, port);
|
|
5350
|
-
HEAPU32[((out)>>2)] = ai;
|
|
5351
|
-
return 0;
|
|
5352
|
-
}
|
|
5353
|
-
|
|
5354
|
-
//
|
|
5355
|
-
// try as a numeric address
|
|
5356
|
-
//
|
|
5357
|
-
node = UTF8ToString(node);
|
|
5358
|
-
addr = inetPton4(node);
|
|
5359
|
-
if (addr !== null) {
|
|
5360
|
-
// incoming node is a valid ipv4 address
|
|
5361
|
-
if (family === 0 || family === 2) {
|
|
5362
|
-
family = 2;
|
|
5363
|
-
}
|
|
5364
|
-
else if (family === 10 && (flags & 8)) {
|
|
5365
|
-
addr = [0, 0, _htonl(0xffff), addr];
|
|
5366
|
-
family = 10;
|
|
5367
|
-
} else {
|
|
5368
|
-
return -2;
|
|
5369
|
-
}
|
|
5370
|
-
} else {
|
|
5371
|
-
addr = inetPton6(node);
|
|
5372
|
-
if (addr !== null) {
|
|
5373
|
-
// incoming node is a valid ipv6 address
|
|
5374
|
-
if (family === 0 || family === 10) {
|
|
5375
|
-
family = 10;
|
|
5376
|
-
} else {
|
|
5377
|
-
return -2;
|
|
5378
|
-
}
|
|
5379
|
-
}
|
|
5380
|
-
}
|
|
5381
|
-
if (addr != null) {
|
|
5382
|
-
ai = allocaddrinfo(family, type, proto, node, addr, port);
|
|
5383
|
-
HEAPU32[((out)>>2)] = ai;
|
|
5384
|
-
return 0;
|
|
5385
|
-
}
|
|
5386
|
-
if (flags & 4) {
|
|
5387
|
-
return -2;
|
|
5388
|
-
}
|
|
5389
|
-
|
|
5390
|
-
//
|
|
5391
|
-
// try as a hostname
|
|
5392
|
-
//
|
|
5393
|
-
// resolve the hostname to a temporary fake address
|
|
5394
|
-
node = DNS.lookup_name(node);
|
|
5395
|
-
addr = inetPton4(node);
|
|
5396
|
-
if (family === 0) {
|
|
5397
|
-
family = 2;
|
|
5398
|
-
} else if (family === 10) {
|
|
5399
|
-
addr = [0, 0, _htonl(0xffff), addr];
|
|
5400
|
-
}
|
|
5401
|
-
ai = allocaddrinfo(family, type, proto, null, addr, port);
|
|
5402
|
-
HEAPU32[((out)>>2)] = ai;
|
|
5403
|
-
return 0;
|
|
5404
|
-
};
|
|
5405
|
-
|
|
5406
4193
|
|
|
5407
4194
|
|
|
5408
4195
|
var handleException = (e) => {
|
|
@@ -5489,10 +4276,24 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
|
|
|
5489
4276
|
|
|
5490
4277
|
// end include: postlibrary.js
|
|
5491
4278
|
|
|
4279
|
+
function slicc_net_ready() { return Module.sliccKernel && Module.sliccKernel.net ? 1 : 0; }
|
|
4280
|
+
function slicc_socket_js(unix_domain,nonblock,cloexec) { return Module.sliccKernel.net.socket(unix_domain ? 'unix' : 'inet', !!nonblock, !!cloexec); }
|
|
4281
|
+
function slicc_socketpair_js(unix_domain,nonblock,cloexec,fds) { const r = Module.sliccKernel.net.socketpair(unix_domain ? 'unix' : 'inet', !!nonblock, !!cloexec); if (typeof r === 'number') return r; HEAP32[fds >> 2] = r[0]; HEAP32[(fds >> 2) + 1] = r[1]; return 0; }
|
|
4282
|
+
function slicc_bind_js(fd,family,ip,port,path,connect) { const host = [ ip >>> 24, (ip >>> 16) & 255, (ip >>> 8) & 255, ip & 255 ].join('.'); const addr = family === 1 ? { family : 'unix', path : UTF8ToString(path) } : { family : 'inet', host, port }; const net = Module.sliccKernel.net; return connect ? net.connect(fd, addr) : net.bind(fd, addr); }
|
|
4283
|
+
function slicc_listen_js(fd,backlog) { return Module.sliccKernel.net.listen(fd, backlog); }
|
|
4284
|
+
function slicc_addr_call_js(op,fd,arg,out) { const net = Module.sliccKernel.net; const r = op === 0 ? net.accept(fd, !!(arg & 1), !!(arg & 2)) : net.name(fd, op === 2); if (typeof r === 'number') return r; const a = op === 0 ? r.peer : r; if (a && a.family === 'unix') { HEAP32[out >> 2] = 1; const bytes = new TextEncoder().encode(a.path).subarray(0, 107); HEAPU8.set(bytes, out + 12); HEAPU8[out + 12 + bytes.length] = 0; } else if (a) { const q = a.host.split('.').map(Number); HEAP32[out >> 2] = 2; HEAPU32[(out + 4) >> 2] = ((q[0] << 24) | (q[1] << 16) | (q[2] << 8) | q[3]) >>> 0; HEAP32[(out + 8) >> 2] = a.port; } return op === 0 ? r.fd : 0; }
|
|
4285
|
+
function slicc_shutdown_js(fd,how) { return Module.sliccKernel.net.shutdown(fd, how); }
|
|
4286
|
+
function slicc_getopt_js(fd,level,name,value) { const r = Module.sliccKernel.net.getopt(fd, level, name); if (typeof r === 'number') return r; HEAP32[value >> 2] = r.value; return 0; }
|
|
4287
|
+
function slicc_setopt_js(fd,level,name,value) { return Module.sliccKernel.net.setopt(fd, level, name, value); }
|
|
4288
|
+
function slicc_send_js(fd,buf,len,dontwait,nosignal) { const bytes = HEAPU8.slice(buf, buf + len); return Module.sliccKernel.net.send(fd, bytes, { dontwait : !!dontwait, nosignal : !!nosignal }); }
|
|
4289
|
+
function slicc_recv_js(fd,buf,len,dontwait,peek) { const r = Module.sliccKernel.net.recv(fd, len, { dontwait : !!dontwait, peek : !!peek }); if (typeof r === 'number') return r; HEAPU8.set(r, buf); return r.length; }
|
|
4290
|
+
function slicc_resolve_js(name,out,max) { const net = Module.sliccKernel && Module.sliccKernel.net; if (!net || typeof net.resolve !== 'function') return -52; const r = net.resolve(UTF8ToString(name), 4); if (typeof r === 'number') return r < 0 ? r : -52; if (!Array.isArray(r)) return -52; let n = 0; for (const a of r) { const parts = String(a).split('.'); if (parts.length !== 4 || n >= max) continue; const q = parts.map(Number); if (q.some((x, i) => String(x) !== parts[i] || x > 255)) continue; HEAPU32[(out >> 2) + n++] = ((q[0] << 24) | (q[1] << 16) | (q[2] << 8) | q[3]) >>> 0; } return n; }
|
|
5492
4291
|
function slicc_spawn_capture_js(path,argv,envp,cwd,in_fd,out_fd,err_fd,actions,nactions) { const strings = (ptr) => { const out = []; for (let i = 0; ptr; i++) { const s = HEAPU32[(ptr >> 2) + i]; if (!s) break; out.push(UTF8ToString(s)); } return out; }; const isTty = (st) => st && FS.isChrdev(st.node.mode); const file = UTF8ToString(path); if (!file) return -44; const args = strings(argv); const envList = strings(envp); const env = {}; for (const kv of envList) { const eq = kv.indexOf('='); if (eq > 0) env[kv.slice(0, eq)] = kv.slice(eq + 1); } if (Module.sliccKernel) { const pairs = []; for (let i = 0; i < nactions; i++) { pairs.push([HEAP32[(actions >> 2) + 2 * i], HEAP32[(actions >> 2) + 2 * i + 1]]); } return Module.sliccKernel.spawn(file, args, envList.length ? env : null, cwd ? UTF8ToString(cwd) : null, [in_fd === -2 ? 0 : in_fd, out_fd, err_fd], pairs); } let input; if (in_fd >= 0) { try { const st = FS.getStream(in_fd); if (st && !isTty(st)) { const chunks = []; const buf = new Uint8Array(65536); let n; while ((n = FS.read(st, buf, 0, buf.length)) > 0) chunks.push(buf.slice(0, n)); if (chunks.length) input = Buffer.concat(chunks); } } catch (e) { } } if (Module.sliccBeforeSpawn) Module.sliccBeforeSpawn(); let r; try { r = require('child_process').spawnSync(file, args.slice(1), { cwd: cwd ? UTF8ToString(cwd) : FS.cwd(), env: envList.length ? env : process.env, input, }); } catch (e) { return e && e.code === 'ENOENT' ? -44 : -29; } finally { if (Module.sliccAfterSpawn) Module.sliccAfterSpawn(); } if (r.error) return r.error.code === 'ENOENT' ? -44 : -29; const put = (fd, data) => { if (fd < 0 || !data || !data.length) return; const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data; let st; try { st = FS.getStream(fd); } catch (e) {} if ((fd === 1 || fd === 2) && (!st || isTty(st))) { (fd === 1 ? process.stdout : process.stderr).write(bytes); return; } if (st) FS.write(st, bytes, 0, bytes.length); }; put(out_fd, r.stdout); put(err_fd, r.stderr); Module.sliccExited = Module.sliccExited || new Map(); Module.sliccNextPid = Module.sliccNextPid || 1000; const pid = ++Module.sliccNextPid; Module.sliccExited.set(pid, r.signal ? 9 : ((r.status ?? 1) & 0xff) << 8); return pid; }
|
|
5493
4292
|
function slicc_wait_js(pid,status,options) { const nohang = options & 1; const gone = (st) => (st & 0xff) !== 0x7f && st !== 0xffff; const done = Module.sliccExited; const kernel = Module.sliccKernel; if (kernel) { const put = (reaped, st) => { if (status && reaped > 0) HEAP32[status >> 2] = st; return reaped; }; const exitedKey = pid > 0 ? (done?.has(pid) ? pid : undefined) : done?.keys().next().value; if (exitedKey !== undefined) { const st = done.get(exitedKey); done.delete(exitedKey); return put(exitedKey, st); } const aliases = Module.sliccAliases; if (pid > 0 && aliases?.has(pid)) { const r = kernel.wait(aliases.get(pid), !!nohang, options); if (typeof r === 'number') return r; if (r[0] > 0 && gone(r[1])) aliases.delete(pid); return put(r[0] > 0 ? pid : 0, r[1]); } const r = kernel.wait(pid, !!nohang, options); if (typeof r === 'number') return r; for (const [forkPid, kernelPid] of aliases ?? []) { if (kernelPid !== r[0]) continue; if (gone(r[1])) aliases.delete(forkPid); return put(forkPid, r[1]); } return put(r[0], r[1]); } if (!done || done.size === 0) return -12; const key = pid > 0 ? pid : done.keys().next().value; if (!done.has(key)) return -12; if (status) HEAP32[status >> 2] = done.get(key); done.delete(key); return key; }
|
|
5494
4293
|
function slicc_exec_detach(pid) { if (!Module.sliccKernel || typeof SliccFork === 'undefined' || !SliccFork.stack.length) return 0; SliccFork.execPid = pid; return 1; }
|
|
5495
4294
|
function slicc_exec_wait_js(pid) { if (!Module.sliccKernel || !Module.sliccKernel.execWait) return -1; return Module.sliccKernel.execWait(pid); }
|
|
4295
|
+
function slicc_execve_js(path,argv,envp) { const k = Module.sliccKernel; if (!k || typeof k.execve !== 'function') return -0x40000000; const strings = (ptr) => { const out = []; for (let i = 0; ptr; i++) { const s = HEAPU32[(ptr >> 2) + i]; if (!s) break; out.push(UTF8ToString(s)); } return out; }; const file = UTF8ToString(path); if (!file) return -44; let env = null; if (envp) { env = {}; for (const kv of strings(envp)) { const eq = kv.indexOf('='); if (eq > 0) env[kv.slice(0, eq)] = kv.slice(eq + 1); } } return k.execve(file, strings(argv), env, null); }
|
|
4296
|
+
function slicc_in_emulated_fork() { return typeof SliccFork !== 'undefined' && SliccFork.stack.length > 0 ? 1 : 0; }
|
|
5496
4297
|
function slicc_sleep_ms(ms) { if (typeof SharedArrayBuffer === 'function' && typeof Atomics === 'object') { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); return; } const end = Date.now() + ms; while (Date.now() < end) {} }
|
|
5497
4298
|
function slicc_default_getpid_js() { return (Module.sliccPid | 0) || 42; }
|
|
5498
4299
|
function slicc_default_getppid_js() { return (Module.sliccPpid | 0) || 1; }
|
|
@@ -5503,16 +4304,12 @@ function slicc_poll_js(fds,n,timeout_ms) { const IN = 0x001 | 0x040; const OUT =
|
|
|
5503
4304
|
function slicc_jobs_js(op,a,b) { const k = Module.sliccKernel; if (!k || !k.setpgid) return -0x40000000; switch (op) { case 0: return k.setpgid(a, b); case 1: return k.getpgid(a); case 2: return k.getsid(a); case 3: return k.setsid(); case 4: return k.tcgetpgrp(a); case 5: return k.tcsetpgrp(a, b); } return -52; }
|
|
5504
4305
|
|
|
5505
4306
|
// Imports from the Wasm binary.
|
|
5506
|
-
var
|
|
5507
|
-
_fflush,
|
|
4307
|
+
var _fflush,
|
|
5508
4308
|
_main,
|
|
5509
4309
|
_slicc_sigpipe,
|
|
5510
4310
|
_slicc_raise,
|
|
5511
4311
|
_slicc_sig_mask,
|
|
5512
4312
|
___funcs_on_exit,
|
|
5513
|
-
_htonl,
|
|
5514
|
-
_htons,
|
|
5515
|
-
_ntohs,
|
|
5516
4313
|
_setThrew,
|
|
5517
4314
|
__emscripten_stack_restore,
|
|
5518
4315
|
__emscripten_stack_alloc,
|
|
@@ -5524,16 +4321,12 @@ var _malloc,
|
|
|
5524
4321
|
|
|
5525
4322
|
|
|
5526
4323
|
function assignWasmExports(wasmExports) {
|
|
5527
|
-
_malloc = wasmExports['malloc'];
|
|
5528
4324
|
_fflush = wasmExports['fflush'];
|
|
5529
4325
|
_main = Module['_main'] = wasmExports['__main_argc_argv'];
|
|
5530
4326
|
_slicc_sigpipe = Module['_slicc_sigpipe'] = wasmExports['slicc_sigpipe'];
|
|
5531
4327
|
_slicc_raise = Module['_slicc_raise'] = wasmExports['slicc_raise'];
|
|
5532
4328
|
_slicc_sig_mask = Module['_slicc_sig_mask'] = wasmExports['slicc_sig_mask'];
|
|
5533
4329
|
___funcs_on_exit = wasmExports['__funcs_on_exit'];
|
|
5534
|
-
_htonl = wasmExports['htonl'];
|
|
5535
|
-
_htons = wasmExports['htons'];
|
|
5536
|
-
_ntohs = wasmExports['ntohs'];
|
|
5537
4330
|
_setThrew = wasmExports['setThrew'];
|
|
5538
4331
|
__emscripten_stack_restore = wasmExports['_emscripten_stack_restore'];
|
|
5539
4332
|
__emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc'];
|
|
@@ -5544,16 +4337,12 @@ function assignWasmExports(wasmExports) {
|
|
|
5544
4337
|
|
|
5545
4338
|
var wasmImports = {
|
|
5546
4339
|
/** @export */
|
|
5547
|
-
|
|
5548
|
-
/** @export */
|
|
5549
|
-
__syscall_accept4: ___syscall_accept4,
|
|
4340
|
+
__assert_fail: ___assert_fail,
|
|
5550
4341
|
/** @export */
|
|
5551
|
-
|
|
4342
|
+
__call_sighandler: ___call_sighandler,
|
|
5552
4343
|
/** @export */
|
|
5553
4344
|
__syscall_chmod: ___syscall_chmod,
|
|
5554
4345
|
/** @export */
|
|
5555
|
-
__syscall_connect: ___syscall_connect,
|
|
5556
|
-
/** @export */
|
|
5557
4346
|
__syscall_dup: ___syscall_dup,
|
|
5558
4347
|
/** @export */
|
|
5559
4348
|
__syscall_dup3: ___syscall_dup3,
|
|
@@ -5566,8 +4355,6 @@ var wasmImports = {
|
|
|
5566
4355
|
/** @export */
|
|
5567
4356
|
__syscall_ioctl: ___syscall_ioctl,
|
|
5568
4357
|
/** @export */
|
|
5569
|
-
__syscall_listen: ___syscall_listen,
|
|
5570
|
-
/** @export */
|
|
5571
4358
|
__syscall_lstat64: ___syscall_lstat64,
|
|
5572
4359
|
/** @export */
|
|
5573
4360
|
__syscall_newfstatat: ___syscall_newfstatat,
|
|
@@ -5576,10 +4363,6 @@ var wasmImports = {
|
|
|
5576
4363
|
/** @export */
|
|
5577
4364
|
__syscall_pipe: ___syscall_pipe,
|
|
5578
4365
|
/** @export */
|
|
5579
|
-
__syscall_recvfrom: ___syscall_recvfrom,
|
|
5580
|
-
/** @export */
|
|
5581
|
-
__syscall_socket: ___syscall_socket,
|
|
5582
|
-
/** @export */
|
|
5583
4366
|
__syscall_stat64: ___syscall_stat64,
|
|
5584
4367
|
/** @export */
|
|
5585
4368
|
_abort_js: __abort_js,
|
|
@@ -5594,8 +4377,6 @@ var wasmImports = {
|
|
|
5594
4377
|
/** @export */
|
|
5595
4378
|
_mktime_js: __mktime_js,
|
|
5596
4379
|
/** @export */
|
|
5597
|
-
_poll_js: __poll_js,
|
|
5598
|
-
/** @export */
|
|
5599
4380
|
_timegm_js: __timegm_js,
|
|
5600
4381
|
/** @export */
|
|
5601
4382
|
_tzset_js: __tzset_js,
|
|
@@ -5622,8 +4403,6 @@ var wasmImports = {
|
|
|
5622
4403
|
/** @export */
|
|
5623
4404
|
fd_write: _fd_write,
|
|
5624
4405
|
/** @export */
|
|
5625
|
-
getaddrinfo: _getaddrinfo,
|
|
5626
|
-
/** @export */
|
|
5627
4406
|
invoke_i,
|
|
5628
4407
|
/** @export */
|
|
5629
4408
|
invoke_ii,
|
|
@@ -5634,6 +4413,8 @@ var wasmImports = {
|
|
|
5634
4413
|
/** @export */
|
|
5635
4414
|
invoke_iiiii,
|
|
5636
4415
|
/** @export */
|
|
4416
|
+
invoke_iiiiii,
|
|
4417
|
+
/** @export */
|
|
5637
4418
|
invoke_v,
|
|
5638
4419
|
/** @export */
|
|
5639
4420
|
invoke_vi,
|
|
@@ -5644,8 +4425,14 @@ var wasmImports = {
|
|
|
5644
4425
|
/** @export */
|
|
5645
4426
|
invoke_viiii,
|
|
5646
4427
|
/** @export */
|
|
4428
|
+
invoke_viiiiii,
|
|
4429
|
+
/** @export */
|
|
5647
4430
|
proc_exit: _proc_exit,
|
|
5648
4431
|
/** @export */
|
|
4432
|
+
slicc_addr_call_js,
|
|
4433
|
+
/** @export */
|
|
4434
|
+
slicc_bind_js,
|
|
4435
|
+
/** @export */
|
|
5649
4436
|
slicc_default_getpid_js,
|
|
5650
4437
|
/** @export */
|
|
5651
4438
|
slicc_default_getppid_js,
|
|
@@ -5654,12 +4441,32 @@ var wasmImports = {
|
|
|
5654
4441
|
/** @export */
|
|
5655
4442
|
slicc_exec_wait_js,
|
|
5656
4443
|
/** @export */
|
|
4444
|
+
slicc_execve_js,
|
|
4445
|
+
/** @export */
|
|
4446
|
+
slicc_in_emulated_fork,
|
|
4447
|
+
/** @export */
|
|
5657
4448
|
slicc_jobs_js,
|
|
5658
4449
|
/** @export */
|
|
5659
4450
|
slicc_kill_js,
|
|
5660
4451
|
/** @export */
|
|
4452
|
+
slicc_listen_js,
|
|
4453
|
+
/** @export */
|
|
4454
|
+
slicc_net_ready,
|
|
4455
|
+
/** @export */
|
|
4456
|
+
slicc_poll_js,
|
|
4457
|
+
/** @export */
|
|
4458
|
+
slicc_recv_js,
|
|
4459
|
+
/** @export */
|
|
4460
|
+
slicc_resolve_js,
|
|
4461
|
+
/** @export */
|
|
4462
|
+
slicc_setopt_js,
|
|
4463
|
+
/** @export */
|
|
4464
|
+
slicc_shutdown_js,
|
|
4465
|
+
/** @export */
|
|
5661
4466
|
slicc_sleep_ms,
|
|
5662
4467
|
/** @export */
|
|
4468
|
+
slicc_socket_js,
|
|
4469
|
+
/** @export */
|
|
5663
4470
|
slicc_spawn_capture_js,
|
|
5664
4471
|
/** @export */
|
|
5665
4472
|
slicc_wait_js
|
|
@@ -5775,6 +4582,28 @@ function invoke_viiii(index,a1,a2,a3,a4) {
|
|
|
5775
4582
|
}
|
|
5776
4583
|
}
|
|
5777
4584
|
|
|
4585
|
+
function invoke_iiiiii(index,a1,a2,a3,a4,a5) {
|
|
4586
|
+
var sp = stackSave();
|
|
4587
|
+
try {
|
|
4588
|
+
return getWasmTableEntry(index)(a1,a2,a3,a4,a5);
|
|
4589
|
+
} catch(e) {
|
|
4590
|
+
stackRestore(sp);
|
|
4591
|
+
if (e !== e+0) throw e;
|
|
4592
|
+
_setThrew(1, 0);
|
|
4593
|
+
}
|
|
4594
|
+
}
|
|
4595
|
+
|
|
4596
|
+
function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) {
|
|
4597
|
+
var sp = stackSave();
|
|
4598
|
+
try {
|
|
4599
|
+
getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6);
|
|
4600
|
+
} catch(e) {
|
|
4601
|
+
stackRestore(sp);
|
|
4602
|
+
if (e !== e+0) throw e;
|
|
4603
|
+
_setThrew(1, 0);
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
|
|
5778
4607
|
|
|
5779
4608
|
// include: postamble.js
|
|
5780
4609
|
// === Auto-generated postamble setup entry stuff ===
|