diff --git a/examples/http_client.js b/examples/http_client.js
index 35bf4fe..33a348f 100644
--- a/examples/http_client.js
+++ b/examples/http_client.js
@@ -2,18 +2,24 @@
///@ts-check
///
///
+///
import * as os from "os";
+import * as std from "std";
+
/** @template T @param {os.Result} result */
function must(result) {
- if (typeof result === "number" && result < 0) throw result;
+ if (typeof result === "number" && result < 0) throw new Error(std.strerror(-result));
return /** @type {T} */ (result)
}
-
-const sockfd = must(os.socket(os.AF_INET, os.SOCK_STREAM));
-const addr = os.getaddrinfo("bellard.org",'80').find(a => a.family == os.AF_INET);
+//USAGE: client.js wttr.in/paris
+const uriRegexp = /^(?[A-Za-z0-9\-\.]+)(?:[0-9]+)?(?.*)$/;
+const { host = "bellard.org", port = ":80", query = "/" } = scriptArgs[1]?.match(uriRegexp)?.groups || {};
+console.log("sending GET on",{ host, port, query })
+const [addr] = must(os.getaddrinfo(host, { service: port.slice(1) }));
+const sockfd = must(os.socket(addr.family, addr.socktype));
await os.connect(sockfd, addr);
-const httpReq = Uint8Array.from("GET / HTTP/1.0\r\n\r\n", c => c.charCodeAt(0))
+const httpReq = Uint8Array.from(`GET ${query||'/'} HTTP/1.0\r\nHost: ${host}\r\nUser-Agent: curl\r\n\r\n`, c => c.charCodeAt(0))
must(await os.send(sockfd, httpReq.buffer) > 0);
const chunk = new Uint8Array(512);
const recvd = await os.recv(sockfd, chunk.buffer);
-console.log([...chunk.slice(0,recvd)].map(c => String.fromCharCode(c)).join(''));
+console.log([...chunk.slice(0, recvd)].map(c => String.fromCharCode(c)).join(''));
diff --git a/examples/http_server.js b/examples/http_server.js
index a4d63aa..b38265f 100755
--- a/examples/http_server.js
+++ b/examples/http_server.js
@@ -2,7 +2,9 @@
///@ts-check
///
///
+///
import * as os from "os";
+import * as std from "std";// for std.strerror
const MIMES = new Map([
['html', 'text/html'],
@@ -17,7 +19,7 @@ const MIMES = new Map([
]);
/** @template T @param {os.Result} result */
function must(result) {
- if (typeof result === "number" && result < 0) throw result;
+ if (typeof result === "number" && result < 0) throw new Error(std.strerror(-result));
return /** @type {T} */ (result)
}
/**@param {os.FileDescriptor} fd */
@@ -40,7 +42,7 @@ function sendLines(fd, lines) {
}
//USAGE: qjs http_server.js [PORT=8080 [HOST=localhost]]
const [port = "8080", host = "localhost"] = scriptArgs.slice(1);
-const ai = os.getaddrinfo(host, port).find(a => a.family == os.AF_INET);
+const [ai] = must(os.getaddrinfo(host, { service: port }));
//if (!ai.length) throw `Unable to getaddrinfo(${host}, ${port})`;
const sock_srv = must(os.socket(os.AF_INET, os.SOCK_STREAM));
must(os.setsockopt(sock_srv, os.SO_REUSEADDR, new Uint32Array([1]).buffer));
diff --git a/quickjs-libc.c b/quickjs-libc.c
index 8786157..fb0f3e1 100644
--- a/quickjs-libc.c
+++ b/quickjs-libc.c
@@ -3710,27 +3710,42 @@ static JSValue js_os_get_setsockopt(JSContext *ctx, JSValueConst this_val,
static JSValue js_os_getaddrinfo(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
- int ret;
- socklen_t objLen;
- JSValue obj, addrObj;
- const char* node = NULL;
+ int ret = -1;
+ if (!JS_IsString(argv[0]))
+ return JS_EXCEPTION;
+ const char* node = JS_ToCString(ctx, argv[0]);
+
const char* service = NULL;
- struct addrinfo *ai,*it;
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ if (!JS_IsNull(argv[1]) && JS_IsObject(argv[1])) {
+ JSValue prop_service = JS_GetPropertyStr(ctx, argv[1], "service");
+ JSValue prop_family = JS_GetPropertyStr(ctx, argv[1], "family");
+ JSValue prop_socktype = JS_GetPropertyStr(ctx, argv[1], "socktype");
+ if (JS_IsException(prop_service) ||
+ JS_IsException(prop_family) ||
+ JS_IsException(prop_socktype))
+ goto fail;
+ if (!JS_IsUndefined(prop_service))
+ service = JS_ToCString(ctx, prop_service);
+ if (!JS_IsUndefined(prop_family))
+ JS_ToInt32(ctx, &hints.ai_family, prop_family);
+ if (!JS_IsUndefined(prop_socktype))
+ JS_ToInt32(ctx, &hints.ai_socktype, prop_socktype);
+ }
- if (!JS_IsNull(argv[0]) && !JS_IsUndefined(argv[0]))
- node = JS_ToCString(ctx, argv[0]);
-
- service = JS_ToCString(ctx, argv[1]);
- if (!service)
- goto fail;
-
- ret = js_get_sockerrno(getaddrinfo(node, service, NULL, &ai));
+ struct addrinfo *ai;
+ ret = js_get_sockerrno(getaddrinfo(node, service, &hints, &ai));
if (ret)
goto fail;
- obj = JS_NewArray(ctx);
+ struct addrinfo *it;
+ socklen_t objLen;
+ JSValue obj = JS_NewArray(ctx);
for (objLen = 0, it = ai; it; it = it->ai_next, objLen++) {
- addrObj = JS_ToSockaddrObj(ctx,(struct sockaddr_storage *)it->ai_addr);
+ JSValue addrObj = JS_ToSockaddrObj(ctx,(struct sockaddr_storage *)it->ai_addr);
+ JSValue prop_socktype = JS_NewUint32(ctx, it->ai_socktype);
+ JS_DefinePropertyValueStr(ctx, addrObj, "socktype", prop_socktype, JS_PROP_C_W_E);
JS_SetPropertyUint32(ctx,obj,objLen,addrObj);
}
@@ -3742,7 +3757,7 @@ fail:
JS_FreeValue(ctx, obj);
JS_FreeCString(ctx, service);
JS_FreeCString(ctx, node);
- return JS_EXCEPTION;
+ return JS_NewInt32(ctx, ret);
}
static JSValue js_os_bind(JSContext *ctx, JSValueConst this_val,