forked from cory/tildefriends
Compare commits
88 Commits
Author | SHA1 | Date | |
---|---|---|---|
fc3dd84122 | |||
9239441d73 | |||
b984811851 | |||
1c52446331 | |||
b6dffa8e66 | |||
315d650d27 | |||
07c121044a | |||
f3169afcf5 | |||
c371fc2a8e | |||
6889e11fd1 | |||
fb73fd0afc | |||
6fcebd7a08 | |||
15ea62a546 | |||
b0cd58f5aa | |||
7fe8f66fd3 | |||
68ca99e9d9 | |||
a2542c658b | |||
eb203c7e62 | |||
6ef466f3ed | |||
5074246462 | |||
73bbcebddb | |||
18128303b6 | |||
c4a2d790a3 | |||
c1ec150696 | |||
f4b856df15 | |||
85b87553dd | |||
5decdf3afa | |||
a4acee4939 | |||
d06aea2831 | |||
ae0a8b0a33 | |||
f0452704a1 | |||
b8b1f1ba80 | |||
caf7478da4 | |||
0e40ba78a4 | |||
d1eac6c9eb | |||
8f5201b2bc | |||
6022001d66 | |||
f018c367ed | |||
48c47f097a | |||
39ac215b5a | |||
7d562ce85c | |||
51b317233a | |||
87ce715011 | |||
ef5afc1e23 | |||
486212f22a | |||
0e8867dd6e | |||
ca28b5ca82 | |||
19e26c1759 | |||
790f6643a4 | |||
2158ad3c0b | |||
d904d8922f | |||
da50792500 | |||
b4629acc48 | |||
0cf4118330 | |||
dd61a6ecc3 | |||
8e6f1284e1 | |||
813d3cd492 | |||
f421606e21 | |||
1ccb9183b4 | |||
7d9b627f37 | |||
3038138909 | |||
2ca08d21e4 | |||
478e96fc5f | |||
e237c7ea1d | |||
bf9ff088fd | |||
e073ebedd1 | |||
10d4ae7dcc | |||
5b8bdbb3e4 | |||
c807e21c6b | |||
cc92d0e316 | |||
09c396d5a3 | |||
bc5bbca951 | |||
ed4faedcd7 | |||
251556ebed | |||
1324afb459 | |||
1119804fc2 | |||
cdf6440197 | |||
8727fe00af | |||
7da7890bb6 | |||
706bd2c51f | |||
acabec940e | |||
470b998b61 | |||
80fad05f23 | |||
07a912fb9a | |||
e9d83262c4 | |||
74323c22f9 | |||
2614e89b1b | |||
e092fe1399 |
67
Makefile
67
Makefile
@ -3,6 +3,10 @@
|
||||
MAKEFLAGS += --warn-undefined-variables
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
VERSION_CODE := 9
|
||||
VERSION_NUMBER := 0.0.9
|
||||
VERSION_NAME := Failure is the only opportunity to begin again.
|
||||
|
||||
PROJECT = tildefriends
|
||||
BUILD_DIR ?= out
|
||||
BUILD_TYPES := debug release windebug winrelease androiddebug androidrelease androiddebug-x86_64 androidrelease-x86_64
|
||||
@ -56,6 +60,7 @@ $(NONANDROID_TARGETS): LDFLAGS += -rdynamic
|
||||
$(ANDROID_TARGETS): CFLAGS += \
|
||||
--sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
|
||||
-fPIC \
|
||||
-fdebug-compilation-dir . \
|
||||
-fomit-frame-pointer \
|
||||
-fno-asynchronous-unwind-tables
|
||||
$(ANDROID_TARGETS): LDFLAGS += --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC
|
||||
@ -141,13 +146,10 @@ UV_SOURCES_unix := \
|
||||
deps/libuv/src/unix/async.c \
|
||||
deps/libuv/src/unix/core.c \
|
||||
deps/libuv/src/unix/dl.c \
|
||||
deps/libuv/src/unix/epoll.c \
|
||||
deps/libuv/src/unix/fs.c \
|
||||
deps/libuv/src/unix/getaddrinfo.c \
|
||||
deps/libuv/src/unix/getnameinfo.c \
|
||||
deps/libuv/src/unix/linux-core.c \
|
||||
deps/libuv/src/unix/linux-inotify.c \
|
||||
deps/libuv/src/unix/linux-syscalls.c \
|
||||
deps/libuv/src/unix/linux.c \
|
||||
deps/libuv/src/unix/loop-watcher.c \
|
||||
deps/libuv/src/unix/loop.c \
|
||||
deps/libuv/src/unix/pipe.c \
|
||||
@ -165,7 +167,6 @@ UV_SOURCES_unix := \
|
||||
deps/libuv/src/unix/tty.c \
|
||||
deps/libuv/src/unix/udp.c
|
||||
UV_SOURCES_android := \
|
||||
deps/libuv/src/unix/pthread-fixes.c \
|
||||
deps/libuv/src/unix/random-getentropy.c
|
||||
UV_SOURCES_win := \
|
||||
deps/libuv/src/win/async.c \
|
||||
@ -197,12 +198,13 @@ UV_OBJS := $(call get_objs,UV_SOURCES)
|
||||
$(UV_OBJS): CFLAGS += \
|
||||
-Ideps/libuv/include \
|
||||
-Ideps/libuv/src \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-incompatible-pointer-types \
|
||||
-Wno-sign-compare \
|
||||
-Wno-unused-variable \
|
||||
-Wno-dangling-pointer \
|
||||
-Wno-incompatible-pointer-types \
|
||||
-Wno-maybe-uninitialized \
|
||||
-Wno-sign-compare \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-unused-result \
|
||||
-Wno-unused-variable \
|
||||
-D_GNU_SOURCE
|
||||
|
||||
SODIUM_SOURCES := \
|
||||
@ -245,7 +247,8 @@ SODIUM_SOURCES := \
|
||||
deps/libsodium/src/libsodium/sodium/core.c \
|
||||
deps/libsodium/src/libsodium/sodium/codecs.c \
|
||||
deps/libsodium/src/libsodium/sodium/runtime.c \
|
||||
deps/libsodium/src/libsodium/sodium/utils.c
|
||||
deps/libsodium/src/libsodium/sodium/utils.c \
|
||||
deps/libsodium/src/libsodium/sodium/version.c
|
||||
SODIUM_OBJS := $(call get_objs,SODIUM_SOURCES)
|
||||
$(SODIUM_OBJS): CFLAGS += \
|
||||
-DCONFIGURED=1 \
|
||||
@ -254,6 +257,7 @@ $(SODIUM_OBJS): CFLAGS += \
|
||||
-Wno-unused-variable \
|
||||
-Wno-type-limits \
|
||||
-Wno-unknown-pragmas \
|
||||
-Ideps/libsodium/builds/msvc \
|
||||
-Ideps/libsodium/src/libsodium/include/sodium
|
||||
|
||||
SQLITE_SOURCES := deps/sqlite/sqlite3.c
|
||||
@ -375,15 +379,17 @@ debug release: LDFLAGS += \
|
||||
-lssl \
|
||||
-lcrypto
|
||||
windebug winrelease: LDFLAGS += \
|
||||
-lwsock32 \
|
||||
-lws2_32 \
|
||||
-lkernel32 \
|
||||
-liphlpapi \
|
||||
-luserenv \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-lcrypt32 \
|
||||
-ldbghelp \
|
||||
-liphlpapi \
|
||||
-lkernel32 \
|
||||
-lole32 \
|
||||
-luserenv \
|
||||
-luuid \
|
||||
-lws2_32 \
|
||||
-lcrypt32
|
||||
-lwsock32
|
||||
$(ANDROID_TARGETS): LDFLAGS += \
|
||||
-target $(ANDROID_NDK_TARGET_TRIPLE)$(ANDROID_NDK_API_VERSION) \
|
||||
-ldl \
|
||||
@ -432,15 +438,32 @@ endef
|
||||
|
||||
$(foreach build_type,$(BUILD_TYPES),$(eval $(call build_rules,$(build_type))))
|
||||
|
||||
src/version.h : $(firstword $(MAKEFILE_LIST))
|
||||
@echo [version] $@
|
||||
@echo "#define VERSION_NUMBER \"$(VERSION_NUMBER)\"\n#define VERSION_NAME \"$(VERSION_NAME)\"\n" > $@
|
||||
|
||||
src/android/AndroidManifest.xml : $(firstword $(MAKEFILE_LIST))
|
||||
@echo [android_version] $@
|
||||
@sed -i \
|
||||
-e 's/versionCode=".*"/versionCode="$(VERSION_CODE)"/' \
|
||||
-e 's/versionName=".*"/versionName="$(VERSION_NUMBER)"/' \
|
||||
-e 's/android:minSdkVersion=".*"/android:minSdkVersion="$(ANDROID_MIN_SDK_VERSION)"/' \
|
||||
$@
|
||||
|
||||
# Android support.
|
||||
out/res/layout_activity_main.xml.flat: src/android/res/layout/activity_main.xml
|
||||
@mkdir -p $(dir $@)
|
||||
@echo [aapt2] $@
|
||||
@$(ANDROID_BUILD_TOOLS)/aapt2 compile -o out/res/ src/android/res/layout/activity_main.xml
|
||||
|
||||
out/apk/res.apk out/gen/com/unprompted/tildefriends/R.java: out/res/layout_activity_main.xml.flat src/android/AndroidManifest.xml
|
||||
out/res/drawable_icon.xml.flat: src/android/res/drawable/icon.xml
|
||||
@mkdir -p $(dir $@)
|
||||
@$(ANDROID_BUILD_TOOLS)/aapt2 link -I $(ANDROID_PLATFORM)/android.jar out/res/layout_activity_main.xml.flat --manifest src/android/AndroidManifest.xml -o out/apk/res.apk --java out/gen/
|
||||
@echo [aapt2] $@
|
||||
@$(ANDROID_BUILD_TOOLS)/aapt2 compile -o out/res/ src/android/res/drawable/icon.xml
|
||||
|
||||
out/apk/res.apk out/gen/com/unprompted/tildefriends/R.java: out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat src/android/AndroidManifest.xml
|
||||
@mkdir -p $(dir $@)
|
||||
@$(ANDROID_BUILD_TOOLS)/aapt2 link -I $(ANDROID_PLATFORM)/android.jar out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat --manifest src/android/AndroidManifest.xml -o out/apk/res.apk --java out/gen/
|
||||
|
||||
JAVA_FILES := out/gen/com/unprompted/tildefriends/R.java $(wildcard src/android/com/unprompted/tildefriends/*.java)
|
||||
CLASS_FILES := $(foreach src,$(JAVA_FILES),out/classes/com/unprompted/tildefriends/$(notdir $(src:.java=.class)))
|
||||
@ -486,14 +509,18 @@ out/%.apk: out/apk/%.unsigned.apk
|
||||
@echo [apksigner] $(notdir $@)
|
||||
@$(ANDROID_BUILD_TOOLS)/apksigner sign --ks keystore.jks --ks-key-alias androidKey --ks-pass pass:android --key-pass pass:android --out $@ $<
|
||||
|
||||
apk: out/TildeFriends-debug.apk
|
||||
apk: out/TildeFriends-release.apk
|
||||
.PHONY: apk
|
||||
|
||||
apkgo: out/TildeFriends-debug.apk
|
||||
apkgo: out/TildeFriends-release.apk
|
||||
@adb install $<
|
||||
@adb shell am start com.unprompted.tildefriends/.MainActivity
|
||||
.PHONY: apkgo
|
||||
|
||||
apklog:
|
||||
@adb logcat *:S tildefriends
|
||||
.PHONY: apklog
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
.PHONY: clean
|
||||
|
@ -1,6 +1,6 @@
|
||||
async function get_apps() {
|
||||
let results = {};
|
||||
await ssb.sqlStream(`
|
||||
await ssb.sqlAsync(`
|
||||
SELECT messages.*
|
||||
FROM messages_fts('"application/tildefriends"')
|
||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||
@ -52,4 +52,4 @@ async function main() {
|
||||
`);
|
||||
}
|
||||
|
||||
main();
|
||||
main();
|
||||
|
@ -16,9 +16,7 @@
|
||||
- / => Something good.
|
||||
- update docs
|
||||
- audit + document API exposed to apps
|
||||
- sqlStream => sqlExec or something
|
||||
- fix weird HTTP warnings
|
||||
- ssb from child process?
|
||||
- channels
|
||||
- placeholder/missing images
|
||||
- no denial of service
|
||||
@ -57,7 +55,9 @@
|
||||
- keep working on good error feedback
|
||||
- build for windows
|
||||
- installable apps (bring back an app message?)
|
||||
- sqlStream => sqlExec or something
|
||||
- !ssb from child process?
|
||||
|
||||
## Done
|
||||
- update LICENSE
|
||||
- logging to browser
|
||||
- logging to browser
|
||||
|
4
apps/sneaker.json
Normal file
4
apps/sneaker.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "👟"
|
||||
}
|
30
apps/sneaker/app.js
Normal file
30
apps/sneaker/app.js
Normal file
@ -0,0 +1,30 @@
|
||||
import * as tfrpc from '/tfrpc.js';
|
||||
|
||||
tfrpc.register(async function getAllIdentities() {
|
||||
return ssb.getAllIdentities();
|
||||
});
|
||||
tfrpc.register(async function query(sql, args) {
|
||||
let result = [];
|
||||
await ssb.sqlAsync(sql, args, function callback(row) {
|
||||
result.push(row);
|
||||
});
|
||||
return result;
|
||||
});
|
||||
|
||||
tfrpc.register(async function store_blob(blob) {
|
||||
if (Array.isArray(blob)) {
|
||||
blob = Uint8Array.from(blob);
|
||||
}
|
||||
return await ssb.blobStore(blob);
|
||||
});
|
||||
tfrpc.register(async function get_blob(id) {
|
||||
return Array.from(new Uint8Array(await ssb.blobGet(id)));
|
||||
});
|
||||
tfrpc.register(async function store_message(message) {
|
||||
return await ssb.storeMessage(message);
|
||||
});
|
||||
|
||||
async function main() {
|
||||
await app.setDocument(utf8Decode(await getFile('index.html')));
|
||||
}
|
||||
main();
|
3
apps/sneaker/filesaver.min.js
vendored
Normal file
3
apps/sneaker/filesaver.min.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),g=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype&&!a?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(b,d,e,g){if(g=g||open("","_blank"),g&&(g.document.title=g.document.body.innerText="downloading..."),"string"==typeof b)return c(b,d,e);var h="application/octet-stream"===b.type,i=/constructor/i.test(f.HTMLElement)||f.safari,j=/CriOS\/[\d]+/.test(navigator.userAgent);if((j||h&&i||a)&&"undefined"!=typeof FileReader){var k=new FileReader;k.onloadend=function(){var a=k.result;a=j?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),g?g.location.href=a:location=a,g=null},k.readAsDataURL(b)}else{var l=f.URL||f.webkitURL,m=l.createObjectURL(b);g?g.location=m:location.href=m,g=null,setTimeout(function(){l.revokeObjectURL(m)},4E4)}});f.saveAs=g.saveAs=g,"undefined"!=typeof module&&(module.exports=g)});
|
||||
|
||||
//# sourceMappingURL=FileSaver.min.js.map
|
14
apps/sneaker/index.html
Normal file
14
apps/sneaker/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html style="color: #fff">
|
||||
<head>
|
||||
<title>Tilde Friends</title>
|
||||
<base target="_top">
|
||||
</head>
|
||||
<body>
|
||||
<tf-sneaker-app/>
|
||||
<script>window.litDisableBundleWarning = true;</script>
|
||||
<script src="filesaver.min.js"></script>
|
||||
<script src="jszip.min.js"></script>
|
||||
<script src="script.js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
13
apps/sneaker/jszip.min.js
vendored
Normal file
13
apps/sneaker/jszip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
126
apps/sneaker/lit-all.min.js
vendored
Normal file
126
apps/sneaker/lit-all.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
apps/sneaker/lit-all.min.js.map
Normal file
1
apps/sneaker/lit-all.min.js.map
Normal file
File diff suppressed because one or more lines are too long
226
apps/sneaker/script.js
Normal file
226
apps/sneaker/script.js
Normal file
@ -0,0 +1,226 @@
|
||||
import {LitElement, html} from './lit-all.min.js';
|
||||
import * as tfrpc from '/static/tfrpc.js';
|
||||
|
||||
class TfSneakerAppElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
feeds: {type: Object},
|
||||
progress: {type: Object},
|
||||
result: {type: String},
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.feeds = [];
|
||||
this.progress = undefined;
|
||||
this.result = undefined;
|
||||
}
|
||||
|
||||
async search() {
|
||||
let q = this.renderRoot.getElementById('search').value;
|
||||
let result = await tfrpc.rpc.query(`
|
||||
SELECT messages.author AS id, json_extract(messages.content, '$.name') AS name
|
||||
FROM messages_fts(?)
|
||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||
WHERE
|
||||
json_extract(messages.content, '$.type') = 'about' AND
|
||||
json_extract(messages.content, '$.about') = messages.author AND
|
||||
json_extract(messages.content, '$.name') IS NOT NULL
|
||||
GROUP BY messages.author
|
||||
HAVING MAX(messages.sequence)
|
||||
ORDER BY COUNT(*) DESC
|
||||
`,
|
||||
[`"${q.replaceAll('"', '""')}"`]);
|
||||
this.feeds = Object.fromEntries(result.map(x => [x.id, x.name]));
|
||||
}
|
||||
|
||||
format_message(message) {
|
||||
let out = {
|
||||
previous: message.previous ?? null,
|
||||
};
|
||||
if (message.sequence_before_author) {
|
||||
out.sequence = message.sequence;
|
||||
out.author = message.author;
|
||||
} else {
|
||||
out.author = message.author;
|
||||
out.sequence = message.sequence;
|
||||
}
|
||||
out.timestamp = message.timestamp;
|
||||
out.hash = message.hash;
|
||||
out.content = JSON.parse(message.content);
|
||||
out.signature = message.signature;
|
||||
return {key: message.id, value: out};
|
||||
}
|
||||
|
||||
sanitize(value) {
|
||||
return value.replaceAll('/', '_').replaceAll('+', '-');
|
||||
}
|
||||
|
||||
guess_ext(data) {
|
||||
function startsWith(prefix) {
|
||||
if (data.length < prefix.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < prefix.length; i++) {
|
||||
if (prefix[i] !== null && data[i] !== prefix[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (startsWith(data, [0xff, 0xd8, 0xff, 0xdb]) ||
|
||||
startsWith(data, [0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01]) ||
|
||||
startsWith(data, [0xff, 0xd8, 0xff, 0xee]) ||
|
||||
startsWith(data, [0xff, 0xd8, 0xff, 0xe1, null, null, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00])) {
|
||||
return '.jpg';
|
||||
} else if (startsWith(data, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) {
|
||||
return '.png';
|
||||
} else if (startsWith(data, [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]) ||
|
||||
startsWith(data, [0x47, 0x49, 0x46, 0x38, 0x39, 0x61])) {
|
||||
return '.gif';
|
||||
} else if (startsWith(data, [0x52, 0x49, 0x46, 0x46, null, null, null, null, 0x57, 0x45, 0x42, 0x50])) {
|
||||
return '.webp';
|
||||
} else if (startsWith(data, [0x3c, 0x73, 0x76, 0x67])) {
|
||||
return '.svg';
|
||||
} else if (startsWith(data, [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32])) {
|
||||
return '.mp3';
|
||||
} else if (startsWith(data, [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6f, 0x6d]) ||
|
||||
startsWith(data, [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32])) {
|
||||
return '.mp4';
|
||||
} else {
|
||||
return '.bin';
|
||||
}
|
||||
}
|
||||
|
||||
async export(id) {
|
||||
let all_messages = '';
|
||||
let sequence = -1;
|
||||
let messages_done = 0;
|
||||
let messages_max = (await tfrpc.rpc.query('SELECT MAX(sequence) AS total FROM messages WHERE author = ?', [id]))[0].total;
|
||||
while (true) {
|
||||
let messages = await tfrpc.rpc.query(
|
||||
'SELECT * FROM messages WHERE author = ? AND SEQUENCE > ? ORDER BY sequence LIMIT 100',
|
||||
[id, sequence]
|
||||
);
|
||||
if (messages?.length) {
|
||||
all_messages += messages.map(x => JSON.stringify(this.format_message(x))).join('\n') + '\n';
|
||||
sequence = messages[messages.length - 1].sequence;
|
||||
messages_done += messages.length;
|
||||
this.progress = {name: 'messages', value: messages_done, max: messages_max};
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let zip = new JSZip();
|
||||
zip.file(`message/classic/${this.sanitize(id)}.ndjson`, all_messages);
|
||||
|
||||
let blobs = await tfrpc.rpc.query(
|
||||
`SELECT blobs.id
|
||||
FROM messages
|
||||
JOIN messages_refs ON messages.id = messages_refs.message
|
||||
JOIN blobs ON messages_refs.ref = blobs.id
|
||||
WHERE messages.author = ?`,
|
||||
[id]);
|
||||
let blobs_done = 0;
|
||||
for (let row of blobs) {
|
||||
this.progress = {name: 'blobs', value: blobs_done, max: blobs.length};
|
||||
let blob = await tfrpc.rpc.get_blob(row.id);
|
||||
zip.file(`blob/classic/${this.sanitize(row.id)}${this.guess_ext(blob)}`, new Uint8Array(blob));
|
||||
blobs_done++;
|
||||
}
|
||||
|
||||
this.progress = {name: 'saving'};
|
||||
let blob = await zip.generateAsync({type: 'blob'});
|
||||
saveAs(blob, `${this.sanitize(id)}.zip`);
|
||||
this.progress = null;
|
||||
}
|
||||
|
||||
keypress(event) {
|
||||
if (event.key == 'Enter') {
|
||||
this.search();
|
||||
}
|
||||
}
|
||||
|
||||
async import(event) {
|
||||
let file = event.target.files[0];
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.progress = {name: 'loading'};
|
||||
let zip = new JSZip();
|
||||
file = await zip.loadAsync(file);
|
||||
let messages = [];
|
||||
let blobs = [];
|
||||
file.forEach(function(path, entry) {
|
||||
if (!entry.dir) {
|
||||
if (path.startsWith('message/classic/')) {
|
||||
messages.push(entry);
|
||||
} else {
|
||||
blobs.push(entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
let success = {messages: 0, blobs: 0};
|
||||
let progress = 0;
|
||||
let total_messages = 0;
|
||||
for (let entry of messages) {
|
||||
let lines = (await entry.async('string')).split('\n');
|
||||
total_messages += lines.length;
|
||||
for (let line of lines) {
|
||||
if (!line.length) {
|
||||
continue;
|
||||
}
|
||||
let message = JSON.parse(line);
|
||||
this.progress = {name: 'messages', value: progress++, max: total_messages};
|
||||
if (await tfrpc.rpc.store_message(message.value)) {
|
||||
success.messages++;
|
||||
}
|
||||
}
|
||||
}
|
||||
progress = 0;
|
||||
for (let blob of blobs) {
|
||||
this.progress = {name: 'blobs', value: progress++, max: blobs.length};
|
||||
if (await tfrpc.rpc.store_blob(await blob.async('arraybuffer'))) {
|
||||
success.blobs++;
|
||||
}
|
||||
}
|
||||
this.progress = undefined;
|
||||
this.result = `imported ${success.messages} messages and ${success.blobs} blobs`;
|
||||
}
|
||||
|
||||
render() {
|
||||
let progress;
|
||||
if (this.progress) {
|
||||
if (this.progress.max) {
|
||||
progress = html`<div><label for="progress">${this.progress.name}</label><progress value=${this.progress.value} max=${this.progress.max}></progress></div>`;
|
||||
} else {
|
||||
progress = html`<div><span>${this.progress.name}</span></div>`;
|
||||
}
|
||||
}
|
||||
return html`<h1>SSB 👟net</h1>
|
||||
<code>${this.result}</code>
|
||||
${progress}
|
||||
|
||||
<h2>Import</h2>
|
||||
<input type="file" id="import" @change=${this.import}></input>
|
||||
|
||||
<h2>Export</h2>
|
||||
<input type="text" id="search" @keypress=${this.keypress}></input>
|
||||
<input type="button" value="Search Users" @click=${this.search}></input>
|
||||
<ul>
|
||||
${Object.entries(this.feeds).map(([id, name]) => html`
|
||||
<li>
|
||||
${this.progress ? undefined : html`<input type="button" value="Export" @click=${() => this.export(id)}></input>`}
|
||||
${name}
|
||||
<code style="color: #ccc">${id}</code>
|
||||
</li>
|
||||
`)}
|
||||
</ul>
|
||||
`;
|
||||
}
|
||||
}
|
||||
customElements.define('tf-sneaker-app', TfSneakerAppElement);
|
@ -79,9 +79,15 @@ tfrpc.register(async function store_blob(blob) {
|
||||
tfrpc.register(async function get_blob(id) {
|
||||
return utf8Decode(await ssb.blobGet(id));
|
||||
});
|
||||
tfrpc.register(async function store_message(message) {
|
||||
return await ssb.storeMessage(message);
|
||||
});
|
||||
tfrpc.register(function apps() {
|
||||
return core.apps();
|
||||
});
|
||||
tfrpc.register(async function try_decrypt(id, content) {
|
||||
return await ssb.privateMessageDecrypt(id, content);
|
||||
});
|
||||
ssb.addEventListener('broadcasts', async function() {
|
||||
await tfrpc.rpc.set('broadcasts', await ssb.getBroadcasts());
|
||||
});
|
||||
|
@ -54,21 +54,27 @@ export function picker(callback, anchor) {
|
||||
}
|
||||
}
|
||||
|
||||
function chosen(event) {
|
||||
console.log(event.srcElement.innerText);
|
||||
callback(event.srcElement.innerText);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
while (list.firstChild) {
|
||||
list.removeChild(list.firstChild);
|
||||
}
|
||||
let search = input.value;
|
||||
let any_at_all = false;
|
||||
Object.entries(json).forEach(function(row) {
|
||||
for (let row of Object.entries(json)) {
|
||||
let header = document.createElement('div');
|
||||
header.appendChild(document.createTextNode(row[0]));
|
||||
list.appendChild(header);
|
||||
let any = false;
|
||||
for (let entry of row[1]) {
|
||||
for (let entry of Object.entries(row[1])) {
|
||||
if (search &&
|
||||
search.length &&
|
||||
entry.name.indexOf(search) == -1) {
|
||||
entry[0].indexOf(search) == -1) {
|
||||
continue;
|
||||
}
|
||||
let emoji = document.createElement('span');
|
||||
@ -76,12 +82,9 @@ export function picker(callback, anchor) {
|
||||
emoji.style.display = 'inline-block';
|
||||
emoji.style.overflow = 'hidden';
|
||||
emoji.style.cursor = 'pointer';
|
||||
emoji.onclick = function() {
|
||||
callback(entry);
|
||||
cleanup();
|
||||
};
|
||||
emoji.title = entry.name;
|
||||
emoji.appendChild(document.createTextNode(entry.emoji));
|
||||
emoji.onclick = chosen;
|
||||
emoji.title = entry[0];
|
||||
emoji.appendChild(document.createTextNode(entry[1]));
|
||||
list.appendChild(emoji);
|
||||
any = true;
|
||||
any_at_all = true;
|
||||
@ -89,7 +92,7 @@ export function picker(callback, anchor) {
|
||||
if (!any) {
|
||||
list.removeChild(header);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!any_at_all) {
|
||||
list.appendChild(document.createTextNode('No matches found.'));
|
||||
}
|
||||
|
15116
apps/ssb/emojis.json
15116
apps/ssb/emojis.json
File diff suppressed because one or more lines are too long
3
apps/ssb/filesaver.min.js
vendored
Normal file
3
apps/ssb/filesaver.min.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),g=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype&&!a?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(b,d,e,g){if(g=g||open("","_blank"),g&&(g.document.title=g.document.body.innerText="downloading..."),"string"==typeof b)return c(b,d,e);var h="application/octet-stream"===b.type,i=/constructor/i.test(f.HTMLElement)||f.safari,j=/CriOS\/[\d]+/.test(navigator.userAgent);if((j||h&&i||a)&&"undefined"!=typeof FileReader){var k=new FileReader;k.onloadend=function(){var a=k.result;a=j?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),g?g.location.href=a:location=a,g=null},k.readAsDataURL(b)}else{var l=f.URL||f.webkitURL,m=l.createObjectURL(b);g?g.location=m:location.href=m,g=null,setTimeout(function(){l.revokeObjectURL(m)},4E4)}});f.saveAs=g.saveAs=g,"undefined"!=typeof module&&(module.exports=g)});
|
||||
|
||||
//# sourceMappingURL=FileSaver.min.js.map
|
@ -13,6 +13,7 @@
|
||||
<body>
|
||||
<tf-app/>
|
||||
<script>window.litDisableBundleWarning = true;</script>
|
||||
<script src="filesaver.min.js"></script>
|
||||
<script src="commonmark.min.js"></script>
|
||||
<script src="commonmark-linkify.js" type="module"></script>
|
||||
<script src="commonmark-hashtag.js" type="module"></script>
|
||||
|
8
apps/ssb/lit-all.min.js
vendored
8
apps/ssb/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -8,6 +8,9 @@ import * as tf_user from './tf-user.js';
|
||||
import * as tf_compose from './tf-compose.js';
|
||||
import * as tf_news from './tf-news.js';
|
||||
import * as tf_profile from './tf-profile.js';
|
||||
import * as tf_tab_mentions from './tf-tab-mentions.js';
|
||||
import * as tf_tab_news from './tf-tab-news.js';
|
||||
import * as tf_tab_news_feed from './tf-tab-news-feed.js';
|
||||
import * as tf_tab_search from './tf-tab-search.js';
|
||||
import * as tf_tab_connections from './tf-tab-connections.js';
|
||||
import * as tf_tag from './tf-tag.js';
|
@ -16,6 +16,7 @@ class TfElement extends LitElement {
|
||||
following: {type: Array},
|
||||
users: {type: Object},
|
||||
ids: {type: Array},
|
||||
tags: {type: Array},
|
||||
};
|
||||
}
|
||||
|
||||
@ -32,6 +33,7 @@ class TfElement extends LitElement {
|
||||
this.following = [];
|
||||
this.users = {};
|
||||
this.loaded = false;
|
||||
this.tags = [];
|
||||
tfrpc.rpc.getBroadcasts().then(b => { self.broadcasts = b || []; });
|
||||
tfrpc.rpc.getConnections().then(c => { self.connections = c || []; });
|
||||
tfrpc.rpc.getHash().then(hash => self.set_hash(hash));
|
||||
@ -64,6 +66,8 @@ class TfElement extends LitElement {
|
||||
this.tab = 'search';
|
||||
} else if (this.hash === '#connections') {
|
||||
this.tab = 'connections';
|
||||
} else if (this.hash === '#mentions') {
|
||||
this.tab = 'mentions';
|
||||
} else {
|
||||
this.tab = 'news';
|
||||
}
|
||||
@ -251,12 +255,34 @@ class TfElement extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
async load_recent_tags() {
|
||||
let start = new Date();
|
||||
this.tags = await tfrpc.rpc.query(`
|
||||
WITH
|
||||
recent AS (SELECT id, content FROM messages
|
||||
WHERE messages.timestamp > ? AND json_extract(content, '$.type') = 'post'
|
||||
ORDER BY timestamp DESC LIMIT 1024),
|
||||
recent_channels AS (SELECT recent.id, '#' || json_extract(content, '$.channel') AS tag
|
||||
FROM recent
|
||||
WHERE json_extract(content, '$.channel') IS NOT NULL),
|
||||
recent_mentions AS (SELECT recent.id, json_extract(mention.value, '$.link') AS tag
|
||||
FROM recent, json_each(recent.content, '$.mentions') AS mention
|
||||
WHERE json_valid(mention.value) AND tag LIKE '#%'),
|
||||
combined AS (SELECT id, tag FROM recent_channels UNION ALL SELECT id, tag FROM recent_mentions),
|
||||
by_message AS (SELECT DISTINCT id, tag FROM combined)
|
||||
SELECT tag, COUNT(*) AS count FROM by_message GROUP BY tag ORDER BY count DESC LIMIT 10
|
||||
`, [new Date() - 7 * 24 * 60 * 60 * 1000]);
|
||||
console.log('tags took', (new Date() - start) / 1000.0, 'seconds');
|
||||
}
|
||||
|
||||
async load() {
|
||||
let whoami = this.whoami;
|
||||
let tags = this.load_recent_tags();
|
||||
let [following, users] = await this.following_deep([whoami], 2, {});
|
||||
users = await this.fetch_about(following.sort(), users);
|
||||
this.following = following;
|
||||
this.users = users;
|
||||
await tags;
|
||||
console.log(`load finished ${whoami} => ${this.whoami}`);
|
||||
this.whoami = whoami;
|
||||
this.loaded = whoami;
|
||||
@ -273,6 +299,10 @@ class TfElement extends LitElement {
|
||||
return html`
|
||||
<tf-tab-connections .users=${this.users} .connections=${this.connections} .broadcasts=${this.broadcasts}></tf-tab-connections>
|
||||
`;
|
||||
} else if (this.tab === 'mentions') {
|
||||
return html`
|
||||
<tf-tab-mentions .following=${this.following} whoami=${this.whoami} .users=${this.users}}></tf-tab-mentions>
|
||||
`;
|
||||
} else if (this.tab === 'search') {
|
||||
return html`
|
||||
<tf-tab-search .following=${this.following} whoami=${this.whoami} .users=${this.users} query=${this.hash?.startsWith('#q=') ? decodeURIComponent(this.hash.substring(3)) : null}></tf-tab-search>
|
||||
@ -286,6 +316,8 @@ class TfElement extends LitElement {
|
||||
await tfrpc.rpc.setHash('#');
|
||||
} else if (tab === 'connections') {
|
||||
await tfrpc.rpc.setHash('#connections');
|
||||
} else if (tab === 'mentions') {
|
||||
await tfrpc.rpc.setHash('#mentions');
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,6 +336,7 @@ class TfElement extends LitElement {
|
||||
<div>
|
||||
<input type="button" class="tab" value="News" ?disabled=${self.tab == 'news'} @click=${() => self.set_tab('news')}></input>
|
||||
<input type="button" class="tab" value="Connections" ?disabled=${self.tab == 'connections'} @click=${() => self.set_tab('connections')}></input>
|
||||
<input type="button" class="tab" value="Mentions" ?disabled=${self.tab == 'mentions'} @click=${() => self.set_tab('mentions')}></input>
|
||||
<input type="button" class="tab" value="Search" ?disabled=${self.tab == 'search'} @click=${() => self.set_tab('search')}></input>
|
||||
</div>
|
||||
`;
|
||||
@ -316,6 +349,7 @@ class TfElement extends LitElement {
|
||||
return html`
|
||||
${this.render_id_picker()}
|
||||
${tabs}
|
||||
${this.tags.map(x => html`<tf-tag tag=${x.tag} count=${x.count}></tf-tag>`)}
|
||||
${contents}
|
||||
`;
|
||||
}
|
||||
|
@ -256,9 +256,18 @@ class TfComposeElement extends LitElement {
|
||||
render_mention(mention) {
|
||||
let self = this;
|
||||
return html`
|
||||
<div>
|
||||
<pre style="white-space: pre-wrap">${JSON.stringify(mention, null, 2)}</pre>
|
||||
<input type="button" value="x" @click=${() => self.remove_mention(mention.link)}></input>
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div style="align-self: center; margin: 0.5em">
|
||||
<input type="button" value="🚮" title="Remove ${mention.name} mention" @click=${() => self.remove_mention(mention.link)}></input>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column">
|
||||
<h3>${mention.name}</h3>
|
||||
<div style="padding-left: 1em">
|
||||
${Object.entries(mention)
|
||||
.filter(x => x[0] != 'name')
|
||||
.map(x => html`<div><span style="font-weight: bold">${x[0]}</span>: ${x[1]}</div>`)}
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ class TfMessageElement extends LitElement {
|
||||
raw: {type: Boolean},
|
||||
blog_data: {type: String},
|
||||
expanded: {type: Object},
|
||||
decrypted: {type: Object},
|
||||
};
|
||||
}
|
||||
|
||||
@ -28,6 +29,7 @@ class TfMessageElement extends LitElement {
|
||||
this.drafts = {};
|
||||
this.raw = false;
|
||||
this.expanded = {};
|
||||
this.decrypted = undefined;
|
||||
}
|
||||
|
||||
show_reply() {
|
||||
@ -74,7 +76,7 @@ class TfMessageElement extends LitElement {
|
||||
}
|
||||
|
||||
vote(emoji) {
|
||||
let reaction = emoji.emoji;
|
||||
let reaction = emoji;
|
||||
let message = this.message.id;
|
||||
if (confirm('Are you sure you want to react with ' + reaction + ' to ' + message + '?')) {
|
||||
tfrpc.rpc.appendMessage(
|
||||
@ -218,8 +220,40 @@ class TfMessageElement extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
render_channels() {
|
||||
let content = this.message?.content;
|
||||
if (this.decrypted?.type == 'post') {
|
||||
content = this.decrypted;
|
||||
}
|
||||
let channels = [];
|
||||
if (typeof content.channel === 'string') {
|
||||
channels.push(`#${content.channel}`);
|
||||
}
|
||||
if (Array.isArray(content.mentions)) {
|
||||
for (let mention of content.mentions) {
|
||||
if (typeof mention?.link === 'string' &&
|
||||
mention.link.startsWith('#')) {
|
||||
channels.push(mention.link);
|
||||
}
|
||||
}
|
||||
}
|
||||
return channels.map(x => html`<tf-tag tag=${x}></tf-tag>`);
|
||||
}
|
||||
|
||||
async try_decrypt(content) {
|
||||
let result = await tfrpc.rpc.try_decrypt(this.whoami, content);
|
||||
if (result) {
|
||||
this.decrypted = JSON.parse(result);
|
||||
} else {
|
||||
this.decrypted = false;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let content = this.message?.content;
|
||||
if (this.decrypted?.type == 'post') {
|
||||
content = this.decrypted;
|
||||
}
|
||||
let self = this;
|
||||
let raw_button = this.raw ?
|
||||
html`<input type="button" value="Message" @click=${() => self.raw = false}></input>` :
|
||||
@ -316,6 +350,7 @@ class TfMessageElement extends LitElement {
|
||||
`;
|
||||
let content_html =
|
||||
html`
|
||||
${this.render_channels()}
|
||||
<div @click=${this.body_click}>${body}</div>
|
||||
${this.render_mentions()}
|
||||
`;
|
||||
@ -328,6 +363,8 @@ class TfMessageElement extends LitElement {
|
||||
` :
|
||||
content_warning :
|
||||
content_html;
|
||||
let is_encrypted = this.decrypted ? html`<span style="align-self: center">🔓</span>` : undefined;
|
||||
let style_background = this.decrypted ? 'rgba(255, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.1)';
|
||||
return html`
|
||||
<style>
|
||||
code {
|
||||
@ -343,9 +380,10 @@ class TfMessageElement extends LitElement {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<div style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px">
|
||||
<div style="border: 1px solid black; background-color: ${style_background}; margin-top: 8px; padding: 16px">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
||||
${is_encrypted}
|
||||
<span style="flex: 1"></span>
|
||||
<span style="padding-right: 8px"><a target="_top" href=${'#' + self.message.id}>%</a> ${new Date(this.message.timestamp).toLocaleString()}</span>
|
||||
<span>${raw_button}</span>
|
||||
@ -430,7 +468,14 @@ class TfMessageElement extends LitElement {
|
||||
</div>
|
||||
`);
|
||||
} else if (typeof(this.message.content) == 'string') {
|
||||
return small_frame(html`<span>🔒</span>`);
|
||||
if (this.decrypted) {
|
||||
return small_frame(html`<span>🔓</span><pre>${JSON.stringify(this.decrypted, null, 2)}</pre>`);
|
||||
} else if (this.decrypted === undefined) {
|
||||
this.try_decrypt(content);
|
||||
return small_frame(html`<span>🔐</span>`);
|
||||
} else {
|
||||
return small_frame(html`<span>🔒</span>`);
|
||||
}
|
||||
} else {
|
||||
return small_frame(html`<div><b>type</b>: ${content.type}</div>`);
|
||||
}
|
||||
|
@ -148,6 +148,10 @@ class TfProfileElement extends LitElement {
|
||||
<div><label for="description">Description:</label></div>
|
||||
<textarea id="description" @input=${event => this.editing = Object.assign({}, this.editing, {description: event.srcElement.value})}>${this.editing.description}</textarea>
|
||||
</div>
|
||||
<div>
|
||||
<label for="public_web_hosting">Public Web Hosting:</label>
|
||||
<input type="checkbox" id="public_web_hosting" value=${this.editing.public_web_hosting} @input=${event => this.editing = Object.assign({}, this.editing, {publicWebHosting: event.srcElement.checked})}></input>
|
||||
</div>
|
||||
<input type="button" value="Attach Image" @click=${this.attach_image}></input>
|
||||
</div>` : null;
|
||||
let image = typeof(profile.image) == 'string' ? profile.image : profile.image?.link;
|
||||
|
65
apps/ssb/tf-tab-mentions.js
Normal file
65
apps/ssb/tf-tab-mentions.js
Normal file
@ -0,0 +1,65 @@
|
||||
import {LitElement, html, unsafeHTML} from './lit-all.min.js';
|
||||
import * as tfrpc from '/static/tfrpc.js';
|
||||
import {styles} from './tf-styles.js';
|
||||
|
||||
class TfTabMentionsElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
whoami: {type: String},
|
||||
users: {type: Object},
|
||||
following: {type: Array},
|
||||
expanded: {type: Object},
|
||||
messages: {type: Array},
|
||||
};
|
||||
}
|
||||
|
||||
static styles = styles;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
let self = this;
|
||||
this.whoami = null;
|
||||
this.users = {};
|
||||
this.following = [];
|
||||
this.expanded = {};
|
||||
this.messages = [];
|
||||
}
|
||||
|
||||
async load() {
|
||||
console.log('Loading...', this.whoami);
|
||||
let results = await tfrpc.rpc.query(`
|
||||
SELECT messages.*
|
||||
FROM messages_fts(?)
|
||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE messages.author != ?
|
||||
ORDER BY timestamp DESC limit 20
|
||||
`,
|
||||
['"' + this.whoami.replace('"', '""') + '"', JSON.stringify(this.following), this.whoami]);
|
||||
console.log('Done.');
|
||||
this.messages = results;
|
||||
}
|
||||
|
||||
on_expand(event) {
|
||||
if (event.detail.expanded) {
|
||||
let expand = {};
|
||||
expand[event.detail.id] = true;
|
||||
this.expanded = Object.assign({}, this.expanded, expand);
|
||||
} else {
|
||||
delete this.expanded[event.detail.id];
|
||||
this.expanded = Object.assign({}, this.expanded);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let self = this;
|
||||
if (!this.loading) {
|
||||
this.loading = true;
|
||||
this.load();
|
||||
}
|
||||
return html`
|
||||
<tf-news id="news" whoami=${this.whoami} .messages=${this.messages} .users=${this.users} .expanded=${this.expanded} @tf-expand=${this.on_expand}></tf-news>
|
||||
`;
|
||||
}
|
||||
}
|
||||
customElements.define('tf-tab-mentions', TfTabMentionsElement);
|
154
apps/ssb/tf-tab-news-feed.js
Normal file
154
apps/ssb/tf-tab-news-feed.js
Normal file
@ -0,0 +1,154 @@
|
||||
import {LitElement, html, unsafeHTML, until} from './lit-all.min.js';
|
||||
import * as tfrpc from '/static/tfrpc.js';
|
||||
import {styles} from './tf-styles.js';
|
||||
|
||||
class TfTabNewsFeedElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
whoami: {type: String},
|
||||
users: {type: Object},
|
||||
hash: {type: String},
|
||||
following: {type: Array},
|
||||
messages: {type: Array},
|
||||
drafts: {type: Object},
|
||||
expanded: {type: Object},
|
||||
};
|
||||
}
|
||||
|
||||
static styles = styles;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
let self = this;
|
||||
this.whoami = null;
|
||||
this.users = {};
|
||||
this.hash = '#';
|
||||
this.following = [];
|
||||
this.drafts = {};
|
||||
this.expanded = {};
|
||||
this.start_time = new Date().valueOf() - 24 * 60 * 60 * 1000;
|
||||
}
|
||||
|
||||
async fetch_messages() {
|
||||
if (this.hash.startsWith('#@')) {
|
||||
let r = await tfrpc.rpc.query(
|
||||
`
|
||||
WITH mine AS (SELECT messages.*
|
||||
FROM messages
|
||||
WHERE messages.author = ?
|
||||
ORDER BY sequence DESC
|
||||
LIMIT 20)
|
||||
SELECT messages.*
|
||||
FROM mine
|
||||
JOIN messages_refs ON mine.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT * FROM mine
|
||||
`,
|
||||
[
|
||||
this.hash.substring(1),
|
||||
]);
|
||||
return r;
|
||||
} else if (this.hash.startsWith('#%')) {
|
||||
return await tfrpc.rpc.query(
|
||||
`
|
||||
SELECT messages.*
|
||||
FROM messages
|
||||
WHERE id = ?1
|
||||
UNION
|
||||
SELECT messages.*
|
||||
FROM messages JOIN messages_refs
|
||||
ON messages.id = messages_refs.message
|
||||
WHERE messages_refs.ref = ?1
|
||||
`,
|
||||
[
|
||||
this.hash.substring(1),
|
||||
]);
|
||||
} else {
|
||||
return await tfrpc.rpc.query(
|
||||
`
|
||||
WITH news AS (SELECT messages.*
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE messages.timestamp > ?
|
||||
ORDER BY messages.timestamp DESC)
|
||||
SELECT messages.*
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT messages.*
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
UNION
|
||||
SELECT news.* FROM news
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.following),
|
||||
this.start_time,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
async load_more() {
|
||||
let last_start_time = this.start_time;
|
||||
this.start_time = last_start_time - 24 * 60 * 60 * 1000;
|
||||
let more = await tfrpc.rpc.query(
|
||||
`
|
||||
WITH news AS (SELECT messages.*
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE messages.timestamp > ?
|
||||
AND messages.timestamp <= ?
|
||||
ORDER BY messages.timestamp DESC)
|
||||
SELECT messages.*
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT messages.*
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
UNION
|
||||
SELECT news.* FROM news
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.following),
|
||||
this.start_time,
|
||||
last_start_time,
|
||||
]);
|
||||
this.messages = [...more, ...this.messages];
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.messages ||
|
||||
this._messages_hash !== this.hash ||
|
||||
this._messages_following !== this.following) {
|
||||
console.log(`loading messages for ${this.whoami}`);
|
||||
let self = this;
|
||||
this.messages = [];
|
||||
this._messages_hash = this.hash;
|
||||
this._messages_following = this.following;
|
||||
this.fetch_messages().then(function(messages) {
|
||||
self.messages = messages;
|
||||
console.log(`loading mesages done for ${self.whoami}`);
|
||||
}).catch(function(error) {
|
||||
alert(JSON.stringify(error, null, 2));
|
||||
});
|
||||
}
|
||||
let more;
|
||||
if (!this.hash.startsWith('#@') && !this.hash.startsWith('#%')) {
|
||||
more = html`
|
||||
<input type="button" value="Load More" @click=${this.load_more}></input>
|
||||
`;
|
||||
}
|
||||
return html`
|
||||
<tf-news id="news" whoami=${this.whoami} .users=${this.users} .messages=${this.messages} .following=${this.following} .drafts=${this.drafts} .expanded=${this.expanded}></tf-news>
|
||||
${more}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('tf-tab-news-feed', TfTabNewsFeedElement);
|
@ -2,114 +2,6 @@ import {LitElement, html, unsafeHTML, until} from './lit-all.min.js';
|
||||
import * as tfrpc from '/static/tfrpc.js';
|
||||
import {styles} from './tf-styles.js';
|
||||
|
||||
class TfTabNewsFeedElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
whoami: {type: String},
|
||||
users: {type: Object},
|
||||
hash: {type: String},
|
||||
following: {type: Array},
|
||||
messages: {type: Array},
|
||||
drafts: {type: Object},
|
||||
expanded: {type: Object},
|
||||
};
|
||||
}
|
||||
|
||||
static styles = styles;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
let self = this;
|
||||
this.whoami = null;
|
||||
this.users = {};
|
||||
this.hash = '#';
|
||||
this.following = [];
|
||||
this.drafts = {};
|
||||
this.expanded = {};
|
||||
}
|
||||
|
||||
async fetch_messages() {
|
||||
if (this.hash.startsWith('#@')) {
|
||||
let r = await tfrpc.rpc.query(
|
||||
`
|
||||
WITH mine AS (SELECT messages.*
|
||||
FROM messages
|
||||
WHERE messages.author = ?
|
||||
ORDER BY sequence DESC
|
||||
LIMIT 20)
|
||||
SELECT messages.*
|
||||
FROM mine
|
||||
JOIN messages_refs ON mine.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT * FROM mine
|
||||
`,
|
||||
[
|
||||
this.hash.substring(1),
|
||||
]);
|
||||
return r;
|
||||
} else if (this.hash.startsWith('#%')) {
|
||||
return await tfrpc.rpc.query(
|
||||
`
|
||||
SELECT messages.*
|
||||
FROM messages
|
||||
WHERE id = ?1
|
||||
UNION
|
||||
SELECT messages.*
|
||||
FROM messages JOIN messages_refs
|
||||
ON messages.id = messages_refs.message
|
||||
WHERE messages_refs.ref = ?1
|
||||
`,
|
||||
[
|
||||
this.hash.substring(1),
|
||||
]);
|
||||
} else {
|
||||
return await tfrpc.rpc.query(
|
||||
`
|
||||
WITH news AS (SELECT messages.*
|
||||
FROM messages
|
||||
JOIN json_each(?) AS following ON messages.author = following.value
|
||||
WHERE messages.timestamp > ?
|
||||
ORDER BY messages.timestamp DESC)
|
||||
SELECT messages.*
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.ref
|
||||
JOIN messages ON messages_refs.message = messages.id
|
||||
UNION
|
||||
SELECT messages.*
|
||||
FROM news
|
||||
JOIN messages_refs ON news.id = messages_refs.message
|
||||
JOIN messages ON messages_refs.ref = messages.id
|
||||
UNION
|
||||
SELECT news.* FROM news
|
||||
`,
|
||||
[
|
||||
JSON.stringify(this.following),
|
||||
new Date().valueOf() - 24 * 60 * 60 * 1000,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.messages ||
|
||||
this._messages_hash !== this.hash ||
|
||||
this._messages_following !== this.following) {
|
||||
console.log(`loading messages for ${this.whoami}`);
|
||||
let self = this;
|
||||
this.messages = [];
|
||||
this._messages_hash = this.hash;
|
||||
this._messages_following = this.following;
|
||||
this.fetch_messages().then(function(messages) {
|
||||
self.messages = messages;
|
||||
console.log(`loading mesages done for ${self.whoami}`);
|
||||
}).catch(function(error) {
|
||||
alert(JSON.stringify(error, null, 2));
|
||||
});
|
||||
}
|
||||
return html`<tf-news id="news" whoami=${this.whoami} .users=${this.users} .messages=${this.messages} .following=${this.following} .drafts=${this.drafts} .expanded=${this.expanded}></tf-news>`;
|
||||
}
|
||||
}
|
||||
|
||||
class TfTabNewsElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
@ -141,9 +33,19 @@ class TfTabNewsElement extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
document.body.addEventListener('keypress', this.on_keypress.bind(this));
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
document.body.removeEventListener('keypress', this.on_keypress.bind(this));
|
||||
}
|
||||
|
||||
show_more() {
|
||||
let unread = this.unread;
|
||||
let news = this.renderRoot?.getElementById('news');
|
||||
let news = this.shadowRoot?.getElementById('news');
|
||||
if (news) {
|
||||
console.log('injecting messages', news.messages);
|
||||
news.messages = Object.values(Object.fromEntries([...this.unread, ...news.messages].map(x => [x.id, x])));
|
||||
@ -193,6 +95,13 @@ class TfTabNewsElement extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
on_keypress(event) {
|
||||
if (event.target === document.body &&
|
||||
event.key == '.') {
|
||||
this.show_more();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let profile = this.hash.startsWith('#@') ?
|
||||
html`<tf-profile id=${this.hash.substring(1)} whoami=${this.whoami} .users=${this.users}></tf-profile>` : undefined;
|
||||
@ -207,5 +116,4 @@ class TfTabNewsElement extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('tf-tab-news-feed', TfTabNewsFeedElement);
|
||||
customElements.define('tf-tab-news', TfTabNewsElement);
|
@ -9,6 +9,7 @@ class TfTabSearchElement extends LitElement {
|
||||
users: {type: Object},
|
||||
following: {type: Array},
|
||||
query: {type: String},
|
||||
expanded: {type: Object},
|
||||
};
|
||||
}
|
||||
|
||||
@ -20,6 +21,7 @@ class TfTabSearchElement extends LitElement {
|
||||
this.whoami = null;
|
||||
this.users = {};
|
||||
this.following = [];
|
||||
this.expanded = {};
|
||||
}
|
||||
|
||||
async search(query) {
|
||||
@ -55,8 +57,20 @@ class TfTabSearchElement extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
on_expand(event) {
|
||||
if (event.detail.expanded) {
|
||||
let expand = {};
|
||||
expand[event.detail.id] = true;
|
||||
this.expanded = Object.assign({}, this.expanded, expand);
|
||||
} else {
|
||||
delete this.expanded[event.detail.id];
|
||||
this.expanded = Object.assign({}, this.expanded);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.query !== this.last_query) {
|
||||
this.last_query = this.query;
|
||||
this.search(this.query);
|
||||
}
|
||||
let self = this;
|
||||
@ -65,7 +79,7 @@ class TfTabSearchElement extends LitElement {
|
||||
<input type="text" id="search" value=${this.query} style="flex: 1" @keydown=${this.search_keydown}></input>
|
||||
<input type="button" value="Search" @click=${(event) => self.search(self.renderRoot.getElementById('search').value)}></input>
|
||||
</div>
|
||||
<tf-news id="news" whoami=${this.whoami} .messages=${this.messages} .users=${this.users}></tf-news>
|
||||
<tf-news id="news" whoami=${this.whoami} .messages=${this.messages} .users=${this.users} .expanded=${this.expanded} @tf-expand=${this.on_expand}></tf-news>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
24
apps/ssb/tf-tag.js
Normal file
24
apps/ssb/tf-tag.js
Normal file
@ -0,0 +1,24 @@
|
||||
import {LitElement, html, unsafeHTML} from './lit-all.min.js';
|
||||
import {styles} from './tf-styles.js';
|
||||
|
||||
class TfTagElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
tag: {type: String},
|
||||
count: {type: Number},
|
||||
};
|
||||
}
|
||||
|
||||
static styles = styles;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
render() {
|
||||
let number = this.count ? html` (${this.count})` : undefined;
|
||||
return html`<a href="#q=${this.tag}" style="display: inline-block; margin: 3px; border: 1px solid black; background-color: #444; padding: 4px; border-radius: 3px">${this.tag}${number}</a>`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('tf-tag', TfTagElement);
|
@ -1,7 +1,6 @@
|
||||
import * as linkify from './commonmark-linkify.js';
|
||||
import * as hashtagify from './commonmark-hashtag.js';
|
||||
|
||||
|
||||
function image(node, entering) {
|
||||
if (node.firstChild?.type === 'text' &&
|
||||
node.firstChild.literal.startsWith('video:')) {
|
||||
|
@ -1,2 +0,0 @@
|
||||
wget https://cdn.jsdelivr.net/gh/lit/dist@2.7.2/all/lit-all.min.js -O lit-all.min.js
|
||||
wget https://cdn.jsdelivr.net/gh/lit/dist@2.7.2/all/lit-all.min.js.map -O lit-all.min.js.map
|
@ -119,7 +119,7 @@ class TodoListElement extends LitElement {
|
||||
} else {
|
||||
return html`
|
||||
<div><input type="checkbox" ?checked=${item.x} @change=${x => self.handle_check(x, item)}></input>
|
||||
<span @click=${x => self.editing = index}>${item.text}</span>
|
||||
<span @click=${x => self.editing = index}>${item.text || '(empty)'}</span>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -61,8 +61,7 @@ function socket(request, response, client) {
|
||||
let process;
|
||||
let options = {};
|
||||
let credentials = auth.query(request.headers);
|
||||
let refresh_token = credentials?.refresh?.token;
|
||||
let refresh_interval = credentials?.refresh?.interval;
|
||||
let refresh = auth.make_refresh(credentials);
|
||||
|
||||
response.onClose = async function() {
|
||||
if (process && process.task) {
|
||||
@ -198,9 +197,9 @@ function socket(request, response, client) {
|
||||
}
|
||||
}
|
||||
|
||||
if (refresh_token) {
|
||||
if (refresh) {
|
||||
return {
|
||||
'Set-Cookie': `session=${refresh_token}; path=/; Max-Age=${refresh_interval}; Secure; SameSite=Strict`,
|
||||
'Set-Cookie': `session=${refresh.token}; path=/; Max-Age=${refresh.interval}; Secure; SameSite=Strict`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
15
core/auth.js
15
core/auth.js
@ -260,12 +260,17 @@ function query(headers) {
|
||||
return {
|
||||
session: entry,
|
||||
permissions: autologin ? getPermissionsForUser(autologin) : getPermissions(session),
|
||||
refresh: {
|
||||
token: makeJwt({name: entry.name}),
|
||||
interval: kRefreshInterval,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { handler, query };
|
||||
function make_refresh(credentials) {
|
||||
if (credentials?.session?.name) {
|
||||
return {
|
||||
token: makeJwt({name: credentials.session.name}),
|
||||
interval: kRefreshInterval,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { handler, query, make_refresh };
|
||||
|
131
core/client.js
131
core/client.js
@ -52,6 +52,8 @@ class TfNavigationElement extends LitElement {
|
||||
show_permissions: {type: Boolean},
|
||||
status: {type: Object},
|
||||
spark_lines: {type: Object},
|
||||
version: {type: Object},
|
||||
show_version: {type: Boolean},
|
||||
};
|
||||
}
|
||||
|
||||
@ -79,6 +81,9 @@ class TfNavigationElement extends LitElement {
|
||||
get_spark_line(key, options) {
|
||||
if (!this.spark_lines[key]) {
|
||||
let spark_line = document.createElement('tf-sparkline');
|
||||
spark_line.style.display = 'flex';
|
||||
spark_line.style.flexDirection = 'row';
|
||||
spark_line.style.flex = '0 100 10em';
|
||||
spark_line.title = key;
|
||||
if (options) {
|
||||
if (options.max) {
|
||||
@ -125,7 +130,8 @@ class TfNavigationElement extends LitElement {
|
||||
${k_global_style}
|
||||
</style>
|
||||
<div style="margin: 4px; display: flex; flex-direction: row; flex-wrap: nowrap; gap: 3px">
|
||||
<span>😎</span>
|
||||
<span style="cursor: pointer" @click=${() => this.show_version = !this.show_version}>😎</span>
|
||||
<span ?hidden=${!this.show_version} style="flex: 0 0; white-space: nowrap" title=${this.version?.name + ' ' + Object.entries(this.version || {}).filter(x => ['name', 'number'].indexOf(x[0]) == -1).map(x => `\n* ${x[0]}: ${x[1]}`)}>${this.version?.number}</span>
|
||||
<a accesskey="h" data-tip="Open home app." href="/" style="color: #fff; white-space: nowrap">TF</a>
|
||||
<a accesskey="a" data-tip="Open apps list." href="/~core/apps/">apps</a>
|
||||
<a accesskey="e" data-tip="Toggle the app editor." href="#" @click=${this.toggle_edit}>edit</a>
|
||||
@ -133,7 +139,7 @@ class TfNavigationElement extends LitElement {
|
||||
<span style="display: inline-block; vertical-align: top; white-space: pre; color: ${this.status.color ?? kErrorColor}">${this.status.message}</span>
|
||||
<span id="requests"></span>
|
||||
${this.render_permissions()}
|
||||
<span style="flex: 1; white-space: nowrap; overflow: hidden; margin: 0; padding: 0">${Object.keys(this.spark_lines).sort().map(x => this.spark_lines[x]).map(x => [x.dataset.emoji, x])}</span>
|
||||
<span style="flex: 1 1; display: flex; flex-direction: row; white-space: nowrap; margin: 0; padding: 0">${Object.keys(this.spark_lines).sort().map(x => this.spark_lines[x]).map(x => [x.dataset.emoji, x])}</span>
|
||||
<span style="flex: 0 0; white-space: nowrap">${this.render_login()}</span>
|
||||
</div>
|
||||
`;
|
||||
@ -207,6 +213,62 @@ class TfFilesElement extends LitElement {
|
||||
}
|
||||
customElements.define('tf-files', TfFilesElement);
|
||||
|
||||
class TfFilesPaneElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
expanded: {type: Boolean},
|
||||
current: {type: String},
|
||||
files: {type: Object},
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.expanded = window.localStorage.getItem('files') != '0';
|
||||
this.files = {};
|
||||
}
|
||||
|
||||
set_expanded(expanded) {
|
||||
this.expanded = expanded;
|
||||
window.localStorage.setItem('files', expanded ? '1' : '0');
|
||||
}
|
||||
|
||||
render() {
|
||||
let self = this;
|
||||
let expander = this.expanded ?
|
||||
html`<span @click=${() => self.set_expanded(false)} class="expander">«</span>` :
|
||||
html`<span @click=${() => self.set_expanded(true)} class="expander">»</span>`;
|
||||
let content = html`
|
||||
<div id="files_content">
|
||||
<tf-files .files=${self.files} current=${self.current} @file_click=${event => openFile(event.detail.file)}></tf-files>
|
||||
<br>
|
||||
<div><button @click=${() => newFile()}>New File</button></div>
|
||||
<div><button @click=${() => removeFile()}>Remove File</button></div>
|
||||
</div>
|
||||
`;
|
||||
return html`
|
||||
<style>
|
||||
.expander {
|
||||
font-weight: bold;
|
||||
width: 100%;
|
||||
right: 0;
|
||||
flex: 0;
|
||||
padding: 0.25em;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<div style="display: flex; flex-direction: row">
|
||||
${this.expanded ? html`<span style="font-weight: bold; text-align: center; flex: 1">Files</span>` : undefined}
|
||||
${expander}
|
||||
</div>
|
||||
${this.expanded ? content : undefined}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
customElements.define('tf-files-pane', TfFilesPaneElement);
|
||||
|
||||
class TfSparkLineElement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
@ -221,6 +283,7 @@ class TfSparkLineElement extends LitElement {
|
||||
this.min = 0;
|
||||
this.max = 1.0;
|
||||
this.lines = [];
|
||||
this.k_values_max = 100;
|
||||
}
|
||||
|
||||
append(key, value) {
|
||||
@ -236,30 +299,31 @@ class TfSparkLineElement extends LitElement {
|
||||
line = {
|
||||
name: key,
|
||||
style: k_colors[this.lines.length % k_colors.length],
|
||||
values: [],
|
||||
values: Array(this.k_values_max).fill(0),
|
||||
};
|
||||
this.lines.push(line);
|
||||
}
|
||||
line.values.push(value);
|
||||
if (line.values.length > 100) {
|
||||
if (line.values.length >= this.k_values_max) {
|
||||
line.values.shift();
|
||||
}
|
||||
line.values.push(value);
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
render_line(line) {
|
||||
if (line?.values?.length >= 2) {
|
||||
let points = [].concat(...line.values.map((x, i) => [100.0 * i / (line.values.length - 1), 10.0 - 10.0 * (x - this.min) / (this.max - this.min)]));
|
||||
return svg`
|
||||
<polyline points=${points.join(' ')} stroke=${line.style} fill="none"/>
|
||||
`;
|
||||
let max = Math.max(this.max, ...line.values);
|
||||
let points = [].concat(...line.values.map((x, i) => [100.0 * i / (line.values.length - 1), 10.0 - 10.0 * (x - this.min) / (max - this.min)]));
|
||||
return svg`<polyline points=${points.join(' ')} stroke=${line.style} fill="none"/>`;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let max = Math.round(10.0 * Math.max(...this.lines.map(line => line.values[line.values.length - 1]))) / 10.0;
|
||||
return html`
|
||||
<svg style="width: 10em; height: 1.4em; vertical-align: top; margin: 0; padding: 0; background: #000" viewBox="0 0 100 10" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg style="width-auto: object-fit: cover; margin: 0; padding: 0; background: #000" viewBox="0 0 100 10" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
|
||||
${this.lines.map(x => this.render_line(x))}
|
||||
<text x="0" y="1em" style="font: 8px sans-serif; fill: #fff">${max}</text>
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
@ -332,6 +396,7 @@ function edit() {
|
||||
gSplit = undefined;
|
||||
}
|
||||
gSplit = Split(['#editPane', '#viewPane'], {minSize: 0});
|
||||
document.getElementById("editPane").style.display = 'flex';
|
||||
|
||||
ensureLoaded([
|
||||
{tagName: "script", attributes: {src: "/codemirror/codemirror.min.js"}},
|
||||
@ -362,16 +427,6 @@ function edit() {
|
||||
});
|
||||
}
|
||||
|
||||
function hideFiles() {
|
||||
window.localStorage.setItem('files', '0');
|
||||
document.getElementById('filesPane').classList.add('collapsed');
|
||||
}
|
||||
|
||||
function showFiles() {
|
||||
window.localStorage.setItem('files', '1');
|
||||
document.getElementById('filesPane').classList.remove('collapsed');
|
||||
}
|
||||
|
||||
function trace() {
|
||||
window.open(`/speedscope/#profileURL=${encodeURIComponent('/trace')}`);
|
||||
}
|
||||
@ -409,7 +464,6 @@ function loadFile(name, id) {
|
||||
}).then(function(text) {
|
||||
gFiles[name].doc = new CodeMirror.Doc(text, guessMode(name));
|
||||
if (!Object.values(gFiles).some(x => !x.doc)) {
|
||||
document.getElementById("editPane").style.display = 'flex';
|
||||
openFile(Object.keys(gFiles).sort()[0]);
|
||||
}
|
||||
});
|
||||
@ -717,6 +771,7 @@ function _receive_websocket_message(message) {
|
||||
if (window.location.hash) {
|
||||
send({event: "hashChange", hash: window.location.hash});
|
||||
}
|
||||
document.getElementsByTagName('tf-navigation')[0].version = message.version;
|
||||
send({action: 'enableStats', enabled: true});
|
||||
} else if (message && message.action == "ping") {
|
||||
send({action: "pong"});
|
||||
@ -834,18 +889,6 @@ function _receive_websocket_message(message) {
|
||||
}
|
||||
}
|
||||
|
||||
function keyEvent(event) {
|
||||
send({
|
||||
event: "key",
|
||||
type: event.type,
|
||||
which: event.which,
|
||||
keyCode: event.keyCode,
|
||||
charCode: event.charCode,
|
||||
character: String.fromCharCode(event.keyCode || event.which),
|
||||
altKey: event.altKey,
|
||||
});
|
||||
}
|
||||
|
||||
function setStatusMessage(message, color) {
|
||||
document.getElementsByTagName('tf-navigation')[0].status = {message: message, color: color};
|
||||
}
|
||||
@ -1070,11 +1113,13 @@ function openFile(name) {
|
||||
}
|
||||
|
||||
function updateFiles() {
|
||||
let files = document.getElementById("files_list");
|
||||
files.files = Object.fromEntries(Object.keys(gFiles).map(file => [file, {
|
||||
clean: gFiles[file].doc.isClean(gFiles[file].generation),
|
||||
}]));
|
||||
files.current = gCurrentFile;
|
||||
let files = document.getElementsByTagName("tf-files-pane")[0];
|
||||
if (files) {
|
||||
files.files = Object.fromEntries(Object.keys(gFiles).map(file => [file, {
|
||||
clean: gFiles[file].doc.isClean(gFiles[file].generation),
|
||||
}]));
|
||||
files.current = gCurrentFile;
|
||||
}
|
||||
|
||||
gEditor.focus();
|
||||
}
|
||||
@ -1108,8 +1153,6 @@ window.addEventListener("load", function() {
|
||||
window.addEventListener("message", message, false);
|
||||
window.addEventListener("online", connectSocket);
|
||||
document.getElementById("name").value = window.location.pathname;
|
||||
document.getElementById('files_hide').addEventListener('click', () => hideFiles());
|
||||
document.getElementById('files_show').addEventListener('click', () => showFiles());
|
||||
document.getElementById('closeStats').addEventListener('click', () => closeStats());
|
||||
document.getElementById('closeEditor').addEventListener('click', () => closeEditor());
|
||||
document.getElementById('save').addEventListener('click', () => save());
|
||||
@ -1123,8 +1166,6 @@ window.addEventListener("load", function() {
|
||||
event.preventDefault();
|
||||
toggleStats();
|
||||
});
|
||||
document.getElementById('new_file_button').addEventListener('click', () => newFile());
|
||||
document.getElementById('remove_file_button').addEventListener('click', () => removeFile());
|
||||
for (let tag of document.getElementsByTagName('a')) {
|
||||
if (tag.accessKey) {
|
||||
tag.classList.add('tooltip_parent');
|
||||
@ -1157,15 +1198,9 @@ window.addEventListener("load", function() {
|
||||
} else {
|
||||
closeEditor();
|
||||
}
|
||||
if (window.localStorage.getItem('files') == '1') {
|
||||
showFiles();
|
||||
} else {
|
||||
hideFiles();
|
||||
}
|
||||
if (window.localStorage.getItem('stats') == '1') {
|
||||
stats();
|
||||
} else {
|
||||
closeStats();
|
||||
}
|
||||
document.getElementById('files_list').addEventListener('file_click', event => openFile(event.detail.file));
|
||||
});
|
||||
|
348
core/core.js
348
core/core.js
@ -1,12 +1,46 @@
|
||||
import * as app from './app.js';
|
||||
import * as auth from './auth.js';
|
||||
import * as form from './form.js';
|
||||
import * as http from './http.js';
|
||||
import * as httpd from './httpd.js';
|
||||
|
||||
let gProcessIndex = 0;
|
||||
let gProcesses = {};
|
||||
let gStatsTimer = false;
|
||||
|
||||
const k_mime_types = {
|
||||
'css': 'text/css',
|
||||
'html': 'text/html',
|
||||
'js': 'text/javascript',
|
||||
'json': 'text/json',
|
||||
'map': 'application/json',
|
||||
'svg': 'image/svg+xml',
|
||||
};
|
||||
|
||||
const k_magic_bytes = [
|
||||
{bytes: [0xff, 0xd8, 0xff, 0xdb], type: 'image/jpeg'},
|
||||
{bytes: [0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01], type: 'image/jpeg'},
|
||||
{bytes: [0xff, 0xd8, 0xff, 0xee], type: 'image/jpeg'},
|
||||
{bytes: [0xff, 0xd8, 0xff, 0xe1, null, null, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00], type: 'image/jpeg'},
|
||||
{bytes: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], type: 'image/png'},
|
||||
{bytes: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61], type: 'image/gif'},
|
||||
{bytes: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61], type: 'image/gif'},
|
||||
{bytes: [0x52, 0x49, 0x46, 0x46, null, null, null, null, 0x57, 0x45, 0x42, 0x50], type: 'image/webp'},
|
||||
{bytes: [0x3c, 0x73, 0x76, 0x67], type: 'image/svg+xml'},
|
||||
{bytes: [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32], type: 'audio/mpeg'},
|
||||
{bytes: [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6f, 0x6d], type: 'video/mp4'},
|
||||
{bytes: [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32], type: 'video/mp4'},
|
||||
];
|
||||
|
||||
let k_static_files = [
|
||||
{uri: '/', path: 'index.html', type: 'text/html; charset=UTF-8'},
|
||||
{uri: '/style.css', type: 'text/css; charset=UTF-8'},
|
||||
{uri: '/favicon.png', type: 'image/png'},
|
||||
{uri: '/client.js', type: 'text/javascript; charset=UTF-8'},
|
||||
{uri: '/tfrpc.js', type: 'text/javascript; charset=UTF-8', headers: {'Access-Control-Allow-Origin': 'null'}},
|
||||
{uri: '/robots.txt', type: 'text/plain; charset=UTF-8'},
|
||||
];
|
||||
|
||||
const k_global_settings = {
|
||||
index: {
|
||||
type: 'string',
|
||||
@ -33,6 +67,11 @@ const k_global_settings = {
|
||||
default_value: undefined,
|
||||
description: 'If connecting by HTTP and HTTPS is configured, Location header prefix (ie, "https://example.com")',
|
||||
},
|
||||
fetch_hosts: {
|
||||
type: 'string',
|
||||
default_value: undefined,
|
||||
description: 'Comma-separated list of host names to which HTTP fetch requests are allowed. None if empty.',
|
||||
},
|
||||
};
|
||||
|
||||
let gGlobalSettings = {
|
||||
@ -46,8 +85,8 @@ function printError(out, error) {
|
||||
out.print(error.fileName + ":" + error.lineNumber + ": " + error.message);
|
||||
out.print(error.stackTrace);
|
||||
} else {
|
||||
for (let i in error) {
|
||||
out.print(i);
|
||||
for (let [k, v] of Object.entries(error)) {
|
||||
out.print(k, v);
|
||||
}
|
||||
out.print(error.toString());
|
||||
}
|
||||
@ -159,7 +198,9 @@ async function getProcessBlob(blobId, key, options) {
|
||||
process.credentials = options.credentials || {};
|
||||
process.task = new Task();
|
||||
process.eventHandlers = {};
|
||||
process.app = new app.App();
|
||||
if (!options?.script || options?.script === 'app.js') {
|
||||
process.app = new app.App();
|
||||
}
|
||||
process.lastActive = Date.now();
|
||||
process.lastPing = null;
|
||||
process.timeout = options.timeout;
|
||||
@ -243,7 +284,7 @@ async function getProcessBlob(blobId, key, options) {
|
||||
throw Error(`Permission denied: ${permission}.`);
|
||||
}
|
||||
|
||||
} else {
|
||||
} else if (process.app) {
|
||||
return process.app.makeFunction(['requestPermission'])(permission).then(function(value) {
|
||||
if (value == 'allow') {
|
||||
storePermission(user, options.packageOwner, options.packageName, permission, true);
|
||||
@ -260,6 +301,8 @@ async function getProcessBlob(blobId, key, options) {
|
||||
}
|
||||
throw Error(`Permission denied: ${permission}.`);
|
||||
});
|
||||
} else {
|
||||
throw Error(`Permission denied: ${permission}.`);
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -310,14 +353,23 @@ async function getProcessBlob(blobId, key, options) {
|
||||
imports.app[api[0]] = process.app.makeFunction(api);
|
||||
}
|
||||
}
|
||||
for (let [name, f] of Object.entries(options?.imports || {})) {
|
||||
imports[name] = f;
|
||||
}
|
||||
process.task.onPrint = function(args) {
|
||||
imports.app.print(...args);
|
||||
if (imports.app) {
|
||||
imports.app.print(...args);
|
||||
}
|
||||
};
|
||||
process.task.onError = function(error) {
|
||||
try {
|
||||
process.app.makeFunction(['error'])(error);
|
||||
} catch(e) {
|
||||
print(e);
|
||||
if (process.app) {
|
||||
process.app.makeFunction(['error'])(error);
|
||||
} else {
|
||||
printError({print: print}, error);
|
||||
}
|
||||
} catch (e) {
|
||||
printError({print: print}, error);
|
||||
}
|
||||
};
|
||||
imports.ssb = Object.fromEntries(Object.keys(ssb).map(key => [key, ssb[key].bind(ssb)]));
|
||||
@ -358,6 +410,9 @@ async function getProcessBlob(blobId, key, options) {
|
||||
return ssb.privateMessageDecrypt(process.credentials.session.name, id, message);
|
||||
}
|
||||
};
|
||||
imports.fetch = function(url, options) {
|
||||
return http.fetch(url, options, gGlobalSettings.fetch_hosts);
|
||||
}
|
||||
|
||||
if (process.credentials &&
|
||||
process.credentials.session &&
|
||||
@ -396,7 +451,7 @@ async function getProcessBlob(blobId, key, options) {
|
||||
try {
|
||||
let appObject = JSON.parse(appSource);
|
||||
if (appObject.type == "tildefriends-app") {
|
||||
appSourceName = 'app.js';
|
||||
appSourceName = options?.script ?? 'app.js';
|
||||
let id = appObject.files[appSourceName];
|
||||
let blob = await getBlobOrContent(id);
|
||||
appSource = utf8Decode(blob);
|
||||
@ -409,19 +464,23 @@ async function getProcessBlob(blobId, key, options) {
|
||||
printError({print: print}, e);
|
||||
}
|
||||
broadcastEvent('onSessionBegin', [getUser(process, process)]);
|
||||
resolveReady(process);
|
||||
if (process.app) {
|
||||
process.app.send({action: "ready"});
|
||||
process.app.send({action: "ready", version: version()});
|
||||
process.sendPermissions();
|
||||
}
|
||||
await process.task.execute({name: appSourceName, source: appSource});
|
||||
resolveReady(process);
|
||||
} catch (error) {
|
||||
if (process?.task?.onError) {
|
||||
process.task.onError(error);
|
||||
if (process.app) {
|
||||
if (process?.task?.onError) {
|
||||
process.task.onError(error);
|
||||
} else {
|
||||
printError({print: print}, error);
|
||||
}
|
||||
} else {
|
||||
printError({print: print}, error);
|
||||
}
|
||||
rejectReady();
|
||||
rejectReady(error);
|
||||
}
|
||||
}
|
||||
return process;
|
||||
@ -436,20 +495,11 @@ function setGlobalSettings(settings) {
|
||||
}
|
||||
}
|
||||
|
||||
let kStaticFiles = [
|
||||
{uri: '/', path: 'index.html', type: 'text/html; charset=UTF-8'},
|
||||
{uri: '/style.css', type: 'text/css; charset=UTF-8'},
|
||||
{uri: '/favicon.png', type: 'image/png'},
|
||||
{uri: '/client.js', type: 'text/javascript; charset=UTF-8'},
|
||||
{uri: '/tfrpc.js', type: 'text/javascript; charset=UTF-8', headers: {'Access-Control-Allow-Origin': 'null'}},
|
||||
{uri: '/robots.txt', type: 'text/plain; charset=UTF-8'},
|
||||
];
|
||||
|
||||
function startsWithBytes(data, bytes) {
|
||||
if (data.byteLength >= bytes.length) {
|
||||
let dataBytes = new Uint8Array(data.slice(0, bytes.length));
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
if (dataBytes[i] != bytes[i] && bytes[i] !== null) {
|
||||
if (dataBytes[i] !== bytes[i] && bytes[i] !== null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -458,16 +508,16 @@ function startsWithBytes(data, bytes) {
|
||||
}
|
||||
|
||||
async function staticFileHandler(request, response, blobId, uri) {
|
||||
for (let i in kStaticFiles) {
|
||||
if (uri === kStaticFiles[i].uri) {
|
||||
let path = kStaticFiles[i].path || uri.substring(1);
|
||||
let type = kStaticFiles[i].type || guessType(path);
|
||||
for (let i in k_static_files) {
|
||||
if (uri === k_static_files[i].uri) {
|
||||
let path = k_static_files[i].path || uri.substring(1);
|
||||
let type = k_static_files[i].type || guessTypeFromName(path);
|
||||
|
||||
let stat = await File.stat('core/' + path);
|
||||
let id = `${stat.mtime}_${stat.size}`;
|
||||
|
||||
if (request.headers['if-none-match'] === '"' + id + '"') {
|
||||
response.writeHead(304, {});
|
||||
response.writeHead(304, {'Content-Length': '0'});
|
||||
response.end();
|
||||
} else {
|
||||
let data = await File.readFile('core/' + path);
|
||||
@ -477,7 +527,7 @@ async function staticFileHandler(request, response, blobId, uri) {
|
||||
'Content-Length': data.byteLength,
|
||||
'etag': '"' + id + '"',
|
||||
},
|
||||
kStaticFiles[i].headers || {}));
|
||||
k_static_files[i].headers || {}));
|
||||
response.end(data);
|
||||
}
|
||||
return;
|
||||
@ -488,14 +538,6 @@ async function staticFileHandler(request, response, blobId, uri) {
|
||||
response.end("File not found");
|
||||
}
|
||||
|
||||
const k_mime_types = {
|
||||
'json': 'text/json',
|
||||
'js': 'text/javascript',
|
||||
'html': 'text/html',
|
||||
'css': 'text/css',
|
||||
'map': 'application/json',
|
||||
};
|
||||
|
||||
async function staticDirectoryHandler(request, response, directory, uri) {
|
||||
let filename = uri || 'index.html';
|
||||
if (filename.indexOf('..') != -1) {
|
||||
@ -509,7 +551,7 @@ async function staticDirectoryHandler(request, response, directory, uri) {
|
||||
let id = `${stat.mtime}_${stat.size}`;
|
||||
|
||||
if (request.headers['if-none-match'] === '"' + id + '"') {
|
||||
response.writeHead(304, {});
|
||||
response.writeHead(304, {'Content-Length': '0'});
|
||||
response.end();
|
||||
} else {
|
||||
let data = await File.readFile(directory + filename);
|
||||
@ -537,40 +579,25 @@ async function wellKnownHandler(request, response, path) {
|
||||
}
|
||||
}
|
||||
|
||||
function sendData(response, data, type, headers) {
|
||||
if (data) {
|
||||
if (startsWithBytes(data, [0xff, 0xd8, 0xff, 0xdb]) ||
|
||||
startsWithBytes(data, [0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01]) ||
|
||||
startsWithBytes(data, [0xff, 0xd8, 0xff, 0xee]) ||
|
||||
startsWithBytes(data, [0xff, 0xd8, 0xff, 0xe1, null, null, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00])) {
|
||||
response.writeHead(200, Object.assign({"Content-Type": "image/jpeg", "Content-Length": data.byteLength}, headers || {}));
|
||||
response.end(data);
|
||||
} else if (startsWithBytes(data, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) {
|
||||
response.writeHead(200, Object.assign({"Content-Type": "image/png", "Content-Length": data.byteLength}, headers || {}));
|
||||
response.end(data);
|
||||
} else if (startsWithBytes(data, [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]) ||
|
||||
startsWithBytes(data, [0x47, 0x49, 0x46, 0x38, 0x39, 0x61])) {
|
||||
response.writeHead(200, Object.assign({"Content-Type": "image/gif", "Content-Length": data.byteLength}, headers || {}));
|
||||
response.end(data);
|
||||
} else if (startsWithBytes(data, [0x52, 0x49, 0x46, 0x46, null, null, null, null, 0x57, 0x45, 0x42, 0x50])) {
|
||||
response.writeHead(200, Object.assign({"Content-Type": "image/webp", "Content-Length": data.byteLength}, headers || {}));
|
||||
response.end(data);
|
||||
} else if (startsWithBytes(data, [0x3c, 0x73, 0x76, 0x67])) {
|
||||
response.writeHead(200, Object.assign({"Content-Type": "image/svg+xml", "Content-Length": data.byteLength}, headers || {}));
|
||||
response.end(data);
|
||||
} else if (startsWithBytes(data, [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32])) {
|
||||
response.writeHead(200, Object.assign({"Content-Type": "audio/mpeg", "Content-Length": data.byteLength}, headers || {}));
|
||||
response.end(data);
|
||||
} else if (startsWithBytes(data, [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6f, 0x6d]) ||
|
||||
startsWithBytes(data, [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32])) {
|
||||
response.writeHead(200, Object.assign({"Content-Type": "video/mp4", "Content-Length": data.byteLength}, headers || {}));
|
||||
response.end(data);
|
||||
} else {
|
||||
response.writeHead(200, Object.assign({"Content-Type": type || "application/binary", "Content-Length": data.byteLength}, headers || {}));
|
||||
response.end(data);
|
||||
function guessTypeFromName(path) {
|
||||
let extension = path.split('.').pop();
|
||||
return k_mime_types[extension];
|
||||
}
|
||||
|
||||
function guessTypeFromMagicBytes(data) {
|
||||
for (let magic of k_magic_bytes) {
|
||||
if (startsWithBytes(data, magic.bytes)) {
|
||||
return magic.type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendData(response, data, type, headers, status_code) {
|
||||
if (data) {
|
||||
response.writeHead(status_code ?? 200, Object.assign({"Content-Type": type || guessTypeFromMagicBytes(data) || "application/binary", "Content-Length": data.byteLength}, headers || {}));
|
||||
response.end(data);
|
||||
} else {
|
||||
response.writeHead(404, Object.assign({"Content-Type": "text/plain; charset=utf-8", "Content-Length": "File not found".length}, headers || {}));
|
||||
response.writeHead(status_code ?? 404, Object.assign({"Content-Type": "text/plain; charset=utf-8", "Content-Length": "File not found".length}, headers || {}));
|
||||
response.end("File not found");
|
||||
}
|
||||
}
|
||||
@ -585,35 +612,58 @@ async function getBlobOrContent(id) {
|
||||
}
|
||||
}
|
||||
|
||||
function guessType(path) {
|
||||
const k_extension_to_type = {
|
||||
'css': 'text/css',
|
||||
'html': 'text/html',
|
||||
'js': 'text/javascript',
|
||||
'svg': 'image/svg+xml',
|
||||
};
|
||||
let extension = path.split('.').pop();
|
||||
return k_extension_to_type[extension];
|
||||
let g_handler_index = 0;
|
||||
async function useAppHandler(response, handler_blob_id, path, query, headers, packageOwner, packageName) {
|
||||
print('useAppHandler', packageOwner, packageName);
|
||||
let do_resolve;
|
||||
let promise = new Promise(async function(resolve, reject) {
|
||||
do_resolve = resolve;
|
||||
});
|
||||
let process;
|
||||
let result;
|
||||
try {
|
||||
process = await getProcessBlob(handler_blob_id, 'handler_' + g_handler_index++, {
|
||||
script: 'handler.js',
|
||||
imports: {
|
||||
request: {
|
||||
path: path,
|
||||
query: query,
|
||||
},
|
||||
respond: do_resolve,
|
||||
},
|
||||
credentials: auth.query(headers),
|
||||
packageOwner: packageOwner,
|
||||
packageName: packageName,
|
||||
});
|
||||
await process.ready;
|
||||
|
||||
result = await promise;
|
||||
} finally {
|
||||
if (process?.task) {
|
||||
await process.task.kill();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async function blobHandler(request, response, blobId, uri) {
|
||||
for (let i in kStaticFiles) {
|
||||
if (uri === kStaticFiles[i].uri && kStaticFiles[i].path) {
|
||||
let stat = await File.stat('core/' + kStaticFiles[i].path);
|
||||
for (let i in k_static_files) {
|
||||
if (uri === k_static_files[i].uri && k_static_files[i].path) {
|
||||
let stat = await File.stat('core/' + k_static_files[i].path);
|
||||
let id = `${stat.mtime}_${stat.size}`;
|
||||
|
||||
if (request.headers['if-none-match'] === '"' + id + '"') {
|
||||
response.writeHead(304, {});
|
||||
response.writeHead(304, {'Content-Length': '0'});
|
||||
response.end();
|
||||
} else {
|
||||
let data = await File.readFile('core/' + kStaticFiles[i].path);
|
||||
let data = await File.readFile('core/' + k_static_files[i].path);
|
||||
response.writeHead(200, Object.assign(
|
||||
{
|
||||
'Content-Type': kStaticFiles[i].type,
|
||||
'Content-Type': k_static_files[i].type,
|
||||
'Content-Length': data.byteLength,
|
||||
'etag': '"' + id + '"',
|
||||
},
|
||||
kStaticFiles[i].headers || {}));
|
||||
k_static_files[i].headers || {}));
|
||||
response.end(data);
|
||||
}
|
||||
return;
|
||||
@ -631,7 +681,9 @@ async function blobHandler(request, response, blobId, uri) {
|
||||
let data;
|
||||
let match;
|
||||
let query = form.decodeForm(request.query);
|
||||
let headers = {};
|
||||
let headers = {
|
||||
'Content-Security-Policy': 'sandbox',
|
||||
};
|
||||
if (query.filename && query.filename.match(/^[A-Za-z0-9\.-]*$/)) {
|
||||
headers['Content-Disposition'] = `attachment; filename=${query.filename}`;
|
||||
}
|
||||
@ -639,6 +691,7 @@ async function blobHandler(request, response, blobId, uri) {
|
||||
let id = await new Database(match[1]).get('path:' + match[2]);
|
||||
if (id) {
|
||||
if (request.headers['if-none-match'] === '"' + id + '"') {
|
||||
headers['Content-Length'] = '0';
|
||||
response.writeHead(304, headers);
|
||||
response.end();
|
||||
} else {
|
||||
@ -651,6 +704,7 @@ async function blobHandler(request, response, blobId, uri) {
|
||||
}
|
||||
} else {
|
||||
if (request.headers['if-none-match'] === '"' + blobId + '"') {
|
||||
headers['Content-Length'] = '0';
|
||||
response.writeHead(304, headers);
|
||||
response.end();
|
||||
} else {
|
||||
@ -659,6 +713,7 @@ async function blobHandler(request, response, blobId, uri) {
|
||||
}
|
||||
} else {
|
||||
if (request.headers['if-none-match'] === '"' + blobId + '"') {
|
||||
headers['Content-Length'] = '0';
|
||||
response.writeHead(304, headers);
|
||||
response.end();
|
||||
} else {
|
||||
@ -738,43 +793,58 @@ async function blobHandler(request, response, blobId, uri) {
|
||||
response.end('OK');
|
||||
} else {
|
||||
let data;
|
||||
let type;
|
||||
let headers;
|
||||
let match;
|
||||
let id;
|
||||
let app_id = blobId;
|
||||
let packageOwner;
|
||||
let packageName;
|
||||
if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) {
|
||||
packageOwner = match[1];
|
||||
packageName = match[2];
|
||||
let db = new Database(match[1]);
|
||||
let id = await db.get('path:' + match[2]);
|
||||
if (id) {
|
||||
if (request.headers['if-none-match'] && request.headers['if-none-match'] == '"' + id + '"') {
|
||||
headers = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
};
|
||||
response.writeHead(304, headers);
|
||||
response.end();
|
||||
} else {
|
||||
data = utf8Decode(await getBlobOrContent(id));
|
||||
let appObject = JSON.parse(data);
|
||||
data = appObject.files[uri.substring(1)];
|
||||
data = await getBlobOrContent(data);
|
||||
type = guessType(uri);
|
||||
headers = {
|
||||
'ETag': '"' + id + '"',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
};
|
||||
sendData(response, data, type, headers);
|
||||
}
|
||||
app_id = await db.get('path:' + match[2]);
|
||||
}
|
||||
|
||||
let app_object = JSON.parse(utf8Decode(await getBlobOrContent(app_id)));
|
||||
id = app_object.files[uri.substring(1)];
|
||||
if (!id && app_object.files['handler.js']) {
|
||||
let answer;
|
||||
try {
|
||||
answer = await useAppHandler(response, app_id, uri.substring(1), request.query ? form.decodeForm(request.query) : undefined, request.headers, packageOwner, packageName);
|
||||
} catch (error) {
|
||||
data = utf8Encode(`Internal Server Error\n\n${error?.message}\n${error?.stack}`);
|
||||
response.writeHead(500, {'Content-Type': 'text/plain; charset=utf-8', 'Content-Length': data.length});
|
||||
response.end(data);
|
||||
return;
|
||||
}
|
||||
if (answer && typeof answer.data == 'string') {
|
||||
answer.data = utf8Encode(answer.data);
|
||||
}
|
||||
sendData(response, answer?.data, answer?.content_type, Object.assign(answer?.headers ?? {}, {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Security-Policy': 'sandbox',
|
||||
}), answer.status_code);
|
||||
} else if (id) {
|
||||
if (request.headers['if-none-match'] && request.headers['if-none-match'] == '"' + id + '"') {
|
||||
let headers = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Security-Policy': 'sandbox',
|
||||
'Content-Length': '0',
|
||||
};
|
||||
response.writeHead(304, headers);
|
||||
response.end();
|
||||
} else {
|
||||
let headers = {
|
||||
'ETag': '"' + id + '"',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Security-Policy': 'sandbox',
|
||||
};
|
||||
data = await getBlobOrContent(id);
|
||||
let type = guessTypeFromName(uri) || guessTypeFromMagicBytes(data);
|
||||
sendData(response, data, type, headers);
|
||||
}
|
||||
} else {
|
||||
data = utf8Decode(await getBlobOrContent(blobId));
|
||||
let appObject = JSON.parse(data);
|
||||
data = appObject.files[uri.substring(1)];
|
||||
data = await getBlobOrContent(data);
|
||||
headers = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
};
|
||||
sendData(response, data, type, headers);
|
||||
sendData(response, data, undefined, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -826,6 +896,16 @@ function enableStats(process, enabled) {
|
||||
}
|
||||
}
|
||||
|
||||
function stringResponse(response, data) {
|
||||
let bytes = utf8Encode(data);
|
||||
response.writeHead(200, {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
"Content-Length": bytes.byteLength.toString(),
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
});
|
||||
return response.end(bytes);
|
||||
}
|
||||
|
||||
loadSettings().then(function() {
|
||||
httpd.all("/login", auth.handler);
|
||||
httpd.all("", function(request, response) {
|
||||
@ -839,8 +919,6 @@ loadSettings().then(function() {
|
||||
return blobHandler(request, response, match[1], match[2]);
|
||||
} else if (match = /^\/static\/lit\/([\.\w-/]*)$/.exec(request.uri)) {
|
||||
return staticDirectoryHandler(request, response, 'deps/lit/', match[1]);
|
||||
} else if (match = /^\/static(\/.*)/.exec(request.uri)) {
|
||||
return staticFileHandler(request, response, null, match[1]);
|
||||
} else if (match = /^\/codemirror\/([\.\w-/]*)$/.exec(request.uri)) {
|
||||
return staticDirectoryHandler(request, response, 'deps/codemirror/', match[1]);
|
||||
} else if (match = /^\/speedscope\/([\.\w-/]*)$/.exec(request.uri)) {
|
||||
@ -849,34 +927,22 @@ loadSettings().then(function() {
|
||||
return staticDirectoryHandler(request, response, 'deps/split/', match[1]);
|
||||
} else if (match = /^\/smoothie\/([\.\w-/]*)$/.exec(request.uri)) {
|
||||
return staticDirectoryHandler(request, response, 'deps/smoothie/', match[1]);
|
||||
} else if (match = /^\/static(\/.*)/.exec(request.uri)) {
|
||||
return staticFileHandler(request, response, null, match[1]);
|
||||
} else if (request.uri == "/robots.txt") {
|
||||
return staticFileHandler(request, response, null, request.uri);
|
||||
} else if (match = /^(.*)(\/(?:save|delete)?)$/.exec(request.uri)) {
|
||||
return blobHandler(request, response, match[1], match[2]);
|
||||
} else if (match = /^\/trace$/.exec(request.uri)) {
|
||||
let data = trace();
|
||||
response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.length.toString()});
|
||||
return response.end(data);
|
||||
return stringResponse(response, trace());
|
||||
} else if (match = /^\/disconnections$/.exec(request.uri)) {
|
||||
let data = utf8Encode(JSON.stringify(disconnectionsDebug(), null, 2));
|
||||
response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.byteLength.toString()});
|
||||
return response.end(data);
|
||||
return stringResponse(response, JSON.stringify(disconnectionsDebug(), null, 2));
|
||||
} else if (match = /^\/debug$/.exec(request.uri)) {
|
||||
let data = JSON.stringify(getDebug(), null, 2);
|
||||
response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.length.toString()});
|
||||
return response.end(data);
|
||||
return stringResponse(response, JSON.stringify(getDebug(), null, 2));
|
||||
} else if (match = /^\/hitches$/.exec(request.uri)) {
|
||||
let data = JSON.stringify(getHitches(), null, 2);
|
||||
response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.length.toString()});
|
||||
return response.end(data);
|
||||
return stringResponse(response, JSON.stringify(getHitches(), null, 2));
|
||||
} else if (match = /^\/mem$/.exec(request.uri)) {
|
||||
let data = JSON.stringify(getAllocations(), null, 2);
|
||||
response.writeHead(200, {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
"Content-Length": data.length.toString(),
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
});
|
||||
return response.end(data);
|
||||
} else if (request.uri == "/robots.txt") {
|
||||
return blobHandler(request, response, null, request.uri);
|
||||
return stringResponse(response, JSON.stringify(getAllocations(), null, 2));
|
||||
} else if ((match = /^\/.well-known\/(.*)/.exec(request.uri)) && request.uri.indexOf("..") == -1) {
|
||||
return wellKnownHandler(request, response, match[1]);
|
||||
} else {
|
||||
|
86
core/http.js
Normal file
86
core/http.js
Normal file
@ -0,0 +1,86 @@
|
||||
function parseUrl(url) {
|
||||
// XXX: Hack.
|
||||
let match = url.match(new RegExp("(\\w+)://([^/:]+)(?::(\\d+))?(.*)"));
|
||||
return {
|
||||
protocol: match[1],
|
||||
host: match[2],
|
||||
path: match[4],
|
||||
port: match[3] ? parseInt(match[3]) : match[1] == "http" ? 80 : 443,
|
||||
};
|
||||
}
|
||||
|
||||
function parseResponse(data) {
|
||||
let firstLine;
|
||||
let headers = {};
|
||||
while (true) {
|
||||
let endLine = data.indexOf('\r\n');
|
||||
let line = data.substring(0, endLine);
|
||||
data = data.substring(endLine + 2);
|
||||
if (!line.length) {
|
||||
break;
|
||||
} else if (!firstLine) {
|
||||
firstLine = line;
|
||||
} else {
|
||||
let colon = line.indexOf(":");
|
||||
headers[line.substring(colon)] = line.substring(colon + 1);
|
||||
}
|
||||
}
|
||||
return {body: data};
|
||||
}
|
||||
|
||||
export function fetch(url, options, allowed_hosts) {
|
||||
let parsed = parseUrl(url);
|
||||
return new Promise(function(resolve, reject) {
|
||||
if ((allowed_hosts ?? []).indexOf(parsed.host) == -1) {
|
||||
throw new Error(`fetch() request to host ${parsed.host} is not allowed.`);
|
||||
}
|
||||
let socket = new Socket();
|
||||
let buffer = new Uint8Array(0);
|
||||
|
||||
return socket.connect(parsed.host, parsed.port).then(function() {
|
||||
socket.read(function(data) {
|
||||
if (data && data.length) {
|
||||
let newBuffer = new Uint8Array(buffer.length + data.length);
|
||||
newBuffer.set(buffer, 0);
|
||||
newBuffer.set(data, buffer.length);
|
||||
buffer = newBuffer;
|
||||
} else {
|
||||
let result = parseHttpResponse(buffer);
|
||||
if (!result) {
|
||||
reject(new Exception('Parse failed.'));
|
||||
}
|
||||
if (typeof result == 'number') {
|
||||
if (result == -2) {
|
||||
reject('Incomplete request.');
|
||||
} else {
|
||||
reject('Bad request.');
|
||||
}
|
||||
} else if (typeof result == 'object') {
|
||||
resolve({
|
||||
body: buffer.slice(result.bytes_parsed),
|
||||
status: result.status,
|
||||
message: result.message,
|
||||
headers: result.headers,
|
||||
});
|
||||
} else {
|
||||
reject(new Exception('Unexpected parse result.'));
|
||||
}
|
||||
resolve(parseResponse(utf8Decode(buffer)));
|
||||
}
|
||||
});
|
||||
|
||||
if (parsed.port == 443) {
|
||||
return socket.startTls();
|
||||
}
|
||||
}).then(function() {
|
||||
let body = typeof options?.body == 'string' ? utf8Encode(options.body) : (options.body || new Uint8Array(0));
|
||||
let headers = utf8Encode(`${options?.method ?? 'GET'} ${parsed.path} HTTP/1.0\r\nHost: ${parsed.host}\r\nConnection: close\r\nContent-Length: ${body.length}\r\n\r\n`);
|
||||
let fullRequest = new Uint8Array(headers.length + body.length);
|
||||
fullRequest.set(headers, 0);
|
||||
fullRequest.set(body, headers.length);
|
||||
socket.write(fullRequest);
|
||||
}).catch(function(error) {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
@ -473,7 +473,7 @@ function handleConnection(client) {
|
||||
|
||||
if (parsing_header)
|
||||
{
|
||||
let result = parseHttp(inputBuffer, inputBuffer.length - data.length);
|
||||
let result = parseHttpRequest(inputBuffer, inputBuffer.length - data.length);
|
||||
if (result) {
|
||||
if (typeof result === 'number') {
|
||||
if (result == -2) {
|
||||
@ -552,7 +552,7 @@ function handleConnection(client) {
|
||||
}
|
||||
|
||||
let kBacklog = 8;
|
||||
let kHost = "0.0.0.0"
|
||||
let kHost = '::';
|
||||
|
||||
let socket = new Socket();
|
||||
socket.bind(kHost, tildefriends.http_port).then(function(port) {
|
||||
|
@ -26,20 +26,7 @@
|
||||
<input type="button" id="stats_button" value="Stats">
|
||||
</div>
|
||||
<div class="hbox" style="height: 100%">
|
||||
<div id="filesPane">
|
||||
<div class="hbox">
|
||||
<span id="files_header">Files</span>
|
||||
<span id="files_hide">«</span>
|
||||
<span id="files_show">»</span>
|
||||
</div>
|
||||
<div id="files_content">
|
||||
<tf-files id="files_list"></tf-files>
|
||||
<ul id="files"></ul>
|
||||
<br>
|
||||
<div><button id="new_file_button">New File</button></div>
|
||||
<div><button id="remove_file_button">Remove File</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<tf-files-pane></tf-files-pane>
|
||||
<div id="docPane" style="display: flex; flex: 1 1 50%; flex-flow: column">
|
||||
<div style="flex: 1 1 50%; position: relative">
|
||||
<textarea id="editor" class="main"></textarea>
|
||||
@ -51,6 +38,7 @@
|
||||
<iframe id="document" sandbox="allow-forms allow-scripts allow-top-navigation allow-modals allow-downloads" style="width: 100%; height: 100%; border: 0"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<script>window.litDisableBundleWarning = true;</script>
|
||||
<script src="/split/split.min.js"></script>
|
||||
<script src="/smoothie/smoothie.js"></script>
|
||||
<script src="/static/client.js" type="module"></script>
|
||||
|
@ -157,51 +157,6 @@ a:active {
|
||||
.cyan { color: #2aa198; }
|
||||
.green { color: #859900; }
|
||||
|
||||
#files_header {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#files_hide {
|
||||
font-weight: bold;
|
||||
width: 100%;
|
||||
right: 0;
|
||||
flex: 0;
|
||||
padding: 0.25em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#files_show {
|
||||
display: none;
|
||||
padding: 0.25em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#filesPane {
|
||||
flex: 1 1 10%;
|
||||
}
|
||||
|
||||
#filesPane.collapsed {
|
||||
flex: 0;
|
||||
}
|
||||
|
||||
.collapsed #files_header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapsed #files_content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapsed #files_hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapsed #files_show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
|
@ -39,9 +39,9 @@ function send(response) {
|
||||
|
||||
function call_rpc(message) {
|
||||
if (message && message.message === 'tfrpc') {
|
||||
let method = g_api[message.method];
|
||||
let id = message.id;
|
||||
if (message.method) {
|
||||
let method = g_api[message.method];
|
||||
if (method) {
|
||||
try {
|
||||
Promise.resolve(method(...message.params)).then(function(result) {
|
||||
@ -53,7 +53,7 @@ function call_rpc(message) {
|
||||
send({message: 'tfrpc', id: id, error: error});
|
||||
}
|
||||
} else {
|
||||
throw new Error(message.method + ' not found.');
|
||||
send({message: 'tfrpc', id: id, error: `Method '${message.method}' not found.`});
|
||||
}
|
||||
} else if (message.error !== undefined) {
|
||||
if (g_calls[id]) {
|
||||
|
25
deps/libuv/.github/workflows/CI-docs.yml
vendored
Normal file
25
deps/libuv/.github/workflows/CI-docs.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: CI-docs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '!docs/code/**'
|
||||
- '.github/workflows/CI-docs.yml'
|
||||
|
||||
jobs:
|
||||
docs-src:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9'
|
||||
cache: 'pip' # caching pip dependencies
|
||||
- run: pip install -r docs/requirements.txt
|
||||
- name: html
|
||||
run: |
|
||||
make -C docs html
|
||||
- name: linkcheck
|
||||
run: |
|
||||
make -C docs linkcheck
|
29
deps/libuv/.github/workflows/CI-unix.yml
vendored
29
deps/libuv/.github/workflows/CI-unix.yml
vendored
@ -14,6 +14,19 @@ on:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: configure
|
||||
run: |
|
||||
./autogen.sh
|
||||
mkdir build
|
||||
(cd build && ../configure)
|
||||
- name: distcheck
|
||||
run: |
|
||||
make -C build distcheck
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
container: reactnativecommunity/react-native-android:2020-5-20
|
||||
@ -33,14 +46,14 @@ jobs:
|
||||
ls -lh build
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-10.15
|
||||
runs-on: macos-11
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Setup
|
||||
run: |
|
||||
brew install ninja
|
||||
brew install ninja automake libtool
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir build
|
||||
@ -59,9 +72,16 @@ jobs:
|
||||
- name: Test
|
||||
run: |
|
||||
cd build && ctest -V
|
||||
- name: Autotools configure
|
||||
if: always()
|
||||
run: |
|
||||
./autogen.sh
|
||||
mkdir build-auto
|
||||
(cd build-auto && ../configure)
|
||||
make -C build-auto -j4
|
||||
|
||||
build-ios:
|
||||
runs-on: macos-10.15
|
||||
runs-on: macos-11
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Configure
|
||||
@ -94,7 +114,6 @@ jobs:
|
||||
- {target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64-static }
|
||||
- {target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel-static }
|
||||
- {target: mips64el,toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc,qemu: qemu-mips64el-static }
|
||||
- {target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static }
|
||||
- {target: arm (u64 slots), toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static}
|
||||
- {target: aarch64 (u64 slots), toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static}
|
||||
- {target: ppc (u64 slots), toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static}
|
||||
@ -106,7 +125,7 @@ jobs:
|
||||
# this ensure install latest qemu on ubuntu, apt get version is old
|
||||
env:
|
||||
QEMU_SRC: "http://archive.ubuntu.com/ubuntu/pool/universe/q/qemu"
|
||||
QEMU_VER: "qemu-user-static_4\\.2-.*_amd64.deb$"
|
||||
QEMU_VER: "qemu-user-static_7\\.0+dfsg-.*_amd64.deb$"
|
||||
run: |
|
||||
DEB=`curl -s $QEMU_SRC/ | grep -o -E 'href="([^"#]+)"' | cut -d'"' -f2 | grep $QEMU_VER | tail -1`
|
||||
wget $QEMU_SRC/$DEB
|
||||
|
93
deps/libuv/.github/workflows/CI-win.yml
vendored
93
deps/libuv/.github/workflows/CI-win.yml
vendored
@ -16,7 +16,7 @@ on:
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: windows-${{ matrix.config.server }}
|
||||
name: build-${{ matrix.config.toolchain}}-${{ matrix.config.arch}}
|
||||
name: build-${{ join(matrix.config.*, '-') }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@ -25,27 +25,98 @@ jobs:
|
||||
- {toolchain: Visual Studio 16 2019, arch: x64, server: 2019}
|
||||
- {toolchain: Visual Studio 17 2022, arch: Win32, server: 2022}
|
||||
- {toolchain: Visual Studio 17 2022, arch: x64, server: 2022}
|
||||
- {toolchain: Visual Studio 17 2022, arch: x64, server: 2022, config: ASAN}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -DBUILD_TESTING=ON -G "${{ matrix.config.toolchain }}" -A ${{ matrix.config.arch }}
|
||||
cmake --build .
|
||||
run:
|
||||
cmake -S . -B build -DBUILD_TESTING=ON
|
||||
-G "${{ matrix.config.toolchain }}" -A ${{ matrix.config.arch }}
|
||||
${{ matrix.config.config == 'ASAN' && '-DASAN=on -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded' || '' }}
|
||||
|
||||
cmake --build build --config RelWithDebInfo
|
||||
|
||||
ls -l build
|
||||
- name: platform_output
|
||||
shell: cmd
|
||||
run: |
|
||||
build\\Debug\\uv_run_tests.exe platform_output
|
||||
run:
|
||||
build\\RelWithDebInfo\\uv_run_tests.exe platform_output
|
||||
- name: platform_output_a
|
||||
shell: cmd
|
||||
run:
|
||||
build\\RelWithDebInfo\\uv_run_tests_a.exe platform_output
|
||||
- name: Test
|
||||
# only valid with libuv-master with the fix for
|
||||
# https://github.com/libuv/leps/blob/master/005-windows-handles-not-fd.md
|
||||
if: ${{ matrix.config.config != 'ASAN' }}
|
||||
shell: cmd
|
||||
run:
|
||||
cd build
|
||||
|
||||
ctest -C RelWithDebInfo -V
|
||||
- name: Test only static
|
||||
if: ${{ matrix.config.config == 'ASAN' }}
|
||||
shell: cmd
|
||||
run:
|
||||
build\\RelWithDebInfo\\uv_run_tests_a.exe
|
||||
|
||||
build-mingw:
|
||||
runs-on: ubuntu-latest
|
||||
name: build-mingw-${{ matrix.config.arch }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {arch: i686, server: 2022, libgcc: dw2 }
|
||||
- {arch: x86_64, server: 2022, libgcc: seh }
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install mingw32 environment
|
||||
run: |
|
||||
build\\Debug\\uv_run_tests_a.exe platform_output
|
||||
sudo apt update
|
||||
sudo apt install mingw-w64 ninja-build -y
|
||||
- name: Build
|
||||
run: |
|
||||
cmake -S . -B build -G Ninja -DHOST_ARCH=${{ matrix.config.arch }} -DBUILD_TESTING=ON -DCMAKE_TOOLCHAIN_FILE=cmake-toolchains/cross-mingw32.cmake
|
||||
cmake --build build
|
||||
cmake --install build --prefix "`pwd`/build/usr"
|
||||
mkdir -p build/usr/test build/usr/bin
|
||||
cp -av test/fixtures build/usr/test
|
||||
cp -av build/uv_run_tests_a.exe build/uv_run_tests.exe \
|
||||
`${{ matrix.config.arch }}-w64-mingw32-gcc -print-file-name=libgcc_s_${{ matrix.config.libgcc }}-1.dll` \
|
||||
`${{ matrix.config.arch }}-w64-mingw32-gcc -print-file-name=libwinpthread-1.dll` \
|
||||
`${{ matrix.config.arch }}-w64-mingw32-gcc -print-file-name=libatomic-1.dll` \
|
||||
build/usr/bin
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mingw-${{ matrix.config.arch }}
|
||||
path: build/usr/**/*
|
||||
retention-days: 2
|
||||
|
||||
test-mingw:
|
||||
runs-on: windows-${{ matrix.config.server }}
|
||||
name: test-mingw-${{ matrix.config.arch }}
|
||||
needs: build-mingw
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {arch: i686, server: 2022}
|
||||
- {arch: x86_64, server: 2022}
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: mingw-${{ matrix.config.arch }}
|
||||
- name: Test
|
||||
shell: cmd
|
||||
run: |
|
||||
cd build
|
||||
ctest -C Debug -V
|
||||
bin\uv_run_tests_a.exe
|
||||
- name: Test
|
||||
shell: cmd
|
||||
run: |
|
||||
bin\uv_run_tests.exe
|
||||
|
41
deps/libuv/.github/workflows/sanitizer.yml
vendored
41
deps/libuv/.github/workflows/sanitizer.yml
vendored
@ -14,7 +14,7 @@ on:
|
||||
|
||||
jobs:
|
||||
sanitizers:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup
|
||||
@ -22,15 +22,7 @@ jobs:
|
||||
sudo apt-get install ninja-build
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: TSAN Build
|
||||
run: |
|
||||
mkdir build-tsan
|
||||
(cd build-tsan && cmake .. -G Ninja -DBUILD_TESTING=ON -DTSAN=ON -DCMAKE_BUILD_TYPE=Release)
|
||||
cmake --build build-tsan
|
||||
- name: TSAN Test
|
||||
continue-on-error: true # currently permit failures
|
||||
run: |
|
||||
./build-tsan/uv_run_tests_a
|
||||
|
||||
- name: ASAN Build
|
||||
run: |
|
||||
mkdir build-asan
|
||||
@ -39,3 +31,32 @@ jobs:
|
||||
- name: ASAN Test
|
||||
run: |
|
||||
./build-asan/uv_run_tests_a
|
||||
|
||||
- name: MSAN Build
|
||||
run: |
|
||||
mkdir build-msan
|
||||
(cd build-msan && cmake .. -G Ninja -DBUILD_TESTING=ON -DMSAN=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang)
|
||||
cmake --build build-msan
|
||||
- name: MSAN Test
|
||||
run: |
|
||||
./build-msan/uv_run_tests_a
|
||||
|
||||
- name: TSAN Build
|
||||
run: |
|
||||
mkdir build-tsan
|
||||
(cd build-tsan && cmake .. -G Ninja -DBUILD_TESTING=ON -DTSAN=ON -DCMAKE_BUILD_TYPE=Release)
|
||||
cmake --build build-tsan
|
||||
- name: TSAN Test
|
||||
# Note: path must be absolute because some tests chdir.
|
||||
# TSan exits with an error when it can't find the file.
|
||||
run: |
|
||||
env TSAN_OPTIONS="suppressions=$PWD/tsansupp.txt" ./build-tsan/uv_run_tests_a
|
||||
|
||||
- name: UBSAN Build
|
||||
run: |
|
||||
mkdir build-ubsan
|
||||
(cd build-ubsan && cmake .. -G Ninja -DBUILD_TESTING=ON -DUBSAN=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang)
|
||||
cmake --build build-ubsan
|
||||
- name: UBSAN Test
|
||||
run: |
|
||||
./build-ubsan/uv_run_tests_a
|
||||
|
3
deps/libuv/.mailmap
vendored
3
deps/libuv/.mailmap
vendored
@ -29,6 +29,7 @@ Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
|
||||
Leith Bade <leith@leithalweapon.geek.nz> <leith@mapbox.com>
|
||||
Leonard Hecker <leonard.hecker91@gmail.com> <leonard@hecker.io>
|
||||
Lewis Russell <me@lewisr.dev> <lewis6991@gmail.com>
|
||||
Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
|
||||
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
|
||||
Michael <michael_dawson@ca.ibm.com>
|
||||
@ -60,5 +61,7 @@ gengjiawen <technicalcute@gmail.com>
|
||||
jBarz <jBarz@users.noreply.github.com> <jbarboza@ca.ibm.com>
|
||||
jBarz <jBarz@users.noreply.github.com> <jbarz@users.noreply.github.com>
|
||||
ptlomholt <pt@lomholt.com>
|
||||
theanarkh <2923878201@qq.com> <theratliter@gmail.com>
|
||||
tjarlama <59913901+tjarlama@users.noreply.github.com> <tjarlama@gmail.com>
|
||||
ywave620 <rogertyang@tencent.com> <60539365+ywave620@users.noreply.github.com>
|
||||
zlargon <zlargon1988@gmail.com>
|
||||
|
6
deps/libuv/.readthedocs.yaml
vendored
6
deps/libuv/.readthedocs.yaml
vendored
@ -5,7 +5,11 @@ sphinx:
|
||||
configuration: null
|
||||
fail_on_warning: false
|
||||
|
||||
build:
|
||||
os: "ubuntu-22.04"
|
||||
tools:
|
||||
python: "3.9"
|
||||
|
||||
python:
|
||||
version: 3.8
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
31
deps/libuv/AUTHORS
vendored
31
deps/libuv/AUTHORS
vendored
@ -517,3 +517,34 @@ chucksilvers <chuq@chuq.com>
|
||||
Sergey Fedorov <vital.had@gmail.com>
|
||||
theanarkh <2923878201@qq.com>
|
||||
Samuel Cabrero <samuelcabrero@gmail.com>
|
||||
自发对称破缺 <429839446@qq.com>
|
||||
Luan Devecchi <luan@engineer.com>
|
||||
Steven Schveighoffer <schveiguy@gmail.com>
|
||||
number201724 <number201724@me.com>
|
||||
Daniel <reymond315qq@gmail.com>
|
||||
Christian Clason <christian.clason@uni-due.de>
|
||||
ywave620 <rogertyang@tencent.com>
|
||||
jensbjorgensen <jbj1@ultraemail.net>
|
||||
daomingq <daoming.qiu@intel.com>
|
||||
Qix <Qix-@users.noreply.github.com>
|
||||
Edward Humes <29870961+aurxenon@users.noreply.github.com>
|
||||
Tim Besard <tim.besard@gmail.com>
|
||||
Sergey Rubanov <chi187@gmail.com>
|
||||
Stefan Stojanovic <StefanStojanovic@users.noreply.github.com>
|
||||
Zvicii <zvicii@qq.com>
|
||||
dundargoc <33953936+dundargoc@users.noreply.github.com>
|
||||
Jack·Boos·Yu <47264268+JackBoosY@users.noreply.github.com>
|
||||
panran <310762957@qq.com>
|
||||
Tamás Bálint Misius <lbphacker@gmail.com>
|
||||
Bruno Passeri <Varstahl@users.noreply.github.com>
|
||||
Jason Zhang <xzha4350@gmail.com>
|
||||
Lewis Russell <me@lewisr.dev>
|
||||
sivadeilra <arlie.davis@gmail.com>
|
||||
cui fliter <imcusg@gmail.com>
|
||||
Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
|
||||
Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com>
|
||||
Stefan Karpinski <stefan@karpinski.org>
|
||||
liuxiang88 <94350585+liuxiang88@users.noreply.github.com>
|
||||
Jeffrey H. Johnson <trnsz@pobox.com>
|
||||
Abdirahim Musse <33973272+abmusse@users.noreply.github.com>
|
||||
小明 <7737673+caobug@users.noreply.github.com>
|
||||
|
194
deps/libuv/CMakeLists.txt
vendored
194
deps/libuv/CMakeLists.txt
vendored
@ -1,8 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
project(libuv LANGUAGES C)
|
||||
|
||||
cmake_policy(SET CMP0057 NEW) # Enable IN_LIST operator
|
||||
cmake_policy(SET CMP0064 NEW) # Support if (TEST) operator
|
||||
if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW) # Enable MSVC_RUNTIME_LIBRARY setting
|
||||
endif()
|
||||
if(POLICY CMP0092)
|
||||
cmake_policy(SET CMP0092 NEW) # disable /W3 warning, if possible
|
||||
endif()
|
||||
|
||||
project(libuv LANGUAGES C)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
|
||||
@ -17,9 +22,13 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS ON)
|
||||
set(CMAKE_C_STANDARD 90)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
option(LIBUV_BUILD_SHARED "Build shared lib" ON)
|
||||
|
||||
cmake_dependent_option(LIBUV_BUILD_TESTS
|
||||
"Build the unit tests when BUILD_TESTING is enabled and we are the root project" ON
|
||||
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
"BUILD_TESTING;LIBUV_BUILD_SHARED;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(LIBUV_BUILD_BENCH
|
||||
"Build the benchmarks when building unit tests and we are the root project" ON
|
||||
"LIBUV_BUILD_TESTS" OFF)
|
||||
@ -27,28 +36,61 @@ cmake_dependent_option(LIBUV_BUILD_BENCH
|
||||
# Qemu Build
|
||||
option(QEMU "build for qemu" OFF)
|
||||
if(QEMU)
|
||||
add_definitions(-D__QEMU__=1)
|
||||
list(APPEND uv_defines __QEMU__=1)
|
||||
endif()
|
||||
|
||||
# Note: these are mutually exclusive.
|
||||
option(ASAN "Enable AddressSanitizer (ASan)" OFF)
|
||||
option(MSAN "Enable MemorySanitizer (MSan)" OFF)
|
||||
option(TSAN "Enable ThreadSanitizer (TSan)" OFF)
|
||||
option(UBSAN "Enable UndefinedBehaviorSanitizer (UBSan)" OFF)
|
||||
|
||||
if((ASAN OR TSAN) AND NOT (CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang"))
|
||||
message(SEND_ERROR "Sanitizer support requires clang or gcc. Try again with -DCMAKE_C_COMPILER.")
|
||||
if(MSAN AND NOT CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang")
|
||||
message(SEND_ERROR "MemorySanitizer requires clang. Try again with -DCMAKE_C_COMPILER=clang")
|
||||
endif()
|
||||
|
||||
if(ASAN)
|
||||
add_definitions(-D__ASAN__=1)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
list(APPEND uv_defines __ASAN__=1)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
elseif(MSVC)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address")
|
||||
else()
|
||||
message(SEND_ERROR "AddressSanitizer support requires clang, gcc, or msvc. Try again with -DCMAKE_C_COMPILER.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSAN)
|
||||
list(APPEND uv_defines __MSAN__=1)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=memory")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=memory")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=memory")
|
||||
endif()
|
||||
|
||||
if(TSAN)
|
||||
add_definitions(-D__TSAN__=1)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
list(APPEND uv_defines __TSAN__=1)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
else()
|
||||
message(SEND_ERROR "ThreadSanitizer support requires clang or gcc. Try again with -DCMAKE_C_COMPILER.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UBSAN)
|
||||
list(APPEND uv_defines __UBSAN__=1)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=undefined")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=undefined")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=undefined")
|
||||
elseif(MSVC)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=undefined")
|
||||
else()
|
||||
message(SEND_ERROR "UndefinedBehaviorSanitizer support requires clang, gcc, or msvc. Try again with -DCMAKE_C_COMPILER.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Compiler check
|
||||
@ -126,6 +168,7 @@ set(uv_sources
|
||||
src/random.c
|
||||
src/strscpy.c
|
||||
src/strtok.c
|
||||
src/thread-common.c
|
||||
src/threadpool.c
|
||||
src/timer.c
|
||||
src/uv-common.c
|
||||
@ -140,7 +183,10 @@ if(WIN32)
|
||||
advapi32
|
||||
iphlpapi
|
||||
userenv
|
||||
ws2_32)
|
||||
ws2_32
|
||||
dbghelp
|
||||
ole32
|
||||
uuid)
|
||||
list(APPEND uv_sources
|
||||
src/win/async.c
|
||||
src/win/core.c
|
||||
@ -216,15 +262,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
list(APPEND uv_defines _GNU_SOURCE)
|
||||
list(APPEND uv_libraries dl)
|
||||
list(APPEND uv_sources
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-syscalls.c
|
||||
src/unix/linux.c
|
||||
src/unix/procfs-exepath.c
|
||||
src/unix/pthread-fixes.c
|
||||
src/unix/random-getentropy.c
|
||||
src/unix/random-getrandom.c
|
||||
src/unix/random-sysctl-linux.c
|
||||
src/unix/epoll.c)
|
||||
src/unix/random-sysctl-linux.c)
|
||||
endif()
|
||||
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux")
|
||||
@ -270,22 +312,14 @@ if(CMAKE_SYSTEM_NAME STREQUAL "GNU")
|
||||
src/unix/hurd.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "kFreeBSD")
|
||||
list(APPEND uv_defines _GNU_SOURCE)
|
||||
list(APPEND uv_libraries dl freebsd-glue)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
list(APPEND uv_defines _GNU_SOURCE _POSIX_C_SOURCE=200112)
|
||||
list(APPEND uv_libraries dl rt)
|
||||
list(APPEND uv_sources
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-syscalls.c
|
||||
src/unix/linux.c
|
||||
src/unix/procfs-exepath.c
|
||||
src/unix/random-getrandom.c
|
||||
src/unix/random-sysctl-linux.c
|
||||
src/unix/epoll.c)
|
||||
src/unix/random-sysctl-linux.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
|
||||
@ -316,7 +350,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
list(APPEND uv_defines _XOPEN_SOURCE=600)
|
||||
list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED)
|
||||
list(APPEND uv_sources
|
||||
src/unix/pthread-fixes.c
|
||||
src/unix/os390.c
|
||||
src/unix/os390-syscalls.c
|
||||
src/unix/os390-proctitle.c)
|
||||
@ -354,6 +387,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS400")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
if(CMAKE_SYSTEM_VERSION STREQUAL "5.10")
|
||||
list(APPEND uv_defines SUNOS_NO_IFADDRS)
|
||||
list(APPEND uv_libraries rt)
|
||||
endif()
|
||||
list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500 _REENTRANT)
|
||||
list(APPEND uv_libraries kstat nsl sendfile socket)
|
||||
list(APPEND uv_sources
|
||||
@ -388,25 +425,42 @@ if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|Linux|NetBSD|OpenBSD")
|
||||
list(APPEND uv_test_libraries util)
|
||||
endif()
|
||||
|
||||
add_library(uv SHARED ${uv_sources})
|
||||
target_compile_definitions(uv
|
||||
INTERFACE
|
||||
USING_UV_SHARED=1
|
||||
PRIVATE
|
||||
BUILDING_UV_SHARED=1
|
||||
${uv_defines})
|
||||
target_compile_options(uv PRIVATE ${uv_cflags})
|
||||
target_include_directories(uv
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
target_include_directories(uv PUBLIC $<BUILD_INTERFACE:${ZOSLIB_DIR}/include>)
|
||||
set_target_properties(uv PROPERTIES LINKER_LANGUAGE CXX)
|
||||
if(CYGWIN OR MSYS)
|
||||
list(APPEND uv_defines _GNU_SOURCE)
|
||||
list(APPEND uv_sources
|
||||
src/unix/cygwin.c
|
||||
src/unix/bsd-ifaddrs.c
|
||||
src/unix/no-fsevents.c
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/posix-hrtime.c
|
||||
src/unix/posix-poll.c
|
||||
src/unix/procfs-exepath.c
|
||||
src/unix/sysinfo-loadavg.c
|
||||
src/unix/sysinfo-memory.c)
|
||||
endif()
|
||||
|
||||
if(LIBUV_BUILD_SHARED)
|
||||
add_library(uv SHARED ${uv_sources})
|
||||
target_compile_definitions(uv
|
||||
INTERFACE
|
||||
USING_UV_SHARED=1
|
||||
PRIVATE
|
||||
BUILDING_UV_SHARED=1
|
||||
${uv_defines})
|
||||
target_compile_options(uv PRIVATE ${uv_cflags})
|
||||
target_include_directories(uv
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
target_include_directories(uv PUBLIC $<BUILD_INTERFACE:${ZOSLIB_DIR}/include>)
|
||||
set_target_properties(uv PROPERTIES LINKER_LANGUAGE CXX)
|
||||
endif()
|
||||
target_link_libraries(uv ${uv_libraries})
|
||||
set_target_properties(uv PROPERTIES OUTPUT_NAME "uv")
|
||||
endif()
|
||||
target_link_libraries(uv ${uv_libraries})
|
||||
|
||||
add_library(uv_a STATIC ${uv_sources})
|
||||
target_compile_definitions(uv_a PRIVATE ${uv_defines})
|
||||
@ -422,6 +476,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
set_target_properties(uv_a PROPERTIES LINKER_LANGUAGE CXX)
|
||||
endif()
|
||||
target_link_libraries(uv_a ${uv_libraries})
|
||||
set_target_properties(uv_a PROPERTIES OUTPUT_NAME "uv")
|
||||
if(MSVC)
|
||||
set_target_properties(uv_a PROPERTIES PREFIX "lib")
|
||||
endif()
|
||||
|
||||
if(LIBUV_BUILD_TESTS)
|
||||
# Small hack: use ${uv_test_sources} now to get the runner skeleton,
|
||||
@ -584,6 +642,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-tcp-rst.c
|
||||
test/test-tcp-shutdown-after-write.c
|
||||
test/test-tcp-try-write.c
|
||||
test/test-tcp-write-in-a-row.c
|
||||
test/test-tcp-try-write-error.c
|
||||
test/test-tcp-unexpected-read.c
|
||||
test/test-tcp-write-after-connect.c
|
||||
@ -592,6 +651,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-tcp-write-to-half-open-connection.c
|
||||
test/test-tcp-writealot.c
|
||||
test/test-test-macros.c
|
||||
test/test-thread-affinity.c
|
||||
test/test-thread-equal.c
|
||||
test/test-thread.c
|
||||
test/test-threadpool-cancel.c
|
||||
@ -624,6 +684,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-udp-sendmmsg-error.c
|
||||
test/test-udp-send-unreachable.c
|
||||
test/test-udp-try-send.c
|
||||
test/test-udp-recv-in-a-row.c
|
||||
test/test-uname.c
|
||||
test/test-walk-handles.c
|
||||
test/test-watcher-cross-stop.c)
|
||||
@ -667,27 +728,36 @@ string(REPLACE ";" " " LIBS "${LIBS}")
|
||||
file(STRINGS configure.ac configure_ac REGEX ^AC_INIT)
|
||||
string(REGEX MATCH "([0-9]+)[.][0-9]+[.][0-9]+" PACKAGE_VERSION "${configure_ac}")
|
||||
set(UV_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
# The version in the filename is mirroring the behaviour of autotools.
|
||||
set_target_properties(uv PROPERTIES
|
||||
VERSION ${UV_VERSION_MAJOR}.0.0
|
||||
SOVERSION ${UV_VERSION_MAJOR})
|
||||
|
||||
set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
configure_file(libuv.pc.in libuv.pc @ONLY)
|
||||
configure_file(libuv-static.pc.in libuv-static.pc @ONLY)
|
||||
|
||||
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libuv.pc ${PROJECT_BINARY_DIR}/libuv-static.pc
|
||||
install(FILES LICENSE-extra DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libuv-static.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(TARGETS uv EXPORT libuvConfig
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(TARGETS uv_a EXPORT libuvConfig
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(EXPORT libuvConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libuv)
|
||||
install(EXPORT libuvConfig
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libuv
|
||||
NAMESPACE libuv::)
|
||||
|
||||
if(LIBUV_BUILD_SHARED)
|
||||
# The version in the filename is mirroring the behaviour of autotools.
|
||||
set_target_properties(uv PROPERTIES
|
||||
VERSION ${UV_VERSION_MAJOR}.0.0
|
||||
SOVERSION ${UV_VERSION_MAJOR})
|
||||
configure_file(libuv.pc.in libuv.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libuv.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(TARGETS uv EXPORT libuvConfig
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_DEBUG_POSTFIX d)
|
||||
|
354
deps/libuv/ChangeLog
vendored
354
deps/libuv/ChangeLog
vendored
@ -1,4 +1,356 @@
|
||||
2022.07.12, Version 1.44.2 (Stable)
|
||||
2023.06.30, Version 1.46.0 (Stable)
|
||||
|
||||
Changes since version 1.45.0:
|
||||
|
||||
* Add SHA to ChangeLog (Santiago Gimeno)
|
||||
|
||||
* misc: update readthedocs config (Jameson Nash)
|
||||
|
||||
* test: remove erroneous RETURN_SKIP (Ben Noordhuis)
|
||||
|
||||
* android: disable io_uring support (Ben Noordhuis)
|
||||
|
||||
* linux: add some more iouring backed fs ops (Santiago Gimeno)
|
||||
|
||||
* build: add autoconf option for disable-maintainer-mode (Jameson Nash)
|
||||
|
||||
* fs: use WTF-8 on Windows (Stefan Karpinski)
|
||||
|
||||
* unix,win: replace QUEUE with struct uv__queue (Ben Noordhuis)
|
||||
|
||||
* linux: fs_read to use io_uring if iovcnt > IOV_MAX (Santiago Gimeno)
|
||||
|
||||
* ios: fix uv_getrusage() ru_maxrss calculation (Ben Noordhuis)
|
||||
|
||||
* include: update outdated code comment (Ben Noordhuis)
|
||||
|
||||
* linux: support abstract unix sockets (Ben Noordhuis)
|
||||
|
||||
* unix,win: add UV_PIPE_NO_TRUNCATE flag (Ben Noordhuis)
|
||||
|
||||
* unix: add loongarch support (liuxiang88)
|
||||
|
||||
* doc: add DPS8M to LINKS.md (Jeffrey H. Johnson)
|
||||
|
||||
* include: add EUNATCH errno mapping (Abdirahim Musse)
|
||||
|
||||
* src: don't run timers if loop is stopped/unref'd (Trevor Norris)
|
||||
|
||||
* win: fix -Wpointer-to-int-cast warning (Ben Noordhuis)
|
||||
|
||||
* test,win: fix -Wunused-variable warning (Ben Noordhuis)
|
||||
|
||||
* test,win: fix -Wformat warning (Ben Noordhuis)
|
||||
|
||||
* linux: work around io_uring IORING_OP_CLOSE bug (Ben Noordhuis)
|
||||
|
||||
* win: remove unused functions (Ben Noordhuis)
|
||||
|
||||
* bench: add bench to check uv_loop_alive (Trevor Norris)
|
||||
|
||||
* test: add uv_cancel test for threadpool (Trevor Norris)
|
||||
|
||||
* unix: skip prohibited syscalls on tvOS and watchOS (小明)
|
||||
|
||||
* unix,fs: make no_pwritev access thread-safe (Santiago Gimeno)
|
||||
|
||||
* unix: fix build for lower versions of Android (小明)
|
||||
|
||||
|
||||
2023.05.19, Version 1.45.0 (Stable), 96e05543f53b19d9642b4b0dd73b86ad3cea313e
|
||||
|
||||
Changes since version 1.44.2:
|
||||
|
||||
* win: remove stdint-msvc2008.h (Ben Noordhuis)
|
||||
|
||||
* android: remove pthread-fixes.c (Ben Noordhuis)
|
||||
|
||||
* build: enable MSVC_RUNTIME_LIBRARY setting (自发对称破缺)
|
||||
|
||||
* unix: switch to c11 atomics (Ben Noordhuis)
|
||||
|
||||
* unix: don't accept() connections in a loop (Ben Noordhuis)
|
||||
|
||||
* win: fix off-by-1 buffer overrun in uv_exepath() (Ben Noordhuis)
|
||||
|
||||
* build: switch ci from macos-10.15 to macos-11 (Ben Noordhuis)
|
||||
|
||||
* win: fix thread race in uv_cwd() and uv_chdir() (Ben Noordhuis)
|
||||
|
||||
* unix,win: remove UV_HANDLE_SHUTTING flag (Santiago Gimeno)
|
||||
|
||||
* win: support Windows 11 in uv_os_uname() (Luan Devecchi)
|
||||
|
||||
* unix: fix uv_getrusage() ru_maxrss reporting (Ben Noordhuis)
|
||||
|
||||
* doc: add note about offset -1 in uv_fs_read/write (Steven Schveighoffer)
|
||||
|
||||
* test: fix musl libc.a dlerror() test expectation (Ben Noordhuis)
|
||||
|
||||
* kqueue: DRY file descriptor deletion logic (Ben Noordhuis)
|
||||
|
||||
* linux: teach uv_get_constrained_memory() cgroupsv2 (Ben Noordhuis)
|
||||
|
||||
* build: upgrade qemu-user-static package (Ben Noordhuis)
|
||||
|
||||
* linux: move epoll.c back into linux-core.c (Ben Noordhuis)
|
||||
|
||||
* unix: remove pre-macos 10.8 compatibility hack (Ben Noordhuis)
|
||||
|
||||
* unix,win: fix memory leak in uv_fs_scandir() (Ben Noordhuis)
|
||||
|
||||
* build: restore qemu download logic (Ben Noordhuis)
|
||||
|
||||
* win: fix uv__pipe_accept memory leak (number201724)
|
||||
|
||||
* doc: update LINKS.md (Daniel)
|
||||
|
||||
* unix: simplify atomic op in uv_tty_reset_mode() (Ben Noordhuis)
|
||||
|
||||
* build: add LIBUV_BUILD_SHARED cmake option (Christian Clason)
|
||||
|
||||
* linux: remove unused or obsolete syscall wrappers (Ben Noordhuis)
|
||||
|
||||
* linux: merge files back into single file (Ben Noordhuis)
|
||||
|
||||
* stream: process more than one write req per loop tick (ywave620)
|
||||
|
||||
* unix,win: give thread pool threads an 8 MB stack (Ben Noordhuis)
|
||||
|
||||
* build: add MemorySanitizer (MSAN) support (Ben Noordhuis)
|
||||
|
||||
* doc: add uv_poll_cb status==UV_EBADF note (jensbjorgensen)
|
||||
|
||||
* build: support AddressSanitizer on MSVC (Jameson Nash)
|
||||
|
||||
* win,pipe: improve method of obtaining pid for ipc (number201724)
|
||||
|
||||
* thread: add support for affinity (daomingq)
|
||||
|
||||
* include: map ENODATA error code (Ben Noordhuis)
|
||||
|
||||
* build: remove bashism from autogen.sh (Santiago Gimeno)
|
||||
|
||||
* win,tcp,udp: remove "active streams" optimization (Saúl Ibarra Corretgé)
|
||||
|
||||
* win: drop code checking for Windows XP / Server 2k3 (Saúl Ibarra Corretgé)
|
||||
|
||||
* unix,win: fix 'sprintf' is deprecated warning (twosee)
|
||||
|
||||
* doc: mention close_cb can be NULL (Qix)
|
||||
|
||||
* win: optimize udp receive performance (ywave620)
|
||||
|
||||
* win: fix an incompatible types warning (twosee)
|
||||
|
||||
* doc: document 0 return value for free/total memory (Ben Noordhuis)
|
||||
|
||||
* darwin: use hw.cpufrequency again for frequency info (Jameson Nash)
|
||||
|
||||
* win,test: change format of TEST_PIPENAME's (Santiago Gimeno)
|
||||
|
||||
* win,pipe: fixes in uv_pipe_connect() (Santiago Gimeno)
|
||||
|
||||
* misc: fix return value of memory functions (theanarkh)
|
||||
|
||||
* src: add new metrics APIs (Trevor Norris)
|
||||
|
||||
* thread: add uv_thread_getcpu() (daomingq)
|
||||
|
||||
* build: don't use ifaddrs.h on solaris 10 (Edward Humes)
|
||||
|
||||
* unix,win: add uv_get_available_memory() (Tim Besard)
|
||||
|
||||
* test: fix -Wunused-but-set-variable warnings (Ben Noordhuis)
|
||||
|
||||
* doc: bump min supported linux and freebsd versions (Ben Noordhuis)
|
||||
|
||||
* Add Socket Runtime to the LINKS.md (Sergey Rubanov)
|
||||
|
||||
* unix: drop kfreebsd support (Ben Noordhuis)
|
||||
|
||||
* win: fix fstat for pipes and character files (Stefan Stojanovic)
|
||||
|
||||
* win: fix -Wunused-variable warning (Ben Noordhuis)
|
||||
|
||||
* win: fix -Wunused-function warning (Ben Noordhuis)
|
||||
|
||||
* build: drop qemu-alpha from ci matrix (Ben Noordhuis)
|
||||
|
||||
* win: move child_stdio_buffer out of uv_process_t (Santiago Gimeno)
|
||||
|
||||
* test: fix some unreachable code warnings (Santiago Gimeno)
|
||||
|
||||
* linux: simplify uv_uptime() (Ben Noordhuis)
|
||||
|
||||
* test: unflake fs_event_watch_dir test (Ben Noordhuis)
|
||||
|
||||
* darwin: remove unused fsevents symbol lookups (Ben Noordhuis)
|
||||
|
||||
* build: add define guard around UV_EXTERN (Zvicii)
|
||||
|
||||
* build: add UndefinedBehaviorSanitizer support (Ben Noordhuis)
|
||||
|
||||
* build: enable platform_output test on qemu (Ben Noordhuis)
|
||||
|
||||
* linux: handle cpu hotplugging in uv_cpu_info() (Ben Noordhuis)
|
||||
|
||||
* build: remove unnecessary policy setting (dundargoc)
|
||||
|
||||
* docs: add vcpkg instruction step (Jack·Boos·Yu)
|
||||
|
||||
* win,fs: fix readlink errno for a non-symlink file (Darshan Sen)
|
||||
|
||||
* misc: extend getpw to take uid as an argument (Jameson Nash)
|
||||
|
||||
* unix,win: use static_assert when available (Ben Noordhuis)
|
||||
|
||||
* docs: delete code Makefile (Jameson Nash)
|
||||
|
||||
* docs: add CI for docs PRs (Jameson Nash)
|
||||
|
||||
* docs: update Sphinx version on RTD (Jameson Nash)
|
||||
|
||||
* doc: clean up license file (Ben Noordhuis)
|
||||
|
||||
* test: fix some warnings when compiling tests (panran)
|
||||
|
||||
* build,win: add mingw-w64 CI configuration (Jameson Nash)
|
||||
|
||||
* build: add CI for distcheck (Jameson Nash)
|
||||
|
||||
* unix: remove busy loop from uv_async_send (Jameson Nash)
|
||||
|
||||
* doc: document uv_fs_cb type (Tamás Bálint Misius)
|
||||
|
||||
* build: Improve build by cmake for Cygwin (erw7)
|
||||
|
||||
* build: add libuv:: namespace to libuvConfig.cmake (AJ Heller)
|
||||
|
||||
* test: fix ThreadSanitizer thread leak warning (Ben Noordhuis)
|
||||
|
||||
* test: fix ThreadSanitizer data race warning (Ben Noordhuis)
|
||||
|
||||
* test: fix ThreadSanitizer data race warning (Ben Noordhuis)
|
||||
|
||||
* test: fix ThreadSanitizer data race warning (Ben Noordhuis)
|
||||
|
||||
* test: cond-skip fork_threadpool_queue_work_simple (Ben Noordhuis)
|
||||
|
||||
* test: cond-skip signal_multiple_loops (Ben Noordhuis)
|
||||
|
||||
* test: cond-skip tcp_writealot (Ben Noordhuis)
|
||||
|
||||
* build: promote tsan ci to must-pass (Ben Noordhuis)
|
||||
|
||||
* build: add CI for OpenBSD and FreeBSD (James McCoy)
|
||||
|
||||
* build,test: fix distcheck errors (Jameson Nash)
|
||||
|
||||
* test: remove bad tty window size assumption (Ben Noordhuis)
|
||||
|
||||
* darwin,process: feed kevent the signal to reap children (Jameson Nash)
|
||||
|
||||
* unix: abort on clock_gettime() error (Ben Noordhuis)
|
||||
|
||||
* test: remove timing-sensitive check (Ben Noordhuis)
|
||||
|
||||
* unix: DRY and fix tcp bind error path (Jameson Nash)
|
||||
|
||||
* macos: fix fsevents thread race conditions (Ben Noordhuis)
|
||||
|
||||
* win: fix leak in uv_chdir (Trevor Norris)
|
||||
|
||||
* test: make valgrind happy (Trevor Norris)
|
||||
|
||||
* barrier: wait for prior out before next in (Jameson Nash)
|
||||
|
||||
* test: fix visual studio 2015 build error (Ben Noordhuis)
|
||||
|
||||
* linux: fix ceph copy error truncating readonly files (Bruno Passeri)
|
||||
|
||||
* test: silence more valgrind warnings (Trevor Norris)
|
||||
|
||||
* doc: add entries to LINKS.md (Trevor Norris)
|
||||
|
||||
* win,unix: change execution order of timers (Trevor Norris)
|
||||
|
||||
* doc: add trevnorris to maintainers (Trevor Norris)
|
||||
|
||||
* linux: remove epoll_pwait() emulation code path (Ben Noordhuis)
|
||||
|
||||
* linux: replace unsafe macro with inline function (Ben Noordhuis)
|
||||
|
||||
* linux: remove arm oabi support (Ben Noordhuis)
|
||||
|
||||
* unix,sunos: SO_REUSEPORT not valid on all sockets (Stacey Marshall)
|
||||
|
||||
* doc: consistent single backquote in misc.rst (Jason Zhang)
|
||||
|
||||
* src: switch to use C11 atomics where available (Trevor Norris)
|
||||
|
||||
* test: don't use static buffer for formatting (Ben Noordhuis)
|
||||
|
||||
* linux: introduce io_uring support (Ben Noordhuis)
|
||||
|
||||
* linux: fix academic valgrind warning (Ben Noordhuis)
|
||||
|
||||
* test: disable signal test under ASan and MSan (Ben Noordhuis)
|
||||
|
||||
* linux: add IORING_OP_OPENAT support (Ben Noordhuis)
|
||||
|
||||
* linux: add IORING_OP_CLOSE support (Ben Noordhuis)
|
||||
|
||||
* linux: remove bug workaround for obsolete kernels (Ben Noordhuis)
|
||||
|
||||
* doc: update active maintainers list (Ben Noordhuis)
|
||||
|
||||
* test: add ASSERT_OK (Trevor Norris)
|
||||
|
||||
* src: fix events/events_waiting metrics counter (Trevor Norris)
|
||||
|
||||
* unix,win: add uv_clock_gettime() (Ben Noordhuis)
|
||||
|
||||
* build: remove freebsd and openbsd buildbots (Ben Noordhuis)
|
||||
|
||||
* win: fix race condition in uv__init_console() (sivadeilra)
|
||||
|
||||
* linux: fix logic bug in sqe ring space check (Ben Noordhuis)
|
||||
|
||||
* linux: use io_uring to batch epoll_ctl calls (Ben Noordhuis)
|
||||
|
||||
* macos: update minimum supported version (Santiago Gimeno)
|
||||
|
||||
* docs: fix some typos (cui fliter)
|
||||
|
||||
* unix: use memcpy() instead of type punning (Ben Noordhuis)
|
||||
|
||||
* test: add additional assert (Mohammed Keyvanzadeh)
|
||||
|
||||
* build: export compile_commands.json (Lewis Russell)
|
||||
|
||||
* win,process: write minidumps when sending SIGQUIT (Elliot Saba)
|
||||
|
||||
* unix: constrained_memory should return UINT64_MAX (Tim Besard)
|
||||
|
||||
* unix: handle CQ overflow in iou ring (Santiago Gimeno)
|
||||
|
||||
* unix: remove clang compiler warning pragmas (Ben Noordhuis)
|
||||
|
||||
* win: fix mingw build (gengjiawen)
|
||||
|
||||
* test: fix -Wbool-compare compiler warning (Ben Noordhuis)
|
||||
|
||||
* win: define MiniDumpWithAvxXStateContext always (Santiago Gimeno)
|
||||
|
||||
* freebsd: hard-code UV_ENODATA definition (Santiago Gimeno)
|
||||
|
||||
* linux: work around EOWNERDEAD io_uring kernel bug (Ben Noordhuis)
|
||||
|
||||
* linux: fix WRITEV with lots of bufs using io_uring (Santiago Gimeno)
|
||||
|
||||
|
||||
2022.07.12, Version 1.44.2 (Stable), 0c1fa696aa502eb749c2c4735005f41ba00a27b8
|
||||
|
||||
Changes since version 1.44.1:
|
||||
|
||||
|
47
deps/libuv/LICENSE
vendored
47
deps/libuv/LICENSE
vendored
@ -1,6 +1,3 @@
|
||||
libuv is licensed for use as follows:
|
||||
|
||||
====
|
||||
Copyright (c) 2015-present libuv project contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -20,47 +17,3 @@ 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.
|
||||
====
|
||||
|
||||
This license applies to parts of libuv originating from the
|
||||
https://github.com/joyent/libuv repository:
|
||||
|
||||
====
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
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.
|
||||
|
||||
====
|
||||
|
||||
This license applies to all parts of libuv that are not externally
|
||||
maintained libraries.
|
||||
|
||||
The externally maintained libraries used by libuv are:
|
||||
|
||||
- tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
|
||||
|
||||
- inet_pton and inet_ntop implementations, contained in src/inet.c, are
|
||||
copyright the Internet Systems Consortium, Inc., and licensed under the ISC
|
||||
license.
|
||||
|
||||
- stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
|
||||
clause BSD license.
|
||||
|
||||
- pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB.
|
||||
Three clause BSD license.
|
||||
|
36
deps/libuv/LICENSE-extra
vendored
Normal file
36
deps/libuv/LICENSE-extra
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
This license applies to parts of libuv originating from the
|
||||
https://github.com/joyent/libuv repository:
|
||||
|
||||
====
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
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.
|
||||
|
||||
====
|
||||
|
||||
This license applies to all parts of libuv that are not externally
|
||||
maintained libraries.
|
||||
|
||||
The externally maintained libraries used by libuv are:
|
||||
|
||||
- tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
|
||||
|
||||
- inet_pton and inet_ntop implementations, contained in src/inet.c, are
|
||||
copyright the Internet Systems Consortium, Inc., and licensed under the ISC
|
||||
license.
|
12
deps/libuv/LINKS.md
vendored
12
deps/libuv/LINKS.md
vendored
@ -1,16 +1,20 @@
|
||||
### Apps / VM
|
||||
* [AliceO2](https://github.com/AliceO2Group/AliceO2): The framework and detector specific code for the reconstruction, calibration and simulation for the ALICE experiment at CERN.
|
||||
* [Beam](https://github.com/BeamMW/beam): A scalable, confidential cryptocurrency based on the Mimblewimble protocol.
|
||||
* [BIND 9](https://bind.isc.org/): DNS software system including an authoritative server, a recursive resolver and related utilities.
|
||||
* [cjdns](https://github.com/cjdelisle/cjdns): Encrypted self-configuring network/VPN routing engine
|
||||
* [clearskies_core](https://github.com/larroy/clearskies_core): Clearskies file synchronization program. (C++11)
|
||||
* [CMake](https://cmake.org) open-source, cross-platform family of tools designed to build, test and package software
|
||||
* [Coherence](https://github.com/liesware/coherence/): Cryptographic server for modern web apps.
|
||||
* [Cocos-Engine](https://github.com/cocos/cocos-engine): The runtime framework for Cocos Creator editor.
|
||||
* [Coherence](https://github.com/liesware/coherence/): Cryptographic server for modern web apps.
|
||||
* [DPS8M](https://dps8m.gitlab.io): GE ∕ Honeywell ∕ Bull DPS‑8/M and 6180/L68 mainframe simulator.
|
||||
* [DPS-For-IoT](https://github.com/intel/dps-for-iot/wiki): Fully distributed publish/subscribe protocol.
|
||||
* [HashLink](https://github.com/HaxeFoundation/hashlink): Haxe run-time with libuv support included.
|
||||
* [Haywire](https://github.com/kellabyte/Haywire): Asynchronous HTTP server.
|
||||
* [H2O](https://github.com/h2o/h2o): An optimized HTTP server with support for HTTP/1.x and HTTP/2.
|
||||
* [Igropyr](https://github.com/guenchi/Igropyr): a async Scheme http server base on libuv.
|
||||
* [Julia](http://julialang.org/): Scientific computing programming language
|
||||
* [Kestrel](https://github.com/aspnet/AspNetCore/tree/master/src/Servers/Kestrel): web server (C# + libuv + [ASP.NET Core](http://github.com/aspnet))
|
||||
* [Kestrel](https://github.com/dotnet/aspnetcore/tree/main/src/Servers/Kestrel): web server (C# + libuv + [ASP.NET Core](http://github.com/aspnet))
|
||||
* [Knot DNS Resolver](https://www.knot-resolver.cz/): A minimalistic DNS caching resolver
|
||||
* [Lever](http://leverlanguage.com): runtime, libuv at the 0.9.0 release
|
||||
* [libnode](https://github.com/plenluno/libnode): C++ implementation of Node.js
|
||||
@ -30,8 +34,10 @@
|
||||
* [phastlight](https://github.com/phastlight/phastlight): Command line tool and web server written in PHP 5.3+ inspired by Node.js
|
||||
* [pilight](https://www.pilight.org/): home automation ("domotica")
|
||||
* [pixie](https://github.com/pixie-lang/pixie): clojure-inspired lisp with a tracing JIT
|
||||
* [Pixie-io](https://github.com/pixie-io/pixie): Open-source observability tool for Kubernetes applications.
|
||||
* [potion](https://github.com/perl11/potion)/[p2](https://github.com/perl11/p2): runtime
|
||||
* [racer](https://libraries.io/rubygems/racer): Ruby web server written as an C extension
|
||||
* [Socket Runtime](https://sockets.sh): A runtime for creating native cross-platform software on mobile and desktop using HTML, CSS, and JavaScript
|
||||
* [spider-gazelle](https://github.com/cotag/spider-gazelle): Ruby web server using libuv bindings
|
||||
* [Suave](http://suave.io/): A simple web development F# library providing a lightweight web server and a set of combinators to manipulate route flow and task composition
|
||||
* [Swish](https://github.com/becls/swish/): Concurrency engine with Erlang-like concepts. Includes a web server.
|
||||
@ -39,6 +45,7 @@
|
||||
* [Urbit](http://urbit.org): runtime
|
||||
* [uv_callback](https://github.com/litesync/uv_callback) libuv thread communication
|
||||
* [uvloop](https://github.com/MagicStack/uvloop): Ultra fast implementation of python's asyncio event loop on top of libuv
|
||||
* [WPILib](https://github.com/wpilibsuite/allwpilib): Libraries for creating robot programs for the roboRIO.
|
||||
* [Wren CLI](https://github.com/wren-lang/wren-cli): For io, process, scheduler and timer modules
|
||||
|
||||
### Other
|
||||
@ -59,6 +66,7 @@
|
||||
* [lluv](https://github.com/moteus/lua-lluv)
|
||||
* C++11
|
||||
* [uvpp](https://github.com/larroy/uvpp) - Not complete, exposes very few aspects of `libuv`
|
||||
* [nsuv](https://github.com/nodesource/nsuv) - Template wrapper focused on enforcing compile-time type safety when propagating data
|
||||
* C++17
|
||||
* [uvw](https://github.com/skypjack/uvw) - Header-only, event based, tiny and easy to use *libuv* wrapper in modern C++.
|
||||
* Python
|
||||
|
8
deps/libuv/MAINTAINERS.md
vendored
8
deps/libuv/MAINTAINERS.md
vendored
@ -4,12 +4,9 @@ libuv is currently managed by the following individuals:
|
||||
|
||||
* **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis))
|
||||
- GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis)
|
||||
* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus))
|
||||
* **Colin Ihrig** ([@cjihrig](https://github.com/cjihrig))
|
||||
- GPG key: 94AE 3667 5C46 4D64 BAFA 68DD 7434 390B DBE9 B9C5 (pubkey-cjihrig)
|
||||
- GPG key: 5735 3E0D BDAA A7E8 39B6 6A1A FF47 D5E4 AD8B 4FDC (pubkey-cjihrig-kb)
|
||||
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
|
||||
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
|
||||
* **Jameson Nash** ([@vtjnash](https://github.com/vtjnash))
|
||||
- GPG key: AEAD 0A4B 6867 6775 1A0E 4AEF 34A2 5FB1 2824 6514 (pubkey-vtjnash)
|
||||
- GPG key: CFBB 9CA9 A5BE AFD7 0E2B 3C5A 79A6 7C55 A367 9C8B (pubkey2022-vtjnash)
|
||||
@ -22,11 +19,16 @@ libuv is currently managed by the following individuals:
|
||||
- GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno)
|
||||
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
|
||||
- GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul)
|
||||
* **Trevor Norris** ([@trevnorris](https://github.com/trevnorris))
|
||||
- GPG key: AEFC 279A 0C93 0676 7E58 29A1 251C A676 820D C7F3 (pubkey-trevnorris)
|
||||
|
||||
## Project Maintainers emeriti
|
||||
|
||||
* **Anna Henningsen** ([@addaleax](https://github.com/addaleax))
|
||||
* **Bartosz Sosnowski** ([@bzoz](https://github.com/bzoz))
|
||||
* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus))
|
||||
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
|
||||
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
|
||||
* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq))
|
||||
* **John Barboza** ([@jbarz](https://github.com/jbarz))
|
||||
|
||||
|
24
deps/libuv/Makefile.am
vendored
24
deps/libuv/Makefile.am
vendored
@ -38,6 +38,7 @@ libuv_la_SOURCES = src/fs-poll.c \
|
||||
src/random.c \
|
||||
src/strscpy.c \
|
||||
src/strscpy.h \
|
||||
src/thread-common.c \
|
||||
src/threadpool.c \
|
||||
src/timer.c \
|
||||
src/uv-data-getter-setters.c \
|
||||
@ -96,7 +97,6 @@ else # WINNT
|
||||
uvinclude_HEADERS += include/uv/unix.h
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/unix
|
||||
libuv_la_SOURCES += src/unix/async.c \
|
||||
src/unix/atomic-ops.h \
|
||||
src/unix/core.c \
|
||||
src/unix/dl.c \
|
||||
src/unix/fs.c \
|
||||
@ -110,7 +110,6 @@ libuv_la_SOURCES += src/unix/async.c \
|
||||
src/unix/process.c \
|
||||
src/unix/random-devurandom.c \
|
||||
src/unix/signal.c \
|
||||
src/unix/spinlock.h \
|
||||
src/unix/stream.c \
|
||||
src/unix/tcp.c \
|
||||
src/unix/thread.c \
|
||||
@ -122,11 +121,13 @@ endif # WINNT
|
||||
EXTRA_DIST = test/fixtures/empty_file \
|
||||
test/fixtures/load_error.node \
|
||||
test/fixtures/lorem_ipsum.txt \
|
||||
test/fixtures/one_file/one_file \
|
||||
include \
|
||||
docs \
|
||||
img \
|
||||
CONTRIBUTING.md \
|
||||
LICENSE \
|
||||
LICENSE-extra \
|
||||
README.md
|
||||
|
||||
|
||||
@ -278,11 +279,13 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-tcp-writealot.c \
|
||||
test/test-tcp-write-fail.c \
|
||||
test/test-tcp-try-write.c \
|
||||
test/test-tcp-write-in-a-row.c \
|
||||
test/test-tcp-try-write-error.c \
|
||||
test/test-tcp-write-queue-order.c \
|
||||
test/test-test-macros.c \
|
||||
test/test-thread-equal.c \
|
||||
test/test-thread.c \
|
||||
test/test-thread-affinity.c \
|
||||
test/test-threadpool-cancel.c \
|
||||
test/test-threadpool.c \
|
||||
test/test-timer-again.c \
|
||||
@ -313,6 +316,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-udp-sendmmsg-error.c \
|
||||
test/test-udp-send-unreachable.c \
|
||||
test/test-udp-try-send.c \
|
||||
test/test-udp-recv-in-a-row.c \
|
||||
test/test-uname.c \
|
||||
test/test-walk-handles.c \
|
||||
test/test-watcher-cross-stop.c
|
||||
@ -393,7 +397,6 @@ endif
|
||||
|
||||
if ANDROID
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/pthread-fixes.c
|
||||
endif
|
||||
|
||||
if CYGWIN
|
||||
@ -467,22 +470,14 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/hurd.c
|
||||
endif
|
||||
|
||||
if KFREEBSD
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
endif
|
||||
|
||||
if LINUX
|
||||
uvinclude_HEADERS += include/uv/linux.h
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/linux-core.c \
|
||||
src/unix/linux-inotify.c \
|
||||
src/unix/linux-syscalls.c \
|
||||
src/unix/linux-syscalls.h \
|
||||
libuv_la_SOURCES += src/unix/linux.c \
|
||||
src/unix/procfs-exepath.c \
|
||||
src/unix/proctitle.c \
|
||||
src/unix/random-getrandom.c \
|
||||
src/unix/random-sysctl-linux.c \
|
||||
src/unix/epoll.c
|
||||
src/unix/random-sysctl-linux.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
@ -546,8 +541,7 @@ libuv_la_CFLAGS += -D_UNIX03_THREADS \
|
||||
-qXPLINK \
|
||||
-qFLOAT=IEEE
|
||||
libuv_la_LDFLAGS += -qXPLINK
|
||||
libuv_la_SOURCES += src/unix/pthread-fixes.c \
|
||||
src/unix/os390.c \
|
||||
libuv_la_SOURCES += src/unix/os390.c \
|
||||
src/unix/os390-syscalls.c \
|
||||
src/unix/proctitle.c
|
||||
endif
|
||||
|
16
deps/libuv/README.md
vendored
16
deps/libuv/README.md
vendored
@ -43,8 +43,11 @@ The ABI/API changes can be tracked [here](http://abi-laboratory.pro/tracker/time
|
||||
|
||||
## Licensing
|
||||
|
||||
libuv is licensed under the MIT license. Check the [LICENSE file](LICENSE).
|
||||
The documentation is licensed under the CC BY 4.0 license. Check the [LICENSE-docs file](LICENSE-docs).
|
||||
libuv is licensed under the MIT license. Check the [LICENSE](LICENSE) and
|
||||
[LICENSE-extra](LICENSE-extra) files.
|
||||
|
||||
The documentation is licensed under the CC BY 4.0 license. Check the
|
||||
[LICENSE-docs file](LICENSE-docs).
|
||||
|
||||
## Community
|
||||
|
||||
@ -220,6 +223,15 @@ Make sure that you specify the architecture you wish to build for in the
|
||||
"ARCHS" flag. You can specify more than one by delimiting with a space
|
||||
(e.g. "x86_64 i386").
|
||||
|
||||
### Install with vcpkg
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/microsoft/vcpkg.git
|
||||
$ ./bootstrap-vcpkg.bat # for powershell
|
||||
$ ./bootstrap-vcpkg.sh # for bash
|
||||
$ ./vcpkg install libuv
|
||||
```
|
||||
|
||||
### Running tests
|
||||
|
||||
Some tests are timing sensitive. Relaxing test timeouts may be necessary
|
||||
|
6
deps/libuv/SUPPORTED_PLATFORMS.md
vendored
6
deps/libuv/SUPPORTED_PLATFORMS.md
vendored
@ -2,10 +2,10 @@
|
||||
|
||||
| System | Support type | Supported versions | Notes |
|
||||
|---|---|---|---|
|
||||
| GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | |
|
||||
| macOS | Tier 1 | macOS >= 10.15 | Current and previous macOS release |
|
||||
| GNU/Linux | Tier 1 | Linux >= 3.10 with glibc >= 2.17 | |
|
||||
| macOS | Tier 1 | macOS >= 11 | Currently supported macOS releases |
|
||||
| Windows | Tier 1 | >= Windows 8 | VS 2015 and later are supported |
|
||||
| FreeBSD | Tier 1 | >= 10 | |
|
||||
| FreeBSD | Tier 2 | >= 12 | |
|
||||
| AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix |
|
||||
| IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |
|
||||
| z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos |
|
||||
|
2
deps/libuv/autogen.sh
vendored
2
deps/libuv/autogen.sh
vendored
@ -17,7 +17,7 @@
|
||||
set -eu
|
||||
cd `dirname "$0"`
|
||||
|
||||
if [ "${1:-dev}" == "release" ]; then
|
||||
if [ "${1:-dev}" = "release" ]; then
|
||||
export LIBUV_RELEASE=true
|
||||
else
|
||||
export LIBUV_RELEASE=false
|
||||
|
17
deps/libuv/cmake-toolchains/cross-mingw32.cmake
vendored
Normal file
17
deps/libuv/cmake-toolchains/cross-mingw32.cmake
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
if(NOT HOST_ARCH)
|
||||
message(SEND_ERROR "-DHOST_ARCH required to be specified")
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
|
||||
HOST_ARCH
|
||||
)
|
||||
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
set(COMPILER_PREFIX "${HOST_ARCH}-w64-mingw32")
|
||||
find_program(CMAKE_RC_COMPILER NAMES ${COMPILER_PREFIX}-windres)
|
||||
find_program(CMAKE_C_COMPILER NAMES ${COMPILER_PREFIX}-gcc)
|
||||
find_program(CMAKE_CXX_COMPILER NAMES ${COMPILER_PREFIX}-g++)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
15
deps/libuv/configure.ac
vendored
15
deps/libuv/configure.ac
vendored
@ -13,12 +13,13 @@
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([libuv], [1.44.2], [https://github.com/libuv/libuv/issues])
|
||||
AC_INIT([libuv], [1.46.0], [https://github.com/libuv/libuv/issues])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
m4_include([m4/libuv-extra-automake-flags.m4])
|
||||
m4_include([m4/as_case.m4])
|
||||
m4_include([m4/libuv-check-flags.m4])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS)
|
||||
AM_MAINTAINER_MODE([enable]) # pass --disable-maintainer-mode if autotools may be unavailable
|
||||
AC_CANONICAL_HOST
|
||||
AC_ENABLE_SHARED
|
||||
AC_ENABLE_STATIC
|
||||
@ -61,8 +62,7 @@ AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])
|
||||
AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false])])
|
||||
AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])])
|
||||
AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])])
|
||||
AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])])
|
||||
AM_CONDITIONAL([KFREEBSD], [AS_CASE([$host_os],[kfreebsd*], [true], [false])])
|
||||
AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[freebsd*], [true], [false])])
|
||||
AM_CONDITIONAL([HAIKU], [AS_CASE([$host_os],[haiku], [true], [false])])
|
||||
AM_CONDITIONAL([HURD], [AS_CASE([$host_os],[gnu*], [true], [false])])
|
||||
AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])])
|
||||
@ -74,12 +74,12 @@ AM_CONDITIONAL([OS400], [AS_CASE([$host_os],[os400], [true], [false])
|
||||
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
|
||||
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
|
||||
AS_CASE([$host_os],[mingw*], [
|
||||
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -luser32"
|
||||
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -luser32 -ldbghelp -lole32 -luuid"
|
||||
])
|
||||
AS_CASE([$host_os], [solaris2.10], [
|
||||
CFLAGS="$CFLAGS -DSUNOS_NO_IFADDRS"
|
||||
])
|
||||
AS_CASE([$host_os], [netbsd*], [AC_CHECK_LIB([kvm], [kvm_open])])
|
||||
AS_CASE([$host_os], [kfreebsd*], [
|
||||
LIBS="$LIBS -lfreebsd-glue"
|
||||
])
|
||||
AS_CASE([$host_os], [haiku], [
|
||||
LIBS="$LIBS -lnetwork"
|
||||
])
|
||||
@ -88,4 +88,5 @@ AC_CONFIG_FILES([Makefile libuv.pc])
|
||||
AC_CONFIG_LINKS([test/fixtures/empty_file:test/fixtures/empty_file])
|
||||
AC_CONFIG_LINKS([test/fixtures/load_error.node:test/fixtures/load_error.node])
|
||||
AC_CONFIG_LINKS([test/fixtures/lorem_ipsum.txt:test/fixtures/lorem_ipsum.txt])
|
||||
AC_CONFIG_LINKS([test/fixtures/one_file/one_file:test/fixtures/one_file/one_file])
|
||||
AC_OUTPUT
|
||||
|
82
deps/libuv/docs/code/Makefile
vendored
82
deps/libuv/docs/code/Makefile
vendored
@ -1,82 +0,0 @@
|
||||
examples=\
|
||||
helloworld\
|
||||
default-loop\
|
||||
idle-basic\
|
||||
uvcat\
|
||||
uvtee\
|
||||
onchange\
|
||||
thread-create\
|
||||
queue-work\
|
||||
progress\
|
||||
tcp-echo-server\
|
||||
dns\
|
||||
udp-dhcp\
|
||||
idle-compute\
|
||||
ref-timer\
|
||||
spawn\
|
||||
detach\
|
||||
proc-streams\
|
||||
cgi\
|
||||
pipe-echo-server\
|
||||
multi-echo-server\
|
||||
tty\
|
||||
tty-gravity\
|
||||
interfaces\
|
||||
locks \
|
||||
signal \
|
||||
uvstop \
|
||||
queue-cancel
|
||||
|
||||
UV_PATH=$(shell pwd)/../..
|
||||
UV_LIB=$(UV_PATH)/.libs/libuv.a
|
||||
CFLAGS=-g -Wall -I$(UV_PATH)/include
|
||||
LIBS=
|
||||
|
||||
uname_S=$(shell uname -s)
|
||||
|
||||
ifeq (Darwin, $(uname_S))
|
||||
CFLAGS+=-framework CoreServices
|
||||
SHARED_LIB_FLAGS=-bundle -undefined dynamic_lookup -o plugin/libhello.dylib
|
||||
endif
|
||||
|
||||
ifeq (Linux, $(uname_S))
|
||||
LIBS=-lrt -ldl -lm -pthread -lcurl
|
||||
SHARED_LIB_FLAGS=-shared -Wl,-soname,libhello.so -o plugin/libhello.so
|
||||
PLUGIN_EXE_FLAGS=-Wl,-export-dynamic
|
||||
endif
|
||||
|
||||
|
||||
all: $(examples) plugin/plugin proc-streams/test cgi/tick multi-echo-server/worker uvwget/uvwget
|
||||
|
||||
$(examples): % : %/main.c
|
||||
gcc $(CFLAGS) -o $@/$@ $< $(UV_LIB) $(LIBS)
|
||||
|
||||
plugin: plugin/plugin
|
||||
plugin/plugin: plugin/*.c
|
||||
gcc $(CFLAGS) $(PLUGIN_EXE_FLAGS) -o plugin/plugin plugin/main.c $(UV_LIB) $(LIBS)
|
||||
gcc -g -Wall -c -fPIC -o plugin/hello.o plugin/hello.c
|
||||
gcc $(SHARED_LIB_FLAGS) plugin/hello.o
|
||||
|
||||
proc-streams/test: proc-streams/test.c
|
||||
gcc -g -Wall -o proc-streams/test proc-streams/test.c
|
||||
|
||||
cgi/tick: cgi/tick.c
|
||||
gcc -g -Wall -o cgi/tick cgi/tick.c
|
||||
|
||||
multi-echo-server/worker: multi-echo-server/worker.c
|
||||
gcc $(CFLAGS) -o multi-echo-server/worker multi-echo-server/worker.c $(UV_LIB) $(LIBS)
|
||||
|
||||
uvwget: uvwget/uvwget
|
||||
uvwget/uvwget: uvwget/main.c
|
||||
gcc $(CFLAGS) `curl-config --cflags --libs` -o uvwget/uvwget uvwget/main.c $(UV_LIB) $(LIBS)
|
||||
|
||||
clean:
|
||||
for dir in $(examples); do cd $$dir; rm -f $$dir; rm -rf $$dir.dSYM; cd ..; done
|
||||
rm -rf plugin/*.o plugin/libhello.*
|
||||
rm -rf plugin/plugin plugin/plugin.dSYM
|
||||
rm -rf proc-streams/test proc-streams/test.dSYM
|
||||
rm -rf cgi/tick cgi/tick.dSYM
|
||||
rm -rf multi-echo-server/worker multi-echo-server/worker.dSYM
|
||||
rm -rf uvwget/uvwget uvwget/uvwget.dSYM
|
||||
|
||||
.PHONY: clean all $(examples) plugin uvwget
|
57
deps/libuv/docs/requirements.txt
vendored
57
deps/libuv/docs/requirements.txt
vendored
@ -1,42 +1,27 @@
|
||||
# primary
|
||||
Sphinx==3.5.4
|
||||
sphinx==6.1.3
|
||||
|
||||
# dependencies
|
||||
alabaster==0.7.12
|
||||
appdirs==1.4.3
|
||||
Babel==2.9.0
|
||||
CacheControl==0.12.6
|
||||
certifi==2019.11.28
|
||||
chardet==3.0.4
|
||||
colorama==0.4.3
|
||||
contextlib2==0.6.0
|
||||
distlib==0.3.0
|
||||
distro==1.4.0
|
||||
docutils==0.16
|
||||
html5lib==1.0.1
|
||||
idna==2.8
|
||||
imagesize==1.2.0
|
||||
ipaddr==2.2.0
|
||||
Jinja2==2.11.3
|
||||
lockfile==0.12.2
|
||||
MarkupSafe==1.1.1
|
||||
msgpack==0.6.2
|
||||
packaging==20.3
|
||||
pep517==0.8.2
|
||||
progress==1.5
|
||||
Pygments==2.8.1
|
||||
pyparsing==2.4.6
|
||||
pytoml==0.1.21
|
||||
pytz==2021.1
|
||||
requests==2.22.0
|
||||
retrying==1.3.3
|
||||
six==1.14.0
|
||||
snowballstemmer==2.1.0
|
||||
sphinxcontrib-applehelp==1.0.2
|
||||
alabaster==0.7.13
|
||||
Babel==2.11.0
|
||||
certifi==2022.12.7
|
||||
charset-normalizer==3.0.1
|
||||
docutils==0.19
|
||||
idna==3.4
|
||||
imagesize==1.4.1
|
||||
importlib-metadata==6.0.0
|
||||
Jinja2==3.1.2
|
||||
MarkupSafe==2.1.2
|
||||
packaging==23.0
|
||||
Pygments==2.14.0
|
||||
pytz==2022.7.1
|
||||
requests==2.28.2
|
||||
snowballstemmer==2.2.0
|
||||
sphinxcontrib-applehelp==1.0.3
|
||||
sphinxcontrib-devhelp==1.0.2
|
||||
sphinxcontrib-htmlhelp==1.0.3
|
||||
sphinxcontrib-htmlhelp==2.0.0
|
||||
sphinxcontrib-jsmath==1.0.1
|
||||
sphinxcontrib-qthelp==1.0.3
|
||||
sphinxcontrib-serializinghtml==1.1.4
|
||||
urllib3==1.25.8
|
||||
webencodings==0.5.1
|
||||
sphinxcontrib-serializinghtml==1.1.5
|
||||
urllib3==1.26.14
|
||||
zipp==3.11.0
|
||||
|
17
deps/libuv/docs/src/design.rst
vendored
17
deps/libuv/docs/src/design.rst
vendored
@ -60,16 +60,15 @@ stages of a loop iteration:
|
||||
:align: center
|
||||
|
||||
|
||||
#. The loop concept of 'now' is updated. The event loop caches the current time at the start of
|
||||
the event loop tick in order to reduce the number of time-related system calls.
|
||||
#. The loop concept of 'now' is initially set.
|
||||
|
||||
#. Due timers are run if the loop was run with ``UV_RUN_DEFAULT``. All active timers scheduled
|
||||
for a time before the loop's concept of *now* get their callbacks called.
|
||||
|
||||
#. If the loop is *alive* an iteration is started, otherwise the loop will exit immediately. So,
|
||||
when is a loop considered to be *alive*? If a loop has active and ref'd handles, active
|
||||
requests or closing handles it's considered to be *alive*.
|
||||
|
||||
#. Due timers are run. All active timers scheduled for a time before the loop's concept of *now*
|
||||
get their callbacks called.
|
||||
|
||||
#. Pending callbacks are called. All I/O callbacks are called right after polling for I/O, for the
|
||||
most part. There are cases, however, in which calling such a callback is deferred for the next
|
||||
loop iteration. If the previous iteration deferred any I/O callback it will be run at this point.
|
||||
@ -101,9 +100,11 @@ stages of a loop iteration:
|
||||
#. Close callbacks are called. If a handle was closed by calling :c:func:`uv_close` it will
|
||||
get the close callback called.
|
||||
|
||||
#. Special case in case the loop was run with ``UV_RUN_ONCE``, as it implies forward progress.
|
||||
It's possible that no I/O callbacks were fired after blocking for I/O, but some time has passed
|
||||
so there might be timers which are due, those timers get their callbacks called.
|
||||
#. The loop concept of 'now' is updated.
|
||||
|
||||
#. Due timers are run. Note that 'now' is not updated again until the next loop iteration.
|
||||
So if a timer became due while other timers were being processed, it won't be run until
|
||||
the following event loop iteration.
|
||||
|
||||
#. Iteration ends. If the loop was run with ``UV_RUN_NOWAIT`` or ``UV_RUN_ONCE`` modes the
|
||||
iteration ends and :c:func:`uv_run` will return. If the loop was run with ``UV_RUN_DEFAULT``
|
||||
|
3
deps/libuv/docs/src/errors.rst
vendored
3
deps/libuv/docs/src/errors.rst
vendored
@ -339,6 +339,9 @@ Error constants
|
||||
|
||||
socket type not supported
|
||||
|
||||
.. c:macro:: UV_EUNATCH
|
||||
|
||||
protocol driver not attached
|
||||
|
||||
API
|
||||
---
|
||||
|
23
deps/libuv/docs/src/fs.rst
vendored
23
deps/libuv/docs/src/fs.rst
vendored
@ -12,6 +12,12 @@ otherwise it will be performed asynchronously.
|
||||
All file operations are run on the threadpool. See :ref:`threadpool` for information
|
||||
on the threadpool size.
|
||||
|
||||
Starting with libuv v1.45.0, some file operations on Linux are handed off to
|
||||
`io_uring <https://en.wikipedia.org/wiki/Io_uring>` when possible. Apart from
|
||||
a (sometimes significant) increase in throughput there should be no change in
|
||||
observable behavior. Libuv reverts to using its threadpool when the necessary
|
||||
kernel features are unavailable or unsuitable.
|
||||
|
||||
.. note::
|
||||
On Windows `uv_fs_*` functions use utf-8 encoding.
|
||||
|
||||
@ -24,7 +30,8 @@ Data types
|
||||
|
||||
.. c:type:: uv_timespec_t
|
||||
|
||||
Portable equivalent of ``struct timespec``.
|
||||
Y2K38-unsafe data type for storing times with nanosecond resolution.
|
||||
Will be replaced with :c:type:`uv_timespec64_t` in libuv v2.0.
|
||||
|
||||
::
|
||||
|
||||
@ -160,6 +167,10 @@ Data types
|
||||
size_t nentries;
|
||||
} uv_dir_t;
|
||||
|
||||
.. c:type:: void (*uv_fs_cb)(uv_fs_t* req)
|
||||
|
||||
Callback called when a request is completed asynchronously.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
@ -218,7 +229,8 @@ API
|
||||
|
||||
.. c:function:: int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`preadv(2)`.
|
||||
Equivalent to :man:`preadv(2)`. If the `offset` argument is `-1`, then
|
||||
the current file offset is used and updated.
|
||||
|
||||
.. warning::
|
||||
On Windows, under non-MSVC environments (e.g. when GCC or Clang is used
|
||||
@ -231,7 +243,8 @@ API
|
||||
|
||||
.. c:function:: int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`pwritev(2)`.
|
||||
Equivalent to :man:`pwritev(2)`. If the `offset` argument is `-1`, then
|
||||
the current file offset is used and updated.
|
||||
|
||||
.. warning::
|
||||
On Windows, under non-MSVC environments (e.g. when GCC or Clang is used
|
||||
@ -463,10 +476,6 @@ API
|
||||
The background story and some more details on these issues can be checked
|
||||
`here <https://github.com/nodejs/node/issues/7726>`_.
|
||||
|
||||
.. note::
|
||||
This function is not implemented on Windows XP and Windows Server 2003.
|
||||
On these systems, UV_ENOSYS is returned.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
|
||||
.. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
|
||||
|
3
deps/libuv/docs/src/guide/networking.rst
vendored
3
deps/libuv/docs/src/guide/networking.rst
vendored
@ -164,7 +164,7 @@ IPv6 stack only
|
||||
|
||||
IPv6 sockets can be used for both IPv4 and IPv6 communication. If you want to
|
||||
restrict the socket to IPv6 only, pass the ``UV_UDP_IPV6ONLY`` flag to
|
||||
``uv_udp_bind`` [#]_.
|
||||
``uv_udp_bind``.
|
||||
|
||||
Multicast
|
||||
~~~~~~~~~
|
||||
@ -250,7 +250,6 @@ times, with each address being reported once.
|
||||
----
|
||||
|
||||
.. [#] https://beej.us/guide/bgnet/html/#broadcast-packetshello-world
|
||||
.. [#] on Windows only supported on Windows Vista and later.
|
||||
.. [#] https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html#ss6.1
|
||||
.. [#] libuv use the system ``getaddrinfo`` in the libuv threadpool. libuv
|
||||
v0.8.0 and earlier also included c-ares_ as an alternative, but this has been
|
||||
|
2
deps/libuv/docs/src/guide/utilities.rst
vendored
2
deps/libuv/docs/src/guide/utilities.rst
vendored
@ -235,7 +235,7 @@ Our downloader is to be invoked as::
|
||||
|
||||
$ ./uvwget [url1] [url2] ...
|
||||
|
||||
So we add each argument as an URL
|
||||
So we add each argument as a URL
|
||||
|
||||
.. rubric:: uvwget/main.c - Adding urls
|
||||
.. literalinclude:: ../../code/uvwget/main.c
|
||||
|
3
deps/libuv/docs/src/handle.rst
vendored
3
deps/libuv/docs/src/handle.rst
vendored
@ -153,6 +153,9 @@ API
|
||||
In-progress requests, like uv_connect_t or uv_write_t, are cancelled and
|
||||
have their callbacks called asynchronously with status=UV_ECANCELED.
|
||||
|
||||
`close_cb` can be `NULL` in cases where no cleanup or deallocation is
|
||||
necessary.
|
||||
|
||||
.. c:function:: void uv_ref(uv_handle_t* handle)
|
||||
|
||||
Reference the given handle. References are idempotent, that is, if a handle
|
||||
|
48
deps/libuv/docs/src/metrics.rst
vendored
48
deps/libuv/docs/src/metrics.rst
vendored
@ -4,8 +4,46 @@
|
||||
Metrics operations
|
||||
======================
|
||||
|
||||
libuv provides a metrics API to track the amount of time the event loop has
|
||||
spent idle in the kernel's event provider.
|
||||
libuv provides a metrics API to track various internal operations of the event
|
||||
loop.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_metrics_t
|
||||
|
||||
The struct that contains event loop metrics. It is recommended to retrieve
|
||||
these metrics in a :c:type:`uv_prepare_cb` in order to make sure there are
|
||||
no inconsistencies with the metrics counters.
|
||||
|
||||
::
|
||||
|
||||
typedef struct {
|
||||
uint64_t loop_count;
|
||||
uint64_t events;
|
||||
uint64_t events_waiting;
|
||||
/* private */
|
||||
uint64_t* reserved[13];
|
||||
} uv_metrics_t;
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:member:: uint64_t uv_metrics_t.loop_count
|
||||
|
||||
Number of event loop iterations.
|
||||
|
||||
.. c:member:: uint64_t uv_metrics_t.events
|
||||
|
||||
Number of events that have been processed by the event handler.
|
||||
|
||||
.. c:member:: uint64_t uv_metrics_t.events_waiting
|
||||
|
||||
Number of events that were waiting to be processed when the event provider
|
||||
was called.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
@ -25,3 +63,9 @@ API
|
||||
:c:type:`UV_METRICS_IDLE_TIME`.
|
||||
|
||||
.. versionadded:: 1.39.0
|
||||
|
||||
.. c:function:: int uv_metrics_info(uv_loop_t* loop, uv_metrics_t* metrics)
|
||||
|
||||
Copy the current set of event loop metrics to the ``metrics`` pointer.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
85
deps/libuv/docs/src/misc.rst
vendored
85
deps/libuv/docs/src/misc.rst
vendored
@ -73,7 +73,8 @@ Data types
|
||||
|
||||
.. c:type:: uv_timeval_t
|
||||
|
||||
Data type for storing times.
|
||||
Y2K38-unsafe data type for storing times with microsecond resolution.
|
||||
Will be replaced with :c:type:`uv_timeval64_t` in libuv v2.0.
|
||||
|
||||
::
|
||||
|
||||
@ -84,7 +85,7 @@ Data types
|
||||
|
||||
.. c:type:: uv_timeval64_t
|
||||
|
||||
Alternative data type for storing times.
|
||||
Y2K38-safe data type for storing times with microsecond resolution.
|
||||
|
||||
::
|
||||
|
||||
@ -93,6 +94,28 @@ Data types
|
||||
int32_t tv_usec;
|
||||
} uv_timeval64_t;
|
||||
|
||||
.. c:type:: uv_timespec64_t
|
||||
|
||||
Y2K38-safe data type for storing times with nanosecond resolution.
|
||||
|
||||
::
|
||||
|
||||
typedef struct {
|
||||
int64_t tv_sec;
|
||||
int32_t tv_nsec;
|
||||
} uv_timespec64_t;
|
||||
|
||||
.. c:enum:: uv_clock_id
|
||||
|
||||
Clock source for :c:func:`uv_clock_gettime`.
|
||||
|
||||
::
|
||||
|
||||
typedef enum {
|
||||
UV_CLOCK_MONOTONIC,
|
||||
UV_CLOCK_REALTIME
|
||||
} uv_clock_id;
|
||||
|
||||
.. c:type:: uv_rusage_t
|
||||
|
||||
Data type for resource usage results.
|
||||
@ -119,7 +142,10 @@ Data types
|
||||
} uv_rusage_t;
|
||||
|
||||
Members marked with `(X)` are unsupported on Windows.
|
||||
See :man:`getrusage(2)` for supported fields on Unix
|
||||
See :man:`getrusage(2)` for supported fields on UNIX-like platforms.
|
||||
|
||||
The maximum resident set size is reported in kilobytes, the unit most
|
||||
platforms use natively.
|
||||
|
||||
.. c:type:: uv_cpu_info_t
|
||||
|
||||
@ -211,7 +237,7 @@ API
|
||||
type of the stdio streams.
|
||||
|
||||
For :man:`isatty(3)` equivalent functionality use this function and test
|
||||
for ``UV_TTY``.
|
||||
for `UV_TTY`.
|
||||
|
||||
.. c:function:: int uv_replace_allocator(uv_malloc_func malloc_func, uv_realloc_func realloc_func, uv_calloc_func calloc_func, uv_free_func free_func)
|
||||
|
||||
@ -225,8 +251,8 @@ API
|
||||
after all resources have been freed and thus libuv doesn't reference
|
||||
any allocated memory chunk.
|
||||
|
||||
On success, it returns 0, if any of the function pointers is NULL it
|
||||
returns UV_EINVAL.
|
||||
On success, it returns 0, if any of the function pointers is `NULL` it
|
||||
returns `UV_EINVAL`.
|
||||
|
||||
.. warning:: There is no protection against changing the allocator multiple
|
||||
times. If the user changes it they are responsible for making
|
||||
@ -362,6 +388,13 @@ API
|
||||
|
||||
Frees the `cpu_infos` array previously allocated with :c:func:`uv_cpu_info`.
|
||||
|
||||
.. c:function:: int uv_cpumask_size(void)
|
||||
|
||||
Returns the maximum size of the mask used for process/thread affinities,
|
||||
or `UV_ENOTSUP` if affinities are not supported on the current platform.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: int uv_interface_addresses(uv_interface_address_t** addresses, int* count)
|
||||
|
||||
Gets address information about the network interfaces on the system. An
|
||||
@ -541,18 +574,21 @@ API
|
||||
|
||||
.. c:function:: uint64_t uv_get_free_memory(void)
|
||||
|
||||
Gets the amount of free memory available in the system, as reported by the kernel (in bytes).
|
||||
Gets the amount of free memory available in the system, as reported by
|
||||
the kernel (in bytes). Returns 0 when unknown.
|
||||
|
||||
.. c:function:: uint64_t uv_get_total_memory(void)
|
||||
|
||||
Gets the total amount of physical memory in the system (in bytes).
|
||||
Returns 0 when unknown.
|
||||
|
||||
.. c:function:: uint64_t uv_get_constrained_memory(void)
|
||||
|
||||
Gets the amount of memory available to the process (in bytes) based on
|
||||
Gets the total amount of memory available to the process (in bytes) based on
|
||||
limits imposed by the OS. If there is no such constraint, or the constraint
|
||||
is unknown, `0` is returned. Note that it is not unusual for this value to
|
||||
be less than or greater than :c:func:`uv_get_total_memory`.
|
||||
is unknown, `0` is returned. If there is a constraining mechanism, but there
|
||||
is no constraint set, `UINT64_MAX` is returned. Note that it is not unusual
|
||||
for this value to be less than or greater than :c:func:`uv_get_total_memory`.
|
||||
|
||||
.. note::
|
||||
This function currently only returns a non-zero value on Linux, based
|
||||
@ -560,9 +596,23 @@ API
|
||||
|
||||
.. versionadded:: 1.29.0
|
||||
|
||||
.. c:function:: uint64_t uv_get_available_memory(void)
|
||||
|
||||
Gets the amount of free memory that is still available to the process (in bytes).
|
||||
This differs from :c:func:`uv_get_free_memory` in that it takes into account any
|
||||
limits imposed by the OS. If there is no such constraint, or the constraint
|
||||
is unknown, the amount returned will be identical to :c:func:`uv_get_free_memory`.
|
||||
|
||||
.. note::
|
||||
This function currently only returns a value that is different from
|
||||
what :c:func:`uv_get_free_memory` reports on Linux, based
|
||||
on cgroups if it is present.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: uint64_t uv_hrtime(void)
|
||||
|
||||
Returns the current high-resolution real time. This is expressed in
|
||||
Returns the current high-resolution timestamp. This is expressed in
|
||||
nanoseconds. It is relative to an arbitrary time in the past. It is not
|
||||
related to the time of day and therefore not subject to clock drift. The
|
||||
primary use is for measuring performance between intervals.
|
||||
@ -571,6 +621,19 @@ API
|
||||
Not every platform can support nanosecond resolution; however, this value will always
|
||||
be in nanoseconds.
|
||||
|
||||
.. c:function:: int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts)
|
||||
|
||||
Obtain the current system time from a high-resolution real-time or monotonic
|
||||
clock source.
|
||||
|
||||
The real-time clock counts from the UNIX epoch (1970-01-01) and is subject
|
||||
to time adjustments; it can jump back in time.
|
||||
|
||||
The monotonic clock counts from an arbitrary point in the past and never
|
||||
jumps back in time.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: void uv_print_all_handles(uv_loop_t* loop, FILE* stream)
|
||||
|
||||
Prints all handles associated with the given `loop` to the given `stream`.
|
||||
|
54
deps/libuv/docs/src/pipe.rst
vendored
54
deps/libuv/docs/src/pipe.rst
vendored
@ -55,17 +55,61 @@ API
|
||||
|
||||
Bind the pipe to a file path (Unix) or a name (Windows).
|
||||
|
||||
Does not support Linux abstract namespace sockets,
|
||||
unlike :c:func:`uv_pipe_bind2`.
|
||||
|
||||
Alias for ``uv_pipe_bind2(handle, name, strlen(name), 0)``.
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes.
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes,
|
||||
typically between 92 and 108 bytes.
|
||||
|
||||
.. c:function:: int uv_pipe_bind2(uv_pipe_t* handle, const char* name, size_t namelen, unsigned int flags)
|
||||
|
||||
Bind the pipe to a file path (Unix) or a name (Windows).
|
||||
|
||||
``flags`` must be zero or ``UV_PIPE_NO_TRUNCATE``. Returns ``UV_EINVAL``
|
||||
for unsupported flags without performing the bind operation.
|
||||
|
||||
Supports Linux abstract namespace sockets. ``namelen`` must include
|
||||
the leading nul byte but not the trailing nul byte.
|
||||
|
||||
.. versionadded:: 1.46.0
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes,
|
||||
typically between 92 and 108 bytes, unless the ``UV_PIPE_NO_TRUNCATE``
|
||||
flag is specified, in which case an ``UV_EINVAL`` error is returned.
|
||||
|
||||
.. c:function:: void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb)
|
||||
|
||||
Connect to the Unix domain socket or the named pipe.
|
||||
Connect to the Unix domain socket or the Windows named pipe.
|
||||
|
||||
Does not support Linux abstract namespace sockets,
|
||||
unlike :c:func:`uv_pipe_connect2`.
|
||||
|
||||
Alias for ``uv_pipe_connect2(req, handle, name, strlen(name), 0, cb)``.
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes.
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes,
|
||||
typically between 92 and 108 bytes.
|
||||
|
||||
.. c:function:: void uv_pipe_connect2(uv_connect_t* req, uv_pipe_t* handle, const char* name, size_t namelen, unsigned int flags, uv_connect_cb cb)
|
||||
|
||||
Connect to the Unix domain socket or the Windows named pipe.
|
||||
|
||||
``flags`` must be zero or ``UV_PIPE_NO_TRUNCATE``. Returns ``UV_EINVAL``
|
||||
for unsupported flags without performing the connect operation.
|
||||
|
||||
Supports Linux abstract namespace sockets. ``namelen`` must include
|
||||
the leading nul byte but not the trailing nul byte.
|
||||
|
||||
.. versionadded:: 1.46.0
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes,
|
||||
typically between 92 and 108 bytes, unless the ``UV_PIPE_NO_TRUNCATE``
|
||||
flag is specified, in which case an ``UV_EINVAL`` error is returned.
|
||||
|
||||
.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size)
|
||||
|
||||
|
4
deps/libuv/docs/src/poll.rst
vendored
4
deps/libuv/docs/src/poll.rst
vendored
@ -101,7 +101,9 @@ API
|
||||
with one of the `UV_E*` error codes (see :ref:`errors`). The user should
|
||||
not close the socket while the handle is active. If the user does that
|
||||
anyway, the callback *may* be called reporting an error status, but this is
|
||||
**not** guaranteed.
|
||||
**not** guaranteed. If `status == UV_EBADF` polling is discontinued for the
|
||||
file handle and no further events will be reported. The user should
|
||||
then call :c:func:`uv_close` on the handle.
|
||||
|
||||
.. note::
|
||||
Calling :c:func:`uv_poll_start` on a handle that is already active is
|
||||
|
BIN
deps/libuv/docs/src/static/loop_iteration.png
vendored
BIN
deps/libuv/docs/src/static/loop_iteration.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 64 KiB |
40
deps/libuv/docs/src/threading.rst
vendored
40
deps/libuv/docs/src/threading.rst
vendored
@ -88,6 +88,46 @@ Threads
|
||||
|
||||
.. versionadded:: 1.26.0
|
||||
|
||||
.. c:function:: int uv_thread_setaffinity(uv_thread_t* tid, char* cpumask, char* oldmask, size_t mask_size)
|
||||
|
||||
Sets the specified thread's affinity to cpumask, which is specified in
|
||||
bytes. Optionally returning the previous affinity setting in oldmask.
|
||||
On Unix, uses :man:`pthread_getaffinity_np(3)` to get the affinity setting
|
||||
and maps the cpu_set_t to bytes in oldmask. Then maps the bytes in cpumask
|
||||
to a cpu_set_t and uses :man:`pthread_setaffinity_np(3)`. On Windows, maps
|
||||
the bytes in cpumask to a bitmask and uses SetThreadAffinityMask() which
|
||||
returns the previous affinity setting.
|
||||
|
||||
The mask_size specifies the number of entries (bytes) in cpumask / oldmask,
|
||||
and must be greater-than-or-equal-to :c:func:`uv_cpumask_size`.
|
||||
|
||||
.. note::
|
||||
Thread affinity setting is not atomic on Windows. Unsupported on macOS.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: int uv_thread_getaffinity(uv_thread_t* tid, char* cpumask, size_t mask_size)
|
||||
|
||||
Gets the specified thread's affinity setting. On Unix, this maps the
|
||||
cpu_set_t returned by :man:`pthread_getaffinity_np(3)` to bytes in cpumask.
|
||||
|
||||
The mask_size specifies the number of entries (bytes) in cpumask,
|
||||
and must be greater-than-or-equal-to :c:func:`uv_cpumask_size`.
|
||||
|
||||
.. note::
|
||||
Thread affinity getting is not atomic on Windows. Unsupported on macOS.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: int uv_thread_getcpu(void)
|
||||
|
||||
Gets the CPU number on which the calling thread is running.
|
||||
|
||||
.. note::
|
||||
Currently only implemented on Windows, Linux and FreeBSD.
|
||||
|
||||
.. versionadded:: 1.45.0
|
||||
|
||||
.. c:function:: uv_thread_t uv_thread_self(void)
|
||||
.. c:function:: int uv_thread_join(uv_thread_t *tid)
|
||||
.. c:function:: int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2)
|
||||
|
3
deps/libuv/docs/src/threadpool.rst
vendored
3
deps/libuv/docs/src/threadpool.rst
vendored
@ -14,6 +14,9 @@ is 1024).
|
||||
|
||||
.. versionchanged:: 1.30.0 the maximum UV_THREADPOOL_SIZE allowed was increased from 128 to 1024.
|
||||
|
||||
.. versionchanged:: 1.45.0 threads now have an 8 MB stack instead of the
|
||||
(sometimes too low) platform default.
|
||||
|
||||
The threadpool is global and shared across all event loops. When a particular
|
||||
function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`)
|
||||
libuv preallocates and initializes the maximum number of threads allowed by
|
||||
|
2
deps/libuv/docs/src/udp.rst
vendored
2
deps/libuv/docs/src/udp.rst
vendored
@ -56,7 +56,7 @@ Data types
|
||||
/*
|
||||
* Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
|
||||
* This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
|
||||
* Linux. This stops the Linux kernel from supressing some ICMP error messages
|
||||
* Linux. This stops the Linux kernel from suppressing some ICMP error messages
|
||||
* and enables full ICMP error reporting for faster failover.
|
||||
* This flag is no-op on platforms other than Linux.
|
||||
*/
|
||||
|
100
deps/libuv/include/uv.h
vendored
100
deps/libuv/include/uv.h
vendored
@ -31,6 +31,7 @@ extern "C" {
|
||||
#error "Define either BUILDING_UV_SHARED or USING_UV_SHARED, not both."
|
||||
#endif
|
||||
|
||||
#ifndef UV_EXTERN
|
||||
#ifdef _WIN32
|
||||
/* Windows - set up dll import/export decorators. */
|
||||
# if defined(BUILDING_UV_SHARED)
|
||||
@ -50,17 +51,19 @@ extern "C" {
|
||||
#else
|
||||
# define UV_EXTERN /* nothing */
|
||||
#endif
|
||||
#endif /* UV_EXTERN */
|
||||
|
||||
#include "uv/errno.h"
|
||||
#include "uv/version.h"
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
# include "uv/stdint-msvc2008.h"
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
/* Internal type, do not use. */
|
||||
struct uv__queue {
|
||||
struct uv__queue* next;
|
||||
struct uv__queue* prev;
|
||||
};
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include "uv/win.h"
|
||||
@ -152,6 +155,8 @@ extern "C" {
|
||||
XX(EFTYPE, "inappropriate file type or format") \
|
||||
XX(EILSEQ, "illegal byte sequence") \
|
||||
XX(ESOCKTNOSUPPORT, "socket type not supported") \
|
||||
XX(ENODATA, "no data available") \
|
||||
XX(EUNATCH, "protocol driver not attached") \
|
||||
|
||||
#define UV_HANDLE_TYPE_MAP(XX) \
|
||||
XX(ASYNC, async) \
|
||||
@ -247,9 +252,12 @@ typedef struct uv_cpu_info_s uv_cpu_info_t;
|
||||
typedef struct uv_interface_address_s uv_interface_address_t;
|
||||
typedef struct uv_dirent_s uv_dirent_t;
|
||||
typedef struct uv_passwd_s uv_passwd_t;
|
||||
typedef struct uv_group_s uv_group_t;
|
||||
typedef struct uv_utsname_s uv_utsname_t;
|
||||
typedef struct uv_statfs_s uv_statfs_t;
|
||||
|
||||
typedef struct uv_metrics_s uv_metrics_t;
|
||||
|
||||
typedef enum {
|
||||
UV_LOOP_BLOCK_SIGNAL = 0,
|
||||
UV_METRICS_IDLE_TIME
|
||||
@ -282,13 +290,13 @@ UV_EXTERN int uv_loop_init(uv_loop_t* loop);
|
||||
UV_EXTERN int uv_loop_close(uv_loop_t* loop);
|
||||
/*
|
||||
* NOTE:
|
||||
* This function is DEPRECATED (to be removed after 0.12), users should
|
||||
* This function is DEPRECATED, users should
|
||||
* allocate the loop manually and use uv_loop_init instead.
|
||||
*/
|
||||
UV_EXTERN uv_loop_t* uv_loop_new(void);
|
||||
/*
|
||||
* NOTE:
|
||||
* This function is DEPRECATED (to be removed after 0.12). Users should use
|
||||
* This function is DEPRECATED. Users should use
|
||||
* uv_loop_close and free the memory manually instead.
|
||||
*/
|
||||
UV_EXTERN void uv_loop_delete(uv_loop_t*);
|
||||
@ -344,11 +352,32 @@ typedef void (*uv_random_cb)(uv_random_t* req,
|
||||
void* buf,
|
||||
size_t buflen);
|
||||
|
||||
typedef enum {
|
||||
UV_CLOCK_MONOTONIC,
|
||||
UV_CLOCK_REALTIME
|
||||
} uv_clock_id;
|
||||
|
||||
/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */
|
||||
typedef struct {
|
||||
long tv_sec;
|
||||
long tv_nsec;
|
||||
} uv_timespec_t;
|
||||
|
||||
typedef struct {
|
||||
int64_t tv_sec;
|
||||
int32_t tv_nsec;
|
||||
} uv_timespec64_t;
|
||||
|
||||
/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */
|
||||
typedef struct {
|
||||
long tv_sec;
|
||||
long tv_usec;
|
||||
} uv_timeval_t;
|
||||
|
||||
typedef struct {
|
||||
int64_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
} uv_timeval64_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t st_dev;
|
||||
@ -437,7 +466,7 @@ struct uv_shutdown_s {
|
||||
uv_handle_type type; \
|
||||
/* private */ \
|
||||
uv_close_cb close_cb; \
|
||||
void* handle_queue[2]; \
|
||||
struct uv__queue handle_queue; \
|
||||
union { \
|
||||
int fd; \
|
||||
void* reserved[4]; \
|
||||
@ -779,6 +808,10 @@ inline int uv_tty_set_mode(uv_tty_t* handle, int mode) {
|
||||
|
||||
UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);
|
||||
|
||||
enum {
|
||||
UV_PIPE_NO_TRUNCATE = 1u << 0
|
||||
};
|
||||
|
||||
/*
|
||||
* uv_pipe_t is a subclass of uv_stream_t.
|
||||
*
|
||||
@ -795,10 +828,20 @@ struct uv_pipe_s {
|
||||
UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);
|
||||
UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file);
|
||||
UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);
|
||||
UV_EXTERN int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
const char* name,
|
||||
size_t namelen,
|
||||
unsigned int flags);
|
||||
UV_EXTERN void uv_pipe_connect(uv_connect_t* req,
|
||||
uv_pipe_t* handle,
|
||||
const char* name,
|
||||
uv_connect_cb cb);
|
||||
UV_EXTERN int uv_pipe_connect2(uv_connect_t* req,
|
||||
uv_pipe_t* handle,
|
||||
const char* name,
|
||||
size_t namelen,
|
||||
unsigned int flags,
|
||||
uv_connect_cb cb);
|
||||
UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,
|
||||
char* buffer,
|
||||
size_t* size);
|
||||
@ -1139,6 +1182,12 @@ struct uv_passwd_s {
|
||||
char* homedir;
|
||||
};
|
||||
|
||||
struct uv_group_s {
|
||||
char* groupname;
|
||||
unsigned long gid;
|
||||
char** members;
|
||||
};
|
||||
|
||||
struct uv_utsname_s {
|
||||
char sysname[256];
|
||||
char release[256];
|
||||
@ -1184,16 +1233,6 @@ UV_EXTERN int uv_uptime(double* uptime);
|
||||
UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
|
||||
UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd);
|
||||
|
||||
typedef struct {
|
||||
long tv_sec;
|
||||
long tv_usec;
|
||||
} uv_timeval_t;
|
||||
|
||||
typedef struct {
|
||||
int64_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
} uv_timeval64_t;
|
||||
|
||||
typedef struct {
|
||||
uv_timeval_t ru_utime; /* user CPU time used */
|
||||
uv_timeval_t ru_stime; /* system CPU time used */
|
||||
@ -1219,6 +1258,9 @@ UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
|
||||
UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);
|
||||
UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd);
|
||||
UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
|
||||
UV_EXTERN int uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid);
|
||||
UV_EXTERN int uv_os_get_group(uv_group_t* grp, uv_uid_t gid);
|
||||
UV_EXTERN void uv_os_free_group(uv_group_t* grp);
|
||||
UV_EXTERN uv_pid_t uv_os_getpid(void);
|
||||
UV_EXTERN uv_pid_t uv_os_getppid(void);
|
||||
|
||||
@ -1245,6 +1287,7 @@ UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
|
||||
UV_EXTERN unsigned int uv_available_parallelism(void);
|
||||
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
|
||||
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
|
||||
UV_EXTERN int uv_cpumask_size(void);
|
||||
|
||||
UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count);
|
||||
@ -1277,6 +1320,15 @@ UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
|
||||
|
||||
UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
|
||||
|
||||
struct uv_metrics_s {
|
||||
uint64_t loop_count;
|
||||
uint64_t events;
|
||||
uint64_t events_waiting;
|
||||
/* private */
|
||||
uint64_t* reserved[13];
|
||||
};
|
||||
|
||||
UV_EXTERN int uv_metrics_info(uv_loop_t* loop, uv_metrics_t* metrics);
|
||||
UV_EXTERN uint64_t uv_metrics_idle_time(uv_loop_t* loop);
|
||||
|
||||
typedef enum {
|
||||
@ -1710,7 +1762,9 @@ UV_EXTERN int uv_chdir(const char* dir);
|
||||
UV_EXTERN uint64_t uv_get_free_memory(void);
|
||||
UV_EXTERN uint64_t uv_get_total_memory(void);
|
||||
UV_EXTERN uint64_t uv_get_constrained_memory(void);
|
||||
UV_EXTERN uint64_t uv_get_available_memory(void);
|
||||
|
||||
UV_EXTERN int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts);
|
||||
UV_EXTERN uint64_t uv_hrtime(void);
|
||||
UV_EXTERN void uv_sleep(unsigned int msec);
|
||||
|
||||
@ -1787,6 +1841,14 @@ UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,
|
||||
const uv_thread_options_t* params,
|
||||
uv_thread_cb entry,
|
||||
void* arg);
|
||||
UV_EXTERN int uv_thread_setaffinity(uv_thread_t* tid,
|
||||
char* cpumask,
|
||||
char* oldmask,
|
||||
size_t mask_size);
|
||||
UV_EXTERN int uv_thread_getaffinity(uv_thread_t* tid,
|
||||
char* cpumask,
|
||||
size_t mask_size);
|
||||
UV_EXTERN int uv_thread_getcpu(void);
|
||||
UV_EXTERN uv_thread_t uv_thread_self(void);
|
||||
UV_EXTERN int uv_thread_join(uv_thread_t *tid);
|
||||
UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2);
|
||||
@ -1808,7 +1870,7 @@ struct uv_loop_s {
|
||||
void* data;
|
||||
/* Loop reference counting. */
|
||||
unsigned int active_handles;
|
||||
void* handle_queue[2];
|
||||
struct uv__queue handle_queue;
|
||||
union {
|
||||
void* unused;
|
||||
unsigned int count;
|
||||
|
6
deps/libuv/include/uv/darwin.h
vendored
6
deps/libuv/include/uv/darwin.h
vendored
@ -40,7 +40,7 @@
|
||||
void* cf_state; \
|
||||
uv_mutex_t cf_mutex; \
|
||||
uv_sem_t cf_sem; \
|
||||
void* cf_signals[2]; \
|
||||
struct uv__queue cf_signals; \
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
uv__io_t event_watcher; \
|
||||
@ -48,8 +48,8 @@
|
||||
int realpath_len; \
|
||||
int cf_flags; \
|
||||
uv_async_t* cf_cb; \
|
||||
void* cf_events[2]; \
|
||||
void* cf_member[2]; \
|
||||
struct uv__queue cf_events; \
|
||||
struct uv__queue cf_member; \
|
||||
int cf_error; \
|
||||
uv_mutex_t cf_mutex; \
|
||||
|
||||
|
19
deps/libuv/include/uv/errno.h
vendored
19
deps/libuv/include/uv/errno.h
vendored
@ -413,7 +413,6 @@
|
||||
#elif defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
# define UV__EHOSTDOWN (-64)
|
||||
@ -457,4 +456,22 @@
|
||||
# define UV__ESOCKTNOSUPPORT (-4025)
|
||||
#endif
|
||||
|
||||
/* FreeBSD defines ENODATA in /usr/include/c++/v1/errno.h which is only visible
|
||||
* if C++ is being used. Define it directly to avoid problems when integrating
|
||||
* libuv in a C++ project.
|
||||
*/
|
||||
#if defined(ENODATA) && !defined(_WIN32)
|
||||
# define UV__ENODATA UV__ERR(ENODATA)
|
||||
#elif defined(__FreeBSD__)
|
||||
# define UV__ENODATA (-9919)
|
||||
#else
|
||||
# define UV__ENODATA (-4024)
|
||||
#endif
|
||||
|
||||
#if defined(EUNATCH) && !defined(_WIN32)
|
||||
# define UV__EUNATCH UV__ERR(EUNATCH)
|
||||
#else
|
||||
# define UV__EUNATCH (-4023)
|
||||
#endif
|
||||
|
||||
#endif /* UV_ERRNO_H_ */
|
||||
|
2
deps/libuv/include/uv/linux.h
vendored
2
deps/libuv/include/uv/linux.h
vendored
@ -28,7 +28,7 @@
|
||||
int inotify_fd; \
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
void* watchers[2]; \
|
||||
struct uv__queue watchers; \
|
||||
int wd; \
|
||||
|
||||
#endif /* UV_LINUX_H */
|
||||
|
247
deps/libuv/include/uv/stdint-msvc2008.h
vendored
247
deps/libuv/include/uv/stdint-msvc2008.h
vendored
@ -1,247 +0,0 @@
|
||||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
2
deps/libuv/include/uv/threadpool.h
vendored
2
deps/libuv/include/uv/threadpool.h
vendored
@ -31,7 +31,7 @@ struct uv__work {
|
||||
void (*work)(struct uv__work *w);
|
||||
void (*done)(struct uv__work *w, int status);
|
||||
struct uv_loop_s* loop;
|
||||
void* wq[2];
|
||||
struct uv__queue wq;
|
||||
};
|
||||
|
||||
#endif /* UV_THREADPOOL_H_ */
|
||||
|
49
deps/libuv/include/uv/unix.h
vendored
49
deps/libuv/include/uv/unix.h
vendored
@ -59,7 +59,6 @@
|
||||
# include "uv/darwin.h"
|
||||
#elif defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
# include "uv/bsd.h"
|
||||
@ -93,8 +92,8 @@ typedef struct uv__io_s uv__io_t;
|
||||
|
||||
struct uv__io_s {
|
||||
uv__io_cb cb;
|
||||
void* pending_queue[2];
|
||||
void* watcher_queue[2];
|
||||
struct uv__queue pending_queue;
|
||||
struct uv__queue watcher_queue;
|
||||
unsigned int pevents; /* Pending event mask i.e. mask at next tick. */
|
||||
unsigned int events; /* Current event mask. */
|
||||
int fd;
|
||||
@ -221,21 +220,21 @@ typedef struct {
|
||||
#define UV_LOOP_PRIVATE_FIELDS \
|
||||
unsigned long flags; \
|
||||
int backend_fd; \
|
||||
void* pending_queue[2]; \
|
||||
void* watcher_queue[2]; \
|
||||
struct uv__queue pending_queue; \
|
||||
struct uv__queue watcher_queue; \
|
||||
uv__io_t** watchers; \
|
||||
unsigned int nwatchers; \
|
||||
unsigned int nfds; \
|
||||
void* wq[2]; \
|
||||
struct uv__queue wq; \
|
||||
uv_mutex_t wq_mutex; \
|
||||
uv_async_t wq_async; \
|
||||
uv_rwlock_t cloexec_lock; \
|
||||
uv_handle_t* closing_handles; \
|
||||
void* process_handles[2]; \
|
||||
void* prepare_handles[2]; \
|
||||
void* check_handles[2]; \
|
||||
void* idle_handles[2]; \
|
||||
void* async_handles[2]; \
|
||||
struct uv__queue process_handles; \
|
||||
struct uv__queue prepare_handles; \
|
||||
struct uv__queue check_handles; \
|
||||
struct uv__queue idle_handles; \
|
||||
struct uv__queue async_handles; \
|
||||
void (*async_unused)(void); /* TODO(bnoordhuis) Remove in libuv v2. */ \
|
||||
uv__io_t async_io_watcher; \
|
||||
int async_wfd; \
|
||||
@ -258,7 +257,7 @@ typedef struct {
|
||||
#define UV_PRIVATE_REQ_TYPES /* empty */
|
||||
|
||||
#define UV_WRITE_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
unsigned int write_index; \
|
||||
uv_buf_t* bufs; \
|
||||
unsigned int nbufs; \
|
||||
@ -266,12 +265,12 @@ typedef struct {
|
||||
uv_buf_t bufsml[4]; \
|
||||
|
||||
#define UV_CONNECT_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
|
||||
#define UV_SHUTDOWN_PRIVATE_FIELDS /* empty */
|
||||
|
||||
#define UV_UDP_SEND_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
struct sockaddr_storage addr; \
|
||||
unsigned int nbufs; \
|
||||
uv_buf_t* bufs; \
|
||||
@ -287,8 +286,8 @@ typedef struct {
|
||||
uv_connect_t *connect_req; \
|
||||
uv_shutdown_t *shutdown_req; \
|
||||
uv__io_t io_watcher; \
|
||||
void* write_queue[2]; \
|
||||
void* write_completed_queue[2]; \
|
||||
struct uv__queue write_queue; \
|
||||
struct uv__queue write_completed_queue; \
|
||||
uv_connection_cb connection_cb; \
|
||||
int delayed_error; \
|
||||
int accepted_fd; \
|
||||
@ -301,30 +300,30 @@ typedef struct {
|
||||
uv_alloc_cb alloc_cb; \
|
||||
uv_udp_recv_cb recv_cb; \
|
||||
uv__io_t io_watcher; \
|
||||
void* write_queue[2]; \
|
||||
void* write_completed_queue[2]; \
|
||||
struct uv__queue write_queue; \
|
||||
struct uv__queue write_completed_queue; \
|
||||
|
||||
#define UV_PIPE_PRIVATE_FIELDS \
|
||||
const char* pipe_fname; /* strdup'ed */
|
||||
const char* pipe_fname; /* NULL or strdup'ed */
|
||||
|
||||
#define UV_POLL_PRIVATE_FIELDS \
|
||||
uv__io_t io_watcher;
|
||||
|
||||
#define UV_PREPARE_PRIVATE_FIELDS \
|
||||
uv_prepare_cb prepare_cb; \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
|
||||
#define UV_CHECK_PRIVATE_FIELDS \
|
||||
uv_check_cb check_cb; \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
|
||||
#define UV_IDLE_PRIVATE_FIELDS \
|
||||
uv_idle_cb idle_cb; \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
|
||||
#define UV_ASYNC_PRIVATE_FIELDS \
|
||||
uv_async_cb async_cb; \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
int pending; \
|
||||
|
||||
#define UV_TIMER_PRIVATE_FIELDS \
|
||||
@ -353,7 +352,7 @@ typedef struct {
|
||||
int retcode;
|
||||
|
||||
#define UV_PROCESS_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
struct uv__queue queue; \
|
||||
int status; \
|
||||
|
||||
#define UV_FS_PRIVATE_FIELDS \
|
||||
@ -418,6 +417,8 @@ typedef struct {
|
||||
# define UV_FS_O_DIRECT 0x04000
|
||||
#elif defined(__linux__) && defined(__x86_64__)
|
||||
# define UV_FS_O_DIRECT 0x04000
|
||||
#elif defined(__linux__) && defined(__loongarch__)
|
||||
# define UV_FS_O_DIRECT 0x04000
|
||||
#elif defined(O_DIRECT)
|
||||
# define UV_FS_O_DIRECT O_DIRECT
|
||||
#else
|
||||
|
4
deps/libuv/include/uv/version.h
vendored
4
deps/libuv/include/uv/version.h
vendored
@ -31,8 +31,8 @@
|
||||
*/
|
||||
|
||||
#define UV_VERSION_MAJOR 1
|
||||
#define UV_VERSION_MINOR 44
|
||||
#define UV_VERSION_PATCH 2
|
||||
#define UV_VERSION_MINOR 46
|
||||
#define UV_VERSION_PATCH 0
|
||||
#define UV_VERSION_IS_RELEASE 1
|
||||
#define UV_VERSION_SUFFIX ""
|
||||
|
||||
|
35
deps/libuv/include/uv/win.h
vendored
35
deps/libuv/include/uv/win.h
vendored
@ -59,12 +59,7 @@ typedef struct pollfd {
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
# include "uv/stdint-msvc2008.h"
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#include "uv/tree.h"
|
||||
#include "uv/threadpool.h"
|
||||
@ -75,6 +70,11 @@ typedef struct pollfd {
|
||||
# define S_IFLNK 0xA000
|
||||
#endif
|
||||
|
||||
// Define missing in Windows Kit Include\{VERSION}\ucrt\sys\stat.h
|
||||
#if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES && !defined(S_IFIFO)
|
||||
# define S_IFIFO _S_IFIFO
|
||||
#endif
|
||||
|
||||
/* Additional signals supported by uv_signal and or uv_kill. The CRT defines
|
||||
* the following signals already:
|
||||
*
|
||||
@ -91,6 +91,7 @@ typedef struct pollfd {
|
||||
* variants (Linux and Darwin)
|
||||
*/
|
||||
#define SIGHUP 1
|
||||
#define SIGQUIT 3
|
||||
#define SIGKILL 9
|
||||
#define SIGWINCH 28
|
||||
|
||||
@ -274,11 +275,12 @@ typedef struct {
|
||||
} uv_rwlock_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int n;
|
||||
unsigned int count;
|
||||
unsigned threshold;
|
||||
unsigned in;
|
||||
uv_mutex_t mutex;
|
||||
uv_sem_t turnstile1;
|
||||
uv_sem_t turnstile2;
|
||||
/* TODO: in v2 make this a uv_cond_t, without unused_ */
|
||||
CONDITION_VARIABLE cond;
|
||||
unsigned out;
|
||||
} uv_barrier_t;
|
||||
|
||||
typedef struct {
|
||||
@ -348,14 +350,14 @@ typedef struct {
|
||||
uv_idle_t* next_idle_handle; \
|
||||
/* This handle holds the peer sockets for the fast variant of uv_poll_t */ \
|
||||
SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT]; \
|
||||
/* Counter to keep track of active tcp streams */ \
|
||||
/* No longer used. */ \
|
||||
unsigned int active_tcp_streams; \
|
||||
/* Counter to keep track of active udp streams */ \
|
||||
/* No longer used. */ \
|
||||
unsigned int active_udp_streams; \
|
||||
/* Counter to started timer */ \
|
||||
uint64_t timer_counter; \
|
||||
/* Threadpool */ \
|
||||
void* wq[2]; \
|
||||
struct uv__queue wq; \
|
||||
uv_mutex_t wq_mutex; \
|
||||
uv_async_t wq_async;
|
||||
|
||||
@ -382,6 +384,7 @@ typedef struct {
|
||||
ULONG_PTR result; /* overlapped.Internal is reused to hold the result */\
|
||||
HANDLE pipeHandle; \
|
||||
DWORD duplex_flags; \
|
||||
WCHAR* name; \
|
||||
} connect; \
|
||||
} u; \
|
||||
struct uv_req_s* next_req;
|
||||
@ -483,7 +486,7 @@ typedef struct {
|
||||
uint32_t payload_remaining; \
|
||||
uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
|
||||
} ipc_data_frame; \
|
||||
void* ipc_xfer_queue[2]; \
|
||||
struct uv__queue ipc_xfer_queue; \
|
||||
int ipc_xfer_queue_length; \
|
||||
uv_write_t* non_overlapped_writes_tail; \
|
||||
CRITICAL_SECTION readfile_thread_lock; \
|
||||
@ -497,7 +500,7 @@ typedef struct {
|
||||
struct { uv_pipe_connection_fields } conn; \
|
||||
} pipe;
|
||||
|
||||
/* TODO: put the parser states in an union - TTY handles are always half-duplex
|
||||
/* TODO: put the parser states in a union - TTY handles are always half-duplex
|
||||
* so read-state can safely overlap write-state. */
|
||||
#define UV_TTY_PRIVATE_FIELDS \
|
||||
HANDLE handle; \
|
||||
@ -605,7 +608,7 @@ typedef struct {
|
||||
struct uv_process_exit_s { \
|
||||
UV_REQ_FIELDS \
|
||||
} exit_req; \
|
||||
BYTE* child_stdio_buffer; \
|
||||
void* unused; /* TODO: retained for ABI compat; remove this in v2.x. */ \
|
||||
int exit_signal; \
|
||||
HANDLE wait_handle; \
|
||||
HANDLE process_handle; \
|
||||
|
2
deps/libuv/libuv-static.pc.in
vendored
2
deps/libuv/libuv-static.pc.in
vendored
@ -8,5 +8,5 @@ Version: @PACKAGE_VERSION@
|
||||
Description: multi-platform support library with a focus on asynchronous I/O.
|
||||
URL: http://libuv.org/
|
||||
|
||||
Libs: -L${libdir} -luv_a @LIBS@
|
||||
Libs: -L${libdir} -l:libuv.a @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
1
deps/libuv/libuv.pc.in
vendored
1
deps/libuv/libuv.pc.in
vendored
@ -2,6 +2,7 @@ prefix=@prefix@
|
||||
exec_prefix=${prefix}
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
LIBUV_STATIC=-L${libdir} -l:libuv.a @LIBS@
|
||||
|
||||
Name: libuv
|
||||
Version: @PACKAGE_VERSION@
|
||||
|
9
deps/libuv/src/inet.c
vendored
9
deps/libuv/src/inet.c
vendored
@ -17,12 +17,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
# include "uv/stdint-msvc2008.h"
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#include "uv.h"
|
||||
#include "uv-common.h"
|
||||
@ -135,7 +130,7 @@ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) {
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += sprintf(tp, "%x", words[i]);
|
||||
tp += snprintf(tp, sizeof tmp - (tp - tmp), "%x", words[i]);
|
||||
}
|
||||
/* Was it a trailing run of 0x00's? */
|
||||
if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words))
|
||||
|
132
deps/libuv/src/queue.h
vendored
132
deps/libuv/src/queue.h
vendored
@ -18,91 +18,73 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef void *QUEUE[2];
|
||||
#define uv__queue_data(pointer, type, field) \
|
||||
((type*) ((char*) (pointer) - offsetof(type, field)))
|
||||
|
||||
/* Private macros. */
|
||||
#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0]))
|
||||
#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1]))
|
||||
#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q)))
|
||||
#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q)))
|
||||
#define uv__queue_foreach(q, h) \
|
||||
for ((q) = (h)->next; (q) != (h); (q) = (q)->next)
|
||||
|
||||
/* Public macros. */
|
||||
#define QUEUE_DATA(ptr, type, field) \
|
||||
((type *) ((char *) (ptr) - offsetof(type, field)))
|
||||
static inline void uv__queue_init(struct uv__queue* q) {
|
||||
q->next = q;
|
||||
q->prev = q;
|
||||
}
|
||||
|
||||
/* Important note: mutating the list while QUEUE_FOREACH is
|
||||
* iterating over its elements results in undefined behavior.
|
||||
*/
|
||||
#define QUEUE_FOREACH(q, h) \
|
||||
for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
|
||||
static inline int uv__queue_empty(const struct uv__queue* q) {
|
||||
return q == q->next;
|
||||
}
|
||||
|
||||
#define QUEUE_EMPTY(q) \
|
||||
((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q))
|
||||
static inline struct uv__queue* uv__queue_head(const struct uv__queue* q) {
|
||||
return q->next;
|
||||
}
|
||||
|
||||
#define QUEUE_HEAD(q) \
|
||||
(QUEUE_NEXT(q))
|
||||
static inline struct uv__queue* uv__queue_next(const struct uv__queue* q) {
|
||||
return q->next;
|
||||
}
|
||||
|
||||
#define QUEUE_INIT(q) \
|
||||
do { \
|
||||
QUEUE_NEXT(q) = (q); \
|
||||
QUEUE_PREV(q) = (q); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_add(struct uv__queue* h, struct uv__queue* n) {
|
||||
h->prev->next = n->next;
|
||||
n->next->prev = h->prev;
|
||||
h->prev = n->prev;
|
||||
h->prev->next = h;
|
||||
}
|
||||
|
||||
#define QUEUE_ADD(h, n) \
|
||||
do { \
|
||||
QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \
|
||||
QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \
|
||||
QUEUE_PREV(h) = QUEUE_PREV(n); \
|
||||
QUEUE_PREV_NEXT(h) = (h); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_split(struct uv__queue* h,
|
||||
struct uv__queue* q,
|
||||
struct uv__queue* n) {
|
||||
n->prev = h->prev;
|
||||
n->prev->next = n;
|
||||
n->next = q;
|
||||
h->prev = q->prev;
|
||||
h->prev->next = h;
|
||||
q->prev = n;
|
||||
}
|
||||
|
||||
#define QUEUE_SPLIT(h, q, n) \
|
||||
do { \
|
||||
QUEUE_PREV(n) = QUEUE_PREV(h); \
|
||||
QUEUE_PREV_NEXT(n) = (n); \
|
||||
QUEUE_NEXT(n) = (q); \
|
||||
QUEUE_PREV(h) = QUEUE_PREV(q); \
|
||||
QUEUE_PREV_NEXT(h) = (h); \
|
||||
QUEUE_PREV(q) = (n); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_move(struct uv__queue* h, struct uv__queue* n) {
|
||||
if (uv__queue_empty(h))
|
||||
uv__queue_init(n);
|
||||
else
|
||||
uv__queue_split(h, h->next, n);
|
||||
}
|
||||
|
||||
#define QUEUE_MOVE(h, n) \
|
||||
do { \
|
||||
if (QUEUE_EMPTY(h)) \
|
||||
QUEUE_INIT(n); \
|
||||
else { \
|
||||
QUEUE* q = QUEUE_HEAD(h); \
|
||||
QUEUE_SPLIT(h, q, n); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_insert_head(struct uv__queue* h,
|
||||
struct uv__queue* q) {
|
||||
q->next = h->next;
|
||||
q->prev = h;
|
||||
q->next->prev = q;
|
||||
h->next = q;
|
||||
}
|
||||
|
||||
#define QUEUE_INSERT_HEAD(h, q) \
|
||||
do { \
|
||||
QUEUE_NEXT(q) = QUEUE_NEXT(h); \
|
||||
QUEUE_PREV(q) = (h); \
|
||||
QUEUE_NEXT_PREV(q) = (q); \
|
||||
QUEUE_NEXT(h) = (q); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_insert_tail(struct uv__queue* h,
|
||||
struct uv__queue* q) {
|
||||
q->next = h;
|
||||
q->prev = h->prev;
|
||||
q->prev->next = q;
|
||||
h->prev = q;
|
||||
}
|
||||
|
||||
#define QUEUE_INSERT_TAIL(h, q) \
|
||||
do { \
|
||||
QUEUE_NEXT(q) = (h); \
|
||||
QUEUE_PREV(q) = QUEUE_PREV(h); \
|
||||
QUEUE_PREV_NEXT(q) = (q); \
|
||||
QUEUE_PREV(h) = (q); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define QUEUE_REMOVE(q) \
|
||||
do { \
|
||||
QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \
|
||||
QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \
|
||||
} \
|
||||
while (0)
|
||||
static inline void uv__queue_remove(struct uv__queue* q) {
|
||||
q->prev->next = q->next;
|
||||
q->next->prev = q->prev;
|
||||
}
|
||||
|
||||
#endif /* QUEUE_H_ */
|
||||
|
175
deps/libuv/src/thread-common.c
vendored
Normal file
175
deps/libuv/src/thread-common.c
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "uv-common.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
|
||||
#endif
|
||||
|
||||
/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */
|
||||
#if defined(_AIX) || \
|
||||
defined(__OpenBSD__) || \
|
||||
!defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
||||
int rc;
|
||||
#ifdef _WIN32
|
||||
uv_barrier_t* b;
|
||||
b = barrier;
|
||||
|
||||
if (barrier == NULL || count == 0)
|
||||
return UV_EINVAL;
|
||||
#else
|
||||
struct _uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || count == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
b = uv__malloc(sizeof(*b));
|
||||
if (b == NULL)
|
||||
return UV_ENOMEM;
|
||||
#endif
|
||||
|
||||
b->in = 0;
|
||||
b->out = 0;
|
||||
b->threshold = count;
|
||||
|
||||
rc = uv_mutex_init(&b->mutex);
|
||||
if (rc != 0)
|
||||
goto error2;
|
||||
|
||||
/* TODO(vjnash): remove these uv_cond_t casts in v2. */
|
||||
rc = uv_cond_init((uv_cond_t*) &b->cond);
|
||||
if (rc != 0)
|
||||
goto error;
|
||||
|
||||
#ifndef _WIN32
|
||||
barrier->b = b;
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
error:
|
||||
uv_mutex_destroy(&b->mutex);
|
||||
error2:
|
||||
#ifndef _WIN32
|
||||
uv__free(b);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int uv_barrier_wait(uv_barrier_t* barrier) {
|
||||
int last;
|
||||
#ifdef _WIN32
|
||||
uv_barrier_t* b;
|
||||
b = barrier;
|
||||
#else
|
||||
struct _uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || barrier->b == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
b = barrier->b;
|
||||
#endif
|
||||
|
||||
uv_mutex_lock(&b->mutex);
|
||||
|
||||
while (b->out != 0)
|
||||
uv_cond_wait((uv_cond_t*) &b->cond, &b->mutex);
|
||||
|
||||
if (++b->in == b->threshold) {
|
||||
b->in = 0;
|
||||
b->out = b->threshold;
|
||||
uv_cond_broadcast((uv_cond_t*) &b->cond);
|
||||
} else {
|
||||
do
|
||||
uv_cond_wait((uv_cond_t*) &b->cond, &b->mutex);
|
||||
while (b->in != 0);
|
||||
}
|
||||
|
||||
last = (--b->out == 0);
|
||||
if (last)
|
||||
uv_cond_broadcast((uv_cond_t*) &b->cond);
|
||||
|
||||
uv_mutex_unlock(&b->mutex);
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
void uv_barrier_destroy(uv_barrier_t* barrier) {
|
||||
#ifdef _WIN32
|
||||
uv_barrier_t* b;
|
||||
b = barrier;
|
||||
#else
|
||||
struct _uv_barrier* b;
|
||||
b = barrier->b;
|
||||
#endif
|
||||
|
||||
uv_mutex_lock(&b->mutex);
|
||||
|
||||
assert(b->in == 0);
|
||||
while (b->out != 0)
|
||||
uv_cond_wait((uv_cond_t*) &b->cond, &b->mutex);
|
||||
|
||||
if (b->in != 0)
|
||||
abort();
|
||||
|
||||
uv_mutex_unlock(&b->mutex);
|
||||
uv_mutex_destroy(&b->mutex);
|
||||
uv_cond_destroy((uv_cond_t*) &b->cond);
|
||||
|
||||
#ifndef _WIN32
|
||||
uv__free(barrier->b);
|
||||
barrier->b = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
||||
return UV__ERR(pthread_barrier_init(barrier, NULL, count));
|
||||
}
|
||||
|
||||
|
||||
int uv_barrier_wait(uv_barrier_t* barrier) {
|
||||
int rc;
|
||||
|
||||
rc = pthread_barrier_wait(barrier);
|
||||
if (rc != 0)
|
||||
if (rc != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
abort();
|
||||
|
||||
return rc == PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
}
|
||||
|
||||
|
||||
void uv_barrier_destroy(uv_barrier_t* barrier) {
|
||||
if (pthread_barrier_destroy(barrier))
|
||||
abort();
|
||||
}
|
||||
|
||||
#endif
|
99
deps/libuv/src/threadpool.c
vendored
99
deps/libuv/src/threadpool.c
vendored
@ -37,10 +37,10 @@ static unsigned int slow_io_work_running;
|
||||
static unsigned int nthreads;
|
||||
static uv_thread_t* threads;
|
||||
static uv_thread_t default_threads[4];
|
||||
static QUEUE exit_message;
|
||||
static QUEUE wq;
|
||||
static QUEUE run_slow_work_message;
|
||||
static QUEUE slow_io_pending_wq;
|
||||
static struct uv__queue exit_message;
|
||||
static struct uv__queue wq;
|
||||
static struct uv__queue run_slow_work_message;
|
||||
static struct uv__queue slow_io_pending_wq;
|
||||
|
||||
static unsigned int slow_work_thread_threshold(void) {
|
||||
return (nthreads + 1) / 2;
|
||||
@ -56,7 +56,7 @@ static void uv__cancelled(struct uv__work* w) {
|
||||
*/
|
||||
static void worker(void* arg) {
|
||||
struct uv__work* w;
|
||||
QUEUE* q;
|
||||
struct uv__queue* q;
|
||||
int is_slow_work;
|
||||
|
||||
uv_sem_post((uv_sem_t*) arg);
|
||||
@ -68,49 +68,49 @@ static void worker(void* arg) {
|
||||
|
||||
/* Keep waiting while either no work is present or only slow I/O
|
||||
and we're at the threshold for that. */
|
||||
while (QUEUE_EMPTY(&wq) ||
|
||||
(QUEUE_HEAD(&wq) == &run_slow_work_message &&
|
||||
QUEUE_NEXT(&run_slow_work_message) == &wq &&
|
||||
while (uv__queue_empty(&wq) ||
|
||||
(uv__queue_head(&wq) == &run_slow_work_message &&
|
||||
uv__queue_next(&run_slow_work_message) == &wq &&
|
||||
slow_io_work_running >= slow_work_thread_threshold())) {
|
||||
idle_threads += 1;
|
||||
uv_cond_wait(&cond, &mutex);
|
||||
idle_threads -= 1;
|
||||
}
|
||||
|
||||
q = QUEUE_HEAD(&wq);
|
||||
q = uv__queue_head(&wq);
|
||||
if (q == &exit_message) {
|
||||
uv_cond_signal(&cond);
|
||||
uv_mutex_unlock(&mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q); /* Signal uv_cancel() that the work req is executing. */
|
||||
uv__queue_remove(q);
|
||||
uv__queue_init(q); /* Signal uv_cancel() that the work req is executing. */
|
||||
|
||||
is_slow_work = 0;
|
||||
if (q == &run_slow_work_message) {
|
||||
/* If we're at the slow I/O threshold, re-schedule until after all
|
||||
other work in the queue is done. */
|
||||
if (slow_io_work_running >= slow_work_thread_threshold()) {
|
||||
QUEUE_INSERT_TAIL(&wq, q);
|
||||
uv__queue_insert_tail(&wq, q);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we encountered a request to run slow I/O work but there is none
|
||||
to run, that means it's cancelled => Start over. */
|
||||
if (QUEUE_EMPTY(&slow_io_pending_wq))
|
||||
if (uv__queue_empty(&slow_io_pending_wq))
|
||||
continue;
|
||||
|
||||
is_slow_work = 1;
|
||||
slow_io_work_running++;
|
||||
|
||||
q = QUEUE_HEAD(&slow_io_pending_wq);
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q);
|
||||
q = uv__queue_head(&slow_io_pending_wq);
|
||||
uv__queue_remove(q);
|
||||
uv__queue_init(q);
|
||||
|
||||
/* If there is more slow I/O work, schedule it to be run as well. */
|
||||
if (!QUEUE_EMPTY(&slow_io_pending_wq)) {
|
||||
QUEUE_INSERT_TAIL(&wq, &run_slow_work_message);
|
||||
if (!uv__queue_empty(&slow_io_pending_wq)) {
|
||||
uv__queue_insert_tail(&wq, &run_slow_work_message);
|
||||
if (idle_threads > 0)
|
||||
uv_cond_signal(&cond);
|
||||
}
|
||||
@ -118,13 +118,13 @@ static void worker(void* arg) {
|
||||
|
||||
uv_mutex_unlock(&mutex);
|
||||
|
||||
w = QUEUE_DATA(q, struct uv__work, wq);
|
||||
w = uv__queue_data(q, struct uv__work, wq);
|
||||
w->work(w);
|
||||
|
||||
uv_mutex_lock(&w->loop->wq_mutex);
|
||||
w->work = NULL; /* Signal uv_cancel() that the work req is done
|
||||
executing. */
|
||||
QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq);
|
||||
uv__queue_insert_tail(&w->loop->wq, &w->wq);
|
||||
uv_async_send(&w->loop->wq_async);
|
||||
uv_mutex_unlock(&w->loop->wq_mutex);
|
||||
|
||||
@ -139,12 +139,12 @@ static void worker(void* arg) {
|
||||
}
|
||||
|
||||
|
||||
static void post(QUEUE* q, enum uv__work_kind kind) {
|
||||
static void post(struct uv__queue* q, enum uv__work_kind kind) {
|
||||
uv_mutex_lock(&mutex);
|
||||
if (kind == UV__WORK_SLOW_IO) {
|
||||
/* Insert into a separate queue. */
|
||||
QUEUE_INSERT_TAIL(&slow_io_pending_wq, q);
|
||||
if (!QUEUE_EMPTY(&run_slow_work_message)) {
|
||||
uv__queue_insert_tail(&slow_io_pending_wq, q);
|
||||
if (!uv__queue_empty(&run_slow_work_message)) {
|
||||
/* Running slow I/O tasks is already scheduled => Nothing to do here.
|
||||
The worker that runs said other task will schedule this one as well. */
|
||||
uv_mutex_unlock(&mutex);
|
||||
@ -153,7 +153,7 @@ static void post(QUEUE* q, enum uv__work_kind kind) {
|
||||
q = &run_slow_work_message;
|
||||
}
|
||||
|
||||
QUEUE_INSERT_TAIL(&wq, q);
|
||||
uv__queue_insert_tail(&wq, q);
|
||||
if (idle_threads > 0)
|
||||
uv_cond_signal(&cond);
|
||||
uv_mutex_unlock(&mutex);
|
||||
@ -191,6 +191,7 @@ void uv__threadpool_cleanup(void) {
|
||||
|
||||
|
||||
static void init_threads(void) {
|
||||
uv_thread_options_t config;
|
||||
unsigned int i;
|
||||
const char* val;
|
||||
uv_sem_t sem;
|
||||
@ -219,15 +220,18 @@ static void init_threads(void) {
|
||||
if (uv_mutex_init(&mutex))
|
||||
abort();
|
||||
|
||||
QUEUE_INIT(&wq);
|
||||
QUEUE_INIT(&slow_io_pending_wq);
|
||||
QUEUE_INIT(&run_slow_work_message);
|
||||
uv__queue_init(&wq);
|
||||
uv__queue_init(&slow_io_pending_wq);
|
||||
uv__queue_init(&run_slow_work_message);
|
||||
|
||||
if (uv_sem_init(&sem, 0))
|
||||
abort();
|
||||
|
||||
config.flags = UV_THREAD_HAS_STACK_SIZE;
|
||||
config.stack_size = 8u << 20; /* 8 MB */
|
||||
|
||||
for (i = 0; i < nthreads; i++)
|
||||
if (uv_thread_create(threads + i, worker, &sem))
|
||||
if (uv_thread_create_ex(threads + i, &config, worker, &sem))
|
||||
abort();
|
||||
|
||||
for (i = 0; i < nthreads; i++)
|
||||
@ -271,15 +275,19 @@ void uv__work_submit(uv_loop_t* loop,
|
||||
}
|
||||
|
||||
|
||||
/* TODO(bnoordhuis) teach libuv how to cancel file operations
|
||||
* that go through io_uring instead of the thread pool.
|
||||
*/
|
||||
static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
|
||||
int cancelled;
|
||||
|
||||
uv_once(&once, init_once); /* Ensure |mutex| is initialized. */
|
||||
uv_mutex_lock(&mutex);
|
||||
uv_mutex_lock(&w->loop->wq_mutex);
|
||||
|
||||
cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL;
|
||||
cancelled = !uv__queue_empty(&w->wq) && w->work != NULL;
|
||||
if (cancelled)
|
||||
QUEUE_REMOVE(&w->wq);
|
||||
uv__queue_remove(&w->wq);
|
||||
|
||||
uv_mutex_unlock(&w->loop->wq_mutex);
|
||||
uv_mutex_unlock(&mutex);
|
||||
@ -289,7 +297,7 @@ static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
|
||||
|
||||
w->work = uv__cancelled;
|
||||
uv_mutex_lock(&loop->wq_mutex);
|
||||
QUEUE_INSERT_TAIL(&loop->wq, &w->wq);
|
||||
uv__queue_insert_tail(&loop->wq, &w->wq);
|
||||
uv_async_send(&loop->wq_async);
|
||||
uv_mutex_unlock(&loop->wq_mutex);
|
||||
|
||||
@ -300,22 +308,39 @@ static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
|
||||
void uv__work_done(uv_async_t* handle) {
|
||||
struct uv__work* w;
|
||||
uv_loop_t* loop;
|
||||
QUEUE* q;
|
||||
QUEUE wq;
|
||||
struct uv__queue* q;
|
||||
struct uv__queue wq;
|
||||
int err;
|
||||
int nevents;
|
||||
|
||||
loop = container_of(handle, uv_loop_t, wq_async);
|
||||
uv_mutex_lock(&loop->wq_mutex);
|
||||
QUEUE_MOVE(&loop->wq, &wq);
|
||||
uv__queue_move(&loop->wq, &wq);
|
||||
uv_mutex_unlock(&loop->wq_mutex);
|
||||
|
||||
while (!QUEUE_EMPTY(&wq)) {
|
||||
q = QUEUE_HEAD(&wq);
|
||||
QUEUE_REMOVE(q);
|
||||
nevents = 0;
|
||||
|
||||
while (!uv__queue_empty(&wq)) {
|
||||
q = uv__queue_head(&wq);
|
||||
uv__queue_remove(q);
|
||||
|
||||
w = container_of(q, struct uv__work, wq);
|
||||
err = (w->work == uv__cancelled) ? UV_ECANCELED : 0;
|
||||
w->done(w, err);
|
||||
nevents++;
|
||||
}
|
||||
|
||||
/* This check accomplishes 2 things:
|
||||
* 1. Even if the queue was empty, the call to uv__work_done() should count
|
||||
* as an event. Which will have been added by the event loop when
|
||||
* calling this callback.
|
||||
* 2. Prevents accidental wrap around in case nevents == 0 events == 0.
|
||||
*/
|
||||
if (nevents > 1) {
|
||||
/* Subtract 1 to counter the call to uv__work_done(). */
|
||||
uv__metrics_inc_events(loop, nevents - 1);
|
||||
if (uv__get_internal_fields(loop)->current_timeout == 0)
|
||||
uv__metrics_inc_events_waiting(loop, nevents - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
34
deps/libuv/src/unix/aix.c
vendored
34
deps/libuv/src/unix/aix.c
vendored
@ -131,11 +131,12 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
||||
|
||||
|
||||
void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
uv__loop_internal_fields_t* lfields;
|
||||
struct pollfd events[1024];
|
||||
struct pollfd pqry;
|
||||
struct pollfd* pe;
|
||||
struct poll_ctl pc;
|
||||
QUEUE* q;
|
||||
struct uv__queue* q;
|
||||
uv__io_t* w;
|
||||
uint64_t base;
|
||||
uint64_t diff;
|
||||
@ -150,16 +151,18 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
int reset_timeout;
|
||||
|
||||
if (loop->nfds == 0) {
|
||||
assert(QUEUE_EMPTY(&loop->watcher_queue));
|
||||
assert(uv__queue_empty(&loop->watcher_queue));
|
||||
return;
|
||||
}
|
||||
|
||||
while (!QUEUE_EMPTY(&loop->watcher_queue)) {
|
||||
q = QUEUE_HEAD(&loop->watcher_queue);
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q);
|
||||
lfields = uv__get_internal_fields(loop);
|
||||
|
||||
w = QUEUE_DATA(q, uv__io_t, watcher_queue);
|
||||
while (!uv__queue_empty(&loop->watcher_queue)) {
|
||||
q = uv__queue_head(&loop->watcher_queue);
|
||||
uv__queue_remove(q);
|
||||
uv__queue_init(q);
|
||||
|
||||
w = uv__queue_data(q, uv__io_t, watcher_queue);
|
||||
assert(w->pevents != 0);
|
||||
assert(w->fd >= 0);
|
||||
assert(w->fd < (int) loop->nwatchers);
|
||||
@ -217,7 +220,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
base = loop->time;
|
||||
count = 48; /* Benchmarks suggest this gives the best throughput. */
|
||||
|
||||
if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
|
||||
if (lfields->flags & UV_METRICS_IDLE_TIME) {
|
||||
reset_timeout = 1;
|
||||
user_timeout = timeout;
|
||||
timeout = 0;
|
||||
@ -232,6 +235,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
if (timeout != 0)
|
||||
uv__metrics_set_provider_entry_time(loop);
|
||||
|
||||
/* Store the current timeout in a location that's globally accessible so
|
||||
* other locations like uv__work_done() can determine whether the queue
|
||||
* of events in the callback were waiting when poll was called.
|
||||
*/
|
||||
lfields->current_timeout = timeout;
|
||||
|
||||
nfds = pollset_poll(loop->backend_fd,
|
||||
events,
|
||||
ARRAY_SIZE(events),
|
||||
@ -321,9 +330,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
nevents++;
|
||||
}
|
||||
|
||||
uv__metrics_inc_events(loop, nevents);
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
uv__metrics_inc_events_waiting(loop, nevents);
|
||||
}
|
||||
|
||||
if (have_signals != 0) {
|
||||
@ -389,6 +400,11 @@ uint64_t uv_get_constrained_memory(void) {
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_available_memory(void) {
|
||||
return uv_get_free_memory();
|
||||
}
|
||||
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
perfstat_cpu_total_t ps_total;
|
||||
int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
|
||||
@ -425,7 +441,7 @@ static char* uv__rawname(const char* cp, char (*dst)[FILENAME_MAX+1]) {
|
||||
static int uv__path_is_a_directory(char* filename) {
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat(filename, &statbuf) < 0)
|
||||
if (uv__stat(filename, &statbuf) < 0)
|
||||
return -1; /* failed: not a directory, assume it is a file */
|
||||
|
||||
if (statbuf.st_type == VDIR)
|
||||
|
166
deps/libuv/src/unix/async.c
vendored
166
deps/libuv/src/unix/async.c
vendored
@ -24,9 +24,9 @@
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
#include "atomic-ops.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h> /* snprintf() */
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
@ -40,6 +40,7 @@
|
||||
|
||||
static void uv__async_send(uv_loop_t* loop);
|
||||
static int uv__async_start(uv_loop_t* loop);
|
||||
static void uv__cpu_relax(void);
|
||||
|
||||
|
||||
int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
|
||||
@ -52,8 +53,9 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
|
||||
uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC);
|
||||
handle->async_cb = async_cb;
|
||||
handle->pending = 0;
|
||||
handle->u.fd = 0; /* This will be used as a busy flag. */
|
||||
|
||||
QUEUE_INSERT_TAIL(&loop->async_handles, &handle->queue);
|
||||
uv__queue_insert_tail(&loop->async_handles, &handle->queue);
|
||||
uv__handle_start(handle);
|
||||
|
||||
return 0;
|
||||
@ -61,46 +63,54 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
|
||||
|
||||
|
||||
int uv_async_send(uv_async_t* handle) {
|
||||
_Atomic int* pending;
|
||||
_Atomic int* busy;
|
||||
|
||||
pending = (_Atomic int*) &handle->pending;
|
||||
busy = (_Atomic int*) &handle->u.fd;
|
||||
|
||||
/* Do a cheap read first. */
|
||||
if (ACCESS_ONCE(int, handle->pending) != 0)
|
||||
if (atomic_load_explicit(pending, memory_order_relaxed) != 0)
|
||||
return 0;
|
||||
|
||||
/* Tell the other thread we're busy with the handle. */
|
||||
if (cmpxchgi(&handle->pending, 0, 1) != 0)
|
||||
return 0;
|
||||
/* Set the loop to busy. */
|
||||
atomic_fetch_add(busy, 1);
|
||||
|
||||
/* Wake up the other thread's event loop. */
|
||||
uv__async_send(handle->loop);
|
||||
if (atomic_exchange(pending, 1) == 0)
|
||||
uv__async_send(handle->loop);
|
||||
|
||||
/* Tell the other thread we're done. */
|
||||
if (cmpxchgi(&handle->pending, 1, 2) != 1)
|
||||
abort();
|
||||
/* Set the loop to not-busy. */
|
||||
atomic_fetch_add(busy, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Only call this from the event loop thread. */
|
||||
static int uv__async_spin(uv_async_t* handle) {
|
||||
/* Wait for the busy flag to clear before closing.
|
||||
* Only call this from the event loop thread. */
|
||||
static void uv__async_spin(uv_async_t* handle) {
|
||||
_Atomic int* pending;
|
||||
_Atomic int* busy;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
pending = (_Atomic int*) &handle->pending;
|
||||
busy = (_Atomic int*) &handle->u.fd;
|
||||
|
||||
/* Set the pending flag first, so no new events will be added by other
|
||||
* threads after this function returns. */
|
||||
atomic_store(pending, 1);
|
||||
|
||||
for (;;) {
|
||||
/* 997 is not completely chosen at random. It's a prime number, acyclical
|
||||
* by nature, and should therefore hopefully dampen sympathetic resonance.
|
||||
/* 997 is not completely chosen at random. It's a prime number, acyclic by
|
||||
* nature, and should therefore hopefully dampen sympathetic resonance.
|
||||
*/
|
||||
for (i = 0; i < 997; i++) {
|
||||
/* rc=0 -- handle is not pending.
|
||||
* rc=1 -- handle is pending, other thread is still working with it.
|
||||
* rc=2 -- handle is pending, other thread is done.
|
||||
*/
|
||||
rc = cmpxchgi(&handle->pending, 2, 0);
|
||||
|
||||
if (rc != 1)
|
||||
return rc;
|
||||
if (atomic_load(busy) == 0)
|
||||
return;
|
||||
|
||||
/* Other thread is busy with this handle, spin until it's done. */
|
||||
cpu_relax();
|
||||
uv__cpu_relax();
|
||||
}
|
||||
|
||||
/* Yield the CPU. We may have preempted the other thread while it's
|
||||
@ -114,7 +124,7 @@ static int uv__async_spin(uv_async_t* handle) {
|
||||
|
||||
void uv__async_close(uv_async_t* handle) {
|
||||
uv__async_spin(handle);
|
||||
QUEUE_REMOVE(&handle->queue);
|
||||
uv__queue_remove(&handle->queue);
|
||||
uv__handle_stop(handle);
|
||||
}
|
||||
|
||||
@ -122,9 +132,10 @@ void uv__async_close(uv_async_t* handle) {
|
||||
static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
char buf[1024];
|
||||
ssize_t r;
|
||||
QUEUE queue;
|
||||
QUEUE* q;
|
||||
struct uv__queue queue;
|
||||
struct uv__queue* q;
|
||||
uv_async_t* h;
|
||||
_Atomic int *pending;
|
||||
|
||||
assert(w == &loop->async_io_watcher);
|
||||
|
||||
@ -146,16 +157,18 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
abort();
|
||||
}
|
||||
|
||||
QUEUE_MOVE(&loop->async_handles, &queue);
|
||||
while (!QUEUE_EMPTY(&queue)) {
|
||||
q = QUEUE_HEAD(&queue);
|
||||
h = QUEUE_DATA(q, uv_async_t, queue);
|
||||
uv__queue_move(&loop->async_handles, &queue);
|
||||
while (!uv__queue_empty(&queue)) {
|
||||
q = uv__queue_head(&queue);
|
||||
h = uv__queue_data(q, uv_async_t, queue);
|
||||
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INSERT_TAIL(&loop->async_handles, q);
|
||||
uv__queue_remove(q);
|
||||
uv__queue_insert_tail(&loop->async_handles, q);
|
||||
|
||||
if (0 == uv__async_spin(h))
|
||||
continue; /* Not pending. */
|
||||
/* Atomically fetch and clear pending flag */
|
||||
pending = (_Atomic int*) &h->pending;
|
||||
if (atomic_exchange(pending, 0) == 0)
|
||||
continue;
|
||||
|
||||
if (h->async_cb == NULL)
|
||||
continue;
|
||||
@ -227,20 +240,28 @@ static int uv__async_start(uv_loop_t* loop) {
|
||||
}
|
||||
|
||||
|
||||
int uv__async_fork(uv_loop_t* loop) {
|
||||
if (loop->async_io_watcher.fd == -1) /* never started */
|
||||
return 0;
|
||||
|
||||
uv__async_stop(loop);
|
||||
|
||||
return uv__async_start(loop);
|
||||
}
|
||||
|
||||
|
||||
void uv__async_stop(uv_loop_t* loop) {
|
||||
struct uv__queue queue;
|
||||
struct uv__queue* q;
|
||||
uv_async_t* h;
|
||||
|
||||
if (loop->async_io_watcher.fd == -1)
|
||||
return;
|
||||
|
||||
/* Make sure no other thread is accessing the async handle fd after the loop
|
||||
* cleanup.
|
||||
*/
|
||||
uv__queue_move(&loop->async_handles, &queue);
|
||||
while (!uv__queue_empty(&queue)) {
|
||||
q = uv__queue_head(&queue);
|
||||
h = uv__queue_data(q, uv_async_t, queue);
|
||||
|
||||
uv__queue_remove(q);
|
||||
uv__queue_insert_tail(&loop->async_handles, q);
|
||||
|
||||
uv__async_spin(h);
|
||||
}
|
||||
|
||||
if (loop->async_wfd != -1) {
|
||||
if (loop->async_wfd != loop->async_io_watcher.fd)
|
||||
uv__close(loop->async_wfd);
|
||||
@ -251,3 +272,58 @@ void uv__async_stop(uv_loop_t* loop) {
|
||||
uv__close(loop->async_io_watcher.fd);
|
||||
loop->async_io_watcher.fd = -1;
|
||||
}
|
||||
|
||||
|
||||
int uv__async_fork(uv_loop_t* loop) {
|
||||
struct uv__queue queue;
|
||||
struct uv__queue* q;
|
||||
uv_async_t* h;
|
||||
|
||||
if (loop->async_io_watcher.fd == -1) /* never started */
|
||||
return 0;
|
||||
|
||||
uv__queue_move(&loop->async_handles, &queue);
|
||||
while (!uv__queue_empty(&queue)) {
|
||||
q = uv__queue_head(&queue);
|
||||
h = uv__queue_data(q, uv_async_t, queue);
|
||||
|
||||
uv__queue_remove(q);
|
||||
uv__queue_insert_tail(&loop->async_handles, q);
|
||||
|
||||
/* The state of any thread that set pending is now likely corrupt in this
|
||||
* child because the user called fork, so just clear these flags and move
|
||||
* on. Calling most libc functions after `fork` is declared to be undefined
|
||||
* behavior anyways, unless async-signal-safe, for multithreaded programs
|
||||
* like libuv, and nothing interesting in pthreads is async-signal-safe.
|
||||
*/
|
||||
h->pending = 0;
|
||||
/* This is the busy flag, and we just abruptly lost all other threads. */
|
||||
h->u.fd = 0;
|
||||
}
|
||||
|
||||
/* Recreate these, since they still exist, but belong to the wrong pid now. */
|
||||
if (loop->async_wfd != -1) {
|
||||
if (loop->async_wfd != loop->async_io_watcher.fd)
|
||||
uv__close(loop->async_wfd);
|
||||
loop->async_wfd = -1;
|
||||
}
|
||||
|
||||
uv__io_stop(loop, &loop->async_io_watcher, POLLIN);
|
||||
uv__close(loop->async_io_watcher.fd);
|
||||
loop->async_io_watcher.fd = -1;
|
||||
|
||||
return uv__async_start(loop);
|
||||
}
|
||||
|
||||
|
||||
static void uv__cpu_relax(void) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
__asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */
|
||||
#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
|
||||
__asm__ __volatile__ ("yield" ::: "memory");
|
||||
#elif (defined(__ppc__) || defined(__ppc64__)) && defined(__APPLE__)
|
||||
__asm volatile ("" : : : "memory");
|
||||
#elif !defined(__APPLE__) && (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__))
|
||||
__asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
|
64
deps/libuv/src/unix/atomic-ops.h
vendored
64
deps/libuv/src/unix/atomic-ops.h
vendored
@ -1,64 +0,0 @@
|
||||
/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_ATOMIC_OPS_H_
|
||||
#define UV_ATOMIC_OPS_H_
|
||||
|
||||
#include "internal.h" /* UV_UNUSED */
|
||||
|
||||
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
#include <atomic.h>
|
||||
#endif
|
||||
|
||||
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
|
||||
UV_UNUSED(static void cpu_relax(void));
|
||||
|
||||
/* Prefer hand-rolled assembly over the gcc builtins because the latter also
|
||||
* issue full memory barriers.
|
||||
*/
|
||||
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
int out;
|
||||
__asm__ __volatile__ ("lock; cmpxchg %2, %1;"
|
||||
: "=a" (out), "+m" (*(volatile int*) ptr)
|
||||
: "r" (newval), "0" (oldval)
|
||||
: "memory");
|
||||
return out;
|
||||
#elif defined(__MVS__)
|
||||
/* Use hand-rolled assembly because codegen from builtin __plo_CSST results in
|
||||
* a runtime bug.
|
||||
*/
|
||||
__asm(" cs %0,%2,%1 \n " : "+r"(oldval), "+m"(*ptr) : "r"(newval) :);
|
||||
return oldval;
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
|
||||
#else
|
||||
return __sync_val_compare_and_swap(ptr, oldval, newval);
|
||||
#endif
|
||||
}
|
||||
|
||||
UV_UNUSED(static void cpu_relax(void)) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
__asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */
|
||||
#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
|
||||
__asm__ __volatile__ ("yield" ::: "memory");
|
||||
#elif (defined(__ppc__) || defined(__ppc64__)) && defined(__APPLE__)
|
||||
__asm volatile ("" : : : "memory");
|
||||
#elif !defined(__APPLE__) && (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__))
|
||||
__asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* UV_ATOMIC_OPS_H_ */
|
249
deps/libuv/src/unix/core.c
vendored
249
deps/libuv/src/unix/core.c
vendored
@ -41,12 +41,13 @@
|
||||
#include <sys/uio.h> /* writev */
|
||||
#include <sys/resource.h> /* getrusage */
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h> /* clock_gettime */
|
||||
|
||||
#ifdef __sun
|
||||
# include <sys/filio.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
@ -66,13 +67,14 @@ extern char** environ;
|
||||
|
||||
#if defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/filio.h>
|
||||
# include <sys/wait.h>
|
||||
# include <sys/param.h>
|
||||
# if defined(__FreeBSD__)
|
||||
# include <sys/cpuset.h>
|
||||
# define uv__accept4 accept4
|
||||
# endif
|
||||
# if defined(__NetBSD__)
|
||||
@ -107,6 +109,35 @@ STATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base));
|
||||
STATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len));
|
||||
|
||||
|
||||
/* https://github.com/libuv/libuv/issues/1674 */
|
||||
int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts) {
|
||||
struct timespec t;
|
||||
int r;
|
||||
|
||||
if (ts == NULL)
|
||||
return UV_EFAULT;
|
||||
|
||||
switch (clock_id) {
|
||||
default:
|
||||
return UV_EINVAL;
|
||||
case UV_CLOCK_MONOTONIC:
|
||||
r = clock_gettime(CLOCK_MONOTONIC, &t);
|
||||
break;
|
||||
case UV_CLOCK_REALTIME:
|
||||
r = clock_gettime(CLOCK_REALTIME, &t);
|
||||
break;
|
||||
}
|
||||
|
||||
if (r)
|
||||
return UV__ERR(errno);
|
||||
|
||||
ts->tv_sec = t.tv_sec;
|
||||
ts->tv_nsec = t.tv_nsec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_hrtime(void) {
|
||||
return uv__hrtime(UV_CLOCK_PRECISE);
|
||||
}
|
||||
@ -232,10 +263,10 @@ int uv__getiovmax(void) {
|
||||
#if defined(IOV_MAX)
|
||||
return IOV_MAX;
|
||||
#elif defined(_SC_IOV_MAX)
|
||||
static int iovmax_cached = -1;
|
||||
static _Atomic int iovmax_cached = -1;
|
||||
int iovmax;
|
||||
|
||||
iovmax = uv__load_relaxed(&iovmax_cached);
|
||||
iovmax = atomic_load_explicit(&iovmax_cached, memory_order_relaxed);
|
||||
if (iovmax != -1)
|
||||
return iovmax;
|
||||
|
||||
@ -247,7 +278,7 @@ int uv__getiovmax(void) {
|
||||
if (iovmax == -1)
|
||||
iovmax = 1;
|
||||
|
||||
uv__store_relaxed(&iovmax_cached, iovmax);
|
||||
atomic_store_explicit(&iovmax_cached, iovmax, memory_order_relaxed);
|
||||
|
||||
return iovmax;
|
||||
#else
|
||||
@ -313,7 +344,7 @@ static void uv__finish_close(uv_handle_t* handle) {
|
||||
}
|
||||
|
||||
uv__handle_unref(handle);
|
||||
QUEUE_REMOVE(&handle->handle_queue);
|
||||
uv__queue_remove(&handle->handle_queue);
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb(handle);
|
||||
@ -349,7 +380,7 @@ int uv_backend_fd(const uv_loop_t* loop) {
|
||||
static int uv__loop_alive(const uv_loop_t* loop) {
|
||||
return uv__has_active_handles(loop) ||
|
||||
uv__has_active_reqs(loop) ||
|
||||
!QUEUE_EMPTY(&loop->pending_queue) ||
|
||||
!uv__queue_empty(&loop->pending_queue) ||
|
||||
loop->closing_handles != NULL;
|
||||
}
|
||||
|
||||
@ -358,8 +389,9 @@ static int uv__backend_timeout(const uv_loop_t* loop) {
|
||||
if (loop->stop_flag == 0 &&
|
||||
/* uv__loop_alive(loop) && */
|
||||
(uv__has_active_handles(loop) || uv__has_active_reqs(loop)) &&
|
||||
QUEUE_EMPTY(&loop->pending_queue) &&
|
||||
QUEUE_EMPTY(&loop->idle_handles) &&
|
||||
uv__queue_empty(&loop->pending_queue) &&
|
||||
uv__queue_empty(&loop->idle_handles) &&
|
||||
(loop->flags & UV_LOOP_REAP_CHILDREN) == 0 &&
|
||||
loop->closing_handles == NULL)
|
||||
return uv__next_timeout(loop);
|
||||
return 0;
|
||||
@ -367,7 +399,7 @@ static int uv__backend_timeout(const uv_loop_t* loop) {
|
||||
|
||||
|
||||
int uv_backend_timeout(const uv_loop_t* loop) {
|
||||
if (QUEUE_EMPTY(&loop->watcher_queue))
|
||||
if (uv__queue_empty(&loop->watcher_queue))
|
||||
return uv__backend_timeout(loop);
|
||||
/* Need to call uv_run to update the backend fd state. */
|
||||
return 0;
|
||||
@ -388,12 +420,19 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
|
||||
if (!r)
|
||||
uv__update_time(loop);
|
||||
|
||||
while (r != 0 && loop->stop_flag == 0) {
|
||||
/* Maintain backwards compatibility by processing timers before entering the
|
||||
* while loop for UV_RUN_DEFAULT. Otherwise timers only need to be executed
|
||||
* once, which should be done after polling in order to maintain proper
|
||||
* execution order of the conceptual event loop. */
|
||||
if (mode == UV_RUN_DEFAULT && r != 0 && loop->stop_flag == 0) {
|
||||
uv__update_time(loop);
|
||||
uv__run_timers(loop);
|
||||
}
|
||||
|
||||
while (r != 0 && loop->stop_flag == 0) {
|
||||
can_sleep =
|
||||
QUEUE_EMPTY(&loop->pending_queue) && QUEUE_EMPTY(&loop->idle_handles);
|
||||
uv__queue_empty(&loop->pending_queue) &&
|
||||
uv__queue_empty(&loop->idle_handles);
|
||||
|
||||
uv__run_pending(loop);
|
||||
uv__run_idle(loop);
|
||||
@ -403,11 +442,13 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
|
||||
if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT)
|
||||
timeout = uv__backend_timeout(loop);
|
||||
|
||||
uv__metrics_inc_loop_count(loop);
|
||||
|
||||
uv__io_poll(loop, timeout);
|
||||
|
||||
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
|
||||
* times to avoid loop starvation.*/
|
||||
for (r = 0; r < 8 && !QUEUE_EMPTY(&loop->pending_queue); r++)
|
||||
for (r = 0; r < 8 && !uv__queue_empty(&loop->pending_queue); r++)
|
||||
uv__run_pending(loop);
|
||||
|
||||
/* Run one final update on the provider_idle_time in case uv__io_poll
|
||||
@ -420,18 +461,8 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
|
||||
uv__run_check(loop);
|
||||
uv__run_closing_handles(loop);
|
||||
|
||||
if (mode == UV_RUN_ONCE) {
|
||||
/* UV_RUN_ONCE implies forward progress: at least one callback must have
|
||||
* been invoked when it returns. uv__io_poll() can return without doing
|
||||
* I/O (meaning: no callbacks) when its timeout expires - which means we
|
||||
* have pending timers that satisfy the forward progress constraint.
|
||||
*
|
||||
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
|
||||
* the check.
|
||||
*/
|
||||
uv__update_time(loop);
|
||||
uv__run_timers(loop);
|
||||
}
|
||||
uv__update_time(loop);
|
||||
uv__run_timers(loop);
|
||||
|
||||
r = uv__loop_alive(loop);
|
||||
if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
|
||||
@ -796,17 +827,17 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
|
||||
|
||||
|
||||
static void uv__run_pending(uv_loop_t* loop) {
|
||||
QUEUE* q;
|
||||
QUEUE pq;
|
||||
struct uv__queue* q;
|
||||
struct uv__queue pq;
|
||||
uv__io_t* w;
|
||||
|
||||
QUEUE_MOVE(&loop->pending_queue, &pq);
|
||||
uv__queue_move(&loop->pending_queue, &pq);
|
||||
|
||||
while (!QUEUE_EMPTY(&pq)) {
|
||||
q = QUEUE_HEAD(&pq);
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q);
|
||||
w = QUEUE_DATA(q, uv__io_t, pending_queue);
|
||||
while (!uv__queue_empty(&pq)) {
|
||||
q = uv__queue_head(&pq);
|
||||
uv__queue_remove(q);
|
||||
uv__queue_init(q);
|
||||
w = uv__queue_data(q, uv__io_t, pending_queue);
|
||||
w->cb(loop, w, POLLOUT);
|
||||
}
|
||||
}
|
||||
@ -861,17 +892,12 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) {
|
||||
void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
|
||||
assert(cb != NULL);
|
||||
assert(fd >= -1);
|
||||
QUEUE_INIT(&w->pending_queue);
|
||||
QUEUE_INIT(&w->watcher_queue);
|
||||
uv__queue_init(&w->pending_queue);
|
||||
uv__queue_init(&w->watcher_queue);
|
||||
w->cb = cb;
|
||||
w->fd = fd;
|
||||
w->events = 0;
|
||||
w->pevents = 0;
|
||||
|
||||
#if defined(UV_HAVE_KQUEUE)
|
||||
w->rcount = 0;
|
||||
w->wcount = 0;
|
||||
#endif /* defined(UV_HAVE_KQUEUE) */
|
||||
}
|
||||
|
||||
|
||||
@ -893,8 +919,8 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (QUEUE_EMPTY(&w->watcher_queue))
|
||||
QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
|
||||
if (uv__queue_empty(&w->watcher_queue))
|
||||
uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue);
|
||||
|
||||
if (loop->watchers[w->fd] == NULL) {
|
||||
loop->watchers[w->fd] = w;
|
||||
@ -919,8 +945,8 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
w->pevents &= ~events;
|
||||
|
||||
if (w->pevents == 0) {
|
||||
QUEUE_REMOVE(&w->watcher_queue);
|
||||
QUEUE_INIT(&w->watcher_queue);
|
||||
uv__queue_remove(&w->watcher_queue);
|
||||
uv__queue_init(&w->watcher_queue);
|
||||
w->events = 0;
|
||||
|
||||
if (w == loop->watchers[w->fd]) {
|
||||
@ -929,14 +955,14 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
loop->nfds--;
|
||||
}
|
||||
}
|
||||
else if (QUEUE_EMPTY(&w->watcher_queue))
|
||||
QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
|
||||
else if (uv__queue_empty(&w->watcher_queue))
|
||||
uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue);
|
||||
}
|
||||
|
||||
|
||||
void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
|
||||
uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
|
||||
QUEUE_REMOVE(&w->pending_queue);
|
||||
uv__queue_remove(&w->pending_queue);
|
||||
|
||||
/* Remove stale events for this file descriptor */
|
||||
if (w->fd != -1)
|
||||
@ -945,8 +971,8 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
|
||||
|
||||
|
||||
void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
|
||||
if (QUEUE_EMPTY(&w->pending_queue))
|
||||
QUEUE_INSERT_TAIL(&loop->pending_queue, &w->pending_queue);
|
||||
if (uv__queue_empty(&w->pending_queue))
|
||||
uv__queue_insert_tail(&loop->pending_queue, &w->pending_queue);
|
||||
}
|
||||
|
||||
|
||||
@ -991,6 +1017,15 @@ int uv_getrusage(uv_rusage_t* rusage) {
|
||||
rusage->ru_nivcsw = usage.ru_nivcsw;
|
||||
#endif
|
||||
|
||||
/* Most platforms report ru_maxrss in kilobytes; macOS and Solaris are
|
||||
* the outliers because of course they are.
|
||||
*/
|
||||
#if defined(__APPLE__)
|
||||
rusage->ru_maxrss /= 1024; /* macOS and iOS report bytes. */
|
||||
#elif defined(__sun)
|
||||
rusage->ru_maxrss /= getpagesize() / 1024; /* Solaris reports pages. */
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1090,8 +1125,8 @@ int uv_os_homedir(char* buffer, size_t* size) {
|
||||
if (r != UV_ENOENT)
|
||||
return r;
|
||||
|
||||
/* HOME is not set, so call uv__getpwuid_r() */
|
||||
r = uv__getpwuid_r(&pwd);
|
||||
/* HOME is not set, so call uv_os_get_passwd() */
|
||||
r = uv_os_get_passwd(&pwd);
|
||||
|
||||
if (r != 0) {
|
||||
return r;
|
||||
@ -1164,11 +1199,10 @@ return_buffer:
|
||||
}
|
||||
|
||||
|
||||
int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
static int uv__getpwuid_r(uv_passwd_t *pwd, uid_t uid) {
|
||||
struct passwd pw;
|
||||
struct passwd* result;
|
||||
char* buf;
|
||||
uid_t uid;
|
||||
size_t bufsize;
|
||||
size_t name_size;
|
||||
size_t homedir_size;
|
||||
@ -1178,8 +1212,6 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
if (pwd == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
uid = geteuid();
|
||||
|
||||
/* Calling sysconf(_SC_GETPW_R_SIZE_MAX) would get the suggested size, but it
|
||||
* is frequently 1024 or 4096, so we can just use that directly. The pwent
|
||||
* will not usually be large. */
|
||||
@ -1238,24 +1270,98 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
}
|
||||
|
||||
|
||||
void uv_os_free_passwd(uv_passwd_t* pwd) {
|
||||
if (pwd == NULL)
|
||||
return;
|
||||
int uv_os_get_group(uv_group_t* grp, uv_uid_t gid) {
|
||||
#if defined(__ANDROID__) && __ANDROID_API__ < 24
|
||||
/* This function getgrgid_r() was added in Android N (level 24) */
|
||||
return UV_ENOSYS;
|
||||
#else
|
||||
struct group gp;
|
||||
struct group* result;
|
||||
char* buf;
|
||||
char* gr_mem;
|
||||
size_t bufsize;
|
||||
size_t name_size;
|
||||
long members;
|
||||
size_t mem_size;
|
||||
int r;
|
||||
|
||||
/*
|
||||
The memory for name, shell, and homedir are allocated in a single
|
||||
uv__malloc() call. The base of the pointer is stored in pwd->username, so
|
||||
that is the field that needs to be freed.
|
||||
*/
|
||||
uv__free(pwd->username);
|
||||
pwd->username = NULL;
|
||||
pwd->shell = NULL;
|
||||
pwd->homedir = NULL;
|
||||
if (grp == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
/* Calling sysconf(_SC_GETGR_R_SIZE_MAX) would get the suggested size, but it
|
||||
* is frequently 1024 or 4096, so we can just use that directly. The pwent
|
||||
* will not usually be large. */
|
||||
for (bufsize = 2000;; bufsize *= 2) {
|
||||
buf = uv__malloc(bufsize);
|
||||
|
||||
if (buf == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
do
|
||||
r = getgrgid_r(gid, &gp, buf, bufsize, &result);
|
||||
while (r == EINTR);
|
||||
|
||||
if (r != 0 || result == NULL)
|
||||
uv__free(buf);
|
||||
|
||||
if (r != ERANGE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (r != 0)
|
||||
return UV__ERR(r);
|
||||
|
||||
if (result == NULL)
|
||||
return UV_ENOENT;
|
||||
|
||||
/* Allocate memory for the groupname and members. */
|
||||
name_size = strlen(gp.gr_name) + 1;
|
||||
members = 0;
|
||||
mem_size = sizeof(char*);
|
||||
for (r = 0; gp.gr_mem[r] != NULL; r++) {
|
||||
mem_size += strlen(gp.gr_mem[r]) + 1 + sizeof(char*);
|
||||
members++;
|
||||
}
|
||||
|
||||
gr_mem = uv__malloc(name_size + mem_size);
|
||||
if (gr_mem == NULL) {
|
||||
uv__free(buf);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
/* Copy the members */
|
||||
grp->members = (char**) gr_mem;
|
||||
grp->members[members] = NULL;
|
||||
gr_mem = (char*) &grp->members[members + 1];
|
||||
for (r = 0; r < members; r++) {
|
||||
grp->members[r] = gr_mem;
|
||||
strcpy(gr_mem, gp.gr_mem[r]);
|
||||
gr_mem += strlen(gr_mem) + 1;
|
||||
}
|
||||
assert(gr_mem == (char*)grp->members + mem_size);
|
||||
|
||||
/* Copy the groupname */
|
||||
grp->groupname = gr_mem;
|
||||
memcpy(grp->groupname, gp.gr_name, name_size);
|
||||
gr_mem += name_size;
|
||||
|
||||
/* Copy the gid */
|
||||
grp->gid = gp.gr_gid;
|
||||
|
||||
uv__free(buf);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int uv_os_get_passwd(uv_passwd_t* pwd) {
|
||||
return uv__getpwuid_r(pwd);
|
||||
return uv__getpwuid_r(pwd, geteuid());
|
||||
}
|
||||
|
||||
|
||||
int uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid) {
|
||||
return uv__getpwuid_r(pwd, uid);
|
||||
}
|
||||
|
||||
|
||||
@ -1416,6 +1522,13 @@ uv_pid_t uv_os_getppid(void) {
|
||||
return getppid();
|
||||
}
|
||||
|
||||
int uv_cpumask_size(void) {
|
||||
#if UV__CPU_AFFINITY_SUPPORTED
|
||||
return CPU_SETSIZE;
|
||||
#else
|
||||
return UV_ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int uv_os_getpriority(uv_pid_t pid, int* priority) {
|
||||
int r;
|
||||
|
4
deps/libuv/src/unix/cygwin.c
vendored
4
deps/libuv/src/unix/cygwin.c
vendored
@ -51,3 +51,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
uint64_t uv_get_constrained_memory(void) {
|
||||
return 0; /* Memory constraints are unknown. */
|
||||
}
|
||||
|
||||
uint64_t uv_get_available_memory(void) {
|
||||
return uv_get_free_memory();
|
||||
}
|
||||
|
16
deps/libuv/src/unix/darwin-stub.h
vendored
16
deps/libuv/src/unix/darwin-stub.h
vendored
@ -27,7 +27,6 @@
|
||||
struct CFArrayCallBacks;
|
||||
struct CFRunLoopSourceContext;
|
||||
struct FSEventStreamContext;
|
||||
struct CFRange;
|
||||
|
||||
typedef double CFAbsoluteTime;
|
||||
typedef double CFTimeInterval;
|
||||
@ -43,23 +42,13 @@ typedef unsigned CFStringEncoding;
|
||||
typedef void* CFAllocatorRef;
|
||||
typedef void* CFArrayRef;
|
||||
typedef void* CFBundleRef;
|
||||
typedef void* CFDataRef;
|
||||
typedef void* CFDictionaryRef;
|
||||
typedef void* CFMutableDictionaryRef;
|
||||
typedef struct CFRange CFRange;
|
||||
typedef void* CFRunLoopRef;
|
||||
typedef void* CFRunLoopSourceRef;
|
||||
typedef void* CFStringRef;
|
||||
typedef void* CFTypeRef;
|
||||
typedef void* FSEventStreamRef;
|
||||
|
||||
typedef uint32_t IOOptionBits;
|
||||
typedef unsigned int io_iterator_t;
|
||||
typedef unsigned int io_object_t;
|
||||
typedef unsigned int io_service_t;
|
||||
typedef unsigned int io_registry_entry_t;
|
||||
|
||||
|
||||
typedef void (*FSEventStreamCallback)(const FSEventStreamRef,
|
||||
void*,
|
||||
size_t,
|
||||
@ -80,11 +69,6 @@ struct FSEventStreamContext {
|
||||
void* pad[3];
|
||||
};
|
||||
|
||||
struct CFRange {
|
||||
CFIndex location;
|
||||
CFIndex length;
|
||||
};
|
||||
|
||||
static const CFStringEncoding kCFStringEncodingUTF8 = 0x8000100;
|
||||
static const OSStatus noErr = 0;
|
||||
|
||||
|
166
deps/libuv/src/unix/darwin.c
vendored
166
deps/libuv/src/unix/darwin.c
vendored
@ -33,13 +33,10 @@
|
||||
#include <sys/sysctl.h>
|
||||
#include <unistd.h> /* sysconf */
|
||||
|
||||
#include "darwin-stub.h"
|
||||
|
||||
static uv_once_t once = UV_ONCE_INIT;
|
||||
static uint64_t (*time_func)(void);
|
||||
static mach_timebase_info_data_t timebase;
|
||||
|
||||
typedef unsigned char UInt8;
|
||||
|
||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||
loop->cf_state = NULL;
|
||||
@ -110,7 +107,7 @@ uint64_t uv_get_free_memory(void) {
|
||||
|
||||
if (host_statistics(mach_host_self(), HOST_VM_INFO,
|
||||
(host_info_t)&info, &count) != KERN_SUCCESS) {
|
||||
return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE);
|
||||
@ -123,7 +120,7 @@ uint64_t uv_get_total_memory(void) {
|
||||
size_t size = sizeof(info);
|
||||
|
||||
if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
|
||||
return UV__ERR(errno);
|
||||
return 0;
|
||||
|
||||
return (uint64_t) info;
|
||||
}
|
||||
@ -134,6 +131,11 @@ uint64_t uv_get_constrained_memory(void) {
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_available_memory(void) {
|
||||
return uv_get_free_memory();
|
||||
}
|
||||
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
struct loadavg info;
|
||||
size_t size = sizeof(info);
|
||||
@ -183,159 +185,17 @@ int uv_uptime(double* uptime) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uv__get_cpu_speed(uint64_t* speed) {
|
||||
/* IOKit */
|
||||
void (*pIOObjectRelease)(io_object_t);
|
||||
kern_return_t (*pIOMasterPort)(mach_port_t, mach_port_t*);
|
||||
CFMutableDictionaryRef (*pIOServiceMatching)(const char*);
|
||||
kern_return_t (*pIOServiceGetMatchingServices)(mach_port_t,
|
||||
CFMutableDictionaryRef,
|
||||
io_iterator_t*);
|
||||
io_service_t (*pIOIteratorNext)(io_iterator_t);
|
||||
CFTypeRef (*pIORegistryEntryCreateCFProperty)(io_registry_entry_t,
|
||||
CFStringRef,
|
||||
CFAllocatorRef,
|
||||
IOOptionBits);
|
||||
|
||||
/* CoreFoundation */
|
||||
CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
|
||||
const char*,
|
||||
CFStringEncoding);
|
||||
CFStringEncoding (*pCFStringGetSystemEncoding)(void);
|
||||
UInt8 *(*pCFDataGetBytePtr)(CFDataRef);
|
||||
CFIndex (*pCFDataGetLength)(CFDataRef);
|
||||
void (*pCFDataGetBytes)(CFDataRef, CFRange, UInt8*);
|
||||
void (*pCFRelease)(CFTypeRef);
|
||||
|
||||
void* core_foundation_handle;
|
||||
void* iokit_handle;
|
||||
int err;
|
||||
|
||||
kern_return_t kr;
|
||||
mach_port_t mach_port;
|
||||
io_iterator_t it;
|
||||
io_object_t service;
|
||||
|
||||
mach_port = 0;
|
||||
|
||||
err = UV_ENOENT;
|
||||
core_foundation_handle = dlopen("/System/Library/Frameworks/"
|
||||
"CoreFoundation.framework/"
|
||||
"CoreFoundation",
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
iokit_handle = dlopen("/System/Library/Frameworks/IOKit.framework/"
|
||||
"IOKit",
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
|
||||
if (core_foundation_handle == NULL || iokit_handle == NULL)
|
||||
goto out;
|
||||
|
||||
#define V(handle, symbol) \
|
||||
do { \
|
||||
*(void **)(&p ## symbol) = dlsym((handle), #symbol); \
|
||||
if (p ## symbol == NULL) \
|
||||
goto out; \
|
||||
} \
|
||||
while (0)
|
||||
V(iokit_handle, IOMasterPort);
|
||||
V(iokit_handle, IOServiceMatching);
|
||||
V(iokit_handle, IOServiceGetMatchingServices);
|
||||
V(iokit_handle, IOIteratorNext);
|
||||
V(iokit_handle, IOObjectRelease);
|
||||
V(iokit_handle, IORegistryEntryCreateCFProperty);
|
||||
V(core_foundation_handle, CFStringCreateWithCString);
|
||||
V(core_foundation_handle, CFStringGetSystemEncoding);
|
||||
V(core_foundation_handle, CFDataGetBytePtr);
|
||||
V(core_foundation_handle, CFDataGetLength);
|
||||
V(core_foundation_handle, CFDataGetBytes);
|
||||
V(core_foundation_handle, CFRelease);
|
||||
#undef V
|
||||
|
||||
#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
|
||||
|
||||
kr = pIOMasterPort(MACH_PORT_NULL, &mach_port);
|
||||
assert(kr == KERN_SUCCESS);
|
||||
CFMutableDictionaryRef classes_to_match
|
||||
= pIOServiceMatching("IOPlatformDevice");
|
||||
kr = pIOServiceGetMatchingServices(mach_port, classes_to_match, &it);
|
||||
assert(kr == KERN_SUCCESS);
|
||||
service = pIOIteratorNext(it);
|
||||
|
||||
CFStringRef device_type_str = S("device_type");
|
||||
CFStringRef clock_frequency_str = S("clock-frequency");
|
||||
|
||||
while (service != 0) {
|
||||
CFDataRef data;
|
||||
data = pIORegistryEntryCreateCFProperty(service,
|
||||
device_type_str,
|
||||
NULL,
|
||||
0);
|
||||
if (data) {
|
||||
const UInt8* raw = pCFDataGetBytePtr(data);
|
||||
if (strncmp((char*)raw, "cpu", 3) == 0 ||
|
||||
strncmp((char*)raw, "processor", 9) == 0) {
|
||||
CFDataRef freq_ref;
|
||||
freq_ref = pIORegistryEntryCreateCFProperty(service,
|
||||
clock_frequency_str,
|
||||
NULL,
|
||||
0);
|
||||
if (freq_ref) {
|
||||
const UInt8* freq_ref_ptr = pCFDataGetBytePtr(freq_ref);
|
||||
CFIndex len = pCFDataGetLength(freq_ref);
|
||||
if (len == 8)
|
||||
memcpy(speed, freq_ref_ptr, 8);
|
||||
else if (len == 4) {
|
||||
uint32_t v;
|
||||
memcpy(&v, freq_ref_ptr, 4);
|
||||
*speed = v;
|
||||
} else {
|
||||
*speed = 0;
|
||||
}
|
||||
|
||||
pCFRelease(freq_ref);
|
||||
pCFRelease(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pCFRelease(data);
|
||||
}
|
||||
|
||||
service = pIOIteratorNext(it);
|
||||
}
|
||||
|
||||
pIOObjectRelease(it);
|
||||
|
||||
err = 0;
|
||||
|
||||
if (device_type_str != NULL)
|
||||
pCFRelease(device_type_str);
|
||||
if (clock_frequency_str != NULL)
|
||||
pCFRelease(clock_frequency_str);
|
||||
|
||||
out:
|
||||
if (core_foundation_handle != NULL)
|
||||
dlclose(core_foundation_handle);
|
||||
|
||||
if (iokit_handle != NULL)
|
||||
dlclose(iokit_handle);
|
||||
|
||||
mach_port_deallocate(mach_task_self(), mach_port);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
|
||||
multiplier = ((uint64_t)1000L / ticks);
|
||||
char model[512];
|
||||
uint64_t cpuspeed;
|
||||
size_t size;
|
||||
unsigned int i;
|
||||
natural_t numcpus;
|
||||
mach_msg_type_number_t msg_type;
|
||||
processor_cpu_load_info_data_t *info;
|
||||
uv_cpu_info_t* cpu_info;
|
||||
uint64_t cpuspeed;
|
||||
int err;
|
||||
|
||||
size = sizeof(model);
|
||||
if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) &&
|
||||
@ -343,9 +203,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
|
||||
err = uv__get_cpu_speed(&cpuspeed);
|
||||
if (err < 0)
|
||||
return err;
|
||||
cpuspeed = 0;
|
||||
size = sizeof(cpuspeed);
|
||||
sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0);
|
||||
if (cpuspeed == 0)
|
||||
/* If sysctl hw.cputype == CPU_TYPE_ARM64, the correct value is unavailable
|
||||
* from Apple, but we can hard-code it here to a plausible value. */
|
||||
cpuspeed = 2400000000;
|
||||
|
||||
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
|
||||
(processor_info_array_t*)&info,
|
||||
|
422
deps/libuv/src/unix/epoll.c
vendored
422
deps/libuv/src/unix/epoll.c
vendored
@ -1,422 +0,0 @@
|
||||
/* Copyright libuv contributors. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
#include <errno.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
int uv__epoll_init(uv_loop_t* loop) {
|
||||
int fd;
|
||||
fd = epoll_create1(O_CLOEXEC);
|
||||
|
||||
/* epoll_create1() can fail either because it's not implemented (old kernel)
|
||||
* or because it doesn't understand the O_CLOEXEC flag.
|
||||
*/
|
||||
if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
|
||||
fd = epoll_create(256);
|
||||
|
||||
if (fd != -1)
|
||||
uv__cloexec(fd, 1);
|
||||
}
|
||||
|
||||
loop->backend_fd = fd;
|
||||
if (fd == -1)
|
||||
return UV__ERR(errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
||||
struct epoll_event* events;
|
||||
struct epoll_event dummy;
|
||||
uintptr_t i;
|
||||
uintptr_t nfds;
|
||||
|
||||
assert(loop->watchers != NULL);
|
||||
assert(fd >= 0);
|
||||
|
||||
events = (struct epoll_event*) loop->watchers[loop->nwatchers];
|
||||
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
|
||||
if (events != NULL)
|
||||
/* Invalidate events with same file descriptor */
|
||||
for (i = 0; i < nfds; i++)
|
||||
if (events[i].data.fd == fd)
|
||||
events[i].data.fd = -1;
|
||||
|
||||
/* Remove the file descriptor from the epoll.
|
||||
* This avoids a problem where the same file description remains open
|
||||
* in another process, causing repeated junk epoll events.
|
||||
*
|
||||
* We pass in a dummy epoll_event, to work around a bug in old kernels.
|
||||
*/
|
||||
if (loop->backend_fd >= 0) {
|
||||
/* Work around a bug in kernels 3.10 to 3.19 where passing a struct that
|
||||
* has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.
|
||||
*/
|
||||
memset(&dummy, 0, sizeof(dummy));
|
||||
epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
||||
struct epoll_event e;
|
||||
int rc;
|
||||
|
||||
memset(&e, 0, sizeof(e));
|
||||
e.events = POLLIN;
|
||||
e.data.fd = -1;
|
||||
|
||||
rc = 0;
|
||||
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))
|
||||
if (errno != EEXIST)
|
||||
rc = UV__ERR(errno);
|
||||
|
||||
if (rc == 0)
|
||||
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))
|
||||
abort();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
/* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
|
||||
* effectively infinite on 32 bits architectures. To avoid blocking
|
||||
* indefinitely, we cap the timeout and poll again if necessary.
|
||||
*
|
||||
* Note that "30 minutes" is a simplification because it depends on
|
||||
* the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200,
|
||||
* that being the largest value I have seen in the wild (and only once.)
|
||||
*/
|
||||
static const int max_safe_timeout = 1789569;
|
||||
static int no_epoll_pwait_cached;
|
||||
static int no_epoll_wait_cached;
|
||||
int no_epoll_pwait;
|
||||
int no_epoll_wait;
|
||||
struct epoll_event events[1024];
|
||||
struct epoll_event* pe;
|
||||
struct epoll_event e;
|
||||
int real_timeout;
|
||||
QUEUE* q;
|
||||
uv__io_t* w;
|
||||
sigset_t sigset;
|
||||
uint64_t sigmask;
|
||||
uint64_t base;
|
||||
int have_signals;
|
||||
int nevents;
|
||||
int count;
|
||||
int nfds;
|
||||
int fd;
|
||||
int op;
|
||||
int i;
|
||||
int user_timeout;
|
||||
int reset_timeout;
|
||||
|
||||
if (loop->nfds == 0) {
|
||||
assert(QUEUE_EMPTY(&loop->watcher_queue));
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&e, 0, sizeof(e));
|
||||
|
||||
while (!QUEUE_EMPTY(&loop->watcher_queue)) {
|
||||
q = QUEUE_HEAD(&loop->watcher_queue);
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q);
|
||||
|
||||
w = QUEUE_DATA(q, uv__io_t, watcher_queue);
|
||||
assert(w->pevents != 0);
|
||||
assert(w->fd >= 0);
|
||||
assert(w->fd < (int) loop->nwatchers);
|
||||
|
||||
e.events = w->pevents;
|
||||
e.data.fd = w->fd;
|
||||
|
||||
if (w->events == 0)
|
||||
op = EPOLL_CTL_ADD;
|
||||
else
|
||||
op = EPOLL_CTL_MOD;
|
||||
|
||||
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
|
||||
* events, skip the syscall and squelch the events after epoll_wait().
|
||||
*/
|
||||
if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
|
||||
if (errno != EEXIST)
|
||||
abort();
|
||||
|
||||
assert(op == EPOLL_CTL_ADD);
|
||||
|
||||
/* We've reactivated a file descriptor that's been watched before. */
|
||||
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))
|
||||
abort();
|
||||
}
|
||||
|
||||
w->events = w->pevents;
|
||||
}
|
||||
|
||||
sigmask = 0;
|
||||
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGPROF);
|
||||
sigmask |= 1 << (SIGPROF - 1);
|
||||
}
|
||||
|
||||
assert(timeout >= -1);
|
||||
base = loop->time;
|
||||
count = 48; /* Benchmarks suggest this gives the best throughput. */
|
||||
real_timeout = timeout;
|
||||
|
||||
if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
|
||||
reset_timeout = 1;
|
||||
user_timeout = timeout;
|
||||
timeout = 0;
|
||||
} else {
|
||||
reset_timeout = 0;
|
||||
user_timeout = 0;
|
||||
}
|
||||
|
||||
/* You could argue there is a dependency between these two but
|
||||
* ultimately we don't care about their ordering with respect
|
||||
* to one another. Worst case, we make a few system calls that
|
||||
* could have been avoided because another thread already knows
|
||||
* they fail with ENOSYS. Hardly the end of the world.
|
||||
*/
|
||||
no_epoll_pwait = uv__load_relaxed(&no_epoll_pwait_cached);
|
||||
no_epoll_wait = uv__load_relaxed(&no_epoll_wait_cached);
|
||||
|
||||
for (;;) {
|
||||
/* Only need to set the provider_entry_time if timeout != 0. The function
|
||||
* will return early if the loop isn't configured with UV_METRICS_IDLE_TIME.
|
||||
*/
|
||||
if (timeout != 0)
|
||||
uv__metrics_set_provider_entry_time(loop);
|
||||
|
||||
/* See the comment for max_safe_timeout for an explanation of why
|
||||
* this is necessary. Executive summary: kernel bug workaround.
|
||||
*/
|
||||
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
|
||||
timeout = max_safe_timeout;
|
||||
|
||||
if (sigmask != 0 && no_epoll_pwait != 0)
|
||||
if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
|
||||
abort();
|
||||
|
||||
if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
|
||||
nfds = epoll_pwait(loop->backend_fd,
|
||||
events,
|
||||
ARRAY_SIZE(events),
|
||||
timeout,
|
||||
&sigset);
|
||||
if (nfds == -1 && errno == ENOSYS) {
|
||||
uv__store_relaxed(&no_epoll_pwait_cached, 1);
|
||||
no_epoll_pwait = 1;
|
||||
}
|
||||
} else {
|
||||
nfds = epoll_wait(loop->backend_fd,
|
||||
events,
|
||||
ARRAY_SIZE(events),
|
||||
timeout);
|
||||
if (nfds == -1 && errno == ENOSYS) {
|
||||
uv__store_relaxed(&no_epoll_wait_cached, 1);
|
||||
no_epoll_wait = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sigmask != 0 && no_epoll_pwait != 0)
|
||||
if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
|
||||
abort();
|
||||
|
||||
/* Update loop->time unconditionally. It's tempting to skip the update when
|
||||
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
|
||||
* operating system didn't reschedule our process while in the syscall.
|
||||
*/
|
||||
SAVE_ERRNO(uv__update_time(loop));
|
||||
|
||||
if (nfds == 0) {
|
||||
assert(timeout != -1);
|
||||
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
}
|
||||
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
|
||||
if (timeout == 0)
|
||||
return;
|
||||
|
||||
/* We may have been inside the system call for longer than |timeout|
|
||||
* milliseconds so we need to update the timestamp to avoid drift.
|
||||
*/
|
||||
goto update_timeout;
|
||||
}
|
||||
|
||||
if (nfds == -1) {
|
||||
if (errno == ENOSYS) {
|
||||
/* epoll_wait() or epoll_pwait() failed, try the other system call. */
|
||||
assert(no_epoll_wait == 0 || no_epoll_pwait == 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (errno != EINTR)
|
||||
abort();
|
||||
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
}
|
||||
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
|
||||
if (timeout == 0)
|
||||
return;
|
||||
|
||||
/* Interrupted by a signal. Update timeout and poll again. */
|
||||
goto update_timeout;
|
||||
}
|
||||
|
||||
have_signals = 0;
|
||||
nevents = 0;
|
||||
|
||||
{
|
||||
/* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */
|
||||
union {
|
||||
struct epoll_event* events;
|
||||
uv__io_t* watchers;
|
||||
} x;
|
||||
|
||||
x.events = events;
|
||||
assert(loop->watchers != NULL);
|
||||
loop->watchers[loop->nwatchers] = x.watchers;
|
||||
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
|
||||
}
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
pe = events + i;
|
||||
fd = pe->data.fd;
|
||||
|
||||
/* Skip invalidated events, see uv__platform_invalidate_fd */
|
||||
if (fd == -1)
|
||||
continue;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert((unsigned) fd < loop->nwatchers);
|
||||
|
||||
w = loop->watchers[fd];
|
||||
|
||||
if (w == NULL) {
|
||||
/* File descriptor that we've stopped watching, disarm it.
|
||||
*
|
||||
* Ignore all errors because we may be racing with another thread
|
||||
* when the file descriptor is closed.
|
||||
*/
|
||||
epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Give users only events they're interested in. Prevents spurious
|
||||
* callbacks when previous callback invocation in this loop has stopped
|
||||
* the current watcher. Also, filters out events that users has not
|
||||
* requested us to watch.
|
||||
*/
|
||||
pe->events &= w->pevents | POLLERR | POLLHUP;
|
||||
|
||||
/* Work around an epoll quirk where it sometimes reports just the
|
||||
* EPOLLERR or EPOLLHUP event. In order to force the event loop to
|
||||
* move forward, we merge in the read/write events that the watcher
|
||||
* is interested in; uv__read() and uv__write() will then deal with
|
||||
* the error or hangup in the usual fashion.
|
||||
*
|
||||
* Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user
|
||||
* reads the available data, calls uv_read_stop(), then sometime later
|
||||
* calls uv_read_start() again. By then, libuv has forgotten about the
|
||||
* hangup and the kernel won't report EPOLLIN again because there's
|
||||
* nothing left to read. If anything, libuv is to blame here. The
|
||||
* current hack is just a quick bandaid; to properly fix it, libuv
|
||||
* needs to remember the error/hangup event. We should get that for
|
||||
* free when we switch over to edge-triggered I/O.
|
||||
*/
|
||||
if (pe->events == POLLERR || pe->events == POLLHUP)
|
||||
pe->events |=
|
||||
w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
|
||||
|
||||
if (pe->events != 0) {
|
||||
/* Run signal watchers last. This also affects child process watchers
|
||||
* because those are implemented in terms of signal watchers.
|
||||
*/
|
||||
if (w == &loop->signal_io_watcher) {
|
||||
have_signals = 1;
|
||||
} else {
|
||||
uv__metrics_update_idle_time(loop);
|
||||
w->cb(loop, w, pe->events);
|
||||
}
|
||||
|
||||
nevents++;
|
||||
}
|
||||
}
|
||||
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
}
|
||||
|
||||
if (have_signals != 0) {
|
||||
uv__metrics_update_idle_time(loop);
|
||||
loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
|
||||
}
|
||||
|
||||
loop->watchers[loop->nwatchers] = NULL;
|
||||
loop->watchers[loop->nwatchers + 1] = NULL;
|
||||
|
||||
if (have_signals != 0)
|
||||
return; /* Event loop should cycle now so don't poll again. */
|
||||
|
||||
if (nevents != 0) {
|
||||
if (nfds == ARRAY_SIZE(events) && --count != 0) {
|
||||
/* Poll for more events but don't block this time. */
|
||||
timeout = 0;
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
return;
|
||||
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
|
||||
update_timeout:
|
||||
assert(timeout > 0);
|
||||
|
||||
real_timeout -= (loop->time - base);
|
||||
if (real_timeout <= 0)
|
||||
return;
|
||||
|
||||
timeout = real_timeout;
|
||||
}
|
||||
}
|
||||
|
33
deps/libuv/src/unix/freebsd.c
vendored
33
deps/libuv/src/unix/freebsd.c
vendored
@ -91,7 +91,7 @@ uint64_t uv_get_free_memory(void) {
|
||||
size_t size = sizeof(freecount);
|
||||
|
||||
if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0))
|
||||
return UV__ERR(errno);
|
||||
return 0;
|
||||
|
||||
return (uint64_t) freecount * sysconf(_SC_PAGESIZE);
|
||||
|
||||
@ -105,7 +105,7 @@ uint64_t uv_get_total_memory(void) {
|
||||
size_t size = sizeof(info);
|
||||
|
||||
if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
|
||||
return UV__ERR(errno);
|
||||
return 0;
|
||||
|
||||
return (uint64_t) info;
|
||||
}
|
||||
@ -116,6 +116,11 @@ uint64_t uv_get_constrained_memory(void) {
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_available_memory(void) {
|
||||
return uv_get_free_memory();
|
||||
}
|
||||
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
struct loadavg info;
|
||||
size_t size = sizeof(info);
|
||||
@ -264,30 +269,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
}
|
||||
|
||||
|
||||
int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
|
||||
#if __FreeBSD__ >= 11 && !defined(__DragonFly__)
|
||||
return sendmmsg(fd,
|
||||
(struct mmsghdr*) mmsg,
|
||||
vlen,
|
||||
0 /* flags */);
|
||||
#else
|
||||
return errno = ENOSYS, -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
|
||||
#if __FreeBSD__ >= 11 && !defined(__DragonFly__)
|
||||
return recvmmsg(fd,
|
||||
(struct mmsghdr*) mmsg,
|
||||
vlen,
|
||||
0 /* flags */,
|
||||
NULL /* timeout */);
|
||||
#else
|
||||
return errno = ENOSYS, -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t
|
||||
uv__fs_copy_file_range(int fd_in,
|
||||
off_t* off_in,
|
||||
|
222
deps/libuv/src/unix/fs.c
vendored
222
deps/libuv/src/unix/fs.c
vendored
@ -48,7 +48,6 @@
|
||||
|
||||
#if defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
# define HAVE_PREADV 1
|
||||
@ -56,11 +55,16 @@
|
||||
# define HAVE_PREADV 0
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
# include "sys/utsname.h"
|
||||
/* preadv() and pwritev() were added in Android N (level 24) */
|
||||
#if defined(__linux__) && !(defined(__ANDROID__) && __ANDROID_API__ < 24)
|
||||
# define TRY_PREADV 1
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__sun)
|
||||
#if defined(__linux__)
|
||||
# include <sys/sendfile.h>
|
||||
#endif
|
||||
|
||||
#if defined(__sun)
|
||||
# include <sys/sendfile.h>
|
||||
# include <sys/sysmacros.h>
|
||||
#endif
|
||||
@ -79,7 +83,6 @@
|
||||
#if defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
# include <sys/param.h>
|
||||
@ -256,7 +259,6 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
|
||||
#elif defined(__APPLE__) \
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
|| defined(__FreeBSD_kernel__) \
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__sun)
|
||||
@ -311,7 +313,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
|
||||
static uv_once_t once = UV_ONCE_INIT;
|
||||
int r;
|
||||
#ifdef O_CLOEXEC
|
||||
static int no_cloexec_support;
|
||||
static _Atomic int no_cloexec_support;
|
||||
#endif
|
||||
static const char pattern[] = "XXXXXX";
|
||||
static const size_t pattern_size = sizeof(pattern) - 1;
|
||||
@ -336,7 +338,8 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
|
||||
uv_once(&once, uv__mkostemp_initonce);
|
||||
|
||||
#ifdef O_CLOEXEC
|
||||
if (uv__load_relaxed(&no_cloexec_support) == 0 && uv__mkostemp != NULL) {
|
||||
if (atomic_load_explicit(&no_cloexec_support, memory_order_relaxed) == 0 &&
|
||||
uv__mkostemp != NULL) {
|
||||
r = uv__mkostemp(path, O_CLOEXEC);
|
||||
|
||||
if (r >= 0)
|
||||
@ -349,7 +352,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
|
||||
|
||||
/* We set the static variable so that next calls don't even
|
||||
try to use mkostemp. */
|
||||
uv__store_relaxed(&no_cloexec_support, 1);
|
||||
atomic_store_explicit(&no_cloexec_support, 1, memory_order_relaxed);
|
||||
}
|
||||
#endif /* O_CLOEXEC */
|
||||
|
||||
@ -458,8 +461,8 @@ static ssize_t uv__fs_preadv(uv_file fd,
|
||||
|
||||
|
||||
static ssize_t uv__fs_read(uv_fs_t* req) {
|
||||
#if defined(__linux__)
|
||||
static int no_preadv;
|
||||
#if TRY_PREADV
|
||||
static _Atomic int no_preadv;
|
||||
#endif
|
||||
unsigned int iovmax;
|
||||
ssize_t result;
|
||||
@ -482,20 +485,20 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
|
||||
#if HAVE_PREADV
|
||||
result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
|
||||
#else
|
||||
# if defined(__linux__)
|
||||
if (uv__load_relaxed(&no_preadv)) retry:
|
||||
# if TRY_PREADV
|
||||
if (atomic_load_explicit(&no_preadv, memory_order_relaxed)) retry:
|
||||
# endif
|
||||
{
|
||||
result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off);
|
||||
}
|
||||
# if defined(__linux__)
|
||||
# if TRY_PREADV
|
||||
else {
|
||||
result = uv__preadv(req->file,
|
||||
(struct iovec*)req->bufs,
|
||||
req->nbufs,
|
||||
req->off);
|
||||
result = preadv(req->file,
|
||||
(struct iovec*) req->bufs,
|
||||
req->nbufs,
|
||||
req->off);
|
||||
if (result == -1 && errno == ENOSYS) {
|
||||
uv__store_relaxed(&no_preadv, 1);
|
||||
atomic_store_explicit(&no_preadv, 1, memory_order_relaxed);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
@ -516,7 +519,7 @@ done:
|
||||
if (result == -1 && errno == EOPNOTSUPP) {
|
||||
struct stat buf;
|
||||
ssize_t rc;
|
||||
rc = fstat(req->file, &buf);
|
||||
rc = uv__fstat(req->file, &buf);
|
||||
if (rc == 0 && S_ISDIR(buf.st_mode)) {
|
||||
errno = EISDIR;
|
||||
}
|
||||
@ -527,19 +530,12 @@ done:
|
||||
}
|
||||
|
||||
|
||||
#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)
|
||||
#define UV_CONST_DIRENT uv__dirent_t
|
||||
#else
|
||||
#define UV_CONST_DIRENT const uv__dirent_t
|
||||
#endif
|
||||
|
||||
|
||||
static int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) {
|
||||
static int uv__fs_scandir_filter(const uv__dirent_t* dent) {
|
||||
return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
|
||||
}
|
||||
|
||||
|
||||
static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
|
||||
static int uv__fs_scandir_sort(const uv__dirent_t** a, const uv__dirent_t** b) {
|
||||
return strcmp((*a)->d_name, (*b)->d_name);
|
||||
}
|
||||
|
||||
@ -715,7 +711,7 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
||||
/* We may not have a real PATH_MAX. Read size of link. */
|
||||
struct stat st;
|
||||
int ret;
|
||||
ret = lstat(req->path, &st);
|
||||
ret = uv__lstat(req->path, &st);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
if (!S_ISLNK(st.st_mode)) {
|
||||
@ -907,31 +903,6 @@ out:
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
static unsigned uv__kernel_version(void) {
|
||||
static unsigned cached_version;
|
||||
struct utsname u;
|
||||
unsigned version;
|
||||
unsigned major;
|
||||
unsigned minor;
|
||||
unsigned patch;
|
||||
|
||||
version = uv__load_relaxed(&cached_version);
|
||||
if (version != 0)
|
||||
return version;
|
||||
|
||||
if (-1 == uname(&u))
|
||||
return 0;
|
||||
|
||||
if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch))
|
||||
return 0;
|
||||
|
||||
version = major * 65536 + minor * 256 + patch;
|
||||
uv__store_relaxed(&cached_version, version);
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
/* Pre-4.20 kernels have a bug where CephFS uses the RADOS copy-from command
|
||||
* in copy_file_range() when it shouldn't. There is no workaround except to
|
||||
* fall back to a regular copy.
|
||||
@ -968,10 +939,10 @@ static int uv__is_cifs_or_smb(int fd) {
|
||||
|
||||
static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off,
|
||||
int out_fd, size_t len) {
|
||||
static int no_copy_file_range_support;
|
||||
static _Atomic int no_copy_file_range_support;
|
||||
ssize_t r;
|
||||
|
||||
if (uv__load_relaxed(&no_copy_file_range_support)) {
|
||||
if (atomic_load_explicit(&no_copy_file_range_support, memory_order_relaxed)) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
@ -990,7 +961,7 @@ static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off,
|
||||
errno = ENOSYS; /* Use fallback. */
|
||||
break;
|
||||
case ENOSYS:
|
||||
uv__store_relaxed(&no_copy_file_range_support, 1);
|
||||
atomic_store_explicit(&no_copy_file_range_support, 1, memory_order_relaxed);
|
||||
break;
|
||||
case EPERM:
|
||||
/* It's been reported that CIFS spuriously fails.
|
||||
@ -1061,10 +1032,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
#elif defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__)
|
||||
#elif defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
{
|
||||
off_t len;
|
||||
ssize_t r;
|
||||
@ -1088,15 +1056,6 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
||||
#endif
|
||||
len = 0;
|
||||
r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
|
||||
#elif defined(__FreeBSD_kernel__)
|
||||
len = 0;
|
||||
r = bsd_sendfile(in_fd,
|
||||
out_fd,
|
||||
req->off,
|
||||
req->bufsml[0].len,
|
||||
NULL,
|
||||
&len,
|
||||
0);
|
||||
#else
|
||||
/* The darwin sendfile takes len as an input for the length to send,
|
||||
* so make sure to initialize it with the caller's value. */
|
||||
@ -1148,7 +1107,6 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
#elif defined(__APPLE__) \
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
|| defined(__FreeBSD_kernel__) \
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__)
|
||||
struct timeval tv[2];
|
||||
@ -1190,7 +1148,6 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) {
|
||||
#elif defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__)
|
||||
struct timeval tv[2];
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
@ -1204,8 +1161,8 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) {
|
||||
|
||||
|
||||
static ssize_t uv__fs_write(uv_fs_t* req) {
|
||||
#if defined(__linux__)
|
||||
static int no_pwritev;
|
||||
#if TRY_PREADV
|
||||
static _Atomic int no_pwritev;
|
||||
#endif
|
||||
ssize_t r;
|
||||
|
||||
@ -1233,20 +1190,20 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
|
||||
#if HAVE_PREADV
|
||||
r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
|
||||
#else
|
||||
# if defined(__linux__)
|
||||
if (no_pwritev) retry:
|
||||
# if TRY_PREADV
|
||||
if (atomic_load_explicit(&no_pwritev, memory_order_relaxed)) retry:
|
||||
# endif
|
||||
{
|
||||
r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
|
||||
}
|
||||
# if defined(__linux__)
|
||||
# if TRY_PREADV
|
||||
else {
|
||||
r = uv__pwritev(req->file,
|
||||
(struct iovec*) req->bufs,
|
||||
req->nbufs,
|
||||
req->off);
|
||||
r = pwritev(req->file,
|
||||
(struct iovec*) req->bufs,
|
||||
req->nbufs,
|
||||
req->off);
|
||||
if (r == -1 && errno == ENOSYS) {
|
||||
no_pwritev = 1;
|
||||
atomic_store_explicit(&no_pwritev, 1, memory_order_relaxed);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
@ -1288,7 +1245,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
return srcfd;
|
||||
|
||||
/* Get the source file's mode. */
|
||||
if (fstat(srcfd, &src_statsbuf)) {
|
||||
if (uv__fstat(srcfd, &src_statsbuf)) {
|
||||
err = UV__ERR(errno);
|
||||
goto out;
|
||||
}
|
||||
@ -1316,7 +1273,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
destination are not the same file. If they are the same, bail out early. */
|
||||
if ((req->flags & UV_FS_COPYFILE_EXCL) == 0) {
|
||||
/* Get the destination file's mode. */
|
||||
if (fstat(dstfd, &dst_statsbuf)) {
|
||||
if (uv__fstat(dstfd, &dst_statsbuf)) {
|
||||
err = UV__ERR(errno);
|
||||
goto out;
|
||||
}
|
||||
@ -1330,7 +1287,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
/* Truncate the file in case the destination already existed. */
|
||||
if (ftruncate(dstfd, 0) != 0) {
|
||||
err = UV__ERR(errno);
|
||||
goto out;
|
||||
|
||||
/* ftruncate() on ceph-fuse fails with EACCES when the file is created
|
||||
* with read only permissions. Since ftruncate() on a newly created
|
||||
* file is a meaningless operation anyway, detect that condition
|
||||
* and squelch the error.
|
||||
*/
|
||||
if (err != UV_EACCES)
|
||||
goto out;
|
||||
|
||||
if (dst_statsbuf.st_size > 0)
|
||||
goto out;
|
||||
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1514,14 +1483,14 @@ static int uv__fs_statx(int fd,
|
||||
uv_stat_t* buf) {
|
||||
STATIC_ASSERT(UV_ENOSYS != -1);
|
||||
#ifdef __linux__
|
||||
static int no_statx;
|
||||
static _Atomic int no_statx;
|
||||
struct uv__statx statxbuf;
|
||||
int dirfd;
|
||||
int flags;
|
||||
int mode;
|
||||
int rc;
|
||||
|
||||
if (uv__load_relaxed(&no_statx))
|
||||
if (atomic_load_explicit(&no_statx, memory_order_relaxed))
|
||||
return UV_ENOSYS;
|
||||
|
||||
dirfd = AT_FDCWD;
|
||||
@ -1555,30 +1524,11 @@ static int uv__fs_statx(int fd,
|
||||
* implemented, rc might return 1 with 0 set as the error code in which
|
||||
* case we return ENOSYS.
|
||||
*/
|
||||
uv__store_relaxed(&no_statx, 1);
|
||||
atomic_store_explicit(&no_statx, 1, memory_order_relaxed);
|
||||
return UV_ENOSYS;
|
||||
}
|
||||
|
||||
buf->st_dev = makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor);
|
||||
buf->st_mode = statxbuf.stx_mode;
|
||||
buf->st_nlink = statxbuf.stx_nlink;
|
||||
buf->st_uid = statxbuf.stx_uid;
|
||||
buf->st_gid = statxbuf.stx_gid;
|
||||
buf->st_rdev = makedev(statxbuf.stx_rdev_major, statxbuf.stx_rdev_minor);
|
||||
buf->st_ino = statxbuf.stx_ino;
|
||||
buf->st_size = statxbuf.stx_size;
|
||||
buf->st_blksize = statxbuf.stx_blksize;
|
||||
buf->st_blocks = statxbuf.stx_blocks;
|
||||
buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec;
|
||||
buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec;
|
||||
buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec;
|
||||
buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec;
|
||||
buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec;
|
||||
buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec;
|
||||
buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec;
|
||||
buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec;
|
||||
buf->st_flags = 0;
|
||||
buf->st_gen = 0;
|
||||
uv__statx_to_stat(&statxbuf, buf);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
@ -1595,7 +1545,7 @@ static int uv__fs_stat(const char *path, uv_stat_t *buf) {
|
||||
if (ret != UV_ENOSYS)
|
||||
return ret;
|
||||
|
||||
ret = stat(path, &pbuf);
|
||||
ret = uv__stat(path, &pbuf);
|
||||
if (ret == 0)
|
||||
uv__to_stat(&pbuf, buf);
|
||||
|
||||
@ -1611,7 +1561,7 @@ static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
|
||||
if (ret != UV_ENOSYS)
|
||||
return ret;
|
||||
|
||||
ret = lstat(path, &pbuf);
|
||||
ret = uv__lstat(path, &pbuf);
|
||||
if (ret == 0)
|
||||
uv__to_stat(&pbuf, buf);
|
||||
|
||||
@ -1627,7 +1577,7 @@ static int uv__fs_fstat(int fd, uv_stat_t *buf) {
|
||||
if (ret != UV_ENOSYS)
|
||||
return ret;
|
||||
|
||||
ret = fstat(fd, &pbuf);
|
||||
ret = uv__fstat(fd, &pbuf);
|
||||
if (ret == 0)
|
||||
uv__to_stat(&pbuf, buf);
|
||||
|
||||
@ -1822,6 +1772,9 @@ int uv_fs_chown(uv_loop_t* loop,
|
||||
int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
|
||||
INIT(CLOSE);
|
||||
req->file = file;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_close(loop, req))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -1869,6 +1822,9 @@ int uv_fs_lchown(uv_loop_t* loop,
|
||||
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
|
||||
INIT(FDATASYNC);
|
||||
req->file = file;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_fsync_or_fdatasync(loop, req, /* IORING_FSYNC_DATASYNC */ 1))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -1876,6 +1832,9 @@ int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
|
||||
int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
|
||||
INIT(FSTAT);
|
||||
req->file = file;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_statx(loop, req, /* is_fstat */ 1, /* is_lstat */ 0))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -1883,6 +1842,9 @@ int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
|
||||
int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
|
||||
INIT(FSYNC);
|
||||
req->file = file;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_fsync_or_fdatasync(loop, req, /* no flags */ 0))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -1929,6 +1891,9 @@ int uv_fs_lutime(uv_loop_t* loop,
|
||||
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
INIT(LSTAT);
|
||||
PATH;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_statx(loop, req, /* is_fstat */ 0, /* is_lstat */ 1))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -1940,6 +1905,9 @@ int uv_fs_link(uv_loop_t* loop,
|
||||
uv_fs_cb cb) {
|
||||
INIT(LINK);
|
||||
PATH2;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_link(loop, req))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -1952,6 +1920,9 @@ int uv_fs_mkdir(uv_loop_t* loop,
|
||||
INIT(MKDIR);
|
||||
PATH;
|
||||
req->mode = mode;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_mkdir(loop, req))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -1990,6 +1961,9 @@ int uv_fs_open(uv_loop_t* loop,
|
||||
PATH;
|
||||
req->flags = flags;
|
||||
req->mode = mode;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_open(loop, req))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -2018,6 +1992,11 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
|
||||
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
|
||||
|
||||
req->off = off;
|
||||
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 1))
|
||||
return 0;
|
||||
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -2095,6 +2074,9 @@ int uv_fs_rename(uv_loop_t* loop,
|
||||
uv_fs_cb cb) {
|
||||
INIT(RENAME);
|
||||
PATH2;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_rename(loop, req))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -2125,6 +2107,9 @@ int uv_fs_sendfile(uv_loop_t* loop,
|
||||
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
INIT(STAT);
|
||||
PATH;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_statx(loop, req, /* is_fstat */ 0, /* is_lstat */ 0))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -2138,6 +2123,9 @@ int uv_fs_symlink(uv_loop_t* loop,
|
||||
INIT(SYMLINK);
|
||||
PATH2;
|
||||
req->flags = flags;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_symlink(loop, req))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -2145,6 +2133,9 @@ int uv_fs_symlink(uv_loop_t* loop,
|
||||
int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
INIT(UNLINK);
|
||||
PATH;
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_unlink(loop, req))
|
||||
return 0;
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -2188,6 +2179,11 @@ int uv_fs_write(uv_loop_t* loop,
|
||||
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
|
||||
|
||||
req->off = off;
|
||||
|
||||
if (cb != NULL)
|
||||
if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 0))
|
||||
return 0;
|
||||
|
||||
POST;
|
||||
}
|
||||
|
||||
@ -2196,7 +2192,7 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
|
||||
if (req == NULL)
|
||||
return;
|
||||
|
||||
/* Only necessary for asychronous requests, i.e., requests with a callback.
|
||||
/* Only necessary for asynchronous requests, i.e., requests with a callback.
|
||||
* Synchronous ones don't copy their arguments and have req->path and
|
||||
* req->new_path pointing to user-owned memory. UV_FS_MKDTEMP and
|
||||
* UV_FS_MKSTEMP are the exception to the rule, they always allocate memory.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user