diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c0f7e8a0221d6..3a8f3f7717c277 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,8 @@ release. -18.20.2
+18.20.3
+18.20.2
18.20.1
18.20.0
18.19.1
diff --git a/README.md b/README.md index 62432860a15041..438d970948e1eb 100644 --- a/README.md +++ b/README.md @@ -745,6 +745,8 @@ Primary GPG keys for Node.js Releasers (some Releasers sign with subkeys): `74F12602B6F1C4E913FAA37AD3A89613643B6201` * **Juan José Arboleda** <> `DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7` +* **Marco Ippolito** <> + `CC68F5A3106FF448322E48ED27F5E38D5B0A215F` * **Michaël Zasso** <> `8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600` * **Myles Borins** <> @@ -766,6 +768,7 @@ gpg --keyserver hkps://keys.openpgp.org --recv-keys 4ED778F539E3634C779C87C6D706 gpg --keyserver hkps://keys.openpgp.org --recv-keys 141F07595B7B3FFE74309A937405533BE57C7D57 gpg --keyserver hkps://keys.openpgp.org --recv-keys 74F12602B6F1C4E913FAA37AD3A89613643B6201 gpg --keyserver hkps://keys.openpgp.org --recv-keys DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 +gpg --keyserver hkps://keys.openpgp.org --recv-keys CC68F5A3106FF448322E48ED27F5E38D5B0A215F gpg --keyserver hkps://keys.openpgp.org --recv-keys 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 gpg --keyserver hkps://keys.openpgp.org --recv-keys C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 gpg --keyserver hkps://keys.openpgp.org --recv-keys 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 diff --git a/common.gypi b/common.gypi index 38471d4639eb5e..ec92c9df4c1ea2 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.36', + 'v8_embedder_string': '-node.37', ##### V8 defaults for Node.js ##### diff --git a/deps/acorn/acorn-walk/CHANGELOG.md b/deps/acorn/acorn-walk/CHANGELOG.md index 30ec5a5eec9911..0b4eea8a95d3ed 100644 --- a/deps/acorn/acorn-walk/CHANGELOG.md +++ b/deps/acorn/acorn-walk/CHANGELOG.md @@ -1,3 +1,17 @@ +## 8.3.1 (2023-12-06) + +### Bug fixes + +Add `Function` and `Class` to the `AggregateType` type, so that they can be used in walkers without raising a type error. + +Visitor functions are now called in such a way that their `this` refers to the object they are part of. + +## 8.3.0 (2023-10-26) + +### New features + +Use a set of new, much more precise, TypeScript types. + ## 8.2.0 (2021-09-06) ### New features diff --git a/deps/acorn/acorn-walk/README.md b/deps/acorn/acorn-walk/README.md index e192baced005ac..3c18a2c76a938e 100644 --- a/deps/acorn/acorn-walk/README.md +++ b/deps/acorn/acorn-walk/README.md @@ -10,9 +10,7 @@ Acorn is open source software released under an You are welcome to [report bugs](https://github.com/acornjs/acorn/issues) or create pull -requests on [github](https://github.com/acornjs/acorn). For questions -and discussion, please use the -[Tern discussion forum](https://discuss.ternjs.net). +requests on [github](https://github.com/acornjs/acorn). ## Installation @@ -68,7 +66,7 @@ const acorn = require("acorn") const walk = require("acorn-walk") walk.ancestor(acorn.parse("foo('hi')"), { - Literal(_, ancestors) { + Literal(_node, _state, ancestors) { console.log("This literal's ancestors are:", ancestors.map(n => n.type)) } }) diff --git a/deps/acorn/acorn-walk/dist/walk.d.mts b/deps/acorn/acorn-walk/dist/walk.d.mts new file mode 100644 index 00000000000000..e07a6afaf8e336 --- /dev/null +++ b/deps/acorn/acorn-walk/dist/walk.d.mts @@ -0,0 +1,177 @@ +import * as acorn from "acorn" + +export type FullWalkerCallback = ( + node: acorn.Node, + state: TState, + type: string +) => void + +export type FullAncestorWalkerCallback = ( + node: acorn.Node, + state: TState, + ancestors: acorn.Node[], + type: string +) => void + +type AggregateType = { + Expression: acorn.Expression, + Statement: acorn.Statement, + Function: acorn.Function, + Class: acorn.Class, + Pattern: acorn.Pattern, + ForInit: acorn.VariableDeclaration | acorn.Expression +} + +export type SimpleVisitors = { + [type in acorn.AnyNode["type"]]?: (node: Extract, state: TState) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState) => void +} + +export type AncestorVisitors = { + [type in acorn.AnyNode["type"]]?: ( node: Extract, state: TState, ancestors: acorn.Node[] +) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState, ancestors: acorn.Node[]) => void +} + +export type WalkerCallback = (node: acorn.Node, state: TState) => void + +export type RecursiveVisitors = { + [type in acorn.AnyNode["type"]]?: ( node: Extract, state: TState, callback: WalkerCallback) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState, callback: WalkerCallback) => void +} + +export type FindPredicate = (type: string, node: acorn.Node) => boolean + +export interface Found { + node: acorn.Node, + state: TState +} + +/** + * does a 'simple' walk over a tree + * @param node the AST node to walk + * @param visitors an object with properties whose names correspond to node types in the {@link https://github.com/estree/estree | ESTree spec}. The properties should contain functions that will be called with the node object and, if applicable the state at that point. + * @param base a walker algorithm + * @param state a start state. The default walker will simply visit all statements and expressions and not produce a meaningful state. (An example of a use of state is to track scope at each point in the tree.) + */ +export function simple( + node: acorn.Node, + visitors: SimpleVisitors, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * does a 'simple' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter. + * @param node + * @param visitors + * @param base + * @param state + */ +export function ancestor( + node: acorn.Node, + visitors: AncestorVisitors, + base?: RecursiveVisitors, + state?: TState + ): void + +/** + * does a 'recursive' walk, where the walker functions are responsible for continuing the walk on the child nodes of their target node. + * @param node + * @param state the start state + * @param functions contain an object that maps node types to walker functions + * @param base provides the fallback walker functions for node types that aren't handled in the {@link functions} object. If not given, the default walkers will be used. + */ +export function recursive( + node: acorn.Node, + state: TState, + functions: RecursiveVisitors, + base?: RecursiveVisitors +): void + +/** + * does a 'full' walk over a tree, calling the {@link callback} with the arguments (node, state, type) for each node + * @param node + * @param callback + * @param base + * @param state + */ +export function full( + node: acorn.Node, + callback: FullWalkerCallback, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * does a 'full' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter. + * @param node + * @param callback + * @param base + * @param state + */ +export function fullAncestor( + node: acorn.Node, + callback: FullAncestorWalkerCallback, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * builds a new walker object by using the walker functions in {@link functions} and filling in the missing ones by taking defaults from {@link base}. + * @param functions + * @param base + */ +export function make( + functions: RecursiveVisitors, + base?: RecursiveVisitors +): RecursiveVisitors + +/** + * tries to locate a node in a tree at the given start and/or end offsets, which satisfies the predicate test. {@link start} and {@link end} can be either `null` (as wildcard) or a `number`. {@link test} may be a string (indicating a node type) or a function that takes (nodeType, node) arguments and returns a boolean indicating whether this node is interesting. {@link base} and {@link state} are optional, and can be used to specify a custom walker. Nodes are tested from inner to outer, so if two nodes match the boundaries, the inner one will be preferred. + * @param node + * @param start + * @param end + * @param type + * @param base + * @param state + */ +export function findNodeAt( + node: acorn.Node, + start: number | undefined, + end?: number | undefined, + type?: FindPredicate | string, + base?: RecursiveVisitors, + state?: TState +): Found | undefined + +/** + * like {@link findNodeAt}, but will match any node that exists 'around' (spanning) the given position. + * @param node + * @param start + * @param type + * @param base + * @param state + */ +export function findNodeAround( + node: acorn.Node, + start: number | undefined, + type?: FindPredicate | string, + base?: RecursiveVisitors, + state?: TState +): Found | undefined + +/** + * Find the outermost matching node after a given position. + */ +export const findNodeAfter: typeof findNodeAround + +/** + * Find the outermost matching node before a given position. + */ +export const findNodeBefore: typeof findNodeAround + +export const base: RecursiveVisitors diff --git a/deps/acorn/acorn-walk/dist/walk.d.ts b/deps/acorn/acorn-walk/dist/walk.d.ts index 2d81f01c166875..e07a6afaf8e336 100644 --- a/deps/acorn/acorn-walk/dist/walk.d.ts +++ b/deps/acorn/acorn-walk/dist/walk.d.ts @@ -1,114 +1,177 @@ -import {Node} from 'acorn'; - -declare module "acorn-walk" { - type FullWalkerCallback = ( - node: Node, - state: TState, - type: string - ) => void; - - type FullAncestorWalkerCallback = ( - node: Node, - state: TState | Node[], - ancestors: Node[], - type: string - ) => void; - type WalkerCallback = (node: Node, state: TState) => void; - - type SimpleWalkerFn = ( - node: Node, - state: TState - ) => void; - - type AncestorWalkerFn = ( - node: Node, - state: TState| Node[], - ancestors: Node[] - ) => void; - - type RecursiveWalkerFn = ( - node: Node, - state: TState, - callback: WalkerCallback - ) => void; - - type SimpleVisitors = { - [type: string]: SimpleWalkerFn - }; - - type AncestorVisitors = { - [type: string]: AncestorWalkerFn - }; - - type RecursiveVisitors = { - [type: string]: RecursiveWalkerFn - }; - - type FindPredicate = (type: string, node: Node) => boolean; - - interface Found { - node: Node, - state: TState - } - - export function simple( - node: Node, - visitors: SimpleVisitors, - base?: RecursiveVisitors, - state?: TState - ): void; +import * as acorn from "acorn" + +export type FullWalkerCallback = ( + node: acorn.Node, + state: TState, + type: string +) => void + +export type FullAncestorWalkerCallback = ( + node: acorn.Node, + state: TState, + ancestors: acorn.Node[], + type: string +) => void + +type AggregateType = { + Expression: acorn.Expression, + Statement: acorn.Statement, + Function: acorn.Function, + Class: acorn.Class, + Pattern: acorn.Pattern, + ForInit: acorn.VariableDeclaration | acorn.Expression +} - export function ancestor( - node: Node, - visitors: AncestorVisitors, - base?: RecursiveVisitors, - state?: TState - ): void; - - export function recursive( - node: Node, - state: TState, - functions: RecursiveVisitors, - base?: RecursiveVisitors - ): void; - - export function full( - node: Node, - callback: FullWalkerCallback, - base?: RecursiveVisitors, - state?: TState - ): void; +export type SimpleVisitors = { + [type in acorn.AnyNode["type"]]?: (node: Extract, state: TState) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState) => void +} - export function fullAncestor( - node: Node, - callback: FullAncestorWalkerCallback, - base?: RecursiveVisitors, - state?: TState - ): void; - - export function make( - functions: RecursiveVisitors, - base?: RecursiveVisitors - ): RecursiveVisitors; - - export function findNodeAt( - node: Node, - start: number | undefined, - end?: number | undefined, - type?: FindPredicate | string, - base?: RecursiveVisitors, - state?: TState - ): Found | undefined; +export type AncestorVisitors = { + [type in acorn.AnyNode["type"]]?: ( node: Extract, state: TState, ancestors: acorn.Node[] +) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState, ancestors: acorn.Node[]) => void +} - export function findNodeAround( - node: Node, - start: number | undefined, - type?: FindPredicate | string, - base?: RecursiveVisitors, - state?: TState - ): Found | undefined; +export type WalkerCallback = (node: acorn.Node, state: TState) => void - export const findNodeAfter: typeof findNodeAround; +export type RecursiveVisitors = { + [type in acorn.AnyNode["type"]]?: ( node: Extract, state: TState, callback: WalkerCallback) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState, callback: WalkerCallback) => void +} - export const base: RecursiveVisitors; +export type FindPredicate = (type: string, node: acorn.Node) => boolean + +export interface Found { + node: acorn.Node, + state: TState } + +/** + * does a 'simple' walk over a tree + * @param node the AST node to walk + * @param visitors an object with properties whose names correspond to node types in the {@link https://github.com/estree/estree | ESTree spec}. The properties should contain functions that will be called with the node object and, if applicable the state at that point. + * @param base a walker algorithm + * @param state a start state. The default walker will simply visit all statements and expressions and not produce a meaningful state. (An example of a use of state is to track scope at each point in the tree.) + */ +export function simple( + node: acorn.Node, + visitors: SimpleVisitors, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * does a 'simple' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter. + * @param node + * @param visitors + * @param base + * @param state + */ +export function ancestor( + node: acorn.Node, + visitors: AncestorVisitors, + base?: RecursiveVisitors, + state?: TState + ): void + +/** + * does a 'recursive' walk, where the walker functions are responsible for continuing the walk on the child nodes of their target node. + * @param node + * @param state the start state + * @param functions contain an object that maps node types to walker functions + * @param base provides the fallback walker functions for node types that aren't handled in the {@link functions} object. If not given, the default walkers will be used. + */ +export function recursive( + node: acorn.Node, + state: TState, + functions: RecursiveVisitors, + base?: RecursiveVisitors +): void + +/** + * does a 'full' walk over a tree, calling the {@link callback} with the arguments (node, state, type) for each node + * @param node + * @param callback + * @param base + * @param state + */ +export function full( + node: acorn.Node, + callback: FullWalkerCallback, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * does a 'full' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter. + * @param node + * @param callback + * @param base + * @param state + */ +export function fullAncestor( + node: acorn.Node, + callback: FullAncestorWalkerCallback, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * builds a new walker object by using the walker functions in {@link functions} and filling in the missing ones by taking defaults from {@link base}. + * @param functions + * @param base + */ +export function make( + functions: RecursiveVisitors, + base?: RecursiveVisitors +): RecursiveVisitors + +/** + * tries to locate a node in a tree at the given start and/or end offsets, which satisfies the predicate test. {@link start} and {@link end} can be either `null` (as wildcard) or a `number`. {@link test} may be a string (indicating a node type) or a function that takes (nodeType, node) arguments and returns a boolean indicating whether this node is interesting. {@link base} and {@link state} are optional, and can be used to specify a custom walker. Nodes are tested from inner to outer, so if two nodes match the boundaries, the inner one will be preferred. + * @param node + * @param start + * @param end + * @param type + * @param base + * @param state + */ +export function findNodeAt( + node: acorn.Node, + start: number | undefined, + end?: number | undefined, + type?: FindPredicate | string, + base?: RecursiveVisitors, + state?: TState +): Found | undefined + +/** + * like {@link findNodeAt}, but will match any node that exists 'around' (spanning) the given position. + * @param node + * @param start + * @param type + * @param base + * @param state + */ +export function findNodeAround( + node: acorn.Node, + start: number | undefined, + type?: FindPredicate | string, + base?: RecursiveVisitors, + state?: TState +): Found | undefined + +/** + * Find the outermost matching node after a given position. + */ +export const findNodeAfter: typeof findNodeAround + +/** + * Find the outermost matching node before a given position. + */ +export const findNodeBefore: typeof findNodeAround + +export const base: RecursiveVisitors diff --git a/deps/acorn/acorn-walk/dist/walk.js b/deps/acorn/acorn-walk/dist/walk.js index a7f81b0061a750..580df6413725f8 100644 --- a/deps/acorn/acorn-walk/dist/walk.js +++ b/deps/acorn/acorn-walk/dist/walk.js @@ -1,10 +1,10 @@ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : - (global = global || self, factory((global.acorn = global.acorn || {}, global.acorn.walk = {}))); -}(this, (function (exports) { 'use strict'; + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.acorn = global.acorn || {}, global.acorn.walk = {}))); +})(this, (function (exports) { 'use strict'; - // AST walker module for Mozilla Parser API compatible trees + // AST walker module for ESTree compatible trees // A simple walk is one where you simply specify callbacks to be // called on specific nodes. The last two arguments are optional. A @@ -14,7 +14,7 @@ // Expression: function(node) { ... } // }); // - // to do something with all expressions. All Parser API node types + // to do something with all expressions. All ESTree node types // can be used to identify node types, as well as Expression and // Statement, which denote categories of nodes. // @@ -25,9 +25,9 @@ function simple(node, visitors, baseVisitor, state, override) { if (!baseVisitor) { baseVisitor = base ; }(function c(node, st, override) { - var type = override || node.type, found = visitors[type]; + var type = override || node.type; baseVisitor[type](node, st, c); - if (found) { found(node, st); } + if (visitors[type]) { visitors[type](node, st); } })(node, state, override); } @@ -38,11 +38,11 @@ var ancestors = []; if (!baseVisitor) { baseVisitor = base ; }(function c(node, st, override) { - var type = override || node.type, found = visitors[type]; + var type = override || node.type; var isNew = node !== ancestors[ancestors.length - 1]; if (isNew) { ancestors.push(node); } baseVisitor[type](node, st, c); - if (found) { found(node, st || ancestors, ancestors); } + if (visitors[type]) { visitors[type](node, st || ancestors, ancestors); } if (isNew) { ancestors.pop(); } })(node, state, override); } @@ -458,6 +458,4 @@ exports.recursive = recursive; exports.simple = simple; - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); +})); diff --git a/deps/acorn/acorn-walk/dist/walk.mjs b/deps/acorn/acorn-walk/dist/walk.mjs index 89dd1f1f4f3557..19eebc0e70f598 100644 --- a/deps/acorn/acorn-walk/dist/walk.mjs +++ b/deps/acorn/acorn-walk/dist/walk.mjs @@ -1,4 +1,4 @@ -// AST walker module for Mozilla Parser API compatible trees +// AST walker module for ESTree compatible trees // A simple walk is one where you simply specify callbacks to be // called on specific nodes. The last two arguments are optional. A @@ -8,7 +8,7 @@ // Expression: function(node) { ... } // }); // -// to do something with all expressions. All Parser API node types +// to do something with all expressions. All ESTree node types // can be used to identify node types, as well as Expression and // Statement, which denote categories of nodes. // @@ -19,9 +19,9 @@ function simple(node, visitors, baseVisitor, state, override) { if (!baseVisitor) { baseVisitor = base ; }(function c(node, st, override) { - var type = override || node.type, found = visitors[type]; + var type = override || node.type; baseVisitor[type](node, st, c); - if (found) { found(node, st); } + if (visitors[type]) { visitors[type](node, st); } })(node, state, override); } @@ -32,11 +32,11 @@ function ancestor(node, visitors, baseVisitor, state, override) { var ancestors = []; if (!baseVisitor) { baseVisitor = base ; }(function c(node, st, override) { - var type = override || node.type, found = visitors[type]; + var type = override || node.type; var isNew = node !== ancestors[ancestors.length - 1]; if (isNew) { ancestors.push(node); } baseVisitor[type](node, st, c); - if (found) { found(node, st || ancestors, ancestors); } + if (visitors[type]) { visitors[type](node, st || ancestors, ancestors); } if (isNew) { ancestors.pop(); } })(node, state, override); } diff --git a/deps/acorn/acorn-walk/package.json b/deps/acorn/acorn-walk/package.json index 8d75b9711c2e35..9d3b7e5248fb83 100644 --- a/deps/acorn/acorn-walk/package.json +++ b/deps/acorn/acorn-walk/package.json @@ -16,8 +16,10 @@ ], "./package.json": "./package.json" }, - "version": "8.2.0", - "engines": {"node": ">=0.4.0"}, + "version": "8.3.2", + "engines": { + "node": ">=0.4.0" + }, "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/deps/acorn/acorn/CHANGELOG.md b/deps/acorn/acorn/CHANGELOG.md index 12464cfdbeefdd..eb848a58b8a091 100644 --- a/deps/acorn/acorn/CHANGELOG.md +++ b/deps/acorn/acorn/CHANGELOG.md @@ -1,3 +1,39 @@ +## 8.11.3 (2023-12-29) + +### Bug fixes + +Add `Function` and `Class` to the `AggregateType` type, so that they can be used in walkers without raising a type error. + +Make sure `onToken` get an `import` keyword token when parsing `import.meta`. + +Fix a bug where `.loc.start` could be undefined for `new.target` `meta` nodes. + +## 8.11.2 (2023-10-27) + +### Bug fixes + +Fix a bug that caused regular expressions after colon tokens to not be properly tokenized in some circumstances. + +## 8.11.1 (2023-10-26) + +### Bug fixes + +Fix a regression where `onToken` would receive 'name' tokens for 'new' keyword tokens. + +## 8.11.0 (2023-10-26) + +### Bug fixes + +Fix an issue where tokenizing (without parsing) an object literal with a property named `class` or `function` could, in some circumstance, put the tokenizer into an invalid state. + +Fix an issue where a slash after a call to a propery named the same as some keywords would be tokenized as a regular expression. + +### New features + +Upgrade to Unicode 15.1. + +Use a set of new, much more precise, TypeScript types. + ## 8.10.0 (2023-07-05) ### New features diff --git a/deps/acorn/acorn/README.md b/deps/acorn/acorn/README.md index b62d02bde1fbb0..cfc51b384a3e2b 100644 --- a/deps/acorn/acorn/README.md +++ b/deps/acorn/acorn/README.md @@ -9,9 +9,7 @@ Acorn is open source software released under an You are welcome to [report bugs](https://github.com/acornjs/acorn/issues) or create pull -requests on [github](https://github.com/acornjs/acorn). For questions -and discussion, please use the -[Tern discussion forum](https://discuss.ternjs.net). +requests on [github](https://github.com/acornjs/acorn). ## Installation @@ -204,6 +202,13 @@ option is enabled). When the token's type is `tokTypes.eof`, you should stop calling the method, since it will keep returning that same token forever. +Note that tokenizing JavaScript without parsing it is, in modern +versions of the language, not really possible due to the way syntax is +overloaded in ways that can only be disambiguated by the parse +context. This package applies a bunch of heuristics to try and do a +reasonable job, but you are advised to use `parse` with the `onToken` +option instead of this. + In ES6 environment, returned result can be used as any other protocol-compliant iterable: diff --git a/deps/acorn/acorn/dist/acorn.d.mts b/deps/acorn/acorn/dist/acorn.d.mts index 49ae59fd95776a..6ad58121195c96 100644 --- a/deps/acorn/acorn/dist/acorn.d.mts +++ b/deps/acorn/acorn/dist/acorn.d.mts @@ -1,26 +1,857 @@ -export { - Node, - Parser, - Position, - SourceLocation, - TokContext, - Token, - TokenType, - defaultOptions, - getLineInfo, - isIdentifierChar, - isIdentifierStart, - isNewLine, - lineBreak, - lineBreakG, - parse, - parseExpressionAt, - tokContexts, - tokTypes, - tokenizer, - version, - AbstractToken, - Comment, - Options, - ecmaVersion, -} from "./acorn.js"; +export interface Node { + start: number + end: number + type: string + range?: [number, number] + loc?: SourceLocation | null +} + +export interface SourceLocation { + source?: string | null + start: Position + end: Position +} + +export interface Position { + /** 1-based */ + line: number + /** 0-based */ + column: number +} + +export interface Identifier extends Node { + type: "Identifier" + name: string +} + +export interface Literal extends Node { + type: "Literal" + value?: string | boolean | null | number | RegExp | bigint + raw?: string + regex?: { + pattern: string + flags: string + } + bigint?: string +} + +export interface Program extends Node { + type: "Program" + body: Array + sourceType: "script" | "module" +} + +export interface Function extends Node { + id?: Identifier | null + params: Array + body: BlockStatement | Expression + generator: boolean + expression: boolean + async: boolean +} + +export interface ExpressionStatement extends Node { + type: "ExpressionStatement" + expression: Expression | Literal + directive?: string +} + +export interface BlockStatement extends Node { + type: "BlockStatement" + body: Array +} + +export interface EmptyStatement extends Node { + type: "EmptyStatement" +} + +export interface DebuggerStatement extends Node { + type: "DebuggerStatement" +} + +export interface WithStatement extends Node { + type: "WithStatement" + object: Expression + body: Statement +} + +export interface ReturnStatement extends Node { + type: "ReturnStatement" + argument?: Expression | null +} + +export interface LabeledStatement extends Node { + type: "LabeledStatement" + label: Identifier + body: Statement +} + +export interface BreakStatement extends Node { + type: "BreakStatement" + label?: Identifier | null +} + +export interface ContinueStatement extends Node { + type: "ContinueStatement" + label?: Identifier | null +} + +export interface IfStatement extends Node { + type: "IfStatement" + test: Expression + consequent: Statement + alternate?: Statement | null +} + +export interface SwitchStatement extends Node { + type: "SwitchStatement" + discriminant: Expression + cases: Array +} + +export interface SwitchCase extends Node { + type: "SwitchCase" + test?: Expression | null + consequent: Array +} + +export interface ThrowStatement extends Node { + type: "ThrowStatement" + argument: Expression +} + +export interface TryStatement extends Node { + type: "TryStatement" + block: BlockStatement + handler?: CatchClause | null + finalizer?: BlockStatement | null +} + +export interface CatchClause extends Node { + type: "CatchClause" + param?: Pattern | null + body: BlockStatement +} + +export interface WhileStatement extends Node { + type: "WhileStatement" + test: Expression + body: Statement +} + +export interface DoWhileStatement extends Node { + type: "DoWhileStatement" + body: Statement + test: Expression +} + +export interface ForStatement extends Node { + type: "ForStatement" + init?: VariableDeclaration | Expression | null + test?: Expression | null + update?: Expression | null + body: Statement +} + +export interface ForInStatement extends Node { + type: "ForInStatement" + left: VariableDeclaration | Pattern + right: Expression + body: Statement +} + +export interface FunctionDeclaration extends Function { + type: "FunctionDeclaration" + id: Identifier + body: BlockStatement +} + +export interface VariableDeclaration extends Node { + type: "VariableDeclaration" + declarations: Array + kind: "var" | "let" | "const" +} + +export interface VariableDeclarator extends Node { + type: "VariableDeclarator" + id: Pattern + init?: Expression | null +} + +export interface ThisExpression extends Node { + type: "ThisExpression" +} + +export interface ArrayExpression extends Node { + type: "ArrayExpression" + elements: Array +} + +export interface ObjectExpression extends Node { + type: "ObjectExpression" + properties: Array +} + +export interface Property extends Node { + type: "Property" + key: Expression + value: Expression + kind: "init" | "get" | "set" + method: boolean + shorthand: boolean + computed: boolean +} + +export interface FunctionExpression extends Function { + type: "FunctionExpression" + body: BlockStatement +} + +export interface UnaryExpression extends Node { + type: "UnaryExpression" + operator: UnaryOperator + prefix: boolean + argument: Expression +} + +export type UnaryOperator = "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" + +export interface UpdateExpression extends Node { + type: "UpdateExpression" + operator: UpdateOperator + argument: Expression + prefix: boolean +} + +export type UpdateOperator = "++" | "--" + +export interface BinaryExpression extends Node { + type: "BinaryExpression" + operator: BinaryOperator + left: Expression | PrivateIdentifier + right: Expression +} + +export type BinaryOperator = "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "|" | "^" | "&" | "in" | "instanceof" | "**" + +export interface AssignmentExpression extends Node { + type: "AssignmentExpression" + operator: AssignmentOperator + left: Pattern + right: Expression +} + +export type AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" | "**=" | "||=" | "&&=" | "??=" + +export interface LogicalExpression extends Node { + type: "LogicalExpression" + operator: LogicalOperator + left: Expression + right: Expression +} + +export type LogicalOperator = "||" | "&&" | "??" + +export interface MemberExpression extends Node { + type: "MemberExpression" + object: Expression | Super + property: Expression | PrivateIdentifier + computed: boolean + optional: boolean +} + +export interface ConditionalExpression extends Node { + type: "ConditionalExpression" + test: Expression + alternate: Expression + consequent: Expression +} + +export interface CallExpression extends Node { + type: "CallExpression" + callee: Expression | Super + arguments: Array + optional: boolean +} + +export interface NewExpression extends Node { + type: "NewExpression" + callee: Expression + arguments: Array +} + +export interface SequenceExpression extends Node { + type: "SequenceExpression" + expressions: Array +} + +export interface ForOfStatement extends Node { + type: "ForOfStatement" + left: VariableDeclaration | Pattern + right: Expression + body: Statement + await: boolean +} + +export interface Super extends Node { + type: "Super" +} + +export interface SpreadElement extends Node { + type: "SpreadElement" + argument: Expression +} + +export interface ArrowFunctionExpression extends Function { + type: "ArrowFunctionExpression" +} + +export interface YieldExpression extends Node { + type: "YieldExpression" + argument?: Expression | null + delegate: boolean +} + +export interface TemplateLiteral extends Node { + type: "TemplateLiteral" + quasis: Array + expressions: Array +} + +export interface TaggedTemplateExpression extends Node { + type: "TaggedTemplateExpression" + tag: Expression + quasi: TemplateLiteral +} + +export interface TemplateElement extends Node { + type: "TemplateElement" + tail: boolean + value: { + cooked?: string | null + raw: string + } +} + +export interface AssignmentProperty extends Node { + type: "Property" + key: Expression + value: Pattern + kind: "init" + method: false + shorthand: boolean + computed: boolean +} + +export interface ObjectPattern extends Node { + type: "ObjectPattern" + properties: Array +} + +export interface ArrayPattern extends Node { + type: "ArrayPattern" + elements: Array +} + +export interface RestElement extends Node { + type: "RestElement" + argument: Pattern +} + +export interface AssignmentPattern extends Node { + type: "AssignmentPattern" + left: Pattern + right: Expression +} + +export interface Class extends Node { + id?: Identifier | null + superClass?: Expression | null + body: ClassBody +} + +export interface ClassBody extends Node { + type: "ClassBody" + body: Array +} + +export interface MethodDefinition extends Node { + type: "MethodDefinition" + key: Expression | PrivateIdentifier + value: FunctionExpression + kind: "constructor" | "method" | "get" | "set" + computed: boolean + static: boolean +} + +export interface ClassDeclaration extends Class { + type: "ClassDeclaration" + id: Identifier +} + +export interface ClassExpression extends Class { + type: "ClassExpression" +} + +export interface MetaProperty extends Node { + type: "MetaProperty" + meta: Identifier + property: Identifier +} + +export interface ImportDeclaration extends Node { + type: "ImportDeclaration" + specifiers: Array + source: Literal +} + +export interface ImportSpecifier extends Node { + type: "ImportSpecifier" + imported: Identifier | Literal + local: Identifier +} + +export interface ImportDefaultSpecifier extends Node { + type: "ImportDefaultSpecifier" + local: Identifier +} + +export interface ImportNamespaceSpecifier extends Node { + type: "ImportNamespaceSpecifier" + local: Identifier +} + +export interface ExportNamedDeclaration extends Node { + type: "ExportNamedDeclaration" + declaration?: Declaration | null + specifiers: Array + source?: Literal | null +} + +export interface ExportSpecifier extends Node { + type: "ExportSpecifier" + exported: Identifier | Literal + local: Identifier | Literal +} + +export interface AnonymousFunctionDeclaration extends Function { + type: "FunctionDeclaration" + id: null + body: BlockStatement +} + +export interface AnonymousClassDeclaration extends Class { + type: "ClassDeclaration" + id: null +} + +export interface ExportDefaultDeclaration extends Node { + type: "ExportDefaultDeclaration" + declaration: AnonymousFunctionDeclaration | FunctionDeclaration | AnonymousClassDeclaration | ClassDeclaration | Expression +} + +export interface ExportAllDeclaration extends Node { + type: "ExportAllDeclaration" + source: Literal + exported?: Identifier | Literal | null +} + +export interface AwaitExpression extends Node { + type: "AwaitExpression" + argument: Expression +} + +export interface ChainExpression extends Node { + type: "ChainExpression" + expression: MemberExpression | CallExpression +} + +export interface ImportExpression extends Node { + type: "ImportExpression" + source: Expression +} + +export interface ParenthesizedExpression extends Node { + type: "ParenthesizedExpression" + expression: Expression +} + +export interface PropertyDefinition extends Node { + type: "PropertyDefinition" + key: Expression | PrivateIdentifier + value?: Expression | null + computed: boolean + static: boolean +} + +export interface PrivateIdentifier extends Node { + type: "PrivateIdentifier" + name: string +} + +export interface StaticBlock extends Node { + type: "StaticBlock" + body: Array +} + +export type Statement = +| ExpressionStatement +| BlockStatement +| EmptyStatement +| DebuggerStatement +| WithStatement +| ReturnStatement +| LabeledStatement +| BreakStatement +| ContinueStatement +| IfStatement +| SwitchStatement +| ThrowStatement +| TryStatement +| WhileStatement +| DoWhileStatement +| ForStatement +| ForInStatement +| ForOfStatement +| Declaration + +export type Declaration = +| FunctionDeclaration +| VariableDeclaration +| ClassDeclaration + +export type Expression = +| Identifier +| Literal +| ThisExpression +| ArrayExpression +| ObjectExpression +| FunctionExpression +| UnaryExpression +| UpdateExpression +| BinaryExpression +| AssignmentExpression +| LogicalExpression +| MemberExpression +| ConditionalExpression +| CallExpression +| NewExpression +| SequenceExpression +| ArrowFunctionExpression +| YieldExpression +| TemplateLiteral +| TaggedTemplateExpression +| ClassExpression +| MetaProperty +| AwaitExpression +| ChainExpression +| ImportExpression +| ParenthesizedExpression + +export type Pattern = +| Identifier +| MemberExpression +| ObjectPattern +| ArrayPattern +| RestElement +| AssignmentPattern + +export type ModuleDeclaration = +| ImportDeclaration +| ExportNamedDeclaration +| ExportDefaultDeclaration +| ExportAllDeclaration + +export type AnyNode = Statement | Expression | Declaration | ModuleDeclaration | Literal | Program | SwitchCase | CatchClause | Property | Super | SpreadElement | TemplateElement | AssignmentProperty | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | ClassBody | MethodDefinition | MetaProperty | ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier | AnonymousFunctionDeclaration | AnonymousClassDeclaration | PropertyDefinition | PrivateIdentifier | StaticBlock + +export function parse(input: string, options: Options): Program + +export function parseExpressionAt(input: string, pos: number, options: Options): Expression + +export function tokenizer(input: string, options: Options): { + getToken(): Token + [Symbol.iterator](): Iterator +} + +export type ecmaVersion = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | "latest" + +export interface Options { + /** + * `ecmaVersion` indicates the ECMAScript version to parse. Must be + * either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10 + * (2019), 11 (2020), 12 (2021), 13 (2022), 14 (2023), or `"latest"` + * (the latest version the library supports). This influences + * support for strict mode, the set of reserved words, and support + * for new syntax features. + */ + ecmaVersion: ecmaVersion + + /** + * `sourceType` indicates the mode the code should be parsed in. + * Can be either `"script"` or `"module"`. This influences global + * strict mode and parsing of `import` and `export` declarations. + */ + sourceType?: "script" | "module" + + /** + * a callback that will be called when a semicolon is automatically inserted. + * @param lastTokEnd the position of the comma as an offset + * @param lastTokEndLoc location if {@link locations} is enabled + */ + onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void + + /** + * similar to `onInsertedSemicolon`, but for trailing commas + * @param lastTokEnd the position of the comma as an offset + * @param lastTokEndLoc location if `locations` is enabled + */ + onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void + + /** + * By default, reserved words are only enforced if ecmaVersion >= 5. + * Set `allowReserved` to a boolean value to explicitly turn this on + * an off. When this option has the value "never", reserved words + * and keywords can also not be used as property names. + */ + allowReserved?: boolean | "never" + + /** + * When enabled, a return at the top level is not considered an error. + */ + allowReturnOutsideFunction?: boolean + + /** + * When enabled, import/export statements are not constrained to + * appearing at the top of the program, and an import.meta expression + * in a script isn't considered an error. + */ + allowImportExportEverywhere?: boolean + + /** + * By default, `await` identifiers are allowed to appear at the top-level scope only if {@link ecmaVersion} >= 2022. + * When enabled, await identifiers are allowed to appear at the top-level scope, + * but they are still not allowed in non-async functions. + */ + allowAwaitOutsideFunction?: boolean + + /** + * When enabled, super identifiers are not constrained to + * appearing in methods and do not raise an error when they appear elsewhere. + */ + allowSuperOutsideMethod?: boolean + + /** + * When enabled, hashbang directive in the beginning of file is + * allowed and treated as a line comment. Enabled by default when + * {@link ecmaVersion} >= 2023. + */ + allowHashBang?: boolean + + /** + * By default, the parser will verify that private properties are + * only used in places where they are valid and have been declared. + * Set this to false to turn such checks off. + */ + checkPrivateFields?: boolean + + /** + * When `locations` is on, `loc` properties holding objects with + * `start` and `end` properties as {@link Position} objects will be attached to the + * nodes. + */ + locations?: boolean + + /** + * a callback that will cause Acorn to call that export function with object in the same + * format as tokens returned from `tokenizer().getToken()`. Note + * that you are not allowed to call the parser from the + * callback—that will corrupt its internal state. + */ + onToken?: ((token: Token) => void) | Token[] + + + /** + * This takes a export function or an array. + * + * When a export function is passed, Acorn will call that export function with `(block, text, start, + * end)` parameters whenever a comment is skipped. `block` is a + * boolean indicating whether this is a block (`/* *\/`) comment, + * `text` is the content of the comment, and `start` and `end` are + * character offsets that denote the start and end of the comment. + * When the {@link locations} option is on, two more parameters are + * passed, the full locations of {@link Position} export type of the start and + * end of the comments. + * + * When a array is passed, each found comment of {@link Comment} export type is pushed to the array. + * + * Note that you are not allowed to call the + * parser from the callback—that will corrupt its internal state. + */ + onComment?: (( + isBlock: boolean, text: string, start: number, end: number, startLoc?: Position, + endLoc?: Position + ) => void) | Comment[] + + /** + * Nodes have their start and end characters offsets recorded in + * `start` and `end` properties (directly on the node, rather than + * the `loc` object, which holds line/column data. To also add a + * [semi-standardized][range] `range` property holding a `[start, + * end]` array with the same numbers, set the `ranges` option to + * `true`. + */ + ranges?: boolean + + /** + * It is possible to parse multiple files into a single AST by + * passing the tree produced by parsing the first file as + * `program` option in subsequent parses. This will add the + * toplevel forms of the parsed file to the `Program` (top) node + * of an existing parse tree. + */ + program?: Node + + /** + * When {@link locations} is on, you can pass this to record the source + * file in every node's `loc` object. + */ + sourceFile?: string + + /** + * This value, if given, is stored in every node, whether {@link locations} is on or off. + */ + directSourceFile?: string + + /** + * When enabled, parenthesized expressions are represented by + * (non-standard) ParenthesizedExpression nodes + */ + preserveParens?: boolean +} + +export class Parser { + options: Options + input: string + + private constructor(options: Options, input: string, startPos?: number) + parse(): Program + + static parse(input: string, options: Options): Program + static parseExpressionAt(input: string, pos: number, options: Options): Expression + static tokenizer(input: string, options: Options): { + getToken(): Token + [Symbol.iterator](): Iterator + } + static extend(...plugins: ((BaseParser: typeof Parser) => typeof Parser)[]): typeof Parser +} + +export const defaultOptions: Options + +export function getLineInfo(input: string, offset: number): Position + +export class TokenType { + label: string + keyword: string | undefined +} + +export const tokTypes: { + num: TokenType + regexp: TokenType + string: TokenType + name: TokenType + privateId: TokenType + eof: TokenType + + bracketL: TokenType + bracketR: TokenType + braceL: TokenType + braceR: TokenType + parenL: TokenType + parenR: TokenType + comma: TokenType + semi: TokenType + colon: TokenType + dot: TokenType + question: TokenType + questionDot: TokenType + arrow: TokenType + template: TokenType + invalidTemplate: TokenType + ellipsis: TokenType + backQuote: TokenType + dollarBraceL: TokenType + + eq: TokenType + assign: TokenType + incDec: TokenType + prefix: TokenType + logicalOR: TokenType + logicalAND: TokenType + bitwiseOR: TokenType + bitwiseXOR: TokenType + bitwiseAND: TokenType + equality: TokenType + relational: TokenType + bitShift: TokenType + plusMin: TokenType + modulo: TokenType + star: TokenType + slash: TokenType + starstar: TokenType + coalesce: TokenType + + _break: TokenType + _case: TokenType + _catch: TokenType + _continue: TokenType + _debugger: TokenType + _default: TokenType + _do: TokenType + _else: TokenType + _finally: TokenType + _for: TokenType + _function: TokenType + _if: TokenType + _return: TokenType + _switch: TokenType + _throw: TokenType + _try: TokenType + _var: TokenType + _const: TokenType + _while: TokenType + _with: TokenType + _new: TokenType + _this: TokenType + _super: TokenType + _class: TokenType + _extends: TokenType + _export: TokenType + _import: TokenType + _null: TokenType + _true: TokenType + _false: TokenType + _in: TokenType + _instanceof: TokenType + _typeof: TokenType + _void: TokenType + _delete: TokenType +} + +export interface Comment { + type: "Line" | "Block" + value: string + start: number + end: number + loc?: SourceLocation + range?: [number, number] +} + +export class Token { + type: TokenType + start: number + end: number + loc?: SourceLocation + range?: [number, number] +} + +export const version: string diff --git a/deps/acorn/acorn/dist/acorn.d.ts b/deps/acorn/acorn/dist/acorn.d.ts index 5b26741473db1a..6ad58121195c96 100644 --- a/deps/acorn/acorn/dist/acorn.d.ts +++ b/deps/acorn/acorn/dist/acorn.d.ts @@ -1,292 +1,857 @@ -export as namespace acorn -export = acorn +export interface Node { + start: number + end: number + type: string + range?: [number, number] + loc?: SourceLocation | null +} -declare namespace acorn { - function parse(input: string, options: Options): Node +export interface SourceLocation { + source?: string | null + start: Position + end: Position +} - function parseExpressionAt(input: string, pos: number, options: Options): Node +export interface Position { + /** 1-based */ + line: number + /** 0-based */ + column: number +} - function tokenizer(input: string, options: Options): { - getToken(): Token - [Symbol.iterator](): Iterator - } +export interface Identifier extends Node { + type: "Identifier" + name: string +} - type ecmaVersion = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 'latest' - - interface Options { - ecmaVersion: ecmaVersion - sourceType?: 'script' | 'module' - onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void - onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void - allowReserved?: boolean | 'never' - allowReturnOutsideFunction?: boolean - allowImportExportEverywhere?: boolean - allowAwaitOutsideFunction?: boolean - allowSuperOutsideMethod?: boolean - allowHashBang?: boolean - locations?: boolean - onToken?: ((token: Token) => any) | Token[] - onComment?: (( - isBlock: boolean, text: string, start: number, end: number, startLoc?: Position, - endLoc?: Position - ) => void) | Comment[] - ranges?: boolean - program?: Node - sourceFile?: string - directSourceFile?: string - preserveParens?: boolean +export interface Literal extends Node { + type: "Literal" + value?: string | boolean | null | number | RegExp | bigint + raw?: string + regex?: { + pattern: string + flags: string } + bigint?: string +} - class Parser { - // state.js - lineStart: number; - options: Options; - curLine: number; - start: number; - end: number; - input: string; - type: TokenType; - - // state.js - constructor(options: Options, input: string, startPos?: number) - parse(this: Parser): Node - - // tokenize.js - next(): void; - nextToken(): void; - - // statement.js - parseTopLevel(node: Node): Node; - - // node.js - finishNode(node: Node, type: string): Node; - finishNodeAt(node: Node, type: string, pos: number, loc: Position): Node; - - // location.js - raise(pos: number, message: string) : void; - raiseRecoverable?(pos: number, message: string) : void; - - // parseutils.js - unexpected(pos: number) : void; - - // index.js - static acorn: typeof acorn; - - // state.js - static parse(this: typeof Parser, input: string, options: Options): Node - static parseExpressionAt(this: typeof Parser, input: string, pos: number, options: Options): Node - static tokenizer(this: typeof Parser, input: string, options: Options): { - getToken(): Token - [Symbol.iterator](): Iterator - } - static extend(this: typeof Parser, ...plugins: ((BaseParser: typeof Parser) => typeof Parser)[]): typeof Parser - } +export interface Program extends Node { + type: "Program" + body: Array + sourceType: "script" | "module" +} - interface Position { line: number; column: number; offset: number } +export interface Function extends Node { + id?: Identifier | null + params: Array + body: BlockStatement | Expression + generator: boolean + expression: boolean + async: boolean +} - const defaultOptions: Options +export interface ExpressionStatement extends Node { + type: "ExpressionStatement" + expression: Expression | Literal + directive?: string +} - function getLineInfo(input: string, offset: number): Position +export interface BlockStatement extends Node { + type: "BlockStatement" + body: Array +} - class SourceLocation { - start: Position - end: Position - source?: string | null - constructor(p: Parser, start: Position, end: Position) - } +export interface EmptyStatement extends Node { + type: "EmptyStatement" +} - class Node { - type: string - start: number - end: number - loc?: SourceLocation - sourceFile?: string - range?: [number, number] - constructor(parser: Parser, pos: number, loc?: SourceLocation) - } +export interface DebuggerStatement extends Node { + type: "DebuggerStatement" +} - class TokenType { - label: string - keyword: string - beforeExpr: boolean - startsExpr: boolean - isLoop: boolean - isAssign: boolean - prefix: boolean - postfix: boolean - binop: number - updateContext?: (prevType: TokenType) => void - constructor(label: string, conf?: any) - } +export interface WithStatement extends Node { + type: "WithStatement" + object: Expression + body: Statement +} - const tokTypes: { - num: TokenType - regexp: TokenType - string: TokenType - name: TokenType - privateId: TokenType - eof: TokenType - bracketL: TokenType - bracketR: TokenType - braceL: TokenType - braceR: TokenType - parenL: TokenType - parenR: TokenType - comma: TokenType - semi: TokenType - colon: TokenType - dot: TokenType - question: TokenType - questionDot: TokenType - arrow: TokenType - template: TokenType - invalidTemplate: TokenType - ellipsis: TokenType - backQuote: TokenType - dollarBraceL: TokenType - eq: TokenType - assign: TokenType - incDec: TokenType - prefix: TokenType - logicalOR: TokenType - logicalAND: TokenType - bitwiseOR: TokenType - bitwiseXOR: TokenType - bitwiseAND: TokenType - equality: TokenType - relational: TokenType - bitShift: TokenType - plusMin: TokenType - modulo: TokenType - star: TokenType - slash: TokenType - starstar: TokenType - coalesce: TokenType - _break: TokenType - _case: TokenType - _catch: TokenType - _continue: TokenType - _debugger: TokenType - _default: TokenType - _do: TokenType - _else: TokenType - _finally: TokenType - _for: TokenType - _function: TokenType - _if: TokenType - _return: TokenType - _switch: TokenType - _throw: TokenType - _try: TokenType - _var: TokenType - _const: TokenType - _while: TokenType - _with: TokenType - _new: TokenType - _this: TokenType - _super: TokenType - _class: TokenType - _extends: TokenType - _export: TokenType - _import: TokenType - _null: TokenType - _true: TokenType - _false: TokenType - _in: TokenType - _instanceof: TokenType - _typeof: TokenType - _void: TokenType - _delete: TokenType - } +export interface ReturnStatement extends Node { + type: "ReturnStatement" + argument?: Expression | null +} - class TokContext { - constructor(token: string, isExpr: boolean, preserveSpace: boolean, override?: (p: Parser) => void) - } +export interface LabeledStatement extends Node { + type: "LabeledStatement" + label: Identifier + body: Statement +} - const tokContexts: { - b_stat: TokContext - b_expr: TokContext - b_tmpl: TokContext - p_stat: TokContext - p_expr: TokContext - q_tmpl: TokContext - f_expr: TokContext - f_stat: TokContext - f_expr_gen: TokContext - f_gen: TokContext - } +export interface BreakStatement extends Node { + type: "BreakStatement" + label?: Identifier | null +} - function isIdentifierStart(code: number, astral?: boolean): boolean +export interface ContinueStatement extends Node { + type: "ContinueStatement" + label?: Identifier | null +} - function isIdentifierChar(code: number, astral?: boolean): boolean +export interface IfStatement extends Node { + type: "IfStatement" + test: Expression + consequent: Statement + alternate?: Statement | null +} - interface AbstractToken { - } +export interface SwitchStatement extends Node { + type: "SwitchStatement" + discriminant: Expression + cases: Array +} - interface Comment extends AbstractToken { - type: 'Line' | 'Block' - value: string - start: number - end: number - loc?: SourceLocation - range?: [number, number] - } +export interface SwitchCase extends Node { + type: "SwitchCase" + test?: Expression | null + consequent: Array +} + +export interface ThrowStatement extends Node { + type: "ThrowStatement" + argument: Expression +} - class Token { - type: TokenType - value: any - start: number - end: number - loc?: SourceLocation - range?: [number, number] - constructor(p: Parser) +export interface TryStatement extends Node { + type: "TryStatement" + block: BlockStatement + handler?: CatchClause | null + finalizer?: BlockStatement | null +} + +export interface CatchClause extends Node { + type: "CatchClause" + param?: Pattern | null + body: BlockStatement +} + +export interface WhileStatement extends Node { + type: "WhileStatement" + test: Expression + body: Statement +} + +export interface DoWhileStatement extends Node { + type: "DoWhileStatement" + body: Statement + test: Expression +} + +export interface ForStatement extends Node { + type: "ForStatement" + init?: VariableDeclaration | Expression | null + test?: Expression | null + update?: Expression | null + body: Statement +} + +export interface ForInStatement extends Node { + type: "ForInStatement" + left: VariableDeclaration | Pattern + right: Expression + body: Statement +} + +export interface FunctionDeclaration extends Function { + type: "FunctionDeclaration" + id: Identifier + body: BlockStatement +} + +export interface VariableDeclaration extends Node { + type: "VariableDeclaration" + declarations: Array + kind: "var" | "let" | "const" +} + +export interface VariableDeclarator extends Node { + type: "VariableDeclarator" + id: Pattern + init?: Expression | null +} + +export interface ThisExpression extends Node { + type: "ThisExpression" +} + +export interface ArrayExpression extends Node { + type: "ArrayExpression" + elements: Array +} + +export interface ObjectExpression extends Node { + type: "ObjectExpression" + properties: Array +} + +export interface Property extends Node { + type: "Property" + key: Expression + value: Expression + kind: "init" | "get" | "set" + method: boolean + shorthand: boolean + computed: boolean +} + +export interface FunctionExpression extends Function { + type: "FunctionExpression" + body: BlockStatement +} + +export interface UnaryExpression extends Node { + type: "UnaryExpression" + operator: UnaryOperator + prefix: boolean + argument: Expression +} + +export type UnaryOperator = "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" + +export interface UpdateExpression extends Node { + type: "UpdateExpression" + operator: UpdateOperator + argument: Expression + prefix: boolean +} + +export type UpdateOperator = "++" | "--" + +export interface BinaryExpression extends Node { + type: "BinaryExpression" + operator: BinaryOperator + left: Expression | PrivateIdentifier + right: Expression +} + +export type BinaryOperator = "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "|" | "^" | "&" | "in" | "instanceof" | "**" + +export interface AssignmentExpression extends Node { + type: "AssignmentExpression" + operator: AssignmentOperator + left: Pattern + right: Expression +} + +export type AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" | "**=" | "||=" | "&&=" | "??=" + +export interface LogicalExpression extends Node { + type: "LogicalExpression" + operator: LogicalOperator + left: Expression + right: Expression +} + +export type LogicalOperator = "||" | "&&" | "??" + +export interface MemberExpression extends Node { + type: "MemberExpression" + object: Expression | Super + property: Expression | PrivateIdentifier + computed: boolean + optional: boolean +} + +export interface ConditionalExpression extends Node { + type: "ConditionalExpression" + test: Expression + alternate: Expression + consequent: Expression +} + +export interface CallExpression extends Node { + type: "CallExpression" + callee: Expression | Super + arguments: Array + optional: boolean +} + +export interface NewExpression extends Node { + type: "NewExpression" + callee: Expression + arguments: Array +} + +export interface SequenceExpression extends Node { + type: "SequenceExpression" + expressions: Array +} + +export interface ForOfStatement extends Node { + type: "ForOfStatement" + left: VariableDeclaration | Pattern + right: Expression + body: Statement + await: boolean +} + +export interface Super extends Node { + type: "Super" +} + +export interface SpreadElement extends Node { + type: "SpreadElement" + argument: Expression +} + +export interface ArrowFunctionExpression extends Function { + type: "ArrowFunctionExpression" +} + +export interface YieldExpression extends Node { + type: "YieldExpression" + argument?: Expression | null + delegate: boolean +} + +export interface TemplateLiteral extends Node { + type: "TemplateLiteral" + quasis: Array + expressions: Array +} + +export interface TaggedTemplateExpression extends Node { + type: "TaggedTemplateExpression" + tag: Expression + quasi: TemplateLiteral +} + +export interface TemplateElement extends Node { + type: "TemplateElement" + tail: boolean + value: { + cooked?: string | null + raw: string } +} + +export interface AssignmentProperty extends Node { + type: "Property" + key: Expression + value: Pattern + kind: "init" + method: false + shorthand: boolean + computed: boolean +} + +export interface ObjectPattern extends Node { + type: "ObjectPattern" + properties: Array +} + +export interface ArrayPattern extends Node { + type: "ArrayPattern" + elements: Array +} + +export interface RestElement extends Node { + type: "RestElement" + argument: Pattern +} + +export interface AssignmentPattern extends Node { + type: "AssignmentPattern" + left: Pattern + right: Expression +} + +export interface Class extends Node { + id?: Identifier | null + superClass?: Expression | null + body: ClassBody +} + +export interface ClassBody extends Node { + type: "ClassBody" + body: Array +} + +export interface MethodDefinition extends Node { + type: "MethodDefinition" + key: Expression | PrivateIdentifier + value: FunctionExpression + kind: "constructor" | "method" | "get" | "set" + computed: boolean + static: boolean +} + +export interface ClassDeclaration extends Class { + type: "ClassDeclaration" + id: Identifier +} + +export interface ClassExpression extends Class { + type: "ClassExpression" +} + +export interface MetaProperty extends Node { + type: "MetaProperty" + meta: Identifier + property: Identifier +} + +export interface ImportDeclaration extends Node { + type: "ImportDeclaration" + specifiers: Array + source: Literal +} + +export interface ImportSpecifier extends Node { + type: "ImportSpecifier" + imported: Identifier | Literal + local: Identifier +} + +export interface ImportDefaultSpecifier extends Node { + type: "ImportDefaultSpecifier" + local: Identifier +} + +export interface ImportNamespaceSpecifier extends Node { + type: "ImportNamespaceSpecifier" + local: Identifier +} + +export interface ExportNamedDeclaration extends Node { + type: "ExportNamedDeclaration" + declaration?: Declaration | null + specifiers: Array + source?: Literal | null +} + +export interface ExportSpecifier extends Node { + type: "ExportSpecifier" + exported: Identifier | Literal + local: Identifier | Literal +} + +export interface AnonymousFunctionDeclaration extends Function { + type: "FunctionDeclaration" + id: null + body: BlockStatement +} + +export interface AnonymousClassDeclaration extends Class { + type: "ClassDeclaration" + id: null +} + +export interface ExportDefaultDeclaration extends Node { + type: "ExportDefaultDeclaration" + declaration: AnonymousFunctionDeclaration | FunctionDeclaration | AnonymousClassDeclaration | ClassDeclaration | Expression +} - function isNewLine(code: number): boolean - - const lineBreak: RegExp - - const lineBreakG: RegExp - - const version: string - - const nonASCIIwhitespace: RegExp - - const keywordTypes: { - _break: TokenType - _case: TokenType - _catch: TokenType - _continue: TokenType - _debugger: TokenType - _default: TokenType - _do: TokenType - _else: TokenType - _finally: TokenType - _for: TokenType - _function: TokenType - _if: TokenType - _return: TokenType - _switch: TokenType - _throw: TokenType - _try: TokenType - _var: TokenType - _const: TokenType - _while: TokenType - _with: TokenType - _new: TokenType - _this: TokenType - _super: TokenType - _class: TokenType - _extends: TokenType - _export: TokenType - _import: TokenType - _null: TokenType - _true: TokenType - _false: TokenType - _in: TokenType - _instanceof: TokenType - _typeof: TokenType - _void: TokenType - _delete: TokenType +export interface ExportAllDeclaration extends Node { + type: "ExportAllDeclaration" + source: Literal + exported?: Identifier | Literal | null +} + +export interface AwaitExpression extends Node { + type: "AwaitExpression" + argument: Expression +} + +export interface ChainExpression extends Node { + type: "ChainExpression" + expression: MemberExpression | CallExpression +} + +export interface ImportExpression extends Node { + type: "ImportExpression" + source: Expression +} + +export interface ParenthesizedExpression extends Node { + type: "ParenthesizedExpression" + expression: Expression +} + +export interface PropertyDefinition extends Node { + type: "PropertyDefinition" + key: Expression | PrivateIdentifier + value?: Expression | null + computed: boolean + static: boolean +} + +export interface PrivateIdentifier extends Node { + type: "PrivateIdentifier" + name: string +} + +export interface StaticBlock extends Node { + type: "StaticBlock" + body: Array +} + +export type Statement = +| ExpressionStatement +| BlockStatement +| EmptyStatement +| DebuggerStatement +| WithStatement +| ReturnStatement +| LabeledStatement +| BreakStatement +| ContinueStatement +| IfStatement +| SwitchStatement +| ThrowStatement +| TryStatement +| WhileStatement +| DoWhileStatement +| ForStatement +| ForInStatement +| ForOfStatement +| Declaration + +export type Declaration = +| FunctionDeclaration +| VariableDeclaration +| ClassDeclaration + +export type Expression = +| Identifier +| Literal +| ThisExpression +| ArrayExpression +| ObjectExpression +| FunctionExpression +| UnaryExpression +| UpdateExpression +| BinaryExpression +| AssignmentExpression +| LogicalExpression +| MemberExpression +| ConditionalExpression +| CallExpression +| NewExpression +| SequenceExpression +| ArrowFunctionExpression +| YieldExpression +| TemplateLiteral +| TaggedTemplateExpression +| ClassExpression +| MetaProperty +| AwaitExpression +| ChainExpression +| ImportExpression +| ParenthesizedExpression + +export type Pattern = +| Identifier +| MemberExpression +| ObjectPattern +| ArrayPattern +| RestElement +| AssignmentPattern + +export type ModuleDeclaration = +| ImportDeclaration +| ExportNamedDeclaration +| ExportDefaultDeclaration +| ExportAllDeclaration + +export type AnyNode = Statement | Expression | Declaration | ModuleDeclaration | Literal | Program | SwitchCase | CatchClause | Property | Super | SpreadElement | TemplateElement | AssignmentProperty | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | ClassBody | MethodDefinition | MetaProperty | ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier | AnonymousFunctionDeclaration | AnonymousClassDeclaration | PropertyDefinition | PrivateIdentifier | StaticBlock + +export function parse(input: string, options: Options): Program + +export function parseExpressionAt(input: string, pos: number, options: Options): Expression + +export function tokenizer(input: string, options: Options): { + getToken(): Token + [Symbol.iterator](): Iterator +} + +export type ecmaVersion = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | "latest" + +export interface Options { + /** + * `ecmaVersion` indicates the ECMAScript version to parse. Must be + * either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10 + * (2019), 11 (2020), 12 (2021), 13 (2022), 14 (2023), or `"latest"` + * (the latest version the library supports). This influences + * support for strict mode, the set of reserved words, and support + * for new syntax features. + */ + ecmaVersion: ecmaVersion + + /** + * `sourceType` indicates the mode the code should be parsed in. + * Can be either `"script"` or `"module"`. This influences global + * strict mode and parsing of `import` and `export` declarations. + */ + sourceType?: "script" | "module" + + /** + * a callback that will be called when a semicolon is automatically inserted. + * @param lastTokEnd the position of the comma as an offset + * @param lastTokEndLoc location if {@link locations} is enabled + */ + onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void + + /** + * similar to `onInsertedSemicolon`, but for trailing commas + * @param lastTokEnd the position of the comma as an offset + * @param lastTokEndLoc location if `locations` is enabled + */ + onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void + + /** + * By default, reserved words are only enforced if ecmaVersion >= 5. + * Set `allowReserved` to a boolean value to explicitly turn this on + * an off. When this option has the value "never", reserved words + * and keywords can also not be used as property names. + */ + allowReserved?: boolean | "never" + + /** + * When enabled, a return at the top level is not considered an error. + */ + allowReturnOutsideFunction?: boolean + + /** + * When enabled, import/export statements are not constrained to + * appearing at the top of the program, and an import.meta expression + * in a script isn't considered an error. + */ + allowImportExportEverywhere?: boolean + + /** + * By default, `await` identifiers are allowed to appear at the top-level scope only if {@link ecmaVersion} >= 2022. + * When enabled, await identifiers are allowed to appear at the top-level scope, + * but they are still not allowed in non-async functions. + */ + allowAwaitOutsideFunction?: boolean + + /** + * When enabled, super identifiers are not constrained to + * appearing in methods and do not raise an error when they appear elsewhere. + */ + allowSuperOutsideMethod?: boolean + + /** + * When enabled, hashbang directive in the beginning of file is + * allowed and treated as a line comment. Enabled by default when + * {@link ecmaVersion} >= 2023. + */ + allowHashBang?: boolean + + /** + * By default, the parser will verify that private properties are + * only used in places where they are valid and have been declared. + * Set this to false to turn such checks off. + */ + checkPrivateFields?: boolean + + /** + * When `locations` is on, `loc` properties holding objects with + * `start` and `end` properties as {@link Position} objects will be attached to the + * nodes. + */ + locations?: boolean + + /** + * a callback that will cause Acorn to call that export function with object in the same + * format as tokens returned from `tokenizer().getToken()`. Note + * that you are not allowed to call the parser from the + * callback—that will corrupt its internal state. + */ + onToken?: ((token: Token) => void) | Token[] + + + /** + * This takes a export function or an array. + * + * When a export function is passed, Acorn will call that export function with `(block, text, start, + * end)` parameters whenever a comment is skipped. `block` is a + * boolean indicating whether this is a block (`/* *\/`) comment, + * `text` is the content of the comment, and `start` and `end` are + * character offsets that denote the start and end of the comment. + * When the {@link locations} option is on, two more parameters are + * passed, the full locations of {@link Position} export type of the start and + * end of the comments. + * + * When a array is passed, each found comment of {@link Comment} export type is pushed to the array. + * + * Note that you are not allowed to call the + * parser from the callback—that will corrupt its internal state. + */ + onComment?: (( + isBlock: boolean, text: string, start: number, end: number, startLoc?: Position, + endLoc?: Position + ) => void) | Comment[] + + /** + * Nodes have their start and end characters offsets recorded in + * `start` and `end` properties (directly on the node, rather than + * the `loc` object, which holds line/column data. To also add a + * [semi-standardized][range] `range` property holding a `[start, + * end]` array with the same numbers, set the `ranges` option to + * `true`. + */ + ranges?: boolean + + /** + * It is possible to parse multiple files into a single AST by + * passing the tree produced by parsing the first file as + * `program` option in subsequent parses. This will add the + * toplevel forms of the parsed file to the `Program` (top) node + * of an existing parse tree. + */ + program?: Node + + /** + * When {@link locations} is on, you can pass this to record the source + * file in every node's `loc` object. + */ + sourceFile?: string + + /** + * This value, if given, is stored in every node, whether {@link locations} is on or off. + */ + directSourceFile?: string + + /** + * When enabled, parenthesized expressions are represented by + * (non-standard) ParenthesizedExpression nodes + */ + preserveParens?: boolean +} + +export class Parser { + options: Options + input: string + + private constructor(options: Options, input: string, startPos?: number) + parse(): Program + + static parse(input: string, options: Options): Program + static parseExpressionAt(input: string, pos: number, options: Options): Expression + static tokenizer(input: string, options: Options): { + getToken(): Token + [Symbol.iterator](): Iterator } + static extend(...plugins: ((BaseParser: typeof Parser) => typeof Parser)[]): typeof Parser } + +export const defaultOptions: Options + +export function getLineInfo(input: string, offset: number): Position + +export class TokenType { + label: string + keyword: string | undefined +} + +export const tokTypes: { + num: TokenType + regexp: TokenType + string: TokenType + name: TokenType + privateId: TokenType + eof: TokenType + + bracketL: TokenType + bracketR: TokenType + braceL: TokenType + braceR: TokenType + parenL: TokenType + parenR: TokenType + comma: TokenType + semi: TokenType + colon: TokenType + dot: TokenType + question: TokenType + questionDot: TokenType + arrow: TokenType + template: TokenType + invalidTemplate: TokenType + ellipsis: TokenType + backQuote: TokenType + dollarBraceL: TokenType + + eq: TokenType + assign: TokenType + incDec: TokenType + prefix: TokenType + logicalOR: TokenType + logicalAND: TokenType + bitwiseOR: TokenType + bitwiseXOR: TokenType + bitwiseAND: TokenType + equality: TokenType + relational: TokenType + bitShift: TokenType + plusMin: TokenType + modulo: TokenType + star: TokenType + slash: TokenType + starstar: TokenType + coalesce: TokenType + + _break: TokenType + _case: TokenType + _catch: TokenType + _continue: TokenType + _debugger: TokenType + _default: TokenType + _do: TokenType + _else: TokenType + _finally: TokenType + _for: TokenType + _function: TokenType + _if: TokenType + _return: TokenType + _switch: TokenType + _throw: TokenType + _try: TokenType + _var: TokenType + _const: TokenType + _while: TokenType + _with: TokenType + _new: TokenType + _this: TokenType + _super: TokenType + _class: TokenType + _extends: TokenType + _export: TokenType + _import: TokenType + _null: TokenType + _true: TokenType + _false: TokenType + _in: TokenType + _instanceof: TokenType + _typeof: TokenType + _void: TokenType + _delete: TokenType +} + +export interface Comment { + type: "Line" | "Block" + value: string + start: number + end: number + loc?: SourceLocation + range?: [number, number] +} + +export class Token { + type: TokenType + start: number + end: number + loc?: SourceLocation + range?: [number, number] +} + +export const version: string diff --git a/deps/acorn/acorn/dist/acorn.js b/deps/acorn/acorn/dist/acorn.js index 62e1aa63d0974f..3a6a3a2aeed54c 100644 --- a/deps/acorn/acorn/dist/acorn.js +++ b/deps/acorn/acorn/dist/acorn.js @@ -8,10 +8,10 @@ var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 81, 2, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 9, 5351, 0, 7, 14, 13835, 9, 87, 9, 39, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4706, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 983, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; // This file was generated. Do not modify manually! - var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 4026, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 757, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938, 6, 4191]; + var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 4026, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 757, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 4191]; // This file was generated. Do not modify manually! - var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; + var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65"; // This file was generated. Do not modify manually! var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ca\ua7d0\ua7d1\ua7d3\ua7d5-\ua7d9\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; @@ -279,8 +279,10 @@ toString.call(obj) === "[object Array]" ); }); + var regexpCache = Object.create(null); + function wordsRegexp(words) { - return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") + return regexpCache[words] || (regexpCache[words] = new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")) } function codePointToString(code) { @@ -340,11 +342,11 @@ // Can be either `"script"` or `"module"`. This influences global // strict mode and parsing of `import` and `export` declarations. sourceType: "script", - // `onInsertedSemicolon` can be a callback that will be called - // when a semicolon is automatically inserted. It will be passed - // the position of the comma as an offset, and if `locations` is - // enabled, it is given the location as a `{line, column}` object - // as second argument. + // `onInsertedSemicolon` can be a callback that will be called when + // a semicolon is automatically inserted. It will be passed the + // position of the inserted semicolon as an offset, and if + // `locations` is enabled, it is given the location as a `{line, + // column}` object as second argument. onInsertedSemicolon: null, // `onTrailingComma` is similar to `onInsertedSemicolon`, but for // trailing commas. @@ -397,6 +399,8 @@ // passed, the full `{line, column}` locations of the start and // end of the comments. Note that you are not allowed to call the // parser from the callback—that will corrupt its internal state. + // When this option has an array as value, objects representing the + // comments are pushed to it. onComment: null, // Nodes have their start and end characters offsets recorded in // `start` and `end` properties (directly on the node, rather than @@ -1772,8 +1776,6 @@ { this.checkPatternExport(exports, pat.left); } else if (type === "RestElement") { this.checkPatternExport(exports, pat.argument); } - else if (type === "ParenthesizedExpression") - { this.checkPatternExport(exports, pat.expression); } }; pp$8.checkVariableExport = function(exports, decls) { @@ -2337,7 +2339,7 @@ { this.exprAllowed = type.beforeExpr; } }; - // Used to handle egde cases when token context could not be inferred correctly during tokenization phase + // Used to handle edge cases when token context could not be inferred correctly during tokenization phase pp$6.overrideContext = function(tokenCtx) { if (this.curContext() !== tokenCtx) { @@ -2390,6 +2392,11 @@ this.exprAllowed = false; }; + types$1.colon.updateContext = function() { + if (this.curContext().token === "function") { this.context.pop(); } + this.exprAllowed = true; + }; + types$1.backQuote.updateContext = function() { if (this.curContext() === types.q_tmpl) { this.context.pop(); } @@ -2935,12 +2942,14 @@ // Consume `import` as an identifier for `import.meta`. // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`. if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); } - var meta = this.parseIdent(true); + this.next(); if (this.type === types$1.parenL && !forNew) { return this.parseDynamicImport(node) } else if (this.type === types$1.dot) { - node.meta = meta; + var meta = this.startNodeAt(node.start, node.loc && node.loc.start); + meta.name = "import"; + node.meta = this.finishNode(meta, "Identifier"); return this.parseImportMeta(node) } else { this.unexpected(); @@ -3088,9 +3097,12 @@ pp$5.parseNew = function() { if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); } var node = this.startNode(); - var meta = this.parseIdent(true); - if (this.options.ecmaVersion >= 6 && this.eat(types$1.dot)) { - node.meta = meta; + this.next(); + if (this.options.ecmaVersion >= 6 && this.type === types$1.dot) { + var meta = this.startNodeAt(node.start, node.loc && node.loc.start); + meta.name = "new"; + node.meta = this.finishNode(meta, "Identifier"); + this.next(); var containsEsc = this.containsEsc; node.property = this.parseIdent(true); if (node.property.name !== "target") @@ -3492,6 +3504,7 @@ (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { this.context.pop(); } + this.type = types$1.name; } else { this.unexpected(); } @@ -5914,7 +5927,7 @@ // [walk]: util/walk.js - var version = "8.10.0"; + var version = "8.11.3"; Parser.acorn = { Parser: Parser, @@ -5939,11 +5952,10 @@ }; // The main exported interface (under `self.acorn` when in the - // browser) is a `parse` function that takes a code string and - // returns an abstract syntax tree as specified by [Mozilla parser - // API][api]. + // browser) is a `parse` function that takes a code string and returns + // an abstract syntax tree as specified by the [ESTree spec][estree]. // - // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API + // [estree]: https://github.com/estree/estree function parse(input, options) { return Parser.parse(input, options) diff --git a/deps/acorn/acorn/dist/acorn.mjs b/deps/acorn/acorn/dist/acorn.mjs index 119eff98d4ded6..d1f81ef48511a4 100644 --- a/deps/acorn/acorn/dist/acorn.mjs +++ b/deps/acorn/acorn/dist/acorn.mjs @@ -2,10 +2,10 @@ var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 81, 2, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 9, 5351, 0, 7, 14, 13835, 9, 87, 9, 39, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4706, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 983, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; // This file was generated. Do not modify manually! -var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 4026, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 757, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938, 6, 4191]; +var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 4026, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 757, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 4191]; // This file was generated. Do not modify manually! -var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; +var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65"; // This file was generated. Do not modify manually! var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ca\ua7d0\ua7d1\ua7d3\ua7d5-\ua7d9\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; @@ -273,8 +273,10 @@ var isArray = Array.isArray || (function (obj) { return ( toString.call(obj) === "[object Array]" ); }); +var regexpCache = Object.create(null); + function wordsRegexp(words) { - return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") + return regexpCache[words] || (regexpCache[words] = new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")) } function codePointToString(code) { @@ -334,11 +336,11 @@ var defaultOptions = { // Can be either `"script"` or `"module"`. This influences global // strict mode and parsing of `import` and `export` declarations. sourceType: "script", - // `onInsertedSemicolon` can be a callback that will be called - // when a semicolon is automatically inserted. It will be passed - // the position of the comma as an offset, and if `locations` is - // enabled, it is given the location as a `{line, column}` object - // as second argument. + // `onInsertedSemicolon` can be a callback that will be called when + // a semicolon is automatically inserted. It will be passed the + // position of the inserted semicolon as an offset, and if + // `locations` is enabled, it is given the location as a `{line, + // column}` object as second argument. onInsertedSemicolon: null, // `onTrailingComma` is similar to `onInsertedSemicolon`, but for // trailing commas. @@ -391,6 +393,8 @@ var defaultOptions = { // passed, the full `{line, column}` locations of the start and // end of the comments. Note that you are not allowed to call the // parser from the callback—that will corrupt its internal state. + // When this option has an array as value, objects representing the + // comments are pushed to it. onComment: null, // Nodes have their start and end characters offsets recorded in // `start` and `end` properties (directly on the node, rather than @@ -1766,8 +1770,6 @@ pp$8.checkPatternExport = function(exports, pat) { { this.checkPatternExport(exports, pat.left); } else if (type === "RestElement") { this.checkPatternExport(exports, pat.argument); } - else if (type === "ParenthesizedExpression") - { this.checkPatternExport(exports, pat.expression); } }; pp$8.checkVariableExport = function(exports, decls) { @@ -2331,7 +2333,7 @@ pp$6.updateContext = function(prevType) { { this.exprAllowed = type.beforeExpr; } }; -// Used to handle egde cases when token context could not be inferred correctly during tokenization phase +// Used to handle edge cases when token context could not be inferred correctly during tokenization phase pp$6.overrideContext = function(tokenCtx) { if (this.curContext() !== tokenCtx) { @@ -2384,6 +2386,11 @@ types$1._function.updateContext = types$1._class.updateContext = function(prevTy this.exprAllowed = false; }; +types$1.colon.updateContext = function() { + if (this.curContext().token === "function") { this.context.pop(); } + this.exprAllowed = true; +}; + types$1.backQuote.updateContext = function() { if (this.curContext() === types.q_tmpl) { this.context.pop(); } @@ -2929,12 +2936,14 @@ pp$5.parseExprImport = function(forNew) { // Consume `import` as an identifier for `import.meta`. // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`. if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); } - var meta = this.parseIdent(true); + this.next(); if (this.type === types$1.parenL && !forNew) { return this.parseDynamicImport(node) } else if (this.type === types$1.dot) { - node.meta = meta; + var meta = this.startNodeAt(node.start, node.loc && node.loc.start); + meta.name = "import"; + node.meta = this.finishNode(meta, "Identifier"); return this.parseImportMeta(node) } else { this.unexpected(); @@ -3082,9 +3091,12 @@ var empty = []; pp$5.parseNew = function() { if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); } var node = this.startNode(); - var meta = this.parseIdent(true); - if (this.options.ecmaVersion >= 6 && this.eat(types$1.dot)) { - node.meta = meta; + this.next(); + if (this.options.ecmaVersion >= 6 && this.type === types$1.dot) { + var meta = this.startNodeAt(node.start, node.loc && node.loc.start); + meta.name = "new"; + node.meta = this.finishNode(meta, "Identifier"); + this.next(); var containsEsc = this.containsEsc; node.property = this.parseIdent(true); if (node.property.name !== "target") @@ -3486,6 +3498,7 @@ pp$5.parseIdentNode = function() { (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { this.context.pop(); } + this.type = types$1.name; } else { this.unexpected(); } @@ -5908,7 +5921,7 @@ pp.readWord = function() { // [walk]: util/walk.js -var version = "8.10.0"; +var version = "8.11.3"; Parser.acorn = { Parser: Parser, @@ -5933,11 +5946,10 @@ Parser.acorn = { }; // The main exported interface (under `self.acorn` when in the -// browser) is a `parse` function that takes a code string and -// returns an abstract syntax tree as specified by [Mozilla parser -// API][api]. +// browser) is a `parse` function that takes a code string and returns +// an abstract syntax tree as specified by the [ESTree spec][estree]. // -// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API +// [estree]: https://github.com/estree/estree function parse(input, options) { return Parser.parse(input, options) diff --git a/deps/acorn/acorn/package.json b/deps/acorn/acorn/package.json index 4243aa3542deb3..1b8dc76afc3cf5 100644 --- a/deps/acorn/acorn/package.json +++ b/deps/acorn/acorn/package.json @@ -16,7 +16,7 @@ ], "./package.json": "./package.json" }, - "version": "8.10.0", + "version": "8.11.3", "engines": { "node": ">=0.4.0" }, diff --git a/deps/ada/ada.cpp b/deps/ada/ada.cpp index 9641cce39cda12..bff36abb835760 100644 --- a/deps/ada/ada.cpp +++ b/deps/ada/ada.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2024-01-29 13:13:24 -0500. Do not edit! */ +/* auto-generated on 2024-04-11 16:39:11 -0400. Do not edit! */ /* begin file src/ada.cpp */ #include "ada.h" /* begin file src/checkers.cpp */ @@ -11585,7 +11585,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { } } } else { // slow path - std::string _buffer = std::string(input); + std::string _buffer(input); // Next function is only valid if the input is ASCII and returns false // otherwise, but it seems that we always have ascii content so we do not // need to check the return value. @@ -13227,7 +13227,7 @@ template } } } else { // slow path - std::string _buffer = std::string(input); + std::string _buffer(input); // Next function is only valid if the input is ASCII and returns false // otherwise, but it seems that we always have ascii content so we do not // need to check the return value. @@ -13683,7 +13683,7 @@ bool url_aggregator::set_host_or_hostname(const std::string_view input) { return false; } - std::string previous_host = std::string(get_hostname()); + std::string previous_host(get_hostname()); uint32_t previous_port = components.port; size_t host_end_pos = input.find('#'); @@ -14983,7 +14983,7 @@ bool ada_can_parse(const char* input, size_t length) noexcept { bool ada_can_parse_with_base(const char* input, size_t input_length, const char* base, size_t base_length) noexcept { - auto base_view = std::string_view(base, base_length); + std::string_view base_view(base, base_length); return ada::can_parse(std::string_view(input, input_length), &base_view); } @@ -15388,14 +15388,18 @@ ada_owned_string ada_search_params_to_string(ada_url_search_params result) { size_t ada_search_params_size(ada_url_search_params result) { ada::result& r = *(ada::result*)result; - if (!r) return 0; + if (!r) { + return 0; + } return r->size(); } void ada_search_params_sort(ada_url_search_params result) { ada::result& r = *(ada::result*)result; - if (r) r->sort(); + if (r) { + r->sort(); + } } void ada_search_params_append(ada_url_search_params result, const char* key, @@ -15444,7 +15448,9 @@ bool ada_search_params_has(ada_url_search_params result, const char* key, size_t key_length) { ada::result& r = *(ada::result*)result; - if (!r) return false; + if (!r) { + return false; + } return r->has(std::string_view(key, key_length)); } @@ -15453,7 +15459,9 @@ bool ada_search_params_has_value(ada_url_search_params result, const char* key, size_t value_length) { ada::result& r = *(ada::result*)result; - if (!r) return false; + if (!r) { + return false; + } return r->has(std::string_view(key, key_length), std::string_view(value, value_length)); } @@ -15462,9 +15470,13 @@ ada_string ada_search_params_get(ada_url_search_params result, const char* key, size_t key_length) { ada::result& r = *(ada::result*)result; - if (!r) return ada_string_create(NULL, 0); + if (!r) { + return ada_string_create(NULL, 0); + } auto found = r->get(std::string_view(key, key_length)); - if (!found.has_value()) return ada_string_create(NULL, 0); + if (!found.has_value()) { + return ada_string_create(NULL, 0); + } return ada_string_create(found->data(), found->length()); } @@ -15522,14 +15534,18 @@ void ada_free_strings(ada_strings result) { size_t ada_strings_size(ada_strings result) { ada::result>* r = (ada::result>*)result; - if (!r) return 0; + if (!r) { + return 0; + } return (*r)->size(); } ada_string ada_strings_get(ada_strings result, size_t index) { ada::result>* r = (ada::result>*)result; - if (!r) return ada_string_create(NULL, 0); + if (!r) { + return ada_string_create(NULL, 0); + } std::string_view view = (*r)->at(index); return ada_string_create(view.data(), view.length()); } @@ -15544,9 +15560,13 @@ ada_string ada_search_params_keys_iter_next( ada_url_search_params_keys_iter result) { ada::result* r = (ada::result*)result; - if (!r) return ada_string_create(NULL, 0); + if (!r) { + return ada_string_create(NULL, 0); + } auto next = (*r)->next(); - if (!next.has_value()) return ada_string_create(NULL, 0); + if (!next.has_value()) { + return ada_string_create(NULL, 0); + } return ada_string_create(next->data(), next->length()); } @@ -15554,7 +15574,9 @@ bool ada_search_params_keys_iter_has_next( ada_url_search_params_keys_iter result) { ada::result* r = (ada::result*)result; - if (!r) return false; + if (!r) { + return false; + } return (*r)->has_next(); } @@ -15569,9 +15591,13 @@ ada_string ada_search_params_values_iter_next( ada_url_search_params_values_iter result) { ada::result* r = (ada::result*)result; - if (!r) return ada_string_create(NULL, 0); + if (!r) { + return ada_string_create(NULL, 0); + } auto next = (*r)->next(); - if (!next.has_value()) return ada_string_create(NULL, 0); + if (!next.has_value()) { + return ada_string_create(NULL, 0); + } return ada_string_create(next->data(), next->length()); } @@ -15579,7 +15605,9 @@ bool ada_search_params_values_iter_has_next( ada_url_search_params_values_iter result) { ada::result* r = (ada::result*)result; - if (!r) return false; + if (!r) { + return false; + } return (*r)->has_next(); } @@ -15596,8 +15624,9 @@ ada_string_pair ada_search_params_entries_iter_next( (ada::result*)result; if (!r) return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)}; auto next = (*r)->next(); - if (!next.has_value()) + if (!next.has_value()) { return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)}; + } return ada_string_pair{ ada_string_create(next->first.data(), next->first.length()), ada_string_create(next->second.data(), next->second.length())}; @@ -15607,7 +15636,9 @@ bool ada_search_params_entries_iter_has_next( ada_url_search_params_entries_iter result) { ada::result* r = (ada::result*)result; - if (!r) return false; + if (!r) { + return false; + } return (*r)->has_next(); } diff --git a/deps/ada/ada.h b/deps/ada/ada.h index 03a22534d3f87c..b9e000b841d1ed 100644 --- a/deps/ada/ada.h +++ b/deps/ada/ada.h @@ -1,4 +1,4 @@ -/* auto-generated on 2024-01-29 13:13:24 -0500. Do not edit! */ +/* auto-generated on 2024-04-11 16:39:11 -0400. Do not edit! */ /* begin file include/ada.h */ /** * @file ada.h @@ -461,9 +461,11 @@ namespace ada { #ifdef ADA_VISUAL_STUDIO #define ADA_ASSUME(COND) __assume(COND) #else -#define ADA_ASSUME(COND) \ - do { \ - if (!(COND)) __builtin_unreachable(); \ +#define ADA_ASSUME(COND) \ + do { \ + if (!(COND)) { \ + __builtin_unreachable(); \ + } \ } while (0) #endif @@ -482,6 +484,9 @@ namespace ada { #include /** + * These functions are not part of our public API and may + * change at any time. + * @private * @namespace ada::character_sets * @brief Includes the definitions for unicode character sets. */ @@ -492,6 +497,11 @@ ada_really_inline bool bit_at(const uint8_t a[], uint8_t i); #endif // ADA_CHARACTER_SETS_H /* end file include/ada/character_sets.h */ +/** + * These functions are not part of our public API and may + * change at any time. + * @private + */ namespace ada::character_sets { constexpr char hex[1024] = @@ -936,19 +946,19 @@ constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32] = { // 20 21 22 23 24 25 26 27 0x00 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, // 28 29 2A 2B 2C 2D 2E 2F - 0x01 | 0x02 | 0x00 | 0x08 | 0x10 | 0x00 | 0x00 | 0x00, + 0x01 | 0x02 | 0x00 | 0x08 | 0x10 | 0x00 | 0x00 | 0x80, // 30 31 32 33 34 35 36 37 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 38 39 3A 3B 3C 3D 3E 3F - 0x00 | 0x00 | 0x00 | 0x00 | 0x10 | 0x00 | 0x40 | 0x80, + 0x00 | 0x00 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, // 40 41 42 43 44 45 46 47 - 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + 0x01 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 48 49 4A 4B 4C 4D 4E 4F 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 50 51 52 53 54 55 56 57 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 58 59 5A 5B 5C 5D 5E 5F - 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + 0x00 | 0x00 | 0x00 | 0x08 | 0x00 | 0x20 | 0x40 | 0x00, // 60 61 62 63 64 65 66 67 0x01 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 68 69 6A 6B 6C 6D 6E 6F @@ -956,7 +966,7 @@ constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32] = { // 70 71 72 73 74 75 76 77 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 78 79 7A 7B 7C 7D 7E 7F - 0x00 | 0x00 | 0x00 | 0x08 | 0x00 | 0x20 | 0x40 | 0x80, + 0x00 | 0x00 | 0x00 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, // 80 81 82 83 84 85 86 87 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, // 88 89 8A 8B 8C 8D 8E 8F @@ -1064,7 +1074,7 @@ ada_really_inline bool begins_with(std::string_view view, } // namespace ada::checkers -#endif // ADA_CHECKERS_H +#endif // ADA_CHECKERS_INL_H /* end file include/ada/checkers-inl.h */ /* begin file include/ada/log.h */ /** @@ -1540,6 +1550,9 @@ struct url_base { #include /** + * These functions are not part of our public API and may + * change at any time. + * * @private * @namespace ada::helpers * @brief Includes the definitions for helper functions @@ -1702,6 +1715,7 @@ inline void inner_concat(std::string& buffer, T t, Args... args) { } /** + * @private * Concatenate the arguments and return a string. * @returns a string */ @@ -1713,6 +1727,7 @@ std::string concat(Args... args) { } /** + * @private * @return Number of leading zeroes. */ inline int leading_zeroes(uint32_t input_num) noexcept { @@ -1726,6 +1741,7 @@ inline int leading_zeroes(uint32_t input_num) noexcept { } /** + * @private * Counts the number of decimal digits necessary to represent x. * faster than std::to_string(x).size(). * @return digit count @@ -4335,6 +4351,30 @@ constexpr std::string_view is_special_list[] = {"http", " ", "https", "ws", constexpr uint16_t special_ports[] = {80, 0, 443, 80, 21, 443, 0, 0}; } // namespace details +/**** + * @private + * In is_special, get_scheme_type, and get_special_port, we + * use a standard hashing technique to find the index of the scheme in + * the is_special_list. The hashing technique is based on the size of + * the scheme and the first character of the scheme. It ensures that we + * do at most one string comparison per call. If the protocol is + * predictible (e.g., it is always "http"), we can get a better average + * performance by using a simpler approach where we loop and compare + * scheme with all possible protocols starting with the most likely + * protocol. Doing multiple comparisons may have a poor worst case + * performance, however. In this instance, we choose a potentially + * slightly lower best-case performance for a better worst-case + * performance. We can revisit this choice at any time. + * + * Reference: + * Schmidt, Douglas C. "Gperf: A perfect hash function generator." + * More C++ gems 17 (2000). + * + * Reference: https://en.wikipedia.org/wiki/Perfect_hash_function + * + * Reference: https://github.com/ada-url/ada/issues/617 + ****/ + ada_really_inline constexpr bool is_special(std::string_view scheme) { if (scheme.empty()) { return false; @@ -4434,12 +4474,17 @@ std::string ipv4(uint64_t address) noexcept; #include /** + * Unicode operations. These functions are not part of our public API and may + * change at any time. + * + * @private * @namespace ada::unicode * @brief Includes the definitions for unicode operations */ namespace ada::unicode { /** + * @private * We receive a UTF-8 string representing a domain name. * If the string is percent encoded, we apply percent decoding. * @@ -4483,11 +4528,13 @@ bool to_ascii(std::optional& out, std::string_view plain, size_t first_percent); /** + * @private * @see https://www.unicode.org/reports/tr46/#ToUnicode */ std::string to_unicode(std::string_view input); /** + * @private * Checks if the input has tab or newline characters. * * @attention The has_tabs_or_newline function is a bottleneck and it is simple @@ -4497,12 +4544,14 @@ ada_really_inline bool has_tabs_or_newline( std::string_view user_input) noexcept; /** + * @private * Checks if the input is a forbidden host code point. * @see https://url.spec.whatwg.org/#forbidden-host-code-point */ ada_really_inline constexpr bool is_forbidden_host_code_point(char c) noexcept; /** + * @private * Checks if the input contains a forbidden domain code point. * @see https://url.spec.whatwg.org/#forbidden-domain-code-point */ @@ -4510,6 +4559,7 @@ ada_really_inline constexpr bool contains_forbidden_domain_code_point( const char* input, size_t length) noexcept; /** + * @private * Checks if the input contains a forbidden domain code point in which case * the first bit is set to 1. If the input contains an upper case ASCII letter, * then the second bit is set to 1. @@ -4520,6 +4570,7 @@ contains_forbidden_domain_code_point_or_upper(const char* input, size_t length) noexcept; /** + * @private * Checks if the input is a forbidden domain code point. * @see https://url.spec.whatwg.org/#forbidden-domain-code-point */ @@ -4527,11 +4578,13 @@ ada_really_inline constexpr bool is_forbidden_domain_code_point( char c) noexcept; /** + * @private * Checks if the input is alphanumeric, '+', '-' or '.' */ ada_really_inline constexpr bool is_alnum_plus(char c) noexcept; /** + * @private * @details An ASCII hex digit is an ASCII upper hex digit or ASCII lower hex * digit. An ASCII upper hex digit is an ASCII digit or a code point in the * range U+0041 (A) to U+0046 (F), inclusive. An ASCII lower hex digit is an @@ -4540,6 +4593,7 @@ ada_really_inline constexpr bool is_alnum_plus(char c) noexcept; ada_really_inline constexpr bool is_ascii_hex_digit(char c) noexcept; /** + * @private * Checks if the input is a C0 control or space character. * * @details A C0 control or space is a C0 control or U+0020 SPACE. @@ -4549,6 +4603,7 @@ ada_really_inline constexpr bool is_ascii_hex_digit(char c) noexcept; ada_really_inline constexpr bool is_c0_control_or_space(char c) noexcept; /** + * @private * Checks if the input is a ASCII tab or newline character. * * @details An ASCII tab or newline is U+0009 TAB, U+000A LF, or U+000D CR. @@ -4556,6 +4611,7 @@ ada_really_inline constexpr bool is_c0_control_or_space(char c) noexcept; ada_really_inline constexpr bool is_ascii_tab_or_newline(char c) noexcept; /** + * @private * @details A double-dot path segment must be ".." or an ASCII case-insensitive * match for ".%2e", "%2e.", or "%2e%2e". */ @@ -4563,6 +4619,7 @@ ada_really_inline ada_constexpr bool is_double_dot_path_segment( std::string_view input) noexcept; /** + * @private * @details A single-dot path segment must be "." or an ASCII case-insensitive * match for "%2e". */ @@ -4570,17 +4627,20 @@ ada_really_inline constexpr bool is_single_dot_path_segment( std::string_view input) noexcept; /** + * @private * @details ipv4 character might contain 0-9 or a-f character ranges. */ ada_really_inline constexpr bool is_lowercase_hex(char c) noexcept; /** + * @private * @details Convert hex to binary. Caller is responsible to ensure that * the parameter is an hexadecimal digit (0-9, A-F, a-f). */ ada_really_inline unsigned constexpr convert_hex_to_binary(char c) noexcept; /** + * @private * first_percent should be = input.find('%') * * @todo It would be faster as noexcept maybe, but it could be unsafe since. @@ -4591,12 +4651,14 @@ ada_really_inline unsigned constexpr convert_hex_to_binary(char c) noexcept; std::string percent_decode(std::string_view input, size_t first_percent); /** + * @private * Returns a percent-encoding string whether percent encoding was needed or not. * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 */ std::string percent_encode(std::string_view input, const uint8_t character_set[]); /** + * @private * Returns a percent-encoded string version of input, while starting the percent * encoding at the provided index. * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 @@ -4604,6 +4666,7 @@ std::string percent_encode(std::string_view input, std::string percent_encode(std::string_view input, const uint8_t character_set[], size_t index); /** + * @private * Returns true if percent encoding was needed, in which case, we store * the percent-encoded content in 'out'. If the boolean 'append' is set to * true, the content is appended to 'out'. @@ -4614,12 +4677,14 @@ template bool percent_encode(std::string_view input, const uint8_t character_set[], std::string& out); /** + * @private * Returns the index at which percent encoding should start, or (equivalently), * the length of the prefix that does not require percent encoding. */ ada_really_inline size_t percent_encode_index(std::string_view input, const uint8_t character_set[]); /** + * @private * Lowers the string in-place, assuming that the content is ASCII. * Return true if the content was ASCII. */ @@ -4957,12 +5022,16 @@ inline std::ostream &operator<<(std::ostream &out, const ada::url &u); #include /** + * These functions are not part of our public API and may + * change at any time. + * @private * @namespace ada::checkers * @brief Includes the definitions for validation functions */ namespace ada::checkers { /** + * @private * Assuming that x is an ASCII letter, this function returns the lower case * equivalent. * @details More likely to be inlined by the compiler and constexpr. @@ -4970,6 +5039,7 @@ namespace ada::checkers { constexpr char to_lower(char x) noexcept; /** + * @private * Returns true if the character is an ASCII letter. Equivalent to std::isalpha * but more likely to be inlined by the compiler. * @@ -4978,6 +5048,7 @@ constexpr char to_lower(char x) noexcept; constexpr bool is_alpha(char x) noexcept; /** + * @private * Check whether a string starts with 0x or 0X. The function is only * safe if input.size() >=2. * @@ -4985,17 +5056,20 @@ constexpr bool is_alpha(char x) noexcept; */ inline bool has_hex_prefix_unsafe(std::string_view input); /** + * @private * Check whether a string starts with 0x or 0X. */ inline bool has_hex_prefix(std::string_view input); /** + * @private * Check whether x is an ASCII digit. More likely to be inlined than * std::isdigit. */ constexpr bool is_digit(char x) noexcept; /** + * @private * @details A string starts with a Windows drive letter if all of the following * are true: * @@ -5009,6 +5083,7 @@ constexpr bool is_digit(char x) noexcept; inline constexpr bool is_windows_drive_letter(std::string_view input) noexcept; /** + * @private * @details A normalized Windows drive letter is a Windows drive letter of which * the second code point is U+003A (:). */ @@ -5016,12 +5091,14 @@ inline constexpr bool is_normalized_windows_drive_letter( std::string_view input) noexcept; /** + * @private * @warning Will be removed when Ada requires C++20. */ ada_really_inline bool begins_with(std::string_view view, std::string_view prefix); /** + * @private * Returns true if an input is an ipv4 address. It is assumed that the string * does not contain uppercase ASCII characters (the input should have been * lowered cased before calling this function) and is not empty. @@ -5029,6 +5106,7 @@ ada_really_inline bool begins_with(std::string_view view, ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept; /** + * @private * Returns a bitset. If the first bit is set, then at least one character needs * percent encoding. If the second bit is set, a \\ is found. If the third bit * is set then we have a dot. If the fourth bit is set, then we have a percent @@ -5038,6 +5116,7 @@ ada_really_inline constexpr uint8_t path_signature( std::string_view input) noexcept; /** + * @private * Returns true if the length of the domain name and its labels are according to * the specifications. The length of the domain must be 255 octets (253 * characters not including the last 2 which are the empty label reserved at the @@ -5589,7 +5668,7 @@ inline std::ostream &operator<<(std::ostream &out, const ada::url &u) { if (query.has_value()) { out.search_start = uint32_t(running_index); running_index += get_search().size(); - if (get_search().size() == 0) { + if (get_search().empty()) { running_index++; } } @@ -5751,6 +5830,10 @@ ada_really_inline size_t url::parse_port(std::string_view view, #include /** + * Unicode operations. These functions are not part of our public API and may + * change at any time. + * + * private * @namespace ada::unicode * @brief Includes the declarations for unicode operations */ @@ -6056,7 +6139,7 @@ inline void url_aggregator::append_base_pathname(const std::string_view input) { ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); #if ADA_DEVELOPMENT_CHECKS // computing the expected password. - std::string path_expected = std::string(get_pathname()); + std::string path_expected(get_pathname()); path_expected.append(input); #endif // ADA_DEVELOPMENT_CHECKS uint32_t ending_index = uint32_t(buffer.size()); @@ -6126,7 +6209,7 @@ inline void url_aggregator::append_base_username(const std::string_view input) { ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); #if ADA_DEVELOPMENT_CHECKS // computing the expected password. - std::string username_expected = std::string(get_username()); + std::string username_expected(get_username()); username_expected.append(input); #endif // ADA_DEVELOPMENT_CHECKS add_authority_slashes_if_needed(); @@ -6156,7 +6239,7 @@ inline void url_aggregator::append_base_username(const std::string_view input) { components.hash_start += difference; } #if ADA_DEVELOPMENT_CHECKS - std::string username_after = std::string(get_username()); + std::string username_after(get_username()); ADA_ASSERT_EQUAL( username_expected, username_after, "append_base_username problem after inserting " + std::string(input)); @@ -6282,7 +6365,7 @@ inline void url_aggregator::append_base_password(const std::string_view input) { components.hash_start += difference; } #if ADA_DEVELOPMENT_CHECKS - std::string password_after = std::string(get_password()); + std::string password_after(get_password()); ADA_ASSERT_EQUAL( password_expected, password_after, "append_base_password problem after inserting " + std::string(input)); @@ -6769,7 +6852,7 @@ struct url_search_params { /** * @see https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior */ - inline std::string to_string(); + inline std::string to_string() const; /** * Returns a simple JS-style iterator over all of the keys in this @@ -6886,12 +6969,12 @@ inline void url_search_params::initialize(std::string_view input) { auto equal = current.find('='); if (equal == std::string_view::npos) { - auto name = std::string(current); + std::string name(current); std::replace(name.begin(), name.end(), '+', ' '); params.emplace_back(unicode::percent_decode(name, name.find('%')), ""); } else { - auto name = std::string(current.substr(0, equal)); - auto value = std::string(current.substr(equal + 1)); + std::string name(current.substr(0, equal)); + std::string value(current.substr(equal + 1)); std::replace(name.begin(), name.end(), '+', ' '); std::replace(value.begin(), value.end(), '+', ' '); @@ -6964,7 +7047,7 @@ inline bool url_search_params::has(std::string_view key, return entry != params.end(); } -inline std::string url_search_params::to_string() { +inline std::string url_search_params::to_string() const { auto character_set = ada::character_sets::WWW_FORM_URLENCODED_PERCENT_ENCODE; std::string out{}; for (size_t i = 0; i < params.size(); i++) { @@ -7049,20 +7132,26 @@ inline bool url_search_params_iter::has_next() { template <> inline std::optional url_search_params_keys_iter::next() { - if (!has_next()) return std::nullopt; + if (!has_next()) { + return std::nullopt; + } return params.params[pos++].first; } template <> inline std::optional url_search_params_values_iter::next() { - if (!has_next()) return std::nullopt; + if (!has_next()) { + return std::nullopt; + } return params.params[pos++].second; } template <> inline std::optional url_search_params_entries_iter::next() { - if (!has_next()) return std::nullopt; + if (!has_next()) { + return std::nullopt; + } return params.params[pos++]; } @@ -7080,14 +7169,14 @@ url_search_params_entries_iter::next() { #ifndef ADA_ADA_VERSION_H #define ADA_ADA_VERSION_H -#define ADA_VERSION "2.7.6" +#define ADA_VERSION "2.7.8" namespace ada { enum { ADA_VERSION_MAJOR = 2, ADA_VERSION_MINOR = 7, - ADA_VERSION_REVISION = 6, + ADA_VERSION_REVISION = 8, }; } // namespace ada diff --git a/deps/cares/CHANGES b/deps/cares/CHANGES index 24a68a89849b67..ae56d4f24bc3d9 100644 --- a/deps/cares/CHANGES +++ b/deps/cares/CHANGES @@ -1,5 +1,250 @@ Changelog for the c-ares project. Generated with git2changes.pl +Version 1.28.1 (30 Mar 2024) + +GitHub (30 Mar 2024) +- [Brad House brought this change] + + release prep for 1.28.1 (#739) + +Brad House (30 Mar 2024) +- ares_search() and ares_getaddrinfo() resolution fails if no search domains + + Due to an error in creating the list of domains to search, if no search + domains were configured, resolution would fail. + + Fixes Issue: #737 + Fix By: Brad House (@bradh352) + +- typo + +Version 1.28.0 (28 Mar 2024) + +GitHub (28 Mar 2024) +- [Brad House brought this change] + + Allow configuration value for NDots to be zero (#735) + + As per Issue #734 some people use `ndots:0` in their configuration which + is allowed by the system resolver but not by c-ares. Add support for + `ndots:0` and add a test case to validate this behavior. + + Fixes Issue: #734 + Fix By: Brad House (@bradh352) + +Brad House (27 Mar 2024) +- typo + +GitHub (27 Mar 2024) +- [Brad House brought this change] + + 1.28.0 release prep (#733) + +Brad House (27 Mar 2024) +- CMake: don't overwrite global required libraries/definitions/includes + + When chain building c-ares, global settings were being unset which + could lead to build problems. + + Fixes Issue: #729 + Fix By: Brad House (@bradh352) + +- remove tests that have been disabled forever + +- clang-format + +- ares_search_dnsrec() takes a const + +- sonarcloud: clean up some minor codesmells + +GitHub (26 Mar 2024) +- [Brad House brought this change] + + mark deprecated functions as such (#732) + + Multiple functions have been deprecated over the years, annotate them + with attribute deprecated. + + When possible show a message about their replacements. + + This is a continuation/completion of PR #706 + + Fix By: Cristian Rodríguez (@crrodriguez) + +Brad House (26 Mar 2024) +- silence clang static analyzer + +- silence coverity + +- coverity: fix mostly bogus warnings + +- fix missing doc + +GitHub (25 Mar 2024) +- [Brad House brought this change] + + Rework internals to pass around `ares_dns_record_t` instead of binary data (#730) + + c-ares has historically passed around raw dns packets in binary form. + Now that we have a new parser, and messages are already parsed + internally, lets pass around that parsed message rather than requiring + multiple parse attempts on the same message. Also add a new + `ares_send_dnsrec()` and `ares_query_dnsrec()` similar to + `ares_search_dnsrec()` added with PR #719 that can return the pointer to + the `ares_dns_record_t` to the caller enqueuing queries and rework + `ares_search_dnsrec()` to use `ares_send_dnsrec()` internally. + + Fix By: Brad House (@bradh352) + +Brad House (23 Mar 2024) +- tests: mockserver is local, shorten timeouts to make test cases run faster to use less CI resources + +- appveyor: disable UWP builds until MSVC version is updated in base image + +GitHub (21 Mar 2024) +- [Faraz brought this change] + + Include netinet6/in6.h (#728) + + On some platforms, "netinet6/in6.h" is not included by "netinet/in.h" + and needs to be included separately. + + Fix By: Faraz (@farazrbx) + +- [Oliver Welsh brought this change] + + Add function ares_search_dnrec() to search for records using the new DNS record parser (#719) + + This PR adds a new function `ares_search_dnsrec()` to search for records + using the new DNS record parser. + + The function takes an arbitrary DNS record object to search (that must + represent a query for a single name). The function takes a new callback + type, `ares_callback_dnsrec`, that is invoked with a parsed DNS record + object rather than the raw buffer(+length). + + The original motivation for this change is to provide support for + [draft-kaplan-enum-sip-routing-04](https://datatracker.ietf.org/doc/html/draft-kaplan-enum-sip-routing-04); + when routing phone calls using an ENUM server, it can be useful to + include identifying source information in an OPT RR options value, to + help select the appropriate route for the call. The new function allows + for more customisable searches like this. + + **Summary of code changes** + + A new function `ares_search_dnsrec()` has been added and exposed. + Moreover, the entire `ares_search_int()` internal code flow has been + refactored to use parsed DNS record objects and the new DNS record + parser. The DNS record object is passed through the `search_query` + structure by encoding/decoding to/from a buffer (if multiple search + domains are used). A helper function `ares_dns_write_query_altname()` is + used to re-write the DNS record object with a new query name (used to + append search domains). + + `ares_search()` is now a wrapper around the new internal code, where the + DNS record object is created based on the name, class and type + parameters. + + The new function uses a new callback type, `ares_callback_dnsrec`. This + is invoked with a parsed DNS record object. For now, we convert from + `ares_callback` to this new type using `ares__dnsrec_convert_cb()`. + + Some functions that are common to both `ares_query()` and + `ares_search()` have been refactored using the new DNS record parser. + See `ares_dns_record_create_query()` and + `ares_dns_query_reply_tostatus()`. + + **Testing** + + A new FV has been added to test the new function, which searches for a + DNS record containing an OPT RR with custom options value. + + As part of this, I needed to enhance the mock DNS server to expect + request text (and assert that it matches actual request text). This is + because the FV needs to check that the request contains the correct OPT + RR. + + **Documentation** + + The man page docs have been updated to describe the new feature. + + **Futures** + + In the future, a new variant of `ares_send()` could be introduced in the + same vein (`ares_send_dnsrec()`). This could be used by + `ares_search_dnsrec()`. Moreover, we could migrate internal code to use + `ares_callback_dnsrec` as the default callback. + + This will help to make the new DNS record parser the norm in C-Ares. + + --------- + + Co-authored-by: Oliver Welsh (@oliverwelsh) + +- [Brad House brought this change] + + Replace configuration file parsers with memory-safe parser (#725) + + Rewrite configuration parsers using new memory safe parsing functions. + After CVE-2024-25629 its obvious that we need to prioritize again on + getting all the hand written parsers with direct pointer manipulation + replaced. They're just not safe and hard to audit. It was yet another + example of 20+yr old code having a memory safety issue just now coming + to light. + + Though these parsers are definitely less efficient, they're written with + memory safety in mind, and any performance difference is going to be + meaningless for something that only happens once a while. + + Fix By: Brad House (@bradh352) + +Brad House (12 Mar 2024) +- skip ubsan/asan on debian arm64 due to the compiler getting killed + +- ares_init potential memory leak + + If initializing using default settings fails, there may be a memory leak of + search domains that were set by system configuration. + + Fixes Issue: #724 + Fix By: Brad House (@bradh352) + +GitHub (12 Mar 2024) +- [Faraz Fallahi brought this change] + + simple implementation for isascii where stdlib isascii is not available (#721) + + Some platforms don't have the isascii() function. Implement as a macro. + + Fix By: Faraz Fallahi (@fffaraz) + +Brad House (11 Mar 2024) +- Doxygen: fix typos + + Fix reported typos in doxygen-style comments. + + Fixes Issue: #722 + Credit: @dzalyalov88 + +- CI: update freebsd image + +- CMake: Fix Chain building if CMAKE runtime paths not set + + This fixes issues created by #708 + + Fix By: Brad House (@bradh352) + +- silence benign warnings + +- Remove acountry completely from code, including manpage + + Since acountry cannot be restored due to nerd.dk being decommissioned, + we should completely remove the manpage and source. This also + will resolve issue #718. + + Fixes Issue: #718 + Fix By: Brad House (@bradh352) + Version 1.27.0 (22 Feb 2024) GitHub (22 Feb 2024) @@ -6100,127 +6345,3 @@ Yang Tse (10 Mar 2013) Daniel Stenberg (9 Mar 2013) - ares.h: there is no ares_free_soa function - -Yang Tse (9 Mar 2013) -- Makefile.am: empty AM_LDFLAGS definition for automake 1.7 compatibility - -- ares_inet_ntop.3: s/socklen_t/ares_socklen_t - -- configure: use XC_LIBTOOL for portability across libtool versions - -- xc-lt-iface.m4: provide XC_LIBTOOL macro - -- Makefile.am: use AM_CPPFLAGS instead of INCLUDES - -- inet_ntop.c: s/socklen_t/ares_socklen_t - -- inet_ntop.c: s/socklen_t/ares_socklen_t for portability - -Daniel Stenberg (19 Feb 2013) -- ares.h: s/socklen_t/ares_socklen_t for portability - -- ares_inet_ntop.3: 4th argument is socklen_t! - -- spell inet correctly! - -- ares_inet_pton/ntop: cleanup - - Make sure that the symbols are always exported and present in c-ares. - - Make the headers prefixed with 'ares'. - - Removed the inet_ntop.h version as it no longer features any content. - -- ares_inet_ntop/ares_inet_pton: added man pages - -Yang Tse (15 Feb 2013) -- [Gisle Vanem brought this change] - - curl_setup_once.h: definition of HAVE_CLOSE_S defines sclose() to close_s() - -- [Gisle Vanem brought this change] - - config-dos.h: define HAVE_CLOSE_S for MSDOS/Watt-32 - -- [Gisle Vanem brought this change] - - config-dos.h: define strerror() to strerror_s_() for High-C - -Daniel Stenberg (13 Feb 2013) -- ares_get_datatype: removed unused function - - it was also wrongly named as internal functions require two underscores - -- ares__bitncmp: use two underscores for private functions - - It used a single one previously making it look like a public one - -- ares__generate_new_id: moved to ares_query.c - - ... and ares__rc4 is turned into a local static function. - -- ares__swap_lists: make private and static - - ... since there's only one user, make it static within ares_process.c - -Yang Tse (13 Feb 2013) -- Makefile.msvc: add four VS version strings - -Daniel Stenberg (13 Feb 2013) -- ares_expand_name.3: clarify how to free the data - -Yang Tse (30 Jan 2013) -- zz40-xc-ovr.m4: fix 'wc' detection - follow-up 2 - - - Fix a pair of single quotes to double quotes. - - URL: http://curl.haxx.se/mail/lib-2013-01/0355.html - Reported by: Tor Arntsen - -- zz40-xc-ovr.m4: fix 'wc' detection - follow-up - - - Take into account that 'wc' may return leading spaces and/or tabs. - - - Set initial IFS to space, tab and newline. - -- zz40-xc-ovr.m4: fix 'wc' detection - - - Take into account that 'wc' may return leading spaces. - - - Set internationalization behavior variables. - - Tor Arntsen analyzed and reported the issue. - - URL: http://curl.haxx.se/mail/lib-2013-01/0351.html - -- zz40-xc-ovr.m4: check another three basic utilities - -- zz40-xc-ovr.m4: 1.0 interface stabilization - - - Stabilization results in 4 public interface m4 macros: - XC_CONFIGURE_PREAMBLE - XC_CONFIGURE_PREAMBLE_VER_MAJOR - XC_CONFIGURE_PREAMBLE_VER_MINOR - XC_CHECK_PATH_SEPARATOR - - Avoid one level of internal indirection - - Update comments - - Drop XC_OVR_ZZ40 macro - -- zz40-xc-ovr.m4: emit witness message in configure BODY - - This avoids witness message in output when running configure --help, - while sending the message to config.log for other configure runs. - -- zz40-xc-ovr.m4: truly do version conditional overriding - - - version conditional overriding - - catch unexpanded XC macros - - fix double words in comments - -- zz40-xc-ovr.m4: fix variable assignment of subshell output bashism - - Tor Arntsen analyzed and reported the issue. - - URL: http://curl.haxx.se/mail/lib-2013-01/0306.html - -- zz40-xc-ovr.m4: reinstate strict AC_REQUIRE macro dependencies diff --git a/deps/cares/CMakeLists.txt b/deps/cares/CMakeLists.txt index e951cafd7b4068..2718ce52b73ff6 100644 --- a/deps/cares/CMakeLists.txt +++ b/deps/cares/CMakeLists.txt @@ -12,10 +12,10 @@ INCLUDE (CheckCSourceCompiles) INCLUDE (CheckStructHasMember) INCLUDE (CheckLibraryExists) -PROJECT (c-ares LANGUAGES C VERSION "1.27.0" ) +PROJECT (c-ares LANGUAGES C VERSION "1.28.1" ) # Set this version before release -SET (CARES_VERSION "1.27.0") +SET (CARES_VERSION "1.28.1") INCLUDE (GNUInstallDirs) # include this *AFTER* PROJECT(), otherwise paths are wrong. @@ -30,7 +30,7 @@ INCLUDE (GNUInstallDirs) # include this *AFTER* PROJECT(), otherwise paths are w # For example, a version of 4:0:2 would generate output such as: # libname.so -> libname.so.2 # libname.so.2 -> libname.so.2.2.0 -SET (CARES_LIB_VERSIONINFO "14:0:12") +SET (CARES_LIB_VERSIONINFO "15:1:13") OPTION (CARES_STATIC "Build as a static library" OFF) @@ -98,7 +98,7 @@ IF (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") SET (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") - SET (PACKAGE_DIRECTORY ${PROJECT_BINARY_DIR}/package) + SET (CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") ENDIF () # Destinations for installing different kinds of targets (pass to install command). @@ -113,11 +113,10 @@ SET (TARGETS_INST_DEST # CHECK_LIBRARY_EXISTS can't be used as it will return true if the function # is found in a different required/dependent library. MACRO (CARES_FUNCTION_IN_LIBRARY func lib var) - - SET (_ORIG_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") + SET (_ORIG_FIL_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") SET (CMAKE_REQUIRED_LIBRARIES ) CHECK_FUNCTION_EXISTS ("${func}" "_CARES_FUNC_IN_LIB_GLOBAL_${func}") - SET (CMAKE_REQUIRED_LIBRARIES "${_ORIG_CMAKE_REQUIRED_LIBRARIES}") + SET (CMAKE_REQUIRED_LIBRARIES "${_ORIG_FIL_CMAKE_REQUIRED_LIBRARIES}") IF ("${_CARES_FUNC_IN_LIB_GLOBAL_${func}}") SET (${var} FALSE) @@ -207,6 +206,7 @@ CHECK_INCLUDE_FILES (malloc.h HAVE_MALLOC_H) CHECK_INCLUDE_FILES (memory.h HAVE_MEMORY_H) CHECK_INCLUDE_FILES (netdb.h HAVE_NETDB_H) CHECK_INCLUDE_FILES (netinet/in.h HAVE_NETINET_IN_H) +CHECK_INCLUDE_FILES (netinet6/in6.h HAVE_NETINET6_IN6_H) # On old MacOS SDK versions, you must include sys/socket.h before net/if.h IF (HAVE_SYS_SOCKET_H) CHECK_INCLUDE_FILES ("sys/socket.h;net/if.h" HAVE_NET_IF_H) @@ -303,7 +303,11 @@ ENDIF () # headers, libraries, and definitions for the detection to work properly # CMAKE_REQUIRED_DEFINITIONS, CMAKE_REQUIRED_LIBRARIES, and # CMAKE_EXTRA_INCLUDE_FILES. When we're done with the detection, we'll -# unset them. +# restore them to their original values (otherwise a parent project +# that tries to set these won't be maintained, see Issue #729) +SET (ORIG_CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEEFINITIONS}) +SET (ORIG_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) +SET (ORIG_CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES}) SET (CMAKE_REQUIRED_DEFINITIONS ${SYSFLAGS}) LIST (APPEND CMAKE_REQUIRED_LIBRARIES ${CARES_DEPENDENT_LIBS}) @@ -323,6 +327,7 @@ CARES_EXTRAINCLUDE_IFSET (HAVE_NETDB_H netdb.h) CARES_EXTRAINCLUDE_IFSET (HAVE_NET_IF_H net/if.h) CARES_EXTRAINCLUDE_IFSET (HAVE_IFADDRS_H ifaddrs.h) CARES_EXTRAINCLUDE_IFSET (HAVE_NETINET_IN_H netinet/in.h) +CARES_EXTRAINCLUDE_IFSET (HAVE_NETINET6_IN6_H netinet6/in6.h) CARES_EXTRAINCLUDE_IFSET (HAVE_NETINET_TCP_H netinet/tcp.h) CARES_EXTRAINCLUDE_IFSET (HAVE_SIGNAL_H signal.h) CARES_EXTRAINCLUDE_IFSET (HAVE_STDLIB_H stdlib.h) @@ -458,10 +463,10 @@ CHECK_SYMBOL_EXISTS (epoll_create1 "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_EPOLL) # from libc. We need to perform a link test instead of a header/symbol test. CHECK_FUNCTION_EXISTS (__system_property_get HAVE___SYSTEM_PROPERTY_GET) -# Unset temporary data -SET (CMAKE_EXTRA_INCLUDE_FILES) -SET (CMAKE_REQUIRED_DEFINITIONS) -SET (CMAKE_REQUIRED_LIBRARIES) +# Restore original values (as per Issue #729) +SET (CMAKE_REQUIRED_DEFINITIONS ${ORIG_CMAKE_REQUIRED_DEEFINITIONS}) +SET (CMAKE_REQUIRED_LIBRARIES ${ORIG_CMAKE_REQUIRED_LIBRARIES}) +SET (CMAKE_EXTRA_INCLUDE_FILES ${ORIG_CMAKE_EXTRA_INCLUDE_FILES}) ################################################################################ diff --git a/deps/cares/Makefile.in b/deps/cares/Makefile.in index d1c663d5488366..928cdc217ee6de 100644 --- a/deps/cares/Makefile.in +++ b/deps/cares/Makefile.in @@ -364,6 +364,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ diff --git a/deps/cares/Makefile.msvc b/deps/cares/Makefile.msvc index c89454ec155d94..f6e8f4e71f2e6f 100644 --- a/deps/cares/Makefile.msvc +++ b/deps/cares/Makefile.msvc @@ -229,7 +229,7 @@ LINK_CMD_EXE_DBG = $(LINK_CMD_EXE) /debug $(PDBTYPE_CONSOLIDATE) CARES_TARGET = $(STA_LIB_REL).lib CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DCARES_STATICLIB CARES_LFLAGS = -SPROG_CFLAGS = /DCARES_STATICLIB +SPROG_CFLAGS = /DCARES_STATICLIB /DCARES_NO_DEPRECATED SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_REL) $(STA_LIB_REL).lib CARES_LINK = $(LINK_CMD_LIB) SPROG_LINK = $(LINK_CMD_EXE_REL) @@ -240,7 +240,7 @@ CC_CMD = $(CC_CMD_REL) CARES_TARGET = $(STA_LIB_DBG).lib CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DCARES_STATICLIB /DDEBUGBUILD CARES_LFLAGS = -SPROG_CFLAGS = /DCARES_STATICLIB +SPROG_CFLAGS = /DCARES_STATICLIB /DCARES_NO_DEPRECATED SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_DBG) $(STA_LIB_DBG).lib CARES_LINK = $(LINK_CMD_LIB) SPROG_LINK = $(LINK_CMD_EXE_DBG) @@ -251,7 +251,7 @@ CC_CMD = $(CC_CMD_DBG) CARES_TARGET = $(DYN_LIB_REL).dll CARES_CFLAGS = /DCARES_BUILDING_LIBRARY CARES_LFLAGS = /release $(EX_LIBS_REL) /implib:$(CARES_OUTDIR)\$(IMP_LIB_REL).lib $(PDB_NONE) -SPROG_CFLAGS = +SPROG_CFLAGS = /DCARES_NO_DEPRECATED SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_REL) $(IMP_LIB_REL).lib CARES_LINK = $(LINK_CMD_DLL) SPROG_LINK = $(LINK_CMD_EXE_REL) @@ -264,7 +264,7 @@ RC_CMD = $(RC_CMD_REL) CARES_TARGET = $(DYN_LIB_DBG).dll CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DDEBUGBUILD CARES_LFLAGS = /debug $(EX_LIBS_DBG) /implib:$(CARES_OUTDIR)\$(IMP_LIB_DBG).lib /pdb:$(CARES_OUTDIR)\$(DYN_LIB_DBG).pdb $(PDBTYPE_CONSOLIDATE) -SPROG_CFLAGS = +SPROG_CFLAGS = /DCARES_NO_DEPRECATED SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_DBG) $(IMP_LIB_DBG).lib CARES_LINK = $(LINK_CMD_DLL) SPROG_LINK = $(LINK_CMD_EXE_DBG) diff --git a/deps/cares/RELEASE-NOTES.md b/deps/cares/RELEASE-NOTES.md index 0fdcbc6b968488..3a9b9dd9c35fa1 100644 --- a/deps/cares/RELEASE-NOTES.md +++ b/deps/cares/RELEASE-NOTES.md @@ -1,40 +1,49 @@ -## c-ares version 1.27.0 - Feb 23 2024 +## c-ares version 1.28.1 - Mar 30 2024 -This is a security, feature, and bugfix release. +This release contains a fix for a single significant regression introduced +in c-ares 1.28.0. -Security: +* `ares_search()` and `ares_getaddrinfo()` resolution fails if no search domains + are specified. [Issue #737](https://github.com/c-ares/c-ares/issues/737) -* Moderate. CVE-2024-25629. Reading malformatted `/etc/resolv.conf`, - `/etc/nsswitch.conf` or the `HOSTALIASES` file could result in a crash. - [GHSA-mg26-v6qh-x48q](https://github.com/c-ares/c-ares/security/advisories/GHSA-mg26-v6qh-x48q) + +## c-ares version 1.28.0 - Mar 29 2024 + +This is a feature and bugfix release. Features: -* New function `ares_queue_active_queries()` to retrieve number of in-flight - queries. [PR #712](https://github.com/c-ares/c-ares/pull/712) -* New function `ares_queue_wait_empty()` to wait for the number of in-flight - queries to reach zero. [PR #710](https://github.com/c-ares/c-ares/pull/710) -* New `ARES_FLAG_NO_DEFLT_SVR` for `ares_init_options()` to return a failure if - no DNS servers can be found rather than attempting to use `127.0.0.1`. This - also introduces a new ares status code of `ARES_ENOSERVER`. [PR #713](https://github.com/c-ares/c-ares/pull/713) +* Emit warnings when deprecated c-ares functions are used. This can be + disabled by passing a compiler definition of `CARES_NO_DEPRECATED`. [PR #732](https://github.com/c-ares/c-ares/pull/732) +* Add function `ares_search_dnsrec()` to search for records using the new DNS + record data structures. [PR #719](https://github.com/c-ares/c-ares/pull/719) +* Rework internals to pass around `ares_dns_record_t` instead of binary data, + this introduces new public functions of `ares_query_dnsrec()` and + `ares_send_dnsrec()`. [PR #730](https://github.com/c-ares/c-ares/pull/730) Changes: -* EDNS Packet size should be 1232 as per DNS Flag Day. [PR #705](https://github.com/c-ares/c-ares/pull/705) +* tests: when performing simulated queries, reduce timeouts to make tests run + faster +* Replace configuration file parsers with memory-safe parser. [PR #725](https://github.com/c-ares/c-ares/pull/725) +* Remove `acountry` completely, the manpage might still get installed otherwise. [Issue #718](https://github.com/c-ares/c-ares/pull/718) Bugfixes: -* Windows DNS suffix search list memory leak. [PR #711](https://github.com/c-ares/c-ares/pull/711) -* Fix warning due to ignoring return code of `write()`. [PR #709](https://github.com/c-ares/c-ares/pull/709) -* CMake: don't override target output locations if not top-level. [Issue #708](https://github.com/c-ares/c-ares/issues/708) -* Fix building c-ares without thread support. [PR #700](https://github.com/c-ares/c-ares/pull/700) +* CMake: don't overwrite global required libraries/definitions/includes which + could cause build errors for projects chain building c-ares. [Issue #729](https://github.com/c-ares/c-ares/issues/729) +* On some platforms, `netinet6/in6.h` is not included by `netinet/in.h` + and needs to be included separately. [PR #728](https://github.com/c-ares/c-ares/pull/728) +* Fix a potential memory leak in `ares_init()`. [Issue #724](https://github.com/c-ares/c-ares/issues/724) +* Some platforms don't have the `isascii()` function. Implement as a macro. [PR #721](https://github.com/c-ares/c-ares/pull/721) +* CMake: Fix Chain building if CMAKE runtime paths not set +* NDots configuration should allow a value of zero. [PR #735](https://github.com/c-ares/c-ares/pull/735) Thanks go to these friendly people for their efforts and contributions for this release: -* Anthony Alayo (@anthonyalayo) * Brad House (@bradh352) -* Cheng Zhao (@zcbenz) * Cristian Rodríguez (@crrodriguez) * Daniel Stenberg (@bagder) +* Faraz (@farazrbx) +* Faraz Fallahi (@fffaraz) * Oliver Welsh (@oliverwelsh) -* Vojtěch Vobr (@vojtechvobr) diff --git a/deps/cares/aminclude_static.am b/deps/cares/aminclude_static.am index e3fc636c7b51a4..6fa817a8346703 100644 --- a/deps/cares/aminclude_static.am +++ b/deps/cares/aminclude_static.am @@ -1,6 +1,6 @@ # aminclude_static.am generated automatically by Autoconf -# from AX_AM_MACROS_STATIC on Fri Feb 23 08:24:27 CET 2024 +# from AX_AM_MACROS_STATIC on Sat Mar 30 16:17:17 CET 2024 # Code coverage diff --git a/deps/cares/cares.gyp b/deps/cares/cares.gyp index e8ac0b75796e72..053cdf8c8286ad 100644 --- a/deps/cares/cares.gyp +++ b/deps/cares/cares.gyp @@ -26,7 +26,6 @@ 'src/lib/ares__llist.c', 'src/lib/ares__llist.h', 'src/lib/ares__parse_into_addrinfo.c', - 'src/lib/ares__read_line.c', 'src/lib/ares__slist.c', 'src/lib/ares__slist.h', 'src/lib/ares__socket.c', @@ -74,7 +73,6 @@ 'src/lib/ares_library_init.c', 'src/lib/ares_ipv6.h', 'src/lib/ares_math.c', - 'src/lib/ares_mkquery.c', 'src/lib/ares_options.c', 'src/lib/ares_parse_a_reply.c', 'src/lib/ares_parse_aaaa_reply.c', @@ -154,7 +152,15 @@ 'type': '<(library)', 'include_dirs': [ 'include' ], 'direct_dependent_settings': { - 'include_dirs': [ 'include' ] + 'include_dirs': [ 'include' ], + 'cflags': [ '-Wno-error=deprecated-declarations' ], + 'conditions': [ + [ 'OS=="mac"', { + 'xcode_settings': { + 'OTHER_CFLAGS': [ '-Wno-error=deprecated-declarations' ] + } + }] + ] }, 'sources': [ '<@(cares_sources_common)', diff --git a/deps/cares/configure b/deps/cares/configure index ac3c7b55db0565..656164f46e3ad8 100755 --- a/deps/cares/configure +++ b/deps/cares/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for c-ares 1.27.0. +# Generated by GNU Autoconf 2.71 for c-ares 1.28.1. # # Report bugs to . # @@ -621,8 +621,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='c-ares' PACKAGE_TARNAME='c-ares' -PACKAGE_VERSION='1.27.0' -PACKAGE_STRING='c-ares 1.27.0' +PACKAGE_VERSION='1.28.1' +PACKAGE_STRING='c-ares 1.28.1' PACKAGE_BUGREPORT='c-ares mailing list: http://lists.haxx.se/listinfo/c-ares' PACKAGE_URL='' @@ -1420,7 +1420,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures c-ares 1.27.0 to adapt to many kinds of systems. +\`configure' configures c-ares 1.28.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1491,7 +1491,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of c-ares 1.27.0:";; + short | recursive ) echo "Configuration of c-ares 1.28.1:";; esac cat <<\_ACEOF @@ -1627,7 +1627,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -c-ares configure 1.27.0 +c-ares configure 1.28.1 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2251,7 +2251,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by c-ares $as_me 1.27.0, which was +It was created by c-ares $as_me 1.28.1, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3225,7 +3225,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -CARES_VERSION_INFO="14:0:12" +CARES_VERSION_INFO="15:1:13" @@ -5907,7 +5907,7 @@ fi # Define the identity of the package. PACKAGE='c-ares' - VERSION='1.27.0' + VERSION='1.28.1' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -21681,6 +21681,31 @@ if test "x$ac_cv_header_netinet_in_h" = xyes then : printf "%s\n" "#define HAVE_NETINET_IN_H 1" >>confdefs.h +fi +ac_fn_c_check_header_compile "$LINENO" "netinet6/in6.h" "ac_cv_header_netinet6_in6_h" " +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_ARPA_NAMESER_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif + + +" +if test "x$ac_cv_header_netinet6_in6_h" = xyes +then : + printf "%s\n" "#define HAVE_NETINET6_IN6_H 1" >>confdefs.h + fi ac_fn_c_check_header_compile "$LINENO" "netinet/tcp.h" "ac_cv_header_netinet_tcp_h" " #ifdef HAVE_SYS_TYPES_H @@ -25931,7 +25956,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by c-ares $as_me 1.27.0, which was +This file was extended by c-ares $as_me 1.28.1, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -25999,7 +26024,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -c-ares config.status 1.27.0 +c-ares config.status 1.28.1 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/deps/cares/configure.ac b/deps/cares/configure.ac index 1a3ba8c3fc4c49..4d263a7f309017 100644 --- a/deps/cares/configure.ac +++ b/deps/cares/configure.ac @@ -2,10 +2,10 @@ dnl Copyright (C) The c-ares project and its contributors dnl SPDX-License-Identifier: MIT AC_PREREQ([2.69]) -AC_INIT([c-ares], [1.27.0], +AC_INIT([c-ares], [1.28.1], [c-ares mailing list: http://lists.haxx.se/listinfo/c-ares]) -CARES_VERSION_INFO="14:0:12" +CARES_VERSION_INFO="15:1:13" dnl This flag accepts an argument of the form current[:revision[:age]]. So, dnl passing -version-info 3:12:1 sets current to 3, revision to 12, and age to dnl 1. @@ -436,6 +436,7 @@ AC_CHECK_HEADERS( netioapi.h \ netdb.h \ netinet/in.h \ + netinet6/in6.h \ netinet/tcp.h \ net/if.h \ ifaddrs.h \ diff --git a/deps/cares/docs/Makefile.in b/deps/cares/docs/Makefile.in index 4f5bb62409c7ab..8cb46878fa59ee 100644 --- a/deps/cares/docs/Makefile.in +++ b/deps/cares/docs/Makefile.in @@ -263,6 +263,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -357,18 +358,22 @@ MANPAGES = ares_cancel.3 \ ares_dns_rcode_tostr.3 \ ares_dns_record.3 \ ares_dns_record_create.3 \ + ares_dns_record_duplicate.3 \ ares_dns_record_get_flags.3 \ ares_dns_record_get_id.3 \ ares_dns_record_get_opcode.3 \ ares_dns_record_get_rcode.3 \ ares_dns_record_destroy.3 \ ares_dns_record_query_add.3 \ + ares_dns_record_query_set_name.3 \ + ares_dns_record_query_set_type.3 \ ares_dns_record_query_cnt.3 \ ares_dns_record_query_get.3 \ ares_dns_record_rr_add.3 \ ares_dns_record_rr_cnt.3 \ ares_dns_record_rr_del.3 \ ares_dns_record_rr_get.3 \ + ares_dns_record_rr_get_const.3 \ ares_dns_rec_type_fromstr.3 \ ares_dns_rec_type_t.3 \ ares_dns_rr.3 \ @@ -442,10 +447,16 @@ MANPAGES = ares_cancel.3 \ ares_parse_uri_reply.3 \ ares_process.3 \ ares_query.3 \ + ares_query_dnsrec.3 \ + ares_queue.3 \ + ares_queue_active_queries.3 \ + ares_queue_wait_empty.3 \ ares_reinit.3 \ ares_save_options.3 \ ares_search.3 \ + ares_search_dnsrec.3 \ ares_send.3 \ + ares_send_dnsrec.3 \ ares_set_local_dev.3 \ ares_set_local_ip4.3 \ ares_set_local_ip6.3 \ diff --git a/deps/cares/docs/Makefile.inc b/deps/cares/docs/Makefile.inc index 3645a7fcddc58b..882bf2280446d5 100644 --- a/deps/cares/docs/Makefile.inc +++ b/deps/cares/docs/Makefile.inc @@ -20,18 +20,22 @@ MANPAGES = ares_cancel.3 \ ares_dns_rcode_tostr.3 \ ares_dns_record.3 \ ares_dns_record_create.3 \ + ares_dns_record_duplicate.3 \ ares_dns_record_get_flags.3 \ ares_dns_record_get_id.3 \ ares_dns_record_get_opcode.3 \ ares_dns_record_get_rcode.3 \ ares_dns_record_destroy.3 \ ares_dns_record_query_add.3 \ + ares_dns_record_query_set_name.3 \ + ares_dns_record_query_set_type.3 \ ares_dns_record_query_cnt.3 \ ares_dns_record_query_get.3 \ ares_dns_record_rr_add.3 \ ares_dns_record_rr_cnt.3 \ ares_dns_record_rr_del.3 \ ares_dns_record_rr_get.3 \ + ares_dns_record_rr_get_const.3 \ ares_dns_rec_type_fromstr.3 \ ares_dns_rec_type_t.3 \ ares_dns_rr.3 \ @@ -105,13 +109,16 @@ MANPAGES = ares_cancel.3 \ ares_parse_uri_reply.3 \ ares_process.3 \ ares_query.3 \ + ares_query_dnsrec.3 \ ares_queue.3 \ ares_queue_active_queries.3 \ ares_queue_wait_empty.3 \ ares_reinit.3 \ ares_save_options.3 \ ares_search.3 \ + ares_search_dnsrec.3 \ ares_send.3 \ + ares_send_dnsrec.3 \ ares_set_local_dev.3 \ ares_set_local_ip4.3 \ ares_set_local_ip6.3 \ diff --git a/deps/cares/docs/adig.1 b/deps/cares/docs/adig.1 index 48b491b593b73c..59923790587ddd 100644 --- a/deps/cares/docs/adig.1 +++ b/deps/cares/docs/adig.1 @@ -64,4 +64,4 @@ Report bugs to the c-ares mailing list: \fBhttps://lists.haxx.se/listinfo/c-ares\fR .SH "SEE ALSO" .PP -acountry(1), ahost(1). +ahost(1). diff --git a/deps/cares/docs/ahost.1 b/deps/cares/docs/ahost.1 index 5feed981ab62c1..e17057273f8285 100644 --- a/deps/cares/docs/ahost.1 +++ b/deps/cares/docs/ahost.1 @@ -47,4 +47,4 @@ Report bugs to the c-ares mailing list: \fBhttps://lists.haxx.se/listinfo/c-ares\fR .SH "SEE ALSO" .PP -acountry(1), adig(1) +adig(1) diff --git a/deps/cares/docs/ares_dns_record.3 b/deps/cares/docs/ares_dns_record.3 index fe23b5eece60e5..01ce7601aa3199 100644 --- a/deps/cares/docs/ares_dns_record.3 +++ b/deps/cares/docs/ares_dns_record.3 @@ -19,7 +19,7 @@ ares_status_t ares_dns_parse(const unsigned char *buf, size_t buf_len, unsigned int flags, ares_dns_record_t **dnsrec); -ares_status_t ares_dns_write(ares_dns_record_t *dnsrec, +ares_status_t ares_dns_write(const ares_dns_record_t *dnsrec, unsigned char **buf, size_t *buf_len); ares_status_t ares_dns_record_create(ares_dns_record_t **dnsrec, @@ -28,6 +28,8 @@ ares_status_t ares_dns_record_create(ares_dns_record_t **dnsrec, ares_dns_opcode_t opcode, ares_dns_rcode_t rcode); +ares_dns_record_t *ares_dns_record_duplicate(const ares_dns_record_t *dnsrec); + unsigned short ares_dns_record_get_id(const ares_dns_record_t *dnsrec); unsigned short ares_dns_record_get_flags(const ares_dns_record_t *dnsrec); @@ -41,6 +43,14 @@ ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec, ares_dns_rec_type_t qtype, ares_dns_class_t qclass); +ares_status_t ares_dns_record_query_set_name(ares_dns_record_t *dnsrec, + size_t idx, + const char *name); + +ares_status_t ares_dns_record_query_set_type(ares_dns_record_t *dnsrec, + size_t idx, + ares_dns_rec_type_t qtype); + size_t ares_dns_record_query_cnt(const ares_dns_record_t *dnsrec); ares_status_t ares_dns_record_query_get(const ares_dns_record_t *dnsrec, @@ -67,7 +77,7 @@ on requests, and some may only be valid on responses: .B ARES_REC_TYPE_SOA - Start of authority zone .br -.B ARES_REC_TYPE_PTR +.B ARES_REC_TYPE_PTR - Domain name pointer .br .B ARES_REC_TYPE_HINFO @@ -317,6 +327,13 @@ is meant mostly for responses and is passed in the .IR rcode parameter and is typically \fPARES_RCODE_NOERROR\fP. +The \fIares_dns_record_duplicate(3)\fP function duplicates an existing DNS +record structure. This may be useful if needing to save a result as retrieved +from \fIares_send_dnsrec(3)\fP or \fIares_search_dnsrec(3)\fP. The structure +to be duplicated is passed in the +.IR dnsrec +parameter, and the duplicated copy is returned, or NULL on error such as +out of memory. The \fIares_dns_record_get_id(3)\fP function is used to retrieve the DNS message id from the DNS record provided in the @@ -350,6 +367,29 @@ parameter and the question class (typically \fIARES_CLASS_IN\fP) in the .IR qclass parameter. +The \fIares_dns_record_query_set_name(3)\fP function is used to modify the +question name in the DNS record provided in the +.IR dnsrec +parameter. The index of the query, which must be less than +\fIares_dns_record_query_cnt(3)\fP, is provided in the +.IR idx +parameter. The new domain name is provided in the +.IR name +parameter. Care should be taken as this will cause invalidation of any +\fIname\fP pointer retrieved from \fIares_dns_Record_query_get(3)\fP. This +function is useful if sending multiple similar queries without re-creating +the entire DNS query. + +The \fIares_dns_record_query_set_type(3)\fP function is used to modify the +question type in the DNS record provided in the +.IR dnsrec +parameter. The index of the query, which must be less than +\fIares_dns_record_query_cnt(3)\fP, is provided in the +.IR idx +parameter. The new query type is provided in the +.IR qtype +parameter. + The \fIares_dns_record_query_cnt(3)\fP function is used to retrieve the number of DNS questions in the DNS record provided in the .IR dnsrec @@ -363,7 +403,8 @@ parameter. The index provided in the parameter must be less than the value returned from \fIares_dns_record_query_cnt(3)\fP. The DNS question name will be returned in the variable pointed to by the .IR name -parameter, this may be provided as NULL if the name is not needed. +parameter, this may be provided as NULL if the name is not needed. This pointer +will be invalided by any call to \fIares_dns_record_query_set_name(3)\fP. The DNS question type will be returned in the variable pointed to by the .IR qtype parameter, this may be provided as NULL if the type is not needed. diff --git a/deps/cares/docs/ares_dns_record_duplicate.3 b/deps/cares/docs/ares_dns_record_duplicate.3 new file mode 100644 index 00000000000000..4acc581d29789c --- /dev/null +++ b/deps/cares/docs/ares_dns_record_duplicate.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_dns_record.3 diff --git a/deps/cares/docs/ares_dns_record_query_set_name.3 b/deps/cares/docs/ares_dns_record_query_set_name.3 new file mode 100644 index 00000000000000..4acc581d29789c --- /dev/null +++ b/deps/cares/docs/ares_dns_record_query_set_name.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_dns_record.3 diff --git a/deps/cares/docs/ares_dns_record_query_set_type.3 b/deps/cares/docs/ares_dns_record_query_set_type.3 new file mode 100644 index 00000000000000..4acc581d29789c --- /dev/null +++ b/deps/cares/docs/ares_dns_record_query_set_type.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_dns_record.3 diff --git a/deps/cares/docs/ares_dns_record_rr_get_const.3 b/deps/cares/docs/ares_dns_record_rr_get_const.3 new file mode 100644 index 00000000000000..b93e4cd4e37fa8 --- /dev/null +++ b/deps/cares/docs/ares_dns_record_rr_get_const.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_dns_rr.3 diff --git a/deps/cares/docs/ares_dns_rr.3 b/deps/cares/docs/ares_dns_rr.3 index 2999d18e3aa6bb..290859e838e7ef 100644 --- a/deps/cares/docs/ares_dns_rr.3 +++ b/deps/cares/docs/ares_dns_rr.3 @@ -4,14 +4,15 @@ .TH ARES_DNS_RR 3 "12 November 2023" .SH NAME ares_dns_record_rr_add, ares_dns_record_rr_cnt, ares_dns_record_rr_del, -ares_dns_record_rr_get, ares_dns_rr_get_addr, ares_dns_rr_get_addr6, -ares_dns_rr_get_bin, ares_dns_rr_get_class, ares_dns_rr_get_name, -ares_dns_rr_get_opt, ares_dns_rr_get_opt_byid, ares_dns_rr_get_opt_cnt, -ares_dns_rr_get_str, ares_dns_rr_get_ttl, ares_dns_rr_get_type, -ares_dns_rr_get_u16, ares_dns_rr_get_u32, ares_dns_rr_get_u8, ares_dns_rr_key_t, -ares_dns_rr_set_addr, ares_dns_rr_set_addr6, ares_dns_rr_set_bin, -ares_dns_rr_set_opt, ares_dns_rr_set_str, ares_dns_rr_set_u16, -ares_dns_rr_set_u32, ares_dns_rr_set_u8, ares_dns_section_t, ares_tlsa_match_t, +ares_dns_record_rr_get, ares_dns_record_rr_get_const, ares_dns_rr_get_addr, +ares_dns_rr_get_addr6, ares_dns_rr_get_bin, ares_dns_rr_get_class, +ares_dns_rr_get_name, ares_dns_rr_get_opt, ares_dns_rr_get_opt_byid, +ares_dns_rr_get_opt_cnt, ares_dns_rr_get_str, ares_dns_rr_get_ttl, +ares_dns_rr_get_type, ares_dns_rr_get_u16, ares_dns_rr_get_u32, +ares_dns_rr_get_u8, ares_dns_rr_key_t, ares_dns_rr_set_addr, +ares_dns_rr_set_addr6, ares_dns_rr_set_bin, ares_dns_rr_set_opt, +ares_dns_rr_set_str, ares_dns_rr_set_u16, ares_dns_rr_set_u32, +ares_dns_rr_set_u8, ares_dns_section_t, ares_tlsa_match_t, ares_tlsa_selector_t, ares_tlsa_usage_t \- DNS Resource Record creating, reading, and writing functions. .SH SYNOPSIS @@ -33,6 +34,10 @@ ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec, ares_dns_section_t sect, size_t idx); +const ares_dns_rr_t *ares_dns_record_rr_get_const(const ares_dns_record_t *dnsrec, + ares_dns_section_t sect, + size_t idx); + ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec, ares_dns_section_t sect, size_t idx); @@ -357,14 +362,17 @@ parameter, and the Time To Live (TTL) in the parameter. -The \fIares_dns_record_rr_get(3)\fP function is used to retrieve the resource -record pointer from the DNS record provided in the +The \fIares_dns_record_rr_get(3)\fP and \fIares_dns_record_rr_get_const(3)\fP +functions are used to retrieve the resource record pointer from the DNS record +provided in the .IR dnsrec parameter, for the resource record section provided in the .IR sect parameter, for the specified index in the .IR idx -parameter. The index must be less than \fIares_dns_record_rr_cnt(3)\fP. +parameter. The index must be less than \fIares_dns_record_rr_cnt(3)\fP. The +former returns a writable pointer to the resource record, while the latter +returns a read-only pointer to the resource record. The \fIares_dns_record_rr_del(3)\fP is used to delete a resource record from @@ -615,8 +623,8 @@ prescribed datatype values and in general can't fail except for misuse cases, in which a 0 (or NULL) may be returned, however 0 can also be a valid return value for most of these functions. -\fIares_dns_record_rr_get(3)\fP will return the requested resource record -pointer or NULL on failure (misuse). +\fIares_dns_record_rr_get(3)\fP and \fIares_dns_record_rr_get_const(3)\fP will +return the requested resource record pointer or NULL on failure (misuse). \fIares_dns_rr_get_opt_byid(3)\fP will return ARES_TRUE if the option was found, otherwise ARES_FALSE if not found (or misuse). diff --git a/deps/cares/docs/ares_init_options.3 b/deps/cares/docs/ares_init_options.3 index 000cc1d9a592b5..72889b5b4874ef 100644 --- a/deps/cares/docs/ares_init_options.3 +++ b/deps/cares/docs/ares_init_options.3 @@ -158,7 +158,7 @@ before giving up. The default is three tries. The number of dots which must be present in a domain name for it to be queried for "as is" prior to querying for it with the default domain extensions appended. The default value is 1 unless set otherwise by -resolv.conf or the RES_OPTIONS environment variable. +resolv.conf or the RES_OPTIONS environment variable. Valid range is 0-15. .TP 18 .B ARES_OPT_MAXTIMEOUTMS .B int \fImaxtimeout\fP; diff --git a/deps/cares/docs/ares_query.3 b/deps/cares/docs/ares_query.3 index 00e44f52594d90..24decf7009441b 100644 --- a/deps/cares/docs/ares_query.3 +++ b/deps/cares/docs/ares_query.3 @@ -9,19 +9,32 @@ ares_query \- Initiate a single-question DNS query .nf #include -typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, - int \fItimeouts\fP, unsigned char *\fIabuf\fP, - int \fIalen\fP) +typedef void (*ares_callback_dnsrec)(void *arg, ares_status_t status, + size_t timeouts, + const ares_dns_record_t *dnsrec); + +ares_status_t ares_query_dnsrec(ares_channel_t *channel, + const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, + ares_callback_dnsrec callback, + void *arg, + unsigned short *qid); + +typedef void (*ares_callback)(void *arg, int status, + int timeouts, unsigned char *abuf, + int alen); + +void ares_query(ares_channel_t *channel, const char *name, + int dnsclass, int type, + ares_callback callback, void *arg); -void ares_query(ares_channel_t *\fIchannel\fP, const char *\fIname\fP, - int \fIdnsclass\fP, int \fItype\fP, - ares_callback \fIcallback\fP, void *\fIarg\fP) .fi + .SH DESCRIPTION -The -.B ares_query -function initiates a single-question DNS query on the name service -channel identified by + +The \fBares_query_dnsrec(3)\fP and \fBares_query(3)\fP functions initiate a +single-question DNS query on the name service channel identified by .IR channel . The parameter .I name @@ -31,27 +44,27 @@ a label must be escaped with a backslash. The parameters .I dnsclass and .I type -give the class and type of the query using the values defined in -.BR . +give the class and type of the query. + +\fBares_query_dnsrec(3)\fP uses the ares \fBares_dns_class_t\fP and +\fBares_dns_rec_type_t\fP defined types. However, \fBares_query(3)\fP uses +the values defined in \fB\fP. + When the query is complete or has failed, the ares library will invoke .IR callback . -Completion or failure of the query may happen immediately, or may -happen during a later call to -.BR ares_process (3) -or -.BR ares_destroy (3). -.PP +Completion or failure of the query may happen immediately (even before the +return of the function call), or may happen during a later call to +\fBares_process(3)\fP or \fBares_destroy(3)\fP. + If this is called from a thread other than which the main program event loop is running, care needs to be taken to ensure any file descriptor lists are updated immediately within the eventloop. When the associated callback is called, it is called with a channel lock so care must be taken to ensure any processing is minimal to prevent DNS channel stalls. -.PP + The callback argument .I arg -is copied from the -.B ares_query -argument +is copied from the \fBares_query_dnsrec(3)\fP or \fBares_query(3)\fP argument .IR arg . The callback argument .I status @@ -73,9 +86,7 @@ The query completed but the server claims to have experienced a failure. (This code can only occur if the .B ARES_FLAG_NOCHECKRESP flag was specified at channel initialization time; otherwise, such -responses are ignored at the -.BR ares_send (3) -level.) +responses are ignored at the \fBares_send_dnsrec(3)\fP level.) .TP 19 .B ARES_ENOTFOUND The query completed but the queried-for domain name was not found. @@ -85,18 +96,14 @@ The query completed but the server does not implement the operation requested by the query. (This code can only occur if the .B ARES_FLAG_NOCHECKRESP flag was specified at channel initialization time; otherwise, such -responses are ignored at the -.BR ares_send (3) -level.) +responses are ignored at the \fBares_send_dnsrec(3)\fP level.) .TP 19 .B ARES_EREFUSED The query completed but the server refused the query. (This code can only occur if the .B ARES_FLAG_NOCHECKRESP flag was specified at channel initialization time; otherwise, such -responses are ignored at the -.BR ares_send (3) -level.) +responses are ignored at the \fBares_send_dnsrec(3)\fP level.) .TP 19 .B ARES_EBADNAME The query name @@ -126,23 +133,26 @@ is being destroyed; the query will not be completed. The query will not be completed because no DNS servers were configured on the channel. .PP + The callback argument .I timeouts reports how many times a query timed out during the execution of the given request. -.PP + If the query completed (even if there was something wrong with it, as indicated by some of the above error codes), the callback argument +.I dnsrec +or .I abuf -points to a result buffer of length -.IR alen . -If the query did not complete, -.I abuf -will be NULL and -.I alen -will be 0. +will be non-NULL, otherwise they will be NULL. + +.SH AVAILABILITY +\fBares_query_dnsrec(3)\fP was introduced in c-ares 1.28.0. + .SH SEE ALSO -.BR ares_process (3) +.BR ares_process (3), +.BR ares_dns_record (3) + .SH AUTHOR Greg Hudson, MIT Information Systems .br diff --git a/deps/cares/docs/ares_query_dnsrec.3 b/deps/cares/docs/ares_query_dnsrec.3 new file mode 100644 index 00000000000000..b178e987646055 --- /dev/null +++ b/deps/cares/docs/ares_query_dnsrec.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_query.3 diff --git a/deps/cares/docs/ares_queue.3 b/deps/cares/docs/ares_queue.3 new file mode 100644 index 00000000000000..1212e8d3f8c3cc --- /dev/null +++ b/deps/cares/docs/ares_queue.3 @@ -0,0 +1,53 @@ +.\" +.\" SPDX-License-Identifier: MIT +.\" +.TH ARES_QUEUE 3 "16 February 2024" +.SH NAME +ares_queue_wait_empty, ares_queue_active_queries \- Functions for checking the +c-ares queue status +.SH SYNOPSIS +.nf +#include + +size_t ares_queue_active_queries(ares_channel_t *channel); + +ares_status_t ares_queue_wait_empty(ares_channel_t *channel, + int timeout_ms); +.fi +.SH DESCRIPTION +The \fBares_queue_active_queries(3)\fP function retrieves the total number of +active queries pending answers from servers. Some c-ares requests may spawn +multiple queries, such as \fIares_getaddrinfo(3)\fP when using \fIAF_UNSPEC\fP, +which will be reflected in this number. The \fBchannel\fP parameter must be set +to an initialized channel. + +The \fBares_queue_wait_empty(3)\fP function blocks until notified that there are +no longer any queries in queue, or the specified timeout has expired. The +\fBchannel\fP parameter must be set to an initialized channel. The +\fBtimeout_ms\fP parameter is the number of milliseconds to wait for the queue +to be empty or -1 for Infinite. + +.SH RETURN VALUES +\fIares_queue_active_queries(3)\fP returns the active query count. + +\fIares_queue_wait_empty(3)\fP can return any of the following values: +.TP 14 +.B ARES_ENOTIMP +if not built with threading support +.TP 14 +.B ARES_ETIMEOUT +if requested timeout expired +.TP 14 +.B ARES_SUCCESS +when queue is empty. +.TP 14 + +.SH AVAILABILITY +This function was first introduced in c-ares version 1.27.0, and requires the +c-ares library to be built with threading support. + +.SH SEE ALSO +.BR ares_init_options (3), +.BR ares_threadsafety (3) +.SH AUTHOR +Copyright (C) 2024 The c-ares project and its members. diff --git a/deps/cares/docs/ares_queue_active_queries.3 b/deps/cares/docs/ares_queue_active_queries.3 new file mode 100644 index 00000000000000..c16c69ddcb9e02 --- /dev/null +++ b/deps/cares/docs/ares_queue_active_queries.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2024 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_queue.3 diff --git a/deps/cares/docs/ares_queue_wait_empty.3 b/deps/cares/docs/ares_queue_wait_empty.3 new file mode 100644 index 00000000000000..c16c69ddcb9e02 --- /dev/null +++ b/deps/cares/docs/ares_queue_wait_empty.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2024 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_queue.3 diff --git a/deps/cares/docs/ares_search.3 b/deps/cares/docs/ares_search.3 index 08246d349d02fd..1a324b0ff47db5 100644 --- a/deps/cares/docs/ares_search.3 +++ b/deps/cares/docs/ares_search.3 @@ -9,13 +9,23 @@ ares_search \- Initiate a DNS query with domain search .nf #include +typedef void (*ares_callback_dnsrec)(void *\fIarg\fP, + ares_status_t \fIstatus\fP, + size_t \fItimeouts\fP, + const ares_dns_record_t *\fIdnsrec\fP); + +void ares_search_dnsrec(ares_channel_t *\fIchannel\fP, + const ares_dns_record_t *\fIdnsrec\fP, + ares_callback_dnsrec \fIcallback\fP, void *\fIarg\fP); + typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, int \fItimeouts\fP, unsigned char *\fIabuf\fP, - int \fIalen\fP) + int \fIalen\fP); void ares_search(ares_channel_t *\fIchannel\fP, const char *\fIname\fP, int \fIdnsclass\fP, int \fItype\fP, - ares_callback \fIcallback\fP, void *\fIarg\fP) + ares_callback \fIcallback\fP, void *\fIarg\fP); + .fi .SH DESCRIPTION The @@ -142,9 +152,34 @@ will usually be NULL and will usually be 0, but in some cases an unsuccessful query result may be placed in .IR abuf . + +The \fIares_search_dnsrec(3)\fP function behaves identically to +\fIares_search(3)\fP, but takes an initialized and filled DNS record object to +use for queries as the second argument +.I dnsrec +instead of a name, class and type. This object is used as the base for the +queries and must itself represent a valid query for a single name. Note that +the search domains will only be appended to the name in the question section; +RRs on the DNS record object will not be affected. Moreover, the +.I callback +argument is of type \fIares_callback_dnsrec\fP. This callback behaves +identically to \fIares_callback\fP, but is invoked with a parsed DNS record +object +.I dnsrec +rather than a raw buffer with length. Note that this object is read-only. + +The \fIares_search_dnsrec(3)\fP function returns an \fIares_status_t\fP response +code. This may be useful to know that the query was enqueued properly. The +response code does not reflect the result of the query, just the result of the +enqueuing of the query. + +.SH AVAILABILITY +\fBares_search_dnsrec(3)\fP was introduced in c-ares 1.28.0. + .SH SEE ALSO .BR ares_process (3), .BR ares_dns_record (3) + .SH AUTHOR Greg Hudson, MIT Information Systems .br diff --git a/deps/cares/docs/ares_search_dnsrec.3 b/deps/cares/docs/ares_search_dnsrec.3 new file mode 100644 index 00000000000000..86c2317c071144 --- /dev/null +++ b/deps/cares/docs/ares_search_dnsrec.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_search.3 diff --git a/deps/cares/docs/ares_send.3 b/deps/cares/docs/ares_send.3 index 1fe1c0273e7379..010bb2579174bd 100644 --- a/deps/cares/docs/ares_send.3 +++ b/deps/cares/docs/ares_send.3 @@ -9,46 +9,78 @@ ares_send \- Initiate a DNS query .nf #include -typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, - int \fItimeouts\fP, unsigned char *\fIabuf\fP, - int \fIalen\fP) +typedef void (*ares_callback_dnsrec)(void *arg, ares_status_t status, + size_t timeouts, + const ares_dns_record_t *dnsrec); + +ares_status_t ares_send_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, + void *arg, unsigned short *qid); + +typedef void (*ares_callback)(void *arg, int status, + int timeouts, unsigned char *abuf, + int alen); + +void ares_send(ares_channel_t *channel, const unsigned char *qbuf, + int qlen, ares_callback callback, void *arg); -void ares_send(ares_channel_t *\fIchannel\fP, const unsigned char *\fIqbuf\fP, - int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP) .fi .SH DESCRIPTION -The -.B ares_send -function initiates a DNS query on the name service channel identified -by -.IR channel . -The parameters -.I qbuf +The \fIares_send_dnsrec(3)\fP function initiates a DNS query formatted using the +\fIares_dns_record_t *\fP data structure created via +\fIares_dns_record_create(3)\fP in the +.IR dnsrec +parameter. The supplied callback in the +.IR callback +parameter also returns the response using a +\fIares_dns_record_t *\fP data structure. + +The \fIares_send(3)\fP function similarly initiates a DNS query, but instead uses +raw binary buffers with fully formatted DNS messages passed in the request via the +.IR qbuf and -.I qlen -give the DNS query, which should already have been formatted according -to the DNS protocol. When the query is complete or has failed, the -ares library will invoke -.IR callback . -Completion or failure of the query may happen immediately, or may -happen later as network events are processed. -.PP +.IR qlen +parameters. The supplied callback in the +.IR callback +parameter also returns the raw binary DNS response in the +.IR abuf +and +.IR alen +parameters. This method should be considered deprecated in favor of +\fIares_send_dnsrec(3)\fP. + +Both functions take an initialized ares channel identified by +.IR channel . + +The \fIares_send_dnsrec(3)\fP also can be supplied an optional output parameter of +.IR qid +to populate the query id as it was placed on the wire. + +The \fIares_send_dnsrec(3)\fP function returns an \fIares_status_t\fP response +code. This may be useful to know that the query was enqueued properly. The +response code does not reflect the result of the query, just the result of the +enqueuing of the query. + +Completion or failure of the query may happen immediately (even before the +function returning), or may happen later as network events are processed. + When the associated callback is called, it is called with a channel lock so care must be taken to ensure any processing is minimal to prevent DNS channel stalls. The callback may be triggered from a different thread than the one which -called \fIares_send(3)\fP. +called \fIares_send_dnsrec(3)\fP or \fIares_send(3)\fP. For integrators running their own event loops and not using \fBARES_OPT_EVENT_THREAD\fP, care needs to be taken to ensure any file descriptor lists are updated immediately within the eventloop when notified. -.PP + The callback argument -.I arg -is copied from the -.B ares_send -argument -.IR arg . +.IR arg +is copied from the \fIares_send_dnsrec(3)\fP or \fIares_send(3)\fP +.IR arg +parameter. + The callback argument .I status indicates whether the query succeeded and, if not, how it failed. It @@ -82,43 +114,44 @@ is being destroyed; the query will not be completed. The query will not be completed because no DNS servers were configured on the channel. .PP + The callback argument .I timeouts reports how many times a query timed out during the execution of the given request. -.PP + If the query completed, the callback argument -.I abuf -points to a result buffer of length -.IR alen . -If the query did not complete, -.I abuf -will be NULL and -.I alen -will be 0. -.PP +.IR dnsrec +for \fIares_send_dnsrec(3)\fP or +.IR abuf +and +.IR alen +for \fIares_send(3)\fP will be non-NULL. + Unless the flag .B ARES_FLAG_NOCHECKRESP -was set at channel initialization time, -.B ares_send -will normally ignore responses whose questions do not match the -questions in -.IR qbuf , -as well as responses with reply codes of +was set at channel initialization time, \fIares_send_dnsrec(3)\fP and +\fIares_send(3)\fP will normally ignore responses whose questions do not match +the supplied questions, as well as responses with reply codes of .BR SERVFAIL , .BR NOTIMP , and .BR REFUSED . Unlike other query functions in the ares library, however, -.B ares_send -does not inspect the header of the reply packet to determine the error -status, so a callback status of +\fIares_send_dnsrec(3)\fP and \fIares_send(3)\fP do not inspect the header of +the reply packet to determine the error status, so a callback status of .B ARES_SUCCESS -does not reflect as much about the response as for other query -functions. +does not reflect as much about the response as for other query functions. + +.SH AVAILABILITY +\fBares_send_dnsrec(3)\fP was introduced in c-ares 1.28.0. + .SH SEE ALSO +.BR ares_dns_record_create (3), .BR ares_process (3), +.BR ares_search (3), .BR ares_dns_record (3) + .SH AUTHOR Greg Hudson, MIT Information Systems .br diff --git a/deps/cares/docs/ares_send_dnsrec.3 b/deps/cares/docs/ares_send_dnsrec.3 new file mode 100644 index 00000000000000..f5596f5cf049bc --- /dev/null +++ b/deps/cares/docs/ares_send_dnsrec.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_send.3 diff --git a/deps/cares/include/Makefile.in b/deps/cares/include/Makefile.in index cf8cb55170cc8b..6e06995bfc5a3b 100644 --- a/deps/cares/include/Makefile.in +++ b/deps/cares/include/Makefile.in @@ -274,6 +274,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ diff --git a/deps/cares/include/ares.h b/deps/cares/include/ares.h index acbd6583074a56..bc17230e47262f 100644 --- a/deps/cares/include/ares.h +++ b/deps/cares/include/ares.h @@ -119,6 +119,37 @@ extern "C" { # endif #endif +#ifdef __GNUC__ +# define CARES_GCC_VERSION \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#else +# define CARES_GCC_VERSION 0 +#endif + +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + +#ifdef CARES_NO_DEPRECATED +# define CARES_DEPRECATED +# define CARES_DEPRECATED_FOR(f) +#else +# if CARES_GCC_VERSION >= 30200 || __has_attribute(__deprecated__) +# define CARES_DEPRECATED __attribute__((__deprecated__)) +# else +# define CARES_DEPRECATED +# endif + +# if CARES_GCC_VERSION >= 40500 || defined(__clang__) +# define CARES_DEPRECATED_FOR(f) \ + __attribute__((deprecated("Use " #f " instead"))) +# elif defined(_MSC_VER) +# define CARES_DEPRECATED_FOR(f) __declspec(deprecated("Use " #f " instead")) +# else +# define CARES_DEPRECATED_FOR(f) CARES_DEPRECATED +# endif +#endif + typedef enum { ARES_SUCCESS = 0, @@ -352,29 +383,57 @@ typedef struct ares_channeldata *ares_channel; /* Current main channel typedef */ typedef struct ares_channeldata ares_channel_t; +/* + * NOTE: before c-ares 1.7.0 we would most often use the system in6_addr + * struct below when ares itself was built, but many apps would use this + * private version since the header checked a HAVE_* define for it. Starting + * with 1.7.0 we always declare and use our own to stop relying on the + * system's one. + */ +struct ares_in6_addr { + union { + unsigned char _S6_u8[16]; + } _S6_un; +}; + +struct ares_addr { + int family; + + union { + struct in_addr addr4; + struct ares_in6_addr addr6; + } addr; +}; + +/* DNS record parser, writer, and helpers */ +#include "ares_dns_record.h" -typedef void (*ares_callback)(void *arg, int status, int timeouts, +typedef void (*ares_callback)(void *arg, int status, int timeouts, unsigned char *abuf, int alen); -typedef void (*ares_host_callback)(void *arg, int status, int timeouts, +typedef void (*ares_callback_dnsrec)(void *arg, ares_status_t status, + size_t timeouts, + const ares_dns_record_t *dnsrec); + +typedef void (*ares_host_callback)(void *arg, int status, int timeouts, struct hostent *hostent); -typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts, +typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts, char *node, char *service); -typedef int (*ares_sock_create_callback)(ares_socket_t socket_fd, int type, +typedef int (*ares_sock_create_callback)(ares_socket_t socket_fd, int type, void *data); -typedef int (*ares_sock_config_callback)(ares_socket_t socket_fd, int type, +typedef int (*ares_sock_config_callback)(ares_socket_t socket_fd, int type, void *data); -typedef void (*ares_addrinfo_callback)(void *arg, int status, int timeouts, +typedef void (*ares_addrinfo_callback)(void *arg, int status, int timeouts, struct ares_addrinfo *res); CARES_EXTERN int ares_library_init(int flags); CARES_EXTERN int ares_library_init_mem(int flags, void *(*amalloc)(size_t size), - void (*afree)(void *ptr), + void (*afree)(void *ptr), void *(*arealloc)(void *ptr, size_t size)); @@ -384,13 +443,14 @@ CARES_EXTERN int ares_library_init_android(jobject connectivity_manager); CARES_EXTERN int ares_library_android_initialized(void); #endif -CARES_EXTERN int ares_library_initialized(void); +CARES_EXTERN int ares_library_initialized(void); -CARES_EXTERN void ares_library_cleanup(void); +CARES_EXTERN void ares_library_cleanup(void); -CARES_EXTERN const char *ares_version(int *version); +CARES_EXTERN const char *ares_version(int *version); -CARES_EXTERN int ares_init(ares_channel_t **channelptr); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_init_options) int ares_init( + ares_channel_t **channelptr); CARES_EXTERN int ares_init_options(ares_channel_t **channelptr, const struct ares_options *options, @@ -453,7 +513,7 @@ struct iovec; struct ares_socket_functions { ares_socket_t (*asocket)(int, int, int, void *); - int (*aclose)(ares_socket_t, void *); + int (*aclose)(ares_socket_t, void *); int (*aconnect)(ares_socket_t, const struct sockaddr *, ares_socklen_t, void *); ares_ssize_t (*arecvfrom)(ares_socket_t, void *, size_t, int, @@ -462,24 +522,76 @@ struct ares_socket_functions { }; CARES_EXTERN void - ares_set_socket_functions(ares_channel_t *channel, - const struct ares_socket_functions *funcs, - void *user_data); + ares_set_socket_functions(ares_channel_t *channel, + const struct ares_socket_functions *funcs, + void *user_data); + +CARES_EXTERN CARES_DEPRECATED_FOR(ares_send_dnsrec) void ares_send( + ares_channel_t *channel, const unsigned char *qbuf, int qlen, + ares_callback callback, void *arg); -CARES_EXTERN void ares_send(ares_channel_t *channel, const unsigned char *qbuf, - int qlen, ares_callback callback, void *arg); +/*! Send a DNS query as an ares_dns_record_t with a callback containing the + * parsed DNS record. + * + * \param[in] channel Pointer to channel on which queries will be sent. + * \param[in] dnsrec DNS Record to send + * \param[in] callback Callback function invoked on completion or failure of + * the query sequence. + * \param[in] arg Additional argument passed to the callback function. + * \param[out] qid Query ID + * \return One of the c-ares status codes. + */ +CARES_EXTERN ares_status_t ares_send_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, + void *arg, unsigned short *qid); -CARES_EXTERN void ares_query(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_query_dnsrec) void ares_query( + ares_channel_t *channel, const char *name, int dnsclass, int type, + ares_callback callback, void *arg); -CARES_EXTERN void ares_search(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg); +/*! Perform a DNS query with a callback containing the parsed DNS record. + * + * \param[in] channel Pointer to channel on which queries will be sent. + * \param[in] name Query name + * \param[in] dnsclass DNS Class + * \param[in] type DNS Record Type + * \param[in] callback Callback function invoked on completion or failure of + * the query sequence. + * \param[in] arg Additional argument passed to the callback function. + * \param[out] qid Query ID + * \return One of the c-ares status codes. + */ +CARES_EXTERN ares_status_t ares_query_dnsrec(ares_channel_t *channel, + const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, + ares_callback_dnsrec callback, + void *arg, unsigned short *qid); + +CARES_EXTERN CARES_DEPRECATED_FOR(ares_search_dnsrec) void ares_search( + ares_channel_t *channel, const char *name, int dnsclass, int type, + ares_callback callback, void *arg); + +/*! Search for a complete DNS message. + * + * \param[in] channel Pointer to channel on which queries will be sent. + * \param[in] dnsrec Pointer to initialized and filled DNS record object. + * \param[in] callback Callback function invoked on completion or failure of + * the query sequence. + * \param[in] arg Additional argument passed to the callback function. + * \return One of the c-ares status codes. In all cases, except + * ARES_EFORMERR due to misuse, this error code will also be sent + * to the provided callback. + */ +CARES_EXTERN ares_status_t ares_search_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, + void *arg); -CARES_EXTERN void ares_gethostbyname(ares_channel_t *channel, const char *name, - int family, ares_host_callback callback, - void *arg); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_getaddrinfo) void ares_gethostbyname( + ares_channel_t *channel, const char *name, int family, + ares_host_callback callback, void *arg); CARES_EXTERN int ares_gethostbyname_file(ares_channel_t *channel, const char *name, int family, @@ -494,61 +606,42 @@ CARES_EXTERN void ares_getnameinfo(ares_channel_t *channel, ares_socklen_t salen, int flags, ares_nameinfo_callback callback, void *arg); -CARES_EXTERN int ares_fds(ares_channel_t *channel, fd_set *read_fds, - fd_set *write_fds); +CARES_EXTERN CARES_DEPRECATED_FOR( + ARES_OPT_EVENT_THREAD or + ARES_OPT_SOCK_STATE_CB) int ares_fds(ares_channel_t *channel, + fd_set *read_fds, fd_set *write_fds); -CARES_EXTERN int ares_getsock(ares_channel_t *channel, ares_socket_t *socks, - int numsocks); +CARES_EXTERN CARES_DEPRECATED_FOR( + ARES_OPT_EVENT_THREAD or + ARES_OPT_SOCK_STATE_CB) int ares_getsock(ares_channel_t *channel, + ares_socket_t *socks, int numsocks); CARES_EXTERN struct timeval *ares_timeout(ares_channel_t *channel, struct timeval *maxtv, struct timeval *tv); -CARES_EXTERN void ares_process(ares_channel_t *channel, fd_set *read_fds, - fd_set *write_fds); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_process_fd) void ares_process( + ares_channel_t *channel, fd_set *read_fds, fd_set *write_fds); CARES_EXTERN void ares_process_fd(ares_channel_t *channel, ares_socket_t read_fd, ares_socket_t write_fd); -CARES_EXTERN int ares_create_query(const char *name, int dnsclass, int type, - unsigned short id, int rd, - unsigned char **buf, int *buflen, - int max_udp_size); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_record_create) int ares_create_query( + const char *name, int dnsclass, int type, unsigned short id, int rd, + unsigned char **buf, int *buflen, int max_udp_size); -CARES_EXTERN int ares_mkquery(const char *name, int dnsclass, int type, - unsigned short id, int rd, unsigned char **buf, - int *buflen); - -CARES_EXTERN int ares_expand_name(const unsigned char *encoded, - const unsigned char *abuf, int alen, char **s, - long *enclen); - -CARES_EXTERN int ares_expand_string(const unsigned char *encoded, - const unsigned char *abuf, int alen, - unsigned char **s, long *enclen); - -/* - * NOTE: before c-ares 1.7.0 we would most often use the system in6_addr - * struct below when ares itself was built, but many apps would use this - * private version since the header checked a HAVE_* define for it. Starting - * with 1.7.0 we always declare and use our own to stop relying on the - * system's one. - */ -struct ares_in6_addr { - union { - unsigned char _S6_u8[16]; - } _S6_un; -}; +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_record_create) int ares_mkquery( + const char *name, int dnsclass, int type, unsigned short id, int rd, + unsigned char **buf, int *buflen); -struct ares_addr { - int family; +CARES_EXTERN int ares_expand_name(const unsigned char *encoded, + const unsigned char *abuf, int alen, char **s, + long *enclen); - union { - struct in_addr addr4; - struct ares_in6_addr addr6; - } addr; -}; +CARES_EXTERN int ares_expand_string(const unsigned char *encoded, + const unsigned char *abuf, int alen, + unsigned char **s, long *enclen); struct ares_addrttl { struct in_addr ipaddr; @@ -675,52 +768,50 @@ struct ares_addrinfo_hints { ** so written. */ -CARES_EXTERN int ares_parse_a_reply(const unsigned char *abuf, int alen, - struct hostent **host, - struct ares_addrttl *addrttls, - int *naddrttls); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_a_reply( + const unsigned char *abuf, int alen, struct hostent **host, + struct ares_addrttl *addrttls, int *naddrttls); -CARES_EXTERN int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, - struct hostent **host, - struct ares_addr6ttl *addrttls, - int *naddrttls); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_aaaa_reply( + const unsigned char *abuf, int alen, struct hostent **host, + struct ares_addr6ttl *addrttls, int *naddrttls); -CARES_EXTERN int ares_parse_caa_reply(const unsigned char *abuf, int alen, - struct ares_caa_reply **caa_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_caa_reply( + const unsigned char *abuf, int alen, struct ares_caa_reply **caa_out); -CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf, int alen, - const void *addr, int addrlen, int family, - struct hostent **host); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_ptr_reply( + const unsigned char *abuf, int alen, const void *addr, int addrlen, + int family, struct hostent **host); -CARES_EXTERN int ares_parse_ns_reply(const unsigned char *abuf, int alen, - struct hostent **host); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_ns_reply( + const unsigned char *abuf, int alen, struct hostent **host); -CARES_EXTERN int ares_parse_srv_reply(const unsigned char *abuf, int alen, - struct ares_srv_reply **srv_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_srv_reply( + const unsigned char *abuf, int alen, struct ares_srv_reply **srv_out); -CARES_EXTERN int ares_parse_mx_reply(const unsigned char *abuf, int alen, - struct ares_mx_reply **mx_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_mx_reply( + const unsigned char *abuf, int alen, struct ares_mx_reply **mx_out); -CARES_EXTERN int ares_parse_txt_reply(const unsigned char *abuf, int alen, - struct ares_txt_reply **txt_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_txt_reply( + const unsigned char *abuf, int alen, struct ares_txt_reply **txt_out); -CARES_EXTERN int ares_parse_txt_reply_ext(const unsigned char *abuf, int alen, - struct ares_txt_ext **txt_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_txt_reply_ext( + const unsigned char *abuf, int alen, struct ares_txt_ext **txt_out); -CARES_EXTERN int ares_parse_naptr_reply(const unsigned char *abuf, int alen, - struct ares_naptr_reply **naptr_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_naptr_reply( + const unsigned char *abuf, int alen, struct ares_naptr_reply **naptr_out); -CARES_EXTERN int ares_parse_soa_reply(const unsigned char *abuf, int alen, - struct ares_soa_reply **soa_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_soa_reply( + const unsigned char *abuf, int alen, struct ares_soa_reply **soa_out); -CARES_EXTERN int ares_parse_uri_reply(const unsigned char *abuf, int alen, - struct ares_uri_reply **uri_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_uri_reply( + const unsigned char *abuf, int alen, struct ares_uri_reply **uri_out); -CARES_EXTERN void ares_free_string(void *str); +CARES_EXTERN void ares_free_string(void *str); -CARES_EXTERN void ares_free_hostent(struct hostent *host); +CARES_EXTERN void ares_free_hostent(struct hostent *host); -CARES_EXTERN void ares_free_data(void *dataptr); +CARES_EXTERN void ares_free_data(void *dataptr); CARES_EXTERN const char *ares_strerror(int code); @@ -747,23 +838,26 @@ struct ares_addr_port_node { int tcp_port; }; -CARES_EXTERN int ares_set_servers(ares_channel_t *channel, - const struct ares_addr_node *servers); -CARES_EXTERN int - ares_set_servers_ports(ares_channel_t *channel, - const struct ares_addr_port_node *servers); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_set_servers_csv) int ares_set_servers( + ares_channel_t *channel, const struct ares_addr_node *servers); + +CARES_EXTERN + CARES_DEPRECATED_FOR(ares_set_servers_ports_csv) int ares_set_servers_ports( + ares_channel_t *channel, const struct ares_addr_port_node *servers); /* Incoming string format: host[:port][,host[:port]]... */ -CARES_EXTERN int ares_set_servers_csv(ares_channel_t *channel, - const char *servers); -CARES_EXTERN int ares_set_servers_ports_csv(ares_channel_t *channel, - const char *servers); -CARES_EXTERN char *ares_get_servers_csv(ares_channel_t *channel); +CARES_EXTERN int ares_set_servers_csv(ares_channel_t *channel, + const char *servers); +CARES_EXTERN int ares_set_servers_ports_csv(ares_channel_t *channel, + const char *servers); +CARES_EXTERN char *ares_get_servers_csv(ares_channel_t *channel); -CARES_EXTERN int ares_get_servers(ares_channel_t *channel, - struct ares_addr_node **servers); -CARES_EXTERN int ares_get_servers_ports(ares_channel_t *channel, - struct ares_addr_port_node **servers); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_get_servers_csv) int ares_get_servers( + ares_channel_t *channel, struct ares_addr_node **servers); + +CARES_EXTERN + CARES_DEPRECATED_FOR(ares_get_servers_ports_csv) int ares_get_servers_ports( + ares_channel_t *channel, struct ares_addr_port_node **servers); CARES_EXTERN const char *ares_inet_ntop(int af, const void *src, char *dst, ares_socklen_t size); @@ -803,7 +897,4 @@ CARES_EXTERN size_t ares_queue_active_queries(ares_channel_t *channel); } #endif -/* DNS record parser, writer, and helpers */ -#include "ares_dns_record.h" - #endif /* ARES__H */ diff --git a/deps/cares/include/ares_dns_record.h b/deps/cares/include/ares_dns_record.h index 3f802aefa3231e..8d09bd0a464254 100644 --- a/deps/cares/include/ares_dns_record.h +++ b/deps/cares/include/ares_dns_record.h @@ -393,11 +393,11 @@ typedef enum { /*! Parse Additional from RFC 1035 that allow name compression as RAW */ ARES_DNS_PARSE_AR_BASE_RAW = 1 << 2, /*! Parse Answers from later RFCs (no name compression) RAW */ - ARES_DNS_PARSE_AN_EXT_RAW = 1 << 3, + ARES_DNS_PARSE_AN_EXT_RAW = 1 << 3, /*! Parse Authority from later RFCs (no name compression) as RAW */ - ARES_DNS_PARSE_NS_EXT_RAW = 1 << 4, - /*< Parse Additional from later RFCs (no name compression) as RAW */ - ARES_DNS_PARSE_AR_EXT_RAW = 1 << 5 + ARES_DNS_PARSE_NS_EXT_RAW = 1 << 4, + /*! Parse Additional from later RFCs (no name compression) as RAW */ + ARES_DNS_PARSE_AR_EXT_RAW = 1 << 5 } ares_dns_parse_flags_t; /*! String representation of DNS Record Type @@ -468,7 +468,7 @@ CARES_EXTERN const char *ares_dns_rcode_tostr(ares_dns_rcode_t rcode); * \param[in] ipaddr ASCII string form of the ip address * \param[in,out] addr Must set "family" member to one of AF_UNSPEC, * AF_INET, AF_INET6 on input. - * \param[out] ptr_len Length of binary form address + * \param[out] out_len Length of binary form address * \return Pointer to start of binary address or NULL on error. */ CARES_EXTERN const void *ares_dns_pton(const char *ipaddr, @@ -619,6 +619,32 @@ CARES_EXTERN ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec, ares_dns_rec_type_t qtype, ares_dns_class_t qclass); +/*! Replace the question name with a new name. This may be used when performing + * a search with aliases. + * + * Note that this will invalidate the name pointer returned from + * ares_dns_record_query_get(). + * + * \param[in] dnsrec Initialized record object + * \param[in] idx Index of question (typically 0) + * \param[in] name Name to use as replacement. + * \return ARES_SUCCESS on success + */ +CARES_EXTERN ares_status_t ares_dns_record_query_set_name( + ares_dns_record_t *dnsrec, size_t idx, const char *name); + + +/*! Replace the question type with a different type. This may be used when + * needing to query more than one address class (e.g. A and AAAA) + * + * \param[in] dnsrec Initialized record object + * \param[in] idx Index of question (typically 0) + * \param[in] qtype Record Type to use as replacement. + * \return ARES_SUCCESS on success + */ +CARES_EXTERN ares_status_t ares_dns_record_query_set_type( + ares_dns_record_t *dnsrec, size_t idx, ares_dns_rec_type_t qtype); + /*! Get the count of queries in the DNS Record * * \param[in] dnsrec Initialized record object @@ -631,6 +657,8 @@ CARES_EXTERN size_t ares_dns_record_query_cnt(const ares_dns_record_t *dnsrec); * \param[in] dnsrec Initialized record object * \param[in] idx Index of query * \param[out] name Optional. Returns name, may pass NULL if not desired. + * This pointer will be invalided by any call to + * ares_dns_record_query_set_name(). * \param[out] qtype Optional. Returns record type, may pass NULL. * \param[out] qclass Optional. Returns class, may pass NULL. * \return ARES_SUCCESS on success @@ -667,17 +695,28 @@ CARES_EXTERN ares_status_t ares_dns_record_rr_add( const char *name, ares_dns_rec_type_t type, ares_dns_class_t rclass, unsigned int ttl); -/*! Fetch a resource record based on the section and index. +/*! Fetch a writable resource record based on the section and index. * * \param[in] dnsrec Initialized record object * \param[in] sect Section for resource record * \param[in] idx Index of resource record in section - * \return NULL on misuse, otherwise a pointer to the resource record + * \return NULL on misuse, otherwise a writable pointer to the resource record */ CARES_EXTERN ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec, ares_dns_section_t sect, size_t idx); +/*! Fetch a non-writeable resource record based on the section and index. + * + * \param[in] dnsrec Initialized record object + * \param[in] sect Section for resource record + * \param[in] idx Index of resource record in section + * \return NULL on misuse, otherwise a const pointer to the resource record + */ +CARES_EXTERN const ares_dns_rr_t * + ares_dns_record_rr_get_const(const ares_dns_record_t *dnsrec, + ares_dns_section_t sect, size_t idx); + /*! Remove the resource record based on the section and index * @@ -686,9 +725,9 @@ CARES_EXTERN ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec, * \param[in] idx Index of resource record in section * \return ARES_SUCCESS on success, otherwise an error code. */ -CARES_EXTERN ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec, - ares_dns_section_t sect, - size_t idx); +CARES_EXTERN ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec, + ares_dns_section_t sect, + size_t idx); /*! Retrieve the resource record Name/Hostname @@ -696,7 +735,7 @@ CARES_EXTERN ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec, * \param[in] rr Pointer to resource record * \return Name */ -CARES_EXTERN const char *ares_dns_rr_get_name(const ares_dns_rr_t *rr); +CARES_EXTERN const char *ares_dns_rr_get_name(const ares_dns_rr_t *rr); /*! Retrieve the resource record type * @@ -959,8 +998,19 @@ CARES_EXTERN ares_status_t ares_dns_parse(const unsigned char *buf, * \param[out] buf_len Length of returned buffer containing DNS message. * \return ARES_SUCCESS on success */ -CARES_EXTERN ares_status_t ares_dns_write(ares_dns_record_t *dnsrec, +CARES_EXTERN ares_status_t ares_dns_write(const ares_dns_record_t *dnsrec, unsigned char **buf, size_t *buf_len); + + +/*! Duplicate a complete DNS message. This does not copy internal members + * (such as the ttl decrement capability). + * + * \param[in] dnsrec Pointer to initialized and filled DNS record object. + * \return duplicted DNS record object, or NULL on out of memory. + */ +CARES_EXTERN ares_dns_record_t * + ares_dns_record_duplicate(const ares_dns_record_t *dnsrec); + /*! @} */ #ifdef __cplusplus diff --git a/deps/cares/include/ares_version.h b/deps/cares/include/ares_version.h index 44dbdef161ac35..0e94a98be8f280 100644 --- a/deps/cares/include/ares_version.h +++ b/deps/cares/include/ares_version.h @@ -31,12 +31,12 @@ #define ARES_COPYRIGHT "2004 - 2024 Daniel Stenberg, ." #define ARES_VERSION_MAJOR 1 -#define ARES_VERSION_MINOR 27 -#define ARES_VERSION_PATCH 0 +#define ARES_VERSION_MINOR 28 +#define ARES_VERSION_PATCH 1 #define ARES_VERSION \ ((ARES_VERSION_MAJOR << 16) | (ARES_VERSION_MINOR << 8) | \ (ARES_VERSION_PATCH)) -#define ARES_VERSION_STR "1.27.0" +#define ARES_VERSION_STR "1.28.1" #if (ARES_VERSION >= 0x010700) # define CARES_HAVE_ARES_LIBRARY_INIT 1 diff --git a/deps/cares/src/Makefile.in b/deps/cares/src/Makefile.in index 040373fe95a247..f657ef0d43e7b9 100644 --- a/deps/cares/src/Makefile.in +++ b/deps/cares/src/Makefile.in @@ -285,6 +285,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ diff --git a/deps/cares/src/lib/CMakeLists.txt b/deps/cares/src/lib/CMakeLists.txt index 015e57f8193ebd..de73f712f1d1ce 100644 --- a/deps/cares/src/lib/CMakeLists.txt +++ b/deps/cares/src/lib/CMakeLists.txt @@ -31,7 +31,6 @@ IF (CARES_SHARED) EXPORT_NAME cares OUTPUT_NAME cares COMPILE_PDB_NAME cares - COMPILE_PDB_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} SOVERSION ${CARES_LIB_VERSION_MAJOR} VERSION "${CARES_LIB_VERSION_MAJOR}.${CARES_LIB_VERSION_MINOR}.${CARES_LIB_VERSION_RELEASE}" C_STANDARD 90 @@ -65,11 +64,13 @@ IF (CARES_SHARED) COMPONENT Library ${TARGETS_INST_DEST} ) - INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cares.pdb - DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT Library - OPTIONAL - ) + IF (MSVC) + INSTALL(FILES $ + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT Library + OPTIONAL + ) + ENDIF () ENDIF () SET (STATIC_SUFFIX "_static") @@ -88,7 +89,6 @@ IF (CARES_STATIC) EXPORT_NAME cares${STATIC_SUFFIX} OUTPUT_NAME cares${STATIC_SUFFIX} COMPILE_PDB_NAME cares${STATIC_SUFFIX} - COMPILE_PDB_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} C_STANDARD 90 ) @@ -116,11 +116,6 @@ IF (CARES_STATIC) INSTALL (TARGETS ${LIBNAME} EXPORT ${PROJECT_NAME}-targets COMPONENT Devel ${TARGETS_INST_DEST} ) - INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cares${STATIC_SUFFIX}.pdb - DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT Library - OPTIONAL - ) ENDIF () # For chain building: add alias targets that look like import libs that would be returned by find_package(c-ares). diff --git a/deps/cares/src/lib/Makefile.in b/deps/cares/src/lib/Makefile.in index c516cba2cf46d2..0060295c21e8ef 100644 --- a/deps/cares/src/lib/Makefile.in +++ b/deps/cares/src/lib/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ # aminclude_static.am generated automatically by Autoconf -# from AX_AM_MACROS_STATIC on Fri Jan 26 17:16:19 CET 2024 +# from AX_AM_MACROS_STATIC on Sat Mar 30 16:15:43 CET 2024 # Copyright (C) The c-ares project and its contributors # SPDX-License-Identifier: MIT @@ -169,14 +169,14 @@ am__objects_1 = libcares_la-ares__addrinfo2hostent.lo \ libcares_la-ares__htable_szvp.lo \ libcares_la-ares__iface_ips.lo libcares_la-ares__llist.lo \ libcares_la-ares__parse_into_addrinfo.lo \ - libcares_la-ares__read_line.lo libcares_la-ares__slist.lo \ - libcares_la-ares__socket.lo libcares_la-ares__sortaddrinfo.lo \ - libcares_la-ares__threads.lo libcares_la-ares__timeval.lo \ - libcares_la-ares_android.lo libcares_la-ares_cancel.lo \ - libcares_la-ares_data.lo libcares_la-ares_destroy.lo \ - libcares_la-ares_dns_mapping.lo libcares_la-ares_dns_name.lo \ - libcares_la-ares_dns_parse.lo libcares_la-ares_dns_record.lo \ - libcares_la-ares_dns_write.lo libcares_la-ares_event_epoll.lo \ + libcares_la-ares__slist.lo libcares_la-ares__socket.lo \ + libcares_la-ares__sortaddrinfo.lo libcares_la-ares__threads.lo \ + libcares_la-ares__timeval.lo libcares_la-ares_android.lo \ + libcares_la-ares_cancel.lo libcares_la-ares_data.lo \ + libcares_la-ares_destroy.lo libcares_la-ares_dns_mapping.lo \ + libcares_la-ares_dns_name.lo libcares_la-ares_dns_parse.lo \ + libcares_la-ares_dns_record.lo libcares_la-ares_dns_write.lo \ + libcares_la-ares_event_epoll.lo \ libcares_la-ares_event_kqueue.lo \ libcares_la-ares_event_poll.lo \ libcares_la-ares_event_select.lo \ @@ -193,9 +193,8 @@ am__objects_1 = libcares_la-ares__addrinfo2hostent.lo \ libcares_la-ares_gethostbyname.lo \ libcares_la-ares_getnameinfo.lo libcares_la-ares_getsock.lo \ libcares_la-ares_init.lo libcares_la-ares_library_init.lo \ - libcares_la-ares_math.lo libcares_la-ares_mkquery.lo \ - libcares_la-ares_create_query.lo libcares_la-ares_options.lo \ - libcares_la-ares_parse_a_reply.lo \ + libcares_la-ares_math.lo libcares_la-ares_create_query.lo \ + libcares_la-ares_options.lo libcares_la-ares_parse_a_reply.lo \ libcares_la-ares_parse_aaaa_reply.lo \ libcares_la-ares_parse_caa_reply.lo \ libcares_la-ares_parse_mx_reply.lo \ @@ -254,7 +253,6 @@ am__depfiles_remade = \ ./$(DEPDIR)/libcares_la-ares__iface_ips.Plo \ ./$(DEPDIR)/libcares_la-ares__llist.Plo \ ./$(DEPDIR)/libcares_la-ares__parse_into_addrinfo.Plo \ - ./$(DEPDIR)/libcares_la-ares__read_line.Plo \ ./$(DEPDIR)/libcares_la-ares__slist.Plo \ ./$(DEPDIR)/libcares_la-ares__socket.Plo \ ./$(DEPDIR)/libcares_la-ares__sortaddrinfo.Plo \ @@ -292,7 +290,6 @@ am__depfiles_remade = \ ./$(DEPDIR)/libcares_la-ares_init.Plo \ ./$(DEPDIR)/libcares_la-ares_library_init.Plo \ ./$(DEPDIR)/libcares_la-ares_math.Plo \ - ./$(DEPDIR)/libcares_la-ares_mkquery.Plo \ ./$(DEPDIR)/libcares_la-ares_options.Plo \ ./$(DEPDIR)/libcares_la-ares_parse_a_reply.Plo \ ./$(DEPDIR)/libcares_la-ares_parse_aaaa_reply.Plo \ @@ -505,6 +502,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -628,7 +626,6 @@ CSOURCES = ares__addrinfo2hostent.c \ ares__iface_ips.c \ ares__llist.c \ ares__parse_into_addrinfo.c \ - ares__read_line.c \ ares__slist.c \ ares__socket.c \ ares__sortaddrinfo.c \ @@ -665,7 +662,6 @@ CSOURCES = ares__addrinfo2hostent.c \ ares_init.c \ ares_library_init.c \ ares_math.c \ - ares_mkquery.c \ ares_create_query.c \ ares_options.c \ ares_parse_a_reply.c \ @@ -834,7 +830,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__iface_ips.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__llist.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__parse_into_addrinfo.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__read_line.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__slist.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__socket.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__sortaddrinfo.Plo@am__quote@ # am--include-marker @@ -872,7 +867,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_init.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_library_init.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_math.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_mkquery.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_options.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_parse_a_reply.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_parse_aaaa_reply.Plo@am__quote@ # am--include-marker @@ -1019,13 +1013,6 @@ libcares_la-ares__parse_into_addrinfo.lo: ares__parse_into_addrinfo.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -c -o libcares_la-ares__parse_into_addrinfo.lo `test -f 'ares__parse_into_addrinfo.c' || echo '$(srcdir)/'`ares__parse_into_addrinfo.c -libcares_la-ares__read_line.lo: ares__read_line.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -MT libcares_la-ares__read_line.lo -MD -MP -MF $(DEPDIR)/libcares_la-ares__read_line.Tpo -c -o libcares_la-ares__read_line.lo `test -f 'ares__read_line.c' || echo '$(srcdir)/'`ares__read_line.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcares_la-ares__read_line.Tpo $(DEPDIR)/libcares_la-ares__read_line.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ares__read_line.c' object='libcares_la-ares__read_line.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -c -o libcares_la-ares__read_line.lo `test -f 'ares__read_line.c' || echo '$(srcdir)/'`ares__read_line.c - libcares_la-ares__slist.lo: ares__slist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -MT libcares_la-ares__slist.lo -MD -MP -MF $(DEPDIR)/libcares_la-ares__slist.Tpo -c -o libcares_la-ares__slist.lo `test -f 'ares__slist.c' || echo '$(srcdir)/'`ares__slist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcares_la-ares__slist.Tpo $(DEPDIR)/libcares_la-ares__slist.Plo @@ -1278,13 +1265,6 @@ libcares_la-ares_math.lo: ares_math.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -c -o libcares_la-ares_math.lo `test -f 'ares_math.c' || echo '$(srcdir)/'`ares_math.c -libcares_la-ares_mkquery.lo: ares_mkquery.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -MT libcares_la-ares_mkquery.lo -MD -MP -MF $(DEPDIR)/libcares_la-ares_mkquery.Tpo -c -o libcares_la-ares_mkquery.lo `test -f 'ares_mkquery.c' || echo '$(srcdir)/'`ares_mkquery.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcares_la-ares_mkquery.Tpo $(DEPDIR)/libcares_la-ares_mkquery.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ares_mkquery.c' object='libcares_la-ares_mkquery.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -c -o libcares_la-ares_mkquery.lo `test -f 'ares_mkquery.c' || echo '$(srcdir)/'`ares_mkquery.c - libcares_la-ares_create_query.lo: ares_create_query.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -MT libcares_la-ares_create_query.lo -MD -MP -MF $(DEPDIR)/libcares_la-ares_create_query.Tpo -c -o libcares_la-ares_create_query.lo `test -f 'ares_create_query.c' || echo '$(srcdir)/'`ares_create_query.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcares_la-ares_create_query.Tpo $(DEPDIR)/libcares_la-ares_create_query.Plo @@ -1728,7 +1708,6 @@ distclean: distclean-recursive -rm -f ./$(DEPDIR)/libcares_la-ares__iface_ips.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__llist.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__parse_into_addrinfo.Plo - -rm -f ./$(DEPDIR)/libcares_la-ares__read_line.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__slist.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__socket.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__sortaddrinfo.Plo @@ -1766,7 +1745,6 @@ distclean: distclean-recursive -rm -f ./$(DEPDIR)/libcares_la-ares_init.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_library_init.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_math.Plo - -rm -f ./$(DEPDIR)/libcares_la-ares_mkquery.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_options.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_parse_a_reply.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_parse_aaaa_reply.Plo @@ -1855,7 +1833,6 @@ maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/libcares_la-ares__iface_ips.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__llist.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__parse_into_addrinfo.Plo - -rm -f ./$(DEPDIR)/libcares_la-ares__read_line.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__slist.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__socket.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__sortaddrinfo.Plo @@ -1893,7 +1870,6 @@ maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/libcares_la-ares_init.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_library_init.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_math.Plo - -rm -f ./$(DEPDIR)/libcares_la-ares_mkquery.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_options.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_parse_a_reply.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_parse_aaaa_reply.Plo diff --git a/deps/cares/src/lib/Makefile.inc b/deps/cares/src/lib/Makefile.inc index 29a65fd35b1dd0..38f7a115fe3598 100644 --- a/deps/cares/src/lib/Makefile.inc +++ b/deps/cares/src/lib/Makefile.inc @@ -13,7 +13,6 @@ CSOURCES = ares__addrinfo2hostent.c \ ares__iface_ips.c \ ares__llist.c \ ares__parse_into_addrinfo.c \ - ares__read_line.c \ ares__slist.c \ ares__socket.c \ ares__sortaddrinfo.c \ @@ -50,7 +49,6 @@ CSOURCES = ares__addrinfo2hostent.c \ ares_init.c \ ares_library_init.c \ ares_math.c \ - ares_mkquery.c \ ares_create_query.c \ ares_options.c \ ares_parse_a_reply.c \ diff --git a/deps/cares/src/lib/ares__buf.c b/deps/cares/src/lib/ares__buf.c index 8f9f32d71867ff..0663383df9e42e 100644 --- a/deps/cares/src/lib/ares__buf.c +++ b/deps/cares/src/lib/ares__buf.c @@ -45,47 +45,6 @@ struct ares__buf { * SIZE_MAX if not set. */ }; -ares_bool_t ares__isprint(int ch) -{ - if (ch >= 0x20 && ch <= 0x7E) { - return ARES_TRUE; - } - return ARES_FALSE; -} - -/* Character set allowed by hostnames. This is to include the normal - * domain name character set plus: - * - underscores which are used in SRV records. - * - Forward slashes such as are used for classless in-addr.arpa - * delegation (CNAMEs) - * - Asterisks may be used for wildcard domains in CNAMEs as seen in the - * real world. - * While RFC 2181 section 11 does state not to do validation, - * that applies to servers, not clients. Vulnerabilities have been - * reported when this validation is not performed. Security is more - * important than edge-case compatibility (which is probably invalid - * anyhow). */ -ares_bool_t ares__is_hostnamech(int ch) -{ - /* [A-Za-z0-9-*._/] - * Don't use isalnum() as it is locale-specific - */ - if (ch >= 'A' && ch <= 'Z') { - return ARES_TRUE; - } - if (ch >= 'a' && ch <= 'z') { - return ARES_TRUE; - } - if (ch >= '0' && ch <= '9') { - return ARES_TRUE; - } - if (ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '*') { - return ARES_TRUE; - } - - return ARES_FALSE; -} - ares__buf_t *ares__buf_create(void) { ares__buf_t *buf = ares_malloc_zero(sizeof(*buf)); @@ -630,6 +589,24 @@ ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf, return ares__buf_consume(buf, len); } +static ares_bool_t ares__is_whitespace(unsigned char c, + ares_bool_t include_linefeed) +{ + switch (c) { + case '\r': + case '\t': + case ' ': + case '\v': + case '\f': + return ARES_TRUE; + case '\n': + return include_linefeed; + default: + break; + } + return ARES_FALSE; +} + size_t ares__buf_consume_whitespace(ares__buf_t *buf, ares_bool_t include_linefeed) { @@ -642,24 +619,11 @@ size_t ares__buf_consume_whitespace(ares__buf_t *buf, } for (i = 0; i < remaining_len; i++) { - switch (ptr[i]) { - case '\r': - case '\t': - case ' ': - case '\v': - case '\f': - break; - case '\n': - if (!include_linefeed) { - goto done; - } - break; - default: - goto done; + if (!ares__is_whitespace(ptr[i], include_linefeed)) { + break; } } -done: if (i > 0) { ares__buf_consume(buf, i); } @@ -677,20 +641,11 @@ size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf) } for (i = 0; i < remaining_len; i++) { - switch (ptr[i]) { - case '\r': - case '\t': - case ' ': - case '\v': - case '\f': - case '\n': - goto done; - default: - break; + if (ares__is_whitespace(ptr[i], ARES_TRUE)) { + break; } } -done: if (i > 0) { ares__buf_consume(buf, i); } @@ -826,7 +781,7 @@ static ares_bool_t ares__buf_split_isduplicate(ares__llist_t *list, ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, size_t delims_len, ares__buf_split_t flags, - ares__llist_t **list) + size_t max_sections, ares__llist_t **list) { ares_status_t status = ARES_SUCCESS; ares_bool_t first = ARES_TRUE; @@ -842,20 +797,57 @@ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, } while (ares__buf_len(buf)) { - size_t len; + size_t len = 0; + const unsigned char *ptr; + + if (first) { + /* No delimiter yet, just tag the start */ + ares__buf_tag(buf); + } else { + if (flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) { + /* tag then eat delimiter so its first byte in buffer */ + ares__buf_tag(buf); + ares__buf_consume(buf, 1); + } else { + /* throw away delimiter */ + ares__buf_consume(buf, 1); + ares__buf_tag(buf); + } + } + + if (max_sections && ares__llist_len(*list) >= max_sections - 1) { + ares__buf_consume(buf, ares__buf_len(buf)); + } else { + ares__buf_consume_until_charset(buf, delims, delims_len, ARES_FALSE); + } - ares__buf_tag(buf); + ptr = ares__buf_tag_fetch(buf, &len); - len = ares__buf_consume_until_charset(buf, delims, delims_len, ARES_FALSE); + /* Shouldn't be possible */ + if (ptr == NULL) { + status = ARES_EFORMERR; + goto done; + } + + if (flags & ARES_BUF_SPLIT_LTRIM) { + size_t i; + for (i = 0; i < len; i++) { + if (!ares__is_whitespace(ptr[i], ARES_TRUE)) { + break; + } + } + ptr += i; + len -= i; + } - /* Don't treat a delimiter as part of the length */ - if (!first && len && flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) { - len--; + if (flags & ARES_BUF_SPLIT_RTRIM) { + while (len && ares__is_whitespace(ptr[len - 1], ARES_TRUE)) { + len--; + } } if (len != 0 || flags & ARES_BUF_SPLIT_ALLOW_BLANK) { - const unsigned char *ptr = ares__buf_tag_fetch(buf, &len); - ares__buf_t *data; + ares__buf_t *data; if (!(flags & ARES_BUF_SPLIT_NO_DUPLICATES) || !ares__buf_split_isduplicate(*list, ptr, len, flags)) { @@ -880,12 +872,6 @@ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, } } - if (!(flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) && - ares__buf_len(buf) != 0) { - /* Consume delimiter */ - ares__buf_consume(buf, 1); - } - first = ARES_FALSE; } @@ -1150,3 +1136,80 @@ ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data, return ARES_SUCCESS; } + +ares_status_t ares__buf_load_file(const char *filename, ares__buf_t *buf) +{ + FILE *fp = NULL; + unsigned char *ptr = NULL; + size_t len = 0; + size_t ptr_len = 0; + long ftell_len = 0; + ares_status_t status; + + if (filename == NULL || buf == NULL) { + return ARES_EFORMERR; + } + + fp = fopen(filename, "rb"); + if (fp == NULL) { + int error = ERRNO; + switch (error) { + case ENOENT: + case ESRCH: + status = ARES_ENOTFOUND; + goto done; + default: + DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, + strerror(error))); + DEBUGF(fprintf(stderr, "Error opening file: %s\n", filename)); + status = ARES_EFILE; + goto done; + } + } + + /* Get length portably, fstat() is POSIX, not C */ + if (fseek(fp, 0, SEEK_END) != 0) { + status = ARES_EFILE; + goto done; + } + + ftell_len = ftell(fp); + if (ftell_len < 0) { + status = ARES_EFILE; + goto done; + } + len = (size_t)ftell_len; + + if (fseek(fp, 0, SEEK_SET) != 0) { + status = ARES_EFILE; + goto done; + } + + if (len == 0) { + status = ARES_SUCCESS; + goto done; + } + + /* Read entire data into buffer */ + ptr_len = len; + ptr = ares__buf_append_start(buf, &ptr_len); + if (ptr == NULL) { + status = ARES_ENOMEM; + goto done; + } + + ptr_len = fread(ptr, 1, len, fp); + if (ptr_len != len) { + status = ARES_EFILE; + goto done; + } + + ares__buf_append_finish(buf, len); + status = ARES_SUCCESS; + +done: + if (fp != NULL) { + fclose(fp); + } + return status; +} diff --git a/deps/cares/src/lib/ares__buf.h b/deps/cares/src/lib/ares__buf.h index 52054a0b33c658..4298814f7b4396 100644 --- a/deps/cares/src/lib/ares__buf.h +++ b/deps/cares/src/lib/ares__buf.h @@ -177,7 +177,7 @@ void ares__buf_append_finish(ares__buf_t *buf, size_t len); * * \param[in] buf Initialized buffer object. * \param[in] data Data to hex dump - * \param[in] data_len Length of data to hexdump + * \param[in] len Length of data to hexdump * \return ARES_SUCCESS on success. */ ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data, @@ -373,7 +373,8 @@ size_t ares__buf_consume_whitespace(ares__buf_t *buf, size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf); -/*! Consume until a character in the character set provided is reached +/*! Consume until a character in the character set provided is reached. Does + * not include the character from the charset at the end. * * \param[in] buf Initialized buffer object * \param[in] charset character set @@ -414,7 +415,9 @@ typedef enum { /*! No flags */ ARES_BUF_SPLIT_NONE = 0, /*! The delimiter will be the first character in the buffer, except the - * first buffer since the start doesn't have a delimiter + * first buffer since the start doesn't have a delimiter. This option is + * incompatible with ARES_BUF_SPLIT_LTRIM since the delimiter is always + * the first character. */ ARES_BUF_SPLIT_DONT_CONSUME_DELIMS = 1 << 0, /*! Allow blank sections, by default blank sections are not emitted. If using @@ -424,7 +427,13 @@ typedef enum { /*! Remove duplicate entries */ ARES_BUF_SPLIT_NO_DUPLICATES = 1 << 2, /*! Perform case-insensitive matching when comparing values */ - ARES_BUF_SPLIT_CASE_INSENSITIVE = 1 << 3 + ARES_BUF_SPLIT_CASE_INSENSITIVE = 1 << 3, + /*! Trim leading whitespace from buffer */ + ARES_BUF_SPLIT_LTRIM = 1 << 4, + /*! Trim trailing whitespace from buffer */ + ARES_BUF_SPLIT_RTRIM = 1 << 5, + /*! Trim leading and trailing whitespace from buffer */ + ARES_BUF_SPLIT_TRIM = (ARES_BUF_SPLIT_LTRIM | ARES_BUF_SPLIT_RTRIM) } ares__buf_split_t; /*! Split the provided buffer into multiple sub-buffers stored in the variable @@ -435,6 +444,12 @@ typedef enum { * \param[in] delims Possible delimiters * \param[in] delims_len Length of possible delimiters * \param[in] flags One more more flags + * \param[in] max_sections Maximum number of sections. Use 0 for + * unlimited. Useful for splitting key/value + * pairs where the delimiter may be a valid + * character in the value. A value of 1 would + * have little usefulness and would effectively + * ignore the delimiter itself. * \param[out] list Result. Depending on flags, this may be a * valid list with no elements. Use * ares__llist_destroy() to free the memory which @@ -444,7 +459,7 @@ typedef enum { */ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, size_t delims_len, ares__buf_split_t flags, - ares__llist_t **list); + size_t max_sections, ares__llist_t **list); /*! Check the unprocessed buffer to see if it begins with the sequence of @@ -536,7 +551,7 @@ size_t ares__buf_get_position(const ares__buf_t *buf); * \param[in] remaining_len maximum length that should be used for parsing * the string, this is often less than the remaining * buffer and is based on the RR record length. - * \param[out] str Pointer passed by reference to be filled in with + * \param[out] name Pointer passed by reference to be filled in with * allocated string of the parsed that must be * ares_free()'d by the caller. * \param[in] allow_multiple ARES_TRUE if it should attempt to parse multiple @@ -567,6 +582,18 @@ ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len, ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len, unsigned char **bin, size_t *bin_len, ares_bool_t allow_multiple); + +/*! Load data from specified file path into provided buffer. The entire file + * is loaded into memory. + * + * \param[in] filename complete path to file + * \param[in,out] buf Initialized (non-const) buffer object to load data + * into + * \return ARES_ENOTFOUND if file not found, ARES_EFILE if issues reading + * file, ARES_ENOMEM if out of memory, ARES_SUCCESS on success. + */ +ares_status_t ares__buf_load_file(const char *filename, ares__buf_t *buf); + /*! @} */ #endif /* __ARES__BUF_H */ diff --git a/deps/cares/src/lib/ares__hosts_file.c b/deps/cares/src/lib/ares__hosts_file.c index c6fe63a429d269..e279623de37e64 100644 --- a/deps/cares/src/lib/ares__hosts_file.c +++ b/deps/cares/src/lib/ares__hosts_file.c @@ -98,95 +98,6 @@ struct ares_hosts_entry { ares__llist_t *hosts; }; -static ares_status_t ares__read_file_into_buf(const char *filename, - ares__buf_t *buf) -{ - FILE *fp = NULL; - unsigned char *ptr = NULL; - size_t len = 0; - size_t ptr_len = 0; - long ftell_len = 0; - ares_status_t status; - - if (filename == NULL || buf == NULL) { - return ARES_EFORMERR; - } - - fp = fopen(filename, "rb"); - if (fp == NULL) { - int error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - status = ARES_ENOTFOUND; - goto done; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", filename)); - status = ARES_EFILE; - goto done; - } - } - - /* Get length portably, fstat() is POSIX, not C */ - if (fseek(fp, 0, SEEK_END) != 0) { - status = ARES_EFILE; - goto done; - } - - ftell_len = ftell(fp); - if (ftell_len < 0) { - status = ARES_EFILE; - goto done; - } - len = (size_t)ftell_len; - - if (fseek(fp, 0, SEEK_SET) != 0) { - status = ARES_EFILE; - goto done; - } - - if (len == 0) { - status = ARES_SUCCESS; - goto done; - } - - /* Read entire data into buffer */ - ptr_len = len; - ptr = ares__buf_append_start(buf, &ptr_len); - if (ptr == NULL) { - status = ARES_ENOMEM; - goto done; - } - - ptr_len = fread(ptr, 1, len, fp); - if (ptr_len != len) { - status = ARES_EFILE; - goto done; - } - - ares__buf_append_finish(buf, len); - status = ARES_SUCCESS; - -done: - if (fp != NULL) { - fclose(fp); - } - return status; -} - -static ares_bool_t ares__is_hostname(const char *str) -{ - size_t i; - for (i = 0; str[i] != 0; i++) { - if (!ares__is_hostnamech(str[i])) { - return ARES_FALSE; - } - } - return ARES_TRUE; -} - const void *ares_dns_pton(const char *ipaddr, struct ares_addr *addr, size_t *out_len) { @@ -605,7 +516,7 @@ static ares_status_t ares__parse_hosts(const char *filename, goto done; } - status = ares__read_file_into_buf(filename, buf); + status = ares__buf_load_file(filename, buf); if (status != ARES_SUCCESS) { goto done; } diff --git a/deps/cares/src/lib/ares__htable.h b/deps/cares/src/lib/ares__htable.h index fd1c0a2366022f..d09c865977cdae 100644 --- a/deps/cares/src/lib/ares__htable.h +++ b/deps/cares/src/lib/ares__htable.h @@ -58,21 +58,21 @@ typedef struct ares__htable ares__htable_t; * but otherwise will not change between calls. * \return hash */ -typedef unsigned int (*ares__htable_hashfunc_t)(const void *key, +typedef unsigned int (*ares__htable_hashfunc_t)(const void *key, unsigned int seed); /*! Callback to free the bucket * * \param[in] bucket user provided bucket */ -typedef void (*ares__htable_bucket_free_t)(void *bucket); +typedef void (*ares__htable_bucket_free_t)(void *bucket); /*! Callback to extract the key from the user-provided bucket * * \param[in] bucket user provided bucket * \return pointer to key held in bucket */ -typedef const void *(*ares__htable_bucket_key_t)(const void *bucket); +typedef const void *(*ares__htable_bucket_key_t)(const void *bucket); /*! Callback to compare two keys for equality * @@ -80,15 +80,15 @@ typedef const void *(*ares__htable_bucket_key_t)(const void *bucket); * \param[in] key2 second key * \return ARES_TRUE if equal, ARES_FALSE if not */ -typedef ares_bool_t (*ares__htable_key_eq_t)(const void *key1, +typedef ares_bool_t (*ares__htable_key_eq_t)(const void *key1, const void *key2); /*! Destroy the initialized hashtable * - * \param[in] initialized hashtable + * \param[in] htable initialized hashtable */ -void ares__htable_destroy(ares__htable_t *htable); +void ares__htable_destroy(ares__htable_t *htable); /*! Create a new hashtable * diff --git a/deps/cares/src/lib/ares__htable_asvp.h b/deps/cares/src/lib/ares__htable_asvp.h index ee253455b2690c..49a766d023091e 100644 --- a/deps/cares/src/lib/ares__htable_asvp.h +++ b/deps/cares/src/lib/ares__htable_asvp.h @@ -51,7 +51,7 @@ typedef struct ares__htable_asvp ares__htable_asvp_t; * * \param[in] val user-supplied value */ -typedef void (*ares__htable_asvp_val_free_t)(void *val); +typedef void (*ares__htable_asvp_val_free_t)(void *val); /*! Destroy hashtable * @@ -71,7 +71,7 @@ ares__htable_asvp_t * /*! Retrieve an array of keys from the hashtable. * * \param[in] htable Initialized hashtable - * \param[out] num_keys Count of returned keys + * \param[out] num Count of returned keys * \return Array of keys in the hashtable. Must be free'd with ares_free(). */ ares_socket_t *ares__htable_asvp_keys(const ares__htable_asvp_t *htable, diff --git a/deps/cares/src/lib/ares__htable_strvp.h b/deps/cares/src/lib/ares__htable_strvp.h index 80d375c06804a5..25dd2b90777d8d 100644 --- a/deps/cares/src/lib/ares__htable_strvp.h +++ b/deps/cares/src/lib/ares__htable_strvp.h @@ -49,7 +49,7 @@ typedef struct ares__htable_strvp ares__htable_strvp_t; * * \param[in] val user-supplied value */ -typedef void (*ares__htable_strvp_val_free_t)(void *val); +typedef void (*ares__htable_strvp_val_free_t)(void *val); /*! Destroy hashtable * diff --git a/deps/cares/src/lib/ares__htable_szvp.h b/deps/cares/src/lib/ares__htable_szvp.h index 9857afe79604d3..62b1776be92b5b 100644 --- a/deps/cares/src/lib/ares__htable_szvp.h +++ b/deps/cares/src/lib/ares__htable_szvp.h @@ -49,7 +49,7 @@ typedef struct ares__htable_szvp ares__htable_szvp_t; * * \param[in] val user-supplied value */ -typedef void (*ares__htable_szvp_val_free_t)(void *val); +typedef void (*ares__htable_szvp_val_free_t)(void *val); /*! Destroy hashtable * diff --git a/deps/cares/src/lib/ares__llist.h b/deps/cares/src/lib/ares__llist.h index bd18bb9ec1d54c..7d57bdab3b077c 100644 --- a/deps/cares/src/lib/ares__llist.h +++ b/deps/cares/src/lib/ares__llist.h @@ -52,7 +52,7 @@ typedef struct ares__llist_node ares__llist_node_t; * * \param[in] data user supplied data */ -typedef void (*ares__llist_destructor_t)(void *data); +typedef void (*ares__llist_destructor_t)(void *data); /*! Create a linked list object * @@ -201,8 +201,8 @@ void ares__llist_destroy(ares__llist_t *list); /*! Detach node from the current list and re-attach it to the new list as the * last entry. * - * \param[in] node node to move - * \param[in] parent new list + * \param[in] node node to move + * \param[in] new_parent new list */ void ares__llist_node_move_parent_last(ares__llist_node_t *node, ares__llist_t *new_parent); @@ -210,8 +210,8 @@ void ares__llist_node_move_parent_last(ares__llist_node_t *node, /*! Detach node from the current list and re-attach it to the new list as the * first entry. * - * \param[in] node node to move - * \param[in] parent new list + * \param[in] node node to move + * \param[in] new_parent new list */ void ares__llist_node_move_parent_first(ares__llist_node_t *node, ares__llist_t *new_parent); diff --git a/deps/cares/src/lib/ares__parse_into_addrinfo.c b/deps/cares/src/lib/ares__parse_into_addrinfo.c index a5ce0c594fc3be..90e951c02f3f6d 100644 --- a/deps/cares/src/lib/ares__parse_into_addrinfo.c +++ b/deps/cares/src/lib/ares__parse_into_addrinfo.c @@ -47,13 +47,12 @@ #include "ares.h" #include "ares_private.h" -ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, +ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec, ares_bool_t cname_only_is_enodata, unsigned short port, struct ares_addrinfo *ai) { ares_status_t status; - ares_dns_record_t *dnsrec = NULL; size_t i; size_t ancount; const char *hostname = NULL; @@ -63,11 +62,6 @@ ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, struct ares_addrinfo_cname *cnames = NULL; struct ares_addrinfo_node *nodes = NULL; - status = ares_dns_parse(abuf, alen, 0, &dnsrec); - if (status != ARES_SUCCESS) { - goto done; - } - /* Save question hostname */ status = ares_dns_record_query_get(dnsrec, 0, &hostname, NULL, NULL); if (status != ARES_SUCCESS) { @@ -83,7 +77,7 @@ ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, for (i = 0; i < ancount; i++) { ares_dns_rec_type_t rtype; const ares_dns_rr_t *rr = - ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, i); + ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i); if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN) { continue; @@ -177,7 +171,6 @@ ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, done: ares__freeaddrinfo_cnames(cnames); ares__freeaddrinfo_nodes(nodes); - ares_dns_record_destroy(dnsrec); /* compatibility */ if (status == ARES_EBADNAME) { diff --git a/deps/cares/src/lib/ares__read_line.c b/deps/cares/src/lib/ares__read_line.c deleted file mode 100644 index 018f55e8b2681f..00000000000000 --- a/deps/cares/src/lib/ares__read_line.c +++ /dev/null @@ -1,90 +0,0 @@ -/* MIT License - * - * Copyright (c) 1998 Massachusetts Institute of Technology - * Copyright (c) The c-ares project and its contributors - * - * 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 (including the next - * paragraph) 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. - * - * SPDX-License-Identifier: MIT - */ - -#include "ares_setup.h" - -#include "ares.h" -#include "ares_private.h" - -/* This is an internal function. Its contract is to read a line from - * a file into a dynamically allocated buffer, zeroing the trailing - * newline if there is one. The calling routine may call - * ares__read_line multiple times with the same buf and bufsize - * pointers; *buf will be reallocated and *bufsize adjusted as - * appropriate. The initial value of *buf should be NULL. After the - * calling routine is done reading lines, it should free *buf. - */ -ares_status_t ares__read_line(FILE *fp, char **buf, size_t *bufsize) -{ - char *newbuf; - size_t offset = 0; - size_t len; - - if (*buf == NULL) { - *buf = ares_malloc(128); - if (!*buf) { - return ARES_ENOMEM; - } - *bufsize = 128; - } - - for (;;) { - int bytestoread = (int)(*bufsize - offset); - - if (!fgets(*buf + offset, bytestoread, fp)) { - return (offset != 0) ? 0 : (ferror(fp)) ? ARES_EFILE : ARES_EOF; - } - len = offset + ares_strlen(*buf + offset); - - /* Probably means there was an embedded NULL as the first character in - * the line, throw away line */ - if (len == 0) { - offset = 0; - continue; - } - - if ((*buf)[len - 1] == '\n') { - (*buf)[len - 1] = 0; - break; - } - offset = len; - if (len < *bufsize - 1) { - continue; - } - - /* Allocate more space. */ - newbuf = ares_realloc(*buf, *bufsize * 2); - if (!newbuf) { - ares_free(*buf); - *buf = NULL; - return ARES_ENOMEM; - } - *buf = newbuf; - *bufsize *= 2; - } - return ARES_SUCCESS; -} diff --git a/deps/cares/src/lib/ares__slist.h b/deps/cares/src/lib/ares__slist.h index 04cd50806ebc2d..26af88fa782499 100644 --- a/deps/cares/src/lib/ares__slist.h +++ b/deps/cares/src/lib/ares__slist.h @@ -63,7 +63,7 @@ typedef struct ares__slist_node ares__slist_node_t; * * \param[in] data User-defined data to destroy */ -typedef void (*ares__slist_destructor_t)(void *data); +typedef void (*ares__slist_destructor_t)(void *data); /*! SkipList comparison function * @@ -71,7 +71,7 @@ typedef void (*ares__slist_destructor_t)(void *data); * \param[in] data2 Second user-defined data object * \return < 0 if data1 < data1, > 0 if data1 > data2, 0 if data1 == data2 */ -typedef int (*ares__slist_cmp_t)(const void *data1, const void *data2); +typedef int (*ares__slist_cmp_t)(const void *data1, const void *data2); /*! Create SkipList * diff --git a/deps/cares/src/lib/ares__threads.c b/deps/cares/src/lib/ares__threads.c index 028790aead5abe..f6de8c698e373d 100644 --- a/deps/cares/src/lib/ares__threads.c +++ b/deps/cares/src/lib/ares__threads.c @@ -138,9 +138,9 @@ struct ares__thread { HANDLE thread; DWORD id; - void *(*func)(void *arg); - void *arg; - void *rv; + void *(*func)(void *arg); + void *arg; + void *rv; }; /* Wrap for pthread compatibility */ @@ -335,8 +335,8 @@ static void ares__timespec_timeout(struct timespec *ts, unsigned long add_ms) # error cannot determine current system time # endif - ts->tv_sec += add_ms / 1000; - ts->tv_nsec += (add_ms % 1000) * 1000000; + ts->tv_sec += (time_t)(add_ms / 1000); + ts->tv_nsec += (long)((add_ms % 1000) * 1000000); /* Normalize if needed */ if (ts->tv_nsec >= 1000000000) { diff --git a/deps/cares/src/lib/ares__threads.h b/deps/cares/src/lib/ares__threads.h index 39764296478a07..108354dfc1e17f 100644 --- a/deps/cares/src/lib/ares__threads.h +++ b/deps/cares/src/lib/ares__threads.h @@ -52,9 +52,9 @@ ares_status_t ares__thread_cond_timedwait(ares__thread_cond_t *cond, struct ares__thread; typedef struct ares__thread ares__thread_t; -typedef void *(*ares__thread_func_t)(void *arg); -ares_status_t ares__thread_create(ares__thread_t **thread, - ares__thread_func_t func, void *arg); +typedef void *(*ares__thread_func_t)(void *arg); +ares_status_t ares__thread_create(ares__thread_t **thread, + ares__thread_func_t func, void *arg); ares_status_t ares__thread_join(ares__thread_t *thread, void **rv); #endif diff --git a/deps/cares/src/lib/ares_cancel.c b/deps/cares/src/lib/ares_cancel.c index 0ee6124dd71440..5a9fb722cb7778 100644 --- a/deps/cares/src/lib/ares_cancel.c +++ b/deps/cares/src/lib/ares_cancel.c @@ -74,7 +74,7 @@ void ares_cancel(ares_channel_t *channel) query->node_all_queries = NULL; /* NOTE: its possible this may enqueue new queries */ - query->callback(query->arg, ARES_ECANCELLED, 0, NULL, 0); + query->callback(query->arg, ARES_ECANCELLED, 0, NULL); ares__free_query(query); /* See if the connection should be cleaned up */ diff --git a/deps/cares/src/lib/ares_config.h.cmake b/deps/cares/src/lib/ares_config.h.cmake index 01dcccaa17c2b4..10a1b7a971604b 100644 --- a/deps/cares/src/lib/ares_config.h.cmake +++ b/deps/cares/src/lib/ares_config.h.cmake @@ -212,6 +212,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_IN_H +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET6_IN6_H + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_TCP_H diff --git a/deps/cares/src/lib/ares_config.h.in b/deps/cares/src/lib/ares_config.h.in index 4e07e58473a009..f486b6b4f000b9 100644 --- a/deps/cares/src/lib/ares_config.h.in +++ b/deps/cares/src/lib/ares_config.h.in @@ -186,6 +186,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET6_IN6_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H diff --git a/deps/cares/src/lib/ares_create_query.c b/deps/cares/src/lib/ares_create_query.c index f66b0ff6e0693d..a2f2caac6e95d9 100644 --- a/deps/cares/src/lib/ares_create_query.c +++ b/deps/cares/src/lib/ares_create_query.c @@ -28,13 +28,15 @@ #include "ares.h" #include "ares_private.h" -int ares_create_query(const char *name, int dnsclass, int type, - unsigned short id, int rd, unsigned char **bufp, - int *buflenp, int max_udp_size) +static int ares_create_query_int(const char *name, int dnsclass, int type, + unsigned short id, int rd, + unsigned char **bufp, int *buflenp, + int max_udp_size) { ares_status_t status; ares_dns_record_t *dnsrec = NULL; size_t len; + ares_dns_flags_t rd_flag = rd ? ARES_FLAG_RD : 0; if (name == NULL || bufp == NULL || buflenp == NULL) { status = ARES_EFORMERR; @@ -44,56 +46,13 @@ int ares_create_query(const char *name, int dnsclass, int type, *bufp = NULL; *buflenp = 0; - /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */ - if (ares__is_onion_domain(name)) { - status = ARES_ENOTFOUND; - goto done; - } - - status = ares_dns_record_create(&dnsrec, id, rd ? ARES_FLAG_RD : 0, - ARES_OPCODE_QUERY, ARES_RCODE_NOERROR); + status = ares_dns_record_create_query( + &dnsrec, name, (ares_dns_class_t)dnsclass, (ares_dns_rec_type_t)type, id, + rd_flag, (size_t)max_udp_size); if (status != ARES_SUCCESS) { goto done; } - status = ares_dns_record_query_add(dnsrec, name, (ares_dns_rec_type_t)type, - (ares_dns_class_t)dnsclass); - if (status != ARES_SUCCESS) { - goto done; - } - - /* max_udp_size > 0 indicates EDNS, so send OPT RR as an additional record */ - if (max_udp_size > 0) { - ares_dns_rr_t *rr = NULL; - - status = ares_dns_record_rr_add(&rr, dnsrec, ARES_SECTION_ADDITIONAL, "", - ARES_REC_TYPE_OPT, ARES_CLASS_IN, 0); - if (status != ARES_SUCCESS) { - goto done; - } - - if (max_udp_size > 65535) { - status = ARES_EFORMERR; - goto done; - } - - status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_UDP_SIZE, - (unsigned short)max_udp_size); - if (status != ARES_SUCCESS) { - goto done; - } - - status = ares_dns_rr_set_u8(rr, ARES_RR_OPT_VERSION, 0); - if (status != ARES_SUCCESS) { - goto done; - } - - status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_FLAGS, 0); - if (status != ARES_SUCCESS) { - goto done; - } - } - status = ares_dns_write(dnsrec, bufp, &len); if (status != ARES_SUCCESS) { goto done; @@ -105,3 +64,17 @@ int ares_create_query(const char *name, int dnsclass, int type, ares_dns_record_destroy(dnsrec); return (int)status; } + +int ares_create_query(const char *name, int dnsclass, int type, + unsigned short id, int rd, unsigned char **bufp, + int *buflenp, int max_udp_size) +{ + return ares_create_query_int(name, dnsclass, type, id, rd, bufp, buflenp, + max_udp_size); +} + +int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id, + int rd, unsigned char **buf, int *buflen) +{ + return ares_create_query_int(name, dnsclass, type, id, rd, buf, buflen, 0); +} diff --git a/deps/cares/src/lib/ares_destroy.c b/deps/cares/src/lib/ares_destroy.c index 145084577f7fba..6965b601e76e07 100644 --- a/deps/cares/src/lib/ares_destroy.c +++ b/deps/cares/src/lib/ares_destroy.c @@ -51,7 +51,7 @@ void ares_destroy(ares_channel_t *channel) struct query *query = ares__llist_node_claim(node); query->node_all_queries = NULL; - query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL, 0); + query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL); ares__free_query(query); node = next; diff --git a/deps/cares/src/lib/ares_dns_mapping.c b/deps/cares/src/lib/ares_dns_mapping.c index 55f1af7939c32f..2b463fe83128a7 100644 --- a/deps/cares/src/lib/ares_dns_mapping.c +++ b/deps/cares/src/lib/ares_dns_mapping.c @@ -883,3 +883,37 @@ const char *ares_dns_rcode_tostr(ares_dns_rcode_t rcode) return "UNKNOWN"; } + +/* Convert an rcode and ancount from a query reply into an ares_status_t + * value. Used internally by ares_search() and ares_query(). + */ +ares_status_t ares_dns_query_reply_tostatus(ares_dns_rcode_t rcode, + size_t ancount) +{ + ares_status_t status = ARES_SUCCESS; + + switch (rcode) { + case ARES_RCODE_NOERROR: + status = (ancount > 0) ? ARES_SUCCESS : ARES_ENODATA; + break; + case ARES_RCODE_FORMERR: + status = ARES_EFORMERR; + break; + case ARES_RCODE_SERVFAIL: + status = ARES_ESERVFAIL; + break; + case ARES_RCODE_NXDOMAIN: + status = ARES_ENOTFOUND; + break; + case ARES_RCODE_NOTIMP: + status = ARES_ENOTIMP; + break; + case ARES_RCODE_REFUSED: + status = ARES_EREFUSED; + break; + default: + break; + } + + return status; +} diff --git a/deps/cares/src/lib/ares_dns_private.h b/deps/cares/src/lib/ares_dns_private.h index 91635e74cd8010..3af4b3c9926e42 100644 --- a/deps/cares/src/lib/ares_dns_private.h +++ b/deps/cares/src/lib/ares_dns_private.h @@ -49,6 +49,33 @@ ares_bool_t ares_dns_has_opt_rr(const ares_dns_record_t *rec); void ares_dns_record_write_ttl_decrement(ares_dns_record_t *dnsrec, unsigned int ttl_decrement); +/*! Create a DNS record object for a query. The arguments are the same as + * those for ares_create_query(). + * + * \param[out] dnsrec DNS record object to create. + * \param[in] name NUL-terminated name for the query. + * \param[in] dnsclass Class for the query. + * \param[in] type Type for the query. + * \param[in] id Identifier for the query. + * \param[in] flags Flags for the query. + * \param[in] max_udp_size Maximum size of a UDP packet for EDNS. + * \return ARES_SUCCESS on success, otherwise an error code. + */ +ares_status_t + ares_dns_record_create_query(ares_dns_record_t **dnsrec, const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, unsigned short id, + ares_dns_flags_t flags, size_t max_udp_size); + +/*! Convert the RCODE and ANCOUNT from a DNS query reply into a status code. + * + * \param[in] rcode The RCODE from the reply. + * \param[in] ancount The ANCOUNT from the reply. + * \return An appropriate status code. + */ +ares_status_t ares_dns_query_reply_tostatus(ares_dns_rcode_t rcode, + size_t ancount); + struct ares_dns_qd { char *name; ares_dns_rec_type_t qtype; diff --git a/deps/cares/src/lib/ares_dns_record.c b/deps/cares/src/lib/ares_dns_record.c index 30219003e24a57..ec7f7e734302de 100644 --- a/deps/cares/src/lib/ares_dns_record.c +++ b/deps/cares/src/lib/ares_dns_record.c @@ -276,6 +276,39 @@ ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec, return ARES_SUCCESS; } +ares_status_t ares_dns_record_query_set_name(ares_dns_record_t *dnsrec, + size_t idx, const char *name) +{ + char *orig_name = NULL; + + if (dnsrec == NULL || idx >= dnsrec->qdcount || name == NULL) { + return ARES_EFORMERR; + } + orig_name = dnsrec->qd[idx].name; + dnsrec->qd[idx].name = ares_strdup(name); + if (dnsrec->qd[idx].name == NULL) { + dnsrec->qd[idx].name = orig_name; + return ARES_ENOMEM; + } + + ares_free(orig_name); + return ARES_SUCCESS; +} + +ares_status_t ares_dns_record_query_set_type(ares_dns_record_t *dnsrec, + size_t idx, + ares_dns_rec_type_t qtype) +{ + if (dnsrec == NULL || idx >= dnsrec->qdcount || + !ares_dns_rec_type_isvalid(qtype, ARES_TRUE)) { + return ARES_EFORMERR; + } + + dnsrec->qd[idx].qtype = qtype; + + return ARES_SUCCESS; +} + ares_status_t ares_dns_record_query_get(const ares_dns_record_t *dnsrec, size_t idx, const char **name, ares_dns_rec_type_t *qtype, @@ -499,7 +532,7 @@ ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec, return &rr_ptr[idx]; } -static const ares_dns_rr_t * +const ares_dns_rr_t * ares_dns_record_rr_get_const(const ares_dns_record_t *dnsrec, ares_dns_section_t sect, size_t idx) { @@ -1314,3 +1347,103 @@ ares_bool_t ares_dns_has_opt_rr(const ares_dns_record_t *rec) } return ARES_FALSE; } + +/* Construct a DNS record for a name with given class and type. Used internally + * by ares_search() and ares_create_query(). + */ +ares_status_t + ares_dns_record_create_query(ares_dns_record_t **dnsrec, const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, unsigned short id, + ares_dns_flags_t flags, size_t max_udp_size) +{ + ares_status_t status; + ares_dns_rr_t *rr = NULL; + + if (dnsrec == NULL) { + return ARES_EFORMERR; + } + + *dnsrec = NULL; + + /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN */ + if (ares__is_onion_domain(name)) { + status = ARES_ENOTFOUND; + goto done; + } + + status = ares_dns_record_create(dnsrec, id, (unsigned short)flags, + ARES_OPCODE_QUERY, ARES_RCODE_NOERROR); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_dns_record_query_add(*dnsrec, name, type, dnsclass); + if (status != ARES_SUCCESS) { + goto done; + } + + /* max_udp_size > 0 indicates EDNS, so send OPT RR as an additional record */ + if (max_udp_size > 0) { + /* max_udp_size must fit into a 16 bit unsigned integer field on the OPT + * RR, so check here that it fits + */ + if (max_udp_size > 65535) { + status = ARES_EFORMERR; + goto done; + } + + status = ares_dns_record_rr_add(&rr, *dnsrec, ARES_SECTION_ADDITIONAL, "", + ARES_REC_TYPE_OPT, ARES_CLASS_IN, 0); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_UDP_SIZE, + (unsigned short)max_udp_size); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_dns_rr_set_u8(rr, ARES_RR_OPT_VERSION, 0); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_FLAGS, 0); + if (status != ARES_SUCCESS) { + goto done; + } + } + +done: + if (status != ARES_SUCCESS) { + ares_dns_record_destroy(*dnsrec); + *dnsrec = NULL; + } + return status; +} + +ares_dns_record_t *ares_dns_record_duplicate(const ares_dns_record_t *dnsrec) +{ + unsigned char *data = NULL; + size_t data_len = 0; + ares_dns_record_t *out = NULL; + ares_status_t status; + + if (dnsrec == NULL) { + return NULL; + } + + status = ares_dns_write(dnsrec, &data, &data_len); + if (status != ARES_SUCCESS) { + return NULL; + } + + status = ares_dns_parse(data, data_len, 0, &out); + ares_free(data); + if (status != ARES_SUCCESS) { + return NULL; + } + return out; +} diff --git a/deps/cares/src/lib/ares_dns_write.c b/deps/cares/src/lib/ares_dns_write.c index 2e99c5ba88aee7..b49ec07bcb9b6b 100644 --- a/deps/cares/src/lib/ares_dns_write.c +++ b/deps/cares/src/lib/ares_dns_write.c @@ -831,10 +831,10 @@ static ares_status_t ares_dns_write_rr_raw_rr(ares__buf_t *buf, return ares__buf_append(buf, data, data_len); } -static ares_status_t ares_dns_write_rr(ares_dns_record_t *dnsrec, - ares__llist_t **namelist, - ares_dns_section_t section, - ares__buf_t *buf) +static ares_status_t ares_dns_write_rr(const ares_dns_record_t *dnsrec, + ares__llist_t **namelist, + ares_dns_section_t section, + ares__buf_t *buf) { size_t i; @@ -849,7 +849,7 @@ static ares_status_t ares_dns_write_rr(ares_dns_record_t *dnsrec, size_t end_length; unsigned int ttl; - rr = ares_dns_record_rr_get(dnsrec, section, i); + rr = ares_dns_record_rr_get_const(dnsrec, section, i); if (rr == NULL) { return ARES_EFORMERR; } @@ -988,8 +988,8 @@ static ares_status_t ares_dns_write_rr(ares_dns_record_t *dnsrec, return ARES_SUCCESS; } -ares_status_t ares_dns_write(ares_dns_record_t *dnsrec, unsigned char **buf, - size_t *buf_len) +ares_status_t ares_dns_write(const ares_dns_record_t *dnsrec, + unsigned char **buf, size_t *buf_len) { ares__buf_t *b = NULL; ares_status_t status; diff --git a/deps/cares/src/lib/ares_event.h b/deps/cares/src/lib/ares_event.h index 9d01d75f372afe..23e9637924ba07 100644 --- a/deps/cares/src/lib/ares_event.h +++ b/deps/cares/src/lib/ares_event.h @@ -72,11 +72,11 @@ struct ares_event { typedef struct { const char *name; ares_bool_t (*init)(ares_event_thread_t *e); - void (*destroy)(ares_event_thread_t *e); + void (*destroy)(ares_event_thread_t *e); ares_bool_t (*event_add)(ares_event_t *event); - void (*event_del)(ares_event_t *event); - void (*event_mod)(ares_event_t *event, ares_event_flags_t new_flags); - size_t (*wait)(ares_event_thread_t *e, unsigned long timeout_ms); + void (*event_del)(ares_event_t *event); + void (*event_mod)(ares_event_t *event, ares_event_flags_t new_flags); + size_t (*wait)(ares_event_thread_t *e, unsigned long timeout_ms); } ares_event_sys_t; struct ares_event_thread { diff --git a/deps/cares/src/lib/ares_event_poll.c b/deps/cares/src/lib/ares_event_poll.c index c16b2824663544..33b1d6dfd58ec7 100644 --- a/deps/cares/src/lib/ares_event_poll.c +++ b/deps/cares/src/lib/ares_event_poll.c @@ -75,8 +75,11 @@ static size_t ares_evsys_poll_wait(ares_event_thread_t *e, size_t cnt = 0; size_t i; - if (num_fds) { + if (fdlist != NULL && num_fds) { pollfd = ares_malloc_zero(sizeof(*pollfd) * num_fds); + if (pollfd == NULL) { + goto done; + } for (i = 0; i < num_fds; i++) { const ares_event_t *ev = ares__htable_asvp_get_direct(e->ev_handles, fdlist[i]); @@ -96,7 +99,7 @@ static size_t ares_evsys_poll_wait(ares_event_thread_t *e, goto done; } - for (i = 0; i < num_fds; i++) { + for (i = 0; pollfd != NULL && i < num_fds; i++) { ares_event_t *ev; ares_event_flags_t flags = 0; diff --git a/deps/cares/src/lib/ares_getaddrinfo.c b/deps/cares/src/lib/ares_getaddrinfo.c index eaa4b422c06e9e..cfc889c70a84e2 100644 --- a/deps/cares/src/lib/ares_getaddrinfo.c +++ b/deps/cares/src/lib/ares_getaddrinfo.c @@ -79,15 +79,20 @@ struct host_query { char *lookups; /* Duplicate memory from channel because of ares_reinit() */ const char *remaining_lookups; /* types of lookup we need to perform ("fb" by default, file and dns respectively) */ - char **domains; /* duplicate from channel for ares_reinit() safety */ - size_t ndomains; - struct ares_addrinfo *ai; /* store results between lookups */ - unsigned short qid_a; /* qid for A request */ - unsigned short qid_aaaa; /* qid for AAAA request */ - size_t remaining; /* number of DNS answers waiting for */ - ares_ssize_t next_domain; /* next search domain to try */ - size_t - nodata_cnt; /* Track nodata responses to possibly override final result */ + + /* Search order for names */ + char **names; + size_t names_cnt; + size_t next_name_idx; /* next name index being attempted */ + + struct ares_addrinfo *ai; /* store results between lookups */ + unsigned short qid_a; /* qid for A request */ + unsigned short qid_aaaa; /* qid for AAAA request */ + + size_t remaining; /* number of DNS answers waiting for */ + + /* Track nodata responses to possibly override final result */ + size_t nodata_cnt; }; static const struct ares_addrinfo_hints default_hints = { @@ -98,10 +103,6 @@ static const struct ares_addrinfo_hints default_hints = { }; /* forward declarations */ -static void host_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen); -static ares_bool_t as_is_first(const struct host_query *hquery); -static ares_bool_t as_is_only(const struct host_query *hquery); static ares_bool_t next_dns_lookup(struct host_query *hquery); struct ares_addrinfo_cname * @@ -324,6 +325,17 @@ static ares_bool_t fake_addrinfo(const char *name, unsigned short port, return ARES_TRUE; } +static void hquery_free(struct host_query *hquery, ares_bool_t cleanup_ai) +{ + if (cleanup_ai) { + ares_freeaddrinfo(hquery->ai); + } + ares__strsplit_free(hquery->names, hquery->names_cnt); + ares_free(hquery->name); + ares_free(hquery->lookups); + ares_free(hquery); +} + static void end_hquery(struct host_query *hquery, ares_status_t status) { struct ares_addrinfo_node sentinel; @@ -349,10 +361,7 @@ static void end_hquery(struct host_query *hquery, ares_status_t status) } hquery->callback(hquery->arg, (int)status, (int)hquery->timeouts, hquery->ai); - ares__strsplit_free(hquery->domains, hquery->ndomains); - ares_free(hquery->lookups); - ares_free(hquery->name); - ares_free(hquery); + hquery_free(hquery, ARES_FALSE); } ares_bool_t ares__is_localhost(const char *name) @@ -478,25 +487,23 @@ static void terminate_retries(const struct host_query *hquery, query->no_retries = ARES_TRUE; } -static void host_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen) +static void host_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec) { struct host_query *hquery = (struct host_query *)arg; ares_status_t addinfostatus = ARES_SUCCESS; - unsigned short qid = 0; - hquery->timeouts += (size_t)timeouts; + hquery->timeouts += timeouts; hquery->remaining--; if (status == ARES_SUCCESS) { - if (alen < 0) { + if (dnsrec == NULL) { addinfostatus = ARES_EBADRESP; } else { - addinfostatus = ares__parse_into_addrinfo(abuf, (size_t)alen, ARES_TRUE, - hquery->port, hquery->ai); + addinfostatus = + ares__parse_into_addrinfo(dnsrec, ARES_TRUE, hquery->port, hquery->ai); } - if (addinfostatus == ARES_SUCCESS && alen >= HFIXEDSZ) { - qid = DNS_HEADER_QID(abuf); /* Converts to host byte order */ - terminate_retries(hquery, qid); + if (addinfostatus == ARES_SUCCESS) { + terminate_retries(hquery, ares_dns_record_get_id(dnsrec)); } } @@ -505,7 +512,7 @@ static void host_callback(void *arg, int status, int timeouts, /* must make sure we don't do next_lookup() on destroy or cancel, * and return the appropriate status. We won't return a partial * result in this case. */ - end_hquery(hquery, (ares_status_t)status); + end_hquery(hquery, status); } else if (addinfostatus != ARES_SUCCESS && addinfostatus != ARES_ENODATA) { /* error in parsing result e.g. no memory */ if (addinfostatus == ARES_EBADRESP && hquery->ai->nodes) { @@ -523,10 +530,9 @@ static void host_callback(void *arg, int status, int timeouts, if (status == ARES_ENODATA || addinfostatus == ARES_ENODATA) { hquery->nodata_cnt++; } - next_lookup(hquery, - hquery->nodata_cnt ? ARES_ENODATA : (ares_status_t)status); + next_lookup(hquery, hquery->nodata_cnt ? ARES_ENODATA : status); } else { - end_hquery(hquery, (ares_status_t)status); + end_hquery(hquery, status); } } @@ -542,7 +548,6 @@ static void ares_getaddrinfo_int(ares_channel_t *channel, const char *name, unsigned short port = 0; int family; struct ares_addrinfo *ai; - char *alias_name = NULL; ares_status_t status; if (!hints) { @@ -563,25 +568,12 @@ static void ares_getaddrinfo_int(ares_channel_t *channel, const char *name, return; } - /* perform HOSTALIAS resolution (technically this function does some other - * things we are going to ignore) */ - status = ares__single_domain(channel, name, &alias_name); - if (status != ARES_SUCCESS) { - callback(arg, (int)status, 0, NULL); - return; - } - - if (alias_name) { - name = alias_name; - } - if (service) { if (hints->ai_flags & ARES_AI_NUMERICSERV) { unsigned long val; errno = 0; val = strtoul(service, NULL, 0); if ((val == 0 && errno != 0) || val > 65535) { - ares_free(alias_name); callback(arg, ARES_ESERVICE, 0, NULL); return; } @@ -593,7 +585,6 @@ static void ares_getaddrinfo_int(ares_channel_t *channel, const char *name, errno = 0; val = strtoul(service, NULL, 0); if ((val == 0 && errno != 0) || val > 65535) { - ares_free(alias_name); callback(arg, ARES_ESERVICE, 0, NULL); return; } @@ -604,66 +595,53 @@ static void ares_getaddrinfo_int(ares_channel_t *channel, const char *name, ai = ares_malloc_zero(sizeof(*ai)); if (!ai) { - ares_free(alias_name); callback(arg, ARES_ENOMEM, 0, NULL); return; } if (fake_addrinfo(name, port, hints, ai, callback, arg)) { - ares_free(alias_name); return; } /* Allocate and fill in the host query structure. */ hquery = ares_malloc_zero(sizeof(*hquery)); if (!hquery) { - ares_free(alias_name); ares_freeaddrinfo(ai); callback(arg, ARES_ENOMEM, 0, NULL); return; } - memset(hquery, 0, sizeof(*hquery)); - hquery->name = ares_strdup(name); - ares_free(alias_name); - if (!hquery->name) { - ares_free(hquery); - ares_freeaddrinfo(ai); + + hquery->port = port; + hquery->channel = channel; + hquery->hints = *hints; + hquery->sent_family = -1; /* nothing is sent yet */ + hquery->callback = callback; + hquery->arg = arg; + hquery->ai = ai; + hquery->name = ares_strdup(name); + if (hquery->name == NULL) { + hquery_free(hquery, ARES_TRUE); callback(arg, ARES_ENOMEM, 0, NULL); return; } - hquery->lookups = ares_strdup(channel->lookups); - if (!hquery->lookups) { - ares_free(hquery->name); - ares_free(hquery); - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); + + status = + ares__search_name_list(channel, name, &hquery->names, &hquery->names_cnt); + if (status != ARES_SUCCESS) { + hquery_free(hquery, ARES_TRUE); + callback(arg, (int)status, 0, NULL); return; } + hquery->next_name_idx = 0; - if (channel->ndomains) { - /* Duplicate for ares_reinit() safety */ - hquery->domains = - ares__strsplit_duplicate(channel->domains, channel->ndomains); - if (hquery->domains == NULL) { - ares_free(hquery->lookups); - ares_free(hquery->name); - ares_free(hquery); - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); - return; - } - hquery->ndomains = channel->ndomains; - } - hquery->port = port; - hquery->channel = channel; - hquery->hints = *hints; - hquery->sent_family = -1; /* nothing is sent yet */ - hquery->callback = callback; - hquery->arg = arg; + hquery->lookups = ares_strdup(channel->lookups); + if (hquery->lookups == NULL) { + hquery_free(hquery, ARES_TRUE); + callback(arg, ARES_ENOMEM, 0, NULL); + return; + } hquery->remaining_lookups = hquery->lookups; - hquery->ai = ai; - hquery->next_domain = -1; /* Start performing lookups according to channel->lookups. */ next_lookup(hquery, ARES_ECONNREFUSED /* initial error code */); @@ -684,93 +662,39 @@ void ares_getaddrinfo(ares_channel_t *channel, const char *name, static ares_bool_t next_dns_lookup(struct host_query *hquery) { - char *s = NULL; - ares_bool_t is_s_allocated = ARES_FALSE; - ares_status_t status; - - /* if next_domain == -1 and as_is_first is true, try hquery->name */ - if (hquery->next_domain == -1) { - if (as_is_first(hquery)) { - s = hquery->name; - } - hquery->next_domain = 0; - } - - /* if as_is_first is false, try hquery->name at last */ - if (!s && (size_t)hquery->next_domain == hquery->ndomains) { - if (!as_is_first(hquery)) { - s = hquery->name; - } - hquery->next_domain++; - } - - if (!s && (size_t)hquery->next_domain < hquery->ndomains && - !as_is_only(hquery)) { - status = ares__cat_domain(hquery->name, - hquery->domains[hquery->next_domain++], &s); - if (status == ARES_SUCCESS) { - is_s_allocated = ARES_TRUE; - } - } + const char *name = NULL; - if (s) { - /* NOTE: hquery may be invalidated during the call to ares_query_qid(), - * so should not be referenced after this point */ - switch (hquery->hints.ai_family) { - case AF_INET: - hquery->remaining += 1; - ares_query_qid(hquery->channel, s, C_IN, T_A, host_callback, hquery, - &hquery->qid_a); - break; - case AF_INET6: - hquery->remaining += 1; - ares_query_qid(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery, - &hquery->qid_aaaa); - break; - case AF_UNSPEC: - hquery->remaining += 2; - ares_query_qid(hquery->channel, s, C_IN, T_A, host_callback, hquery, - &hquery->qid_a); - ares_query_qid(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery, - &hquery->qid_aaaa); - break; - default: - break; - } - if (is_s_allocated) { - ares_free(s); - } - return ARES_TRUE; - } else { - assert(!hquery->ai->nodes); + if (hquery->next_name_idx >= hquery->names_cnt) { return ARES_FALSE; } -} -static ares_bool_t as_is_first(const struct host_query *hquery) -{ - const char *p; - size_t ndots = 0; - for (p = hquery->name; p && *p; p++) { - if (*p == '.') { - ndots++; - } - } - if (as_is_only(hquery)) { - /* prevent ARES_EBADNAME for valid FQDN, where ndots < channel->ndots */ - return ARES_TRUE; - } - return ndots >= hquery->channel->ndots ? ARES_TRUE : ARES_FALSE; -} + name = hquery->names[hquery->next_name_idx++]; -static ares_bool_t as_is_only(const struct host_query *hquery) -{ - size_t nname = ares_strlen(hquery->name); - if (hquery->channel->flags & ARES_FLAG_NOSEARCH) { - return ARES_TRUE; - } - if (hquery->name != NULL && nname && hquery->name[nname - 1] == '.') { - return ARES_TRUE; + /* NOTE: hquery may be invalidated during the call to ares_query_qid(), + * so should not be referenced after this point */ + switch (hquery->hints.ai_family) { + case AF_INET: + hquery->remaining += 1; + ares_query_dnsrec(hquery->channel, name, ARES_CLASS_IN, ARES_REC_TYPE_A, + host_callback, hquery, &hquery->qid_a); + break; + case AF_INET6: + hquery->remaining += 1; + ares_query_dnsrec(hquery->channel, name, ARES_CLASS_IN, + ARES_REC_TYPE_AAAA, host_callback, hquery, + &hquery->qid_aaaa); + break; + case AF_UNSPEC: + hquery->remaining += 2; + ares_query_dnsrec(hquery->channel, name, ARES_CLASS_IN, ARES_REC_TYPE_A, + host_callback, hquery, &hquery->qid_a); + ares_query_dnsrec(hquery->channel, name, ARES_CLASS_IN, + ARES_REC_TYPE_AAAA, host_callback, hquery, + &hquery->qid_aaaa); + break; + default: + break; } - return ARES_FALSE; + + return ARES_TRUE; } diff --git a/deps/cares/src/lib/ares_gethostbyaddr.c b/deps/cares/src/lib/ares_gethostbyaddr.c index ab54706ba96889..453673260dcee5 100644 --- a/deps/cares/src/lib/ares_gethostbyaddr.c +++ b/deps/cares/src/lib/ares_gethostbyaddr.c @@ -59,11 +59,11 @@ struct addr_query { size_t timeouts; }; -static void next_lookup(struct addr_query *aquery); -static void addr_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen); -static void end_aquery(struct addr_query *aquery, ares_status_t status, - struct hostent *host); +static void next_lookup(struct addr_query *aquery); +static void addr_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec); +static void end_aquery(struct addr_query *aquery, ares_status_t status, + struct hostent *host); static ares_status_t file_lookup(ares_channel_t *channel, const struct ares_addr *addr, struct hostent **host); @@ -138,7 +138,8 @@ static void next_lookup(struct addr_query *aquery) return; } aquery->remaining_lookups = p + 1; - ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback, aquery); + ares_query_dnsrec(aquery->channel, name, ARES_CLASS_IN, + ARES_REC_TYPE_PTR, addr_callback, aquery, NULL); ares_free(name); return; case 'f': @@ -159,27 +160,27 @@ static void next_lookup(struct addr_query *aquery) end_aquery(aquery, ARES_ENOTFOUND, NULL); } -static void addr_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen) +static void addr_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec) { struct addr_query *aquery = (struct addr_query *)arg; struct hostent *host; size_t addrlen; - aquery->timeouts += (size_t)timeouts; + aquery->timeouts += timeouts; if (status == ARES_SUCCESS) { if (aquery->addr.family == AF_INET) { addrlen = sizeof(aquery->addr.addr.addr4); - status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addr.addr4, - (int)addrlen, AF_INET, &host); + status = ares_parse_ptr_reply_dnsrec(dnsrec, &aquery->addr.addr.addr4, + (int)addrlen, AF_INET, &host); } else { addrlen = sizeof(aquery->addr.addr.addr6); - status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addr.addr6, - (int)addrlen, AF_INET6, &host); + status = ares_parse_ptr_reply_dnsrec(dnsrec, &aquery->addr.addr.addr6, + (int)addrlen, AF_INET6, &host); } - end_aquery(aquery, (ares_status_t)status, host); + end_aquery(aquery, status, host); } else if (status == ARES_EDESTRUCTION || status == ARES_ECANCELLED) { - end_aquery(aquery, (ares_status_t)status, NULL); + end_aquery(aquery, status, NULL); } else { next_lookup(aquery); } diff --git a/deps/cares/src/lib/ares_init.c b/deps/cares/src/lib/ares_init.c index bae7c72fe2cf67..28a509ea48a5af 100644 --- a/deps/cares/src/lib/ares_init.c +++ b/deps/cares/src/lib/ares_init.c @@ -152,10 +152,6 @@ static ares_status_t init_by_defaults(ares_channel_t *channel) channel->tries = DEFAULT_TRIES; } - if (channel->ndots == 0) { - channel->ndots = 1; - } - if (ares__slist_len(channel->servers) == 0) { /* Add a default local named server to the channel unless configured not * to (in which case return an error). @@ -261,31 +257,6 @@ static ares_status_t init_by_defaults(ares_channel_t *channel) } error: - if (rc) { - if (channel->domains && channel->domains[0]) { - ares_free(channel->domains[0]); - } - if (channel->domains) { - ares_free(channel->domains); - channel->domains = NULL; - } - - if (channel->lookups) { - ares_free(channel->lookups); - channel->lookups = NULL; - } - - if (channel->resolvconf_path) { - ares_free(channel->resolvconf_path); - channel->resolvconf_path = NULL; - } - - if (channel->hosts_path) { - ares_free(channel->hosts_path); - channel->hosts_path = NULL; - } - } - if (hostname) { ares_free(hostname); } @@ -309,6 +280,9 @@ int ares_init_options(ares_channel_t **channelptr, return ARES_ENOMEM; } + /* One option where zero is valid, so set default value here */ + channel->ndots = 1; + status = ares__channel_threading_init(channel); if (status != ARES_SUCCESS) { goto done; diff --git a/deps/cares/src/lib/ares_ipv6.h b/deps/cares/src/lib/ares_ipv6.h index be8cbe989396c2..28d7851ff3f051 100644 --- a/deps/cares/src/lib/ares_ipv6.h +++ b/deps/cares/src/lib/ares_ipv6.h @@ -27,6 +27,10 @@ #ifndef ARES_IPV6_H #define ARES_IPV6_H +#ifdef HAVE_NETINET6_IN6_H +# include +#endif + #ifndef HAVE_PF_INET6 # define PF_INET6 AF_INET6 #endif diff --git a/deps/cares/src/lib/ares_library_init.c b/deps/cares/src/lib/ares_library_init.c index 5cd39dc244ba4b..2767f1f93c77e4 100644 --- a/deps/cares/src/lib/ares_library_init.c +++ b/deps/cares/src/lib/ares_library_init.c @@ -72,7 +72,7 @@ static void default_free(void *p) #endif void *(*ares_malloc)(size_t size) = default_malloc; void *(*ares_realloc)(void *ptr, size_t size) = default_realloc; -void (*ares_free)(void *ptr) = default_free; +void (*ares_free)(void *ptr) = default_free; void *ares_malloc_zero(size_t size) { @@ -114,7 +114,7 @@ int ares_library_init(int flags) } int ares_library_init_mem(int flags, void *(*amalloc)(size_t size), - void (*afree)(void *ptr), + void (*afree)(void *ptr), void *(*arealloc)(void *ptr, size_t size)) { if (amalloc) { diff --git a/deps/cares/src/lib/ares_mkquery.c b/deps/cares/src/lib/ares_mkquery.c deleted file mode 100644 index da1898e74cd951..00000000000000 --- a/deps/cares/src/lib/ares_mkquery.c +++ /dev/null @@ -1,35 +0,0 @@ -/* MIT License - * - * Copyright (c) 1998 Massachusetts Institute of Technology - * Copyright (c) The c-ares project and its contributors - * - * 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 (including the next - * paragraph) 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. - * - * SPDX-License-Identifier: MIT - */ - -#include "ares_setup.h" -#include "ares.h" - -int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id, - int rd, unsigned char **buf, int *buflen) -{ - return ares_create_query(name, dnsclass, type, id, rd, buf, buflen, 0); -} diff --git a/deps/cares/src/lib/ares_options.c b/deps/cares/src/lib/ares_options.c index 342d2ea1bec968..adc3e062ac437e 100644 --- a/deps/cares/src/lib/ares_options.c +++ b/deps/cares/src/lib/ares_options.c @@ -316,7 +316,7 @@ ares_status_t ares__init_by_options(ares_channel_t *channel, } if (optmask & ARES_OPT_NDOTS) { - if (options->ndots <= 0) { + if (options->ndots < 0) { optmask &= ~(ARES_OPT_NDOTS); } else { channel->ndots = (size_t)options->ndots; diff --git a/deps/cares/src/lib/ares_parse_a_reply.c b/deps/cares/src/lib/ares_parse_a_reply.c index f576575fe4b2fd..da841f0da9af36 100644 --- a/deps/cares/src/lib/ares_parse_a_reply.c +++ b/deps/cares/src/lib/ares_parse_a_reply.c @@ -59,6 +59,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, char *question_hostname = NULL; ares_status_t status; size_t req_naddrttls = 0; + ares_dns_record_t *dnsrec = NULL; if (alen < 0) { return ARES_EBADRESP; @@ -71,7 +72,12 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, memset(&ai, 0, sizeof(ai)); - status = ares__parse_into_addrinfo(abuf, (size_t)alen, 0, 0, &ai); + status = ares_dns_parse(abuf, (size_t)alen, 0, &dnsrec); + if (status != ARES_SUCCESS) { + goto fail; + } + + status = ares__parse_into_addrinfo(dnsrec, 0, 0, &ai); if (status != ARES_SUCCESS && status != ARES_ENODATA) { goto fail; } @@ -96,6 +102,11 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, ares__freeaddrinfo_nodes(ai.nodes); ares_free(ai.name); ares_free(question_hostname); + ares_dns_record_destroy(dnsrec); + + if (status == ARES_EBADNAME) { + status = ARES_EBADRESP; + } return (int)status; } diff --git a/deps/cares/src/lib/ares_parse_aaaa_reply.c b/deps/cares/src/lib/ares_parse_aaaa_reply.c index cef4ad7f80948f..b3eba166be6ad6 100644 --- a/deps/cares/src/lib/ares_parse_aaaa_reply.c +++ b/deps/cares/src/lib/ares_parse_aaaa_reply.c @@ -61,6 +61,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, char *question_hostname = NULL; ares_status_t status; size_t req_naddrttls = 0; + ares_dns_record_t *dnsrec = NULL; if (alen < 0) { return ARES_EBADRESP; @@ -73,7 +74,12 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, memset(&ai, 0, sizeof(ai)); - status = ares__parse_into_addrinfo(abuf, (size_t)alen, 0, 0, &ai); + status = ares_dns_parse(abuf, (size_t)alen, 0, &dnsrec); + if (status != ARES_SUCCESS) { + goto fail; + } + + status = ares__parse_into_addrinfo(dnsrec, 0, 0, &ai); if (status != ARES_SUCCESS && status != ARES_ENODATA) { goto fail; } @@ -97,6 +103,11 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, ares__freeaddrinfo_nodes(ai.nodes); ares_free(question_hostname); ares_free(ai.name); + ares_dns_record_destroy(dnsrec); + + if (status == ARES_EBADNAME) { + status = ARES_EBADRESP; + } return (int)status; } diff --git a/deps/cares/src/lib/ares_parse_ptr_reply.c b/deps/cares/src/lib/ares_parse_ptr_reply.c index d8a29f272251cf..6ee20f722e3d01 100644 --- a/deps/cares/src/lib/ares_parse_ptr_reply.c +++ b/deps/cares/src/lib/ares_parse_ptr_reply.c @@ -36,33 +36,20 @@ #include "ares.h" #include "ares_private.h" -int ares_parse_ptr_reply(const unsigned char *abuf, int alen_int, - const void *addr, int addrlen, int family, - struct hostent **host) +ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec, + const void *addr, int addrlen, + int family, struct hostent **host) { - ares_status_t status; - size_t alen; - size_t ptrcount = 0; - struct hostent *hostent = NULL; - const char *hostname = NULL; - const char *ptrname = NULL; - ares_dns_record_t *dnsrec = NULL; - size_t i; - size_t ancount; + ares_status_t status; + size_t ptrcount = 0; + struct hostent *hostent = NULL; + const char *hostname = NULL; + const char *ptrname = NULL; + size_t i; + size_t ancount; *host = NULL; - if (alen_int < 0) { - return ARES_EBADRESP; - } - - alen = (size_t)alen_int; - - status = ares_dns_parse(abuf, alen, 0, &dnsrec); - if (status != ARES_SUCCESS) { - goto done; - } - /* Fetch name from query as we will use it to compare later on. Old code * did this check, so we'll retain it. */ status = ares_dns_record_query_get(dnsrec, 0, &ptrname, NULL, NULL); @@ -114,7 +101,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen_int, /* Cycle through answers */ for (i = 0; i < ancount; i++) { const ares_dns_rr_t *rr = - ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, i); + ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i); if (rr == NULL) { /* Shouldn't be possible */ @@ -195,6 +182,34 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen_int, } else { *host = hostent; } + return status; +} + +int ares_parse_ptr_reply(const unsigned char *abuf, int alen_int, + const void *addr, int addrlen, int family, + struct hostent **host) +{ + size_t alen; + ares_dns_record_t *dnsrec = NULL; + ares_status_t status; + + if (alen_int < 0) { + return ARES_EBADRESP; + } + + alen = (size_t)alen_int; + + status = ares_dns_parse(abuf, alen, 0, &dnsrec); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_parse_ptr_reply_dnsrec(dnsrec, addr, addrlen, family, host); + +done: ares_dns_record_destroy(dnsrec); + if (status == ARES_EBADNAME) { + status = ARES_EBADRESP; + } return (int)status; } diff --git a/deps/cares/src/lib/ares_private.h b/deps/cares/src/lib/ares_private.h index fd321b911c4a1c..6a9e04af2eb633 100644 --- a/deps/cares/src/lib/ares_private.h +++ b/deps/cares/src/lib/ares_private.h @@ -209,7 +209,7 @@ struct query { unsigned char *qbuf; size_t qlen; - ares_callback callback; + ares_callback_dnsrec callback; void *arg; /* Query status */ @@ -318,12 +318,12 @@ struct ares_channeldata { }; /* Does the domain end in ".onion" or ".onion."? Case-insensitive. */ -ares_bool_t ares__is_onion_domain(const char *name); +ares_bool_t ares__is_onion_domain(const char *name); /* Memory management functions */ -extern void *(*ares_malloc)(size_t size); -extern void *(*ares_realloc)(void *ptr, size_t size); -extern void (*ares_free)(void *ptr); +extern void *(*ares_malloc)(size_t size); +extern void *(*ares_realloc)(void *ptr, size_t size); +extern void (*ares_free)(void *ptr); void *ares_malloc_zero(size_t size); void *ares_realloc_zero(void *ptr, size_t orig_size, size_t new_size); @@ -335,23 +335,37 @@ ares_bool_t ares__timedout(const struct timeval *now, ares_status_t ares__send_query(struct query *query, struct timeval *now); ares_status_t ares__requeue_query(struct query *query, struct timeval *now); -/* Identical to ares_query, but returns a normal ares return code like - * ARES_SUCCESS, and can be passed the qid by reference which will be - * filled in on ARES_SUCCESS */ -ares_status_t ares_query_qid(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg, unsigned short *qid); -/* Identical to ares_send() except returns normal ares return codes like - * ARES_SUCCESS */ -ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, - size_t qlen, ares_callback callback, void *arg, - unsigned short *qid); -void ares__close_connection(struct server_connection *conn); -void ares__close_sockets(struct server_state *server); -void ares__check_cleanup_conn(const ares_channel_t *channel, - struct server_connection *conn); -ares_status_t ares__read_line(FILE *fp, char **buf, size_t *bufsize); -void ares__free_query(struct query *query); +/*! Retrieve a list of names to use for searching. The first successful + * query in the list wins. This function also uses the HOSTSALIASES file + * as well as uses channel configuration to determine the search order. + * + * \param[in] channel initialized ares channel + * \param[in] name initial name being searched + * \param[out] names array of names to attempt, use ares__strsplit_free() + * when no longer needed. + * \param[out] names_len number of names in array + * \return ARES_SUCCESS on success, otherwise one of the other error codes. + */ +ares_status_t ares__search_name_list(const ares_channel_t *channel, + const char *name, char ***names, + size_t *names_len); + +/*! Function to create callback arg for converting from ares_callback_dnsrec + * to ares_calback */ +void *ares__dnsrec_convert_arg(ares_callback callback, void *arg); + +/*! Callback function used to convert from the ares_callback_dnsrec prototype to + * the ares_callback prototype, by writing the result and passing that to + * the inner callback. + */ +void ares__dnsrec_convert_cb(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec); + +void ares__close_connection(struct server_connection *conn); +void ares__close_sockets(struct server_state *server); +void ares__check_cleanup_conn(const ares_channel_t *channel, + struct server_connection *conn); +void ares__free_query(struct query *query); ares_rand_state *ares__init_rand_state(void); void ares__destroy_rand_state(ares_rand_state *state); @@ -391,6 +405,7 @@ typedef struct { size_t tries; ares_bool_t rotate; size_t timeout_ms; + ares_bool_t usevc; } ares_sysconfig_t; ares_status_t ares__init_by_environment(ares_sysconfig_t *sysconfig); @@ -401,8 +416,13 @@ ares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort, const char *str); void ares__destroy_servers_state(ares_channel_t *channel); -ares_status_t ares__single_domain(const ares_channel_t *channel, - const char *name, char **s); + +/* Returns ARES_SUCCESS if alias found, alias is set. Returns ARES_ENOTFOUND + * if not alias found. Returns other errors on critical failure like + * ARES_ENOMEM */ +ares_status_t ares__lookup_hostaliases(const ares_channel_t *channel, + const char *name, char **alias); + ares_status_t ares__cat_domain(const char *name, const char *domain, char **s); ares_status_t ares__sortaddrinfo(ares_channel_t *channel, struct ares_addrinfo_node *ai_node); @@ -427,10 +447,13 @@ ares_status_t ares_append_ai_node(int aftype, unsigned short port, void ares__addrinfo_cat_cnames(struct ares_addrinfo_cname **head, struct ares_addrinfo_cname *tail); -ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, +ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec, ares_bool_t cname_only_is_enodata, unsigned short port, struct ares_addrinfo *ai); +ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec, + const void *addr, int addrlen, + int family, struct hostent **host); ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family, struct hostent **host); @@ -456,10 +479,9 @@ ares_ssize_t ares__socket_recvfrom(ares_channel_t *channel, ares_socket_t s, ares_ssize_t ares__socket_recv(ares_channel_t *channel, ares_socket_t s, void *data, size_t data_len); void ares__close_socket(ares_channel, ares_socket_t); -int ares__connect_socket(ares_channel_t *channel, ares_socket_t sockfd, - const struct sockaddr *addr, ares_socklen_t addrlen); -ares_bool_t ares__is_hostnamech(int ch); -void ares__destroy_server(struct server_state *server); +int ares__connect_socket(ares_channel_t *channel, ares_socket_t sockfd, + const struct sockaddr *addr, ares_socklen_t addrlen); +void ares__destroy_server(struct server_state *server); ares_status_t ares__servers_update(ares_channel_t *channel, ares__llist_t *server_list, @@ -494,7 +516,6 @@ ares_status_t ares__hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry, unsigned short port, ares_bool_t want_cnames, struct ares_addrinfo *ai); -ares_bool_t ares__isprint(int ch); /*! Parse a compressed DNS name as defined in RFC1035 starting at the current @@ -560,7 +581,7 @@ void ares_queue_notify_empty(ares_channel_t *channel); } while (0) #define ARES_CONFIG_CHECK(x) \ - (x && x->lookups && ares__slist_len(x->servers) > 0 && x->ndots > 0 && \ + (x && x->lookups && ares__slist_len(x->servers) > 0 && \ x->timeout > 0 && x->tries > 0) ares_bool_t ares__subnet_match(const struct ares_addr *addr, @@ -583,10 +604,10 @@ ares_status_t ares_qcache_insert(ares_channel_t *channel, const struct timeval *now, const struct query *query, ares_dns_record_t *dnsrec); -ares_status_t ares_qcache_fetch(ares_channel_t *channel, - const struct timeval *now, - const unsigned char *qbuf, size_t qlen, - unsigned char **abuf, size_t *alen); +ares_status_t ares_qcache_fetch(ares_channel_t *channel, + const struct timeval *now, + const ares_dns_record_t *dnsrec, + const ares_dns_record_t **dnsrec_resp); ares_status_t ares__channel_threading_init(ares_channel_t *channel); void ares__channel_threading_destroy(ares_channel_t *channel); diff --git a/deps/cares/src/lib/ares_process.c b/deps/cares/src/lib/ares_process.c index bd84d09e134805..b9705ae882b9ff 100644 --- a/deps/cares/src/lib/ares_process.c +++ b/deps/cares/src/lib/ares_process.c @@ -68,8 +68,7 @@ static ares_bool_t same_questions(const ares_dns_record_t *qrec, static ares_bool_t same_address(const struct sockaddr *sa, const struct ares_addr *aa); static void end_query(ares_channel_t *channel, struct query *query, - ares_status_t status, const unsigned char *abuf, - size_t alen); + ares_status_t status, const ares_dns_record_t *dnsrec); static void server_increment_failures(struct server_state *server) { @@ -625,6 +624,7 @@ static ares_status_t process_answer(ares_channel_t *channel, ares_dns_record_t *rdnsrec = NULL; ares_dns_record_t *qdnsrec = NULL; ares_status_t status; + ares_bool_t is_cached = ARES_FALSE; /* Parse the response */ status = ares_dns_parse(abuf, alen, 0, &rdnsrec); @@ -648,7 +648,7 @@ static ares_status_t process_answer(ares_channel_t *channel, /* Parse the question we sent as we use it to compare */ status = ares_dns_parse(query->qbuf, query->qlen, 0, &qdnsrec); if (status != ARES_SUCCESS) { - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); goto cleanup; } @@ -674,7 +674,7 @@ static ares_status_t process_answer(ares_channel_t *channel, ares_dns_has_opt_rr(qdnsrec) && !ares_dns_has_opt_rr(rdnsrec)) { status = rewrite_without_edns(qdnsrec, query); if (status != ARES_SUCCESS) { - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); goto cleanup; } @@ -729,16 +729,20 @@ static ares_status_t process_answer(ares_channel_t *channel, /* If cache insertion was successful, it took ownership. We ignore * other cache insertion failures. */ if (ares_qcache_insert(channel, now, query, rdnsrec) == ARES_SUCCESS) { - rdnsrec = NULL; + is_cached = ARES_TRUE; } server_set_good(server); - end_query(channel, query, ARES_SUCCESS, abuf, alen); + end_query(channel, query, ARES_SUCCESS, rdnsrec); status = ARES_SUCCESS; cleanup: - ares_dns_record_destroy(rdnsrec); + /* Don't cleanup the cached pointer to the dns response */ + if (!is_cached) { + ares_dns_record_destroy(rdnsrec); + } + ares_dns_record_destroy(qdnsrec); return status; } @@ -774,7 +778,7 @@ ares_status_t ares__requeue_query(struct query *query, struct timeval *now) query->error_status = ARES_ETIMEOUT; } - end_query(channel, query, query->error_status, NULL, 0); + end_query(channel, query, query->error_status, NULL); return ARES_ETIMEOUT; } @@ -893,7 +897,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) } if (server == NULL) { - end_query(channel, query, ARES_ENOSERVER /* ? */, NULL, 0); + end_query(channel, query, ARES_ENOSERVER /* ? */, NULL); return ARES_ENOSERVER; } @@ -920,7 +924,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) /* Anything else is not retryable, likely ENOMEM */ default: - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); return status; } } @@ -931,7 +935,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) status = ares__append_tcpbuf(server, query); if (status != ARES_SUCCESS) { - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); /* Only safe to kill connection if it was new, otherwise it should be * cleaned up by another process later */ @@ -979,7 +983,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) /* Anything else is not retryable, likely ENOMEM */ default: - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); return status; } node = ares__llist_node_first(server->connections); @@ -1011,7 +1015,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) query->node_queries_by_timeout = ares__slist_insert(channel->queries_by_timeout, query); if (!query->node_queries_by_timeout) { - end_query(channel, query, ARES_ENOMEM, NULL, 0); + end_query(channel, query, ARES_ENOMEM, NULL); /* Only safe to kill connection if it was new, otherwise it should be * cleaned up by another process later */ if (new_connection) { @@ -1027,7 +1031,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) ares__llist_insert_last(conn->queries_to_conn, query); if (query->node_queries_to_conn == NULL) { - end_query(channel, query, ARES_ENOMEM, NULL, 0); + end_query(channel, query, ARES_ENOMEM, NULL); /* Only safe to kill connection if it was new, otherwise it should be * cleaned up by another process later */ if (new_connection) { @@ -1124,14 +1128,10 @@ static void ares_detach_query(struct query *query) } static void end_query(ares_channel_t *channel, struct query *query, - ares_status_t status, const unsigned char *abuf, - size_t alen) + ares_status_t status, const ares_dns_record_t *dnsrec) { /* Invoke the callback. */ - query->callback(query->arg, (int)status, (int)query->timeouts, - /* due to prior design flaws, abuf isn't meant to be modified, - * but bad prototypes, ugh. Lets cast off constfor compat. */ - (unsigned char *)((void *)((size_t)abuf)), (int)alen); + query->callback(query->arg, status, query->timeouts, dnsrec); ares__free_query(query); /* Check and notify if no other queries are enqueued on the channel. This diff --git a/deps/cares/src/lib/ares_qcache.c b/deps/cares/src/lib/ares_qcache.c index bab8781850789a..2af1125a0d299f 100644 --- a/deps/cares/src/lib/ares_qcache.c +++ b/deps/cares/src/lib/ares_qcache.c @@ -81,6 +81,7 @@ static char *ares__qcache_calc_key(const ares_dns_record_t *dnsrec) for (i = 0; i < ares_dns_record_query_cnt(dnsrec); i++) { const char *name; + size_t name_len; ares_dns_rec_type_t qtype; ares_dns_class_t qclass; @@ -114,7 +115,15 @@ static char *ares__qcache_calc_key(const ares_dns_record_t *dnsrec) goto fail; } - status = ares__buf_append_str(buf, name); + /* On queries, a '.' may be appended to the name to indicate an explicit + * name lookup without performing a search. Strip this since its not part + * of a cached response. */ + name_len = ares_strlen(name); + if (name_len && name[name_len - 1] == '.') { + name_len--; + } + + status = ares__buf_append(buf, (const unsigned char *)name, name_len); if (status != ARES_SUCCESS) { goto fail; } @@ -384,20 +393,24 @@ static ares_status_t ares__qcache_insert(ares__qcache_t *qcache, return ARES_ENOMEM; } -static ares_status_t ares__qcache_fetch(ares__qcache_t *qcache, - const ares_dns_record_t *dnsrec, - const struct timeval *now, - unsigned char **buf, size_t *buf_len) +ares_status_t ares_qcache_fetch(ares_channel_t *channel, + const struct timeval *now, + const ares_dns_record_t *dnsrec, + const ares_dns_record_t **dnsrec_resp) { char *key = NULL; ares__qcache_entry_t *entry; - ares_status_t status; + ares_status_t status = ARES_SUCCESS; - if (qcache == NULL || dnsrec == NULL) { + if (channel == NULL || dnsrec == NULL || dnsrec_resp == NULL) { return ARES_EFORMERR; } - ares__qcache_expire(qcache, now); + if (channel->qcache == NULL) { + return ARES_ENOTFOUND; + } + + ares__qcache_expire(channel->qcache, now); key = ares__qcache_calc_key(dnsrec); if (key == NULL) { @@ -405,7 +418,7 @@ static ares_status_t ares__qcache_fetch(ares__qcache_t *qcache, goto done; } - entry = ares__htable_strvp_get_direct(qcache->cache, key); + entry = ares__htable_strvp_get_direct(channel->qcache->cache, key); if (entry == NULL) { status = ARES_ENOTFOUND; goto done; @@ -414,7 +427,7 @@ static ares_status_t ares__qcache_fetch(ares__qcache_t *qcache, ares_dns_record_write_ttl_decrement( entry->dnsrec, (unsigned int)(now->tv_sec - entry->insert_ts)); - status = ares_dns_write(entry->dnsrec, buf, buf_len); + *dnsrec_resp = entry->dnsrec; done: ares_free(key); @@ -429,27 +442,3 @@ ares_status_t ares_qcache_insert(ares_channel_t *channel, return ares__qcache_insert(channel->qcache, dnsrec, query->qbuf, query->qlen, now); } - -ares_status_t ares_qcache_fetch(ares_channel_t *channel, - const struct timeval *now, - const unsigned char *qbuf, size_t qlen, - unsigned char **abuf, size_t *alen) -{ - ares_status_t status; - ares_dns_record_t *dnsrec = NULL; - - if (channel->qcache == NULL) { - return ARES_ENOTFOUND; - } - - status = ares_dns_parse(qbuf, qlen, 0, &dnsrec); - if (status != ARES_SUCCESS) { - goto done; - } - - status = ares__qcache_fetch(channel->qcache, dnsrec, now, abuf, alen); - -done: - ares_dns_record_destroy(dnsrec); - return status; -} diff --git a/deps/cares/src/lib/ares_query.c b/deps/cares/src/lib/ares_query.c index 098e6789471809..0eea80e7fc1e59 100644 --- a/deps/cares/src/lib/ares_query.c +++ b/deps/cares/src/lib/ares_query.c @@ -37,103 +37,116 @@ #include "ares_dns.h" #include "ares_private.h" -struct qquery { - ares_callback callback; - void *arg; -}; +typedef struct { + ares_callback_dnsrec callback; + void *arg; +} ares_query_dnsrec_arg_t; -static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, - int alen); - -ares_status_t ares_query_qid(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg, unsigned short *qid) +static void ares_query_dnsrec_cb(void *arg, ares_status_t status, + size_t timeouts, + const ares_dns_record_t *dnsrec) { - struct qquery *qquery; - unsigned char *qbuf; - int qlen; - int rd; - ares_status_t status; - - /* Compose the query. */ - rd = !(channel->flags & ARES_FLAG_NORECURSE); - status = (ares_status_t)ares_create_query( - name, dnsclass, type, 0, rd, &qbuf, &qlen, - (channel->flags & ARES_FLAG_EDNS) ? (int)channel->ednspsz : 0); + ares_query_dnsrec_arg_t *qquery = arg; + if (status != ARES_SUCCESS) { - if (qbuf != NULL) { - ares_free(qbuf); + qquery->callback(qquery->arg, status, timeouts, dnsrec); + } else { + size_t ancount; + ares_dns_rcode_t rcode; + /* Pull the response code and answer count from the packet and convert any + * errors. + */ + rcode = ares_dns_record_get_rcode(dnsrec); + ancount = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); + status = ares_dns_query_reply_tostatus(rcode, ancount); + qquery->callback(qquery->arg, status, timeouts, dnsrec); + } + ares_free(qquery); +} + +static ares_status_t ares_query_int(ares_channel_t *channel, const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, + ares_callback_dnsrec callback, void *arg, + unsigned short *qid) +{ + ares_status_t status; + ares_dns_record_t *dnsrec = NULL; + ares_dns_flags_t flags = 0; + ares_query_dnsrec_arg_t *qquery = NULL; + + if (channel == NULL || name == NULL || callback == NULL) { + status = ARES_EFORMERR; + if (callback != NULL) { + callback(arg, status, 0, NULL); } - callback(arg, (int)status, 0, NULL, 0); return status; } - /* Allocate and fill in the query structure. */ - qquery = ares_malloc(sizeof(struct qquery)); - if (!qquery) { - ares_free_string(qbuf); - callback(arg, ARES_ENOMEM, 0, NULL, 0); - return ARES_ENOMEM; + if (!(channel->flags & ARES_FLAG_NORECURSE)) { + flags |= ARES_FLAG_RD; } + + status = ares_dns_record_create_query( + &dnsrec, name, dnsclass, type, 0, flags, + (size_t)(channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : 0); + if (status != ARES_SUCCESS) { + callback(arg, status, 0, NULL); + return status; + } + + qquery = ares_malloc(sizeof(*qquery)); + if (qquery == NULL) { + status = ARES_ENOMEM; + callback(arg, status, 0, NULL); + ares_dns_record_destroy(dnsrec); + return status; + } + qquery->callback = callback; qquery->arg = arg; /* Send it off. qcallback will be called when we get an answer. */ - status = ares_send_ex(channel, qbuf, (size_t)qlen, qcallback, qquery, qid); - ares_free_string(qbuf); + status = ares_send_dnsrec(channel, dnsrec, ares_query_dnsrec_cb, qquery, qid); + ares_dns_record_destroy(dnsrec); return status; } -void ares_query(ares_channel_t *channel, const char *name, int dnsclass, - int type, ares_callback callback, void *arg) +ares_status_t ares_query_dnsrec(ares_channel_t *channel, const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, + ares_callback_dnsrec callback, void *arg, + unsigned short *qid) { + ares_status_t status; + if (channel == NULL) { - return; + return ARES_EFORMERR; } + ares__channel_lock(channel); - ares_query_qid(channel, name, dnsclass, type, callback, arg, NULL); + status = ares_query_int(channel, name, dnsclass, type, callback, arg, qid); ares__channel_unlock(channel); + return status; } -static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, - int alen) +void ares_query(ares_channel_t *channel, const char *name, int dnsclass, + int type, ares_callback callback, void *arg) { - struct qquery *qquery = (struct qquery *)arg; - size_t ancount; - int rcode; + void *carg = NULL; - if (status != ARES_SUCCESS) { - qquery->callback(qquery->arg, status, timeouts, abuf, alen); - } else { - /* Pull the response code and answer count from the packet. */ - rcode = DNS_HEADER_RCODE(abuf); - ancount = DNS_HEADER_ANCOUNT(abuf); - - /* Convert errors. */ - switch (rcode) { - case NOERROR: - status = (ancount > 0) ? ARES_SUCCESS : ARES_ENODATA; - break; - case FORMERR: - status = ARES_EFORMERR; - break; - case SERVFAIL: - status = ARES_ESERVFAIL; - break; - case NXDOMAIN: - status = ARES_ENOTFOUND; - break; - case NOTIMP: - status = ARES_ENOTIMP; - break; - case REFUSED: - status = ARES_EREFUSED; - break; - default: - break; - } - qquery->callback(qquery->arg, status, timeouts, abuf, alen); + if (channel == NULL) { + return; } - ares_free(qquery); + + carg = ares__dnsrec_convert_arg(callback, arg); + if (carg == NULL) { + callback(arg, ARES_ENOMEM, 0, NULL, 0); + return; + } + + ares_query_dnsrec(channel, name, (ares_dns_class_t)dnsclass, + (ares_dns_rec_type_t)type, ares__dnsrec_convert_cb, carg, + NULL); } diff --git a/deps/cares/src/lib/ares_search.c b/deps/cares/src/lib/ares_search.c index 429c7e1db0de26..4fd909cd4f8b9f 100644 --- a/deps/cares/src/lib/ares_search.c +++ b/deps/cares/src/lib/ares_search.c @@ -33,209 +33,437 @@ #include "ares.h" #include "ares_private.h" +#include "ares_dns.h" struct search_query { - /* Arguments passed to ares_search */ - ares_channel_t *channel; - char *name; /* copied into an allocated buffer */ - int dnsclass; - int type; - ares_callback callback; - void *arg; - char **domains; /* duplicate for ares_reinit() safety */ - size_t ndomains; - - int status_as_is; /* error status from trying as-is */ - size_t next_domain; /* next search domain to try */ - ares_bool_t trying_as_is; /* current query is for name as-is */ - size_t timeouts; /* number of timeouts we saw for this request */ + /* Arguments passed to ares_search_dnsrec() */ + ares_channel_t *channel; + ares_callback_dnsrec callback; + void *arg; + + /* Duplicate of DNS record passed to ares_search_dnsrec() */ + ares_dns_record_t *dnsrec; + + /* Search order for names */ + char **names; + size_t names_cnt; + + /* State tracking progress through the search query */ + size_t next_name_idx; /* next name index being attempted */ + size_t timeouts; /* number of timeouts we saw for this request */ ares_bool_t ever_got_nodata; /* did we ever get ARES_ENODATA along the way? */ }; -static void search_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen); +static void squery_free(struct search_query *squery) +{ + if (squery == NULL) { + return; + } + ares__strsplit_free(squery->names, squery->names_cnt); + ares_dns_record_destroy(squery->dnsrec); + ares_free(squery); +} + +/* End a search query by invoking the user callback and freeing the + * search_query structure. + */ static void end_squery(struct search_query *squery, ares_status_t status, - unsigned char *abuf, size_t alen); + const ares_dns_record_t *dnsrec) +{ + squery->callback(squery->arg, status, squery->timeouts, dnsrec); + squery_free(squery); +} + +static void search_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec); -static void ares_search_int(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg) +static ares_status_t ares_search_next(ares_channel_t *channel, + struct search_query *squery, + ares_bool_t *skip_cleanup) { - struct search_query *squery; - char *s; - const char *p; - ares_status_t status; - size_t ndots; + ares_status_t status; - /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */ - if (ares__is_onion_domain(name)) { - callback(arg, ARES_ENOTFOUND, 0, NULL, 0); - return; + *skip_cleanup = ARES_FALSE; + + /* Misuse check */ + if (squery->next_name_idx >= squery->names_cnt) { + return ARES_EFORMERR; } - /* If name only yields one domain to search, then we don't have - * to keep extra state, so just do an ares_query(). - */ - status = ares__single_domain(channel, name, &s); + status = ares_dns_record_query_set_name( + squery->dnsrec, 0, squery->names[squery->next_name_idx++]); if (status != ARES_SUCCESS) { - callback(arg, (int)status, 0, NULL, 0); + return status; + } + + status = + ares_send_dnsrec(channel, squery->dnsrec, search_callback, squery, NULL); + + if (status != ARES_EFORMERR) { + *skip_cleanup = ARES_TRUE; + } + + return status; +} + +static void search_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec) +{ + struct search_query *squery = (struct search_query *)arg; + ares_channel_t *channel = squery->channel; + ares_dns_rcode_t rcode; + size_t ancount; + ares_status_t mystatus; + ares_bool_t skip_cleanup = ARES_FALSE; + + squery->timeouts += timeouts; + + if (status != ARES_SUCCESS) { + end_squery(squery, status, dnsrec); return; } - if (s) { - ares_query(channel, s, dnsclass, type, callback, arg); - ares_free(s); + + rcode = ares_dns_record_get_rcode(dnsrec); + ancount = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); + mystatus = ares_dns_query_reply_tostatus(rcode, ancount); + + if (mystatus != ARES_ENODATA && mystatus != ARES_ESERVFAIL && + mystatus != ARES_ENOTFOUND) { + end_squery(squery, mystatus, dnsrec); return; } - /* Allocate a search_query structure to hold the state necessary for - * doing multiple lookups. + /* If we ever get ARES_ENODATA along the way, record that; if the search + * should run to the very end and we got at least one ARES_ENODATA, + * then callers like ares_gethostbyname() may want to try a T_A search + * even if the last domain we queried for T_AAAA resource records + * returned ARES_ENOTFOUND. */ - squery = ares_malloc_zero(sizeof(*squery)); - if (!squery) { - callback(arg, ARES_ENOMEM, 0, NULL, 0); + if (mystatus == ARES_ENODATA) { + squery->ever_got_nodata = ARES_TRUE; + } + + if (squery->next_name_idx < squery->names_cnt) { + mystatus = ares_search_next(channel, squery, &skip_cleanup); + if (mystatus != ARES_SUCCESS && !skip_cleanup) { + end_squery(squery, mystatus, NULL); + } return; } - squery->channel = channel; - squery->name = ares_strdup(name); - if (!squery->name) { - ares_free(squery); - callback(arg, ARES_ENOMEM, 0, NULL, 0); + + + /* We have no more domains to search, return an appropriate response. */ + if (mystatus == ARES_ENOTFOUND && squery->ever_got_nodata) { + end_squery(squery, ARES_ENODATA, NULL); return; } - /* Duplicate domains for safety during ares_reinit() */ - if (channel->ndomains) { - squery->domains = - ares__strsplit_duplicate(channel->domains, channel->ndomains); - if (squery->domains == NULL) { - ares_free(squery->name); - ares_free(squery); - callback(arg, ARES_ENOMEM, 0, NULL, 0); - return; + end_squery(squery, mystatus, NULL); +} + +/* Determine if the domain should be looked up as-is, or if it is eligible + * for search by appending domains */ +static ares_bool_t ares__search_eligible(const ares_channel_t *channel, + const char *name) +{ + size_t len = ares_strlen(name); + + /* Name ends in '.', cannot search */ + if (len && name[len - 1] == '.') { + return ARES_FALSE; + } + + if (channel->flags & ARES_FLAG_NOSEARCH) { + return ARES_FALSE; + } + + return ARES_TRUE; +} + +ares_status_t ares__search_name_list(const ares_channel_t *channel, + const char *name, char ***names, + size_t *names_len) +{ + ares_status_t status; + char **list = NULL; + size_t list_len = 0; + char *alias = NULL; + size_t ndots = 0; + size_t idx = 0; + const char *p; + size_t i; + + /* Perform HOSTALIASES resolution */ + status = ares__lookup_hostaliases(channel, name, &alias); + if (status == ARES_SUCCESS) { + /* If hostalias succeeds, there is no searching, it is used as-is */ + list_len = 1; + list = ares_malloc_zero(sizeof(*list) * list_len); + if (list == NULL) { + status = ARES_ENOMEM; + goto done; } - squery->ndomains = channel->ndomains; + list[0] = alias; + alias = NULL; + goto done; + } else if (status != ARES_ENOTFOUND) { + goto done; } - squery->dnsclass = dnsclass; - squery->type = type; - squery->status_as_is = -1; - squery->callback = callback; - squery->arg = arg; - squery->timeouts = 0; - squery->ever_got_nodata = ARES_FALSE; + /* See if searching is eligible at all, if not, look up as-is only */ + if (!ares__search_eligible(channel, name)) { + list_len = 1; + list = ares_malloc_zero(sizeof(*list) * list_len); + if (list == NULL) { + status = ARES_ENOMEM; + goto done; + } + list[0] = ares_strdup(name); + if (list[0] == NULL) { + status = ARES_ENOMEM; + } else { + status = ARES_SUCCESS; + } + goto done; + } - /* Count the number of dots in name. */ + /* Count the number of dots in name */ ndots = 0; - for (p = name; *p; p++) { + for (p = name; *p != 0; p++) { if (*p == '.') { ndots++; } } - /* If ndots is at least the channel ndots threshold (usually 1), - * then we try the name as-is first. Otherwise, we try the name - * as-is last. - */ - if (ndots >= channel->ndots || squery->ndomains == 0) { - /* Try the name as-is first. */ - squery->next_domain = 0; - squery->trying_as_is = ARES_TRUE; - ares_query(channel, name, dnsclass, type, search_callback, squery); - } else { - /* Try the name as-is last; start with the first search domain. */ - squery->next_domain = 1; - squery->trying_as_is = ARES_FALSE; - status = ares__cat_domain(name, squery->domains[0], &s); - if (status == ARES_SUCCESS) { - ares_query(channel, s, dnsclass, type, search_callback, squery); - ares_free(s); - } else { - /* failed, free the malloc()ed memory */ - ares_free(squery->name); - ares_free(squery); - callback(arg, (int)status, 0, NULL, 0); + /* Allocate an entry for each search domain, plus one for as-is */ + list_len = channel->ndomains + 1; + list = ares_malloc_zero(sizeof(*list) * list_len); + if (list == NULL) { + status = ARES_ENOMEM; + goto done; + } + + /* Set status here, its possible there are no search domains at all, so + * status may be ARES_ENOTFOUND from ares__lookup_hostaliases(). */ + status = ARES_SUCCESS; + + /* Try as-is first */ + if (ndots >= channel->ndots) { + list[idx] = ares_strdup(name); + if (list[idx] == NULL) { + status = ARES_ENOMEM; + goto done; + } + idx++; + } + + /* Append each search suffix to the name */ + for (i = 0; i < channel->ndomains; i++) { + status = ares__cat_domain(name, channel->domains[i], &list[idx]); + if (status != ARES_SUCCESS) { + goto done; } + idx++; } + + /* Try as-is last */ + if (ndots < channel->ndots) { + list[idx] = ares_strdup(name); + if (list[idx] == NULL) { + status = ARES_ENOMEM; + goto done; + } + idx++; + } + + +done: + if (status == ARES_SUCCESS) { + *names = list; + *names_len = list_len; + } else { + ares__strsplit_free(list, list_len); + } + + ares_free(alias); + return status; } -void ares_search(ares_channel_t *channel, const char *name, int dnsclass, - int type, ares_callback callback, void *arg) +static ares_status_t ares_search_int(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, void *arg) { - if (channel == NULL) { - return; + struct search_query *squery = NULL; + const char *name; + ares_status_t status = ARES_SUCCESS; + ares_bool_t skip_cleanup = ARES_FALSE; + + /* Extract the name for the search. Note that searches are only supported for + * DNS records containing a single query. + */ + if (ares_dns_record_query_cnt(dnsrec) != 1) { + status = ARES_EBADQUERY; + goto fail; } - ares__channel_lock(channel); - ares_search_int(channel, name, dnsclass, type, callback, arg); - ares__channel_unlock(channel); + + status = ares_dns_record_query_get(dnsrec, 0, &name, NULL, NULL); + if (status != ARES_SUCCESS) { + goto fail; + } + + /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */ + if (ares__is_onion_domain(name)) { + status = ARES_ENOTFOUND; + goto fail; + } + + /* Allocate a search_query structure to hold the state necessary for + * doing multiple lookups. + */ + squery = ares_malloc_zero(sizeof(*squery)); + if (squery == NULL) { + status = ARES_ENOMEM; + goto fail; + } + + squery->channel = channel; + + /* Duplicate DNS record since, name will need to be rewritten */ + squery->dnsrec = ares_dns_record_duplicate(dnsrec); + if (squery->dnsrec == NULL) { + status = ARES_ENOMEM; + goto fail; + } + + squery->callback = callback; + squery->arg = arg; + squery->timeouts = 0; + squery->ever_got_nodata = ARES_FALSE; + + status = + ares__search_name_list(channel, name, &squery->names, &squery->names_cnt); + if (status != ARES_SUCCESS) { + goto fail; + } + + status = ares_search_next(channel, squery, &skip_cleanup); + if (status != ARES_SUCCESS) { + goto fail; + } + + return status; + +fail: + if (!skip_cleanup) { + squery_free(squery); + callback(arg, status, 0, NULL); + } + return status; } -static void search_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen) +/* Callback argument structure passed to ares__dnsrec_convert_cb(). */ +typedef struct { + ares_callback callback; + void *arg; +} dnsrec_convert_arg_t; + +/*! Function to create callback arg for converting from ares_callback_dnsrec + * to ares_calback */ +void *ares__dnsrec_convert_arg(ares_callback callback, void *arg) { - struct search_query *squery = (struct search_query *)arg; - ares_channel_t *channel = squery->channel; - char *s; + dnsrec_convert_arg_t *carg = ares_malloc_zero(sizeof(*carg)); + if (carg == NULL) { + return NULL; + } + carg->callback = callback; + carg->arg = arg; + return carg; +} - squery->timeouts += (size_t)timeouts; +/*! Callback function used to convert from the ares_callback_dnsrec prototype to + * the ares_callback prototype, by writing the result and passing that to + * the inner callback. + */ +void ares__dnsrec_convert_cb(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec) +{ + dnsrec_convert_arg_t *carg = arg; + unsigned char *abuf = NULL; + size_t alen = 0; - /* Stop searching unless we got a non-fatal error. */ - if (status != ARES_ENODATA && status != ARES_ESERVFAIL && - status != ARES_ENOTFOUND) { - end_squery(squery, (ares_status_t)status, abuf, (size_t)alen); - } else { - /* Save the status if we were trying as-is. */ - if (squery->trying_as_is) { - squery->status_as_is = status; + if (dnsrec != NULL) { + ares_status_t mystatus = ares_dns_write(dnsrec, &abuf, &alen); + if (mystatus != ARES_SUCCESS) { + status = mystatus; } + } - /* - * If we ever get ARES_ENODATA along the way, record that; if the search - * should run to the very end and we got at least one ARES_ENODATA, - * then callers like ares_gethostbyname() may want to try a T_A search - * even if the last domain we queried for T_AAAA resource records - * returned ARES_ENOTFOUND. - */ - if (status == ARES_ENODATA) { - squery->ever_got_nodata = ARES_TRUE; - } + carg->callback(carg->arg, (int)status, (int)timeouts, abuf, (int)alen); - if (squery->next_domain < squery->ndomains) { - ares_status_t mystatus; - /* Try the next domain. */ - mystatus = ares__cat_domain(squery->name, - squery->domains[squery->next_domain], &s); - if (mystatus != ARES_SUCCESS) { - end_squery(squery, mystatus, NULL, 0); - } else { - squery->trying_as_is = ARES_FALSE; - squery->next_domain++; - ares_query(channel, s, squery->dnsclass, squery->type, search_callback, - squery); - ares_free(s); - } - } else if (squery->status_as_is == -1) { - /* Try the name as-is at the end. */ - squery->trying_as_is = ARES_TRUE; - ares_query(channel, squery->name, squery->dnsclass, squery->type, - search_callback, squery); - } else { - if (squery->status_as_is == ARES_ENOTFOUND && squery->ever_got_nodata) { - end_squery(squery, ARES_ENODATA, NULL, 0); - } else { - end_squery(squery, (ares_status_t)squery->status_as_is, NULL, 0); - } - } + ares_free(abuf); + ares_free(carg); +} + +/* Search for a DNS name with given class and type. Wrapper around + * ares_search_int() where the DNS record to search is first constructed. + */ +void ares_search(ares_channel_t *channel, const char *name, int dnsclass, + int type, ares_callback callback, void *arg) +{ + ares_status_t status; + ares_dns_record_t *dnsrec = NULL; + size_t max_udp_size; + ares_dns_flags_t rd_flag; + void *carg = NULL; + if (channel == NULL || name == NULL) { + return; + } + + /* For now, ares_search_int() uses the ares_callback prototype. We need to + * wrap the callback passed to this function in ares__dnsrec_convert_cb, to + * convert from ares_callback_dnsrec to ares_callback. Allocate the convert + * arg structure here. + */ + carg = ares__dnsrec_convert_arg(callback, arg); + if (carg == NULL) { + callback(arg, ARES_ENOMEM, 0, NULL, 0); + return; + } + + rd_flag = !(channel->flags & ARES_FLAG_NORECURSE) ? ARES_FLAG_RD : 0; + max_udp_size = (channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : 0; + status = ares_dns_record_create_query( + &dnsrec, name, (ares_dns_class_t)dnsclass, (ares_dns_rec_type_t)type, 0, + rd_flag, max_udp_size); + if (status != ARES_SUCCESS) { + callback(arg, (int)status, 0, NULL, 0); + ares_free(carg); + return; } + + ares__channel_lock(channel); + ares_search_int(channel, dnsrec, ares__dnsrec_convert_cb, carg); + ares__channel_unlock(channel); + + ares_dns_record_destroy(dnsrec); } -static void end_squery(struct search_query *squery, ares_status_t status, - unsigned char *abuf, size_t alen) +/* Search for a DNS record. Wrapper around ares_search_int(). */ +ares_status_t ares_search_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, void *arg) { - squery->callback(squery->arg, (int)status, (int)squery->timeouts, abuf, - (int)alen); - ares__strsplit_free(squery->domains, squery->ndomains); - ares_free(squery->name); - ares_free(squery); + ares_status_t status; + + if (channel == NULL || dnsrec == NULL || callback == NULL) { + return ARES_EFORMERR; + } + + ares__channel_lock(channel); + status = ares_search_int(channel, dnsrec, callback, arg); + ares__channel_unlock(channel); + + return status; } /* Concatenate two domains. */ @@ -260,89 +488,113 @@ ares_status_t ares__cat_domain(const char *name, const char *domain, char **s) return ARES_SUCCESS; } -/* Determine if this name only yields one query. If it does, set *s to - * the string we should query, in an allocated buffer. If not, set *s - * to NULL. - */ -ares_status_t ares__single_domain(const ares_channel_t *channel, - const char *name, char **s) +ares_status_t ares__lookup_hostaliases(const ares_channel_t *channel, + const char *name, char **alias) { - size_t len = ares_strlen(name); - const char *hostaliases; - FILE *fp; - char *line = NULL; - ares_status_t status; - size_t linesize; - const char *p; - const char *q; - int error; + ares_status_t status = ARES_SUCCESS; + const char *hostaliases = NULL; + ares__buf_t *buf = NULL; + ares__llist_t *lines = NULL; + ares__llist_node_t *node; + + if (channel == NULL || name == NULL || alias == NULL) { + return ARES_EFORMERR; + } + + *alias = NULL; + + /* Configuration says to not perform alias lookup */ + if (channel->flags & ARES_FLAG_NOALIASES) { + return ARES_ENOTFOUND; + } + + /* If a domain has a '.', its not allowed to perform an alias lookup */ + if (strchr(name, '.') != NULL) { + return ARES_ENOTFOUND; + } - /* If the name contains a trailing dot, then the single query is the name - * sans the trailing dot. + hostaliases = getenv("HOSTALIASES"); + if (hostaliases == NULL) { + status = ARES_ENOTFOUND; + goto done; + } + + buf = ares__buf_create(); + if (buf == NULL) { + status = ARES_ENOMEM; + goto done; + } + + status = ares__buf_load_file(hostaliases, buf); + if (status != ARES_SUCCESS) { + goto done; + } + + /* The HOSTALIASES file is structured as one alias per line. The first + * field in the line is the simple hostname with no periods, followed by + * whitespace, then the full domain name, e.g.: + * + * c-ares www.c-ares.org + * curl www.curl.se */ - if ((len > 0) && (name[len - 1] == '.')) { - *s = ares_strdup(name); - return (*s) ? ARES_SUCCESS : ARES_ENOMEM; - } - - if (!(channel->flags & ARES_FLAG_NOALIASES) && !strchr(name, '.')) { - /* The name might be a host alias. */ - hostaliases = getenv("HOSTALIASES"); - if (hostaliases) { - fp = fopen(hostaliases, "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == - ARES_SUCCESS) { - if (strncasecmp(line, name, len) != 0 || !ISSPACE(line[len])) { - continue; - } - p = line + len; - while (ISSPACE(*p)) { - p++; - } - if (*p) { - q = p + 1; - while (*q && !ISSPACE(*q)) { - q++; - } - *s = ares_malloc((size_t)(q - p + 1)); - if (*s) { - memcpy(*s, p, (size_t)(q - p)); - (*s)[q - p] = 0; - } - ares_free(line); - fclose(fp); - return (*s) ? ARES_SUCCESS : ARES_ENOMEM; - } - } - ares_free(line); - fclose(fp); - if (status != ARES_SUCCESS && status != ARES_EOF) { - return status; - } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", hostaliases)); - *s = NULL; - return ARES_EFILE; - } - } - } + + status = ares__buf_split(buf, (const unsigned char *)"\n", 1, + ARES_BUF_SPLIT_TRIM, 0, &lines); + if (status != ARES_SUCCESS) { + goto done; } - if (channel->flags & ARES_FLAG_NOSEARCH || channel->ndomains == 0) { - /* No domain search to do; just try the name as-is. */ - *s = ares_strdup(name); - return (*s) ? ARES_SUCCESS : ARES_ENOMEM; + for (node = ares__llist_node_first(lines); node != NULL; + node = ares__llist_node_next(node)) { + ares__buf_t *line = ares__llist_node_val(node); + char hostname[64] = ""; + char fqdn[256] = ""; + + /* Pull off hostname */ + ares__buf_tag(line); + ares__buf_consume_nonwhitespace(line); + if (ares__buf_tag_fetch_string(line, hostname, sizeof(hostname)) != + ARES_SUCCESS) { + continue; + } + + /* Match hostname */ + if (strcasecmp(hostname, name) != 0) { + continue; + } + + /* consume whitespace */ + ares__buf_consume_whitespace(line, ARES_TRUE); + + /* pull off fqdn */ + ares__buf_tag(line); + ares__buf_consume_nonwhitespace(line); + if (ares__buf_tag_fetch_string(line, fqdn, sizeof(fqdn)) != ARES_SUCCESS || + ares_strlen(fqdn) == 0) { + continue; + } + + /* Validate characterset */ + if (!ares__is_hostname(fqdn)) { + continue; + } + + *alias = ares_strdup(fqdn); + if (*alias == NULL) { + status = ARES_ENOMEM; + goto done; + } + + /* Good! */ + status = ARES_SUCCESS; + goto done; } - *s = NULL; - return ARES_SUCCESS; + status = ARES_ENOTFOUND; + +done: + ares__buf_destroy(buf); + ares__llist_destroy(lines); + + return status; } diff --git a/deps/cares/src/lib/ares_send.c b/deps/cares/src/lib/ares_send.c index 6cefdb6a36a87e..54f2b504d50cac 100644 --- a/deps/cares/src/lib/ares_send.c +++ b/deps/cares/src/lib/ares_send.c @@ -48,52 +48,47 @@ static unsigned short generate_unique_qid(ares_channel_t *channel) return id; } -ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, - size_t qlen, ares_callback callback, void *arg, - unsigned short *qid) +static ares_status_t ares_send_dnsrec_int(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, + void *arg, unsigned short *qid) { - struct query *query; - size_t packetsz; - struct timeval now = ares__tvnow(); - ares_status_t status; - unsigned short id = generate_unique_qid(channel); - unsigned char *abuf = NULL; - size_t alen = 0; + struct query *query; + size_t packetsz; + struct timeval now = ares__tvnow(); + ares_status_t status; + unsigned short id = generate_unique_qid(channel); + const ares_dns_record_t *dnsrec_resp = NULL; - /* Verify that the query is at least long enough to hold the header. */ - if (qlen < HFIXEDSZ || qlen >= (1 << 16)) { - callback(arg, ARES_EBADQUERY, 0, NULL, 0); - return ARES_EBADQUERY; - } if (ares__slist_len(channel->servers) == 0) { - callback(arg, ARES_ENOSERVER, 0, NULL, 0); + callback(arg, ARES_ENOSERVER, 0, NULL); return ARES_ENOSERVER; } /* Check query cache */ - status = ares_qcache_fetch(channel, &now, qbuf, qlen, &abuf, &alen); + status = ares_qcache_fetch(channel, &now, dnsrec, &dnsrec_resp); if (status != ARES_ENOTFOUND) { /* ARES_SUCCESS means we retrieved the cache, anything else is a critical * failure, all result in termination */ - callback(arg, (int)status, 0, abuf, (int)alen); - ares_free(abuf); + callback(arg, status, 0, dnsrec_resp); return status; } /* Allocate space for query and allocated fields. */ query = ares_malloc(sizeof(struct query)); if (!query) { - callback(arg, ARES_ENOMEM, 0, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL); return ARES_ENOMEM; } memset(query, 0, sizeof(*query)); query->channel = channel; - query->qbuf = ares_malloc(qlen); - if (!query->qbuf) { + + status = ares_dns_write(dnsrec, &query->qbuf, &query->qlen); + if (status != ARES_SUCCESS) { ares_free(query); - callback(arg, ARES_ENOMEM, 0, NULL, 0); - return ARES_ENOMEM; + callback(arg, status, 0, NULL); + return status; } query->qid = id; @@ -103,8 +98,6 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, /* Ignore first 2 bytes, assign our own query id */ query->qbuf[0] = (unsigned char)((id >> 8) & 0xFF); query->qbuf[1] = (unsigned char)(id & 0xFF); - memcpy(query->qbuf + 2, qbuf + 2, qlen - 2); - query->qlen = qlen; /* Fill in query arguments. */ query->callback = callback; @@ -114,7 +107,8 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, query->try_count = 0; packetsz = (channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : PACKETSZ; - query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > packetsz; + query->using_tcp = + (channel->flags & ARES_FLAG_USEVC) || query->qlen > packetsz; query->error_status = ARES_SUCCESS; query->timeouts = 0; @@ -127,7 +121,7 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, query->node_all_queries = ares__llist_insert_last(channel->all_queries, query); if (query->node_all_queries == NULL) { - callback(arg, ARES_ENOMEM, 0, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL); ares__free_query(query); return ARES_ENOMEM; } @@ -136,7 +130,7 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, * responses quickly. */ if (!ares__htable_szvp_insert(channel->queries_by_qid, query->qid, query)) { - callback(arg, ARES_ENOMEM, 0, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL); ares__free_query(query); return ARES_ENOMEM; } @@ -150,18 +144,60 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, return status; } +ares_status_t ares_send_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, void *arg, + unsigned short *qid) +{ + ares_status_t status; + + if (channel == NULL) { + return ARES_EFORMERR; + } + + ares__channel_lock(channel); + + status = ares_send_dnsrec_int(channel, dnsrec, callback, arg, qid); + + ares__channel_unlock(channel); + + return status; +} + void ares_send(ares_channel_t *channel, const unsigned char *qbuf, int qlen, ares_callback callback, void *arg) { + ares_dns_record_t *dnsrec = NULL; + ares_status_t status; + void *carg = NULL; + if (channel == NULL) { return; } - ares__channel_lock(channel); + /* Verify that the query is at least long enough to hold the header. */ + if (qlen < HFIXEDSZ || qlen >= (1 << 16)) { + callback(arg, ARES_EBADQUERY, 0, NULL, 0); + return; + } - ares_send_ex(channel, qbuf, (size_t)qlen, callback, arg, NULL); + status = ares_dns_parse(qbuf, (size_t)qlen, 0, &dnsrec); + if (status != ARES_SUCCESS) { + callback(arg, (int)status, 0, NULL, 0); + return; + } - ares__channel_unlock(channel); + carg = ares__dnsrec_convert_arg(callback, arg); + if (carg == NULL) { + status = ARES_ENOMEM; + ares_dns_record_destroy(dnsrec); + callback(arg, (int)status, 0, NULL, 0); + return; + } + + ares_send_dnsrec(channel, dnsrec, ares__dnsrec_convert_cb, carg, NULL); + + ares_dns_record_destroy(dnsrec); } size_t ares_queue_active_queries(ares_channel_t *channel) diff --git a/deps/cares/src/lib/ares_str.c b/deps/cares/src/lib/ares_str.c index 80660136dac8e1..5f25cfeaff041e 100644 --- a/deps/cares/src/lib/ares_str.c +++ b/deps/cares/src/lib/ares_str.c @@ -110,6 +110,54 @@ ares_bool_t ares_str_isnum(const char *str) return ARES_TRUE; } +void ares__str_rtrim(char *str) +{ + size_t len; + size_t i; + + if (str == NULL) { + return; + } + + len = ares_strlen(str); + for (i = len; i > 0; i--) { + if (!ares__isspace(str[i - 1])) { + break; + } + } + str[i] = 0; +} + +void ares__str_ltrim(char *str) +{ + size_t i; + size_t len; + + if (str == NULL) { + return; + } + + for (i = 0; str[i] != 0 && ares__isspace(str[i]); i++) { + /* Do nothing */ + } + + if (i == 0) { + return; + } + + len = ares_strlen(str); + if (i != len) { + memmove(str, str + i, len - i); + } + str[len - i] = 0; +} + +void ares__str_trim(char *str) +{ + ares__str_ltrim(str); + ares__str_rtrim(str); +} + /* tolower() is locale-specific. Use a lookup table fast conversion that only * operates on ASCII */ static const unsigned char ares__tolower_lookup[] = { @@ -151,3 +199,71 @@ ares_bool_t ares__memeq_ci(const unsigned char *ptr, const unsigned char *val, } return ARES_TRUE; } + +ares_bool_t ares__isspace(int ch) +{ + switch (ch) { + case '\r': + case '\t': + case ' ': + case '\v': + case '\f': + case '\n': + return ARES_TRUE; + default: + break; + } + return ARES_FALSE; +} + +ares_bool_t ares__isprint(int ch) +{ + if (ch >= 0x20 && ch <= 0x7E) { + return ARES_TRUE; + } + return ARES_FALSE; +} + +/* Character set allowed by hostnames. This is to include the normal + * domain name character set plus: + * - underscores which are used in SRV records. + * - Forward slashes such as are used for classless in-addr.arpa + * delegation (CNAMEs) + * - Asterisks may be used for wildcard domains in CNAMEs as seen in the + * real world. + * While RFC 2181 section 11 does state not to do validation, + * that applies to servers, not clients. Vulnerabilities have been + * reported when this validation is not performed. Security is more + * important than edge-case compatibility (which is probably invalid + * anyhow). */ +ares_bool_t ares__is_hostnamech(int ch) +{ + /* [A-Za-z0-9-*._/] + * Don't use isalnum() as it is locale-specific + */ + if (ch >= 'A' && ch <= 'Z') { + return ARES_TRUE; + } + if (ch >= 'a' && ch <= 'z') { + return ARES_TRUE; + } + if (ch >= '0' && ch <= '9') { + return ARES_TRUE; + } + if (ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '*') { + return ARES_TRUE; + } + + return ARES_FALSE; +} + +ares_bool_t ares__is_hostname(const char *str) +{ + size_t i; + for (i = 0; str[i] != 0; i++) { + if (!ares__is_hostnamech(str[i])) { + return ARES_FALSE; + } + } + return ARES_TRUE; +} diff --git a/deps/cares/src/lib/ares_str.h b/deps/cares/src/lib/ares_str.h index 2bf32d0d253da7..8d869073d8153c 100644 --- a/deps/cares/src/lib/ares_str.h +++ b/deps/cares/src/lib/ares_str.h @@ -24,8 +24,8 @@ * * SPDX-License-Identifier: MIT */ -#ifndef HEADER_CARES_STRDUP_H -#define HEADER_CARES_STRDUP_H +#ifndef __ARES_STR_H +#define __ARES_STR_H #include "ares_setup.h" #include "ares.h" @@ -48,8 +48,19 @@ size_t ares_strcpy(char *dest, const char *src, size_t dest_size); ares_bool_t ares_str_isnum(const char *str); +void ares__str_ltrim(char *str); +void ares__str_rtrim(char *str); +void ares__str_trim(char *str); + unsigned char ares__tolower(unsigned char c); ares_bool_t ares__memeq_ci(const unsigned char *ptr, const unsigned char *val, size_t len); -#endif /* HEADER_CARES_STRDUP_H */ +ares_bool_t ares__isspace(int ch); +ares_bool_t ares__isprint(int ch); +ares_bool_t ares__is_hostnamech(int ch); + +ares_bool_t ares__is_hostname(const char *str); + + +#endif /* __ARES_STR_H */ diff --git a/deps/cares/src/lib/ares_strsplit.c b/deps/cares/src/lib/ares_strsplit.c index 5ec615c76482ed..395bf1ebb9a5ec 100644 --- a/deps/cares/src/lib/ares_strsplit.c +++ b/deps/cares/src/lib/ares_strsplit.c @@ -94,7 +94,7 @@ char **ares__strsplit(const char *in, const char *delms, size_t *num_elm) status = ares__buf_split( buf, (const unsigned char *)delms, ares_strlen(delms), - ARES_BUF_SPLIT_NO_DUPLICATES | ARES_BUF_SPLIT_CASE_INSENSITIVE, &llist); + ARES_BUF_SPLIT_NO_DUPLICATES | ARES_BUF_SPLIT_CASE_INSENSITIVE, 0, &llist); if (status != ARES_SUCCESS) { goto done; } diff --git a/deps/cares/src/lib/ares_sysconfig.c b/deps/cares/src/lib/ares_sysconfig.c index 825008b7b8a543..474534512af191 100644 --- a/deps/cares/src/lib/ares_sysconfig.c +++ b/deps/cares/src/lib/ares_sysconfig.c @@ -954,7 +954,7 @@ static ares_status_t ares__init_sysconfig_libresolv(ares_sysconfig_t *sysconfig) } } - if (res.ndots > 0) { + if (res.ndots >= 0) { sysconfig->ndots = (size_t)res.ndots; } if (res.retry > 0) { @@ -1059,6 +1059,10 @@ static ares_status_t ares_sysconfig_apply(ares_channel_t *channel, channel->rotate = sysconfig->rotate; } + if (sysconfig->usevc) { + channel->flags |= ARES_FLAG_USEVC; + } + return ARES_SUCCESS; } diff --git a/deps/cares/src/lib/ares_sysconfig_files.c b/deps/cares/src/lib/ares_sysconfig_files.c index 9802c7e54a5419..557888bc740a39 100644 --- a/deps/cares/src/lib/ares_sysconfig_files.c +++ b/deps/cares/src/lib/ares_sysconfig_files.c @@ -134,7 +134,7 @@ static ares_status_t parse_sort(ares__buf_t *buf, struct apattern *pat) ares__buf_tag(buf); /* Consume ip address */ - if (ares__buf_consume_charset(buf, ip_charset, sizeof(ip_charset)) == 0) { + if (ares__buf_consume_charset(buf, ip_charset, sizeof(ip_charset) - 1) == 0) { return ARES_EBADSTR; } @@ -162,8 +162,8 @@ static ares_status_t parse_sort(ares__buf_t *buf, struct apattern *pat) ares__buf_tag(buf); /* Consume mask */ - if (ares__buf_consume_charset(buf, ipv4_charset, sizeof(ipv4_charset)) == - 0) { + if (ares__buf_consume_charset(buf, ipv4_charset, + sizeof(ipv4_charset) - 1) == 0) { return ARES_EBADSTR; } @@ -241,7 +241,7 @@ ares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort, /* Split on space or semicolon */ status = ares__buf_split(buf, (const unsigned char *)" ;", 2, - ARES_BUF_SPLIT_NONE, &list); + ARES_BUF_SPLIT_NONE, 0, &list); if (status != ARES_SUCCESS) { goto done; } @@ -282,7 +282,8 @@ ares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort, return status; } -static ares_status_t config_search(ares_sysconfig_t *sysconfig, const char *str) +static ares_status_t config_search(ares_sysconfig_t *sysconfig, const char *str, + size_t max_domains) { if (sysconfig->domains && sysconfig->ndomains > 0) { /* if we already have some domains present, free them first */ @@ -296,410 +297,515 @@ static ares_status_t config_search(ares_sysconfig_t *sysconfig, const char *str) return ARES_ENOMEM; } + /* Truncate if necessary */ + if (max_domains && sysconfig->ndomains > max_domains) { + size_t i; + for (i = max_domains; i < sysconfig->ndomains; i++) { + ares_free(sysconfig->domains[i]); + sysconfig->domains[i] = NULL; + } + sysconfig->ndomains = max_domains; + } + return ARES_SUCCESS; } -static ares_status_t config_domain(ares_sysconfig_t *sysconfig, char *str) +static ares_status_t buf_fetch_string(ares__buf_t *buf, char *str, + size_t str_len) { - char *q; - - /* Set a single search domain. */ - q = str; - while (*q && !ISSPACE(*q)) { - q++; - } - *q = '\0'; + ares_status_t status; + ares__buf_tag(buf); + ares__buf_consume(buf, ares__buf_len(buf)); - return config_search(sysconfig, str); + status = ares__buf_tag_fetch_string(buf, str, str_len); + return status; } -static ares_status_t config_lookup(ares_sysconfig_t *sysconfig, const char *str, - const char *bindch, const char *altbindch, - const char *filech) +static ares_status_t config_lookup(ares_sysconfig_t *sysconfig, + ares__buf_t *buf, const char *separators) { - char lookups[3]; - char *l; - const char *p; - ares_bool_t found; - - if (altbindch == NULL) { - altbindch = bindch; + ares_status_t status; + char lookupstr[32]; + size_t lookupstr_cnt = 0; + ares__llist_t *lookups = NULL; + ares__llist_node_t *node; + size_t separators_len = ares_strlen(separators); + + status = ares__buf_split(buf, (const unsigned char *)separators, + separators_len, ARES_BUF_SPLIT_TRIM, 0, &lookups); + if (status != ARES_SUCCESS) { + goto done; } - /* Set the lookup order. Only the first letter of each work - * is relevant, and it has to be "b" for DNS or "f" for the - * host file. Ignore everything else. - */ - l = lookups; - p = str; - found = ARES_FALSE; - while (*p) { - if ((*p == *bindch || *p == *altbindch || *p == *filech) && - l < lookups + 2) { - if (*p == *bindch || *p == *altbindch) { - *l++ = 'b'; - } else { - *l++ = 'f'; - } - found = ARES_TRUE; + memset(lookupstr, 0, sizeof(lookupstr)); + + for (node = ares__llist_node_first(lookups); node != NULL; + node = ares__llist_node_next(node)) { + char value[128]; + char ch; + ares__buf_t *valbuf = ares__llist_node_val(node); + + status = buf_fetch_string(valbuf, value, sizeof(value)); + if (status != ARES_SUCCESS) { + continue; } - while (*p && !ISSPACE(*p) && (*p != ',')) { - p++; + + if (strcasecmp(value, "dns") == 0 || strcasecmp(value, "bind") == 0 || + strcasecmp(value, "resolv") == 0 || strcasecmp(value, "resolve") == 0) { + ch = 'b'; + } else if (strcasecmp(value, "files") == 0 || + strcasecmp(value, "file") == 0 || + strcasecmp(value, "local") == 0) { + ch = 'f'; + } else { + continue; } - while (*p && (ISSPACE(*p) || (*p == ','))) { - p++; + + /* Look for a duplicate and ignore */ + if (memchr(lookupstr, ch, lookupstr_cnt) == NULL) { + lookupstr[lookupstr_cnt++] = ch; } } - if (!found) { - return ARES_ENOTINITIALIZED; + + if (lookupstr_cnt) { + ares_free(sysconfig->lookups); + sysconfig->lookups = ares_strdup(lookupstr); + if (sysconfig->lookups == NULL) { + return ARES_ENOMEM; + } } - *l = '\0'; - ares_free(sysconfig->lookups); - sysconfig->lookups = ares_strdup(lookups); - if (sysconfig->lookups == NULL) { - return ARES_ENOMEM; + status = ARES_SUCCESS; + +done: + if (status != ARES_ENOMEM) { + status = ARES_SUCCESS; } - return ARES_SUCCESS; + ares__llist_destroy(lookups); + return status; } -static const char *try_option(const char *p, const char *q, const char *opt) +static ares_status_t process_option(ares_sysconfig_t *sysconfig, + ares__buf_t *option) { - size_t len = ares_strlen(opt); - return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL; + ares__llist_t *kv = NULL; + char key[32] = ""; + char val[32] = ""; + unsigned int valint = 0; + ares_status_t status; + + /* Split on : */ + status = ares__buf_split(option, (const unsigned char *)":", 1, + ARES_BUF_SPLIT_TRIM, 2, &kv); + if (status != ARES_SUCCESS) { + goto done; + } + + status = buf_fetch_string(ares__llist_first_val(kv), key, sizeof(key)); + if (status != ARES_SUCCESS) { + goto done; + } + if (ares__llist_len(kv) == 2) { + status = buf_fetch_string(ares__llist_last_val(kv), val, sizeof(val)); + if (status != ARES_SUCCESS) { + goto done; + } + valint = (unsigned int)strtoul(val, NULL, 10); + } + + if (strcmp(key, "ndots") == 0) { + sysconfig->ndots = valint; + } else if (strcmp(key, "retrans") == 0 || strcmp(key, "timeout") == 0) { + if (valint == 0) { + return ARES_EFORMERR; + } + sysconfig->timeout_ms = valint * 1000; + } else if (strcmp(key, "retry") == 0 || strcmp(key, "attempts") == 0) { + if (valint == 0) { + return ARES_EFORMERR; + } + sysconfig->tries = valint; + } else if (strcmp(key, "rotate") == 0) { + sysconfig->rotate = ARES_TRUE; + } else if (strcmp(key, "use-vc") == 0 || strcmp(key, "usevc") == 0) { + sysconfig->usevc = ARES_TRUE; + } + +done: + ares__llist_destroy(kv); + return status; } static ares_status_t set_options(ares_sysconfig_t *sysconfig, const char *str) { - const char *p; - const char *q; - const char *val; + ares__buf_t *buf = NULL; + ares__llist_t *options = NULL; + ares_status_t status; + ares__llist_node_t *node; - if (str == NULL) { - return ARES_SUCCESS; + buf = ares__buf_create_const((const unsigned char *)str, ares_strlen(str)); + if (buf == NULL) { + return ARES_ENOMEM; } - p = str; - while (*p) { - q = p; - while (*q && !ISSPACE(*q)) { - q++; - } - val = try_option(p, q, "ndots:"); - if (val) { - sysconfig->ndots = strtoul(val, NULL, 10); - } + status = ares__buf_split(buf, (const unsigned char *)" \t", 2, + ARES_BUF_SPLIT_TRIM, 0, &options); + if (status != ARES_SUCCESS) { + goto done; + } - // Outdated option. - val = try_option(p, q, "retrans:"); - if (val) { - sysconfig->timeout_ms = strtoul(val, NULL, 10); - } + for (node = ares__llist_node_first(options); node != NULL; + node = ares__llist_node_next(node)) { + ares__buf_t *valbuf = ares__llist_node_val(node); - val = try_option(p, q, "timeout:"); - if (val) { - sysconfig->timeout_ms = strtoul(val, NULL, 10) * 1000; + status = process_option(sysconfig, valbuf); + /* Out of memory is the only fatal condition */ + if (status == ARES_ENOMEM) { + goto done; } + } - // Outdated option. - val = try_option(p, q, "retry:"); - if (val) { - sysconfig->tries = strtoul(val, NULL, 10); - } + status = ARES_SUCCESS; - val = try_option(p, q, "attempts:"); - if (val) { - sysconfig->tries = strtoul(val, NULL, 10); - } +done: + ares__llist_destroy(options); + ares__buf_destroy(buf); + return status; +} - val = try_option(p, q, "rotate"); - if (val) { - sysconfig->rotate = ARES_TRUE; +ares_status_t ares__init_by_environment(ares_sysconfig_t *sysconfig) +{ + const char *localdomain; + const char *res_options; + ares_status_t status; + + localdomain = getenv("LOCALDOMAIN"); + if (localdomain) { + char *temp = ares_strdup(localdomain); + if (temp == NULL) { + return ARES_ENOMEM; } + status = config_search(sysconfig, temp, 1); + ares_free(temp); + if (status != ARES_SUCCESS) { + return status; + } + } - p = q; - while (ISSPACE(*p)) { - p++; + res_options = getenv("RES_OPTIONS"); + if (res_options) { + status = set_options(sysconfig, res_options); + if (status != ARES_SUCCESS) { + return status; } } return ARES_SUCCESS; } -static char *try_config(char *s, const char *opt, char scc) +/* Configuration Files: + * /etc/resolv.conf + * - All Unix-like systems + * - Comments start with ; or # + * - Lines have a keyword followed by a value that is interpreted specific + * to the keyword: + * - Keywords: + * - nameserver - IP address of nameserver with optional port (using a : + * prefix). If using an ipv6 address and specifying a port, the ipv6 + * address must be encapsulated in brackets. For link-local ipv6 + * addresses, the interface can also be specified with a % prefix. e.g.: + * "nameserver [fe80::1]:1234%iface" + * This keyword may be specified multiple times. + * - search - whitespace separated list of domains + * - domain - obsolete, same as search except only a single domain + * - lookup / hostresorder - local, bind, file, files + * - sortlist - whitespace separated ip-address/netmask pairs + * - options - options controlling resolver variables + * - ndots:n - set ndots option + * - timeout:n (retrans:n) - timeout per query attempt in seconds + * - attempts:n (retry:n) - number of times resolver will send query + * - rotate - round-robin selection of name servers + * - use-vc / usevc - force tcp + * /etc/nsswitch.conf + * - Modern Linux, FreeBSD, HP-UX, Solaris + * - Search order set via: + * "hosts: files dns mdns4_minimal mdns4" + * - files is /etc/hosts + * - dns is dns + * - mdns4_minimal does mdns only if ending in .local + * - mdns4 does not limit to domains ending in .local + * /etc/netsvc.conf + * - AIX + * - Search order set via: + * "hosts = local , bind" + * - bind is dns + * - local is /etc/hosts + * /etc/svc.conf + * - Tru64 + * - Same format as /etc/netsvc.conf + * /etc/host.conf + * - Early FreeBSD, Early Linux + * - Not worth supporting, format varied based on system, FreeBSD used + * just a line per search order, Linux used "order " and a comma + * delimited list of "bind" and "hosts" + */ + + +/* This function will only return ARES_SUCCESS or ARES_ENOMEM. Any other + * conditions are ignored. Users may mess up config files, but we want to + * process anything we can. */ +static ares_status_t parse_resolvconf_line(ares_sysconfig_t *sysconfig, + ares__buf_t *line) { - size_t len; - char *p; - char *q; + char option[32]; + char value[512]; + ares_status_t status = ARES_SUCCESS; - if (!s || !opt) { - /* no line or no option */ - return NULL; /* LCOV_EXCL_LINE */ + /* Ignore lines beginning with a comment */ + if (ares__buf_begins_with(line, (const unsigned char *)"#", 1) || + ares__buf_begins_with(line, (const unsigned char *)";", 1)) { + return ARES_SUCCESS; } - /* Hash '#' character is always used as primary comment char, additionally - a not-NUL secondary comment char will be considered when specified. */ + ares__buf_tag(line); - /* trim line comment */ - p = s; - if (scc) { - while (*p && (*p != '#') && (*p != scc)) { - p++; - } - } else { - while (*p && (*p != '#')) { - p++; - } + /* Shouldn't be possible, but if it happens, ignore the line. */ + if (ares__buf_consume_nonwhitespace(line) == 0) { + return ARES_SUCCESS; } - *p = '\0'; - /* trim trailing whitespace */ - q = p - 1; - while ((q >= s) && ISSPACE(*q)) { - q--; + status = ares__buf_tag_fetch_string(line, option, sizeof(option)); + if (status != ARES_SUCCESS) { + return ARES_SUCCESS; } - *++q = '\0'; - /* skip leading whitespace */ - p = s; - while (*p && ISSPACE(*p)) { - p++; - } + ares__buf_consume_whitespace(line, ARES_TRUE); - if (!*p) { - /* empty line */ - return NULL; + status = buf_fetch_string(line, value, sizeof(value)); + if (status != ARES_SUCCESS) { + return ARES_SUCCESS; } - if ((len = ares_strlen(opt)) == 0) { - /* empty option */ - return NULL; /* LCOV_EXCL_LINE */ + ares__str_trim(value); + if (*value == 0) { + return ARES_SUCCESS; } - if (strncmp(p, opt, len) != 0) { - /* line and option do not match */ - return NULL; + /* At this point we have a string option and a string value, both trimmed + * of leading and trailing whitespace. Lets try to evaluate them */ + if (strcmp(option, "domain") == 0) { + /* Domain is legacy, don't overwrite an existing config set by search */ + if (sysconfig->domains == NULL) { + status = config_search(sysconfig, value, 1); + } + } else if (strcmp(option, "lookup") == 0 || + strcmp(option, "hostresorder") == 0) { + ares__buf_tag_rollback(line); + status = config_lookup(sysconfig, line, " \t"); + } else if (strcmp(option, "search") == 0) { + status = config_search(sysconfig, value, 0); + } else if (strcmp(option, "nameserver") == 0) { + status = + ares__sconfig_append_fromstr(&sysconfig->sconfig, value, ARES_TRUE); + } else if (strcmp(option, "sortlist") == 0) { + /* Ignore all failures except ENOMEM. If the sysadmin set a bad + * sortlist, just ignore the sortlist, don't cause an inoperable + * channel */ + status = + ares__parse_sortlist(&sysconfig->sortlist, &sysconfig->nsortlist, value); + if (status != ARES_ENOMEM) { + status = ARES_SUCCESS; + } + } else if (strcmp(option, "options") == 0) { + status = set_options(sysconfig, value); } - /* skip over given option name */ - p += len; + return status; +} + +/* This function will only return ARES_SUCCESS or ARES_ENOMEM. Any other + * conditions are ignored. Users may mess up config files, but we want to + * process anything we can. */ +static ares_status_t parse_nsswitch_line(ares_sysconfig_t *sysconfig, + ares__buf_t *line) +{ + char option[32]; + ares__buf_t *buf; + ares_status_t status = ARES_SUCCESS; + ares__llist_t *sects = NULL; - if (!*p) { - /* no option value */ - return NULL; /* LCOV_EXCL_LINE */ + /* Ignore lines beginning with a comment */ + if (ares__buf_begins_with(line, (const unsigned char *)"#", 1)) { + return ARES_SUCCESS; } - if ((opt[len - 1] != ':') && (opt[len - 1] != '=') && !ISSPACE(*p)) { - /* whitespace between option name and value is mandatory - for given option names which do not end with ':' or '=' */ - return NULL; + /* database : values (space delimited) */ + status = ares__buf_split(line, (const unsigned char *)":", 1, + ARES_BUF_SPLIT_TRIM, 2, §s); + + if (status != ARES_SUCCESS || ares__llist_len(sects) != 2) { + goto done; } - /* skip over whitespace */ - while (*p && ISSPACE(*p)) { - p++; + buf = ares__llist_first_val(sects); + status = buf_fetch_string(buf, option, sizeof(option)); + if (status != ARES_SUCCESS) { + goto done; } - if (!*p) { - /* no option value */ - return NULL; + /* Only support "hosts:" */ + if (strcmp(option, "hosts") != 0) { + goto done; } - /* return pointer to option value */ - return p; + /* Values are space separated */ + buf = ares__llist_last_val(sects); + status = config_lookup(sysconfig, buf, " \t"); + +done: + ares__llist_destroy(sects); + if (status != ARES_ENOMEM) { + status = ARES_SUCCESS; + } + return status; } -ares_status_t ares__init_by_environment(ares_sysconfig_t *sysconfig) +/* This function will only return ARES_SUCCESS or ARES_ENOMEM. Any other + * conditions are ignored. Users may mess up config files, but we want to + * process anything we can. */ +static ares_status_t parse_svcconf_line(ares_sysconfig_t *sysconfig, + ares__buf_t *line) { - const char *localdomain; - const char *res_options; - ares_status_t status; + char option[32]; + ares__buf_t *buf; + ares_status_t status = ARES_SUCCESS; + ares__llist_t *sects = NULL; - localdomain = getenv("LOCALDOMAIN"); - if (localdomain) { - char *temp = ares_strdup(localdomain); - if (temp == NULL) { - return ARES_ENOMEM; - } - status = config_domain(sysconfig, temp); - ares_free(temp); - if (status != ARES_SUCCESS) { - return status; - } + /* Ignore lines beginning with a comment */ + if (ares__buf_begins_with(line, (const unsigned char *)"#", 1)) { + return ARES_SUCCESS; } - res_options = getenv("RES_OPTIONS"); - if (res_options) { - status = set_options(sysconfig, res_options); - if (status != ARES_SUCCESS) { - return status; - } + /* database = values (comma delimited)*/ + status = ares__buf_split(line, (const unsigned char *)"=", 1, + ARES_BUF_SPLIT_TRIM, 2, §s); + + if (status != ARES_SUCCESS || ares__llist_len(sects) != 2) { + goto done; } - return ARES_SUCCESS; + buf = ares__llist_first_val(sects); + status = buf_fetch_string(buf, option, sizeof(option)); + if (status != ARES_SUCCESS) { + goto done; + } + + /* Only support "hosts=" */ + if (strcmp(option, "hosts") != 0) { + goto done; + } + + /* Values are comma separated */ + buf = ares__llist_last_val(sects); + status = config_lookup(sysconfig, buf, ","); + +done: + ares__llist_destroy(sects); + if (status != ARES_ENOMEM) { + status = ARES_SUCCESS; + } + return status; } -ares_status_t ares__init_sysconfig_files(const ares_channel_t *channel, - ares_sysconfig_t *sysconfig) +typedef ares_status_t (*line_callback_t)(ares_sysconfig_t *sysconfig, + ares__buf_t *line); + +/* Should only return: + * ARES_ENOTFOUND - file not found + * ARES_EFILE - error reading file (perms) + * ARES_ENOMEM - out of memory + * ARES_SUCCESS - file processed, doesn't necessarily mean it was a good + * file, but we're not erroring out if we can't parse + * something (or anything at all) */ +static ares_status_t process_config_lines(const char *filename, + ares_sysconfig_t *sysconfig, + line_callback_t cb) { - char *p; - FILE *fp = NULL; - char *line = NULL; - size_t linesize = 0; - int error; - const char *resolvconf_path; - ares_status_t status = ARES_SUCCESS; + ares_status_t status = ARES_SUCCESS; + ares__llist_node_t *node; + ares__llist_t *lines = NULL; + ares__buf_t *buf = NULL; - /* Support path for resolvconf filename set by ares_init_options */ - if (channel->resolvconf_path) { - resolvconf_path = channel->resolvconf_path; - } else { - resolvconf_path = PATH_RESOLV_CONF; - } - - fp = fopen(resolvconf_path, "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { - if ((p = try_config(line, "domain", ';'))) { - status = config_domain(sysconfig, p); - } else if ((p = try_config(line, "lookup", ';'))) { - status = config_lookup(sysconfig, p, "bind", NULL, "file"); - } else if ((p = try_config(line, "search", ';'))) { - status = config_search(sysconfig, p); - } else if ((p = try_config(line, "nameserver", ';'))) { - status = - ares__sconfig_append_fromstr(&sysconfig->sconfig, p, ARES_TRUE); - } else if ((p = try_config(line, "sortlist", ';'))) { - /* Ignore all failures except ENOMEM. If the sysadmin set a bad - * sortlist, just ignore the sortlist, don't cause an inoperable - * channel */ - status = - ares__parse_sortlist(&sysconfig->sortlist, &sysconfig->nsortlist, p); - if (status != ARES_ENOMEM) { - status = ARES_SUCCESS; - } - } else if ((p = try_config(line, "options", ';'))) { - status = set_options(sysconfig, p); - } else { - status = ARES_SUCCESS; - } - if (status != ARES_SUCCESS) { - fclose(fp); - goto done; - } - } - fclose(fp); + buf = ares__buf_create(); + if (buf == NULL) { + status = ARES_ENOMEM; + goto done; + } - if (status != ARES_EOF) { - goto done; - } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF)); - status = ARES_EFILE; - goto done; - } + status = ares__buf_load_file(filename, buf); + if (status != ARES_SUCCESS) { + goto done; } + status = ares__buf_split(buf, (const unsigned char *)"\n", 1, + ARES_BUF_SPLIT_TRIM, 0, &lines); + if (status != ARES_SUCCESS) { + goto done; + } - /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */ - fp = fopen("/etc/nsswitch.conf", "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { - if ((p = try_config(line, "hosts:", '\0'))) { - (void)config_lookup(sysconfig, p, "dns", "resolve", "files"); - } - } - fclose(fp); - if (status != ARES_EOF) { + for (node = ares__llist_node_first(lines); node != NULL; + node = ares__llist_node_next(node)) { + ares__buf_t *line = ares__llist_node_val(node); + + status = cb(sysconfig, line); + if (status != ARES_SUCCESS) { goto done; } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF( - fprintf(stderr, "Error opening file: %s\n", "/etc/nsswitch.conf")); - break; - } - /* ignore error, maybe we will get luck in next if clause */ } +done: + ares__buf_destroy(buf); + ares__llist_destroy(lines); - /* Linux / GNU libc 2.x and possibly others have host.conf */ - fp = fopen("/etc/host.conf", "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { - if ((p = try_config(line, "order", '\0'))) { - /* ignore errors */ - (void)config_lookup(sysconfig, p, "bind", NULL, "hosts"); - } - } - fclose(fp); - if (status != ARES_EOF) { - goto done; - } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/host.conf")); - break; - } + return status; +} + +ares_status_t ares__init_sysconfig_files(const ares_channel_t *channel, + ares_sysconfig_t *sysconfig) +{ + ares_status_t status = ARES_SUCCESS; + + /* Resolv.conf */ + status = process_config_lines((channel->resolvconf_path != NULL) + ? channel->resolvconf_path + : PATH_RESOLV_CONF, + sysconfig, parse_resolvconf_line); + if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) { + goto done; + } - /* ignore error, maybe we will get luck in next if clause */ + /* Nsswitch.conf */ + status = + process_config_lines("/etc/nsswitch.conf", sysconfig, parse_nsswitch_line); + if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) { + goto done; } + /* netsvc.conf */ + status = + process_config_lines("/etc/netsvc.conf", sysconfig, parse_svcconf_line); + if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) { + goto done; + } - /* Tru64 uses /etc/svc.conf */ - fp = fopen("/etc/svc.conf", "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { - if ((p = try_config(line, "hosts=", '\0'))) { - /* ignore errors */ - (void)config_lookup(sysconfig, p, "bind", NULL, "local"); - } - } - fclose(fp); - if (status != ARES_EOF) { - goto done; - } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf")); - break; - } - /* ignore error */ + /* svc.conf */ + status = process_config_lines("/etc/svc.conf", sysconfig, parse_svcconf_line); + if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) { + goto done; } status = ARES_SUCCESS; done: - ares_free(line); - return status; } diff --git a/deps/cares/src/lib/ares_update_servers.c b/deps/cares/src/lib/ares_update_servers.c index dd24fbfdd4675c..fce791476327c3 100644 --- a/deps/cares/src/lib/ares_update_servers.c +++ b/deps/cares/src/lib/ares_update_servers.c @@ -266,8 +266,8 @@ static ares_status_t parse_nameserver(ares__buf_t *buf, ares_sconfig_t *sconfig) } else { /* IPv6 */ const unsigned char ipv6_charset[] = "ABCDEFabcdef0123456789.:"; - if (ares__buf_consume_charset(buf, ipv6_charset, sizeof(ipv6_charset)) == - 0) { + if (ares__buf_consume_charset(buf, ipv6_charset, + sizeof(ipv6_charset) - 1) == 0) { return ARES_EBADSTR; } } @@ -318,8 +318,8 @@ static ares_status_t parse_nameserver(ares__buf_t *buf, ares_sconfig_t *sconfig) ares__buf_tag(buf); - if (ares__buf_consume_charset(buf, iface_charset, sizeof(iface_charset)) == - 0) { + if (ares__buf_consume_charset(buf, iface_charset, + sizeof(iface_charset) - 1) == 0) { return ARES_EBADSTR; } @@ -463,7 +463,7 @@ ares_status_t ares__sconfig_append_fromstr(ares__llist_t **sconfig, } status = ares__buf_split(buf, (const unsigned char *)" ,", 2, - ARES_BUF_SPLIT_NONE, &list); + ARES_BUF_SPLIT_NONE, 0, &list); if (status != ARES_SUCCESS) { goto done; } @@ -1080,7 +1080,7 @@ static ares_status_t set_servers_csv(ares_channel_t *channel, const char *_csv) if (ares_strlen(_csv) == 0) { /* blank all servers */ - return (ares_status_t)ares_set_servers_ports(channel, NULL); + return ares__servers_update(channel, NULL, ARES_TRUE); } status = ares__sconfig_append_fromstr(&slist, _csv, ARES_FALSE); diff --git a/deps/cares/src/lib/setup_once.h b/deps/cares/src/lib/setup_once.h index 8341b348e7a9e0..a6168c9aed5365 100644 --- a/deps/cares/src/lib/setup_once.h +++ b/deps/cares/src/lib/setup_once.h @@ -274,7 +274,7 @@ Error Missing_definition_of_macro_sread #define ISPRINT(x) (isprint((int)((unsigned char)x))) #define ISUPPER(x) (isupper((int)((unsigned char)x))) #define ISLOWER(x) (islower((int)((unsigned char)x))) -#define ISASCII(x) (isascii((int)((unsigned char)x))) +#define ISASCII(x) (((unsigned char)x) <= 127 ? 1 : 0) #define ISBLANK(x) \ (int)((((unsigned char)x) == ' ') || (((unsigned char)x) == '\t')) diff --git a/deps/cares/src/tools/CMakeLists.txt b/deps/cares/src/tools/CMakeLists.txt index 13aefe135e9105..fb795a91741aaf 100644 --- a/deps/cares/src/tools/CMakeLists.txt +++ b/deps/cares/src/tools/CMakeLists.txt @@ -19,7 +19,7 @@ IF (CARES_BUILD_TOOLS) C_STANDARD 90 ) - TARGET_COMPILE_DEFINITIONS (ahost PRIVATE HAVE_CONFIG_H=1) + TARGET_COMPILE_DEFINITIONS (ahost PRIVATE HAVE_CONFIG_H=1 CARES_NO_DEPRECATED) TARGET_LINK_LIBRARIES (ahost PRIVATE ${PROJECT_NAME}) IF (CARES_INSTALL) INSTALL (TARGETS ahost COMPONENT Tools ${TARGETS_INST_DEST}) @@ -40,7 +40,7 @@ IF (CARES_BUILD_TOOLS) C_STANDARD 90 ) - TARGET_COMPILE_DEFINITIONS (adig PRIVATE HAVE_CONFIG_H=1) + TARGET_COMPILE_DEFINITIONS (adig PRIVATE HAVE_CONFIG_H=1 CARES_NO_DEPRECATED) TARGET_LINK_LIBRARIES (adig PRIVATE ${PROJECT_NAME}) IF (CARES_INSTALL) INSTALL (TARGETS adig COMPONENT Tools ${TARGETS_INST_DEST}) diff --git a/deps/cares/src/tools/Makefile.am b/deps/cares/src/tools/Makefile.am index 729658d79a76da..ba7a672f89faf5 100644 --- a/deps/cares/src/tools/Makefile.am +++ b/deps/cares/src/tools/Makefile.am @@ -15,7 +15,8 @@ noinst_PROGRAMS =$(PROGS) AM_CPPFLAGS += -I$(top_builddir)/include \ -I$(top_builddir)/src/lib \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/src/lib + -I$(top_srcdir)/src/lib \ + -DCARES_NO_DEPRECATED include Makefile.inc diff --git a/deps/cares/src/tools/Makefile.in b/deps/cares/src/tools/Makefile.in index f0602fe172fdbb..0b7a310baaab5d 100644 --- a/deps/cares/src/tools/Makefile.in +++ b/deps/cares/src/tools/Makefile.in @@ -228,7 +228,7 @@ AM_CFLAGS = @AM_CFLAGS@ # might possibly already be installed in the system. AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_builddir)/include \ -I$(top_builddir)/src/lib -I$(top_srcdir)/include \ - -I$(top_srcdir)/src/lib + -I$(top_srcdir)/src/lib -DCARES_NO_DEPRECATED AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ @@ -310,6 +310,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ diff --git a/deps/corepack/CHANGELOG.md b/deps/corepack/CHANGELOG.md index 439f6fd3b8e968..f5cef27cc047f9 100644 --- a/deps/corepack/CHANGELOG.md +++ b/deps/corepack/CHANGELOG.md @@ -1,5 +1,56 @@ # Changelog +## [0.28.0](https://github.com/nodejs/corepack/compare/v0.27.0...v0.28.0) (2024-04-20) + + +### ⚠ BREAKING CHANGES + +* call `executePackageManagerRequest` directly ([#430](https://github.com/nodejs/corepack/issues/430)) + +### Bug Fixes + +* call `executePackageManagerRequest` directly ([#430](https://github.com/nodejs/corepack/issues/430)) ([0f9b748](https://github.com/nodejs/corepack/commit/0f9b74864048d5dc150a63cc582966af0c5f363f)) + +## [0.27.0](https://github.com/nodejs/corepack/compare/v0.26.0...v0.27.0) (2024-04-19) + + +### ⚠ BREAKING CHANGES + +* attempting to download a version from the npm registry (or a mirror) that was published using the now deprecated PGP signature without providing a hash will trigger an error. Users can disable the signature verification using a environment variable. + +### Features + +* separate read and write operations on lastKnownGood.json ([#446](https://github.com/nodejs/corepack/issues/446)) ([c449adc](https://github.com/nodejs/corepack/commit/c449adc81822a604ee8f00ae2b53fc411535f96d)) +* update package manager versions ([#425](https://github.com/nodejs/corepack/issues/425)) ([1423190](https://github.com/nodejs/corepack/commit/142319056424b1e0da2bdbe801c52c5910023707)) +* update package manager versions ([#462](https://github.com/nodejs/corepack/issues/462)) ([56816c2](https://github.com/nodejs/corepack/commit/56816c2b7ebc9926f07048b0ec4ff6025bb4e293)) +* verify integrity signature when downloading from npm registry ([#432](https://github.com/nodejs/corepack/issues/432)) ([e561dd0](https://github.com/nodejs/corepack/commit/e561dd00bbacc5bc15a492fc36574fa0e37bff7b)) + + +### Bug Fixes + +* add path to `package.json` in error message ([#456](https://github.com/nodejs/corepack/issues/456)) ([32a93ea](https://github.com/nodejs/corepack/commit/32a93ea4f51eb7db7dc95a16c5719695edf4b53e)) +* correctly set `Dispatcher` prototype for `ProxyAgent` ([#451](https://github.com/nodejs/corepack/issues/451)) ([73d9a1e](https://github.com/nodejs/corepack/commit/73d9a1e2d2f84906bf01952f1dca8adab576b7bf)) +* download fewer metadata from npm registry ([#436](https://github.com/nodejs/corepack/issues/436)) ([082fabf](https://github.com/nodejs/corepack/commit/082fabf8b15658e69e4fb62bb854fe9aace78b70)) +* hash check when downloading Yarn Berry from npm ([#439](https://github.com/nodejs/corepack/issues/439)) ([4672162](https://github.com/nodejs/corepack/commit/467216281e1719a739d0eeea370b335adfb37b8d)) +* Incorrect authorization prefix for basic auth, and undocumented env var ([#454](https://github.com/nodejs/corepack/issues/454)) ([2d63536](https://github.com/nodejs/corepack/commit/2d63536413971d43f570deb035845aa0bd5202f0)) +* re-add support for custom registries with auth ([#397](https://github.com/nodejs/corepack/issues/397)) ([d267753](https://github.com/nodejs/corepack/commit/d2677538cdb613fcab6d2a45bb07f349bdc65c2b)) + +## [0.26.0](https://github.com/nodejs/corepack/compare/v0.25.2...v0.26.0) (2024-03-08) + + +### Features + +* Pins the package manager as it's used for the first time ([#413](https://github.com/nodejs/corepack/issues/413)) ([8b6c6d4](https://github.com/nodejs/corepack/commit/8b6c6d4b2b7a9d61ae6c33c07e12354bd5afc2ba)) +* update package manager versions ([#415](https://github.com/nodejs/corepack/issues/415)) ([e8edba7](https://github.com/nodejs/corepack/commit/e8edba771bca6fb10c855c04eee8102ffa792d58)) + + +### Bug Fixes + +* group the download prompt together ([#391](https://github.com/nodejs/corepack/issues/391)) ([00506b2](https://github.com/nodejs/corepack/commit/00506b2a15dd87ec03240578077a35b7980e00c1)) +* ignore `EROFS` errors ([#421](https://github.com/nodejs/corepack/issues/421)) ([b7ec137](https://github.com/nodejs/corepack/commit/b7ec137210efd35c3461321b6434e3e13a87d42f)) +* improve support for `COREPACK_NPM_REGISTRY` with Yarn Berry ([#396](https://github.com/nodejs/corepack/issues/396)) ([47be27c](https://github.com/nodejs/corepack/commit/47be27c9db988e10f651d23b3f53bcf55318a894)) +* Windows malicious file analysis waiting problem ([#398](https://github.com/nodejs/corepack/issues/398)) ([295a1cd](https://github.com/nodejs/corepack/commit/295a1cdb9cbbbce8434e8d82b96eb63e57c46c1a)) + ## [0.25.2](https://github.com/nodejs/corepack/compare/v0.25.1...v0.25.2) (2024-02-21) diff --git a/deps/corepack/README.md b/deps/corepack/README.md index 2f5819d913eb37..42dc8c19085e88 100644 --- a/deps/corepack/README.md +++ b/deps/corepack/README.md @@ -1,5 +1,7 @@ # corepack +[![Join us on OpenJS slack (channel #nodejs-corepack)](https://img.shields.io/badge/OpenJS%20Slack-%23nodejs--corepack-blue)](https://slack-invite.openjsf.org/) + Corepack is a zero-runtime-dependency Node.js script that acts as a bridge between Node.js projects and the package managers they are intended to be used with during development. In practical terms, **Corepack lets you use Yarn, npm, @@ -54,7 +56,7 @@ projects, `pnpm install` in pnpm projects, and `npm` in npm projects. Corepack will catch these calls, and depending on the situation: - **If the local project is configured for the package manager you're using**, - Corepack will silently download and cache the latest compatible version. + Corepack will download and cache the latest compatible version. - **If the local project is configured for a different package manager**, Corepack will request you to run the command again using the right package @@ -235,6 +237,12 @@ same major line. Should you need to upgrade to a new major, use an explicit package manager, and to not update the Last Known Good version when it downloads a new version of the same major line. +- `COREPACK_ENABLE_AUTO_PIN` can be set to `0` to prevent Corepack from + updating the `packageManager` field when it detects that the local package + doesn't list it. In general we recommend to always list a `packageManager` + field (which you can easily set through `corepack use [name]@[version]`), as + it ensures that your project installs are always deterministic. + - `COREPACK_ENABLE_DOWNLOAD_PROMPT` can be set to `0` to prevent Corepack showing the URL when it needs to download software, or can be set to `1` to have the URL shown. By default, when Corepack is called @@ -288,6 +296,9 @@ same major line. Should you need to upgrade to a new major, use an explicit - `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` are supported through [`node-proxy-agent`](https://github.com/TooTallNate/node-proxy-agent). +- `COREPACK_INTEGRITY_KEYS` can be set to an empty string to instruct Corepack + to skip integrity checks, or a JSON string containing custom keys. + ## Troubleshooting ### Networking @@ -303,10 +314,6 @@ There are a wide variety of networking issues that can occur while running `core See [`CONTRIBUTING.md`](./CONTRIBUTING.md). -## Design - -See [`DESIGN.md`](/DESIGN.md). - ## License (MIT) See [`LICENSE.md`](./LICENSE.md). diff --git a/deps/corepack/dist/lib/corepack.cjs b/deps/corepack/dist/lib/corepack.cjs index 3d8e819e7997e7..f81b561ce54d87 100644 --- a/deps/corepack/dist/lib/corepack.cjs +++ b/deps/corepack/dist/lib/corepack.cjs @@ -4316,78 +4316,9 @@ var require_proxy_from_env = __commonJS({ } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/symbols.js -var require_symbols = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/symbols.js"(exports, module2) { - module2.exports = { - kClose: Symbol("close"), - kDestroy: Symbol("destroy"), - kDispatch: Symbol("dispatch"), - kUrl: Symbol("url"), - kWriting: Symbol("writing"), - kResuming: Symbol("resuming"), - kQueue: Symbol("queue"), - kConnect: Symbol("connect"), - kConnecting: Symbol("connecting"), - kHeadersList: Symbol("headers list"), - kKeepAliveDefaultTimeout: Symbol("default keep alive timeout"), - kKeepAliveMaxTimeout: Symbol("max keep alive timeout"), - kKeepAliveTimeoutThreshold: Symbol("keep alive timeout threshold"), - kKeepAliveTimeoutValue: Symbol("keep alive timeout"), - kKeepAlive: Symbol("keep alive"), - kHeadersTimeout: Symbol("headers timeout"), - kBodyTimeout: Symbol("body timeout"), - kServerName: Symbol("server name"), - kLocalAddress: Symbol("local address"), - kHost: Symbol("host"), - kNoRef: Symbol("no ref"), - kBodyUsed: Symbol("used"), - kRunning: Symbol("running"), - kBlocking: Symbol("blocking"), - kPending: Symbol("pending"), - kSize: Symbol("size"), - kBusy: Symbol("busy"), - kQueued: Symbol("queued"), - kFree: Symbol("free"), - kConnected: Symbol("connected"), - kClosed: Symbol("closed"), - kNeedDrain: Symbol("need drain"), - kReset: Symbol("reset"), - kDestroyed: Symbol.for("nodejs.stream.destroyed"), - kMaxHeadersSize: Symbol("max headers size"), - kRunningIdx: Symbol("running index"), - kPendingIdx: Symbol("pending index"), - kError: Symbol("error"), - kClients: Symbol("clients"), - kClient: Symbol("client"), - kParser: Symbol("parser"), - kOnDestroyed: Symbol("destroy callbacks"), - kPipelining: Symbol("pipelining"), - kSocket: Symbol("socket"), - kHostHeader: Symbol("host header"), - kConnector: Symbol("connector"), - kStrictContentLength: Symbol("strict content length"), - kMaxRedirections: Symbol("maxRedirections"), - kMaxRequests: Symbol("maxRequestsPerClient"), - kProxy: Symbol("proxy agent options"), - kCounter: Symbol("socket request counter"), - kInterceptors: Symbol("dispatch interceptors"), - kMaxResponseSize: Symbol("max response size"), - kHTTP2Session: Symbol("http2Session"), - kHTTP2SessionState: Symbol("http2Session state"), - kHTTP2BuildRequest: Symbol("http2 build request"), - kHTTP1BuildRequest: Symbol("http1 build request"), - kHTTP2CopyHeaders: Symbol("http2 copy headers"), - kHTTPConnVersion: Symbol("http connection version"), - kRetryHandlerDefaultRetry: Symbol("retry agent default retry"), - kConstruct: Symbol("constructable") - }; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/errors.js +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/errors.js var require_errors = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/errors.js"(exports, module2) { + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/errors.js"(exports, module2) { "use strict"; var UndiciError = class extends Error { constructor(message) { @@ -4563,6 +4494,15 @@ var require_errors = __commonJS({ this.headers = headers; } }; + var SecureProxyConnectionError = class extends UndiciError { + constructor(cause, message, options) { + super(message, { cause, ...options ?? {} }); + this.name = "SecureProxyConnectionError"; + this.message = message || "Secure Proxy Connection failed"; + this.code = "UND_ERR_PRX_TLS"; + this.cause = cause; + } + }; module2.exports = { AbortError, HTTPParserError, @@ -4584,4716 +4524,4094 @@ var require_errors = __commonJS({ ResponseContentLengthMismatchError, BalancedPoolMissingUpstreamError, ResponseExceededMaxSizeError, - RequestRetryError + RequestRetryError, + SecureProxyConnectionError }; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/dispatcher.js -var require_dispatcher = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/dispatcher.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/symbols.js +var require_symbols = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/symbols.js"(exports, module2) { + module2.exports = { + kClose: Symbol("close"), + kDestroy: Symbol("destroy"), + kDispatch: Symbol("dispatch"), + kUrl: Symbol("url"), + kWriting: Symbol("writing"), + kResuming: Symbol("resuming"), + kQueue: Symbol("queue"), + kConnect: Symbol("connect"), + kConnecting: Symbol("connecting"), + kHeadersList: Symbol("headers list"), + kKeepAliveDefaultTimeout: Symbol("default keep alive timeout"), + kKeepAliveMaxTimeout: Symbol("max keep alive timeout"), + kKeepAliveTimeoutThreshold: Symbol("keep alive timeout threshold"), + kKeepAliveTimeoutValue: Symbol("keep alive timeout"), + kKeepAlive: Symbol("keep alive"), + kHeadersTimeout: Symbol("headers timeout"), + kBodyTimeout: Symbol("body timeout"), + kServerName: Symbol("server name"), + kLocalAddress: Symbol("local address"), + kHost: Symbol("host"), + kNoRef: Symbol("no ref"), + kBodyUsed: Symbol("used"), + kRunning: Symbol("running"), + kBlocking: Symbol("blocking"), + kPending: Symbol("pending"), + kSize: Symbol("size"), + kBusy: Symbol("busy"), + kQueued: Symbol("queued"), + kFree: Symbol("free"), + kConnected: Symbol("connected"), + kClosed: Symbol("closed"), + kNeedDrain: Symbol("need drain"), + kReset: Symbol("reset"), + kDestroyed: Symbol.for("nodejs.stream.destroyed"), + kResume: Symbol("resume"), + kOnError: Symbol("on error"), + kMaxHeadersSize: Symbol("max headers size"), + kRunningIdx: Symbol("running index"), + kPendingIdx: Symbol("pending index"), + kError: Symbol("error"), + kClients: Symbol("clients"), + kClient: Symbol("client"), + kParser: Symbol("parser"), + kOnDestroyed: Symbol("destroy callbacks"), + kPipelining: Symbol("pipelining"), + kSocket: Symbol("socket"), + kHostHeader: Symbol("host header"), + kConnector: Symbol("connector"), + kStrictContentLength: Symbol("strict content length"), + kMaxRedirections: Symbol("maxRedirections"), + kMaxRequests: Symbol("maxRequestsPerClient"), + kProxy: Symbol("proxy agent options"), + kCounter: Symbol("socket request counter"), + kInterceptors: Symbol("dispatch interceptors"), + kMaxResponseSize: Symbol("max response size"), + kHTTP2Session: Symbol("http2Session"), + kHTTP2SessionState: Symbol("http2Session state"), + kRetryHandlerDefaultRetry: Symbol("retry agent default retry"), + kConstruct: Symbol("constructable"), + kListeners: Symbol("listeners"), + kHTTPContext: Symbol("http context"), + kMaxConcurrentStreams: Symbol("max concurrent streams") + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/constants.js +var require_constants2 = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/constants.js"(exports, module2) { "use strict"; - var EventEmitter = require("node:events"); - var Dispatcher = class extends EventEmitter { - dispatch() { - throw new Error("not implemented"); - } - close() { - throw new Error("not implemented"); - } - destroy() { - throw new Error("not implemented"); - } + var headerNameLowerCasedRecord = {}; + var wellknownHeaderNames = [ + "Accept", + "Accept-Encoding", + "Accept-Language", + "Accept-Ranges", + "Access-Control-Allow-Credentials", + "Access-Control-Allow-Headers", + "Access-Control-Allow-Methods", + "Access-Control-Allow-Origin", + "Access-Control-Expose-Headers", + "Access-Control-Max-Age", + "Access-Control-Request-Headers", + "Access-Control-Request-Method", + "Age", + "Allow", + "Alt-Svc", + "Alt-Used", + "Authorization", + "Cache-Control", + "Clear-Site-Data", + "Connection", + "Content-Disposition", + "Content-Encoding", + "Content-Language", + "Content-Length", + "Content-Location", + "Content-Range", + "Content-Security-Policy", + "Content-Security-Policy-Report-Only", + "Content-Type", + "Cookie", + "Cross-Origin-Embedder-Policy", + "Cross-Origin-Opener-Policy", + "Cross-Origin-Resource-Policy", + "Date", + "Device-Memory", + "Downlink", + "ECT", + "ETag", + "Expect", + "Expect-CT", + "Expires", + "Forwarded", + "From", + "Host", + "If-Match", + "If-Modified-Since", + "If-None-Match", + "If-Range", + "If-Unmodified-Since", + "Keep-Alive", + "Last-Modified", + "Link", + "Location", + "Max-Forwards", + "Origin", + "Permissions-Policy", + "Pragma", + "Proxy-Authenticate", + "Proxy-Authorization", + "RTT", + "Range", + "Referer", + "Referrer-Policy", + "Refresh", + "Retry-After", + "Sec-WebSocket-Accept", + "Sec-WebSocket-Extensions", + "Sec-WebSocket-Key", + "Sec-WebSocket-Protocol", + "Sec-WebSocket-Version", + "Server", + "Server-Timing", + "Service-Worker-Allowed", + "Service-Worker-Navigation-Preload", + "Set-Cookie", + "SourceMap", + "Strict-Transport-Security", + "Supports-Loading-Mode", + "TE", + "Timing-Allow-Origin", + "Trailer", + "Transfer-Encoding", + "Upgrade", + "Upgrade-Insecure-Requests", + "User-Agent", + "Vary", + "Via", + "WWW-Authenticate", + "X-Content-Type-Options", + "X-DNS-Prefetch-Control", + "X-Frame-Options", + "X-Permitted-Cross-Domain-Policies", + "X-Powered-By", + "X-Requested-With", + "X-XSS-Protection" + ]; + for (let i = 0; i < wellknownHeaderNames.length; ++i) { + const key = wellknownHeaderNames[i]; + const lowerCasedKey = key.toLowerCase(); + headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = lowerCasedKey; + } + Object.setPrototypeOf(headerNameLowerCasedRecord, null); + module2.exports = { + wellknownHeaderNames, + headerNameLowerCasedRecord }; - module2.exports = Dispatcher; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/dispatcher-base.js -var require_dispatcher_base = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/dispatcher-base.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/tree.js +var require_tree = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/tree.js"(exports, module2) { "use strict"; - var Dispatcher = require_dispatcher(); var { - ClientDestroyedError, - ClientClosedError, - InvalidArgumentError - } = require_errors(); - var { kDestroy, kClose, kDispatch, kInterceptors } = require_symbols(); - var kDestroyed = Symbol("destroyed"); - var kClosed = Symbol("closed"); - var kOnDestroyed = Symbol("onDestroyed"); - var kOnClosed = Symbol("onClosed"); - var kInterceptedDispatch = Symbol("Intercepted Dispatch"); - var DispatcherBase = class extends Dispatcher { - constructor() { - super(); - this[kDestroyed] = false; - this[kOnDestroyed] = null; - this[kClosed] = false; - this[kOnClosed] = []; - } - get destroyed() { - return this[kDestroyed]; - } - get closed() { - return this[kClosed]; - } - get interceptors() { - return this[kInterceptors]; - } - set interceptors(newInterceptors) { - if (newInterceptors) { - for (let i = newInterceptors.length - 1; i >= 0; i--) { - const interceptor = this[kInterceptors][i]; - if (typeof interceptor !== "function") { - throw new InvalidArgumentError("interceptor must be an function"); - } - } + wellknownHeaderNames, + headerNameLowerCasedRecord + } = require_constants2(); + var TstNode = class _TstNode { + /** @type {any} */ + value = null; + /** @type {null | TstNode} */ + left = null; + /** @type {null | TstNode} */ + middle = null; + /** @type {null | TstNode} */ + right = null; + /** @type {number} */ + code; + /** + * @param {string} key + * @param {any} value + * @param {number} index + */ + constructor(key, value, index) { + if (index === void 0 || index >= key.length) { + throw new TypeError("Unreachable"); } - this[kInterceptors] = newInterceptors; - } - close(callback) { - if (callback === void 0) { - return new Promise((resolve, reject) => { - this.close((err, data) => { - return err ? reject(err) : resolve(data); - }); - }); + const code = this.code = key.charCodeAt(index); + if (code > 127) { + throw new TypeError("key must be ascii string"); } - if (typeof callback !== "function") { - throw new InvalidArgumentError("invalid callback"); + if (key.length !== ++index) { + this.middle = new _TstNode(key, value, index); + } else { + this.value = value; } - if (this[kDestroyed]) { - queueMicrotask(() => callback(new ClientDestroyedError(), null)); - return; + } + /** + * @param {string} key + * @param {any} value + */ + add(key, value) { + const length = key.length; + if (length === 0) { + throw new TypeError("Unreachable"); } - if (this[kClosed]) { - if (this[kOnClosed]) { - this[kOnClosed].push(callback); + let index = 0; + let node = this; + while (true) { + const code = key.charCodeAt(index); + if (code > 127) { + throw new TypeError("key must be ascii string"); + } + if (node.code === code) { + if (length === ++index) { + node.value = value; + break; + } else if (node.middle !== null) { + node = node.middle; + } else { + node.middle = new _TstNode(key, value, index); + break; + } + } else if (node.code < code) { + if (node.left !== null) { + node = node.left; + } else { + node.left = new _TstNode(key, value, index); + break; + } + } else if (node.right !== null) { + node = node.right; } else { - queueMicrotask(() => callback(null, null)); + node.right = new _TstNode(key, value, index); + break; } - return; } - this[kClosed] = true; - this[kOnClosed].push(callback); - const onClosed = () => { - const callbacks = this[kOnClosed]; - this[kOnClosed] = null; - for (let i = 0; i < callbacks.length; i++) { - callbacks[i](null, null); - } - }; - this[kClose]().then(() => this.destroy()).then(() => { - queueMicrotask(onClosed); - }); } - destroy(err, callback) { - if (typeof err === "function") { - callback = err; - err = null; - } - if (callback === void 0) { - return new Promise((resolve, reject) => { - this.destroy(err, (err2, data) => { - return err2 ? ( - /* istanbul ignore next: should never error */ - reject(err2) - ) : resolve(data); - }); - }); - } - if (typeof callback !== "function") { - throw new InvalidArgumentError("invalid callback"); - } - if (this[kDestroyed]) { - if (this[kOnDestroyed]) { - this[kOnDestroyed].push(callback); - } else { - queueMicrotask(() => callback(null, null)); + /** + * @param {Uint8Array} key + * @return {TstNode | null} + */ + search(key) { + const keylength = key.length; + let index = 0; + let node = this; + while (node !== null && index < keylength) { + let code = key[index]; + if (code <= 90 && code >= 65) { + code |= 32; } - return; - } - if (!err) { - err = new ClientDestroyedError(); - } - this[kDestroyed] = true; - this[kOnDestroyed] = this[kOnDestroyed] || []; - this[kOnDestroyed].push(callback); - const onDestroyed = () => { - const callbacks = this[kOnDestroyed]; - this[kOnDestroyed] = null; - for (let i = 0; i < callbacks.length; i++) { - callbacks[i](null, null); + while (node !== null) { + if (code === node.code) { + if (keylength === ++index) { + return node; + } + node = node.middle; + break; + } + node = node.code < code ? node.left : node.right; } - }; - this[kDestroy](err).then(() => { - queueMicrotask(onDestroyed); - }); - } - [kInterceptedDispatch](opts, handler) { - if (!this[kInterceptors] || this[kInterceptors].length === 0) { - this[kInterceptedDispatch] = this[kDispatch]; - return this[kDispatch](opts, handler); } - let dispatch = this[kDispatch].bind(this); - for (let i = this[kInterceptors].length - 1; i >= 0; i--) { - dispatch = this[kInterceptors][i](dispatch); - } - this[kInterceptedDispatch] = dispatch; - return dispatch(opts, handler); + return null; } - dispatch(opts, handler) { - if (!handler || typeof handler !== "object") { - throw new InvalidArgumentError("handler must be an object"); - } - try { - if (!opts || typeof opts !== "object") { - throw new InvalidArgumentError("opts must be an object."); - } - if (this[kDestroyed] || this[kOnDestroyed]) { - throw new ClientDestroyedError(); - } - if (this[kClosed]) { - throw new ClientClosedError(); - } - return this[kInterceptedDispatch](opts, handler); - } catch (err) { - if (typeof handler.onError !== "function") { - throw new InvalidArgumentError("invalid onError method"); - } - handler.onError(err); - return false; + }; + var TernarySearchTree = class { + /** @type {TstNode | null} */ + node = null; + /** + * @param {string} key + * @param {any} value + * */ + insert(key, value) { + if (this.node === null) { + this.node = new TstNode(key, value, 0); + } else { + this.node.add(key, value); } } + /** + * @param {Uint8Array} key + * @return {any} + */ + lookup(key) { + return this.node?.search(key)?.value ?? null; + } + }; + var tree = new TernarySearchTree(); + for (let i = 0; i < wellknownHeaderNames.length; ++i) { + const key = headerNameLowerCasedRecord[wellknownHeaderNames[i]]; + tree.insert(key, key); + } + module2.exports = { + TernarySearchTree, + tree }; - module2.exports = DispatcherBase; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/node/fixed-queue.js -var require_fixed_queue = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/node/fixed-queue.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/util.js +var require_util = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/util.js"(exports, module2) { "use strict"; - var kSize = 2048; - var kMask = kSize - 1; - var FixedCircularBuffer = class { - constructor() { - this.bottom = 0; - this.top = 0; - this.list = new Array(kSize); - this.next = null; - } - isEmpty() { - return this.top === this.bottom; + var assert3 = require("node:assert"); + var { kDestroyed, kBodyUsed, kListeners } = require_symbols(); + var { IncomingMessage } = require("node:http"); + var stream = require("node:stream"); + var net = require("node:net"); + var { InvalidArgumentError } = require_errors(); + var { Blob: Blob2 } = require("node:buffer"); + var nodeUtil = require("node:util"); + var { stringify } = require("node:querystring"); + var { headerNameLowerCasedRecord } = require_constants2(); + var { tree } = require_tree(); + var [nodeMajor, nodeMinor] = process.versions.node.split(".").map((v) => Number(v)); + function nop() { + } + function isStream(obj) { + return obj && typeof obj === "object" && typeof obj.pipe === "function" && typeof obj.on === "function"; + } + function isBlobLike(object) { + if (object === null) { + return false; + } else if (object instanceof Blob2) { + return true; + } else if (typeof object !== "object") { + return false; + } else { + const sTag = object[Symbol.toStringTag]; + return (sTag === "Blob" || sTag === "File") && ("stream" in object && typeof object.stream === "function" || "arrayBuffer" in object && typeof object.arrayBuffer === "function"); } - isFull() { - return (this.top + 1 & kMask) === this.bottom; + } + function buildURL(url, queryParams) { + if (url.includes("?") || url.includes("#")) { + throw new Error('Query params cannot be passed when url already contains "?" or "#".'); } - push(data) { - this.list[this.top] = data; - this.top = this.top + 1 & kMask; + const stringified = stringify(queryParams); + if (stringified) { + url += "?" + stringified; } - shift() { - const nextItem = this.list[this.bottom]; - if (nextItem === void 0) - return null; - this.list[this.bottom] = void 0; - this.bottom = this.bottom + 1 & kMask; - return nextItem; + return url; + } + function parseURL(url) { + if (typeof url === "string") { + url = new URL(url); + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); + } + return url; } - }; - module2.exports = class FixedQueue { - constructor() { - this.head = this.tail = new FixedCircularBuffer(); + if (!url || typeof url !== "object") { + throw new InvalidArgumentError("Invalid URL: The URL argument must be a non-null object."); } - isEmpty() { - return this.head.isEmpty(); + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); } - push(data) { - if (this.head.isFull()) { - this.head = this.head.next = new FixedCircularBuffer(); + if (!(url instanceof URL)) { + if (url.port != null && url.port !== "" && !Number.isFinite(parseInt(url.port))) { + throw new InvalidArgumentError("Invalid URL: port must be a valid integer or a string representation of an integer."); } - this.head.push(data); - } - shift() { - const tail = this.tail; - const next = tail.shift(); - if (tail.isEmpty() && tail.next !== null) { - this.tail = tail.next; + if (url.path != null && typeof url.path !== "string") { + throw new InvalidArgumentError("Invalid URL path: the path must be a string or null/undefined."); } - return next; + if (url.pathname != null && typeof url.pathname !== "string") { + throw new InvalidArgumentError("Invalid URL pathname: the pathname must be a string or null/undefined."); + } + if (url.hostname != null && typeof url.hostname !== "string") { + throw new InvalidArgumentError("Invalid URL hostname: the hostname must be a string or null/undefined."); + } + if (url.origin != null && typeof url.origin !== "string") { + throw new InvalidArgumentError("Invalid URL origin: the origin must be a string or null/undefined."); + } + const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80; + let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`; + let path10 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`; + if (origin.endsWith("/")) { + origin = origin.substring(0, origin.length - 1); + } + if (path10 && !path10.startsWith("/")) { + path10 = `/${path10}`; + } + url = new URL(origin + path10); } - }; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/pool-stats.js -var require_pool_stats = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/pool-stats.js"(exports, module2) { - var { kFree, kConnected, kPending, kQueued, kRunning, kSize } = require_symbols(); - var kPool = Symbol("pool"); - var PoolStats = class { - constructor(pool) { - this[kPool] = pool; + return url; + } + function parseOrigin(url) { + url = parseURL(url); + if (url.pathname !== "/" || url.search || url.hash) { + throw new InvalidArgumentError("invalid url"); } - get connected() { - return this[kPool][kConnected]; + return url; + } + function getHostname(host) { + if (host[0] === "[") { + const idx2 = host.indexOf("]"); + assert3(idx2 !== -1); + return host.substring(1, idx2); } - get free() { - return this[kPool][kFree]; + const idx = host.indexOf(":"); + if (idx === -1) + return host; + return host.substring(0, idx); + } + function getServerName(host) { + if (!host) { + return null; } - get pending() { - return this[kPool][kPending]; + assert3.strictEqual(typeof host, "string"); + const servername = getHostname(host); + if (net.isIP(servername)) { + return ""; } - get queued() { - return this[kPool][kQueued]; + return servername; + } + function deepClone(obj) { + return JSON.parse(JSON.stringify(obj)); + } + function isAsyncIterable(obj) { + return !!(obj != null && typeof obj[Symbol.asyncIterator] === "function"); + } + function isIterable(obj) { + return !!(obj != null && (typeof obj[Symbol.iterator] === "function" || typeof obj[Symbol.asyncIterator] === "function")); + } + function bodyLength(body) { + if (body == null) { + return 0; + } else if (isStream(body)) { + const state = body._readableState; + return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) ? state.length : null; + } else if (isBlobLike(body)) { + return body.size != null ? body.size : null; + } else if (isBuffer(body)) { + return body.byteLength; } - get running() { - return this[kPool][kRunning]; + return null; + } + function isDestroyed(body) { + return body && !!(body.destroyed || body[kDestroyed] || stream.isDestroyed?.(body)); + } + function isReadableAborted(stream2) { + const state = stream2?._readableState; + return isDestroyed(stream2) && state && !state.endEmitted; + } + function destroy(stream2, err) { + if (stream2 == null || !isStream(stream2) || isDestroyed(stream2)) { + return; } - get size() { - return this[kPool][kSize]; + if (typeof stream2.destroy === "function") { + if (Object.getPrototypeOf(stream2).constructor === IncomingMessage) { + stream2.socket = null; + } + stream2.destroy(err); + } else if (err) { + queueMicrotask(() => { + stream2.emit("error", err); + }); } - }; - module2.exports = PoolStats; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/pool-base.js -var require_pool_base = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/pool-base.js"(exports, module2) { - "use strict"; - var DispatcherBase = require_dispatcher_base(); - var FixedQueue = require_fixed_queue(); - var { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = require_symbols(); - var PoolStats = require_pool_stats(); - var kClients = Symbol("clients"); - var kNeedDrain = Symbol("needDrain"); - var kQueue = Symbol("queue"); - var kClosedResolve = Symbol("closed resolve"); - var kOnDrain = Symbol("onDrain"); - var kOnConnect = Symbol("onConnect"); - var kOnDisconnect = Symbol("onDisconnect"); - var kOnConnectionError = Symbol("onConnectionError"); - var kGetDispatcher = Symbol("get dispatcher"); - var kAddClient = Symbol("add client"); - var kRemoveClient = Symbol("remove client"); - var kStats = Symbol("stats"); - var PoolBase = class extends DispatcherBase { - constructor() { - super(); - this[kQueue] = new FixedQueue(); - this[kClients] = []; - this[kQueued] = 0; - const pool = this; - this[kOnDrain] = function onDrain(origin, targets) { - const queue = pool[kQueue]; - let needDrain = false; - while (!needDrain) { - const item = queue.shift(); - if (!item) { - break; - } - pool[kQueued]--; - needDrain = !this.dispatch(item.opts, item.handler); - } - this[kNeedDrain] = needDrain; - if (!this[kNeedDrain] && pool[kNeedDrain]) { - pool[kNeedDrain] = false; - pool.emit("drain", origin, [pool, ...targets]); + if (stream2.destroyed !== true) { + stream2[kDestroyed] = true; + } + } + var KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/; + function parseKeepAliveTimeout(val) { + const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR); + return m ? parseInt(m[1], 10) * 1e3 : null; + } + function headerNameToString(value) { + return typeof value === "string" ? headerNameLowerCasedRecord[value] ?? value.toLowerCase() : tree.lookup(value) ?? value.toString("latin1").toLowerCase(); + } + function bufferToLowerCasedHeaderName(value) { + return tree.lookup(value) ?? value.toString("latin1").toLowerCase(); + } + function parseHeaders(headers, obj) { + if (obj === void 0) + obj = {}; + for (let i = 0; i < headers.length; i += 2) { + const key = headerNameToString(headers[i]); + let val = obj[key]; + if (val) { + if (typeof val === "string") { + val = [val]; + obj[key] = val; } - if (pool[kClosedResolve] && queue.isEmpty()) { - Promise.all(pool[kClients].map((c) => c.close())).then(pool[kClosedResolve]); + val.push(headers[i + 1].toString("utf8")); + } else { + const headersValue = headers[i + 1]; + if (typeof headersValue === "string") { + obj[key] = headersValue; + } else { + obj[key] = Array.isArray(headersValue) ? headersValue.map((x) => x.toString("utf8")) : headersValue.toString("utf8"); } - }; - this[kOnConnect] = (origin, targets) => { - pool.emit("connect", origin, [pool, ...targets]); - }; - this[kOnDisconnect] = (origin, targets, err) => { - pool.emit("disconnect", origin, [pool, ...targets], err); - }; - this[kOnConnectionError] = (origin, targets, err) => { - pool.emit("connectionError", origin, [pool, ...targets], err); - }; - this[kStats] = new PoolStats(this); + } } - get [kBusy]() { - return this[kNeedDrain]; + if ("content-length" in obj && "content-disposition" in obj) { + obj["content-disposition"] = Buffer.from(obj["content-disposition"]).toString("latin1"); } - get [kConnected]() { - return this[kClients].filter((client) => client[kConnected]).length; + return obj; + } + function parseRawHeaders(headers) { + const len = headers.length; + const ret = new Array(len); + let hasContentLength = false; + let contentDispositionIdx = -1; + let key; + let val; + let kLen = 0; + for (let n = 0; n < headers.length; n += 2) { + key = headers[n]; + val = headers[n + 1]; + typeof key !== "string" && (key = key.toString()); + typeof val !== "string" && (val = val.toString("utf8")); + kLen = key.length; + if (kLen === 14 && key[7] === "-" && (key === "content-length" || key.toLowerCase() === "content-length")) { + hasContentLength = true; + } else if (kLen === 19 && key[7] === "-" && (key === "content-disposition" || key.toLowerCase() === "content-disposition")) { + contentDispositionIdx = n + 1; + } + ret[n] = key; + ret[n + 1] = val; } - get [kFree]() { - return this[kClients].filter((client) => client[kConnected] && !client[kNeedDrain]).length; + if (hasContentLength && contentDispositionIdx !== -1) { + ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString("latin1"); } - get [kPending]() { - let ret = this[kQueued]; - for (const { [kPending]: pending } of this[kClients]) { - ret += pending; - } - return ret; + return ret; + } + function isBuffer(buffer) { + return buffer instanceof Uint8Array || Buffer.isBuffer(buffer); + } + function validateHandler(handler, method, upgrade) { + if (!handler || typeof handler !== "object") { + throw new InvalidArgumentError("handler must be an object"); } - get [kRunning]() { - let ret = 0; - for (const { [kRunning]: running } of this[kClients]) { - ret += running; - } - return ret; + if (typeof handler.onConnect !== "function") { + throw new InvalidArgumentError("invalid onConnect method"); } - get [kSize]() { - let ret = this[kQueued]; - for (const { [kSize]: size } of this[kClients]) { - ret += size; - } - return ret; + if (typeof handler.onError !== "function") { + throw new InvalidArgumentError("invalid onError method"); } - get stats() { - return this[kStats]; + if (typeof handler.onBodySent !== "function" && handler.onBodySent !== void 0) { + throw new InvalidArgumentError("invalid onBodySent method"); } - async [kClose]() { - if (this[kQueue].isEmpty()) { - return Promise.all(this[kClients].map((c) => c.close())); - } else { - return new Promise((resolve) => { - this[kClosedResolve] = resolve; - }); + if (upgrade || method === "CONNECT") { + if (typeof handler.onUpgrade !== "function") { + throw new InvalidArgumentError("invalid onUpgrade method"); } - } - async [kDestroy](err) { - while (true) { - const item = this[kQueue].shift(); - if (!item) { - break; - } - item.handler.onError(err); + } else { + if (typeof handler.onHeaders !== "function") { + throw new InvalidArgumentError("invalid onHeaders method"); } - return Promise.all(this[kClients].map((c) => c.destroy(err))); - } - [kDispatch](opts, handler) { - const dispatcher = this[kGetDispatcher](); - if (!dispatcher) { - this[kNeedDrain] = true; - this[kQueue].push({ opts, handler }); - this[kQueued]++; - } else if (!dispatcher.dispatch(opts, handler)) { - dispatcher[kNeedDrain] = true; - this[kNeedDrain] = !this[kGetDispatcher](); + if (typeof handler.onData !== "function") { + throw new InvalidArgumentError("invalid onData method"); + } + if (typeof handler.onComplete !== "function") { + throw new InvalidArgumentError("invalid onComplete method"); } - return !this[kNeedDrain]; } - [kAddClient](client) { - client.on("drain", this[kOnDrain]).on("connect", this[kOnConnect]).on("disconnect", this[kOnDisconnect]).on("connectionError", this[kOnConnectionError]); - this[kClients].push(client); - if (this[kNeedDrain]) { - process.nextTick(() => { - if (this[kNeedDrain]) { - this[kOnDrain](client[kUrl], [this, client]); + } + function isDisturbed(body) { + return !!(body && (stream.isDisturbed(body) || body[kBodyUsed])); + } + function isErrored(body) { + return !!(body && stream.isErrored(body)); + } + function isReadable(body) { + return !!(body && stream.isReadable(body)); + } + function getSocketInfo(socket) { + return { + localAddress: socket.localAddress, + localPort: socket.localPort, + remoteAddress: socket.remoteAddress, + remotePort: socket.remotePort, + remoteFamily: socket.remoteFamily, + timeout: socket.timeout, + bytesWritten: socket.bytesWritten, + bytesRead: socket.bytesRead + }; + } + function ReadableStreamFrom(iterable) { + let iterator; + return new ReadableStream( + { + async start() { + iterator = iterable[Symbol.asyncIterator](); + }, + async pull(controller) { + const { done, value } = await iterator.next(); + if (done) { + queueMicrotask(() => { + controller.close(); + controller.byobRequest?.respond(0); + }); + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value); + if (buf.byteLength) { + controller.enqueue(new Uint8Array(buf)); + } } - }); + return controller.desiredSize > 0; + }, + async cancel(reason) { + await iterator.return(); + }, + type: "bytes" } - return this; + ); + } + function isFormDataLike(object) { + return object && typeof object === "object" && typeof object.append === "function" && typeof object.delete === "function" && typeof object.get === "function" && typeof object.getAll === "function" && typeof object.has === "function" && typeof object.set === "function" && object[Symbol.toStringTag] === "FormData"; + } + function addAbortListener(signal, listener) { + if ("addEventListener" in signal) { + signal.addEventListener("abort", listener, { once: true }); + return () => signal.removeEventListener("abort", listener); } - [kRemoveClient](client) { - client.close(() => { - const idx = this[kClients].indexOf(client); - if (idx !== -1) { - this[kClients].splice(idx, 1); - } - }); - this[kNeedDrain] = this[kClients].some((dispatcher) => !dispatcher[kNeedDrain] && dispatcher.closed !== true && dispatcher.destroyed !== true); + signal.addListener("abort", listener); + return () => signal.removeListener("abort", listener); + } + var hasToWellFormed = typeof String.prototype.toWellFormed === "function"; + var hasIsWellFormed = typeof String.prototype.isWellFormed === "function"; + function toUSVString(val) { + return hasToWellFormed ? `${val}`.toWellFormed() : nodeUtil.toUSVString(val); + } + function isUSVString(val) { + return hasIsWellFormed ? `${val}`.isWellFormed() : toUSVString(val) === `${val}`; + } + function isTokenCharCode(c) { + switch (c) { + case 34: + case 40: + case 41: + case 44: + case 47: + case 58: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 91: + case 92: + case 93: + case 123: + case 125: + return false; + default: + return c >= 33 && c <= 126; } - }; + } + function isValidHTTPToken(characters) { + if (characters.length === 0) { + return false; + } + for (let i = 0; i < characters.length; ++i) { + if (!isTokenCharCode(characters.charCodeAt(i))) { + return false; + } + } + return true; + } + var headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; + function isValidHeaderChar(characters) { + return !headerCharRegex.test(characters); + } + function parseRangeHeader(range) { + if (range == null || range === "") + return { start: 0, end: null, size: null }; + const m = range ? range.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null; + return m ? { + start: parseInt(m[1]), + end: m[2] ? parseInt(m[2]) : null, + size: m[3] ? parseInt(m[3]) : null + } : null; + } + function addListener(obj, name, listener) { + const listeners = obj[kListeners] ??= []; + listeners.push([name, listener]); + obj.on(name, listener); + return obj; + } + function removeAllListeners(obj) { + for (const [name, listener] of obj[kListeners] ?? []) { + obj.removeListener(name, listener); + } + obj[kListeners] = null; + } + function errorRequest(client, request, err) { + try { + request.onError(err); + assert3(request.aborted); + } catch (err2) { + client.emit("error", err2); + } + } + var kEnumerableProperty = /* @__PURE__ */ Object.create(null); + kEnumerableProperty.enumerable = true; module2.exports = { - PoolBase, - kClients, - kNeedDrain, - kAddClient, - kRemoveClient, - kGetDispatcher - }; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/constants.js -var require_constants2 = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/constants.js"(exports, module2) { - "use strict"; - var headerNameLowerCasedRecord = {}; - var wellknownHeaderNames = [ - "Accept", - "Accept-Encoding", - "Accept-Language", - "Accept-Ranges", - "Access-Control-Allow-Credentials", - "Access-Control-Allow-Headers", - "Access-Control-Allow-Methods", - "Access-Control-Allow-Origin", - "Access-Control-Expose-Headers", - "Access-Control-Max-Age", - "Access-Control-Request-Headers", - "Access-Control-Request-Method", - "Age", - "Allow", - "Alt-Svc", - "Alt-Used", - "Authorization", - "Cache-Control", - "Clear-Site-Data", - "Connection", - "Content-Disposition", - "Content-Encoding", - "Content-Language", - "Content-Length", - "Content-Location", - "Content-Range", - "Content-Security-Policy", - "Content-Security-Policy-Report-Only", - "Content-Type", - "Cookie", - "Cross-Origin-Embedder-Policy", - "Cross-Origin-Opener-Policy", - "Cross-Origin-Resource-Policy", - "Date", - "Device-Memory", - "Downlink", - "ECT", - "ETag", - "Expect", - "Expect-CT", - "Expires", - "Forwarded", - "From", - "Host", - "If-Match", - "If-Modified-Since", - "If-None-Match", - "If-Range", - "If-Unmodified-Since", - "Keep-Alive", - "Last-Modified", - "Link", - "Location", - "Max-Forwards", - "Origin", - "Permissions-Policy", - "Pragma", - "Proxy-Authenticate", - "Proxy-Authorization", - "RTT", - "Range", - "Referer", - "Referrer-Policy", - "Refresh", - "Retry-After", - "Sec-WebSocket-Accept", - "Sec-WebSocket-Extensions", - "Sec-WebSocket-Key", - "Sec-WebSocket-Protocol", - "Sec-WebSocket-Version", - "Server", - "Server-Timing", - "Service-Worker-Allowed", - "Service-Worker-Navigation-Preload", - "Set-Cookie", - "SourceMap", - "Strict-Transport-Security", - "Supports-Loading-Mode", - "TE", - "Timing-Allow-Origin", - "Trailer", - "Transfer-Encoding", - "Upgrade", - "Upgrade-Insecure-Requests", - "User-Agent", - "Vary", - "Via", - "WWW-Authenticate", - "X-Content-Type-Options", - "X-DNS-Prefetch-Control", - "X-Frame-Options", - "X-Permitted-Cross-Domain-Policies", - "X-Powered-By", - "X-Requested-With", - "X-XSS-Protection" - ]; - for (let i = 0; i < wellknownHeaderNames.length; ++i) { - const key = wellknownHeaderNames[i]; - const lowerCasedKey = key.toLowerCase(); - headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = lowerCasedKey; - } - Object.setPrototypeOf(headerNameLowerCasedRecord, null); - module2.exports = { - wellknownHeaderNames, - headerNameLowerCasedRecord + kEnumerableProperty, + nop, + isDisturbed, + isErrored, + isReadable, + toUSVString, + isUSVString, + isReadableAborted, + isBlobLike, + parseOrigin, + parseURL, + getServerName, + isStream, + isIterable, + isAsyncIterable, + isDestroyed, + headerNameToString, + bufferToLowerCasedHeaderName, + addListener, + removeAllListeners, + errorRequest, + parseRawHeaders, + parseHeaders, + parseKeepAliveTimeout, + destroy, + bodyLength, + deepClone, + ReadableStreamFrom, + isBuffer, + validateHandler, + getSocketInfo, + isFormDataLike, + buildURL, + addAbortListener, + isValidHTTPToken, + isValidHeaderChar, + isTokenCharCode, + parseRangeHeader, + nodeMajor, + nodeMinor, + nodeHasAutoSelectFamily: nodeMajor > 18 || nodeMajor === 18 && nodeMinor >= 13, + safeHTTPMethods: ["GET", "HEAD", "OPTIONS", "TRACE"] }; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/tree.js -var require_tree = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/tree.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/readable.js +var require_readable = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/readable.js"(exports, module2) { "use strict"; - var { - wellknownHeaderNames, - headerNameLowerCasedRecord - } = require_constants2(); - var TstNode = class _TstNode { - /** @type {any} */ - value = null; - /** @type {null | TstNode} */ - left = null; - /** @type {null | TstNode} */ - middle = null; - /** @type {null | TstNode} */ - right = null; - /** @type {number} */ - code; - /** - * @param {Uint8Array} key - * @param {any} value - * @param {number} index - */ - constructor(key, value, index) { - if (index === void 0 || index >= key.length) { - throw new TypeError("Unreachable"); + var assert3 = require("node:assert"); + var { Readable: Readable2 } = require("node:stream"); + var { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = require_errors(); + var util = require_util(); + var { ReadableStreamFrom } = require_util(); + var kConsume = Symbol("kConsume"); + var kReading = Symbol("kReading"); + var kBody = Symbol("kBody"); + var kAbort = Symbol("kAbort"); + var kContentType = Symbol("kContentType"); + var kContentLength = Symbol("kContentLength"); + var noop = () => { + }; + var BodyReadable = class extends Readable2 { + constructor({ + resume, + abort, + contentType = "", + contentLength, + highWaterMark = 64 * 1024 + // Same as nodejs fs streams. + }) { + super({ + autoDestroy: true, + read: resume, + highWaterMark + }); + this._readableState.dataEmitted = false; + this[kAbort] = abort; + this[kConsume] = null; + this[kBody] = null; + this[kContentType] = contentType; + this[kContentLength] = contentLength; + this[kReading] = false; + } + destroy(err) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError(); } - this.code = key[index]; - if (key.length !== ++index) { - this.middle = new _TstNode(key, value, index); - } else { - this.value = value; + if (err) { + this[kAbort](); } + return super.destroy(err); } - /** - * @param {Uint8Array} key - * @param {any} value - * @param {number} index - */ - add(key, value, index) { - if (index === void 0 || index >= key.length) { - throw new TypeError("Unreachable"); + _destroy(err, callback) { + setImmediate(() => { + callback(err); + }); + } + on(ev, ...args) { + if (ev === "data" || ev === "readable") { + this[kReading] = true; } - const code = key[index]; - if (this.code === code) { - if (key.length === ++index) { - this.value = value; - } else if (this.middle !== null) { - this.middle.add(key, value, index); - } else { - this.middle = new _TstNode(key, value, index); - } - } else if (this.code < code) { - if (this.left !== null) { - this.left.add(key, value, index); - } else { - this.left = new _TstNode(key, value, index); + return super.on(ev, ...args); + } + addListener(ev, ...args) { + return this.on(ev, ...args); + } + off(ev, ...args) { + const ret = super.off(ev, ...args); + if (ev === "data" || ev === "readable") { + this[kReading] = this.listenerCount("data") > 0 || this.listenerCount("readable") > 0; + } + return ret; + } + removeListener(ev, ...args) { + return this.off(ev, ...args); + } + push(chunk) { + if (this[kConsume] && chunk !== null) { + consumePush(this[kConsume], chunk); + return this[kReading] ? super.push(chunk) : true; + } + return super.push(chunk); + } + // https://fetch.spec.whatwg.org/#dom-body-text + async text() { + return consume(this, "text"); + } + // https://fetch.spec.whatwg.org/#dom-body-json + async json() { + return consume(this, "json"); + } + // https://fetch.spec.whatwg.org/#dom-body-blob + async blob() { + return consume(this, "blob"); + } + // https://fetch.spec.whatwg.org/#dom-body-arraybuffer + async arrayBuffer() { + return consume(this, "arrayBuffer"); + } + // https://fetch.spec.whatwg.org/#dom-body-formdata + async formData() { + throw new NotSupportedError(); + } + // https://fetch.spec.whatwg.org/#dom-body-bodyused + get bodyUsed() { + return util.isDisturbed(this); + } + // https://fetch.spec.whatwg.org/#dom-body-body + get body() { + if (!this[kBody]) { + this[kBody] = ReadableStreamFrom(this); + if (this[kConsume]) { + this[kBody].getReader(); + assert3(this[kBody].locked); } - } else if (this.right !== null) { - this.right.add(key, value, index); - } else { - this.right = new _TstNode(key, value, index); } + return this[kBody]; } - /** - * @param {Uint8Array} key - * @return {TstNode | null} - */ - search(key) { - const keylength = key.length; - let index = 0; - let node = this; - while (node !== null && index < keylength) { - let code = key[index]; - if (code >= 65 && code <= 90) { - code |= 32; + async dump(opts) { + let limit = Number.isFinite(opts?.limit) ? opts.limit : 128 * 1024; + const signal = opts?.signal; + if (signal != null && (typeof signal !== "object" || !("aborted" in signal))) { + throw new InvalidArgumentError("signal must be an AbortSignal"); + } + signal?.throwIfAborted(); + if (this._readableState.closeEmitted) { + return null; + } + return await new Promise((resolve, reject) => { + if (this[kContentLength] > limit) { + this.destroy(new AbortError()); } - while (node !== null) { - if (code === node.code) { - if (keylength === ++index) { - return node; - } - node = node.middle; - break; + const onAbort = () => { + this.destroy(signal.reason ?? new AbortError()); + }; + signal?.addEventListener("abort", onAbort); + this.on("close", function() { + signal?.removeEventListener("abort", onAbort); + if (signal?.aborted) { + reject(signal.reason ?? new AbortError()); + } else { + resolve(null); } - node = node.code < code ? node.left : node.right; - } - } - return null; + }).on("error", noop).on("data", function(chunk) { + limit -= chunk.length; + if (limit <= 0) { + this.destroy(); + } + }).resume(); + }); } }; - var TernarySearchTree = class { - /** @type {TstNode | null} */ - node = null; - /** - * @param {Uint8Array} key - * @param {any} value - * */ - insert(key, value) { - if (this.node === null) { - this.node = new TstNode(key, value, 0); + function isLocked(self2) { + return self2[kBody] && self2[kBody].locked === true || self2[kConsume]; + } + function isUnusable(self2) { + return util.isDisturbed(self2) || isLocked(self2); + } + async function consume(stream, type) { + assert3(!stream[kConsume]); + return new Promise((resolve, reject) => { + if (isUnusable(stream)) { + const rState = stream._readableState; + if (rState.destroyed && rState.closeEmitted === false) { + stream.on("error", (err) => { + reject(err); + }).on("close", () => { + reject(new TypeError("unusable")); + }); + } else { + reject(rState.errored ?? new TypeError("unusable")); + } } else { - this.node.add(key, value, 0); + queueMicrotask(() => { + stream[kConsume] = { + type, + stream, + resolve, + reject, + length: 0, + body: [] + }; + stream.on("error", function(err) { + consumeFinish(this[kConsume], err); + }).on("close", function() { + if (this[kConsume].body !== null) { + consumeFinish(this[kConsume], new RequestAbortedError()); + } + }); + consumeStart(stream[kConsume]); + }); } + }); + } + function consumeStart(consume2) { + if (consume2.body === null) { + return; } - /** - * @param {Uint8Array} key - */ - lookup(key) { - return this.node?.search(key)?.value ?? null; + const { _readableState: state } = consume2.stream; + if (state.bufferIndex) { + const start = state.bufferIndex; + const end = state.buffer.length; + for (let n = start; n < end; n++) { + consumePush(consume2, state.buffer[n]); + } + } else { + for (const chunk of state.buffer) { + consumePush(consume2, chunk); + } + } + if (state.endEmitted) { + consumeEnd(this[kConsume]); + } else { + consume2.stream.on("end", function() { + consumeEnd(this[kConsume]); + }); + } + consume2.stream.resume(); + while (consume2.stream.read() != null) { } - }; - var tree = new TernarySearchTree(); - for (let i = 0; i < wellknownHeaderNames.length; ++i) { - const key = headerNameLowerCasedRecord[wellknownHeaderNames[i]]; - tree.insert(Buffer.from(key), key); } - module2.exports = { - TernarySearchTree, - tree - }; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/util.js -var require_util = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/util.js"(exports, module2) { - "use strict"; - var assert3 = require("node:assert"); - var { kDestroyed, kBodyUsed } = require_symbols(); - var { IncomingMessage } = require("node:http"); - var stream = require("node:stream"); - var net = require("node:net"); - var { InvalidArgumentError } = require_errors(); - var { Blob: Blob2 } = require("node:buffer"); - var nodeUtil = require("node:util"); - var { stringify } = require("node:querystring"); - var { headerNameLowerCasedRecord } = require_constants2(); - var { tree } = require_tree(); - var [nodeMajor, nodeMinor] = process.versions.node.split(".").map((v) => Number(v)); - function nop() { + function chunksDecode(chunks, length) { + if (chunks.length === 0 || length === 0) { + return ""; + } + const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, length); + const bufferLength = buffer.length; + const start = bufferLength > 2 && buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191 ? 3 : 0; + return buffer.utf8Slice(start, bufferLength); } - function isStream(obj) { - return obj && typeof obj === "object" && typeof obj.pipe === "function" && typeof obj.on === "function"; + function consumeEnd(consume2) { + const { type, body, resolve, stream, length } = consume2; + try { + if (type === "text") { + resolve(chunksDecode(body, length)); + } else if (type === "json") { + resolve(JSON.parse(chunksDecode(body, length))); + } else if (type === "arrayBuffer") { + const dst = new Uint8Array(length); + let pos = 0; + for (const buf of body) { + dst.set(buf, pos); + pos += buf.byteLength; + } + resolve(dst.buffer); + } else if (type === "blob") { + resolve(new Blob(body, { type: stream[kContentType] })); + } + consumeFinish(consume2); + } catch (err) { + stream.destroy(err); + } } - function isBlobLike(object) { - return Blob2 && object instanceof Blob2 || object && typeof object === "object" && (typeof object.stream === "function" || typeof object.arrayBuffer === "function") && /^(Blob|File)$/.test(object[Symbol.toStringTag]); + function consumePush(consume2, chunk) { + consume2.length += chunk.length; + consume2.body.push(chunk); } - function buildURL(url, queryParams) { - if (url.includes("?") || url.includes("#")) { - throw new Error('Query params cannot be passed when url already contains "?" or "#".'); + function consumeFinish(consume2, err) { + if (consume2.body === null) { + return; } - const stringified = stringify(queryParams); - if (stringified) { - url += "?" + stringified; + if (err) { + consume2.reject(err); + } else { + consume2.resolve(); } - return url; + consume2.type = null; + consume2.stream = null; + consume2.resolve = null; + consume2.reject = null; + consume2.length = 0; + consume2.body = null; } - function parseURL(url) { - if (typeof url === "string") { - url = new URL(url); - if (!/^https?:/.test(url.origin || url.protocol)) { - throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); + module2.exports = { Readable: BodyReadable, chunksDecode }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/util.js +var require_util2 = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/util.js"(exports, module2) { + var assert3 = require("node:assert"); + var { + ResponseStatusCodeError + } = require_errors(); + var { chunksDecode } = require_readable(); + var CHUNK_LIMIT = 128 * 1024; + async function getResolveErrorBodyCallback({ callback, body, contentType, statusCode, statusMessage, headers }) { + assert3(body); + let chunks = []; + let length = 0; + for await (const chunk of body) { + chunks.push(chunk); + length += chunk.length; + if (length > CHUNK_LIMIT) { + chunks = null; + break; } - return url; } - if (!url || typeof url !== "object") { - throw new InvalidArgumentError("Invalid URL: The URL argument must be a non-null object."); - } - if (!/^https?:/.test(url.origin || url.protocol)) { - throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); + const message = `Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ""}`; + if (statusCode === 204 || !contentType || !chunks) { + queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers))); + return; } - if (!(url instanceof URL)) { - if (url.port != null && url.port !== "" && !Number.isFinite(parseInt(url.port))) { - throw new InvalidArgumentError("Invalid URL: port must be a valid integer or a string representation of an integer."); - } - if (url.path != null && typeof url.path !== "string") { - throw new InvalidArgumentError("Invalid URL path: the path must be a string or null/undefined."); - } - if (url.pathname != null && typeof url.pathname !== "string") { - throw new InvalidArgumentError("Invalid URL pathname: the pathname must be a string or null/undefined."); - } - if (url.hostname != null && typeof url.hostname !== "string") { - throw new InvalidArgumentError("Invalid URL hostname: the hostname must be a string or null/undefined."); - } - if (url.origin != null && typeof url.origin !== "string") { - throw new InvalidArgumentError("Invalid URL origin: the origin must be a string or null/undefined."); - } - const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80; - let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`; - let path10 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`; - if (origin.endsWith("/")) { - origin = origin.substring(0, origin.length - 1); - } - if (path10 && !path10.startsWith("/")) { - path10 = `/${path10}`; + const stackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; + let payload; + try { + if (isContentTypeApplicationJson(contentType)) { + payload = JSON.parse(chunksDecode(chunks, length)); + } else if (isContentTypeText(contentType)) { + payload = chunksDecode(chunks, length); } - url = new URL(origin + path10); - } - return url; - } - function parseOrigin(url) { - url = parseURL(url); - if (url.pathname !== "/" || url.search || url.hash) { - throw new InvalidArgumentError("invalid url"); + } catch { + } finally { + Error.stackTraceLimit = stackTraceLimit; } - return url; + queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers, payload))); } - function getHostname(host) { - if (host[0] === "[") { - const idx2 = host.indexOf("]"); - assert3(idx2 !== -1); - return host.substring(1, idx2); + var isContentTypeApplicationJson = (contentType) => { + return contentType.length > 15 && contentType[11] === "/" && contentType[0] === "a" && contentType[1] === "p" && contentType[2] === "p" && contentType[3] === "l" && contentType[4] === "i" && contentType[5] === "c" && contentType[6] === "a" && contentType[7] === "t" && contentType[8] === "i" && contentType[9] === "o" && contentType[10] === "n" && contentType[12] === "j" && contentType[13] === "s" && contentType[14] === "o" && contentType[15] === "n"; + }; + var isContentTypeText = (contentType) => { + return contentType.length > 4 && contentType[4] === "/" && contentType[0] === "t" && contentType[1] === "e" && contentType[2] === "x" && contentType[3] === "t"; + }; + module2.exports = { + getResolveErrorBodyCallback, + isContentTypeApplicationJson, + isContentTypeText + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/abort-signal.js +var require_abort_signal = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/abort-signal.js"(exports, module2) { + var { addAbortListener } = require_util(); + var { RequestAbortedError } = require_errors(); + var kListener = Symbol("kListener"); + var kSignal = Symbol("kSignal"); + function abort(self2) { + if (self2.abort) { + self2.abort(self2[kSignal]?.reason); + } else { + self2.reason = self2[kSignal]?.reason ?? new RequestAbortedError(); } - const idx = host.indexOf(":"); - if (idx === -1) - return host; - return host.substring(0, idx); + removeSignal(self2); } - function getServerName(host) { - if (!host) { - return null; - } - assert3.strictEqual(typeof host, "string"); - const servername = getHostname(host); - if (net.isIP(servername)) { - return ""; + function addSignal(self2, signal) { + self2.reason = null; + self2[kSignal] = null; + self2[kListener] = null; + if (!signal) { + return; } - return servername; - } - function deepClone(obj) { - return JSON.parse(JSON.stringify(obj)); - } - function isAsyncIterable(obj) { - return !!(obj != null && typeof obj[Symbol.asyncIterator] === "function"); - } - function isIterable(obj) { - return !!(obj != null && (typeof obj[Symbol.iterator] === "function" || typeof obj[Symbol.asyncIterator] === "function")); - } - function bodyLength(body) { - if (body == null) { - return 0; - } else if (isStream(body)) { - const state = body._readableState; - return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) ? state.length : null; - } else if (isBlobLike(body)) { - return body.size != null ? body.size : null; - } else if (isBuffer(body)) { - return body.byteLength; + if (signal.aborted) { + abort(self2); + return; } - return null; - } - function isDestroyed(stream2) { - return !stream2 || !!(stream2.destroyed || stream2[kDestroyed]); - } - function isReadableAborted(stream2) { - const state = stream2?._readableState; - return isDestroyed(stream2) && state && !state.endEmitted; + self2[kSignal] = signal; + self2[kListener] = () => { + abort(self2); + }; + addAbortListener(self2[kSignal], self2[kListener]); } - function destroy(stream2, err) { - if (stream2 == null || !isStream(stream2) || isDestroyed(stream2)) { + function removeSignal(self2) { + if (!self2[kSignal]) { return; } - if (typeof stream2.destroy === "function") { - if (Object.getPrototypeOf(stream2).constructor === IncomingMessage) { - stream2.socket = null; + if ("removeEventListener" in self2[kSignal]) { + self2[kSignal].removeEventListener("abort", self2[kListener]); + } else { + self2[kSignal].removeListener("abort", self2[kListener]); + } + self2[kSignal] = null; + self2[kListener] = null; + } + module2.exports = { + addSignal, + removeSignal + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-request.js +var require_api_request = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-request.js"(exports, module2) { + "use strict"; + var assert3 = require("node:assert"); + var { Readable: Readable2 } = require_readable(); + var { InvalidArgumentError } = require_errors(); + var util = require_util(); + var { getResolveErrorBodyCallback } = require_util2(); + var { AsyncResource } = require("node:async_hooks"); + var { addSignal, removeSignal } = require_abort_signal(); + var RequestHandler = class extends AsyncResource { + constructor(opts, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError, highWaterMark } = opts; + try { + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + if (highWaterMark && (typeof highWaterMark !== "number" || highWaterMark < 0)) { + throw new InvalidArgumentError("invalid highWaterMark"); + } + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + if (method === "CONNECT") { + throw new InvalidArgumentError("invalid method"); + } + if (onInfo && typeof onInfo !== "function") { + throw new InvalidArgumentError("invalid onInfo callback"); + } + super("UNDICI_REQUEST"); + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on("error", util.nop), err); + } + throw err; } - stream2.destroy(err); - } else if (err) { - process.nextTick((stream3, err2) => { - stream3.emit("error", err2); - }, stream2, err); + this.responseHeaders = responseHeaders || null; + this.opaque = opaque || null; + this.callback = callback; + this.res = null; + this.abort = null; + this.body = body; + this.trailers = {}; + this.context = null; + this.onInfo = onInfo || null; + this.throwOnError = throwOnError; + this.highWaterMark = highWaterMark; + if (util.isStream(body)) { + body.on("error", (err) => { + this.onError(err); + }); + } + addSignal(this, signal); } - if (stream2.destroyed !== true) { - stream2[kDestroyed] = true; + onConnect(abort, context) { + if (this.reason) { + abort(this.reason); + return; + } + assert3(this.callback); + this.abort = abort; + this.context = context; } - } - var KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/; - function parseKeepAliveTimeout(val) { - const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR); - return m ? parseInt(m[1], 10) * 1e3 : null; - } - function headerNameToString(value) { - return typeof value === "string" ? headerNameLowerCasedRecord[value] ?? value.toLowerCase() : tree.lookup(value) ?? value.toString("latin1").toLowerCase(); - } - function bufferToLowerCasedHeaderName(value) { - return tree.lookup(value) ?? value.toString("latin1").toLowerCase(); - } - function parseHeaders(headers, obj) { - if (!Array.isArray(headers)) - return headers; - if (obj === void 0) - obj = {}; - for (let i = 0; i < headers.length; i += 2) { - const key = headerNameToString(headers[i]); - let val = obj[key]; - if (val) { - if (typeof val === "string") { - val = [val]; - obj[key] = val; + onHeaders(statusCode, rawHeaders, resume, statusMessage) { + const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this; + const headers = responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders); + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }); } - val.push(headers[i + 1].toString("utf8")); - } else { - const headersValue = headers[i + 1]; - if (typeof headersValue === "string") { - obj[key] = headersValue; + return; + } + const parsedHeaders = responseHeaders === "raw" ? util.parseHeaders(rawHeaders) : headers; + const contentType = parsedHeaders["content-type"]; + const contentLength = parsedHeaders["content-length"]; + const body = new Readable2({ resume, abort, contentType, contentLength, highWaterMark }); + this.callback = null; + this.res = body; + if (callback !== null) { + if (this.throwOnError && statusCode >= 400) { + this.runInAsyncScope( + getResolveErrorBodyCallback, + null, + { callback, body, contentType, statusCode, statusMessage, headers } + ); } else { - obj[key] = Array.isArray(headersValue) ? headersValue.map((x) => x.toString("utf8")) : headersValue.toString("utf8"); + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + trailers: this.trailers, + opaque, + body, + context + }); } } } - if ("content-length" in obj && "content-disposition" in obj) { - obj["content-disposition"] = Buffer.from(obj["content-disposition"]).toString("latin1"); + onData(chunk) { + const { res } = this; + return res.push(chunk); } - return obj; - } - function parseRawHeaders(headers) { - const ret = []; - let hasContentLength = false; - let contentDispositionIdx = -1; - for (let n = 0; n < headers.length; n += 2) { - const key = headers[n + 0].toString(); - const val = headers[n + 1].toString("utf8"); - if (key.length === 14 && (key === "content-length" || key.toLowerCase() === "content-length")) { - ret.push(key, val); - hasContentLength = true; - } else if (key.length === 19 && (key === "content-disposition" || key.toLowerCase() === "content-disposition")) { - contentDispositionIdx = ret.push(key, val) - 1; - } else { - ret.push(key, val); + onComplete(trailers) { + const { res } = this; + removeSignal(this); + util.parseHeaders(trailers, this.trailers); + res.push(null); + } + onError(err) { + const { res, callback, body, opaque } = this; + removeSignal(this); + if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + if (res) { + this.res = null; + queueMicrotask(() => { + util.destroy(res, err); + }); + } + if (body) { + this.body = null; + util.destroy(body, err); } } - if (hasContentLength && contentDispositionIdx !== -1) { - ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString("latin1"); + }; + function request(opts, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + request.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data); + }); + }); + } + try { + this.dispatch(opts, new RequestHandler(opts, callback)); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts?.opaque; + queueMicrotask(() => callback(err, { opaque })); } - return ret; } - function isBuffer(buffer) { - return buffer instanceof Uint8Array || Buffer.isBuffer(buffer); - } - function validateHandler(handler, method, upgrade) { - if (!handler || typeof handler !== "object") { - throw new InvalidArgumentError("handler must be an object"); + module2.exports = request; + module2.exports.RequestHandler = RequestHandler; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-stream.js +var require_api_stream = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-stream.js"(exports, module2) { + "use strict"; + var assert3 = require("node:assert"); + var { finished, PassThrough } = require("node:stream"); + var { InvalidArgumentError, InvalidReturnValueError } = require_errors(); + var util = require_util(); + var { getResolveErrorBodyCallback } = require_util2(); + var { AsyncResource } = require("node:async_hooks"); + var { addSignal, removeSignal } = require_abort_signal(); + var StreamHandler = class extends AsyncResource { + constructor(opts, factory, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts; + try { + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + if (typeof factory !== "function") { + throw new InvalidArgumentError("invalid factory"); + } + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + if (method === "CONNECT") { + throw new InvalidArgumentError("invalid method"); + } + if (onInfo && typeof onInfo !== "function") { + throw new InvalidArgumentError("invalid onInfo callback"); + } + super("UNDICI_STREAM"); + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on("error", util.nop), err); + } + throw err; + } + this.responseHeaders = responseHeaders || null; + this.opaque = opaque || null; + this.factory = factory; + this.callback = callback; + this.res = null; + this.abort = null; + this.context = null; + this.trailers = null; + this.body = body; + this.onInfo = onInfo || null; + this.throwOnError = throwOnError || false; + if (util.isStream(body)) { + body.on("error", (err) => { + this.onError(err); + }); + } + addSignal(this, signal); } - if (typeof handler.onConnect !== "function") { - throw new InvalidArgumentError("invalid onConnect method"); + onConnect(abort, context) { + if (this.reason) { + abort(this.reason); + return; + } + assert3(this.callback); + this.abort = abort; + this.context = context; } - if (typeof handler.onError !== "function") { - throw new InvalidArgumentError("invalid onError method"); + onHeaders(statusCode, rawHeaders, resume, statusMessage) { + const { factory, opaque, context, callback, responseHeaders } = this; + const headers = responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders); + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }); + } + return; + } + this.factory = null; + let res; + if (this.throwOnError && statusCode >= 400) { + const parsedHeaders = responseHeaders === "raw" ? util.parseHeaders(rawHeaders) : headers; + const contentType = parsedHeaders["content-type"]; + res = new PassThrough(); + this.callback = null; + this.runInAsyncScope( + getResolveErrorBodyCallback, + null, + { callback, body: res, contentType, statusCode, statusMessage, headers } + ); + } else { + if (factory === null) { + return; + } + res = this.runInAsyncScope(factory, null, { + statusCode, + headers, + opaque, + context + }); + if (!res || typeof res.write !== "function" || typeof res.end !== "function" || typeof res.on !== "function") { + throw new InvalidReturnValueError("expected Writable"); + } + finished(res, { readable: false }, (err) => { + const { callback: callback2, res: res2, opaque: opaque2, trailers, abort } = this; + this.res = null; + if (err || !res2.readable) { + util.destroy(res2, err); + } + this.callback = null; + this.runInAsyncScope(callback2, null, err || null, { opaque: opaque2, trailers }); + if (err) { + abort(); + } + }); + } + res.on("drain", resume); + this.res = res; + const needDrain = res.writableNeedDrain !== void 0 ? res.writableNeedDrain : res._writableState?.needDrain; + return needDrain !== true; } - if (typeof handler.onBodySent !== "function" && handler.onBodySent !== void 0) { - throw new InvalidArgumentError("invalid onBodySent method"); + onData(chunk) { + const { res } = this; + return res ? res.write(chunk) : true; } - if (upgrade || method === "CONNECT") { - if (typeof handler.onUpgrade !== "function") { - throw new InvalidArgumentError("invalid onUpgrade method"); + onComplete(trailers) { + const { res } = this; + removeSignal(this); + if (!res) { + return; } - } else { - if (typeof handler.onHeaders !== "function") { - throw new InvalidArgumentError("invalid onHeaders method"); + this.trailers = util.parseHeaders(trailers); + res.end(); + } + onError(err) { + const { res, callback, opaque, body } = this; + removeSignal(this); + this.factory = null; + if (res) { + this.res = null; + util.destroy(res, err); + } else if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); } - if (typeof handler.onData !== "function") { - throw new InvalidArgumentError("invalid onData method"); + if (body) { + this.body = null; + util.destroy(body, err); } - if (typeof handler.onComplete !== "function") { - throw new InvalidArgumentError("invalid onComplete method"); + } + }; + function stream(opts, factory, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + stream.call(this, opts, factory, (err, data) => { + return err ? reject(err) : resolve(data); + }); + }); + } + try { + this.dispatch(opts, new StreamHandler(opts, factory, callback)); + } catch (err) { + if (typeof callback !== "function") { + throw err; } + const opaque = opts?.opaque; + queueMicrotask(() => callback(err, { opaque })); } } - function isDisturbed(body) { - return !!(body && (stream.isDisturbed(body) || body[kBodyUsed])); - } - function isErrored(body) { - return !!(body && stream.isErrored(body)); - } - function isReadable(body) { - return !!(body && stream.isReadable(body)); - } - function getSocketInfo(socket) { - return { - localAddress: socket.localAddress, - localPort: socket.localPort, - remoteAddress: socket.remoteAddress, - remotePort: socket.remotePort, - remoteFamily: socket.remoteFamily, - timeout: socket.timeout, - bytesWritten: socket.bytesWritten, - bytesRead: socket.bytesRead - }; - } - function ReadableStreamFrom(iterable) { - let iterator; - return new ReadableStream( - { - async start() { - iterator = iterable[Symbol.asyncIterator](); + module2.exports = stream; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-pipeline.js +var require_api_pipeline = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-pipeline.js"(exports, module2) { + "use strict"; + var { + Readable: Readable2, + Duplex, + PassThrough + } = require("node:stream"); + var { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError + } = require_errors(); + var util = require_util(); + var { AsyncResource } = require("node:async_hooks"); + var { addSignal, removeSignal } = require_abort_signal(); + var assert3 = require("node:assert"); + var kResume = Symbol("resume"); + var PipelineRequest = class extends Readable2 { + constructor() { + super({ autoDestroy: true }); + this[kResume] = null; + } + _read() { + const { [kResume]: resume } = this; + if (resume) { + this[kResume] = null; + resume(); + } + } + _destroy(err, callback) { + this._read(); + callback(err); + } + }; + var PipelineResponse = class extends Readable2 { + constructor(resume) { + super({ autoDestroy: true }); + this[kResume] = resume; + } + _read() { + this[kResume](); + } + _destroy(err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError(); + } + callback(err); + } + }; + var PipelineHandler = class extends AsyncResource { + constructor(opts, handler) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (typeof handler !== "function") { + throw new InvalidArgumentError("invalid handler"); + } + const { signal, method, opaque, onInfo, responseHeaders } = opts; + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + if (method === "CONNECT") { + throw new InvalidArgumentError("invalid method"); + } + if (onInfo && typeof onInfo !== "function") { + throw new InvalidArgumentError("invalid onInfo callback"); + } + super("UNDICI_PIPELINE"); + this.opaque = opaque || null; + this.responseHeaders = responseHeaders || null; + this.handler = handler; + this.abort = null; + this.context = null; + this.onInfo = onInfo || null; + this.req = new PipelineRequest().on("error", util.nop); + this.ret = new Duplex({ + readableObjectMode: opts.objectMode, + autoDestroy: true, + read: () => { + const { body } = this; + if (body?.resume) { + body.resume(); + } }, - async pull(controller) { - const { done, value } = await iterator.next(); - if (done) { - queueMicrotask(() => { - controller.close(); - controller.byobRequest?.respond(0); - }); + write: (chunk, encoding, callback) => { + const { req } = this; + if (req.push(chunk, encoding) || req._readableState.destroyed) { + callback(); } else { - const buf = Buffer.isBuffer(value) ? value : Buffer.from(value); - if (buf.byteLength) { - controller.enqueue(new Uint8Array(buf)); - } + req[kResume] = callback; } - return controller.desiredSize > 0; - }, - async cancel(reason) { - await iterator.return(); }, - type: "bytes" + destroy: (err, callback) => { + const { body, req, res, ret, abort } = this; + if (!err && !ret._readableState.endEmitted) { + err = new RequestAbortedError(); + } + if (abort && err) { + abort(); + } + util.destroy(body, err); + util.destroy(req, err); + util.destroy(res, err); + removeSignal(this); + callback(err); + } + }).on("prefinish", () => { + const { req } = this; + req.push(null); + }); + this.res = null; + addSignal(this, signal); + } + onConnect(abort, context) { + const { ret, res } = this; + if (this.reason) { + abort(this.reason); + return; } - ); - } - function isFormDataLike(object) { - return object && typeof object === "object" && typeof object.append === "function" && typeof object.delete === "function" && typeof object.get === "function" && typeof object.getAll === "function" && typeof object.has === "function" && typeof object.set === "function" && object[Symbol.toStringTag] === "FormData"; - } - function addAbortListener(signal, listener) { - if ("addEventListener" in signal) { - signal.addEventListener("abort", listener, { once: true }); - return () => signal.removeEventListener("abort", listener); + assert3(!res, "pipeline cannot be retried"); + assert3(!ret.destroyed); + this.abort = abort; + this.context = context; } - signal.addListener("abort", listener); - return () => signal.removeListener("abort", listener); - } - var hasToWellFormed = !!String.prototype.toWellFormed; - function toUSVString(val) { - if (hasToWellFormed) { - return `${val}`.toWellFormed(); - } else if (nodeUtil.toUSVString) { - return nodeUtil.toUSVString(val); + onHeaders(statusCode, rawHeaders, resume) { + const { opaque, handler, context } = this; + if (statusCode < 200) { + if (this.onInfo) { + const headers = this.responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders); + this.onInfo({ statusCode, headers }); + } + return; + } + this.res = new PipelineResponse(resume); + let body; + try { + this.handler = null; + const headers = this.responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders); + body = this.runInAsyncScope(handler, null, { + statusCode, + headers, + opaque, + body: this.res, + context + }); + } catch (err) { + this.res.on("error", util.nop); + throw err; + } + if (!body || typeof body.on !== "function") { + throw new InvalidReturnValueError("expected Readable"); + } + body.on("data", (chunk) => { + const { ret, body: body2 } = this; + if (!ret.push(chunk) && body2.pause) { + body2.pause(); + } + }).on("error", (err) => { + const { ret } = this; + util.destroy(ret, err); + }).on("end", () => { + const { ret } = this; + ret.push(null); + }).on("close", () => { + const { ret } = this; + if (!ret._readableState.ended) { + util.destroy(ret, new RequestAbortedError()); + } + }); + this.body = body; } - return `${val}`; - } - function isTokenCharCode(c) { - switch (c) { - case 34: - case 40: - case 41: - case 44: - case 47: - case 58: - case 59: - case 60: - case 61: - case 62: - case 63: - case 64: - case 91: - case 92: - case 93: - case 123: - case 125: - return false; - default: - return c >= 33 && c <= 126; + onData(chunk) { + const { res } = this; + return res.push(chunk); + } + onComplete(trailers) { + const { res } = this; + res.push(null); + } + onError(err) { + const { ret } = this; + this.handler = null; + util.destroy(ret, err); + } + }; + function pipeline(opts, handler) { + try { + const pipelineHandler = new PipelineHandler(opts, handler); + this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler); + return pipelineHandler.ret; + } catch (err) { + return new PassThrough().destroy(err); } } - function isValidHTTPToken(characters) { - if (characters.length === 0) { - return false; + module2.exports = pipeline; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-upgrade.js +var require_api_upgrade = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-upgrade.js"(exports, module2) { + "use strict"; + var { InvalidArgumentError, SocketError } = require_errors(); + var { AsyncResource } = require("node:async_hooks"); + var util = require_util(); + var { addSignal, removeSignal } = require_abort_signal(); + var assert3 = require("node:assert"); + var UpgradeHandler = class extends AsyncResource { + constructor(opts, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + const { signal, opaque, responseHeaders } = opts; + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + super("UNDICI_UPGRADE"); + this.responseHeaders = responseHeaders || null; + this.opaque = opaque || null; + this.callback = callback; + this.abort = null; + this.context = null; + addSignal(this, signal); } - for (let i = 0; i < characters.length; ++i) { - if (!isTokenCharCode(characters.charCodeAt(i))) { - return false; + onConnect(abort, context) { + if (this.reason) { + abort(this.reason); + return; + } + assert3(this.callback); + this.abort = abort; + this.context = null; + } + onHeaders() { + throw new SocketError("bad upgrade", null); + } + onUpgrade(statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this; + assert3.strictEqual(statusCode, 101); + removeSignal(this); + this.callback = null; + const headers = this.responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders); + this.runInAsyncScope(callback, null, null, { + headers, + socket, + opaque, + context + }); + } + onError(err) { + const { callback, opaque } = this; + removeSignal(this); + if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); } } - return true; + }; + function upgrade(opts, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + upgrade.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data); + }); + }); + } + try { + const upgradeHandler = new UpgradeHandler(opts, callback); + this.dispatch({ + ...opts, + method: opts.method || "GET", + upgrade: opts.protocol || "Websocket" + }, upgradeHandler); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts?.opaque; + queueMicrotask(() => callback(err, { opaque })); + } } - function parseRangeHeader(range) { - if (range == null || range === "") - return { start: 0, end: null, size: null }; - const m = range ? range.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null; - return m ? { - start: parseInt(m[1]), - end: m[2] ? parseInt(m[2]) : null, - size: m[3] ? parseInt(m[3]) : null - } : null; - } - var kEnumerableProperty = /* @__PURE__ */ Object.create(null); - kEnumerableProperty.enumerable = true; - module2.exports = { - kEnumerableProperty, - nop, - isDisturbed, - isErrored, - isReadable, - toUSVString, - isReadableAborted, - isBlobLike, - parseOrigin, - parseURL, - getServerName, - isStream, - isIterable, - isAsyncIterable, - isDestroyed, - headerNameToString, - bufferToLowerCasedHeaderName, - parseRawHeaders, - parseHeaders, - parseKeepAliveTimeout, - destroy, - bodyLength, - deepClone, - ReadableStreamFrom, - isBuffer, - validateHandler, - getSocketInfo, - isFormDataLike, - buildURL, - addAbortListener, - isValidHTTPToken, - isTokenCharCode, - parseRangeHeader, - nodeMajor, - nodeMinor, - nodeHasAutoSelectFamily: nodeMajor > 18 || nodeMajor === 18 && nodeMinor >= 13, - safeHTTPMethods: ["GET", "HEAD", "OPTIONS", "TRACE"] - }; + module2.exports = upgrade; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/diagnostics.js -var require_diagnostics = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/diagnostics.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-connect.js +var require_api_connect = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/api-connect.js"(exports, module2) { "use strict"; - var diagnosticsChannel = require("node:diagnostics_channel"); - var util = require("node:util"); - var undiciDebugLog = util.debuglog("undici"); - var fetchDebuglog = util.debuglog("fetch"); - var websocketDebuglog = util.debuglog("websocket"); - var isClientSet = false; - var channels = { - // Client - beforeConnect: diagnosticsChannel.channel("undici:client:beforeConnect"), - connected: diagnosticsChannel.channel("undici:client:connected"), - connectError: diagnosticsChannel.channel("undici:client:connectError"), - sendHeaders: diagnosticsChannel.channel("undici:client:sendHeaders"), - // Request - create: diagnosticsChannel.channel("undici:request:create"), - bodySent: diagnosticsChannel.channel("undici:request:bodySent"), - headers: diagnosticsChannel.channel("undici:request:headers"), - trailers: diagnosticsChannel.channel("undici:request:trailers"), - error: diagnosticsChannel.channel("undici:request:error"), - // WebSocket - open: diagnosticsChannel.channel("undici:websocket:open"), - close: diagnosticsChannel.channel("undici:websocket:close"), - socketError: diagnosticsChannel.channel("undici:websocket:socket_error"), - ping: diagnosticsChannel.channel("undici:websocket:ping"), - pong: diagnosticsChannel.channel("undici:websocket:pong") - }; - if (undiciDebugLog.enabled || fetchDebuglog.enabled) { - const debuglog = fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog; - diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => { - const { - connectParams: { version: version2, protocol, port, host } - } = evt; - debuglog( - "connecting to %s using %s%s", - `${host}${port ? `:${port}` : ""}`, - protocol, - version2 - ); - }); - diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => { - const { - connectParams: { version: version2, protocol, port, host } - } = evt; - debuglog( - "connected to %s using %s%s", - `${host}${port ? `:${port}` : ""}`, - protocol, - version2 - ); - }); - diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => { - const { - connectParams: { version: version2, protocol, port, host }, - error - } = evt; - debuglog( - "connection to %s using %s%s errored - %s", - `${host}${port ? `:${port}` : ""}`, - protocol, - version2, - error.message - ); - }); - diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { - const { - request: { method, path: path10, origin } - } = evt; - debuglog("sending request to %s %s/%s", method, origin, path10); - }); - diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => { - const { - request: { method, path: path10, origin }, - response: { statusCode } - } = evt; - debuglog( - "received response to %s %s/%s - HTTP %d", - method, - origin, - path10, - statusCode - ); - }); - diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => { - const { - request: { method, path: path10, origin } - } = evt; - debuglog("trailers received from %s %s/%s", method, origin, path10); - }); - diagnosticsChannel.channel("undici:request:error").subscribe((evt) => { - const { - request: { method, path: path10, origin }, - error - } = evt; - debuglog( - "request to %s %s/%s errored - %s", - method, - origin, - path10, - error.message - ); - }); - isClientSet = true; - } - if (websocketDebuglog.enabled) { - if (!isClientSet) { - const debuglog = undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog; - diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => { - const { - connectParams: { version: version2, protocol, port, host } - } = evt; - debuglog( - "connecting to %s%s using %s%s", - host, - port ? `:${port}` : "", - protocol, - version2 - ); - }); - diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => { - const { - connectParams: { version: version2, protocol, port, host } - } = evt; - debuglog( - "connected to %s%s using %s%s", - host, - port ? `:${port}` : "", - protocol, - version2 - ); - }); - diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => { - const { - connectParams: { version: version2, protocol, port, host }, - error - } = evt; - debuglog( - "connection to %s%s using %s%s errored - %s", - host, - port ? `:${port}` : "", - protocol, - version2, - error.message - ); + var assert3 = require("node:assert"); + var { AsyncResource } = require("node:async_hooks"); + var { InvalidArgumentError, SocketError } = require_errors(); + var util = require_util(); + var { addSignal, removeSignal } = require_abort_signal(); + var ConnectHandler = class extends AsyncResource { + constructor(opts, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + const { signal, opaque, responseHeaders } = opts; + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + super("UNDICI_CONNECT"); + this.opaque = opaque || null; + this.responseHeaders = responseHeaders || null; + this.callback = callback; + this.abort = null; + addSignal(this, signal); + } + onConnect(abort, context) { + if (this.reason) { + abort(this.reason); + return; + } + assert3(this.callback); + this.abort = abort; + this.context = context; + } + onHeaders() { + throw new SocketError("bad connect", null); + } + onUpgrade(statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this; + removeSignal(this); + this.callback = null; + let headers = rawHeaders; + if (headers != null) { + headers = this.responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders); + } + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + socket, + opaque, + context }); - diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { - const { - request: { method, path: path10, origin } - } = evt; - debuglog("sending request to %s %s/%s", method, origin, path10); + } + onError(err) { + const { callback, opaque } = this; + removeSignal(this); + if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + } + }; + function connect(opts, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + connect.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data); + }); }); } - diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => { - const { - address: { address, port } - } = evt; - websocketDebuglog("connection opened %s%s", address, port ? `:${port}` : ""); - }); - diagnosticsChannel.channel("undici:websocket:close").subscribe((evt) => { - const { websocket, code, reason } = evt; - websocketDebuglog( - "closed connection to %s - %s %s", - websocket.url, - code, - reason - ); - }); - diagnosticsChannel.channel("undici:websocket:socket_error").subscribe((err) => { - websocketDebuglog("connection errored - %s", err.message); - }); - diagnosticsChannel.channel("undici:websocket:ping").subscribe((evt) => { - websocketDebuglog("ping received"); - }); - diagnosticsChannel.channel("undici:websocket:pong").subscribe((evt) => { - websocketDebuglog("pong received"); - }); + try { + const connectHandler = new ConnectHandler(opts, callback); + this.dispatch({ ...opts, method: "CONNECT" }, connectHandler); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts?.opaque; + queueMicrotask(() => callback(err, { opaque })); + } } - module2.exports = { - channels - }; + module2.exports = connect; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/timers.js -var require_timers = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/timers.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/index.js +var require_api = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/api/index.js"(exports, module2) { "use strict"; - var fastNow = Date.now(); - var fastNowTimeout; - var fastTimers = []; - function onTimeout() { - fastNow = Date.now(); - let len = fastTimers.length; - let idx = 0; - while (idx < len) { - const timer = fastTimers[idx]; - if (timer.state === 0) { - timer.state = fastNow + timer.delay; - } else if (timer.state > 0 && fastNow >= timer.state) { - timer.state = -1; - timer.callback(timer.opaque); - } - if (timer.state === -1) { - timer.state = -2; - if (idx !== len - 1) { - fastTimers[idx] = fastTimers.pop(); - } else { - fastTimers.pop(); - } - len -= 1; - } else { - idx += 1; - } - } - if (fastTimers.length > 0) { - refreshTimeout(); - } - } - function refreshTimeout() { - if (fastNowTimeout?.refresh) { - fastNowTimeout.refresh(); - } else { - clearTimeout(fastNowTimeout); - fastNowTimeout = setTimeout(onTimeout, 1e3); - if (fastNowTimeout.unref) { - fastNowTimeout.unref(); - } - } - } - var Timeout = class { - constructor(callback, delay, opaque) { - this.callback = callback; - this.delay = delay; - this.opaque = opaque; - this.state = -2; - this.refresh(); - } - refresh() { - if (this.state === -2) { - fastTimers.push(this); - if (!fastNowTimeout || fastTimers.length === 1) { - refreshTimeout(); - } - } - this.state = 0; - } - clear() { - this.state = -1; - } - }; - module2.exports = { - setTimeout(callback, delay, opaque) { - return delay < 1e3 ? setTimeout(callback, delay, opaque) : new Timeout(callback, delay, opaque); - }, - clearTimeout(timeout) { - if (timeout instanceof Timeout) { - timeout.clear(); - } else { - clearTimeout(timeout); - } - } - }; + module2.exports.request = require_api_request(); + module2.exports.stream = require_api_stream(); + module2.exports.pipeline = require_api_pipeline(); + module2.exports.upgrade = require_api_upgrade(); + module2.exports.connect = require_api_connect(); } }); -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/deps/streamsearch/sbmh.js -var require_sbmh = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/deps/streamsearch/sbmh.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/dispatcher.js +var require_dispatcher = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/dispatcher.js"(exports, module2) { "use strict"; - var EventEmitter = require("node:events").EventEmitter; - var inherits = require("node:util").inherits; - function SBMH(needle) { - if (typeof needle === "string") { - needle = Buffer.from(needle); - } - if (!Buffer.isBuffer(needle)) { - throw new TypeError("The needle has to be a String or a Buffer."); - } - const needleLength = needle.length; - if (needleLength === 0) { - throw new Error("The needle cannot be an empty String/Buffer."); - } - if (needleLength > 256) { - throw new Error("The needle cannot have a length bigger than 256."); - } - this.maxMatches = Infinity; - this.matches = 0; - this._occ = new Array(256).fill(needleLength); - this._lookbehind_size = 0; - this._needle = needle; - this._bufpos = 0; - this._lookbehind = Buffer.alloc(needleLength); - for (var i = 0; i < needleLength - 1; ++i) { - this._occ[needle[i]] = needleLength - 1 - i; - } - } - inherits(SBMH, EventEmitter); - SBMH.prototype.reset = function() { - this._lookbehind_size = 0; - this.matches = 0; - this._bufpos = 0; - }; - SBMH.prototype.push = function(chunk, pos) { - if (!Buffer.isBuffer(chunk)) { - chunk = Buffer.from(chunk, "binary"); - } - const chlen = chunk.length; - this._bufpos = pos || 0; - let r; - while (r !== chlen && this.matches < this.maxMatches) { - r = this._sbmh_feed(chunk); + var EventEmitter = require("node:events"); + var Dispatcher = class extends EventEmitter { + dispatch() { + throw new Error("not implemented"); } - return r; - }; - SBMH.prototype._sbmh_feed = function(data) { - const len = data.length; - const needle = this._needle; - const needleLength = needle.length; - const lastNeedleChar = needle[needleLength - 1]; - let pos = -this._lookbehind_size; - let ch; - if (pos < 0) { - while (pos < 0 && pos <= len - needleLength) { - ch = this._sbmh_lookup_char(data, pos + needleLength - 1); - if (ch === lastNeedleChar && this._sbmh_memcmp(data, pos, needleLength - 1)) { - this._lookbehind_size = 0; - ++this.matches; - this.emit("info", true); - return this._bufpos = pos + needleLength; - } - pos += this._occ[ch]; - } - if (pos < 0) { - while (pos < 0 && !this._sbmh_memcmp(data, pos, len - pos)) { - ++pos; - } - } - if (pos >= 0) { - this.emit("info", false, this._lookbehind, 0, this._lookbehind_size); - this._lookbehind_size = 0; - } else { - const bytesToCutOff = this._lookbehind_size + pos; - if (bytesToCutOff > 0) { - this.emit("info", false, this._lookbehind, 0, bytesToCutOff); - } - this._lookbehind.copy( - this._lookbehind, - 0, - bytesToCutOff, - this._lookbehind_size - bytesToCutOff - ); - this._lookbehind_size -= bytesToCutOff; - data.copy(this._lookbehind, this._lookbehind_size); - this._lookbehind_size += len; - this._bufpos = len; - return len; - } - } - pos += (pos >= 0) * this._bufpos; - if (data.indexOf(needle, pos) !== -1) { - pos = data.indexOf(needle, pos); - ++this.matches; - if (pos > 0) { - this.emit("info", true, data, this._bufpos, pos); - } else { - this.emit("info", true); + close() { + throw new Error("not implemented"); + } + destroy() { + throw new Error("not implemented"); + } + compose(...args) { + const interceptors = Array.isArray(args[0]) ? args[0] : args; + let dispatch = this.dispatch.bind(this); + for (const interceptor of interceptors) { + if (interceptor == null) { + continue; + } + if (typeof interceptor !== "function") { + throw new TypeError(`invalid interceptor, expected function received ${typeof interceptor}`); + } + dispatch = interceptor(dispatch); + if (dispatch == null || typeof dispatch !== "function" || dispatch.length !== 2) { + throw new TypeError("invalid interceptor"); + } } - return this._bufpos = pos + needleLength; - } else { - pos = len - needleLength; + return new ComposedDispatcher(this, dispatch); } - while (pos < len && (data[pos] !== needle[0] || Buffer.compare( - data.subarray(pos, pos + len - pos), - needle.subarray(0, len - pos) - ) !== 0)) { - ++pos; + }; + var ComposedDispatcher = class extends Dispatcher { + #dispatcher = null; + #dispatch = null; + constructor(dispatcher, dispatch) { + super(); + this.#dispatcher = dispatcher; + this.#dispatch = dispatch; } - if (pos < len) { - data.copy(this._lookbehind, 0, pos, pos + (len - pos)); - this._lookbehind_size = len - pos; + dispatch(...args) { + this.#dispatch(...args); } - if (pos > 0) { - this.emit("info", false, data, this._bufpos, pos < len ? pos : len); + close(...args) { + return this.#dispatcher.close(...args); } - this._bufpos = len; - return len; - }; - SBMH.prototype._sbmh_lookup_char = function(data, pos) { - return pos < 0 ? this._lookbehind[this._lookbehind_size + pos] : data[pos]; - }; - SBMH.prototype._sbmh_memcmp = function(data, pos, len) { - for (var i = 0; i < len; ++i) { - if (this._sbmh_lookup_char(data, pos + i) !== this._needle[i]) { - return false; - } + destroy(...args) { + return this.#dispatcher.destroy(...args); } - return true; }; - module2.exports = SBMH; - } -}); - -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js -var require_PartStream = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js"(exports, module2) { - "use strict"; - var inherits = require("node:util").inherits; - var ReadableStream2 = require("node:stream").Readable; - function PartStream(opts) { - ReadableStream2.call(this, opts); - } - inherits(PartStream, ReadableStream2); - PartStream.prototype._read = function(n) { - }; - module2.exports = PartStream; + module2.exports = Dispatcher; } }); -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/getLimit.js -var require_getLimit = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/getLimit.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/dispatcher-base.js +var require_dispatcher_base = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/dispatcher-base.js"(exports, module2) { "use strict"; - module2.exports = function getLimit(limits, name, defaultLimit) { - if (!limits || limits[name] === void 0 || limits[name] === null) { - return defaultLimit; + var Dispatcher = require_dispatcher(); + var { + ClientDestroyedError, + ClientClosedError, + InvalidArgumentError + } = require_errors(); + var { kDestroy, kClose, kDispatch, kInterceptors } = require_symbols(); + var kDestroyed = Symbol("destroyed"); + var kClosed = Symbol("closed"); + var kOnDestroyed = Symbol("onDestroyed"); + var kOnClosed = Symbol("onClosed"); + var kInterceptedDispatch = Symbol("Intercepted Dispatch"); + var DispatcherBase = class extends Dispatcher { + constructor() { + super(); + this[kDestroyed] = false; + this[kOnDestroyed] = null; + this[kClosed] = false; + this[kOnClosed] = []; } - if (typeof limits[name] !== "number" || isNaN(limits[name])) { - throw new TypeError("Limit " + name + " is not a valid number"); + get destroyed() { + return this[kDestroyed]; } - return limits[name]; - }; - } -}); - -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js -var require_HeaderParser = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js"(exports, module2) { - "use strict"; - var EventEmitter = require("node:events").EventEmitter; - var inherits = require("node:util").inherits; - var getLimit = require_getLimit(); - var StreamSearch = require_sbmh(); - var B_DCRLF = Buffer.from("\r\n\r\n"); - var RE_CRLF = /\r\n/g; - var RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/; - function HeaderParser(cfg) { - EventEmitter.call(this); - cfg = cfg || {}; - const self2 = this; - this.nread = 0; - this.maxed = false; - this.npairs = 0; - this.maxHeaderPairs = getLimit(cfg, "maxHeaderPairs", 2e3); - this.maxHeaderSize = getLimit(cfg, "maxHeaderSize", 80 * 1024); - this.buffer = ""; - this.header = {}; - this.finished = false; - this.ss = new StreamSearch(B_DCRLF); - this.ss.on("info", function(isMatch, data, start, end) { - if (data && !self2.maxed) { - if (self2.nread + end - start >= self2.maxHeaderSize) { - end = self2.maxHeaderSize - self2.nread + start; - self2.nread = self2.maxHeaderSize; - self2.maxed = true; - } else { - self2.nread += end - start; - } - self2.buffer += data.toString("binary", start, end); - } - if (isMatch) { - self2._finish(); - } - }); - } - inherits(HeaderParser, EventEmitter); - HeaderParser.prototype.push = function(data) { - const r = this.ss.push(data); - if (this.finished) { - return r; - } - }; - HeaderParser.prototype.reset = function() { - this.finished = false; - this.buffer = ""; - this.header = {}; - this.ss.reset(); - }; - HeaderParser.prototype._finish = function() { - if (this.buffer) { - this._parseHeader(); - } - this.ss.matches = this.ss.maxMatches; - const header = this.header; - this.header = {}; - this.buffer = ""; - this.finished = true; - this.nread = this.npairs = 0; - this.maxed = false; - this.emit("header", header); - }; - HeaderParser.prototype._parseHeader = function() { - if (this.npairs === this.maxHeaderPairs) { - return; + get closed() { + return this[kClosed]; } - const lines = this.buffer.split(RE_CRLF); - const len = lines.length; - let m, h; - for (var i = 0; i < len; ++i) { - if (lines[i].length === 0) { - continue; - } - if (lines[i][0] === " " || lines[i][0] === " ") { - if (h) { - this.header[h][this.header[h].length - 1] += lines[i]; - continue; + get interceptors() { + return this[kInterceptors]; + } + set interceptors(newInterceptors) { + if (newInterceptors) { + for (let i = newInterceptors.length - 1; i >= 0; i--) { + const interceptor = this[kInterceptors][i]; + if (typeof interceptor !== "function") { + throw new InvalidArgumentError("interceptor must be an function"); + } } } - const posColon = lines[i].indexOf(":"); - if (posColon === -1 || posColon === 0) { - return; - } - m = RE_HDR.exec(lines[i]); - h = m[1].toLowerCase(); - this.header[h] = this.header[h] || []; - this.header[h].push(m[2] || ""); - if (++this.npairs === this.maxHeaderPairs) { - break; - } + this[kInterceptors] = newInterceptors; } - }; - module2.exports = HeaderParser; - } -}); - -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js -var require_Dicer = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js"(exports, module2) { - "use strict"; - var WritableStream = require("node:stream").Writable; - var inherits = require("node:util").inherits; - var StreamSearch = require_sbmh(); - var PartStream = require_PartStream(); - var HeaderParser = require_HeaderParser(); - var DASH = 45; - var B_ONEDASH = Buffer.from("-"); - var B_CRLF = Buffer.from("\r\n"); - var EMPTY_FN = function() { - }; - function Dicer(cfg) { - if (!(this instanceof Dicer)) { - return new Dicer(cfg); - } - WritableStream.call(this, cfg); - if (!cfg || !cfg.headerFirst && typeof cfg.boundary !== "string") { - throw new TypeError("Boundary required"); - } - if (typeof cfg.boundary === "string") { - this.setBoundary(cfg.boundary); - } else { - this._bparser = void 0; - } - this._headerFirst = cfg.headerFirst; - this._dashes = 0; - this._parts = 0; - this._finished = false; - this._realFinish = false; - this._isPreamble = true; - this._justMatched = false; - this._firstWrite = true; - this._inHeader = true; - this._part = void 0; - this._cb = void 0; - this._ignoreData = false; - this._partOpts = { highWaterMark: cfg.partHwm }; - this._pause = false; - const self2 = this; - this._hparser = new HeaderParser(cfg); - this._hparser.on("header", function(header) { - self2._inHeader = false; - self2._part.emit("header", header); - }); - } - inherits(Dicer, WritableStream); - Dicer.prototype.emit = function(ev) { - if (ev === "finish" && !this._realFinish) { - if (!this._finished) { - const self2 = this; - process.nextTick(function() { - self2.emit("error", new Error("Unexpected end of multipart data")); - if (self2._part && !self2._ignoreData) { - const type = self2._isPreamble ? "Preamble" : "Part"; - self2._part.emit("error", new Error(type + " terminated early due to unexpected end of multipart data")); - self2._part.push(null); - process.nextTick(function() { - self2._realFinish = true; - self2.emit("finish"); - self2._realFinish = false; - }); - return; - } - self2._realFinish = true; - self2.emit("finish"); - self2._realFinish = false; + close(callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + this.close((err, data) => { + return err ? reject(err) : resolve(data); + }); }); } - } else { - WritableStream.prototype.emit.apply(this, arguments); - } - }; - Dicer.prototype._write = function(data, encoding, cb) { - if (!this._hparser && !this._bparser) { - return cb(); - } - if (this._headerFirst && this._isPreamble) { - if (!this._part) { - this._part = new PartStream(this._partOpts); - if (this._events.preamble) { - this.emit("preamble", this._part); - } else { - this._ignore(); - } + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); } - const r = this._hparser.push(data); - if (!this._inHeader && r !== void 0 && r < data.length) { - data = data.slice(r); - } else { - return cb(); + if (this[kDestroyed]) { + queueMicrotask(() => callback(new ClientDestroyedError(), null)); + return; } - } - if (this._firstWrite) { - this._bparser.push(B_CRLF); - this._firstWrite = false; - } - this._bparser.push(data); - if (this._pause) { - this._cb = cb; - } else { - cb(); - } - }; - Dicer.prototype.reset = function() { - this._part = void 0; - this._bparser = void 0; - this._hparser = void 0; - }; - Dicer.prototype.setBoundary = function(boundary) { - const self2 = this; - this._bparser = new StreamSearch("\r\n--" + boundary); - this._bparser.on("info", function(isMatch, data, start, end) { - self2._oninfo(isMatch, data, start, end); - }); - }; - Dicer.prototype._ignore = function() { - if (this._part && !this._ignoreData) { - this._ignoreData = true; - this._part.on("error", EMPTY_FN); - this._part.resume(); - } - }; - Dicer.prototype._oninfo = function(isMatch, data, start, end) { - let buf; - const self2 = this; - let i = 0; - let r; - let shouldWriteMore = true; - if (!this._part && this._justMatched && data) { - while (this._dashes < 2 && start + i < end) { - if (data[start + i] === DASH) { - ++i; - ++this._dashes; + if (this[kClosed]) { + if (this[kOnClosed]) { + this[kOnClosed].push(callback); } else { - if (this._dashes) { - buf = B_ONEDASH; - } - this._dashes = 0; - break; - } - } - if (this._dashes === 2) { - if (start + i < end && this._events.trailer) { - this.emit("trailer", data.slice(start + i, end)); - } - this.reset(); - this._finished = true; - if (self2._parts === 0) { - self2._realFinish = true; - self2.emit("finish"); - self2._realFinish = false; + queueMicrotask(() => callback(null, null)); } - } - if (this._dashes) { return; } - } - if (this._justMatched) { - this._justMatched = false; - } - if (!this._part) { - this._part = new PartStream(this._partOpts); - this._part._read = function(n) { - self2._unpause(); + this[kClosed] = true; + this[kOnClosed].push(callback); + const onClosed = () => { + const callbacks = this[kOnClosed]; + this[kOnClosed] = null; + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null); + } }; - if (this._isPreamble && this._events.preamble) { - this.emit("preamble", this._part); - } else if (this._isPreamble !== true && this._events.part) { - this.emit("part", this._part); - } else { - this._ignore(); - } - if (!this._isPreamble) { - this._inHeader = true; - } + this[kClose]().then(() => this.destroy()).then(() => { + queueMicrotask(onClosed); + }); } - if (data && start < end && !this._ignoreData) { - if (this._isPreamble || !this._inHeader) { - if (buf) { - shouldWriteMore = this._part.push(buf); - } - shouldWriteMore = this._part.push(data.slice(start, end)); - if (!shouldWriteMore) { - this._pause = true; - } - } else if (!this._isPreamble && this._inHeader) { - if (buf) { - this._hparser.push(buf); - } - r = this._hparser.push(data.slice(start, end)); - if (!this._inHeader && r !== void 0 && r < end) { - this._oninfo(false, data, start + r, end); - } + destroy(err, callback) { + if (typeof err === "function") { + callback = err; + err = null; } - } - if (isMatch) { - this._hparser.reset(); - if (this._isPreamble) { - this._isPreamble = false; - } else { - if (start !== end) { - ++this._parts; - this._part.on("end", function() { - if (--self2._parts === 0) { - if (self2._finished) { - self2._realFinish = true; - self2.emit("finish"); - self2._realFinish = false; - } else { - self2._unpause(); - } - } + if (callback === void 0) { + return new Promise((resolve, reject) => { + this.destroy(err, (err2, data) => { + return err2 ? ( + /* istanbul ignore next: should never error */ + reject(err2) + ) : resolve(data); }); - } + }); } - this._part.push(null); - this._part = void 0; - this._ignoreData = false; - this._justMatched = true; - this._dashes = 0; - } - }; - Dicer.prototype._unpause = function() { - if (!this._pause) { - return; - } - this._pause = false; - if (this._cb) { - const cb = this._cb; - this._cb = void 0; - cb(); - } - }; - module2.exports = Dicer; - } -}); - -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/decodeText.js -var require_decodeText = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/decodeText.js"(exports, module2) { - "use strict"; - var utf8Decoder = new TextDecoder("utf-8"); - var textDecoders = /* @__PURE__ */ new Map([ - ["utf-8", utf8Decoder], - ["utf8", utf8Decoder] - ]); - function getDecoder(charset) { - let lc; - while (true) { - switch (charset) { - case "utf-8": - case "utf8": - return decoders.utf8; - case "latin1": - case "ascii": - case "us-ascii": - case "iso-8859-1": - case "iso8859-1": - case "iso88591": - case "iso_8859-1": - case "windows-1252": - case "iso_8859-1:1987": - case "cp1252": - case "x-cp1252": - return decoders.latin1; - case "utf16le": - case "utf-16le": - case "ucs2": - case "ucs-2": - return decoders.utf16le; - case "base64": - return decoders.base64; - default: - if (lc === void 0) { - lc = true; - charset = charset.toLowerCase(); - continue; - } - return decoders.other.bind(charset); - } - } - } - var decoders = { - utf8: (data, sourceEncoding) => { - if (data.length === 0) { - return ""; - } - if (typeof data === "string") { - data = Buffer.from(data, sourceEncoding); - } - return data.utf8Slice(0, data.length); - }, - latin1: (data, sourceEncoding) => { - if (data.length === 0) { - return ""; - } - if (typeof data === "string") { - return data; - } - return data.latin1Slice(0, data.length); - }, - utf16le: (data, sourceEncoding) => { - if (data.length === 0) { - return ""; + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); } - if (typeof data === "string") { - data = Buffer.from(data, sourceEncoding); + if (this[kDestroyed]) { + if (this[kOnDestroyed]) { + this[kOnDestroyed].push(callback); + } else { + queueMicrotask(() => callback(null, null)); + } + return; } - return data.ucs2Slice(0, data.length); - }, - base64: (data, sourceEncoding) => { - if (data.length === 0) { - return ""; + if (!err) { + err = new ClientDestroyedError(); } - if (typeof data === "string") { - data = Buffer.from(data, sourceEncoding); + this[kDestroyed] = true; + this[kOnDestroyed] = this[kOnDestroyed] || []; + this[kOnDestroyed].push(callback); + const onDestroyed = () => { + const callbacks = this[kOnDestroyed]; + this[kOnDestroyed] = null; + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null); + } + }; + this[kDestroy](err).then(() => { + queueMicrotask(onDestroyed); + }); + } + [kInterceptedDispatch](opts, handler) { + if (!this[kInterceptors] || this[kInterceptors].length === 0) { + this[kInterceptedDispatch] = this[kDispatch]; + return this[kDispatch](opts, handler); } - return data.base64Slice(0, data.length); - }, - other: (data, sourceEncoding) => { - if (data.length === 0) { - return ""; + let dispatch = this[kDispatch].bind(this); + for (let i = this[kInterceptors].length - 1; i >= 0; i--) { + dispatch = this[kInterceptors][i](dispatch); } - if (typeof data === "string") { - data = Buffer.from(data, sourceEncoding); + this[kInterceptedDispatch] = dispatch; + return dispatch(opts, handler); + } + dispatch(opts, handler) { + if (!handler || typeof handler !== "object") { + throw new InvalidArgumentError("handler must be an object"); } - if (textDecoders.has(exports.toString())) { - try { - return textDecoders.get(exports).decode(data); - } catch (e) { + try { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("opts must be an object."); + } + if (this[kDestroyed] || this[kOnDestroyed]) { + throw new ClientDestroyedError(); + } + if (this[kClosed]) { + throw new ClientClosedError(); + } + return this[kInterceptedDispatch](opts, handler); + } catch (err) { + if (typeof handler.onError !== "function") { + throw new InvalidArgumentError("invalid onError method"); } + handler.onError(err); + return false; } - return typeof data === "string" ? data : data.toString(); } }; - function decodeText(text, sourceEncoding, destEncoding) { - if (text) { - return getDecoder(destEncoding)(text, sourceEncoding); - } - return text; - } - module2.exports = decodeText; + module2.exports = DispatcherBase; } }); -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/parseParams.js -var require_parseParams = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/parseParams.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/fixed-queue.js +var require_fixed_queue = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/fixed-queue.js"(exports, module2) { "use strict"; - var decodeText = require_decodeText(); - var RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g; - var EncodedLookup = { - "%00": "\0", - "%01": "", - "%02": "", - "%03": "", - "%04": "", - "%05": "", - "%06": "", - "%07": "\x07", - "%08": "\b", - "%09": " ", - "%0a": "\n", - "%0A": "\n", - "%0b": "\v", - "%0B": "\v", - "%0c": "\f", - "%0C": "\f", - "%0d": "\r", - "%0D": "\r", - "%0e": "", - "%0E": "", - "%0f": "", - "%0F": "", - "%10": "", - "%11": "", - "%12": "", - "%13": "", - "%14": "", - "%15": "", - "%16": "", - "%17": "", - "%18": "", - "%19": "", - "%1a": "", - "%1A": "", - "%1b": "\x1B", - "%1B": "\x1B", - "%1c": "", - "%1C": "", - "%1d": "", - "%1D": "", - "%1e": "", - "%1E": "", - "%1f": "", - "%1F": "", - "%20": " ", - "%21": "!", - "%22": '"', - "%23": "#", - "%24": "$", - "%25": "%", - "%26": "&", - "%27": "'", - "%28": "(", - "%29": ")", - "%2a": "*", - "%2A": "*", - "%2b": "+", - "%2B": "+", - "%2c": ",", - "%2C": ",", - "%2d": "-", - "%2D": "-", - "%2e": ".", - "%2E": ".", - "%2f": "/", - "%2F": "/", - "%30": "0", - "%31": "1", - "%32": "2", - "%33": "3", - "%34": "4", - "%35": "5", - "%36": "6", - "%37": "7", - "%38": "8", - "%39": "9", - "%3a": ":", - "%3A": ":", - "%3b": ";", - "%3B": ";", - "%3c": "<", - "%3C": "<", - "%3d": "=", - "%3D": "=", - "%3e": ">", - "%3E": ">", - "%3f": "?", - "%3F": "?", - "%40": "@", - "%41": "A", - "%42": "B", - "%43": "C", - "%44": "D", - "%45": "E", - "%46": "F", - "%47": "G", - "%48": "H", - "%49": "I", - "%4a": "J", - "%4A": "J", - "%4b": "K", - "%4B": "K", - "%4c": "L", - "%4C": "L", - "%4d": "M", - "%4D": "M", - "%4e": "N", - "%4E": "N", - "%4f": "O", - "%4F": "O", - "%50": "P", - "%51": "Q", - "%52": "R", - "%53": "S", - "%54": "T", - "%55": "U", - "%56": "V", - "%57": "W", - "%58": "X", - "%59": "Y", - "%5a": "Z", - "%5A": "Z", - "%5b": "[", - "%5B": "[", - "%5c": "\\", - "%5C": "\\", - "%5d": "]", - "%5D": "]", - "%5e": "^", - "%5E": "^", - "%5f": "_", - "%5F": "_", - "%60": "`", - "%61": "a", - "%62": "b", - "%63": "c", - "%64": "d", - "%65": "e", - "%66": "f", - "%67": "g", - "%68": "h", - "%69": "i", - "%6a": "j", - "%6A": "j", - "%6b": "k", - "%6B": "k", - "%6c": "l", - "%6C": "l", - "%6d": "m", - "%6D": "m", - "%6e": "n", - "%6E": "n", - "%6f": "o", - "%6F": "o", - "%70": "p", - "%71": "q", - "%72": "r", - "%73": "s", - "%74": "t", - "%75": "u", - "%76": "v", - "%77": "w", - "%78": "x", - "%79": "y", - "%7a": "z", - "%7A": "z", - "%7b": "{", - "%7B": "{", - "%7c": "|", - "%7C": "|", - "%7d": "}", - "%7D": "}", - "%7e": "~", - "%7E": "~", - "%7f": "\x7F", - "%7F": "\x7F", - "%80": "\x80", - "%81": "\x81", - "%82": "\x82", - "%83": "\x83", - "%84": "\x84", - "%85": "\x85", - "%86": "\x86", - "%87": "\x87", - "%88": "\x88", - "%89": "\x89", - "%8a": "\x8A", - "%8A": "\x8A", - "%8b": "\x8B", - "%8B": "\x8B", - "%8c": "\x8C", - "%8C": "\x8C", - "%8d": "\x8D", - "%8D": "\x8D", - "%8e": "\x8E", - "%8E": "\x8E", - "%8f": "\x8F", - "%8F": "\x8F", - "%90": "\x90", - "%91": "\x91", - "%92": "\x92", - "%93": "\x93", - "%94": "\x94", - "%95": "\x95", - "%96": "\x96", - "%97": "\x97", - "%98": "\x98", - "%99": "\x99", - "%9a": "\x9A", - "%9A": "\x9A", - "%9b": "\x9B", - "%9B": "\x9B", - "%9c": "\x9C", - "%9C": "\x9C", - "%9d": "\x9D", - "%9D": "\x9D", - "%9e": "\x9E", - "%9E": "\x9E", - "%9f": "\x9F", - "%9F": "\x9F", - "%a0": "\xA0", - "%A0": "\xA0", - "%a1": "\xA1", - "%A1": "\xA1", - "%a2": "\xA2", - "%A2": "\xA2", - "%a3": "\xA3", - "%A3": "\xA3", - "%a4": "\xA4", - "%A4": "\xA4", - "%a5": "\xA5", - "%A5": "\xA5", - "%a6": "\xA6", - "%A6": "\xA6", - "%a7": "\xA7", - "%A7": "\xA7", - "%a8": "\xA8", - "%A8": "\xA8", - "%a9": "\xA9", - "%A9": "\xA9", - "%aa": "\xAA", - "%Aa": "\xAA", - "%aA": "\xAA", - "%AA": "\xAA", - "%ab": "\xAB", - "%Ab": "\xAB", - "%aB": "\xAB", - "%AB": "\xAB", - "%ac": "\xAC", - "%Ac": "\xAC", - "%aC": "\xAC", - "%AC": "\xAC", - "%ad": "\xAD", - "%Ad": "\xAD", - "%aD": "\xAD", - "%AD": "\xAD", - "%ae": "\xAE", - "%Ae": "\xAE", - "%aE": "\xAE", - "%AE": "\xAE", - "%af": "\xAF", - "%Af": "\xAF", - "%aF": "\xAF", - "%AF": "\xAF", - "%b0": "\xB0", - "%B0": "\xB0", - "%b1": "\xB1", - "%B1": "\xB1", - "%b2": "\xB2", - "%B2": "\xB2", - "%b3": "\xB3", - "%B3": "\xB3", - "%b4": "\xB4", - "%B4": "\xB4", - "%b5": "\xB5", - "%B5": "\xB5", - "%b6": "\xB6", - "%B6": "\xB6", - "%b7": "\xB7", - "%B7": "\xB7", - "%b8": "\xB8", - "%B8": "\xB8", - "%b9": "\xB9", - "%B9": "\xB9", - "%ba": "\xBA", - "%Ba": "\xBA", - "%bA": "\xBA", - "%BA": "\xBA", - "%bb": "\xBB", - "%Bb": "\xBB", - "%bB": "\xBB", - "%BB": "\xBB", - "%bc": "\xBC", - "%Bc": "\xBC", - "%bC": "\xBC", - "%BC": "\xBC", - "%bd": "\xBD", - "%Bd": "\xBD", - "%bD": "\xBD", - "%BD": "\xBD", - "%be": "\xBE", - "%Be": "\xBE", - "%bE": "\xBE", - "%BE": "\xBE", - "%bf": "\xBF", - "%Bf": "\xBF", - "%bF": "\xBF", - "%BF": "\xBF", - "%c0": "\xC0", - "%C0": "\xC0", - "%c1": "\xC1", - "%C1": "\xC1", - "%c2": "\xC2", - "%C2": "\xC2", - "%c3": "\xC3", - "%C3": "\xC3", - "%c4": "\xC4", - "%C4": "\xC4", - "%c5": "\xC5", - "%C5": "\xC5", - "%c6": "\xC6", - "%C6": "\xC6", - "%c7": "\xC7", - "%C7": "\xC7", - "%c8": "\xC8", - "%C8": "\xC8", - "%c9": "\xC9", - "%C9": "\xC9", - "%ca": "\xCA", - "%Ca": "\xCA", - "%cA": "\xCA", - "%CA": "\xCA", - "%cb": "\xCB", - "%Cb": "\xCB", - "%cB": "\xCB", - "%CB": "\xCB", - "%cc": "\xCC", - "%Cc": "\xCC", - "%cC": "\xCC", - "%CC": "\xCC", - "%cd": "\xCD", - "%Cd": "\xCD", - "%cD": "\xCD", - "%CD": "\xCD", - "%ce": "\xCE", - "%Ce": "\xCE", - "%cE": "\xCE", - "%CE": "\xCE", - "%cf": "\xCF", - "%Cf": "\xCF", - "%cF": "\xCF", - "%CF": "\xCF", - "%d0": "\xD0", - "%D0": "\xD0", - "%d1": "\xD1", - "%D1": "\xD1", - "%d2": "\xD2", - "%D2": "\xD2", - "%d3": "\xD3", - "%D3": "\xD3", - "%d4": "\xD4", - "%D4": "\xD4", - "%d5": "\xD5", - "%D5": "\xD5", - "%d6": "\xD6", - "%D6": "\xD6", - "%d7": "\xD7", - "%D7": "\xD7", - "%d8": "\xD8", - "%D8": "\xD8", - "%d9": "\xD9", - "%D9": "\xD9", - "%da": "\xDA", - "%Da": "\xDA", - "%dA": "\xDA", - "%DA": "\xDA", - "%db": "\xDB", - "%Db": "\xDB", - "%dB": "\xDB", - "%DB": "\xDB", - "%dc": "\xDC", - "%Dc": "\xDC", - "%dC": "\xDC", - "%DC": "\xDC", - "%dd": "\xDD", - "%Dd": "\xDD", - "%dD": "\xDD", - "%DD": "\xDD", - "%de": "\xDE", - "%De": "\xDE", - "%dE": "\xDE", - "%DE": "\xDE", - "%df": "\xDF", - "%Df": "\xDF", - "%dF": "\xDF", - "%DF": "\xDF", - "%e0": "\xE0", - "%E0": "\xE0", - "%e1": "\xE1", - "%E1": "\xE1", - "%e2": "\xE2", - "%E2": "\xE2", - "%e3": "\xE3", - "%E3": "\xE3", - "%e4": "\xE4", - "%E4": "\xE4", - "%e5": "\xE5", - "%E5": "\xE5", - "%e6": "\xE6", - "%E6": "\xE6", - "%e7": "\xE7", - "%E7": "\xE7", - "%e8": "\xE8", - "%E8": "\xE8", - "%e9": "\xE9", - "%E9": "\xE9", - "%ea": "\xEA", - "%Ea": "\xEA", - "%eA": "\xEA", - "%EA": "\xEA", - "%eb": "\xEB", - "%Eb": "\xEB", - "%eB": "\xEB", - "%EB": "\xEB", - "%ec": "\xEC", - "%Ec": "\xEC", - "%eC": "\xEC", - "%EC": "\xEC", - "%ed": "\xED", - "%Ed": "\xED", - "%eD": "\xED", - "%ED": "\xED", - "%ee": "\xEE", - "%Ee": "\xEE", - "%eE": "\xEE", - "%EE": "\xEE", - "%ef": "\xEF", - "%Ef": "\xEF", - "%eF": "\xEF", - "%EF": "\xEF", - "%f0": "\xF0", - "%F0": "\xF0", - "%f1": "\xF1", - "%F1": "\xF1", - "%f2": "\xF2", - "%F2": "\xF2", - "%f3": "\xF3", - "%F3": "\xF3", - "%f4": "\xF4", - "%F4": "\xF4", - "%f5": "\xF5", - "%F5": "\xF5", - "%f6": "\xF6", - "%F6": "\xF6", - "%f7": "\xF7", - "%F7": "\xF7", - "%f8": "\xF8", - "%F8": "\xF8", - "%f9": "\xF9", - "%F9": "\xF9", - "%fa": "\xFA", - "%Fa": "\xFA", - "%fA": "\xFA", - "%FA": "\xFA", - "%fb": "\xFB", - "%Fb": "\xFB", - "%fB": "\xFB", - "%FB": "\xFB", - "%fc": "\xFC", - "%Fc": "\xFC", - "%fC": "\xFC", - "%FC": "\xFC", - "%fd": "\xFD", - "%Fd": "\xFD", - "%fD": "\xFD", - "%FD": "\xFD", - "%fe": "\xFE", - "%Fe": "\xFE", - "%fE": "\xFE", - "%FE": "\xFE", - "%ff": "\xFF", - "%Ff": "\xFF", - "%fF": "\xFF", - "%FF": "\xFF" - }; - function encodedReplacer(match) { - return EncodedLookup[match]; - } - var STATE_KEY = 0; - var STATE_VALUE = 1; - var STATE_CHARSET = 2; - var STATE_LANG = 3; - function parseParams(str) { - const res = []; - let state = STATE_KEY; - let charset = ""; - let inquote = false; - let escaping = false; - let p = 0; - let tmp = ""; - const len = str.length; - for (var i = 0; i < len; ++i) { - const char = str[i]; - if (char === "\\" && inquote) { - if (escaping) { - escaping = false; - } else { - escaping = true; - continue; - } - } else if (char === '"') { - if (!escaping) { - if (inquote) { - inquote = false; - state = STATE_KEY; - } else { - inquote = true; - } - continue; - } else { - escaping = false; - } - } else { - if (escaping && inquote) { - tmp += "\\"; - } - escaping = false; - if ((state === STATE_CHARSET || state === STATE_LANG) && char === "'") { - if (state === STATE_CHARSET) { - state = STATE_LANG; - charset = tmp.substring(1); - } else { - state = STATE_VALUE; - } - tmp = ""; - continue; - } else if (state === STATE_KEY && (char === "*" || char === "=") && res.length) { - state = char === "*" ? STATE_CHARSET : STATE_VALUE; - res[p] = [tmp, void 0]; - tmp = ""; - continue; - } else if (!inquote && char === ";") { - state = STATE_KEY; - if (charset) { - if (tmp.length) { - tmp = decodeText( - tmp.replace(RE_ENCODED, encodedReplacer), - "binary", - charset - ); - } - charset = ""; - } else if (tmp.length) { - tmp = decodeText(tmp, "binary", "utf8"); - } - if (res[p] === void 0) { - res[p] = tmp; - } else { - res[p][1] = tmp; - } - tmp = ""; - ++p; - continue; - } else if (!inquote && (char === " " || char === " ")) { - continue; - } - } - tmp += char; + var kSize = 2048; + var kMask = kSize - 1; + var FixedCircularBuffer = class { + constructor() { + this.bottom = 0; + this.top = 0; + this.list = new Array(kSize); + this.next = null; } - if (charset && tmp.length) { - tmp = decodeText( - tmp.replace(RE_ENCODED, encodedReplacer), - "binary", - charset - ); - } else if (tmp) { - tmp = decodeText(tmp, "binary", "utf8"); + isEmpty() { + return this.top === this.bottom; } - if (res[p] === void 0) { - if (tmp) { - res[p] = tmp; - } - } else { - res[p][1] = tmp; + isFull() { + return (this.top + 1 & kMask) === this.bottom; } - return res; - } - module2.exports = parseParams; - } -}); - -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/basename.js -var require_basename = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/basename.js"(exports, module2) { - "use strict"; - module2.exports = function basename(path10) { - if (typeof path10 !== "string") { - return ""; + push(data) { + this.list[this.top] = data; + this.top = this.top + 1 & kMask; } - for (var i = path10.length - 1; i >= 0; --i) { - switch (path10.charCodeAt(i)) { - case 47: - case 92: - path10 = path10.slice(i + 1); - return path10 === ".." || path10 === "." ? "" : path10; - } + shift() { + const nextItem = this.list[this.bottom]; + if (nextItem === void 0) + return null; + this.list[this.bottom] = void 0; + this.bottom = this.bottom + 1 & kMask; + return nextItem; } - return path10 === ".." || path10 === "." ? "" : path10; }; - } -}); - -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/types/multipart.js -var require_multipart = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/types/multipart.js"(exports, module2) { - "use strict"; - var { Readable: Readable2 } = require("node:stream"); - var { inherits } = require("node:util"); - var Dicer = require_Dicer(); - var parseParams = require_parseParams(); - var decodeText = require_decodeText(); - var basename = require_basename(); - var getLimit = require_getLimit(); - var RE_BOUNDARY = /^boundary$/i; - var RE_FIELD = /^form-data$/i; - var RE_CHARSET = /^charset$/i; - var RE_FILENAME = /^filename$/i; - var RE_NAME = /^name$/i; - Multipart.detect = /^multipart\/form-data/i; - function Multipart(boy, cfg) { - let i; - let len; - const self2 = this; - let boundary; - const limits = cfg.limits; - const isPartAFile = cfg.isPartAFile || ((fieldName, contentType, fileName) => contentType === "application/octet-stream" || fileName !== void 0); - const parsedConType = cfg.parsedConType || []; - const defCharset = cfg.defCharset || "utf8"; - const preservePath = cfg.preservePath; - const fileOpts = { highWaterMark: cfg.fileHwm }; - for (i = 0, len = parsedConType.length; i < len; ++i) { - if (Array.isArray(parsedConType[i]) && RE_BOUNDARY.test(parsedConType[i][0])) { - boundary = parsedConType[i][1]; - break; - } + module2.exports = class FixedQueue { + constructor() { + this.head = this.tail = new FixedCircularBuffer(); } - function checkFinished() { - if (nends === 0 && finished && !boy._done) { - finished = false; - self2.end(); - } + isEmpty() { + return this.head.isEmpty(); } - if (typeof boundary !== "string") { - throw new Error("Multipart: Boundary not found"); + push(data) { + if (this.head.isFull()) { + this.head = this.head.next = new FixedCircularBuffer(); + } + this.head.push(data); } - const fieldSizeLimit = getLimit(limits, "fieldSize", 1 * 1024 * 1024); - const fileSizeLimit = getLimit(limits, "fileSize", Infinity); - const filesLimit = getLimit(limits, "files", Infinity); - const fieldsLimit = getLimit(limits, "fields", Infinity); - const partsLimit = getLimit(limits, "parts", Infinity); - const headerPairsLimit = getLimit(limits, "headerPairs", 2e3); - const headerSizeLimit = getLimit(limits, "headerSize", 80 * 1024); - let nfiles = 0; - let nfields = 0; - let nends = 0; - let curFile; - let curField; - let finished = false; - this._needDrain = false; - this._pause = false; - this._cb = void 0; - this._nparts = 0; - this._boy = boy; - const parserCfg = { - boundary, - maxHeaderPairs: headerPairsLimit, - maxHeaderSize: headerSizeLimit, - partHwm: fileOpts.highWaterMark, - highWaterMark: cfg.highWaterMark - }; - this.parser = new Dicer(parserCfg); - this.parser.on("drain", function() { - self2._needDrain = false; - if (self2._cb && !self2._pause) { - const cb = self2._cb; - self2._cb = void 0; - cb(); + shift() { + const tail = this.tail; + const next = tail.shift(); + if (tail.isEmpty() && tail.next !== null) { + this.tail = tail.next; } - }).on("part", function onPart(part) { - if (++self2._nparts > partsLimit) { - self2.parser.removeListener("part", onPart); - self2.parser.on("part", skipPart); - boy.hitPartsLimit = true; - boy.emit("partsLimit"); - return skipPart(part); - } - if (curField) { - const field = curField; - field.emit("end"); - field.removeAllListeners("end"); - } - part.on("header", function(header) { - let contype; - let fieldname; - let parsed; - let charset; - let encoding; - let filename; - let nsize = 0; - if (header["content-type"]) { - parsed = parseParams(header["content-type"][0]); - if (parsed[0]) { - contype = parsed[0].toLowerCase(); - for (i = 0, len = parsed.length; i < len; ++i) { - if (RE_CHARSET.test(parsed[i][0])) { - charset = parsed[i][1].toLowerCase(); - break; - } - } - } - } - if (contype === void 0) { - contype = "text/plain"; - } - if (charset === void 0) { - charset = defCharset; - } - if (header["content-disposition"]) { - parsed = parseParams(header["content-disposition"][0]); - if (!RE_FIELD.test(parsed[0])) { - return skipPart(part); - } - for (i = 0, len = parsed.length; i < len; ++i) { - if (RE_NAME.test(parsed[i][0])) { - fieldname = parsed[i][1]; - } else if (RE_FILENAME.test(parsed[i][0])) { - filename = parsed[i][1]; - if (!preservePath) { - filename = basename(filename); - } - } - } - } else { - return skipPart(part); - } - if (header["content-transfer-encoding"]) { - encoding = header["content-transfer-encoding"][0].toLowerCase(); - } else { - encoding = "7bit"; - } - let onData, onEnd; - if (isPartAFile(fieldname, contype, filename)) { - if (nfiles === filesLimit) { - if (!boy.hitFilesLimit) { - boy.hitFilesLimit = true; - boy.emit("filesLimit"); - } - return skipPart(part); - } - ++nfiles; - if (!boy._events.file) { - self2.parser._ignore(); - return; - } - ++nends; - const file = new FileStream(fileOpts); - curFile = file; - file.on("end", function() { - --nends; - self2._pause = false; - checkFinished(); - if (self2._cb && !self2._needDrain) { - const cb = self2._cb; - self2._cb = void 0; - cb(); - } - }); - file._read = function(n) { - if (!self2._pause) { - return; - } - self2._pause = false; - if (self2._cb && !self2._needDrain) { - const cb = self2._cb; - self2._cb = void 0; - cb(); - } - }; - boy.emit("file", fieldname, file, filename, encoding, contype); - onData = function(data) { - if ((nsize += data.length) > fileSizeLimit) { - const extralen = fileSizeLimit - nsize + data.length; - if (extralen > 0) { - file.push(data.slice(0, extralen)); - } - file.truncated = true; - file.bytesRead = fileSizeLimit; - part.removeAllListeners("data"); - file.emit("limit"); - return; - } else if (!file.push(data)) { - self2._pause = true; - } - file.bytesRead = nsize; - }; - onEnd = function() { - curFile = void 0; - file.push(null); - }; - } else { - if (nfields === fieldsLimit) { - if (!boy.hitFieldsLimit) { - boy.hitFieldsLimit = true; - boy.emit("fieldsLimit"); - } - return skipPart(part); - } - ++nfields; - ++nends; - let buffer = ""; - let truncated = false; - curField = part; - onData = function(data) { - if ((nsize += data.length) > fieldSizeLimit) { - const extralen = fieldSizeLimit - (nsize - data.length); - buffer += data.toString("binary", 0, extralen); - truncated = true; - part.removeAllListeners("data"); - } else { - buffer += data.toString("binary"); - } - }; - onEnd = function() { - curField = void 0; - if (buffer.length) { - buffer = decodeText(buffer, "binary", charset); - } - boy.emit("field", fieldname, buffer, false, truncated, encoding, contype); - --nends; - checkFinished(); - }; - } - part._readableState.sync = false; - part.on("data", onData); - part.on("end", onEnd); - }).on("error", function(err) { - if (curFile) { - curFile.emit("error", err); - } - }); - }).on("error", function(err) { - boy.emit("error", err); - }).on("finish", function() { - finished = true; - checkFinished(); - }); - } - Multipart.prototype.write = function(chunk, cb) { - const r = this.parser.write(chunk); - if (r && !this._pause) { - cb(); - } else { - this._needDrain = !r; - this._cb = cb; - } - }; - Multipart.prototype.end = function() { - const self2 = this; - if (self2.parser.writable) { - self2.parser.end(); - } else if (!self2._boy._done) { - process.nextTick(function() { - self2._boy._done = true; - self2._boy.emit("finish"); - }); + return next; } }; - function skipPart(part) { - part.resume(); - } - function FileStream(opts) { - Readable2.call(this, opts); - this.bytesRead = 0; - this.truncated = false; - } - inherits(FileStream, Readable2); - FileStream.prototype._read = function(n) { - }; - module2.exports = Multipart; } }); -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/Decoder.js -var require_Decoder = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/utils/Decoder.js"(exports, module2) { - "use strict"; - var RE_PLUS = /\+/g; - var HEX = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ]; - function Decoder() { - this.buffer = void 0; - } - Decoder.prototype.write = function(str) { - str = str.replace(RE_PLUS, " "); - let res = ""; - let i = 0; - let p = 0; - const len = str.length; - for (; i < len; ++i) { - if (this.buffer !== void 0) { - if (!HEX[str.charCodeAt(i)]) { - res += "%" + this.buffer; - this.buffer = void 0; - --i; - } else { - this.buffer += str[i]; - ++p; - if (this.buffer.length === 2) { - res += String.fromCharCode(parseInt(this.buffer, 16)); - this.buffer = void 0; - } - } - } else if (str[i] === "%") { - if (i > p) { - res += str.substring(p, i); - p = i; - } - this.buffer = ""; - ++p; - } +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/pool-stats.js +var require_pool_stats = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/pool-stats.js"(exports, module2) { + var { kFree, kConnected, kPending, kQueued, kRunning, kSize } = require_symbols(); + var kPool = Symbol("pool"); + var PoolStats = class { + constructor(pool) { + this[kPool] = pool; + } + get connected() { + return this[kPool][kConnected]; } - if (p < len && this.buffer === void 0) { - res += str.substring(p); + get free() { + return this[kPool][kFree]; + } + get pending() { + return this[kPool][kPending]; + } + get queued() { + return this[kPool][kQueued]; + } + get running() { + return this[kPool][kRunning]; + } + get size() { + return this[kPool][kSize]; } - return res; - }; - Decoder.prototype.reset = function() { - this.buffer = void 0; }; - module2.exports = Decoder; + module2.exports = PoolStats; } }); -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/types/urlencoded.js -var require_urlencoded = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/types/urlencoded.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/pool-base.js +var require_pool_base = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/pool-base.js"(exports, module2) { "use strict"; - var Decoder = require_Decoder(); - var decodeText = require_decodeText(); - var getLimit = require_getLimit(); - var RE_CHARSET = /^charset$/i; - UrlEncoded.detect = /^application\/x-www-form-urlencoded/i; - function UrlEncoded(boy, cfg) { - const limits = cfg.limits; - const parsedConType = cfg.parsedConType; - this.boy = boy; - this.fieldSizeLimit = getLimit(limits, "fieldSize", 1 * 1024 * 1024); - this.fieldNameSizeLimit = getLimit(limits, "fieldNameSize", 100); - this.fieldsLimit = getLimit(limits, "fields", Infinity); - let charset; - for (var i = 0, len = parsedConType.length; i < len; ++i) { - if (Array.isArray(parsedConType[i]) && RE_CHARSET.test(parsedConType[i][0])) { - charset = parsedConType[i][1].toLowerCase(); - break; - } - } - if (charset === void 0) { - charset = cfg.defCharset || "utf8"; - } - this.decoder = new Decoder(); - this.charset = charset; - this._fields = 0; - this._state = "key"; - this._checkingBytes = true; - this._bytesKey = 0; - this._bytesVal = 0; - this._key = ""; - this._val = ""; - this._keyTrunc = false; - this._valTrunc = false; - this._hitLimit = false; - } - UrlEncoded.prototype.write = function(data, cb) { - if (this._fields === this.fieldsLimit) { - if (!this.boy.hitFieldsLimit) { - this.boy.hitFieldsLimit = true; - this.boy.emit("fieldsLimit"); - } - return cb(); - } - let idxeq; - let idxamp; - let i; - let p = 0; - const len = data.length; - while (p < len) { - if (this._state === "key") { - idxeq = idxamp = void 0; - for (i = p; i < len; ++i) { - if (!this._checkingBytes) { - ++p; - } - if (data[i] === 61) { - idxeq = i; - break; - } else if (data[i] === 38) { - idxamp = i; - break; - } - if (this._checkingBytes && this._bytesKey === this.fieldNameSizeLimit) { - this._hitLimit = true; + var DispatcherBase = require_dispatcher_base(); + var FixedQueue = require_fixed_queue(); + var { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = require_symbols(); + var PoolStats = require_pool_stats(); + var kClients = Symbol("clients"); + var kNeedDrain = Symbol("needDrain"); + var kQueue = Symbol("queue"); + var kClosedResolve = Symbol("closed resolve"); + var kOnDrain = Symbol("onDrain"); + var kOnConnect = Symbol("onConnect"); + var kOnDisconnect = Symbol("onDisconnect"); + var kOnConnectionError = Symbol("onConnectionError"); + var kGetDispatcher = Symbol("get dispatcher"); + var kAddClient = Symbol("add client"); + var kRemoveClient = Symbol("remove client"); + var kStats = Symbol("stats"); + var PoolBase = class extends DispatcherBase { + constructor() { + super(); + this[kQueue] = new FixedQueue(); + this[kClients] = []; + this[kQueued] = 0; + const pool = this; + this[kOnDrain] = function onDrain(origin, targets) { + const queue = pool[kQueue]; + let needDrain = false; + while (!needDrain) { + const item = queue.shift(); + if (!item) { break; - } else if (this._checkingBytes) { - ++this._bytesKey; - } - } - if (idxeq !== void 0) { - if (idxeq > p) { - this._key += this.decoder.write(data.toString("binary", p, idxeq)); - } - this._state = "val"; - this._hitLimit = false; - this._checkingBytes = true; - this._val = ""; - this._bytesVal = 0; - this._valTrunc = false; - this.decoder.reset(); - p = idxeq + 1; - } else if (idxamp !== void 0) { - ++this._fields; - let key; - const keyTrunc = this._keyTrunc; - if (idxamp > p) { - key = this._key += this.decoder.write(data.toString("binary", p, idxamp)); - } else { - key = this._key; - } - this._hitLimit = false; - this._checkingBytes = true; - this._key = ""; - this._bytesKey = 0; - this._keyTrunc = false; - this.decoder.reset(); - if (key.length) { - this.boy.emit( - "field", - decodeText(key, "binary", this.charset), - "", - keyTrunc, - false - ); - } - p = idxamp + 1; - if (this._fields === this.fieldsLimit) { - return cb(); - } - } else if (this._hitLimit) { - if (i > p) { - this._key += this.decoder.write(data.toString("binary", p, i)); - } - p = i; - if ((this._bytesKey = this._key.length) === this.fieldNameSizeLimit) { - this._checkingBytes = false; - this._keyTrunc = true; } - } else { - if (p < len) { - this._key += this.decoder.write(data.toString("binary", p)); - } - p = len; + pool[kQueued]--; + needDrain = !this.dispatch(item.opts, item.handler); } - } else { - idxamp = void 0; - for (i = p; i < len; ++i) { - if (!this._checkingBytes) { - ++p; - } - if (data[i] === 38) { - idxamp = i; - break; - } - if (this._checkingBytes && this._bytesVal === this.fieldSizeLimit) { - this._hitLimit = true; - break; - } else if (this._checkingBytes) { - ++this._bytesVal; - } + this[kNeedDrain] = needDrain; + if (!this[kNeedDrain] && pool[kNeedDrain]) { + pool[kNeedDrain] = false; + pool.emit("drain", origin, [pool, ...targets]); } - if (idxamp !== void 0) { - ++this._fields; - if (idxamp > p) { - this._val += this.decoder.write(data.toString("binary", p, idxamp)); - } - this.boy.emit( - "field", - decodeText(this._key, "binary", this.charset), - decodeText(this._val, "binary", this.charset), - this._keyTrunc, - this._valTrunc - ); - this._state = "key"; - this._hitLimit = false; - this._checkingBytes = true; - this._key = ""; - this._bytesKey = 0; - this._keyTrunc = false; - this.decoder.reset(); - p = idxamp + 1; - if (this._fields === this.fieldsLimit) { - return cb(); - } - } else if (this._hitLimit) { - if (i > p) { - this._val += this.decoder.write(data.toString("binary", p, i)); - } - p = i; - if (this._val === "" && this.fieldSizeLimit === 0 || (this._bytesVal = this._val.length) === this.fieldSizeLimit) { - this._checkingBytes = false; - this._valTrunc = true; - } - } else { - if (p < len) { - this._val += this.decoder.write(data.toString("binary", p)); - } - p = len; + if (pool[kClosedResolve] && queue.isEmpty()) { + Promise.all(pool[kClients].map((c) => c.close())).then(pool[kClosedResolve]); } + }; + this[kOnConnect] = (origin, targets) => { + pool.emit("connect", origin, [pool, ...targets]); + }; + this[kOnDisconnect] = (origin, targets, err) => { + pool.emit("disconnect", origin, [pool, ...targets], err); + }; + this[kOnConnectionError] = (origin, targets, err) => { + pool.emit("connectionError", origin, [pool, ...targets], err); + }; + this[kStats] = new PoolStats(this); + } + get [kBusy]() { + return this[kNeedDrain]; + } + get [kConnected]() { + return this[kClients].filter((client) => client[kConnected]).length; + } + get [kFree]() { + return this[kClients].filter((client) => client[kConnected] && !client[kNeedDrain]).length; + } + get [kPending]() { + let ret = this[kQueued]; + for (const { [kPending]: pending } of this[kClients]) { + ret += pending; } + return ret; } - cb(); - }; - UrlEncoded.prototype.end = function() { - if (this.boy._done) { - return; + get [kRunning]() { + let ret = 0; + for (const { [kRunning]: running } of this[kClients]) { + ret += running; + } + return ret; } - if (this._state === "key" && this._key.length > 0) { - this.boy.emit( - "field", - decodeText(this._key, "binary", this.charset), - "", - this._keyTrunc, - false - ); - } else if (this._state === "val") { - this.boy.emit( - "field", - decodeText(this._key, "binary", this.charset), - decodeText(this._val, "binary", this.charset), - this._keyTrunc, - this._valTrunc - ); + get [kSize]() { + let ret = this[kQueued]; + for (const { [kSize]: size } of this[kClients]) { + ret += size; + } + return ret; } - this.boy._done = true; - this.boy.emit("finish"); - }; - module2.exports = UrlEncoded; - } -}); - -// .yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/main.js -var require_main = __commonJS({ - ".yarn/cache/@fastify-busboy-npm-2.1.0-960844a007-7bb641080a.zip/node_modules/@fastify/busboy/lib/main.js"(exports, module2) { - "use strict"; - var WritableStream = require("node:stream").Writable; - var { inherits } = require("node:util"); - var Dicer = require_Dicer(); - var MultipartParser = require_multipart(); - var UrlencodedParser = require_urlencoded(); - var parseParams = require_parseParams(); - function Busboy(opts) { - if (!(this instanceof Busboy)) { - return new Busboy(opts); - } - if (typeof opts !== "object") { - throw new TypeError("Busboy expected an options-Object."); - } - if (typeof opts.headers !== "object") { - throw new TypeError("Busboy expected an options-Object with headers-attribute."); - } - if (typeof opts.headers["content-type"] !== "string") { - throw new TypeError("Missing Content-Type-header."); - } - const { - headers, - ...streamOptions - } = opts; - this.opts = { - autoDestroy: false, - ...streamOptions - }; - WritableStream.call(this, this.opts); - this._done = false; - this._parser = this.getParserByHeaders(headers); - this._finished = false; - } - inherits(Busboy, WritableStream); - Busboy.prototype.emit = function(ev) { - if (ev === "finish") { - if (!this._done) { - this._parser?.end(); - return; - } else if (this._finished) { - return; + get stats() { + return this[kStats]; + } + async [kClose]() { + if (this[kQueue].isEmpty()) { + return Promise.all(this[kClients].map((c) => c.close())); + } else { + return new Promise((resolve) => { + this[kClosedResolve] = resolve; + }); } - this._finished = true; } - WritableStream.prototype.emit.apply(this, arguments); - }; - Busboy.prototype.getParserByHeaders = function(headers) { - const parsed = parseParams(headers["content-type"]); - const cfg = { - defCharset: this.opts.defCharset, - fileHwm: this.opts.fileHwm, - headers, - highWaterMark: this.opts.highWaterMark, - isPartAFile: this.opts.isPartAFile, - limits: this.opts.limits, - parsedConType: parsed, - preservePath: this.opts.preservePath - }; - if (MultipartParser.detect.test(parsed[0])) { - return new MultipartParser(this, cfg); + async [kDestroy](err) { + while (true) { + const item = this[kQueue].shift(); + if (!item) { + break; + } + item.handler.onError(err); + } + return Promise.all(this[kClients].map((c) => c.destroy(err))); + } + [kDispatch](opts, handler) { + const dispatcher = this[kGetDispatcher](); + if (!dispatcher) { + this[kNeedDrain] = true; + this[kQueue].push({ opts, handler }); + this[kQueued]++; + } else if (!dispatcher.dispatch(opts, handler)) { + dispatcher[kNeedDrain] = true; + this[kNeedDrain] = !this[kGetDispatcher](); + } + return !this[kNeedDrain]; + } + [kAddClient](client) { + client.on("drain", this[kOnDrain]).on("connect", this[kOnConnect]).on("disconnect", this[kOnDisconnect]).on("connectionError", this[kOnConnectionError]); + this[kClients].push(client); + if (this[kNeedDrain]) { + queueMicrotask(() => { + if (this[kNeedDrain]) { + this[kOnDrain](client[kUrl], [this, client]); + } + }); + } + return this; } - if (UrlencodedParser.detect.test(parsed[0])) { - return new UrlencodedParser(this, cfg); + [kRemoveClient](client) { + client.close(() => { + const idx = this[kClients].indexOf(client); + if (idx !== -1) { + this[kClients].splice(idx, 1); + } + }); + this[kNeedDrain] = this[kClients].some((dispatcher) => !dispatcher[kNeedDrain] && dispatcher.closed !== true && dispatcher.destroyed !== true); } - throw new Error("Unsupported Content-Type."); }; - Busboy.prototype._write = function(chunk, encoding, cb) { - this._parser.write(chunk, cb); + module2.exports = { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher }; - module2.exports = Busboy; - module2.exports.default = Busboy; - module2.exports.Busboy = Busboy; - module2.exports.Dicer = Dicer; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/constants.js -var require_constants3 = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/constants.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/diagnostics.js +var require_diagnostics = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/diagnostics.js"(exports, module2) { "use strict"; - var corsSafeListedMethods = ["GET", "HEAD", "POST"]; - var corsSafeListedMethodsSet = new Set(corsSafeListedMethods); - var nullBodyStatus = [101, 204, 205, 304]; - var redirectStatus = [301, 302, 303, 307, 308]; - var redirectStatusSet = new Set(redirectStatus); - var badPorts = [ - "1", - "7", - "9", - "11", - "13", - "15", - "17", - "19", - "20", - "21", - "22", - "23", - "25", - "37", - "42", - "43", - "53", - "69", - "77", - "79", - "87", - "95", - "101", - "102", - "103", - "104", - "109", - "110", - "111", - "113", - "115", - "117", - "119", - "123", - "135", - "137", - "139", - "143", - "161", - "179", - "389", - "427", - "465", - "512", - "513", - "514", - "515", - "526", - "530", - "531", - "532", - "540", - "548", - "554", - "556", - "563", - "587", - "601", - "636", - "989", - "990", - "993", - "995", - "1719", - "1720", - "1723", - "2049", - "3659", - "4045", - "5060", - "5061", - "6000", - "6566", - "6665", - "6666", - "6667", - "6668", - "6669", - "6697", - "10080" - ]; - var badPortsSet = new Set(badPorts); - var referrerPolicy = [ - "", - "no-referrer", - "no-referrer-when-downgrade", - "same-origin", - "origin", - "strict-origin", - "origin-when-cross-origin", - "strict-origin-when-cross-origin", - "unsafe-url" - ]; - var referrerPolicySet = new Set(referrerPolicy); - var requestRedirect = ["follow", "manual", "error"]; - var safeMethods = ["GET", "HEAD", "OPTIONS", "TRACE"]; - var safeMethodsSet = new Set(safeMethods); - var requestMode = ["navigate", "same-origin", "no-cors", "cors"]; - var requestCredentials = ["omit", "same-origin", "include"]; - var requestCache = [ - "default", - "no-store", - "reload", - "no-cache", - "force-cache", - "only-if-cached" - ]; - var requestBodyHeader = [ - "content-encoding", - "content-language", - "content-location", - "content-type", - // See https://github.com/nodejs/undici/issues/2021 - // 'Content-Length' is a forbidden header name, which is typically - // removed in the Headers implementation. However, undici doesn't - // filter out headers, so we add it here. - "content-length" - ]; - var requestDuplex = [ - "half" - ]; - var forbiddenMethods = ["CONNECT", "TRACE", "TRACK"]; - var forbiddenMethodsSet = new Set(forbiddenMethods); - var subresource = [ - "audio", - "audioworklet", - "font", - "image", - "manifest", - "paintworklet", - "script", - "style", - "track", - "video", - "xslt", - "" - ]; - var subresourceSet = new Set(subresource); - module2.exports = { - subresource, - forbiddenMethods, - requestBodyHeader, - referrerPolicy, - requestRedirect, - requestMode, - requestCredentials, - requestCache, - redirectStatus, - corsSafeListedMethods, - nullBodyStatus, - safeMethods, - badPorts, - requestDuplex, - subresourceSet, - badPortsSet, - redirectStatusSet, - corsSafeListedMethodsSet, - safeMethodsSet, - forbiddenMethodsSet, - referrerPolicySet + var diagnosticsChannel = require("node:diagnostics_channel"); + var util = require("node:util"); + var undiciDebugLog = util.debuglog("undici"); + var fetchDebuglog = util.debuglog("fetch"); + var websocketDebuglog = util.debuglog("websocket"); + var isClientSet = false; + var channels = { + // Client + beforeConnect: diagnosticsChannel.channel("undici:client:beforeConnect"), + connected: diagnosticsChannel.channel("undici:client:connected"), + connectError: diagnosticsChannel.channel("undici:client:connectError"), + sendHeaders: diagnosticsChannel.channel("undici:client:sendHeaders"), + // Request + create: diagnosticsChannel.channel("undici:request:create"), + bodySent: diagnosticsChannel.channel("undici:request:bodySent"), + headers: diagnosticsChannel.channel("undici:request:headers"), + trailers: diagnosticsChannel.channel("undici:request:trailers"), + error: diagnosticsChannel.channel("undici:request:error"), + // WebSocket + open: diagnosticsChannel.channel("undici:websocket:open"), + close: diagnosticsChannel.channel("undici:websocket:close"), + socketError: diagnosticsChannel.channel("undici:websocket:socket_error"), + ping: diagnosticsChannel.channel("undici:websocket:ping"), + pong: diagnosticsChannel.channel("undici:websocket:pong") }; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/global.js -var require_global = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/global.js"(exports, module2) { - "use strict"; - var globalOrigin = Symbol.for("undici.globalOrigin.1"); - function getGlobalOrigin() { - return globalThis[globalOrigin]; + if (undiciDebugLog.enabled || fetchDebuglog.enabled) { + const debuglog = fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog; + diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => { + const { + connectParams: { version: version2, protocol, port, host } + } = evt; + debuglog( + "connecting to %s using %s%s", + `${host}${port ? `:${port}` : ""}`, + protocol, + version2 + ); + }); + diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => { + const { + connectParams: { version: version2, protocol, port, host } + } = evt; + debuglog( + "connected to %s using %s%s", + `${host}${port ? `:${port}` : ""}`, + protocol, + version2 + ); + }); + diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => { + const { + connectParams: { version: version2, protocol, port, host }, + error + } = evt; + debuglog( + "connection to %s using %s%s errored - %s", + `${host}${port ? `:${port}` : ""}`, + protocol, + version2, + error.message + ); + }); + diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { + const { + request: { method, path: path10, origin } + } = evt; + debuglog("sending request to %s %s/%s", method, origin, path10); + }); + diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => { + const { + request: { method, path: path10, origin }, + response: { statusCode } + } = evt; + debuglog( + "received response to %s %s/%s - HTTP %d", + method, + origin, + path10, + statusCode + ); + }); + diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => { + const { + request: { method, path: path10, origin } + } = evt; + debuglog("trailers received from %s %s/%s", method, origin, path10); + }); + diagnosticsChannel.channel("undici:request:error").subscribe((evt) => { + const { + request: { method, path: path10, origin }, + error + } = evt; + debuglog( + "request to %s %s/%s errored - %s", + method, + origin, + path10, + error.message + ); + }); + isClientSet = true; } - function setGlobalOrigin(newOrigin) { - if (newOrigin === void 0) { - Object.defineProperty(globalThis, globalOrigin, { - value: void 0, - writable: true, - enumerable: false, - configurable: false + if (websocketDebuglog.enabled) { + if (!isClientSet) { + const debuglog = undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog; + diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => { + const { + connectParams: { version: version2, protocol, port, host } + } = evt; + debuglog( + "connecting to %s%s using %s%s", + host, + port ? `:${port}` : "", + protocol, + version2 + ); + }); + diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => { + const { + connectParams: { version: version2, protocol, port, host } + } = evt; + debuglog( + "connected to %s%s using %s%s", + host, + port ? `:${port}` : "", + protocol, + version2 + ); + }); + diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => { + const { + connectParams: { version: version2, protocol, port, host }, + error + } = evt; + debuglog( + "connection to %s%s using %s%s errored - %s", + host, + port ? `:${port}` : "", + protocol, + version2, + error.message + ); + }); + diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { + const { + request: { method, path: path10, origin } + } = evt; + debuglog("sending request to %s %s/%s", method, origin, path10); }); - return; - } - const parsedURL = new URL(newOrigin); - if (parsedURL.protocol !== "http:" && parsedURL.protocol !== "https:") { - throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`); } - Object.defineProperty(globalThis, globalOrigin, { - value: parsedURL, - writable: true, - enumerable: false, - configurable: false + diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => { + const { + address: { address, port } + } = evt; + websocketDebuglog("connection opened %s%s", address, port ? `:${port}` : ""); + }); + diagnosticsChannel.channel("undici:websocket:close").subscribe((evt) => { + const { websocket, code, reason } = evt; + websocketDebuglog( + "closed connection to %s - %s %s", + websocket.url, + code, + reason + ); + }); + diagnosticsChannel.channel("undici:websocket:socket_error").subscribe((err) => { + websocketDebuglog("connection errored - %s", err.message); + }); + diagnosticsChannel.channel("undici:websocket:ping").subscribe((evt) => { + websocketDebuglog("ping received"); + }); + diagnosticsChannel.channel("undici:websocket:pong").subscribe((evt) => { + websocketDebuglog("pong received"); }); } module2.exports = { - getGlobalOrigin, - setGlobalOrigin + channels }; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/dataURL.js -var require_dataURL = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/dataURL.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/request.js +var require_request = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/request.js"(exports, module2) { + "use strict"; + var { + InvalidArgumentError, + NotSupportedError + } = require_errors(); var assert3 = require("node:assert"); - var encoder = new TextEncoder(); - var HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+-.^_|~A-Za-z0-9]+$/; - var HTTP_WHITESPACE_REGEX = /[\u000A|\u000D|\u0009|\u0020]/; - var ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g; - var HTTP_QUOTED_STRING_TOKENS = /[\u0009|\u0020-\u007E|\u0080-\u00FF]/; - function dataURLProcessor(dataURL) { - assert3(dataURL.protocol === "data:"); - let input = URLSerializer(dataURL, true); - input = input.slice(5); - const position = { position: 0 }; - let mimeType = collectASequenceOfCodePointsFast( - ",", - input, - position - ); - const mimeTypeLength = mimeType.length; - mimeType = removeASCIIWhitespace(mimeType, true, true); - if (position.position >= input.length) { - return "failure"; + var { + isValidHTTPToken, + isValidHeaderChar, + isStream, + destroy, + isBuffer, + isFormDataLike, + isIterable, + isBlobLike, + buildURL, + validateHandler, + getServerName + } = require_util(); + var { channels } = require_diagnostics(); + var { headerNameLowerCasedRecord } = require_constants2(); + var invalidPathRegex = /[^\u0021-\u00ff]/; + var kHandler = Symbol("handler"); + var Request = class { + constructor(origin, { + path: path10, + method, + body, + headers, + query, + idempotent, + blocking, + upgrade, + headersTimeout, + bodyTimeout, + reset, + throwOnError, + expectContinue, + servername + }, handler) { + if (typeof path10 !== "string") { + throw new InvalidArgumentError("path must be a string"); + } else if (path10[0] !== "/" && !(path10.startsWith("http://") || path10.startsWith("https://")) && method !== "CONNECT") { + throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); + } else if (invalidPathRegex.exec(path10) !== null) { + throw new InvalidArgumentError("invalid request path"); + } + if (typeof method !== "string") { + throw new InvalidArgumentError("method must be a string"); + } else if (!isValidHTTPToken(method)) { + throw new InvalidArgumentError("invalid request method"); + } + if (upgrade && typeof upgrade !== "string") { + throw new InvalidArgumentError("upgrade must be a string"); + } + if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError("invalid headersTimeout"); + } + if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError("invalid bodyTimeout"); + } + if (reset != null && typeof reset !== "boolean") { + throw new InvalidArgumentError("invalid reset"); + } + if (expectContinue != null && typeof expectContinue !== "boolean") { + throw new InvalidArgumentError("invalid expectContinue"); + } + this.headersTimeout = headersTimeout; + this.bodyTimeout = bodyTimeout; + this.throwOnError = throwOnError === true; + this.method = method; + this.abort = null; + if (body == null) { + this.body = null; + } else if (isStream(body)) { + this.body = body; + const rState = this.body._readableState; + if (!rState || !rState.autoDestroy) { + this.endHandler = function autoDestroy() { + destroy(this); + }; + this.body.on("end", this.endHandler); + } + this.errorHandler = (err) => { + if (this.abort) { + this.abort(err); + } else { + this.error = err; + } + }; + this.body.on("error", this.errorHandler); + } else if (isBuffer(body)) { + this.body = body.byteLength ? body : null; + } else if (ArrayBuffer.isView(body)) { + this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null; + } else if (body instanceof ArrayBuffer) { + this.body = body.byteLength ? Buffer.from(body) : null; + } else if (typeof body === "string") { + this.body = body.length ? Buffer.from(body) : null; + } else if (isFormDataLike(body) || isIterable(body) || isBlobLike(body)) { + this.body = body; + } else { + throw new InvalidArgumentError("body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable"); + } + this.completed = false; + this.aborted = false; + this.upgrade = upgrade || null; + this.path = query ? buildURL(path10, query) : path10; + this.origin = origin; + this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; + this.blocking = blocking == null ? false : blocking; + this.reset = reset == null ? null : reset; + this.host = null; + this.contentLength = null; + this.contentType = null; + this.headers = []; + this.expectContinue = expectContinue != null ? expectContinue : false; + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError("headers array must be even"); + } + for (let i = 0; i < headers.length; i += 2) { + processHeader(this, headers[i], headers[i + 1]); + } + } else if (headers && typeof headers === "object") { + if (headers[Symbol.iterator]) { + for (const header of headers) { + if (!Array.isArray(header) || header.length !== 2) { + throw new InvalidArgumentError("headers must be in key-value pair format"); + } + processHeader(this, header[0], header[1]); + } + } else { + const keys = Object.keys(headers); + for (let i = 0; i < keys.length; ++i) { + processHeader(this, keys[i], headers[keys[i]]); + } + } + } else if (headers != null) { + throw new InvalidArgumentError("headers must be an object or an array"); + } + validateHandler(handler, method, upgrade); + this.servername = servername || getServerName(this.host); + this[kHandler] = handler; + if (channels.create.hasSubscribers) { + channels.create.publish({ request: this }); + } } - position.position++; - const encodedBody = input.slice(mimeTypeLength + 1); - let body = stringPercentDecode(encodedBody); - if (/;(\u0020){0,}base64$/i.test(mimeType)) { - const stringBody = isomorphicDecode(body); - body = forgivingBase64(stringBody); - if (body === "failure") { - return "failure"; + onBodySent(chunk) { + if (this[kHandler].onBodySent) { + try { + return this[kHandler].onBodySent(chunk); + } catch (err) { + this.abort(err); + } } - mimeType = mimeType.slice(0, -6); - mimeType = mimeType.replace(/(\u0020)+$/, ""); - mimeType = mimeType.slice(0, -1); } - if (mimeType.startsWith(";")) { - mimeType = "text/plain" + mimeType; + onRequestSent() { + if (channels.bodySent.hasSubscribers) { + channels.bodySent.publish({ request: this }); + } + if (this[kHandler].onRequestSent) { + try { + return this[kHandler].onRequestSent(); + } catch (err) { + this.abort(err); + } + } } - let mimeTypeRecord = parseMIMEType(mimeType); - if (mimeTypeRecord === "failure") { - mimeTypeRecord = parseMIMEType("text/plain;charset=US-ASCII"); + onConnect(abort) { + assert3(!this.aborted); + assert3(!this.completed); + if (this.error) { + abort(this.error); + } else { + this.abort = abort; + return this[kHandler].onConnect(abort); + } } - return { mimeType: mimeTypeRecord, body }; - } - function URLSerializer(url, excludeFragment = false) { - if (!excludeFragment) { - return url.href; + onResponseStarted() { + return this[kHandler].onResponseStarted?.(); } - const href = url.href; - const hashLength = url.hash.length; - const serialized = hashLength === 0 ? href : href.substring(0, href.length - hashLength); - if (!hashLength && href.endsWith("#")) { - return serialized.slice(0, -1); + onHeaders(statusCode, headers, resume, statusText) { + assert3(!this.aborted); + assert3(!this.completed); + if (channels.headers.hasSubscribers) { + channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }); + } + try { + return this[kHandler].onHeaders(statusCode, headers, resume, statusText); + } catch (err) { + this.abort(err); + } } - return serialized; - } - function collectASequenceOfCodePoints(condition, input, position) { - let result = ""; - while (position.position < input.length && condition(input[position.position])) { - result += input[position.position]; - position.position++; + onData(chunk) { + assert3(!this.aborted); + assert3(!this.completed); + try { + return this[kHandler].onData(chunk); + } catch (err) { + this.abort(err); + return false; + } } - return result; - } - function collectASequenceOfCodePointsFast(char, input, position) { - const idx = input.indexOf(char, position.position); - const start = position.position; - if (idx === -1) { - position.position = input.length; - return input.slice(start); - } - position.position = idx; - return input.slice(start, position.position); - } - function stringPercentDecode(input) { - const bytes = encoder.encode(input); - return percentDecode(bytes); - } - function isHexCharByte(byte) { - return byte >= 48 && byte <= 57 || byte >= 65 && byte <= 70 || byte >= 97 && byte <= 102; - } - function hexByteToNumber(byte) { - return ( - // 0-9 - byte >= 48 && byte <= 57 ? byte - 48 : (byte & 223) - 55 - ); - } - function percentDecode(input) { - const length = input.length; - const output = new Uint8Array(length); - let j = 0; - for (let i = 0; i < length; ++i) { - const byte = input[i]; - if (byte !== 37) { - output[j++] = byte; - } else if (byte === 37 && !(isHexCharByte(input[i + 1]) && isHexCharByte(input[i + 2]))) { - output[j++] = 37; - } else { - output[j++] = hexByteToNumber(input[i + 1]) << 4 | hexByteToNumber(input[i + 2]); - i += 2; - } - } - return length === j ? output : output.subarray(0, j); - } - function parseMIMEType(input) { - input = removeHTTPWhitespace(input, true, true); - const position = { position: 0 }; - const type = collectASequenceOfCodePointsFast( - "/", - input, - position - ); - if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { - return "failure"; - } - if (position.position > input.length) { - return "failure"; - } - position.position++; - let subtype = collectASequenceOfCodePointsFast( - ";", - input, - position - ); - subtype = removeHTTPWhitespace(subtype, false, true); - if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { - return "failure"; + onUpgrade(statusCode, headers, socket) { + assert3(!this.aborted); + assert3(!this.completed); + return this[kHandler].onUpgrade(statusCode, headers, socket); } - const typeLowercase = type.toLowerCase(); - const subtypeLowercase = subtype.toLowerCase(); - const mimeType = { - type: typeLowercase, - subtype: subtypeLowercase, - /** @type {Map} */ - parameters: /* @__PURE__ */ new Map(), - // https://mimesniff.spec.whatwg.org/#mime-type-essence - essence: `${typeLowercase}/${subtypeLowercase}` - }; - while (position.position < input.length) { - position.position++; - collectASequenceOfCodePoints( - // https://fetch.spec.whatwg.org/#http-whitespace - (char) => HTTP_WHITESPACE_REGEX.test(char), - input, - position - ); - let parameterName = collectASequenceOfCodePoints( - (char) => char !== ";" && char !== "=", - input, - position - ); - parameterName = parameterName.toLowerCase(); - if (position.position < input.length) { - if (input[position.position] === ";") { - continue; - } - position.position++; + onComplete(trailers) { + this.onFinally(); + assert3(!this.aborted); + this.completed = true; + if (channels.trailers.hasSubscribers) { + channels.trailers.publish({ request: this, trailers }); } - if (position.position > input.length) { - break; + try { + return this[kHandler].onComplete(trailers); + } catch (err) { + this.onError(err); } - let parameterValue = null; - if (input[position.position] === '"') { - parameterValue = collectAnHTTPQuotedString(input, position, true); - collectASequenceOfCodePointsFast( - ";", - input, - position - ); - } else { - parameterValue = collectASequenceOfCodePointsFast( - ";", - input, - position - ); - parameterValue = removeHTTPWhitespace(parameterValue, false, true); - if (parameterValue.length === 0) { - continue; - } + } + onError(error) { + this.onFinally(); + if (channels.error.hasSubscribers) { + channels.error.publish({ request: this, error }); } - if (parameterName.length !== 0 && HTTP_TOKEN_CODEPOINTS.test(parameterName) && (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && !mimeType.parameters.has(parameterName)) { - mimeType.parameters.set(parameterName, parameterValue); + if (this.aborted) { + return; } + this.aborted = true; + return this[kHandler].onError(error); } - return mimeType; - } - function forgivingBase64(data) { - data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, ""); - let dataLength = data.length; - if (dataLength % 4 === 0) { - if (data.charCodeAt(dataLength - 1) === 61) { - --dataLength; - if (data.charCodeAt(dataLength - 1) === 61) { - --dataLength; - } + onFinally() { + if (this.errorHandler) { + this.body.off("error", this.errorHandler); + this.errorHandler = null; + } + if (this.endHandler) { + this.body.off("end", this.endHandler); + this.endHandler = null; } } - if (dataLength % 4 === 1) { - return "failure"; + addHeader(key, value) { + processHeader(this, key, value); + return this; } - if (/[^+/0-9A-Za-z]/.test(data.length === dataLength ? data : data.substring(0, dataLength))) { - return "failure"; + }; + function processHeader(request, key, val) { + if (val && (typeof val === "object" && !Array.isArray(val))) { + throw new InvalidArgumentError(`invalid ${key} header`); + } else if (val === void 0) { + return; } - const buffer = Buffer.from(data, "base64"); - return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength); - } - function collectAnHTTPQuotedString(input, position, extractValue) { - const positionStart = position.position; - let value = ""; - assert3(input[position.position] === '"'); - position.position++; - while (true) { - value += collectASequenceOfCodePoints( - (char) => char !== '"' && char !== "\\", - input, - position - ); - if (position.position >= input.length) { - break; + let headerName = headerNameLowerCasedRecord[key]; + if (headerName === void 0) { + headerName = key.toLowerCase(); + if (headerNameLowerCasedRecord[headerName] === void 0 && !isValidHTTPToken(headerName)) { + throw new InvalidArgumentError("invalid header key"); } - const quoteOrBackslash = input[position.position]; - position.position++; - if (quoteOrBackslash === "\\") { - if (position.position >= input.length) { - value += "\\"; - break; + } + if (Array.isArray(val)) { + const arr = []; + for (let i = 0; i < val.length; i++) { + if (typeof val[i] === "string") { + if (!isValidHeaderChar(val[i])) { + throw new InvalidArgumentError(`invalid ${key} header`); + } + arr.push(val[i]); + } else if (val[i] === null) { + arr.push(""); + } else if (typeof val[i] === "object") { + throw new InvalidArgumentError(`invalid ${key} header`); + } else { + arr.push(`${val[i]}`); } - value += input[position.position]; - position.position++; - } else { - assert3(quoteOrBackslash === '"'); - break; } + val = arr; + } else if (typeof val === "string") { + if (!isValidHeaderChar(val)) { + throw new InvalidArgumentError(`invalid ${key} header`); + } + } else if (val === null) { + val = ""; + } else if (typeof val === "object") { + throw new InvalidArgumentError(`invalid ${key} header`); + } else { + val = `${val}`; } - if (extractValue) { - return value; - } - return input.slice(positionStart, position.position); - } - function serializeAMimeType(mimeType) { - assert3(mimeType !== "failure"); - const { parameters, essence } = mimeType; - let serialization = essence; - for (let [name, value] of parameters.entries()) { - serialization += ";"; - serialization += name; - serialization += "="; - if (!HTTP_TOKEN_CODEPOINTS.test(value)) { - value = value.replace(/(\\|")/g, "\\$1"); - value = '"' + value; - value += '"'; + if (request.host === null && headerName === "host") { + if (typeof val !== "string") { + throw new InvalidArgumentError("invalid host header"); } - serialization += value; + request.host = val; + } else if (request.contentLength === null && headerName === "content-length") { + request.contentLength = parseInt(val, 10); + if (!Number.isFinite(request.contentLength)) { + throw new InvalidArgumentError("invalid content-length header"); + } + } else if (request.contentType === null && headerName === "content-type") { + request.contentType = val; + request.headers.push(key, val); + } else if (headerName === "transfer-encoding" || headerName === "keep-alive" || headerName === "upgrade") { + throw new InvalidArgumentError(`invalid ${headerName} header`); + } else if (headerName === "connection") { + const value = typeof val === "string" ? val.toLowerCase() : null; + if (value !== "close" && value !== "keep-alive") { + throw new InvalidArgumentError("invalid connection header"); + } + if (value === "close") { + request.reset = true; + } + } else if (headerName === "expect") { + throw new NotSupportedError("expect header not supported"); + } else { + request.headers.push(key, val); } - return serialization; - } - function isHTTPWhiteSpace(char) { - return char === 13 || char === 10 || char === 9 || char === 32; - } - function removeHTTPWhitespace(str, leading = true, trailing = true) { - return removeChars(str, leading, trailing, isHTTPWhiteSpace); - } - function isASCIIWhitespace(char) { - return char === 13 || char === 10 || char === 9 || char === 12 || char === 32; - } - function removeASCIIWhitespace(str, leading = true, trailing = true) { - return removeChars(str, leading, trailing, isASCIIWhitespace); } - function removeChars(str, leading, trailing, predicate) { - let lead = 0; - let trail = str.length - 1; - if (leading) { - while (lead < str.length && predicate(str.charCodeAt(lead))) - lead++; - } - if (trailing) { - while (trail > 0 && predicate(str.charCodeAt(trail))) - trail--; - } - return lead === 0 && trail === str.length - 1 ? str : str.slice(lead, trail + 1); - } - function isomorphicDecode(input) { - const length = input.length; - if ((2 << 15) - 1 > length) { - return String.fromCharCode.apply(null, input); - } - let result = ""; - let i = 0; - let addition = (2 << 15) - 1; - while (i < length) { - if (i + addition > length) { - addition = length - i; - } - result += String.fromCharCode.apply(null, input.subarray(i, i += addition)); - } - return result; - } - function minimizeSupportedMimeType(mimeType) { - switch (mimeType.essence) { - case "application/ecmascript": - case "application/javascript": - case "application/x-ecmascript": - case "application/x-javascript": - case "text/ecmascript": - case "text/javascript": - case "text/javascript1.0": - case "text/javascript1.1": - case "text/javascript1.2": - case "text/javascript1.3": - case "text/javascript1.4": - case "text/javascript1.5": - case "text/jscript": - case "text/livescript": - case "text/x-ecmascript": - case "text/x-javascript": - return "text/javascript"; - case "application/json": - case "text/json": - return "application/json"; - case "image/svg+xml": - return "image/svg+xml"; - case "text/xml": - case "application/xml": - return "application/xml"; - } - if (mimeType.subtype.endsWith("+json")) { - return "application/json"; - } - if (mimeType.subtype.endsWith("+xml")) { - return "application/xml"; - } - return ""; - } - module2.exports = { - dataURLProcessor, - URLSerializer, - collectASequenceOfCodePoints, - collectASequenceOfCodePointsFast, - stringPercentDecode, - parseMIMEType, - collectAnHTTPQuotedString, - serializeAMimeType, - removeChars, - minimizeSupportedMimeType - }; + module2.exports = Request; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/util.js -var require_util2 = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/util.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/connect.js +var require_connect = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/core/connect.js"(exports, module2) { "use strict"; - var { Transform } = require("node:stream"); - var zlib = require("node:zlib"); - var { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = require_constants3(); - var { getGlobalOrigin } = require_global(); - var { collectASequenceOfCodePoints, collectAnHTTPQuotedString, removeChars, parseMIMEType } = require_dataURL(); - var { performance } = require("node:perf_hooks"); - var { isBlobLike, toUSVString, ReadableStreamFrom, isValidHTTPToken } = require_util(); + var net = require("node:net"); var assert3 = require("node:assert"); - var { isUint8Array } = require("util/types"); - var crypto; - try { - crypto = require("node:crypto"); - } catch { - } - function responseURL(response) { - const urlList = response.urlList; - const length = urlList.length; - return length === 0 ? null : urlList[length - 1].toString(); - } - function responseLocationURL(response, requestFragment) { - if (!redirectStatusSet.has(response.status)) { - return null; - } - let location = response.headersList.get("location", true); - if (location !== null && isValidHeaderValue(location)) { - location = new URL(location, responseURL(response)); - } - if (location && !location.hash) { - location.hash = requestFragment; - } - return location; - } - function requestCurrentURL(request) { - return request.urlList[request.urlList.length - 1]; - } - function requestBadPort(request) { - const url = requestCurrentURL(request); - if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { - return "blocked"; - } - return "allowed"; - } - function isErrorLike(object) { - return object instanceof Error || (object?.constructor?.name === "Error" || object?.constructor?.name === "DOMException"); - } - function isValidReasonPhrase(statusText) { - for (let i = 0; i < statusText.length; ++i) { - const c = statusText.charCodeAt(i); - if (!(c === 9 || // HTAB - c >= 32 && c <= 126 || // SP / VCHAR - c >= 128 && c <= 255)) { - return false; + var util = require_util(); + var { InvalidArgumentError, ConnectTimeoutError } = require_errors(); + var tls; + var SessionCache; + if (global.FinalizationRegistry && !(process.env.NODE_V8_COVERAGE || process.env.UNDICI_NO_FG)) { + SessionCache = class WeakSessionCache { + constructor(maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions; + this._sessionCache = /* @__PURE__ */ new Map(); + this._sessionRegistry = new global.FinalizationRegistry((key) => { + if (this._sessionCache.size < this._maxCachedSessions) { + return; + } + const ref = this._sessionCache.get(key); + if (ref !== void 0 && ref.deref() === void 0) { + this._sessionCache.delete(key); + } + }); } - } - return true; - } - function isValidHeaderName(potentialValue) { - return isValidHTTPToken(potentialValue); - } - function isValidHeaderValue(potentialValue) { - if (potentialValue.startsWith(" ") || potentialValue.startsWith(" ") || potentialValue.endsWith(" ") || potentialValue.endsWith(" ")) { - return false; - } - if (potentialValue.includes("\0") || potentialValue.includes("\r") || potentialValue.includes("\n")) { - return false; - } - return true; - } - function setRequestReferrerPolicyOnRedirect(request, actualResponse) { - const { headersList } = actualResponse; - const policyHeader = (headersList.get("referrer-policy", true) ?? "").split(","); - let policy = ""; - if (policyHeader.length > 0) { - for (let i = policyHeader.length; i !== 0; i--) { - const token = policyHeader[i - 1].trim(); - if (referrerPolicyTokens.has(token)) { - policy = token; - break; + get(sessionKey) { + const ref = this._sessionCache.get(sessionKey); + return ref ? ref.deref() : null; + } + set(sessionKey, session) { + if (this._maxCachedSessions === 0) { + return; } + this._sessionCache.set(sessionKey, new WeakRef(session)); + this._sessionRegistry.register(session, sessionKey); } - } - if (policy !== "") { - request.referrerPolicy = policy; - } - } - function crossOriginResourcePolicyCheck() { - return "allowed"; - } - function corsCheck() { - return "success"; - } - function TAOCheck() { - return "success"; - } - function appendFetchMetadata(httpRequest) { - let header = null; - header = httpRequest.mode; - httpRequest.headersList.set("sec-fetch-mode", header, true); - } - function appendRequestOriginHeader(request) { - let serializedOrigin = request.origin; - if (request.responseTainting === "cors" || request.mode === "websocket") { - if (serializedOrigin) { - request.headersList.append("origin", serializedOrigin, true); + }; + } else { + SessionCache = class SimpleSessionCache { + constructor(maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions; + this._sessionCache = /* @__PURE__ */ new Map(); } - } else if (request.method !== "GET" && request.method !== "HEAD") { - switch (request.referrerPolicy) { - case "no-referrer": - serializedOrigin = null; - break; - case "no-referrer-when-downgrade": - case "strict-origin": - case "strict-origin-when-cross-origin": - if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { - serializedOrigin = null; - } - break; - case "same-origin": - if (!sameOrigin(request, requestCurrentURL(request))) { - serializedOrigin = null; - } - break; - default: + get(sessionKey) { + return this._sessionCache.get(sessionKey); } - if (serializedOrigin) { - request.headersList.append("origin", serializedOrigin, true); + set(sessionKey, session) { + if (this._maxCachedSessions === 0) { + return; + } + if (this._sessionCache.size >= this._maxCachedSessions) { + const { value: oldestKey } = this._sessionCache.keys().next(); + this._sessionCache.delete(oldestKey); + } + this._sessionCache.set(sessionKey, session); } - } - } - function coarsenTime(timestamp, crossOriginIsolatedCapability) { - return timestamp; + }; } - function clampAndCoarsenConnectionTimingInfo(connectionTimingInfo, defaultStartTime, crossOriginIsolatedCapability) { - if (!connectionTimingInfo?.startTime || connectionTimingInfo.startTime < defaultStartTime) { - return { - domainLookupStartTime: defaultStartTime, - domainLookupEndTime: defaultStartTime, - connectionStartTime: defaultStartTime, - connectionEndTime: defaultStartTime, - secureConnectionStartTime: defaultStartTime, - ALPNNegotiatedProtocol: connectionTimingInfo?.ALPNNegotiatedProtocol - }; + function buildConnector({ allowH2, maxCachedSessions, socketPath, timeout, ...opts }) { + if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { + throw new InvalidArgumentError("maxCachedSessions must be a positive integer or zero"); } - return { - domainLookupStartTime: coarsenTime(connectionTimingInfo.domainLookupStartTime, crossOriginIsolatedCapability), - domainLookupEndTime: coarsenTime(connectionTimingInfo.domainLookupEndTime, crossOriginIsolatedCapability), - connectionStartTime: coarsenTime(connectionTimingInfo.connectionStartTime, crossOriginIsolatedCapability), - connectionEndTime: coarsenTime(connectionTimingInfo.connectionEndTime, crossOriginIsolatedCapability), - secureConnectionStartTime: coarsenTime(connectionTimingInfo.secureConnectionStartTime, crossOriginIsolatedCapability), - ALPNNegotiatedProtocol: connectionTimingInfo.ALPNNegotiatedProtocol - }; - } - function coarsenedSharedCurrentTime(crossOriginIsolatedCapability) { - return coarsenTime(performance.now(), crossOriginIsolatedCapability); - } - function createOpaqueTimingInfo(timingInfo) { - return { - startTime: timingInfo.startTime ?? 0, - redirectStartTime: 0, - redirectEndTime: 0, - postRedirectStartTime: timingInfo.startTime ?? 0, - finalServiceWorkerStartTime: 0, - finalNetworkResponseStartTime: 0, - finalNetworkRequestStartTime: 0, - endTime: 0, - encodedBodySize: 0, - decodedBodySize: 0, - finalConnectionTimingInfo: null + const options = { path: socketPath, ...opts }; + const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions); + timeout = timeout == null ? 1e4 : timeout; + allowH2 = allowH2 != null ? allowH2 : false; + return function connect({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { + let socket; + if (protocol === "https:") { + if (!tls) { + tls = require("node:tls"); + } + servername = servername || options.servername || util.getServerName(host) || null; + const sessionKey = servername || hostname; + const session = sessionCache.get(sessionKey) || null; + assert3(sessionKey); + socket = tls.connect({ + highWaterMark: 16384, + // TLS in node can't have bigger HWM anyway... + ...options, + servername, + session, + localAddress, + // TODO(HTTP/2): Add support for h2c + ALPNProtocols: allowH2 ? ["http/1.1", "h2"] : ["http/1.1"], + socket: httpSocket, + // upgrade socket connection + port: port || 443, + host: hostname + }); + socket.on("session", function(session2) { + sessionCache.set(sessionKey, session2); + }); + } else { + assert3(!httpSocket, "httpSocket can only be sent on TLS update"); + socket = net.connect({ + highWaterMark: 64 * 1024, + // Same as nodejs fs streams. + ...options, + localAddress, + port: port || 80, + host: hostname + }); + } + if (options.keepAlive == null || options.keepAlive) { + const keepAliveInitialDelay = options.keepAliveInitialDelay === void 0 ? 6e4 : options.keepAliveInitialDelay; + socket.setKeepAlive(true, keepAliveInitialDelay); + } + const cancelTimeout = setupTimeout(() => onConnectTimeout(socket), timeout); + socket.setNoDelay(true).once(protocol === "https:" ? "secureConnect" : "connect", function() { + cancelTimeout(); + if (callback) { + const cb = callback; + callback = null; + cb(null, this); + } + }).on("error", function(err) { + cancelTimeout(); + if (callback) { + const cb = callback; + callback = null; + cb(err); + } + }); + return socket; }; } - function makePolicyContainer() { - return { - referrerPolicy: "strict-origin-when-cross-origin" + function setupTimeout(onConnectTimeout2, timeout) { + if (!timeout) { + return () => { + }; + } + let s1 = null; + let s2 = null; + const timeoutId = setTimeout(() => { + s1 = setImmediate(() => { + if (process.platform === "win32") { + s2 = setImmediate(() => onConnectTimeout2()); + } else { + onConnectTimeout2(); + } + }); + }, timeout); + return () => { + clearTimeout(timeoutId); + clearImmediate(s1); + clearImmediate(s2); }; } - function clonePolicyContainer(policyContainer) { - return { - referrerPolicy: policyContainer.referrerPolicy - }; + function onConnectTimeout(socket) { + let message = "Connect Timeout Error"; + if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) { + message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(", ")})`; + } + util.destroy(socket, new ConnectTimeoutError(message)); } - function determineRequestsReferrer(request) { - const policy = request.referrerPolicy; - assert3(policy); - let referrerSource = null; - if (request.referrer === "client") { - const globalOrigin = getGlobalOrigin(); - if (!globalOrigin || globalOrigin.origin === "null") { - return "no-referrer"; + module2.exports = buildConnector; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/util/timers.js +var require_timers = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/util/timers.js"(exports, module2) { + "use strict"; + var fastNow = Date.now(); + var fastNowTimeout; + var fastTimers = []; + function onTimeout() { + fastNow = Date.now(); + let len = fastTimers.length; + let idx = 0; + while (idx < len) { + const timer = fastTimers[idx]; + if (timer.state === 0) { + timer.state = fastNow + timer.delay; + } else if (timer.state > 0 && fastNow >= timer.state) { + timer.state = -1; + timer.callback(timer.opaque); } - referrerSource = new URL(globalOrigin); - } else if (request.referrer instanceof URL) { - referrerSource = request.referrer; - } - let referrerURL = stripURLForReferrer(referrerSource); - const referrerOrigin = stripURLForReferrer(referrerSource, true); - if (referrerURL.toString().length > 4096) { - referrerURL = referrerOrigin; - } - const areSameOrigin = sameOrigin(request, referrerURL); - const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(request.url); - switch (policy) { - case "origin": - return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true); - case "unsafe-url": - return referrerURL; - case "same-origin": - return areSameOrigin ? referrerOrigin : "no-referrer"; - case "origin-when-cross-origin": - return areSameOrigin ? referrerURL : referrerOrigin; - case "strict-origin-when-cross-origin": { - const currentURL = requestCurrentURL(request); - if (sameOrigin(referrerURL, currentURL)) { - return referrerURL; - } - if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { - return "no-referrer"; + if (timer.state === -1) { + timer.state = -2; + if (idx !== len - 1) { + fastTimers[idx] = fastTimers.pop(); + } else { + fastTimers.pop(); } - return referrerOrigin; + len -= 1; + } else { + idx += 1; } - case "strict-origin": - case "no-referrer-when-downgrade": - default: - return isNonPotentiallyTrustWorthy ? "no-referrer" : referrerOrigin; - } - } - function stripURLForReferrer(url, originOnly) { - assert3(url instanceof URL); - if (url.protocol === "file:" || url.protocol === "about:" || url.protocol === "blank:") { - return "no-referrer"; } - url.username = ""; - url.password = ""; - url.hash = ""; - if (originOnly) { - url.pathname = ""; - url.search = ""; + if (fastTimers.length > 0) { + refreshTimeout(); } - return url; } - function isURLPotentiallyTrustworthy(url) { - if (!(url instanceof URL)) { - return false; - } - if (url.href === "about:blank" || url.href === "about:srcdoc") { - return true; - } - if (url.protocol === "data:") - return true; - if (url.protocol === "file:") - return true; - return isOriginPotentiallyTrustworthy(url.origin); - function isOriginPotentiallyTrustworthy(origin) { - if (origin == null || origin === "null") - return false; - const originAsURL = new URL(origin); - if (originAsURL.protocol === "https:" || originAsURL.protocol === "wss:") { - return true; - } - if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) || (originAsURL.hostname === "localhost" || originAsURL.hostname.includes("localhost.")) || originAsURL.hostname.endsWith(".localhost")) { - return true; + function refreshTimeout() { + if (fastNowTimeout?.refresh) { + fastNowTimeout.refresh(); + } else { + clearTimeout(fastNowTimeout); + fastNowTimeout = setTimeout(onTimeout, 1e3); + if (fastNowTimeout.unref) { + fastNowTimeout.unref(); } - return false; } } - function bytesMatch(bytes, metadataList) { - if (crypto === void 0) { - return true; - } - const parsedMetadata = parseMetadata(metadataList); - if (parsedMetadata === "no metadata") { - return true; + var Timeout = class { + constructor(callback, delay, opaque) { + this.callback = callback; + this.delay = delay; + this.opaque = opaque; + this.state = -2; + this.refresh(); } - if (parsedMetadata.length === 0) { - return true; + refresh() { + if (this.state === -2) { + fastTimers.push(this); + if (!fastNowTimeout || fastTimers.length === 1) { + refreshTimeout(); + } + } + this.state = 0; } - const list = parsedMetadata.sort((c, d) => d.algo.localeCompare(c.algo)); - const strongest = list[0].algo; - const metadata = list.filter((item) => item.algo === strongest); - for (const item of metadata) { - const algorithm = item.algo; - let expectedValue = item.hash; - if (expectedValue.endsWith("==")) { - expectedValue = expectedValue.slice(0, -2); - } - let actualValue = crypto.createHash(algorithm).update(bytes).digest("base64"); - if (actualValue.endsWith("==")) { - actualValue = actualValue.slice(0, -2); - } - if (actualValue === expectedValue) { - return true; - } - let actualBase64URL = crypto.createHash(algorithm).update(bytes).digest("base64url"); - if (actualBase64URL.endsWith("==")) { - actualBase64URL = actualBase64URL.slice(0, -2); - } - if (actualBase64URL === expectedValue) { - return true; - } - } - return false; - } - var parseHashWithOptions = /(?sha256|sha384|sha512)-(?[A-Za-z0-9+/]+={0,2}(?=\s|$))( +[!-~]*)?/i; - function parseMetadata(metadata) { - const result = []; - let empty = true; - const supportedHashes = crypto.getHashes(); - for (const token of metadata.split(" ")) { - empty = false; - const parsedToken = parseHashWithOptions.exec(token); - if (parsedToken === null || parsedToken.groups === void 0) { - continue; - } - const algorithm = parsedToken.groups.algo; - if (supportedHashes.includes(algorithm.toLowerCase())) { - result.push(parsedToken.groups); - } - } - if (empty === true) { - return "no metadata"; - } - return result; - } - function tryUpgradeRequestToAPotentiallyTrustworthyURL(request) { - } - function sameOrigin(A, B) { - if (A.origin === B.origin && A.origin === "null") { - return true; - } - if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { - return true; + clear() { + this.state = -1; } - return false; - } - function createDeferredPromise() { - let res; - let rej; - const promise = new Promise((resolve, reject) => { - res = resolve; - rej = reject; - }); - return { promise, resolve: res, reject: rej }; - } - function isAborted(fetchParams) { - return fetchParams.controller.state === "aborted"; - } - function isCancelled(fetchParams) { - return fetchParams.controller.state === "aborted" || fetchParams.controller.state === "terminated"; - } - var normalizeMethodRecordBase = { - delete: "DELETE", - DELETE: "DELETE", - get: "GET", - GET: "GET", - head: "HEAD", - HEAD: "HEAD", - options: "OPTIONS", - OPTIONS: "OPTIONS", - post: "POST", - POST: "POST", - put: "PUT", - PUT: "PUT" - }; - var normalizeMethodRecord = { - ...normalizeMethodRecordBase, - patch: "patch", - PATCH: "PATCH" }; - Object.setPrototypeOf(normalizeMethodRecordBase, null); - Object.setPrototypeOf(normalizeMethodRecord, null); - function normalizeMethod(method) { - return normalizeMethodRecordBase[method.toLowerCase()] ?? method; - } - function serializeJavascriptValueToJSONString(value) { - const result = JSON.stringify(value); - if (result === void 0) { - throw new TypeError("Value is not JSON serializable"); - } - assert3(typeof result === "string"); - return result; - } - var esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())); - function makeIterator(iterator, name, kind, keyIndex = 0, valueIndex = 1) { - const object = { - index: 0, - kind, - target: iterator - }; - const iteratorObject = Object.create(esIteratorPrototype); - Object.defineProperty(iteratorObject, "next", { - value: function next() { - if (Object.getPrototypeOf(this) !== iteratorObject) { - throw new TypeError( - `'next' called on an object that does not implement interface ${name} Iterator.` - ); - } - const { index, kind: kind2, target } = object; - const values = target(); - const len = values.length; - if (index >= len) { - return { value: void 0, done: true }; - } - const { [keyIndex]: key, [valueIndex]: value } = values[index]; - object.index = index + 1; - let result; - switch (kind2) { - case "key": - result = key; - break; - case "value": - result = value; - break; - case "key+value": - result = [key, value]; - break; - } - return { - value: result, - done: false - }; - }, - writable: true, - enumerable: true, - configurable: true - }); - Object.defineProperty(iteratorObject, Symbol.toStringTag, { - value: `${name} Iterator`, - writable: false, - enumerable: false, - configurable: true - }); - return Object.create(iteratorObject); - } - async function fullyReadBody(body, processBody, processBodyError) { - const successSteps = processBody; - const errorSteps = processBodyError; - let reader; - try { - reader = body.stream.getReader(); - } catch (e) { - errorSteps(e); - return; - } - try { - const result = await readAllBytes(reader); - successSteps(result); - } catch (e) { - errorSteps(e); - } - } - function isReadableStreamLike(stream) { - return stream instanceof ReadableStream || stream[Symbol.toStringTag] === "ReadableStream" && typeof stream.tee === "function"; - } - function readableStreamClose(controller) { - try { - controller.close(); - controller.byobRequest?.respond(0); - } catch (err) { - if (!err.message.includes("Controller is already closed") && !err.message.includes("ReadableStream is already closed")) { - throw err; + module2.exports = { + setTimeout(callback, delay, opaque) { + return delay < 1e3 ? setTimeout(callback, delay, opaque) : new Timeout(callback, delay, opaque); + }, + clearTimeout(timeout) { + if (timeout instanceof Timeout) { + timeout.clear(); + } else { + clearTimeout(timeout); } } - } - function isomorphicEncode(input) { - for (let i = 0; i < input.length; i++) { - assert3(input.charCodeAt(i) <= 255); - } - return input; - } - async function readAllBytes(reader) { - const bytes = []; - let byteLength = 0; - while (true) { - const { done, value: chunk } = await reader.read(); - if (done) { - return Buffer.concat(bytes, byteLength); - } - if (!isUint8Array(chunk)) { - throw new TypeError("Received non-Uint8Array chunk"); + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/llhttp/utils.js +var require_utils = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/llhttp/utils.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.enumToMap = void 0; + function enumToMap(obj) { + const res = {}; + Object.keys(obj).forEach((key) => { + const value = obj[key]; + if (typeof value === "number") { + res[key] = value; } - bytes.push(chunk); - byteLength += chunk.length; - } - } - function urlIsLocal(url) { - assert3("protocol" in url); - const protocol = url.protocol; - return protocol === "about:" || protocol === "blob:" || protocol === "data:"; - } - function urlHasHttpsScheme(url) { - if (typeof url === "string") { - return url.startsWith("https:"); - } - return url.protocol === "https:"; - } - function urlIsHttpHttpsScheme(url) { - assert3("protocol" in url); - const protocol = url.protocol; - return protocol === "http:" || protocol === "https:"; + }); + return res; } - function simpleRangeHeaderValue(value, allowWhitespace) { - const data = value; - if (!data.startsWith("bytes")) { - return "failure"; - } - const position = { position: 5 }; - if (allowWhitespace) { - collectASequenceOfCodePoints( - (char) => char === " " || char === " ", - data, - position - ); - } - if (data.charCodeAt(position.position) !== 61) { - return "failure"; - } - position.position++; - if (allowWhitespace) { - collectASequenceOfCodePoints( - (char) => char === " " || char === " ", - data, - position - ); - } - const rangeStart = collectASequenceOfCodePoints( - (char) => { - const code = char.charCodeAt(0); - return code >= 48 && code <= 57; - }, - data, - position - ); - const rangeStartValue = rangeStart.length ? Number(rangeStart) : null; - if (allowWhitespace) { - collectASequenceOfCodePoints( - (char) => char === " " || char === " ", - data, - position - ); - } - if (data.charCodeAt(position.position) !== 45) { - return "failure"; - } - position.position++; - if (allowWhitespace) { - collectASequenceOfCodePoints( - (char) => char === " " || char === " ", - data, - position - ); - } - const rangeEnd = collectASequenceOfCodePoints( - (char) => { - const code = char.charCodeAt(0); - return code >= 48 && code <= 57; - }, - data, - position - ); - const rangeEndValue = rangeEnd.length ? Number(rangeEnd) : null; - if (position.position < data.length) { - return "failure"; - } - if (rangeEndValue === null && rangeStartValue === null) { - return "failure"; - } - if (rangeStartValue > rangeEndValue) { - return "failure"; - } - return { rangeStartValue, rangeEndValue }; - } - function buildContentRange(rangeStart, rangeEnd, fullLength) { - let contentRange = "bytes "; - contentRange += isomorphicEncode(`${rangeStart}`); - contentRange += "-"; - contentRange += isomorphicEncode(`${rangeEnd}`); - contentRange += "/"; - contentRange += isomorphicEncode(`${fullLength}`); - return contentRange; - } - var InflateStream = class extends Transform { - _transform(chunk, encoding, callback) { - if (!this._inflateStream) { - if (chunk.length === 0) { - callback(); - return; - } - this._inflateStream = (chunk[0] & 15) === 8 ? zlib.createInflate() : zlib.createInflateRaw(); - this._inflateStream.on("data", this.push.bind(this)); - this._inflateStream.on("end", () => this.push(null)); - this._inflateStream.on("error", (err) => this.destroy(err)); - } - this._inflateStream.write(chunk, encoding, callback); - } - _final(callback) { - if (this._inflateStream) { - this._inflateStream.end(); - this._inflateStream = null; - } - callback(); - } - }; - function createInflate() { - return new InflateStream(); - } - function extractMimeType(headers) { - let charset = null; - let essence = null; - let mimeType = null; - const values = getDecodeSplit("content-type", headers); - if (values === null) { - return "failure"; - } - for (const value of values) { - const temporaryMimeType = parseMIMEType(value); - if (temporaryMimeType === "failure" || temporaryMimeType.essence === "*/*") { - continue; - } - mimeType = temporaryMimeType; - if (mimeType.essence !== essence) { - charset = null; - if (mimeType.parameters.has("charset")) { - charset = mimeType.parameters.get("charset"); - } - essence = mimeType.essence; - } else if (!mimeType.parameters.has("charset") && charset !== null) { - mimeType.parameters.set("charset", charset); - } - } - if (mimeType == null) { - return "failure"; - } - return mimeType; - } - function gettingDecodingSplitting(value) { - const input = value; - const position = { position: 0 }; - const values = []; - let temporaryValue = ""; - while (position.position < input.length) { - temporaryValue += collectASequenceOfCodePoints( - (char) => char !== '"' && char !== ",", - input, - position - ); - if (position.position < input.length) { - if (input.charCodeAt(position.position) === 34) { - temporaryValue += collectAnHTTPQuotedString( - input, - position - ); - if (position.position < input.length) { - continue; - } - } else { - assert3(input.charCodeAt(position.position) === 44); - position.position++; - } - } - temporaryValue = removeChars(temporaryValue, true, true, (char) => char === 9 || char === 32); - values.push(temporaryValue); - temporaryValue = ""; - } - return values; - } - function getDecodeSplit(name, list) { - const value = list.get(name, true); - if (value === null) { - return null; - } - return gettingDecodingSplitting(value); - } - module2.exports = { - isAborted, - isCancelled, - createDeferredPromise, - ReadableStreamFrom, - toUSVString, - tryUpgradeRequestToAPotentiallyTrustworthyURL, - clampAndCoarsenConnectionTimingInfo, - coarsenedSharedCurrentTime, - determineRequestsReferrer, - makePolicyContainer, - clonePolicyContainer, - appendFetchMetadata, - appendRequestOriginHeader, - TAOCheck, - corsCheck, - crossOriginResourcePolicyCheck, - createOpaqueTimingInfo, - setRequestReferrerPolicyOnRedirect, - isValidHTTPToken, - requestBadPort, - requestCurrentURL, - responseURL, - responseLocationURL, - isBlobLike, - isURLPotentiallyTrustworthy, - isValidReasonPhrase, - sameOrigin, - normalizeMethod, - serializeJavascriptValueToJSONString, - makeIterator, - isValidHeaderName, - isValidHeaderValue, - isErrorLike, - fullyReadBody, - bytesMatch, - isReadableStreamLike, - readableStreamClose, - isomorphicEncode, - urlIsLocal, - urlHasHttpsScheme, - urlIsHttpHttpsScheme, - readAllBytes, - normalizeMethodRecord, - simpleRangeHeaderValue, - buildContentRange, - parseMetadata, - createInflate, - extractMimeType - }; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/symbols.js -var require_symbols2 = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/symbols.js"(exports, module2) { - "use strict"; - module2.exports = { - kUrl: Symbol("url"), - kHeaders: Symbol("headers"), - kSignal: Symbol("signal"), - kState: Symbol("state"), - kGuard: Symbol("guard"), - kRealm: Symbol("realm") - }; + exports.enumToMap = enumToMap; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/webidl.js -var require_webidl = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/webidl.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/llhttp/constants.js +var require_constants3 = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/llhttp/constants.js"(exports) { "use strict"; - var { types } = require("node:util"); - var { toUSVString } = require_util2(); - var webidl = {}; - webidl.converters = {}; - webidl.util = {}; - webidl.errors = {}; - webidl.errors.exception = function(message) { - return new TypeError(`${message.header}: ${message.message}`); - }; - webidl.errors.conversionFailed = function(context) { - const plural2 = context.types.length === 1 ? "" : " one of"; - const message = `${context.argument} could not be converted to${plural2}: ${context.types.join(", ")}.`; - return webidl.errors.exception({ - header: context.prefix, - message - }); - }; - webidl.errors.invalidArgument = function(context) { - return webidl.errors.exception({ - header: context.prefix, - message: `"${context.value}" is an invalid ${context.type}.` - }); - }; - webidl.brandCheck = function(V, I, opts = void 0) { - if (opts?.strict !== false) { - if (!(V instanceof I)) { - throw new TypeError("Illegal invocation"); - } - } else { - if (V?.[Symbol.toStringTag] !== I.prototype[Symbol.toStringTag]) { - throw new TypeError("Illegal invocation"); - } - } - }; - webidl.argumentLengthCheck = function({ length }, min, ctx) { - if (length < min) { - throw webidl.errors.exception({ - message: `${min} argument${min !== 1 ? "s" : ""} required, but${length ? " only" : ""} ${length} found.`, - ...ctx - }); - } - }; - webidl.illegalConstructor = function() { - throw webidl.errors.exception({ - header: "TypeError", - message: "Illegal constructor" - }); - }; - webidl.util.Type = function(V) { - switch (typeof V) { - case "undefined": - return "Undefined"; - case "boolean": - return "Boolean"; - case "string": - return "String"; - case "symbol": - return "Symbol"; - case "number": - return "Number"; - case "bigint": - return "BigInt"; - case "function": - case "object": { - if (V === null) { - return "Null"; - } - return "Object"; - } - } - }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.SPECIAL_HEADERS = exports.HEADER_STATE = exports.MINOR = exports.MAJOR = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.STRICT_TOKEN = exports.HEX = exports.URL_CHAR = exports.STRICT_URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.FINISH = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; + var utils_1 = require_utils(); + var ERROR; + (function(ERROR2) { + ERROR2[ERROR2["OK"] = 0] = "OK"; + ERROR2[ERROR2["INTERNAL"] = 1] = "INTERNAL"; + ERROR2[ERROR2["STRICT"] = 2] = "STRICT"; + ERROR2[ERROR2["LF_EXPECTED"] = 3] = "LF_EXPECTED"; + ERROR2[ERROR2["UNEXPECTED_CONTENT_LENGTH"] = 4] = "UNEXPECTED_CONTENT_LENGTH"; + ERROR2[ERROR2["CLOSED_CONNECTION"] = 5] = "CLOSED_CONNECTION"; + ERROR2[ERROR2["INVALID_METHOD"] = 6] = "INVALID_METHOD"; + ERROR2[ERROR2["INVALID_URL"] = 7] = "INVALID_URL"; + ERROR2[ERROR2["INVALID_CONSTANT"] = 8] = "INVALID_CONSTANT"; + ERROR2[ERROR2["INVALID_VERSION"] = 9] = "INVALID_VERSION"; + ERROR2[ERROR2["INVALID_HEADER_TOKEN"] = 10] = "INVALID_HEADER_TOKEN"; + ERROR2[ERROR2["INVALID_CONTENT_LENGTH"] = 11] = "INVALID_CONTENT_LENGTH"; + ERROR2[ERROR2["INVALID_CHUNK_SIZE"] = 12] = "INVALID_CHUNK_SIZE"; + ERROR2[ERROR2["INVALID_STATUS"] = 13] = "INVALID_STATUS"; + ERROR2[ERROR2["INVALID_EOF_STATE"] = 14] = "INVALID_EOF_STATE"; + ERROR2[ERROR2["INVALID_TRANSFER_ENCODING"] = 15] = "INVALID_TRANSFER_ENCODING"; + ERROR2[ERROR2["CB_MESSAGE_BEGIN"] = 16] = "CB_MESSAGE_BEGIN"; + ERROR2[ERROR2["CB_HEADERS_COMPLETE"] = 17] = "CB_HEADERS_COMPLETE"; + ERROR2[ERROR2["CB_MESSAGE_COMPLETE"] = 18] = "CB_MESSAGE_COMPLETE"; + ERROR2[ERROR2["CB_CHUNK_HEADER"] = 19] = "CB_CHUNK_HEADER"; + ERROR2[ERROR2["CB_CHUNK_COMPLETE"] = 20] = "CB_CHUNK_COMPLETE"; + ERROR2[ERROR2["PAUSED"] = 21] = "PAUSED"; + ERROR2[ERROR2["PAUSED_UPGRADE"] = 22] = "PAUSED_UPGRADE"; + ERROR2[ERROR2["PAUSED_H2_UPGRADE"] = 23] = "PAUSED_H2_UPGRADE"; + ERROR2[ERROR2["USER"] = 24] = "USER"; + })(ERROR = exports.ERROR || (exports.ERROR = {})); + var TYPE; + (function(TYPE2) { + TYPE2[TYPE2["BOTH"] = 0] = "BOTH"; + TYPE2[TYPE2["REQUEST"] = 1] = "REQUEST"; + TYPE2[TYPE2["RESPONSE"] = 2] = "RESPONSE"; + })(TYPE = exports.TYPE || (exports.TYPE = {})); + var FLAGS; + (function(FLAGS2) { + FLAGS2[FLAGS2["CONNECTION_KEEP_ALIVE"] = 1] = "CONNECTION_KEEP_ALIVE"; + FLAGS2[FLAGS2["CONNECTION_CLOSE"] = 2] = "CONNECTION_CLOSE"; + FLAGS2[FLAGS2["CONNECTION_UPGRADE"] = 4] = "CONNECTION_UPGRADE"; + FLAGS2[FLAGS2["CHUNKED"] = 8] = "CHUNKED"; + FLAGS2[FLAGS2["UPGRADE"] = 16] = "UPGRADE"; + FLAGS2[FLAGS2["CONTENT_LENGTH"] = 32] = "CONTENT_LENGTH"; + FLAGS2[FLAGS2["SKIPBODY"] = 64] = "SKIPBODY"; + FLAGS2[FLAGS2["TRAILING"] = 128] = "TRAILING"; + FLAGS2[FLAGS2["TRANSFER_ENCODING"] = 512] = "TRANSFER_ENCODING"; + })(FLAGS = exports.FLAGS || (exports.FLAGS = {})); + var LENIENT_FLAGS; + (function(LENIENT_FLAGS2) { + LENIENT_FLAGS2[LENIENT_FLAGS2["HEADERS"] = 1] = "HEADERS"; + LENIENT_FLAGS2[LENIENT_FLAGS2["CHUNKED_LENGTH"] = 2] = "CHUNKED_LENGTH"; + LENIENT_FLAGS2[LENIENT_FLAGS2["KEEP_ALIVE"] = 4] = "KEEP_ALIVE"; + })(LENIENT_FLAGS = exports.LENIENT_FLAGS || (exports.LENIENT_FLAGS = {})); + var METHODS; + (function(METHODS2) { + METHODS2[METHODS2["DELETE"] = 0] = "DELETE"; + METHODS2[METHODS2["GET"] = 1] = "GET"; + METHODS2[METHODS2["HEAD"] = 2] = "HEAD"; + METHODS2[METHODS2["POST"] = 3] = "POST"; + METHODS2[METHODS2["PUT"] = 4] = "PUT"; + METHODS2[METHODS2["CONNECT"] = 5] = "CONNECT"; + METHODS2[METHODS2["OPTIONS"] = 6] = "OPTIONS"; + METHODS2[METHODS2["TRACE"] = 7] = "TRACE"; + METHODS2[METHODS2["COPY"] = 8] = "COPY"; + METHODS2[METHODS2["LOCK"] = 9] = "LOCK"; + METHODS2[METHODS2["MKCOL"] = 10] = "MKCOL"; + METHODS2[METHODS2["MOVE"] = 11] = "MOVE"; + METHODS2[METHODS2["PROPFIND"] = 12] = "PROPFIND"; + METHODS2[METHODS2["PROPPATCH"] = 13] = "PROPPATCH"; + METHODS2[METHODS2["SEARCH"] = 14] = "SEARCH"; + METHODS2[METHODS2["UNLOCK"] = 15] = "UNLOCK"; + METHODS2[METHODS2["BIND"] = 16] = "BIND"; + METHODS2[METHODS2["REBIND"] = 17] = "REBIND"; + METHODS2[METHODS2["UNBIND"] = 18] = "UNBIND"; + METHODS2[METHODS2["ACL"] = 19] = "ACL"; + METHODS2[METHODS2["REPORT"] = 20] = "REPORT"; + METHODS2[METHODS2["MKACTIVITY"] = 21] = "MKACTIVITY"; + METHODS2[METHODS2["CHECKOUT"] = 22] = "CHECKOUT"; + METHODS2[METHODS2["MERGE"] = 23] = "MERGE"; + METHODS2[METHODS2["M-SEARCH"] = 24] = "M-SEARCH"; + METHODS2[METHODS2["NOTIFY"] = 25] = "NOTIFY"; + METHODS2[METHODS2["SUBSCRIBE"] = 26] = "SUBSCRIBE"; + METHODS2[METHODS2["UNSUBSCRIBE"] = 27] = "UNSUBSCRIBE"; + METHODS2[METHODS2["PATCH"] = 28] = "PATCH"; + METHODS2[METHODS2["PURGE"] = 29] = "PURGE"; + METHODS2[METHODS2["MKCALENDAR"] = 30] = "MKCALENDAR"; + METHODS2[METHODS2["LINK"] = 31] = "LINK"; + METHODS2[METHODS2["UNLINK"] = 32] = "UNLINK"; + METHODS2[METHODS2["SOURCE"] = 33] = "SOURCE"; + METHODS2[METHODS2["PRI"] = 34] = "PRI"; + METHODS2[METHODS2["DESCRIBE"] = 35] = "DESCRIBE"; + METHODS2[METHODS2["ANNOUNCE"] = 36] = "ANNOUNCE"; + METHODS2[METHODS2["SETUP"] = 37] = "SETUP"; + METHODS2[METHODS2["PLAY"] = 38] = "PLAY"; + METHODS2[METHODS2["PAUSE"] = 39] = "PAUSE"; + METHODS2[METHODS2["TEARDOWN"] = 40] = "TEARDOWN"; + METHODS2[METHODS2["GET_PARAMETER"] = 41] = "GET_PARAMETER"; + METHODS2[METHODS2["SET_PARAMETER"] = 42] = "SET_PARAMETER"; + METHODS2[METHODS2["REDIRECT"] = 43] = "REDIRECT"; + METHODS2[METHODS2["RECORD"] = 44] = "RECORD"; + METHODS2[METHODS2["FLUSH"] = 45] = "FLUSH"; + })(METHODS = exports.METHODS || (exports.METHODS = {})); + exports.METHODS_HTTP = [ + METHODS.DELETE, + METHODS.GET, + METHODS.HEAD, + METHODS.POST, + METHODS.PUT, + METHODS.CONNECT, + METHODS.OPTIONS, + METHODS.TRACE, + METHODS.COPY, + METHODS.LOCK, + METHODS.MKCOL, + METHODS.MOVE, + METHODS.PROPFIND, + METHODS.PROPPATCH, + METHODS.SEARCH, + METHODS.UNLOCK, + METHODS.BIND, + METHODS.REBIND, + METHODS.UNBIND, + METHODS.ACL, + METHODS.REPORT, + METHODS.MKACTIVITY, + METHODS.CHECKOUT, + METHODS.MERGE, + METHODS["M-SEARCH"], + METHODS.NOTIFY, + METHODS.SUBSCRIBE, + METHODS.UNSUBSCRIBE, + METHODS.PATCH, + METHODS.PURGE, + METHODS.MKCALENDAR, + METHODS.LINK, + METHODS.UNLINK, + METHODS.PRI, + // TODO(indutny): should we allow it with HTTP? + METHODS.SOURCE + ]; + exports.METHODS_ICE = [ + METHODS.SOURCE + ]; + exports.METHODS_RTSP = [ + METHODS.OPTIONS, + METHODS.DESCRIBE, + METHODS.ANNOUNCE, + METHODS.SETUP, + METHODS.PLAY, + METHODS.PAUSE, + METHODS.TEARDOWN, + METHODS.GET_PARAMETER, + METHODS.SET_PARAMETER, + METHODS.REDIRECT, + METHODS.RECORD, + METHODS.FLUSH, + // For AirPlay + METHODS.GET, + METHODS.POST + ]; + exports.METHOD_MAP = utils_1.enumToMap(METHODS); + exports.H_METHOD_MAP = {}; + Object.keys(exports.METHOD_MAP).forEach((key) => { + if (/^H/.test(key)) { + exports.H_METHOD_MAP[key] = exports.METHOD_MAP[key]; + } + }); + var FINISH; + (function(FINISH2) { + FINISH2[FINISH2["SAFE"] = 0] = "SAFE"; + FINISH2[FINISH2["SAFE_WITH_CB"] = 1] = "SAFE_WITH_CB"; + FINISH2[FINISH2["UNSAFE"] = 2] = "UNSAFE"; + })(FINISH = exports.FINISH || (exports.FINISH = {})); + exports.ALPHA = []; + for (let i = "A".charCodeAt(0); i <= "Z".charCodeAt(0); i++) { + exports.ALPHA.push(String.fromCharCode(i)); + exports.ALPHA.push(String.fromCharCode(i + 32)); + } + exports.NUM_MAP = { + 0: 0, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9 + }; + exports.HEX_MAP = { + 0: 0, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9, + A: 10, + B: 11, + C: 12, + D: 13, + E: 14, + F: 15, + a: 10, + b: 11, + c: 12, + d: 13, + e: 14, + f: 15 + }; + exports.NUM = [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ]; + exports.ALPHANUM = exports.ALPHA.concat(exports.NUM); + exports.MARK = ["-", "_", ".", "!", "~", "*", "'", "(", ")"]; + exports.USERINFO_CHARS = exports.ALPHANUM.concat(exports.MARK).concat(["%", ";", ":", "&", "=", "+", "$", ","]); + exports.STRICT_URL_CHAR = [ + "!", + '"', + "$", + "%", + "&", + "'", + "(", + ")", + "*", + "+", + ",", + "-", + ".", + "/", + ":", + ";", + "<", + "=", + ">", + "@", + "[", + "\\", + "]", + "^", + "_", + "`", + "{", + "|", + "}", + "~" + ].concat(exports.ALPHANUM); + exports.URL_CHAR = exports.STRICT_URL_CHAR.concat([" ", "\f"]); + for (let i = 128; i <= 255; i++) { + exports.URL_CHAR.push(i); + } + exports.HEX = exports.NUM.concat(["a", "b", "c", "d", "e", "f", "A", "B", "C", "D", "E", "F"]); + exports.STRICT_TOKEN = [ + "!", + "#", + "$", + "%", + "&", + "'", + "*", + "+", + "-", + ".", + "^", + "_", + "`", + "|", + "~" + ].concat(exports.ALPHANUM); + exports.TOKEN = exports.STRICT_TOKEN.concat([" "]); + exports.HEADER_CHARS = [" "]; + for (let i = 32; i <= 255; i++) { + if (i !== 127) { + exports.HEADER_CHARS.push(i); + } + } + exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS.filter((c) => c !== 44); + exports.MAJOR = exports.NUM_MAP; + exports.MINOR = exports.MAJOR; + var HEADER_STATE; + (function(HEADER_STATE2) { + HEADER_STATE2[HEADER_STATE2["GENERAL"] = 0] = "GENERAL"; + HEADER_STATE2[HEADER_STATE2["CONNECTION"] = 1] = "CONNECTION"; + HEADER_STATE2[HEADER_STATE2["CONTENT_LENGTH"] = 2] = "CONTENT_LENGTH"; + HEADER_STATE2[HEADER_STATE2["TRANSFER_ENCODING"] = 3] = "TRANSFER_ENCODING"; + HEADER_STATE2[HEADER_STATE2["UPGRADE"] = 4] = "UPGRADE"; + HEADER_STATE2[HEADER_STATE2["CONNECTION_KEEP_ALIVE"] = 5] = "CONNECTION_KEEP_ALIVE"; + HEADER_STATE2[HEADER_STATE2["CONNECTION_CLOSE"] = 6] = "CONNECTION_CLOSE"; + HEADER_STATE2[HEADER_STATE2["CONNECTION_UPGRADE"] = 7] = "CONNECTION_UPGRADE"; + HEADER_STATE2[HEADER_STATE2["TRANSFER_ENCODING_CHUNKED"] = 8] = "TRANSFER_ENCODING_CHUNKED"; + })(HEADER_STATE = exports.HEADER_STATE || (exports.HEADER_STATE = {})); + exports.SPECIAL_HEADERS = { + "connection": HEADER_STATE.CONNECTION, + "content-length": HEADER_STATE.CONTENT_LENGTH, + "proxy-connection": HEADER_STATE.CONNECTION, + "transfer-encoding": HEADER_STATE.TRANSFER_ENCODING, + "upgrade": HEADER_STATE.UPGRADE + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/llhttp/llhttp-wasm.js +var require_llhttp_wasm = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/llhttp/llhttp-wasm.js"(exports, module2) { + var { Buffer: Buffer2 } = require("node:buffer"); + module2.exports = Buffer2.from("AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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ADcDACAAQShqQgA3AwAgAEEgakIANwMAIABBEGpCADcDACAAQQhqQgA3AwAgAEHdATYCHEEAC3sBAX8CQCAAKAIMIgMNAAJAIAAoAgRFDQAgACABNgIECwJAIAAgASACEMSAgIAAIgMNACAAKAIMDwsgACADNgIcQQAhAyAAKAIEIgFFDQAgACABIAIgACgCCBGBgICAAAAiAUUNACAAIAI2AhQgACABNgIMIAEhAwsgAwvk8wEDDn8DfgR/I4CAgIAAQRBrIgMkgICAgAAgASEEIAEhBSABIQYgASEHIAEhCCABIQkgASEKIAEhCyABIQwgASENIAEhDiABIQ8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCHCIQQX9qDt0B2gEB2QECAwQFBgcICQoLDA0O2AEPENcBERLWARMUFRYXGBkaG+AB3wEcHR7VAR8gISIjJCXUASYnKCkqKyzTAdIBLS7RAdABLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVG2wFHSElKzwHOAUvNAUzMAU1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4ABgQGCAYMBhAGFAYYBhwGIAYkB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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FCAAIBA2AgxBACEQDLIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDLEBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxRCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLABCyAAQQA2AhwgACABNgIUIABBxoqAgAA2AhAgAEEHNgIMQQAhEAyvAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAyuAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAytAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMTQsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAysAQsgAEEANgIcIAAgATYCFCAAQdyIgIAANgIQIABBBzYCDEEAIRAMqwELIBBBP0cNASABQQFqIQELQQUhEAyQAQtBACEQIABBADYCHCAAIAE2AhQgAEH9koCAADYCECAAQQc2AgwMqAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMpwELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMpgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEYLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMpQELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0gA2AhwgACAUNgIUIAAgATYCDEEAIRAMpAELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0wA2AhwgACAUNgIUIAAgATYCDEEAIRAMowELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDEMLIABB5QA2AhwgACAU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YWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21ldGhvZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lYCBjYWxsYmFjayBlcnJvcgBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNlcnZlcgBJbnZhbGlkIGhlYWRlciB2YWx1ZSBjaGFyAEludmFsaWQgaGVhZGVyIGZpZWxkIGNoYXIAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl92ZXJzaW9uAEludmFsaWQgbWlub3IgdmVyc2lvbgBJbnZhbGlkIG1ham9yIHZlcnNpb24ARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgdmVyc2lvbgBFeHBlY3RlZCBDUkxGIGFmdGVyIHZlcnNpb24ASW52YWxpZCBIVFRQIHZlcnNpb24ASW52YWxpZCBoZWFkZXIgdG9rZW4AU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl91cmwASW52YWxpZCBjaGFyYWN0ZXJzIGluIHVybABVbmV4cGVjdGVkIHN0YXJ0IGNoYXIgaW4gdXJsAERvdWJsZSBAIGluIHVybABFbXB0eSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXJhY3RlciBpbiBDb250ZW50LUxlbmd0aABEdXBsaWNhdGUgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyIGluIHVybCBwYXRoAENvbnRlbnQtTGVuZ3RoIGNhbid0IGJlIHByZXNlbnQgd2l0aCBUcmFuc2Zlci1FbmNvZGluZwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBzaXplAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX3ZhbHVlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgdmFsdWUATWlzc2luZyBleHBlY3RlZCBMRiBhZnRlciBoZWFkZXIgdmFsdWUASW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fbmFtZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIG5hbWUAUGF1c2Ugb24gQ09OTkVDVC9VcGdyYWRlAFBhdXNlIG9uIFBSSS9VcGdyYWRlAEV4cGVjdGVkIEhUVFAvMiBDb25uZWN0aW9uIFByZWZhY2UAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9tZXRob2QARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgbWV0aG9kAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX2ZpZWxkAFBhdXNlZABJbnZhbGlkIHdvcmQgZW5jb3VudGVyZWQASW52YWxpZCBtZXRob2QgZW5jb3VudGVyZWQAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzY2hlbWEAUmVxdWVzdCBoYXMgaW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX0NIVU5LX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX05BTUVfQ09NUExFVEUASFBFX0NCX01FU1NBR0VfQ09NUExFVEUASFBFX0NCX01FVEhPRF9DT01QTEVURQBIUEVfQ0JfSEVBREVSX0ZJRUxEX0NPTVBMRVRFAERFTEVURQBIUEVfSU5WQUxJRF9FT0ZfU1RBVEUASU5WQUxJRF9TU0xfQ0VSVElGSUNBVEUAUEFVU0UATk9fUkVTUE9OU0UAVU5TVVBQT1JURURfTUVESUFfVFlQRQBHT05FAE5PVF9BQ0NFUFRBQkxFAFNFUlZJQ0VfVU5BVkFJTEFCTEUAUkFOR0VfTk9UX1NBVElTRklBQkxFAE9SSUdJTl9JU19VTlJFQUNIQUJMRQBSRVNQT05TRV9JU19TVEFMRQBQVVJHRQBNRVJHRQBSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFAFJFUVVFU1RfSEVBREVSX1RPT19MQVJHRQBQQVlMT0FEX1RPT19MQVJHRQBJTlNVRkZJQ0lFTlRfU1RPUkFHRQBIUEVfUEFVU0VEX1VQR1JBREUASFBFX1BBVVNFRF9IMl9VUEdSQURFAFNPVVJDRQBBTk5PVU5DRQBUUkFDRQBIUEVfVU5FWFBFQ1RFRF9TUEFDRQBERVNDUklCRQBVTlNVQlNDUklCRQBSRUNPUkQASFBFX0lOVkFMSURfTUVUSE9EAE5PVF9GT1VORABQUk9QRklORABVTkJJTkQAUkVCSU5EAFVOQVVUSE9SSVpFRABNRVRIT0RfTk9UX0FMTE9XRUQASFRUUF9WRVJTSU9OX05PVF9TVVBQT1JURUQAQUxSRUFEWV9SRVBPUlRFRABBQ0NFUFRFRABOT1RfSU1QTEVNRU5URUQATE9PUF9ERVRFQ1RFRABIUEVfQ1JfRVhQRUNURUQASFBFX0xGX0VYUEVDVEVEAENSRUFURUQASU1fVVNFRABIUEVfUEFVU0VEAFRJTUVPVVRfT0NDVVJFRABQQVlNRU5UX1JFUVVJUkVEAFBSRUNPTkRJVElPTl9SRVFVSVJFRABQUk9YWV9BVVRIRU5USUNBVElPTl9SRVFVSVJFRABORVRXT1JLX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAExFTkdUSF9SRVFVSVJFRABTU0xfQ0VSVElGSUNBVEVfUkVRVUlSRUQAVVBHUkFERV9SRVFVSVJFRABQQUdFX0VYUElSRUQAUFJFQ09ORElUSU9OX0ZBSUxFRABFWFBFQ1RBVElPTl9GQUlMRUQAUkVWQUxJREFUSU9OX0ZBSUxFRABTU0xfSEFORFNIQUtFX0ZBSUxFRABMT0NLRUQAVFJBTlNGT1JNQVRJT05fQVBQTElFRABOT1RfTU9ESUZJRUQATk9UX0VYVEVOREVEAEJBTkRXSURUSF9MSU1JVF9FWENFRURFRABTSVRFX0lTX09WRVJMT0FERUQASEVBRABFeHBlY3RlZCBIVFRQLwAAXhMAACYTAAAwEAAA8BcAAJ0TAAAVEgAAORcAAPASAAAKEAAAdRIAAK0SAACCEwAATxQAAH8QAACgFQAAIxQAAIkSAACLFAAATRUAANQRAADPFAAAEBgAAMkWAADcFgAAwREAAOAXAAC7FAAAdBQAAHwVAADlFAAACBcAAB8QAABlFQAAoxQAACgVAAACFQAAmRUAACwQAACLGQAATw8AANQOAABqEAAAzhAAAAIXAACJDgAAbhMAABwTAABmFAAAVhcAAMETAADNEwAAbBMAAGgXAABmFwAAXxcAACITAADODwAAaQ4AANgOAABjFgAAyxMAAKoOAAAoFwAAJhcAAMUTAABdFgAA6BEAAGcTAABlEwAA8hYAAHMTAAAdFwAA+RYAAPMRAADPDgAAzhUAAAwSAACzEQAApREAAGEQAAAyFwAAuxMAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIDAgICAgIAAAICAAICAAICAgICAgICAgIABAAAAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbG9zZWVlcC1hbGl2ZQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEAAAEBAAEBAAEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AAAAAAAAAAAAAAAAAAAByYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AAAAAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQIAAQMAAAAAAAAAAAAAAAAAAAAAAAAEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAIAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOT1VOQ0VFQ0tPVVRORUNURVRFQ1JJQkVMVVNIRVRFQURTRUFSQ0hSR0VDVElWSVRZTEVOREFSVkVPVElGWVBUSU9OU0NIU0VBWVNUQVRDSEdFT1JESVJFQ1RPUlRSQ0hQQVJBTUVURVJVUkNFQlNDUklCRUFSRE9XTkFDRUlORE5LQ0tVQlNDUklCRUhUVFAvQURUUC8=", "base64"); + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +var require_llhttp_simd_wasm = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js"(exports, module2) { + var { Buffer: Buffer2 } = require("node:buffer"); + module2.exports = Buffer2.from("AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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IAH9CwMAIABBMGogAf0LAwAgAEEgaiAB/QsDACAAQd0BNgIcQQALewEBfwJAIAAoAgwiAw0AAkAgACgCBEUNACAAIAE2AgQLAkAgACABIAIQxICAgAAiAw0AIAAoAgwPCyAAIAM2AhxBACEDIAAoAgQiAUUNACAAIAEgAiAAKAIIEYGAgIAAACIBRQ0AIAAgAjYCFCAAIAE2AgwgASEDCyADC+TzAQMOfwN+BH8jgICAgABBEGsiAySAgICAACABIQQgASEFIAEhBiABIQcgASEIIAEhCSABIQogASELIAEhDCABIQ0gASEOIAEhDwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIcIhBBf2oO3QHaAQHZAQIDBAUGBwgJCgsMDQ7YAQ8Q1wEREtYBExQVFhcYGRob4AHfARwdHtUBHyAhIiMkJdQBJicoKSorLNMB0gEtLtEB0AEvMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUbbAUdISUrPAc4BS80BTMwBTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAOxwEAAQID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YWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsb3NlZWVwLWFsaXZlAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgAAAAAAAAAAAAAAAAAAAHJhbnNmZXItZW5jb2RpbmdwZ3JhZGUNCg0KDQpTTQ0KDQpUVFAvQ0UvVFNQLwAAAAAAAAAAAAAAAAECAAEDAAAAAAAAAAAAAAAAAAAAAAAABAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAABAAACAAAAAAAAAAAAAAAAAAAAAAAAAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAACAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==", "base64"); + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/constants.js +var require_constants4 = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/constants.js"(exports, module2) { + "use strict"; + var corsSafeListedMethods = ["GET", "HEAD", "POST"]; + var corsSafeListedMethodsSet = new Set(corsSafeListedMethods); + var nullBodyStatus = [101, 204, 205, 304]; + var redirectStatus = [301, 302, 303, 307, 308]; + var redirectStatusSet = new Set(redirectStatus); + var badPorts = [ + "1", + "7", + "9", + "11", + "13", + "15", + "17", + "19", + "20", + "21", + "22", + "23", + "25", + "37", + "42", + "43", + "53", + "69", + "77", + "79", + "87", + "95", + "101", + "102", + "103", + "104", + "109", + "110", + "111", + "113", + "115", + "117", + "119", + "123", + "135", + "137", + "139", + "143", + "161", + "179", + "389", + "427", + "465", + "512", + "513", + "514", + "515", + "526", + "530", + "531", + "532", + "540", + "548", + "554", + "556", + "563", + "587", + "601", + "636", + "989", + "990", + "993", + "995", + "1719", + "1720", + "1723", + "2049", + "3659", + "4045", + "4190", + "5060", + "5061", + "6000", + "6566", + "6665", + "6666", + "6667", + "6668", + "6669", + "6679", + "6697", + "10080" + ]; + var badPortsSet = new Set(badPorts); + var referrerPolicy = [ + "", + "no-referrer", + "no-referrer-when-downgrade", + "same-origin", + "origin", + "strict-origin", + "origin-when-cross-origin", + "strict-origin-when-cross-origin", + "unsafe-url" + ]; + var referrerPolicySet = new Set(referrerPolicy); + var requestRedirect = ["follow", "manual", "error"]; + var safeMethods = ["GET", "HEAD", "OPTIONS", "TRACE"]; + var safeMethodsSet = new Set(safeMethods); + var requestMode = ["navigate", "same-origin", "no-cors", "cors"]; + var requestCredentials = ["omit", "same-origin", "include"]; + var requestCache = [ + "default", + "no-store", + "reload", + "no-cache", + "force-cache", + "only-if-cached" + ]; + var requestBodyHeader = [ + "content-encoding", + "content-language", + "content-location", + "content-type", + // See https://github.com/nodejs/undici/issues/2021 + // 'Content-Length' is a forbidden header name, which is typically + // removed in the Headers implementation. However, undici doesn't + // filter out headers, so we add it here. + "content-length" + ]; + var requestDuplex = [ + "half" + ]; + var forbiddenMethods = ["CONNECT", "TRACE", "TRACK"]; + var forbiddenMethodsSet = new Set(forbiddenMethods); + var subresource = [ + "audio", + "audioworklet", + "font", + "image", + "manifest", + "paintworklet", + "script", + "style", + "track", + "video", + "xslt", + "" + ]; + var subresourceSet = new Set(subresource); + module2.exports = { + subresource, + forbiddenMethods, + requestBodyHeader, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + redirectStatus, + corsSafeListedMethods, + nullBodyStatus, + safeMethods, + badPorts, + requestDuplex, + subresourceSet, + badPortsSet, + redirectStatusSet, + corsSafeListedMethodsSet, + safeMethodsSet, + forbiddenMethodsSet, + referrerPolicySet + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/global.js +var require_global = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/global.js"(exports, module2) { + "use strict"; + var globalOrigin = Symbol.for("undici.globalOrigin.1"); + function getGlobalOrigin() { + return globalThis[globalOrigin]; + } + function setGlobalOrigin(newOrigin) { + if (newOrigin === void 0) { + Object.defineProperty(globalThis, globalOrigin, { + value: void 0, + writable: true, + enumerable: false, + configurable: false + }); + return; + } + const parsedURL = new URL(newOrigin); + if (parsedURL.protocol !== "http:" && parsedURL.protocol !== "https:") { + throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`); + } + Object.defineProperty(globalThis, globalOrigin, { + value: parsedURL, + writable: true, + enumerable: false, + configurable: false + }); + } + module2.exports = { + getGlobalOrigin, + setGlobalOrigin + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/data-url.js +var require_data_url = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/data-url.js"(exports, module2) { + "use strict"; + var assert3 = require("node:assert"); + var encoder = new TextEncoder(); + var HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+-.^_|~A-Za-z0-9]+$/; + var HTTP_WHITESPACE_REGEX = /[\u000A\u000D\u0009\u0020]/; + var ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g; + var HTTP_QUOTED_STRING_TOKENS = /[\u0009\u0020-\u007E\u0080-\u00FF]/; + function dataURLProcessor(dataURL) { + assert3(dataURL.protocol === "data:"); + let input = URLSerializer(dataURL, true); + input = input.slice(5); + const position = { position: 0 }; + let mimeType = collectASequenceOfCodePointsFast( + ",", + input, + position + ); + const mimeTypeLength = mimeType.length; + mimeType = removeASCIIWhitespace(mimeType, true, true); + if (position.position >= input.length) { + return "failure"; + } + position.position++; + const encodedBody = input.slice(mimeTypeLength + 1); + let body = stringPercentDecode(encodedBody); + if (/;(\u0020){0,}base64$/i.test(mimeType)) { + const stringBody = isomorphicDecode(body); + body = forgivingBase64(stringBody); + if (body === "failure") { + return "failure"; + } + mimeType = mimeType.slice(0, -6); + mimeType = mimeType.replace(/(\u0020)+$/, ""); + mimeType = mimeType.slice(0, -1); + } + if (mimeType.startsWith(";")) { + mimeType = "text/plain" + mimeType; + } + let mimeTypeRecord = parseMIMEType(mimeType); + if (mimeTypeRecord === "failure") { + mimeTypeRecord = parseMIMEType("text/plain;charset=US-ASCII"); + } + return { mimeType: mimeTypeRecord, body }; + } + function URLSerializer(url, excludeFragment = false) { + if (!excludeFragment) { + return url.href; + } + const href = url.href; + const hashLength = url.hash.length; + const serialized = hashLength === 0 ? href : href.substring(0, href.length - hashLength); + if (!hashLength && href.endsWith("#")) { + return serialized.slice(0, -1); + } + return serialized; + } + function collectASequenceOfCodePoints(condition, input, position) { + let result = ""; + while (position.position < input.length && condition(input[position.position])) { + result += input[position.position]; + position.position++; + } + return result; + } + function collectASequenceOfCodePointsFast(char, input, position) { + const idx = input.indexOf(char, position.position); + const start = position.position; + if (idx === -1) { + position.position = input.length; + return input.slice(start); + } + position.position = idx; + return input.slice(start, position.position); + } + function stringPercentDecode(input) { + const bytes = encoder.encode(input); + return percentDecode(bytes); + } + function isHexCharByte(byte) { + return byte >= 48 && byte <= 57 || byte >= 65 && byte <= 70 || byte >= 97 && byte <= 102; + } + function hexByteToNumber(byte) { + return ( + // 0-9 + byte >= 48 && byte <= 57 ? byte - 48 : (byte & 223) - 55 + ); + } + function percentDecode(input) { + const length = input.length; + const output = new Uint8Array(length); + let j = 0; + for (let i = 0; i < length; ++i) { + const byte = input[i]; + if (byte !== 37) { + output[j++] = byte; + } else if (byte === 37 && !(isHexCharByte(input[i + 1]) && isHexCharByte(input[i + 2]))) { + output[j++] = 37; + } else { + output[j++] = hexByteToNumber(input[i + 1]) << 4 | hexByteToNumber(input[i + 2]); + i += 2; + } + } + return length === j ? output : output.subarray(0, j); + } + function parseMIMEType(input) { + input = removeHTTPWhitespace(input, true, true); + const position = { position: 0 }; + const type = collectASequenceOfCodePointsFast( + "/", + input, + position + ); + if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { + return "failure"; + } + if (position.position > input.length) { + return "failure"; + } + position.position++; + let subtype = collectASequenceOfCodePointsFast( + ";", + input, + position + ); + subtype = removeHTTPWhitespace(subtype, false, true); + if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { + return "failure"; + } + const typeLowercase = type.toLowerCase(); + const subtypeLowercase = subtype.toLowerCase(); + const mimeType = { + type: typeLowercase, + subtype: subtypeLowercase, + /** @type {Map} */ + parameters: /* @__PURE__ */ new Map(), + // https://mimesniff.spec.whatwg.org/#mime-type-essence + essence: `${typeLowercase}/${subtypeLowercase}` + }; + while (position.position < input.length) { + position.position++; + collectASequenceOfCodePoints( + // https://fetch.spec.whatwg.org/#http-whitespace + (char) => HTTP_WHITESPACE_REGEX.test(char), + input, + position + ); + let parameterName = collectASequenceOfCodePoints( + (char) => char !== ";" && char !== "=", + input, + position + ); + parameterName = parameterName.toLowerCase(); + if (position.position < input.length) { + if (input[position.position] === ";") { + continue; + } + position.position++; + } + if (position.position > input.length) { + break; + } + let parameterValue = null; + if (input[position.position] === '"') { + parameterValue = collectAnHTTPQuotedString(input, position, true); + collectASequenceOfCodePointsFast( + ";", + input, + position + ); + } else { + parameterValue = collectASequenceOfCodePointsFast( + ";", + input, + position + ); + parameterValue = removeHTTPWhitespace(parameterValue, false, true); + if (parameterValue.length === 0) { + continue; + } + } + if (parameterName.length !== 0 && HTTP_TOKEN_CODEPOINTS.test(parameterName) && (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && !mimeType.parameters.has(parameterName)) { + mimeType.parameters.set(parameterName, parameterValue); + } + } + return mimeType; + } + function forgivingBase64(data) { + data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, ""); + let dataLength = data.length; + if (dataLength % 4 === 0) { + if (data.charCodeAt(dataLength - 1) === 61) { + --dataLength; + if (data.charCodeAt(dataLength - 1) === 61) { + --dataLength; + } + } + } + if (dataLength % 4 === 1) { + return "failure"; + } + if (/[^+/0-9A-Za-z]/.test(data.length === dataLength ? data : data.substring(0, dataLength))) { + return "failure"; + } + const buffer = Buffer.from(data, "base64"); + return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength); + } + function collectAnHTTPQuotedString(input, position, extractValue) { + const positionStart = position.position; + let value = ""; + assert3(input[position.position] === '"'); + position.position++; + while (true) { + value += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== "\\", + input, + position + ); + if (position.position >= input.length) { + break; + } + const quoteOrBackslash = input[position.position]; + position.position++; + if (quoteOrBackslash === "\\") { + if (position.position >= input.length) { + value += "\\"; + break; + } + value += input[position.position]; + position.position++; + } else { + assert3(quoteOrBackslash === '"'); + break; + } + } + if (extractValue) { + return value; + } + return input.slice(positionStart, position.position); + } + function serializeAMimeType(mimeType) { + assert3(mimeType !== "failure"); + const { parameters, essence } = mimeType; + let serialization = essence; + for (let [name, value] of parameters.entries()) { + serialization += ";"; + serialization += name; + serialization += "="; + if (!HTTP_TOKEN_CODEPOINTS.test(value)) { + value = value.replace(/(\\|")/g, "\\$1"); + value = '"' + value; + value += '"'; + } + serialization += value; + } + return serialization; + } + function isHTTPWhiteSpace(char) { + return char === 13 || char === 10 || char === 9 || char === 32; + } + function removeHTTPWhitespace(str, leading = true, trailing = true) { + return removeChars(str, leading, trailing, isHTTPWhiteSpace); + } + function isASCIIWhitespace(char) { + return char === 13 || char === 10 || char === 9 || char === 12 || char === 32; + } + function removeASCIIWhitespace(str, leading = true, trailing = true) { + return removeChars(str, leading, trailing, isASCIIWhitespace); + } + function removeChars(str, leading, trailing, predicate) { + let lead = 0; + let trail = str.length - 1; + if (leading) { + while (lead < str.length && predicate(str.charCodeAt(lead))) + lead++; + } + if (trailing) { + while (trail > 0 && predicate(str.charCodeAt(trail))) + trail--; + } + return lead === 0 && trail === str.length - 1 ? str : str.slice(lead, trail + 1); + } + function isomorphicDecode(input) { + const length = input.length; + if ((2 << 15) - 1 > length) { + return String.fromCharCode.apply(null, input); + } + let result = ""; + let i = 0; + let addition = (2 << 15) - 1; + while (i < length) { + if (i + addition > length) { + addition = length - i; + } + result += String.fromCharCode.apply(null, input.subarray(i, i += addition)); + } + return result; + } + function minimizeSupportedMimeType(mimeType) { + switch (mimeType.essence) { + case "application/ecmascript": + case "application/javascript": + case "application/x-ecmascript": + case "application/x-javascript": + case "text/ecmascript": + case "text/javascript": + case "text/javascript1.0": + case "text/javascript1.1": + case "text/javascript1.2": + case "text/javascript1.3": + case "text/javascript1.4": + case "text/javascript1.5": + case "text/jscript": + case "text/livescript": + case "text/x-ecmascript": + case "text/x-javascript": + return "text/javascript"; + case "application/json": + case "text/json": + return "application/json"; + case "image/svg+xml": + return "image/svg+xml"; + case "text/xml": + case "application/xml": + return "application/xml"; + } + if (mimeType.subtype.endsWith("+json")) { + return "application/json"; + } + if (mimeType.subtype.endsWith("+xml")) { + return "application/xml"; + } + return ""; + } + module2.exports = { + dataURLProcessor, + URLSerializer, + collectASequenceOfCodePoints, + collectASequenceOfCodePointsFast, + stringPercentDecode, + parseMIMEType, + collectAnHTTPQuotedString, + serializeAMimeType, + removeChars, + minimizeSupportedMimeType, + HTTP_TOKEN_CODEPOINTS, + isomorphicDecode + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/webidl.js +var require_webidl = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/webidl.js"(exports, module2) { + "use strict"; + var { types, inspect } = require("node:util"); + var { toUSVString } = require_util(); + var webidl = {}; + webidl.converters = {}; + webidl.util = {}; + webidl.errors = {}; + webidl.errors.exception = function(message) { + return new TypeError(`${message.header}: ${message.message}`); + }; + webidl.errors.conversionFailed = function(context) { + const plural2 = context.types.length === 1 ? "" : " one of"; + const message = `${context.argument} could not be converted to${plural2}: ${context.types.join(", ")}.`; + return webidl.errors.exception({ + header: context.prefix, + message + }); + }; + webidl.errors.invalidArgument = function(context) { + return webidl.errors.exception({ + header: context.prefix, + message: `"${context.value}" is an invalid ${context.type}.` + }); + }; + webidl.brandCheck = function(V, I, opts = void 0) { + if (opts?.strict !== false) { + if (!(V instanceof I)) { + throw new TypeError("Illegal invocation"); + } + } else { + if (V?.[Symbol.toStringTag] !== I.prototype[Symbol.toStringTag]) { + throw new TypeError("Illegal invocation"); + } + } + }; + webidl.argumentLengthCheck = function({ length }, min, ctx) { + if (length < min) { + throw webidl.errors.exception({ + message: `${min} argument${min !== 1 ? "s" : ""} required, but${length ? " only" : ""} ${length} found.`, + ...ctx + }); + } + }; + webidl.illegalConstructor = function() { + throw webidl.errors.exception({ + header: "TypeError", + message: "Illegal constructor" + }); + }; + webidl.util.Type = function(V) { + switch (typeof V) { + case "undefined": + return "Undefined"; + case "boolean": + return "Boolean"; + case "string": + return "String"; + case "symbol": + return "Symbol"; + case "number": + return "Number"; + case "bigint": + return "BigInt"; + case "function": + case "object": { + if (V === null) { + return "Null"; + } + return "Object"; + } + } + }; webidl.util.ConvertToInt = function(V, bitLength, signedness, opts = {}) { let upperBound; let lowerBound; @@ -9319,7 +8637,7 @@ var require_webidl = __commonJS({ if (Number.isNaN(x) || x === Number.POSITIVE_INFINITY || x === Number.NEGATIVE_INFINITY) { throw webidl.errors.exception({ header: "Integer conversion", - message: `Could not convert ${V} to an integer.` + message: `Could not convert ${webidl.util.Stringify(V)} to an integer.` }); } x = webidl.util.IntegerPart(x); @@ -9357,15 +8675,28 @@ var require_webidl = __commonJS({ } return r; }; + webidl.util.Stringify = function(V) { + const type = webidl.util.Type(V); + switch (type) { + case "Symbol": + return `Symbol(${V.description})`; + case "Object": + return inspect(V); + case "String": + return `"${V}"`; + default: + return `${V}`; + } + }; webidl.sequenceConverter = function(converter) { - return (V) => { + return (V, Iterable) => { if (webidl.util.Type(V) !== "Object") { throw webidl.errors.exception({ header: "Sequence", message: `Value of type ${webidl.util.Type(V)} is not an Object.` }); } - const method = V?.[Symbol.iterator]?.(); + const method = typeof Iterable === "function" ? Iterable() : V?.[Symbol.iterator]?.(); const seq = []; if (method === void 0 || typeof method.next !== "function") { throw webidl.errors.exception({ @@ -9393,7 +8724,7 @@ var require_webidl = __commonJS({ } const result = {}; if (!types.isProxy(O)) { - const keys2 = Object.keys(O); + const keys2 = [...Object.getOwnPropertyNames(O), ...Object.getOwnPropertySymbols(O)]; for (const key of keys2) { const typedKey = keyConverter(key); const typedValue = valueConverter(O[key]); @@ -9418,7 +8749,7 @@ var require_webidl = __commonJS({ if (opts.strict !== false && !(V instanceof i)) { throw webidl.errors.exception({ header: i.name, - message: `Expected ${V} to be an instance of ${i.name}.` + message: `Expected ${webidl.util.Stringify(V)} to be an instance of ${i.name}.` }); } return V; @@ -9520,8 +8851,8 @@ var require_webidl = __commonJS({ webidl.converters.ArrayBuffer = function(V, opts = {}) { if (webidl.util.Type(V) !== "Object" || !types.isAnyArrayBuffer(V)) { throw webidl.errors.conversionFailed({ - prefix: `${V}`, - argument: `${V}`, + prefix: webidl.util.Stringify(V), + argument: webidl.util.Stringify(V), types: ["ArrayBuffer"] }); } @@ -9531,13 +8862,19 @@ var require_webidl = __commonJS({ message: "SharedArrayBuffer is not allowed." }); } + if (V.resizable || V.growable) { + throw webidl.errors.exception({ + header: "ArrayBuffer", + message: "Received a resizable ArrayBuffer." + }); + } return V; }; webidl.converters.TypedArray = function(V, T, opts = {}) { if (webidl.util.Type(V) !== "Object" || !types.isTypedArray(V) || V.constructor.name !== T.name) { throw webidl.errors.conversionFailed({ prefix: `${T.name}`, - argument: `${V}`, + argument: webidl.util.Stringify(V), types: [T.name] }); } @@ -9547,6 +8884,12 @@ var require_webidl = __commonJS({ message: "SharedArrayBuffer is not allowed." }); } + if (V.buffer.resizable || V.buffer.growable) { + throw webidl.errors.exception({ + header: "ArrayBuffer", + message: "Received a resizable ArrayBuffer." + }); + } return V; }; webidl.converters.DataView = function(V, opts = {}) { @@ -9562,1848 +8905,1787 @@ var require_webidl = __commonJS({ message: "SharedArrayBuffer is not allowed." }); } - return V; - }; - webidl.converters.BufferSource = function(V, opts = {}) { - if (types.isAnyArrayBuffer(V)) { - return webidl.converters.ArrayBuffer(V, { ...opts, allowShared: false }); - } - if (types.isTypedArray(V)) { - return webidl.converters.TypedArray(V, V.constructor, { ...opts, allowShared: false }); - } - if (types.isDataView(V)) { - return webidl.converters.DataView(V, opts, { ...opts, allowShared: false }); - } - throw new TypeError(`Could not convert ${V} to a BufferSource.`); - }; - webidl.converters["sequence"] = webidl.sequenceConverter( - webidl.converters.ByteString - ); - webidl.converters["sequence>"] = webidl.sequenceConverter( - webidl.converters["sequence"] - ); - webidl.converters["record"] = webidl.recordConverter( - webidl.converters.ByteString, - webidl.converters.ByteString - ); - module2.exports = { - webidl - }; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/file.js -var require_file = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/file.js"(exports, module2) { - "use strict"; - var { Blob: Blob2, File: NativeFile } = require("node:buffer"); - var { types } = require("node:util"); - var { kState } = require_symbols2(); - var { isBlobLike } = require_util2(); - var { webidl } = require_webidl(); - var { parseMIMEType, serializeAMimeType } = require_dataURL(); - var { kEnumerableProperty } = require_util(); - var encoder = new TextEncoder(); - var File = class _File extends Blob2 { - constructor(fileBits, fileName, options = {}) { - webidl.argumentLengthCheck(arguments, 2, { header: "File constructor" }); - fileBits = webidl.converters["sequence"](fileBits); - fileName = webidl.converters.USVString(fileName); - options = webidl.converters.FilePropertyBag(options); - const n = fileName; - let t = options.type; - let d; - substep: { - if (t) { - t = parseMIMEType(t); - if (t === "failure") { - t = ""; - break substep; - } - t = serializeAMimeType(t).toLowerCase(); - } - d = options.lastModified; - } - super(processBlobParts(fileBits, options), { type: t }); - this[kState] = { - name: n, - lastModified: d, - type: t - }; - } - get name() { - webidl.brandCheck(this, _File); - return this[kState].name; - } - get lastModified() { - webidl.brandCheck(this, _File); - return this[kState].lastModified; - } - get type() { - webidl.brandCheck(this, _File); - return this[kState].type; - } - }; - var FileLike = class _FileLike { - constructor(blobLike, fileName, options = {}) { - const n = fileName; - const t = options.type; - const d = options.lastModified ?? Date.now(); - this[kState] = { - blobLike, - name: n, - type: t, - lastModified: d - }; - } - stream(...args) { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.stream(...args); - } - arrayBuffer(...args) { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.arrayBuffer(...args); - } - slice(...args) { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.slice(...args); - } - text(...args) { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.text(...args); - } - get size() { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.size; - } - get type() { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.type; - } - get name() { - webidl.brandCheck(this, _FileLike); - return this[kState].name; - } - get lastModified() { - webidl.brandCheck(this, _FileLike); - return this[kState].lastModified; - } - get [Symbol.toStringTag]() { - return "File"; - } - }; - Object.defineProperties(File.prototype, { - [Symbol.toStringTag]: { - value: "File", - configurable: true - }, - name: kEnumerableProperty, - lastModified: kEnumerableProperty - }); - webidl.converters.Blob = webidl.interfaceConverter(Blob2); - webidl.converters.BlobPart = function(V, opts) { - if (webidl.util.Type(V) === "Object") { - if (isBlobLike(V)) { - return webidl.converters.Blob(V, { strict: false }); - } - if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) { - return webidl.converters.BufferSource(V, opts); - } + if (V.buffer.resizable || V.buffer.growable) { + throw webidl.errors.exception({ + header: "ArrayBuffer", + message: "Received a resizable ArrayBuffer." + }); } - return webidl.converters.USVString(V, opts); + return V; }; - webidl.converters["sequence"] = webidl.sequenceConverter( - webidl.converters.BlobPart - ); - webidl.converters.FilePropertyBag = webidl.dictionaryConverter([ - { - key: "lastModified", - converter: webidl.converters["long long"], - get defaultValue() { - return Date.now(); - } - }, - { - key: "type", - converter: webidl.converters.DOMString, - defaultValue: "" - }, - { - key: "endings", - converter: (value) => { - value = webidl.converters.DOMString(value); - value = value.toLowerCase(); - if (value !== "native") { - value = "transparent"; - } - return value; - }, - defaultValue: "transparent" - } - ]); - function processBlobParts(parts, options) { - const bytes = []; - for (const element of parts) { - if (typeof element === "string") { - let s = element; - if (options.endings === "native") { - s = convertLineEndingsNative(s); - } - bytes.push(encoder.encode(s)); - } else if (ArrayBuffer.isView(element) || types.isArrayBuffer(element)) { - if (element.buffer) { - bytes.push( - new Uint8Array(element.buffer, element.byteOffset, element.byteLength) - ); - } else { - bytes.push(new Uint8Array(element)); - } - } else if (isBlobLike(element)) { - bytes.push(element); - } + webidl.converters.BufferSource = function(V, opts = {}) { + if (types.isAnyArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, { ...opts, allowShared: false }); } - return bytes; - } - function convertLineEndingsNative(s) { - let nativeLineEnding = "\n"; - if (process.platform === "win32") { - nativeLineEnding = "\r\n"; + if (types.isTypedArray(V)) { + return webidl.converters.TypedArray(V, V.constructor, { ...opts, allowShared: false }); } - return s.replace(/\r?\n/g, nativeLineEnding); - } - function isFileLike(object) { - return NativeFile && object instanceof NativeFile || object instanceof File || object && (typeof object.stream === "function" || typeof object.arrayBuffer === "function") && object[Symbol.toStringTag] === "File"; - } - module2.exports = { File, FileLike, isFileLike }; + if (types.isDataView(V)) { + return webidl.converters.DataView(V, opts, { ...opts, allowShared: false }); + } + throw new TypeError(`Could not convert ${webidl.util.Stringify(V)} to a BufferSource.`); + }; + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.ByteString + ); + webidl.converters["sequence>"] = webidl.sequenceConverter( + webidl.converters["sequence"] + ); + webidl.converters["record"] = webidl.recordConverter( + webidl.converters.ByteString, + webidl.converters.ByteString + ); + module2.exports = { + webidl + }; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/formdata.js -var require_formdata = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/formdata.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/util.js +var require_util3 = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/util.js"(exports, module2) { "use strict"; - var { isBlobLike, toUSVString, makeIterator } = require_util2(); - var { kState } = require_symbols2(); - var { kEnumerableProperty } = require_util(); - var { File: UndiciFile, FileLike, isFileLike } = require_file(); + var { Transform } = require("node:stream"); + var zlib = require("node:zlib"); + var { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = require_constants4(); + var { getGlobalOrigin } = require_global(); + var { collectASequenceOfCodePoints, collectAnHTTPQuotedString, removeChars, parseMIMEType } = require_data_url(); + var { performance } = require("node:perf_hooks"); + var { isBlobLike, ReadableStreamFrom, isValidHTTPToken } = require_util(); + var assert3 = require("node:assert"); + var { isUint8Array } = require("node:util/types"); var { webidl } = require_webidl(); - var { File: NativeFile } = require("node:buffer"); - var File = NativeFile ?? UndiciFile; - var FormData = class _FormData { - constructor(form) { - if (form !== void 0) { - throw webidl.errors.conversionFailed({ - prefix: "FormData constructor", - argument: "Argument 1", - types: ["undefined"] - }); + var supportedHashes = []; + var crypto; + try { + crypto = require("node:crypto"); + const possibleRelevantHashes = ["sha256", "sha384", "sha512"]; + supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash)); + } catch { + } + function responseURL(response) { + const urlList = response.urlList; + const length = urlList.length; + return length === 0 ? null : urlList[length - 1].toString(); + } + function responseLocationURL(response, requestFragment) { + if (!redirectStatusSet.has(response.status)) { + return null; + } + let location = response.headersList.get("location", true); + if (location !== null && isValidHeaderValue(location)) { + if (!isValidEncodedURL(location)) { + location = normalizeBinaryStringToUtf8(location); } - this[kState] = []; + location = new URL(location, responseURL(response)); } - append(name, value, filename = void 0) { - webidl.brandCheck(this, _FormData); - webidl.argumentLengthCheck(arguments, 2, { header: "FormData.append" }); - if (arguments.length === 3 && !isBlobLike(value)) { - throw new TypeError( - "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" - ); + if (location && !location.hash) { + location.hash = requestFragment; + } + return location; + } + function isValidEncodedURL(url) { + for (let i = 0; i < url.length; ++i) { + const code = url.charCodeAt(i); + if (code > 126 || // Non-US-ASCII + DEL + code < 32) { + return false; } - name = webidl.converters.USVString(name); - value = isBlobLike(value) ? webidl.converters.Blob(value, { strict: false }) : webidl.converters.USVString(value); - filename = arguments.length === 3 ? webidl.converters.USVString(filename) : void 0; - const entry = makeEntry(name, value, filename); - this[kState].push(entry); } - delete(name) { - webidl.brandCheck(this, _FormData); - webidl.argumentLengthCheck(arguments, 1, { header: "FormData.delete" }); - name = webidl.converters.USVString(name); - this[kState] = this[kState].filter((entry) => entry.name !== name); + return true; + } + function normalizeBinaryStringToUtf8(value) { + return Buffer.from(value, "binary").toString("utf8"); + } + function requestCurrentURL(request) { + return request.urlList[request.urlList.length - 1]; + } + function requestBadPort(request) { + const url = requestCurrentURL(request); + if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { + return "blocked"; } - get(name) { - webidl.brandCheck(this, _FormData); - webidl.argumentLengthCheck(arguments, 1, { header: "FormData.get" }); - name = webidl.converters.USVString(name); - const idx = this[kState].findIndex((entry) => entry.name === name); - if (idx === -1) { - return null; + return "allowed"; + } + function isErrorLike(object) { + return object instanceof Error || (object?.constructor?.name === "Error" || object?.constructor?.name === "DOMException"); + } + function isValidReasonPhrase(statusText) { + for (let i = 0; i < statusText.length; ++i) { + const c = statusText.charCodeAt(i); + if (!(c === 9 || // HTAB + c >= 32 && c <= 126 || // SP / VCHAR + c >= 128 && c <= 255)) { + return false; } - return this[kState][idx].value; } - getAll(name) { - webidl.brandCheck(this, _FormData); - webidl.argumentLengthCheck(arguments, 1, { header: "FormData.getAll" }); - name = webidl.converters.USVString(name); - return this[kState].filter((entry) => entry.name === name).map((entry) => entry.value); + return true; + } + var isValidHeaderName = isValidHTTPToken; + function isValidHeaderValue(potentialValue) { + return (potentialValue[0] === " " || potentialValue[0] === " " || potentialValue[potentialValue.length - 1] === " " || potentialValue[potentialValue.length - 1] === " " || potentialValue.includes("\n") || potentialValue.includes("\r") || potentialValue.includes("\0")) === false; + } + function setRequestReferrerPolicyOnRedirect(request, actualResponse) { + const { headersList } = actualResponse; + const policyHeader = (headersList.get("referrer-policy", true) ?? "").split(","); + let policy = ""; + if (policyHeader.length > 0) { + for (let i = policyHeader.length; i !== 0; i--) { + const token = policyHeader[i - 1].trim(); + if (referrerPolicyTokens.has(token)) { + policy = token; + break; + } + } } - has(name) { - webidl.brandCheck(this, _FormData); - webidl.argumentLengthCheck(arguments, 1, { header: "FormData.has" }); - name = webidl.converters.USVString(name); - return this[kState].findIndex((entry) => entry.name === name) !== -1; + if (policy !== "") { + request.referrerPolicy = policy; } - set(name, value, filename = void 0) { - webidl.brandCheck(this, _FormData); - webidl.argumentLengthCheck(arguments, 2, { header: "FormData.set" }); - if (arguments.length === 3 && !isBlobLike(value)) { - throw new TypeError( - "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" - ); + } + function crossOriginResourcePolicyCheck() { + return "allowed"; + } + function corsCheck() { + return "success"; + } + function TAOCheck() { + return "success"; + } + function appendFetchMetadata(httpRequest) { + let header = null; + header = httpRequest.mode; + httpRequest.headersList.set("sec-fetch-mode", header, true); + } + function appendRequestOriginHeader(request) { + let serializedOrigin = request.origin; + if (request.responseTainting === "cors" || request.mode === "websocket") { + if (serializedOrigin) { + request.headersList.append("origin", serializedOrigin, true); } - name = webidl.converters.USVString(name); - value = isBlobLike(value) ? webidl.converters.Blob(value, { strict: false }) : webidl.converters.USVString(value); - filename = arguments.length === 3 ? toUSVString(filename) : void 0; - const entry = makeEntry(name, value, filename); - const idx = this[kState].findIndex((entry2) => entry2.name === name); - if (idx !== -1) { - this[kState] = [ - ...this[kState].slice(0, idx), - entry, - ...this[kState].slice(idx + 1).filter((entry2) => entry2.name !== name) - ]; - } else { - this[kState].push(entry); + } else if (request.method !== "GET" && request.method !== "HEAD") { + switch (request.referrerPolicy) { + case "no-referrer": + serializedOrigin = null; + break; + case "no-referrer-when-downgrade": + case "strict-origin": + case "strict-origin-when-cross-origin": + if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { + serializedOrigin = null; + } + break; + case "same-origin": + if (!sameOrigin(request, requestCurrentURL(request))) { + serializedOrigin = null; + } + break; + default: + } + if (serializedOrigin) { + request.headersList.append("origin", serializedOrigin, true); + } + } + } + function coarsenTime(timestamp, crossOriginIsolatedCapability) { + return timestamp; + } + function clampAndCoarsenConnectionTimingInfo(connectionTimingInfo, defaultStartTime, crossOriginIsolatedCapability) { + if (!connectionTimingInfo?.startTime || connectionTimingInfo.startTime < defaultStartTime) { + return { + domainLookupStartTime: defaultStartTime, + domainLookupEndTime: defaultStartTime, + connectionStartTime: defaultStartTime, + connectionEndTime: defaultStartTime, + secureConnectionStartTime: defaultStartTime, + ALPNNegotiatedProtocol: connectionTimingInfo?.ALPNNegotiatedProtocol + }; + } + return { + domainLookupStartTime: coarsenTime(connectionTimingInfo.domainLookupStartTime, crossOriginIsolatedCapability), + domainLookupEndTime: coarsenTime(connectionTimingInfo.domainLookupEndTime, crossOriginIsolatedCapability), + connectionStartTime: coarsenTime(connectionTimingInfo.connectionStartTime, crossOriginIsolatedCapability), + connectionEndTime: coarsenTime(connectionTimingInfo.connectionEndTime, crossOriginIsolatedCapability), + secureConnectionStartTime: coarsenTime(connectionTimingInfo.secureConnectionStartTime, crossOriginIsolatedCapability), + ALPNNegotiatedProtocol: connectionTimingInfo.ALPNNegotiatedProtocol + }; + } + function coarsenedSharedCurrentTime(crossOriginIsolatedCapability) { + return coarsenTime(performance.now(), crossOriginIsolatedCapability); + } + function createOpaqueTimingInfo(timingInfo) { + return { + startTime: timingInfo.startTime ?? 0, + redirectStartTime: 0, + redirectEndTime: 0, + postRedirectStartTime: timingInfo.startTime ?? 0, + finalServiceWorkerStartTime: 0, + finalNetworkResponseStartTime: 0, + finalNetworkRequestStartTime: 0, + endTime: 0, + encodedBodySize: 0, + decodedBodySize: 0, + finalConnectionTimingInfo: null + }; + } + function makePolicyContainer() { + return { + referrerPolicy: "strict-origin-when-cross-origin" + }; + } + function clonePolicyContainer(policyContainer) { + return { + referrerPolicy: policyContainer.referrerPolicy + }; + } + function determineRequestsReferrer(request) { + const policy = request.referrerPolicy; + assert3(policy); + let referrerSource = null; + if (request.referrer === "client") { + const globalOrigin = getGlobalOrigin(); + if (!globalOrigin || globalOrigin.origin === "null") { + return "no-referrer"; } + referrerSource = new URL(globalOrigin); + } else if (request.referrer instanceof URL) { + referrerSource = request.referrer; } - entries() { - webidl.brandCheck(this, _FormData); - return makeIterator( - () => this[kState], - "FormData", - "key+value", - "name", - "value" - ); - } - keys() { - webidl.brandCheck(this, _FormData); - return makeIterator( - () => this[kState], - "FormData", - "key", - "name", - "value" - ); - } - values() { - webidl.brandCheck(this, _FormData); - return makeIterator( - () => this[kState], - "FormData", - "value", - "name", - "value" - ); + let referrerURL = stripURLForReferrer(referrerSource); + const referrerOrigin = stripURLForReferrer(referrerSource, true); + if (referrerURL.toString().length > 4096) { + referrerURL = referrerOrigin; } - /** - * @param {(value: string, key: string, self: FormData) => void} callbackFn - * @param {unknown} thisArg - */ - forEach(callbackFn, thisArg = globalThis) { - webidl.brandCheck(this, _FormData); - webidl.argumentLengthCheck(arguments, 1, { header: "FormData.forEach" }); - if (typeof callbackFn !== "function") { - throw new TypeError( - "Failed to execute 'forEach' on 'FormData': parameter 1 is not of type 'Function'." - ); - } - for (const [key, value] of this) { - callbackFn.call(thisArg, value, key, this); + const areSameOrigin = sameOrigin(request, referrerURL); + const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(request.url); + switch (policy) { + case "origin": + return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true); + case "unsafe-url": + return referrerURL; + case "same-origin": + return areSameOrigin ? referrerOrigin : "no-referrer"; + case "origin-when-cross-origin": + return areSameOrigin ? referrerURL : referrerOrigin; + case "strict-origin-when-cross-origin": { + const currentURL = requestCurrentURL(request); + if (sameOrigin(referrerURL, currentURL)) { + return referrerURL; + } + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return "no-referrer"; + } + return referrerOrigin; } + case "strict-origin": + case "no-referrer-when-downgrade": + default: + return isNonPotentiallyTrustWorthy ? "no-referrer" : referrerOrigin; } - }; - FormData.prototype[Symbol.iterator] = FormData.prototype.entries; - Object.defineProperties(FormData.prototype, { - append: kEnumerableProperty, - delete: kEnumerableProperty, - get: kEnumerableProperty, - getAll: kEnumerableProperty, - has: kEnumerableProperty, - set: kEnumerableProperty, - entries: kEnumerableProperty, - keys: kEnumerableProperty, - values: kEnumerableProperty, - forEach: kEnumerableProperty, - [Symbol.iterator]: { enumerable: false }, - [Symbol.toStringTag]: { - value: "FormData", - configurable: true + } + function stripURLForReferrer(url, originOnly) { + assert3(url instanceof URL); + url = new URL(url); + if (url.protocol === "file:" || url.protocol === "about:" || url.protocol === "blank:") { + return "no-referrer"; } - }); - function makeEntry(name, value, filename) { - name = Buffer.from(name).toString("utf8"); - if (typeof value === "string") { - value = Buffer.from(value).toString("utf8"); - } else { - if (!isFileLike(value)) { - value = value instanceof Blob ? new File([value], "blob", { type: value.type }) : new FileLike(value, "blob", { type: value.type }); - } - if (filename !== void 0) { - const options = { - type: value.type, - lastModified: value.lastModified - }; - value = NativeFile && value instanceof NativeFile || value instanceof UndiciFile ? new File([value], filename, options) : new FileLike(value, filename, options); - } + url.username = ""; + url.password = ""; + url.hash = ""; + if (originOnly) { + url.pathname = ""; + url.search = ""; } - return { name, value }; + return url; } - module2.exports = { FormData }; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/body.js -var require_body = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/fetch/body.js"(exports, module2) { - "use strict"; - var Busboy = require_main(); - var util = require_util(); - var { - ReadableStreamFrom, - isBlobLike, - isReadableStreamLike, - readableStreamClose, - createDeferredPromise, - fullyReadBody, - extractMimeType - } = require_util2(); - var { FormData } = require_formdata(); - var { kState } = require_symbols2(); - var { webidl } = require_webidl(); - var { Blob: Blob2, File: NativeFile } = require("node:buffer"); - var { kBodyUsed } = require_symbols(); - var assert3 = require("node:assert"); - var { isErrored } = require_util(); - var { isUint8Array, isArrayBuffer } = require("util/types"); - var { File: UndiciFile } = require_file(); - var { serializeAMimeType } = require_dataURL(); - var File = NativeFile ?? UndiciFile; - var textEncoder = new TextEncoder(); - var textDecoder = new TextDecoder(); - function extractBody(object, keepalive = false) { - let stream = null; - if (object instanceof ReadableStream) { - stream = object; - } else if (isBlobLike(object)) { - stream = object.stream(); - } else { - stream = new ReadableStream({ - async pull(controller) { - const buffer = typeof source === "string" ? textEncoder.encode(source) : source; - if (buffer.byteLength) { - controller.enqueue(buffer); - } - queueMicrotask(() => readableStreamClose(controller)); - }, - start() { - }, - type: "bytes" - }); - } - assert3(isReadableStreamLike(stream)); - let action = null; - let source = null; - let length = null; - let type = null; - if (typeof object === "string") { - source = object; - type = "text/plain;charset=UTF-8"; - } else if (object instanceof URLSearchParams) { - source = object.toString(); - type = "application/x-www-form-urlencoded;charset=UTF-8"; - } else if (isArrayBuffer(object)) { - source = new Uint8Array(object.slice()); - } else if (ArrayBuffer.isView(object)) { - source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)); - } else if (util.isFormDataLike(object)) { - const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, "0")}`; - const prefix = `--${boundary}\r -Content-Disposition: form-data`; - const escape = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22"); - const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, "\r\n"); - const blobParts = []; - const rn = new Uint8Array([13, 10]); - length = 0; - let hasUnknownSizeValue = false; - for (const [name, value] of object) { - if (typeof value === "string") { - const chunk2 = textEncoder.encode(prefix + `; name="${escape(normalizeLinefeeds(name))}"\r -\r -${normalizeLinefeeds(value)}\r -`); - blobParts.push(chunk2); - length += chunk2.byteLength; - } else { - const chunk2 = textEncoder.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` + (value.name ? `; filename="${escape(value.name)}"` : "") + `\r -Content-Type: ${value.type || "application/octet-stream"}\r -\r -`); - blobParts.push(chunk2, value, rn); - if (typeof value.size === "number") { - length += chunk2.byteLength + value.size + rn.byteLength; - } else { - hasUnknownSizeValue = true; - } - } - } - const chunk = textEncoder.encode(`--${boundary}--`); - blobParts.push(chunk); - length += chunk.byteLength; - if (hasUnknownSizeValue) { - length = null; - } - source = object; - action = async function* () { - for (const part of blobParts) { - if (part.stream) { - yield* part.stream(); - } else { - yield part; - } - } - }; - type = `multipart/form-data; boundary=${boundary}`; - } else if (isBlobLike(object)) { - source = object; - length = object.size; - if (object.type) { - type = object.type; - } - } else if (typeof object[Symbol.asyncIterator] === "function") { - if (keepalive) { - throw new TypeError("keepalive"); - } - if (util.isDisturbed(object) || object.locked) { - throw new TypeError( - "Response body object should not be disturbed or locked" - ); - } - stream = object instanceof ReadableStream ? object : ReadableStreamFrom(object); + function isURLPotentiallyTrustworthy(url) { + if (!(url instanceof URL)) { + return false; } - if (typeof source === "string" || util.isBuffer(source)) { - length = Buffer.byteLength(source); + if (url.href === "about:blank" || url.href === "about:srcdoc") { + return true; } - if (action != null) { - let iterator; - stream = new ReadableStream({ - async start() { - iterator = action(object)[Symbol.asyncIterator](); - }, - async pull(controller) { - const { value, done } = await iterator.next(); - if (done) { - queueMicrotask(() => { - controller.close(); - controller.byobRequest?.respond(0); - }); - } else { - if (!isErrored(stream)) { - const buffer = new Uint8Array(value); - if (buffer.byteLength) { - controller.enqueue(buffer); - } - } - } - return controller.desiredSize > 0; - }, - async cancel(reason) { - await iterator.return(); - }, - type: "bytes" - }); + if (url.protocol === "data:") + return true; + if (url.protocol === "file:") + return true; + return isOriginPotentiallyTrustworthy(url.origin); + function isOriginPotentiallyTrustworthy(origin) { + if (origin == null || origin === "null") + return false; + const originAsURL = new URL(origin); + if (originAsURL.protocol === "https:" || originAsURL.protocol === "wss:") { + return true; + } + if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) || (originAsURL.hostname === "localhost" || originAsURL.hostname.includes("localhost.")) || originAsURL.hostname.endsWith(".localhost")) { + return true; + } + return false; } - const body = { stream, source, length }; - return [body, type]; } - function safelyExtractBody(object, keepalive = false) { - if (object instanceof ReadableStream) { - assert3(!util.isDisturbed(object), "The body has already been consumed."); - assert3(!object.locked, "The stream is locked."); + function bytesMatch(bytes, metadataList) { + if (crypto === void 0) { + return true; } - return extractBody(object, keepalive); - } - function cloneBody(body) { - const [out1, out2] = body.stream.tee(); - const out2Clone = structuredClone(out2, { transfer: [out2] }); - const [, finalClone] = out2Clone.tee(); - body.stream = out1; - return { - stream: finalClone, - length: body.length, - source: body.source - }; - } - async function* consumeBody(body) { - if (body) { - if (isUint8Array(body)) { - yield body; - } else { - const stream = body.stream; - if (util.isDisturbed(stream)) { - throw new TypeError("The body has already been consumed."); - } - if (stream.locked) { - throw new TypeError("The stream is locked."); + const parsedMetadata = parseMetadata(metadataList); + if (parsedMetadata === "no metadata") { + return true; + } + if (parsedMetadata.length === 0) { + return true; + } + const strongest = getStrongestMetadata(parsedMetadata); + const metadata = filterMetadataListByAlgorithm(parsedMetadata, strongest); + for (const item of metadata) { + const algorithm = item.algo; + const expectedValue = item.hash; + let actualValue = crypto.createHash(algorithm).update(bytes).digest("base64"); + if (actualValue[actualValue.length - 1] === "=") { + if (actualValue[actualValue.length - 2] === "=") { + actualValue = actualValue.slice(0, -2); + } else { + actualValue = actualValue.slice(0, -1); } - stream[kBodyUsed] = true; - yield* stream; + } + if (compareBase64Mixed(actualValue, expectedValue)) { + return true; } } + return false; } - function throwIfAborted(state) { - if (state.aborted) { - throw new DOMException("The operation was aborted.", "AbortError"); + var parseHashWithOptions = /(?sha256|sha384|sha512)-((?[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i; + function parseMetadata(metadata) { + const result = []; + let empty = true; + for (const token of metadata.split(" ")) { + empty = false; + const parsedToken = parseHashWithOptions.exec(token); + if (parsedToken === null || parsedToken.groups === void 0 || parsedToken.groups.algo === void 0) { + continue; + } + const algorithm = parsedToken.groups.algo.toLowerCase(); + if (supportedHashes.includes(algorithm)) { + result.push(parsedToken.groups); + } } + if (empty === true) { + return "no metadata"; + } + return result; } - function bodyMixinMethods(instance) { - const methods = { - blob() { - return specConsumeBody(this, (bytes) => { - let mimeType = bodyMimeType(this); - if (mimeType === null) { - mimeType = ""; - } else if (mimeType) { - mimeType = serializeAMimeType(mimeType); - } - return new Blob2([bytes], { type: mimeType }); - }, instance); - }, - arrayBuffer() { - return specConsumeBody(this, (bytes) => { - return new Uint8Array(bytes).buffer; - }, instance); - }, - text() { - return specConsumeBody(this, utf8DecodeBytes, instance); - }, - json() { - return specConsumeBody(this, parseJSONFromBytes, instance); - }, - async formData() { - webidl.brandCheck(this, instance); - throwIfAborted(this[kState]); - const mimeType = bodyMimeType(this); - if (mimeType !== null && mimeType.essence === "multipart/form-data") { - const headers = {}; - for (const [key, value] of this.headers) - headers[key] = value; - const responseFormData = new FormData(); - let busboy; - try { - busboy = new Busboy({ - headers, - preservePath: true - }); - } catch (err) { - throw new DOMException(`${err}`, "AbortError"); - } - busboy.on("field", (name, value) => { - responseFormData.append(name, value); - }); - busboy.on("file", (name, value, filename, encoding, mimeType2) => { - const chunks = []; - if (encoding === "base64" || encoding.toLowerCase() === "base64") { - let base64chunk = ""; - value.on("data", (chunk) => { - base64chunk += chunk.toString().replace(/[\r\n]/gm, ""); - const end = base64chunk.length - base64chunk.length % 4; - chunks.push(Buffer.from(base64chunk.slice(0, end), "base64")); - base64chunk = base64chunk.slice(end); - }); - value.on("end", () => { - chunks.push(Buffer.from(base64chunk, "base64")); - responseFormData.append(name, new File(chunks, filename, { type: mimeType2 })); - }); - } else { - value.on("data", (chunk) => { - chunks.push(chunk); - }); - value.on("end", () => { - responseFormData.append(name, new File(chunks, filename, { type: mimeType2 })); - }); - } - }); - const busboyResolve = new Promise((resolve, reject) => { - busboy.on("finish", resolve); - busboy.on("error", (err) => reject(new TypeError(err))); - }); - if (this.body !== null) - for await (const chunk of consumeBody(this[kState].body)) - busboy.write(chunk); - busboy.end(); - await busboyResolve; - return responseFormData; - } else if (mimeType !== null && mimeType.essence === "application/x-www-form-urlencoded") { - let entries; - try { - let text = ""; - const streamingDecoder = new TextDecoder("utf-8", { ignoreBOM: true }); - for await (const chunk of consumeBody(this[kState].body)) { - if (!isUint8Array(chunk)) { - throw new TypeError("Expected Uint8Array chunk"); - } - text += streamingDecoder.decode(chunk, { stream: true }); - } - text += streamingDecoder.decode(); - entries = new URLSearchParams(text); - } catch (err) { - throw new TypeError(void 0, { cause: err }); - } - const formData = new FormData(); - for (const [name, value] of entries) { - formData.append(name, value); - } - return formData; - } else { - await Promise.resolve(); - throwIfAborted(this[kState]); - throw webidl.errors.exception({ - header: `${instance.name}.formData`, - message: "Could not parse content as FormData." - }); - } + function getStrongestMetadata(metadataList) { + let algorithm = metadataList[0].algo; + if (algorithm[3] === "5") { + return algorithm; + } + for (let i = 1; i < metadataList.length; ++i) { + const metadata = metadataList[i]; + if (metadata.algo[3] === "5") { + algorithm = "sha512"; + break; + } else if (algorithm[3] === "3") { + continue; + } else if (metadata.algo[3] === "3") { + algorithm = "sha384"; } - }; - return methods; + } + return algorithm; } - function mixinBody(prototype) { - Object.assign(prototype.prototype, bodyMixinMethods(prototype)); + function filterMetadataListByAlgorithm(metadataList, algorithm) { + if (metadataList.length === 1) { + return metadataList; + } + let pos = 0; + for (let i = 0; i < metadataList.length; ++i) { + if (metadataList[i].algo === algorithm) { + metadataList[pos++] = metadataList[i]; + } + } + metadataList.length = pos; + return metadataList; } - async function specConsumeBody(object, convertBytesToJSValue, instance) { - webidl.brandCheck(object, instance); - throwIfAborted(object[kState]); - if (bodyUnusable(object[kState].body)) { - throw new TypeError("Body is unusable"); + function compareBase64Mixed(actualValue, expectedValue) { + if (actualValue.length !== expectedValue.length) { + return false; } - const promise = createDeferredPromise(); - const errorSteps = (error) => promise.reject(error); - const successSteps = (data) => { - try { - promise.resolve(convertBytesToJSValue(data)); - } catch (e) { - errorSteps(e); + for (let i = 0; i < actualValue.length; ++i) { + if (actualValue[i] !== expectedValue[i]) { + if (actualValue[i] === "+" && expectedValue[i] === "-" || actualValue[i] === "/" && expectedValue[i] === "_") { + continue; + } + return false; } - }; - if (object[kState].body == null) { - successSteps(new Uint8Array()); - return promise.promise; } - await fullyReadBody(object[kState].body, successSteps, errorSteps); - return promise.promise; + return true; } - function bodyUnusable(body) { - return body != null && (body.stream.locked || util.isDisturbed(body.stream)); + function tryUpgradeRequestToAPotentiallyTrustworthyURL(request) { } - function utf8DecodeBytes(buffer) { - if (buffer.length === 0) { - return ""; + function sameOrigin(A, B) { + if (A.origin === B.origin && A.origin === "null") { + return true; } - if (buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191) { - buffer = buffer.subarray(3); + if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { + return true; } - const output = textDecoder.decode(buffer); - return output; + return false; } - function parseJSONFromBytes(bytes) { - return JSON.parse(utf8DecodeBytes(bytes)); + function createDeferredPromise() { + let res; + let rej; + const promise = new Promise((resolve, reject) => { + res = resolve; + rej = reject; + }); + return { promise, resolve: res, reject: rej }; } - function bodyMimeType(requestOrResponse) { - const headers = requestOrResponse[kState].headersList; - const mimeType = extractMimeType(headers); - if (mimeType === "failure") { - return null; - } - return mimeType; + function isAborted(fetchParams) { + return fetchParams.controller.state === "aborted"; } - module2.exports = { - extractBody, - safelyExtractBody, - cloneBody, - mixinBody - }; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/request.js -var require_request = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/request.js"(exports, module2) { - "use strict"; - var { - InvalidArgumentError, - NotSupportedError - } = require_errors(); - var assert3 = require("node:assert"); - var { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = require_symbols(); - var util = require_util(); - var { channels } = require_diagnostics(); - var { headerNameLowerCasedRecord } = require_constants2(); - var headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; - var invalidPathRegex = /[^\u0021-\u00ff]/; - var kHandler = Symbol("handler"); - var extractBody; - var Request = class _Request { - constructor(origin, { - path: path10, - method, - body, - headers, - query, - idempotent, - blocking, - upgrade, - headersTimeout, - bodyTimeout, - reset, - throwOnError, - expectContinue - }, handler) { - if (typeof path10 !== "string") { - throw new InvalidArgumentError("path must be a string"); - } else if (path10[0] !== "/" && !(path10.startsWith("http://") || path10.startsWith("https://")) && method !== "CONNECT") { - throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); - } else if (invalidPathRegex.exec(path10) !== null) { - throw new InvalidArgumentError("invalid request path"); - } - if (typeof method !== "string") { - throw new InvalidArgumentError("method must be a string"); - } else if (!util.isValidHTTPToken(method)) { - throw new InvalidArgumentError("invalid request method"); - } - if (upgrade && typeof upgrade !== "string") { - throw new InvalidArgumentError("upgrade must be a string"); - } - if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { - throw new InvalidArgumentError("invalid headersTimeout"); - } - if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { - throw new InvalidArgumentError("invalid bodyTimeout"); - } - if (reset != null && typeof reset !== "boolean") { - throw new InvalidArgumentError("invalid reset"); - } - if (expectContinue != null && typeof expectContinue !== "boolean") { - throw new InvalidArgumentError("invalid expectContinue"); - } - this.headersTimeout = headersTimeout; - this.bodyTimeout = bodyTimeout; - this.throwOnError = throwOnError === true; - this.method = method; - this.abort = null; - if (body == null) { - this.body = null; - } else if (util.isStream(body)) { - this.body = body; - const rState = this.body._readableState; - if (!rState || !rState.autoDestroy) { - this.endHandler = function autoDestroy() { - util.destroy(this); + function isCancelled(fetchParams) { + return fetchParams.controller.state === "aborted" || fetchParams.controller.state === "terminated"; + } + var normalizeMethodRecordBase = { + delete: "DELETE", + DELETE: "DELETE", + get: "GET", + GET: "GET", + head: "HEAD", + HEAD: "HEAD", + options: "OPTIONS", + OPTIONS: "OPTIONS", + post: "POST", + POST: "POST", + put: "PUT", + PUT: "PUT" + }; + var normalizeMethodRecord = { + ...normalizeMethodRecordBase, + patch: "patch", + PATCH: "PATCH" + }; + Object.setPrototypeOf(normalizeMethodRecordBase, null); + Object.setPrototypeOf(normalizeMethodRecord, null); + function normalizeMethod(method) { + return normalizeMethodRecordBase[method.toLowerCase()] ?? method; + } + function serializeJavascriptValueToJSONString(value) { + const result = JSON.stringify(value); + if (result === void 0) { + throw new TypeError("Value is not JSON serializable"); + } + assert3(typeof result === "string"); + return result; + } + var esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())); + function createIterator(name, kInternalIterator, keyIndex = 0, valueIndex = 1) { + class FastIterableIterator { + /** @type {any} */ + #target; + /** @type {'key' | 'value' | 'key+value'} */ + #kind; + /** @type {number} */ + #index; + /** + * @see https://webidl.spec.whatwg.org/#dfn-default-iterator-object + * @param {unknown} target + * @param {'key' | 'value' | 'key+value'} kind + */ + constructor(target, kind) { + this.#target = target; + this.#kind = kind; + this.#index = 0; + } + next() { + if (typeof this !== "object" || this === null || !(#target in this)) { + throw new TypeError( + `'next' called on an object that does not implement interface ${name} Iterator.` + ); + } + const index = this.#index; + const values = this.#target[kInternalIterator]; + const len = values.length; + if (index >= len) { + return { + value: void 0, + done: true }; - this.body.on("end", this.endHandler); } - this.errorHandler = (err) => { - if (this.abort) { - this.abort(err); - } else { - this.error = err; - } + const { [keyIndex]: key, [valueIndex]: value } = values[index]; + this.#index = index + 1; + let result; + switch (this.#kind) { + case "key": + result = key; + break; + case "value": + result = value; + break; + case "key+value": + result = [key, value]; + break; + } + return { + value: result, + done: false }; - this.body.on("error", this.errorHandler); - } else if (util.isBuffer(body)) { - this.body = body.byteLength ? body : null; - } else if (ArrayBuffer.isView(body)) { - this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null; - } else if (body instanceof ArrayBuffer) { - this.body = body.byteLength ? Buffer.from(body) : null; - } else if (typeof body === "string") { - this.body = body.length ? Buffer.from(body) : null; - } else if (util.isFormDataLike(body) || util.isIterable(body) || util.isBlobLike(body)) { - this.body = body; - } else { - throw new InvalidArgumentError("body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable"); } - this.completed = false; - this.aborted = false; - this.upgrade = upgrade || null; - this.path = query ? util.buildURL(path10, query) : path10; - this.origin = origin; - this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; - this.blocking = blocking == null ? false : blocking; - this.reset = reset == null ? null : reset; - this.host = null; - this.contentLength = null; - this.contentType = null; - this.headers = ""; - this.expectContinue = expectContinue != null ? expectContinue : false; - if (Array.isArray(headers)) { - if (headers.length % 2 !== 0) { - throw new InvalidArgumentError("headers array must be even"); - } - for (let i = 0; i < headers.length; i += 2) { - processHeader(this, headers[i], headers[i + 1]); + } + delete FastIterableIterator.prototype.constructor; + Object.setPrototypeOf(FastIterableIterator.prototype, esIteratorPrototype); + Object.defineProperties(FastIterableIterator.prototype, { + [Symbol.toStringTag]: { + writable: false, + enumerable: false, + configurable: true, + value: `${name} Iterator` + }, + next: { writable: true, enumerable: true, configurable: true } + }); + return function(target, kind) { + return new FastIterableIterator(target, kind); + }; + } + function iteratorMixin(name, object, kInternalIterator, keyIndex = 0, valueIndex = 1) { + const makeIterator = createIterator(name, kInternalIterator, keyIndex, valueIndex); + const properties = { + keys: { + writable: true, + enumerable: true, + configurable: true, + value: function keys() { + webidl.brandCheck(this, object); + return makeIterator(this, "key"); } - } else if (headers && typeof headers === "object") { - const keys = Object.keys(headers); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - processHeader(this, key, headers[key]); + }, + values: { + writable: true, + enumerable: true, + configurable: true, + value: function values() { + webidl.brandCheck(this, object); + return makeIterator(this, "value"); } - } else if (headers != null) { - throw new InvalidArgumentError("headers must be an object or an array"); - } - if (util.isFormDataLike(this.body)) { - if (!extractBody) { - extractBody = require_body().extractBody; + }, + entries: { + writable: true, + enumerable: true, + configurable: true, + value: function entries() { + webidl.brandCheck(this, object); + return makeIterator(this, "key+value"); } - const [bodyStream, contentType] = extractBody(body); - if (this.contentType == null) { - this.contentType = contentType; - this.headers += `content-type: ${contentType}\r -`; + }, + forEach: { + writable: true, + enumerable: true, + configurable: true, + value: function forEach(callbackfn, thisArg = globalThis) { + webidl.brandCheck(this, object); + webidl.argumentLengthCheck(arguments, 1, { header: `${name}.forEach` }); + if (typeof callbackfn !== "function") { + throw new TypeError( + `Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.` + ); + } + for (const { 0: key, 1: value } of makeIterator(this, "key+value")) { + callbackfn.call(thisArg, value, key, this); + } } - this.body = bodyStream.stream; - this.contentLength = bodyStream.length; - } else if (util.isBlobLike(body) && this.contentType == null && body.type) { - this.contentType = body.type; - this.headers += `content-type: ${body.type}\r -`; } - util.validateHandler(handler, method, upgrade); - this.servername = util.getServerName(this.host); - this[kHandler] = handler; - if (channels.create.hasSubscribers) { - channels.create.publish({ request: this }); + }; + return Object.defineProperties(object.prototype, { + ...properties, + [Symbol.iterator]: { + writable: true, + enumerable: false, + configurable: true, + value: properties.entries.value + } + }); + } + async function fullyReadBody(body, processBody, processBodyError) { + const successSteps = processBody; + const errorSteps = processBodyError; + let reader; + try { + reader = body.stream.getReader(); + } catch (e) { + errorSteps(e); + return; + } + try { + const result = await readAllBytes(reader); + successSteps(result); + } catch (e) { + errorSteps(e); + } + } + function isReadableStreamLike(stream) { + return stream instanceof ReadableStream || stream[Symbol.toStringTag] === "ReadableStream" && typeof stream.tee === "function"; + } + function readableStreamClose(controller) { + try { + controller.close(); + controller.byobRequest?.respond(0); + } catch (err) { + if (!err.message.includes("Controller is already closed") && !err.message.includes("ReadableStream is already closed")) { + throw err; } } - onBodySent(chunk) { - if (this[kHandler].onBodySent) { - try { - return this[kHandler].onBodySent(chunk); - } catch (err) { - this.abort(err); - } + } + function isomorphicEncode(input) { + for (let i = 0; i < input.length; i++) { + assert3(input.charCodeAt(i) <= 255); + } + return input; + } + async function readAllBytes(reader) { + const bytes = []; + let byteLength = 0; + while (true) { + const { done, value: chunk } = await reader.read(); + if (done) { + return Buffer.concat(bytes, byteLength); + } + if (!isUint8Array(chunk)) { + throw new TypeError("Received non-Uint8Array chunk"); } + bytes.push(chunk); + byteLength += chunk.length; + } + } + function urlIsLocal(url) { + assert3("protocol" in url); + const protocol = url.protocol; + return protocol === "about:" || protocol === "blob:" || protocol === "data:"; + } + function urlHasHttpsScheme(url) { + return typeof url === "string" && url[5] === ":" && url[0] === "h" && url[1] === "t" && url[2] === "t" && url[3] === "p" && url[4] === "s" || url.protocol === "https:"; + } + function urlIsHttpHttpsScheme(url) { + assert3("protocol" in url); + const protocol = url.protocol; + return protocol === "http:" || protocol === "https:"; + } + function simpleRangeHeaderValue(value, allowWhitespace) { + const data = value; + if (!data.startsWith("bytes")) { + return "failure"; + } + const position = { position: 5 }; + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === " " || char === " ", + data, + position + ); + } + if (data.charCodeAt(position.position) !== 61) { + return "failure"; + } + position.position++; + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === " " || char === " ", + data, + position + ); + } + const rangeStart = collectASequenceOfCodePoints( + (char) => { + const code = char.charCodeAt(0); + return code >= 48 && code <= 57; + }, + data, + position + ); + const rangeStartValue = rangeStart.length ? Number(rangeStart) : null; + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === " " || char === " ", + data, + position + ); + } + if (data.charCodeAt(position.position) !== 45) { + return "failure"; + } + position.position++; + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === " " || char === " ", + data, + position + ); + } + const rangeEnd = collectASequenceOfCodePoints( + (char) => { + const code = char.charCodeAt(0); + return code >= 48 && code <= 57; + }, + data, + position + ); + const rangeEndValue = rangeEnd.length ? Number(rangeEnd) : null; + if (position.position < data.length) { + return "failure"; + } + if (rangeEndValue === null && rangeStartValue === null) { + return "failure"; } - onRequestSent() { - if (channels.bodySent.hasSubscribers) { - channels.bodySent.publish({ request: this }); - } - if (this[kHandler].onRequestSent) { - try { - return this[kHandler].onRequestSent(); - } catch (err) { - this.abort(err); + if (rangeStartValue > rangeEndValue) { + return "failure"; + } + return { rangeStartValue, rangeEndValue }; + } + function buildContentRange(rangeStart, rangeEnd, fullLength) { + let contentRange = "bytes "; + contentRange += isomorphicEncode(`${rangeStart}`); + contentRange += "-"; + contentRange += isomorphicEncode(`${rangeEnd}`); + contentRange += "/"; + contentRange += isomorphicEncode(`${fullLength}`); + return contentRange; + } + var InflateStream = class extends Transform { + _transform(chunk, encoding, callback) { + if (!this._inflateStream) { + if (chunk.length === 0) { + callback(); + return; } + this._inflateStream = (chunk[0] & 15) === 8 ? zlib.createInflate() : zlib.createInflateRaw(); + this._inflateStream.on("data", this.push.bind(this)); + this._inflateStream.on("end", () => this.push(null)); + this._inflateStream.on("error", (err) => this.destroy(err)); } + this._inflateStream.write(chunk, encoding, callback); } - onConnect(abort) { - assert3(!this.aborted); - assert3(!this.completed); - if (this.error) { - abort(this.error); - } else { - this.abort = abort; - return this[kHandler].onConnect(abort); + _final(callback) { + if (this._inflateStream) { + this._inflateStream.end(); + this._inflateStream = null; } + callback(); } - onResponseStarted() { - return this[kHandler].onResponseStarted?.(); + }; + function createInflate() { + return new InflateStream(); + } + function extractMimeType(headers) { + let charset = null; + let essence = null; + let mimeType = null; + const values = getDecodeSplit("content-type", headers); + if (values === null) { + return "failure"; } - onHeaders(statusCode, headers, resume, statusText) { - assert3(!this.aborted); - assert3(!this.completed); - if (channels.headers.hasSubscribers) { - channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }); + for (const value of values) { + const temporaryMimeType = parseMIMEType(value); + if (temporaryMimeType === "failure" || temporaryMimeType.essence === "*/*") { + continue; } - try { - return this[kHandler].onHeaders(statusCode, headers, resume, statusText); - } catch (err) { - this.abort(err); + mimeType = temporaryMimeType; + if (mimeType.essence !== essence) { + charset = null; + if (mimeType.parameters.has("charset")) { + charset = mimeType.parameters.get("charset"); + } + essence = mimeType.essence; + } else if (!mimeType.parameters.has("charset") && charset !== null) { + mimeType.parameters.set("charset", charset); } } - onData(chunk) { - assert3(!this.aborted); - assert3(!this.completed); - try { - return this[kHandler].onData(chunk); - } catch (err) { - this.abort(err); - return false; + if (mimeType == null) { + return "failure"; + } + return mimeType; + } + function gettingDecodingSplitting(value) { + const input = value; + const position = { position: 0 }; + const values = []; + let temporaryValue = ""; + while (position.position < input.length) { + temporaryValue += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== ",", + input, + position + ); + if (position.position < input.length) { + if (input.charCodeAt(position.position) === 34) { + temporaryValue += collectAnHTTPQuotedString( + input, + position + ); + if (position.position < input.length) { + continue; + } + } else { + assert3(input.charCodeAt(position.position) === 44); + position.position++; + } } + temporaryValue = removeChars(temporaryValue, true, true, (char) => char === 9 || char === 32); + values.push(temporaryValue); + temporaryValue = ""; } - onUpgrade(statusCode, headers, socket) { - assert3(!this.aborted); - assert3(!this.completed); - return this[kHandler].onUpgrade(statusCode, headers, socket); + return values; + } + function getDecodeSplit(name, list) { + const value = list.get(name, true); + if (value === null) { + return null; } - onComplete(trailers) { - this.onFinally(); - assert3(!this.aborted); - this.completed = true; - if (channels.trailers.hasSubscribers) { - channels.trailers.publish({ request: this, trailers }); - } - try { - return this[kHandler].onComplete(trailers); - } catch (err) { - this.onError(err); - } + return gettingDecodingSplitting(value); + } + var textDecoder = new TextDecoder(); + function utf8DecodeBytes(buffer) { + if (buffer.length === 0) { + return ""; } - onError(error) { - this.onFinally(); - if (channels.error.hasSubscribers) { - channels.error.publish({ request: this, error }); - } - if (this.aborted) { - return; - } - this.aborted = true; - return this[kHandler].onError(error); + if (buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191) { + buffer = buffer.subarray(3); } - onFinally() { - if (this.errorHandler) { - this.body.off("error", this.errorHandler); - this.errorHandler = null; - } - if (this.endHandler) { - this.body.off("end", this.endHandler); - this.endHandler = null; + const output = textDecoder.decode(buffer); + return output; + } + module2.exports = { + isAborted, + isCancelled, + isValidEncodedURL, + createDeferredPromise, + ReadableStreamFrom, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + clampAndCoarsenConnectionTimingInfo, + coarsenedSharedCurrentTime, + determineRequestsReferrer, + makePolicyContainer, + clonePolicyContainer, + appendFetchMetadata, + appendRequestOriginHeader, + TAOCheck, + corsCheck, + crossOriginResourcePolicyCheck, + createOpaqueTimingInfo, + setRequestReferrerPolicyOnRedirect, + isValidHTTPToken, + requestBadPort, + requestCurrentURL, + responseURL, + responseLocationURL, + isBlobLike, + isURLPotentiallyTrustworthy, + isValidReasonPhrase, + sameOrigin, + normalizeMethod, + serializeJavascriptValueToJSONString, + iteratorMixin, + createIterator, + isValidHeaderName, + isValidHeaderValue, + isErrorLike, + fullyReadBody, + bytesMatch, + isReadableStreamLike, + readableStreamClose, + isomorphicEncode, + urlIsLocal, + urlHasHttpsScheme, + urlIsHttpHttpsScheme, + readAllBytes, + normalizeMethodRecord, + simpleRangeHeaderValue, + buildContentRange, + parseMetadata, + createInflate, + extractMimeType, + getDecodeSplit, + utf8DecodeBytes + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/symbols.js +var require_symbols2 = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/symbols.js"(exports, module2) { + "use strict"; + module2.exports = { + kUrl: Symbol("url"), + kHeaders: Symbol("headers"), + kSignal: Symbol("signal"), + kState: Symbol("state"), + kGuard: Symbol("guard"), + kRealm: Symbol("realm"), + kDispatcher: Symbol("dispatcher") + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/file.js +var require_file = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/file.js"(exports, module2) { + "use strict"; + var { EOL } = require("node:os"); + var { Blob: Blob2, File: NativeFile } = require("node:buffer"); + var { types } = require("node:util"); + var { kState } = require_symbols2(); + var { isBlobLike } = require_util3(); + var { webidl } = require_webidl(); + var { parseMIMEType, serializeAMimeType } = require_data_url(); + var { kEnumerableProperty } = require_util(); + var encoder = new TextEncoder(); + var File = class _File extends Blob2 { + constructor(fileBits, fileName, options = {}) { + webidl.argumentLengthCheck(arguments, 2, { header: "File constructor" }); + fileBits = webidl.converters["sequence"](fileBits); + fileName = webidl.converters.USVString(fileName); + options = webidl.converters.FilePropertyBag(options); + const n = fileName; + let t = options.type; + let d; + substep: { + if (t) { + t = parseMIMEType(t); + if (t === "failure") { + t = ""; + break substep; + } + t = serializeAMimeType(t).toLowerCase(); + } + d = options.lastModified; } + super(processBlobParts(fileBits, options), { type: t }); + this[kState] = { + name: n, + lastModified: d, + type: t + }; } - // TODO: adjust to support H2 - addHeader(key, value) { - processHeader(this, key, value); - return this; - } - static [kHTTP1BuildRequest](origin, opts, handler) { - return new _Request(origin, opts, handler); + get name() { + webidl.brandCheck(this, _File); + return this[kState].name; } - static [kHTTP2BuildRequest](origin, opts, handler) { - const headers = opts.headers; - opts = { ...opts, headers: null }; - const request = new _Request(origin, opts, handler); - request.headers = {}; - if (Array.isArray(headers)) { - if (headers.length % 2 !== 0) { - throw new InvalidArgumentError("headers array must be even"); - } - for (let i = 0; i < headers.length; i += 2) { - processHeader(request, headers[i], headers[i + 1], true); - } - } else if (headers && typeof headers === "object") { - const keys = Object.keys(headers); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - processHeader(request, key, headers[key], true); - } - } else if (headers != null) { - throw new InvalidArgumentError("headers must be an object or an array"); - } - return request; + get lastModified() { + webidl.brandCheck(this, _File); + return this[kState].lastModified; } - static [kHTTP2CopyHeaders](raw) { - const rawHeaders = raw.split("\r\n"); - const headers = {}; - for (const header of rawHeaders) { - const [key, value] = header.split(": "); - if (value == null || value.length === 0) - continue; - if (headers[key]) { - headers[key] += `,${value}`; - } else { - headers[key] = value; - } - } - return headers; + get type() { + webidl.brandCheck(this, _File); + return this[kState].type; } }; - function processHeaderValue(key, val, skipAppend) { - if (val && typeof val === "object") { - throw new InvalidArgumentError(`invalid ${key} header`); + var FileLike = class _FileLike { + constructor(blobLike, fileName, options = {}) { + const n = fileName; + const t = options.type; + const d = options.lastModified ?? Date.now(); + this[kState] = { + blobLike, + name: n, + type: t, + lastModified: d + }; } - val = val != null ? `${val}` : ""; - if (headerCharRegex.exec(val) !== null) { - throw new InvalidArgumentError(`invalid ${key} header`); + stream(...args) { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.stream(...args); } - return skipAppend ? val : `${key}: ${val}\r -`; - } - function processHeader(request, key, val, skipAppend = false) { - if (val && (typeof val === "object" && !Array.isArray(val))) { - throw new InvalidArgumentError(`invalid ${key} header`); - } else if (val === void 0) { - return; + arrayBuffer(...args) { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.arrayBuffer(...args); } - let headerName = headerNameLowerCasedRecord[key]; - if (headerName === void 0) { - headerName = key.toLowerCase(); - if (headerNameLowerCasedRecord[headerName] === void 0 && !util.isValidHTTPToken(headerName)) { - throw new InvalidArgumentError("invalid header key"); - } + slice(...args) { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.slice(...args); } - if (request.host === null && headerName === "host") { - if (headerCharRegex.exec(val) !== null) { - throw new InvalidArgumentError(`invalid ${key} header`); - } - request.host = val; - } else if (request.contentLength === null && headerName === "content-length") { - request.contentLength = parseInt(val, 10); - if (!Number.isFinite(request.contentLength)) { - throw new InvalidArgumentError("invalid content-length header"); - } - } else if (request.contentType === null && headerName === "content-type") { - request.contentType = val; - if (skipAppend) - request.headers[key] = processHeaderValue(key, val, skipAppend); - else - request.headers += processHeaderValue(key, val); - } else if (headerName === "transfer-encoding" || headerName === "keep-alive" || headerName === "upgrade") { - throw new InvalidArgumentError(`invalid ${headerName} header`); - } else if (headerName === "connection") { - const value = typeof val === "string" ? val.toLowerCase() : null; - if (value !== "close" && value !== "keep-alive") { - throw new InvalidArgumentError("invalid connection header"); - } else if (value === "close") { - request.reset = true; - } - } else if (headerName === "expect") { - throw new NotSupportedError("expect header not supported"); - } else if (Array.isArray(val)) { - for (let i = 0; i < val.length; i++) { - if (skipAppend) { - if (request.headers[key]) { - request.headers[key] += `,${processHeaderValue(key, val[i], skipAppend)}`; - } else { - request.headers[key] = processHeaderValue(key, val[i], skipAppend); - } - } else { - request.headers += processHeaderValue(key, val[i]); - } - } - } else if (skipAppend) { - request.headers[key] = processHeaderValue(key, val, skipAppend); - } else { - request.headers += processHeaderValue(key, val); + text(...args) { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.text(...args); } - } - module2.exports = Request; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/connect.js -var require_connect = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/core/connect.js"(exports, module2) { - "use strict"; - var net = require("node:net"); - var assert3 = require("node:assert"); - var util = require_util(); - var { InvalidArgumentError, ConnectTimeoutError } = require_errors(); - var tls; - var SessionCache; - if (global.FinalizationRegistry && !(process.env.NODE_V8_COVERAGE || process.env.UNDICI_NO_FG)) { - SessionCache = class WeakSessionCache { - constructor(maxCachedSessions) { - this._maxCachedSessions = maxCachedSessions; - this._sessionCache = /* @__PURE__ */ new Map(); - this._sessionRegistry = new global.FinalizationRegistry((key) => { - if (this._sessionCache.size < this._maxCachedSessions) { - return; - } - const ref = this._sessionCache.get(key); - if (ref !== void 0 && ref.deref() === void 0) { - this._sessionCache.delete(key); - } - }); - } - get(sessionKey) { - const ref = this._sessionCache.get(sessionKey); - return ref ? ref.deref() : null; - } - set(sessionKey, session) { - if (this._maxCachedSessions === 0) { - return; - } - this._sessionCache.set(sessionKey, new WeakRef(session)); - this._sessionRegistry.register(session, sessionKey); - } - }; - } else { - SessionCache = class SimpleSessionCache { - constructor(maxCachedSessions) { - this._maxCachedSessions = maxCachedSessions; - this._sessionCache = /* @__PURE__ */ new Map(); - } - get(sessionKey) { - return this._sessionCache.get(sessionKey); - } - set(sessionKey, session) { - if (this._maxCachedSessions === 0) { - return; - } - if (this._sessionCache.size >= this._maxCachedSessions) { - const { value: oldestKey } = this._sessionCache.keys().next(); - this._sessionCache.delete(oldestKey); - } - this._sessionCache.set(sessionKey, session); - } - }; - } - function buildConnector({ allowH2, maxCachedSessions, socketPath, timeout, ...opts }) { - if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { - throw new InvalidArgumentError("maxCachedSessions must be a positive integer or zero"); + get size() { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.size; } - const options = { path: socketPath, ...opts }; - const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions); - timeout = timeout == null ? 1e4 : timeout; - allowH2 = allowH2 != null ? allowH2 : false; - return function connect({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { - let socket; - if (protocol === "https:") { - if (!tls) { - tls = require("node:tls"); - } - servername = servername || options.servername || util.getServerName(host) || null; - const sessionKey = servername || hostname; - const session = sessionCache.get(sessionKey) || null; - assert3(sessionKey); - socket = tls.connect({ - highWaterMark: 16384, - // TLS in node can't have bigger HWM anyway... - ...options, - servername, - session, - localAddress, - // TODO(HTTP/2): Add support for h2c - ALPNProtocols: allowH2 ? ["http/1.1", "h2"] : ["http/1.1"], - socket: httpSocket, - // upgrade socket connection - port: port || 443, - host: hostname - }); - socket.on("session", function(session2) { - sessionCache.set(sessionKey, session2); - }); - } else { - assert3(!httpSocket, "httpSocket can only be sent on TLS update"); - socket = net.connect({ - highWaterMark: 64 * 1024, - // Same as nodejs fs streams. - ...options, - localAddress, - port: port || 80, - host: hostname - }); - } - if (options.keepAlive == null || options.keepAlive) { - const keepAliveInitialDelay = options.keepAliveInitialDelay === void 0 ? 6e4 : options.keepAliveInitialDelay; - socket.setKeepAlive(true, keepAliveInitialDelay); - } - const cancelTimeout = setupTimeout(() => onConnectTimeout(socket), timeout); - socket.setNoDelay(true).once(protocol === "https:" ? "secureConnect" : "connect", function() { - cancelTimeout(); - if (callback) { - const cb = callback; - callback = null; - cb(null, this); - } - }).on("error", function(err) { - cancelTimeout(); - if (callback) { - const cb = callback; - callback = null; - cb(err); - } - }); - return socket; - }; - } - function setupTimeout(onConnectTimeout2, timeout) { - if (!timeout) { - return () => { - }; + get type() { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.type; + } + get name() { + webidl.brandCheck(this, _FileLike); + return this[kState].name; + } + get lastModified() { + webidl.brandCheck(this, _FileLike); + return this[kState].lastModified; + } + get [Symbol.toStringTag]() { + return "File"; } - let s1 = null; - let s2 = null; - const timeoutId = setTimeout(() => { - s1 = setImmediate(() => { - if (process.platform === "win32") { - s2 = setImmediate(() => onConnectTimeout2()); - } else { - onConnectTimeout2(); - } - }); - }, timeout); - return () => { - clearTimeout(timeoutId); - clearImmediate(s1); - clearImmediate(s2); - }; - } - function onConnectTimeout(socket) { - let message = "Connect Timeout Error"; - if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) { - message = +` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(", ")})`; + }; + Object.defineProperties(File.prototype, { + [Symbol.toStringTag]: { + value: "File", + configurable: true + }, + name: kEnumerableProperty, + lastModified: kEnumerableProperty + }); + webidl.converters.Blob = webidl.interfaceConverter(Blob2); + webidl.converters.BlobPart = function(V, opts) { + if (webidl.util.Type(V) === "Object") { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }); + } + if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) { + return webidl.converters.BufferSource(V, opts); + } } - util.destroy(socket, new ConnectTimeoutError(message)); - } - module2.exports = buildConnector; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/llhttp/utils.js -var require_utils = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/llhttp/utils.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.enumToMap = void 0; - function enumToMap(obj) { - const res = {}; - Object.keys(obj).forEach((key) => { - const value = obj[key]; - if (typeof value === "number") { - res[key] = value; + return webidl.converters.USVString(V, opts); + }; + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.BlobPart + ); + webidl.converters.FilePropertyBag = webidl.dictionaryConverter([ + { + key: "lastModified", + converter: webidl.converters["long long"], + get defaultValue() { + return Date.now(); } - }); - return res; - } - exports.enumToMap = enumToMap; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/llhttp/constants.js -var require_constants4 = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/llhttp/constants.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.SPECIAL_HEADERS = exports.HEADER_STATE = exports.MINOR = exports.MAJOR = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.STRICT_TOKEN = exports.HEX = exports.URL_CHAR = exports.STRICT_URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.FINISH = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; - var utils_1 = require_utils(); - var ERROR; - (function(ERROR2) { - ERROR2[ERROR2["OK"] = 0] = "OK"; - ERROR2[ERROR2["INTERNAL"] = 1] = "INTERNAL"; - ERROR2[ERROR2["STRICT"] = 2] = "STRICT"; - ERROR2[ERROR2["LF_EXPECTED"] = 3] = "LF_EXPECTED"; - ERROR2[ERROR2["UNEXPECTED_CONTENT_LENGTH"] = 4] = "UNEXPECTED_CONTENT_LENGTH"; - ERROR2[ERROR2["CLOSED_CONNECTION"] = 5] = "CLOSED_CONNECTION"; - ERROR2[ERROR2["INVALID_METHOD"] = 6] = "INVALID_METHOD"; - ERROR2[ERROR2["INVALID_URL"] = 7] = "INVALID_URL"; - ERROR2[ERROR2["INVALID_CONSTANT"] = 8] = "INVALID_CONSTANT"; - ERROR2[ERROR2["INVALID_VERSION"] = 9] = "INVALID_VERSION"; - ERROR2[ERROR2["INVALID_HEADER_TOKEN"] = 10] = "INVALID_HEADER_TOKEN"; - ERROR2[ERROR2["INVALID_CONTENT_LENGTH"] = 11] = "INVALID_CONTENT_LENGTH"; - ERROR2[ERROR2["INVALID_CHUNK_SIZE"] = 12] = "INVALID_CHUNK_SIZE"; - ERROR2[ERROR2["INVALID_STATUS"] = 13] = "INVALID_STATUS"; - ERROR2[ERROR2["INVALID_EOF_STATE"] = 14] = "INVALID_EOF_STATE"; - ERROR2[ERROR2["INVALID_TRANSFER_ENCODING"] = 15] = "INVALID_TRANSFER_ENCODING"; - ERROR2[ERROR2["CB_MESSAGE_BEGIN"] = 16] = "CB_MESSAGE_BEGIN"; - ERROR2[ERROR2["CB_HEADERS_COMPLETE"] = 17] = "CB_HEADERS_COMPLETE"; - ERROR2[ERROR2["CB_MESSAGE_COMPLETE"] = 18] = "CB_MESSAGE_COMPLETE"; - ERROR2[ERROR2["CB_CHUNK_HEADER"] = 19] = "CB_CHUNK_HEADER"; - ERROR2[ERROR2["CB_CHUNK_COMPLETE"] = 20] = "CB_CHUNK_COMPLETE"; - ERROR2[ERROR2["PAUSED"] = 21] = "PAUSED"; - ERROR2[ERROR2["PAUSED_UPGRADE"] = 22] = "PAUSED_UPGRADE"; - ERROR2[ERROR2["PAUSED_H2_UPGRADE"] = 23] = "PAUSED_H2_UPGRADE"; - ERROR2[ERROR2["USER"] = 24] = "USER"; - })(ERROR = exports.ERROR || (exports.ERROR = {})); - var TYPE; - (function(TYPE2) { - TYPE2[TYPE2["BOTH"] = 0] = "BOTH"; - TYPE2[TYPE2["REQUEST"] = 1] = "REQUEST"; - TYPE2[TYPE2["RESPONSE"] = 2] = "RESPONSE"; - })(TYPE = exports.TYPE || (exports.TYPE = {})); - var FLAGS; - (function(FLAGS2) { - FLAGS2[FLAGS2["CONNECTION_KEEP_ALIVE"] = 1] = "CONNECTION_KEEP_ALIVE"; - FLAGS2[FLAGS2["CONNECTION_CLOSE"] = 2] = "CONNECTION_CLOSE"; - FLAGS2[FLAGS2["CONNECTION_UPGRADE"] = 4] = "CONNECTION_UPGRADE"; - FLAGS2[FLAGS2["CHUNKED"] = 8] = "CHUNKED"; - FLAGS2[FLAGS2["UPGRADE"] = 16] = "UPGRADE"; - FLAGS2[FLAGS2["CONTENT_LENGTH"] = 32] = "CONTENT_LENGTH"; - FLAGS2[FLAGS2["SKIPBODY"] = 64] = "SKIPBODY"; - FLAGS2[FLAGS2["TRAILING"] = 128] = "TRAILING"; - FLAGS2[FLAGS2["TRANSFER_ENCODING"] = 512] = "TRANSFER_ENCODING"; - })(FLAGS = exports.FLAGS || (exports.FLAGS = {})); - var LENIENT_FLAGS; - (function(LENIENT_FLAGS2) { - LENIENT_FLAGS2[LENIENT_FLAGS2["HEADERS"] = 1] = "HEADERS"; - LENIENT_FLAGS2[LENIENT_FLAGS2["CHUNKED_LENGTH"] = 2] = "CHUNKED_LENGTH"; - LENIENT_FLAGS2[LENIENT_FLAGS2["KEEP_ALIVE"] = 4] = "KEEP_ALIVE"; - })(LENIENT_FLAGS = exports.LENIENT_FLAGS || (exports.LENIENT_FLAGS = {})); - var METHODS; - (function(METHODS2) { - METHODS2[METHODS2["DELETE"] = 0] = "DELETE"; - METHODS2[METHODS2["GET"] = 1] = "GET"; - METHODS2[METHODS2["HEAD"] = 2] = "HEAD"; - METHODS2[METHODS2["POST"] = 3] = "POST"; - METHODS2[METHODS2["PUT"] = 4] = "PUT"; - METHODS2[METHODS2["CONNECT"] = 5] = "CONNECT"; - METHODS2[METHODS2["OPTIONS"] = 6] = "OPTIONS"; - METHODS2[METHODS2["TRACE"] = 7] = "TRACE"; - METHODS2[METHODS2["COPY"] = 8] = "COPY"; - METHODS2[METHODS2["LOCK"] = 9] = "LOCK"; - METHODS2[METHODS2["MKCOL"] = 10] = "MKCOL"; - METHODS2[METHODS2["MOVE"] = 11] = "MOVE"; - METHODS2[METHODS2["PROPFIND"] = 12] = "PROPFIND"; - METHODS2[METHODS2["PROPPATCH"] = 13] = "PROPPATCH"; - METHODS2[METHODS2["SEARCH"] = 14] = "SEARCH"; - METHODS2[METHODS2["UNLOCK"] = 15] = "UNLOCK"; - METHODS2[METHODS2["BIND"] = 16] = "BIND"; - METHODS2[METHODS2["REBIND"] = 17] = "REBIND"; - METHODS2[METHODS2["UNBIND"] = 18] = "UNBIND"; - METHODS2[METHODS2["ACL"] = 19] = "ACL"; - METHODS2[METHODS2["REPORT"] = 20] = "REPORT"; - METHODS2[METHODS2["MKACTIVITY"] = 21] = "MKACTIVITY"; - METHODS2[METHODS2["CHECKOUT"] = 22] = "CHECKOUT"; - METHODS2[METHODS2["MERGE"] = 23] = "MERGE"; - METHODS2[METHODS2["M-SEARCH"] = 24] = "M-SEARCH"; - METHODS2[METHODS2["NOTIFY"] = 25] = "NOTIFY"; - METHODS2[METHODS2["SUBSCRIBE"] = 26] = "SUBSCRIBE"; - METHODS2[METHODS2["UNSUBSCRIBE"] = 27] = "UNSUBSCRIBE"; - METHODS2[METHODS2["PATCH"] = 28] = "PATCH"; - METHODS2[METHODS2["PURGE"] = 29] = "PURGE"; - METHODS2[METHODS2["MKCALENDAR"] = 30] = "MKCALENDAR"; - METHODS2[METHODS2["LINK"] = 31] = "LINK"; - METHODS2[METHODS2["UNLINK"] = 32] = "UNLINK"; - METHODS2[METHODS2["SOURCE"] = 33] = "SOURCE"; - METHODS2[METHODS2["PRI"] = 34] = "PRI"; - METHODS2[METHODS2["DESCRIBE"] = 35] = "DESCRIBE"; - METHODS2[METHODS2["ANNOUNCE"] = 36] = "ANNOUNCE"; - METHODS2[METHODS2["SETUP"] = 37] = "SETUP"; - METHODS2[METHODS2["PLAY"] = 38] = "PLAY"; - METHODS2[METHODS2["PAUSE"] = 39] = "PAUSE"; - METHODS2[METHODS2["TEARDOWN"] = 40] = "TEARDOWN"; - METHODS2[METHODS2["GET_PARAMETER"] = 41] = "GET_PARAMETER"; - METHODS2[METHODS2["SET_PARAMETER"] = 42] = "SET_PARAMETER"; - METHODS2[METHODS2["REDIRECT"] = 43] = "REDIRECT"; - METHODS2[METHODS2["RECORD"] = 44] = "RECORD"; - METHODS2[METHODS2["FLUSH"] = 45] = "FLUSH"; - })(METHODS = exports.METHODS || (exports.METHODS = {})); - exports.METHODS_HTTP = [ - METHODS.DELETE, - METHODS.GET, - METHODS.HEAD, - METHODS.POST, - METHODS.PUT, - METHODS.CONNECT, - METHODS.OPTIONS, - METHODS.TRACE, - METHODS.COPY, - METHODS.LOCK, - METHODS.MKCOL, - METHODS.MOVE, - METHODS.PROPFIND, - METHODS.PROPPATCH, - METHODS.SEARCH, - METHODS.UNLOCK, - METHODS.BIND, - METHODS.REBIND, - METHODS.UNBIND, - METHODS.ACL, - METHODS.REPORT, - METHODS.MKACTIVITY, - METHODS.CHECKOUT, - METHODS.MERGE, - METHODS["M-SEARCH"], - METHODS.NOTIFY, - METHODS.SUBSCRIBE, - METHODS.UNSUBSCRIBE, - METHODS.PATCH, - METHODS.PURGE, - METHODS.MKCALENDAR, - METHODS.LINK, - METHODS.UNLINK, - METHODS.PRI, - // TODO(indutny): should we allow it with HTTP? - METHODS.SOURCE - ]; - exports.METHODS_ICE = [ - METHODS.SOURCE - ]; - exports.METHODS_RTSP = [ - METHODS.OPTIONS, - METHODS.DESCRIBE, - METHODS.ANNOUNCE, - METHODS.SETUP, - METHODS.PLAY, - METHODS.PAUSE, - METHODS.TEARDOWN, - METHODS.GET_PARAMETER, - METHODS.SET_PARAMETER, - METHODS.REDIRECT, - METHODS.RECORD, - METHODS.FLUSH, - // For AirPlay - METHODS.GET, - METHODS.POST - ]; - exports.METHOD_MAP = utils_1.enumToMap(METHODS); - exports.H_METHOD_MAP = {}; - Object.keys(exports.METHOD_MAP).forEach((key) => { - if (/^H/.test(key)) { - exports.H_METHOD_MAP[key] = exports.METHOD_MAP[key]; + }, + { + key: "type", + converter: webidl.converters.DOMString, + defaultValue: "" + }, + { + key: "endings", + converter: (value) => { + value = webidl.converters.DOMString(value); + value = value.toLowerCase(); + if (value !== "native") { + value = "transparent"; + } + return value; + }, + defaultValue: "transparent" } - }); - var FINISH; - (function(FINISH2) { - FINISH2[FINISH2["SAFE"] = 0] = "SAFE"; - FINISH2[FINISH2["SAFE_WITH_CB"] = 1] = "SAFE_WITH_CB"; - FINISH2[FINISH2["UNSAFE"] = 2] = "UNSAFE"; - })(FINISH = exports.FINISH || (exports.FINISH = {})); - exports.ALPHA = []; - for (let i = "A".charCodeAt(0); i <= "Z".charCodeAt(0); i++) { - exports.ALPHA.push(String.fromCharCode(i)); - exports.ALPHA.push(String.fromCharCode(i + 32)); + ]); + function processBlobParts(parts, options) { + const bytes = []; + for (const element of parts) { + if (typeof element === "string") { + let s = element; + if (options.endings === "native") { + s = convertLineEndingsNative(s); + } + bytes.push(encoder.encode(s)); + } else if (ArrayBuffer.isView(element) || types.isArrayBuffer(element)) { + if (element.buffer) { + bytes.push( + new Uint8Array(element.buffer, element.byteOffset, element.byteLength) + ); + } else { + bytes.push(new Uint8Array(element)); + } + } else if (isBlobLike(element)) { + bytes.push(element); + } + } + return bytes; } - exports.NUM_MAP = { - 0: 0, - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9 - }; - exports.HEX_MAP = { - 0: 0, - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - A: 10, - B: 11, - C: 12, - D: 13, - E: 14, - F: 15, - a: 10, - b: 11, - c: 12, - d: 13, - e: 14, - f: 15 - }; - exports.NUM = [ - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9" - ]; - exports.ALPHANUM = exports.ALPHA.concat(exports.NUM); - exports.MARK = ["-", "_", ".", "!", "~", "*", "'", "(", ")"]; - exports.USERINFO_CHARS = exports.ALPHANUM.concat(exports.MARK).concat(["%", ";", ":", "&", "=", "+", "$", ","]); - exports.STRICT_URL_CHAR = [ - "!", - '"', - "$", - "%", - "&", - "'", - "(", - ")", - "*", - "+", - ",", - "-", - ".", - "/", - ":", - ";", - "<", - "=", - ">", - "@", - "[", - "\\", - "]", - "^", - "_", - "`", - "{", - "|", - "}", - "~" - ].concat(exports.ALPHANUM); - exports.URL_CHAR = exports.STRICT_URL_CHAR.concat([" ", "\f"]); - for (let i = 128; i <= 255; i++) { - exports.URL_CHAR.push(i); + function convertLineEndingsNative(s) { + return s.replace(/\r?\n/g, EOL); } - exports.HEX = exports.NUM.concat(["a", "b", "c", "d", "e", "f", "A", "B", "C", "D", "E", "F"]); - exports.STRICT_TOKEN = [ - "!", - "#", - "$", - "%", - "&", - "'", - "*", - "+", - "-", - ".", - "^", - "_", - "`", - "|", - "~" - ].concat(exports.ALPHANUM); - exports.TOKEN = exports.STRICT_TOKEN.concat([" "]); - exports.HEADER_CHARS = [" "]; - for (let i = 32; i <= 255; i++) { - if (i !== 127) { - exports.HEADER_CHARS.push(i); + function isFileLike(object) { + return NativeFile && object instanceof NativeFile || object instanceof File || object && (typeof object.stream === "function" || typeof object.arrayBuffer === "function") && object[Symbol.toStringTag] === "File"; + } + module2.exports = { File, FileLike, isFileLike }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/formdata.js +var require_formdata = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/formdata.js"(exports, module2) { + "use strict"; + var { isBlobLike, iteratorMixin } = require_util3(); + var { kState } = require_symbols2(); + var { kEnumerableProperty } = require_util(); + var { File: UndiciFile, FileLike, isFileLike } = require_file(); + var { webidl } = require_webidl(); + var { File: NativeFile } = require("node:buffer"); + var nodeUtil = require("node:util"); + var File = NativeFile ?? UndiciFile; + var FormData = class _FormData { + constructor(form) { + if (form !== void 0) { + throw webidl.errors.conversionFailed({ + prefix: "FormData constructor", + argument: "Argument 1", + types: ["undefined"] + }); + } + this[kState] = []; + } + append(name, value, filename = void 0) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 2, { header: "FormData.append" }); + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" + ); + } + name = webidl.converters.USVString(name); + value = isBlobLike(value) ? webidl.converters.Blob(value, { strict: false }) : webidl.converters.USVString(value); + filename = arguments.length === 3 ? webidl.converters.USVString(filename) : void 0; + const entry = makeEntry(name, value, filename); + this[kState].push(entry); + } + delete(name) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 1, { header: "FormData.delete" }); + name = webidl.converters.USVString(name); + this[kState] = this[kState].filter((entry) => entry.name !== name); + } + get(name) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 1, { header: "FormData.get" }); + name = webidl.converters.USVString(name); + const idx = this[kState].findIndex((entry) => entry.name === name); + if (idx === -1) { + return null; + } + return this[kState][idx].value; + } + getAll(name) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 1, { header: "FormData.getAll" }); + name = webidl.converters.USVString(name); + return this[kState].filter((entry) => entry.name === name).map((entry) => entry.value); + } + has(name) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 1, { header: "FormData.has" }); + name = webidl.converters.USVString(name); + return this[kState].findIndex((entry) => entry.name === name) !== -1; + } + set(name, value, filename = void 0) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 2, { header: "FormData.set" }); + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" + ); + } + name = webidl.converters.USVString(name); + value = isBlobLike(value) ? webidl.converters.Blob(value, { strict: false }) : webidl.converters.USVString(value); + filename = arguments.length === 3 ? webidl.converters.USVString(filename) : void 0; + const entry = makeEntry(name, value, filename); + const idx = this[kState].findIndex((entry2) => entry2.name === name); + if (idx !== -1) { + this[kState] = [ + ...this[kState].slice(0, idx), + entry, + ...this[kState].slice(idx + 1).filter((entry2) => entry2.name !== name) + ]; + } else { + this[kState].push(entry); + } + } + [nodeUtil.inspect.custom](depth, options) { + const state = this[kState].reduce((a, b) => { + if (a[b.name]) { + if (Array.isArray(a[b.name])) { + a[b.name].push(b.value); + } else { + a[b.name] = [a[b.name], b.value]; + } + } else { + a[b.name] = b.value; + } + return a; + }, { __proto__: null }); + options.depth ??= depth; + options.colors ??= true; + const output = nodeUtil.formatWithOptions(options, state); + return `FormData ${output.slice(output.indexOf("]") + 2)}`; + } + }; + iteratorMixin("FormData", FormData, kState, "name", "value"); + Object.defineProperties(FormData.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + getAll: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "FormData", + configurable: true + } + }); + function makeEntry(name, value, filename) { + if (typeof value === "string") { + } else { + if (!isFileLike(value)) { + value = value instanceof Blob ? new File([value], "blob", { type: value.type }) : new FileLike(value, "blob", { type: value.type }); + } + if (filename !== void 0) { + const options = { + type: value.type, + lastModified: value.lastModified + }; + value = NativeFile && value instanceof NativeFile || value instanceof UndiciFile ? new File([value], filename, options) : new FileLike(value, filename, options); + } } + return { name, value }; } - exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS.filter((c) => c !== 44); - exports.MAJOR = exports.NUM_MAP; - exports.MINOR = exports.MAJOR; - var HEADER_STATE; - (function(HEADER_STATE2) { - HEADER_STATE2[HEADER_STATE2["GENERAL"] = 0] = "GENERAL"; - HEADER_STATE2[HEADER_STATE2["CONNECTION"] = 1] = "CONNECTION"; - HEADER_STATE2[HEADER_STATE2["CONTENT_LENGTH"] = 2] = "CONTENT_LENGTH"; - HEADER_STATE2[HEADER_STATE2["TRANSFER_ENCODING"] = 3] = "TRANSFER_ENCODING"; - HEADER_STATE2[HEADER_STATE2["UPGRADE"] = 4] = "UPGRADE"; - HEADER_STATE2[HEADER_STATE2["CONNECTION_KEEP_ALIVE"] = 5] = "CONNECTION_KEEP_ALIVE"; - HEADER_STATE2[HEADER_STATE2["CONNECTION_CLOSE"] = 6] = "CONNECTION_CLOSE"; - HEADER_STATE2[HEADER_STATE2["CONNECTION_UPGRADE"] = 7] = "CONNECTION_UPGRADE"; - HEADER_STATE2[HEADER_STATE2["TRANSFER_ENCODING_CHUNKED"] = 8] = "TRANSFER_ENCODING_CHUNKED"; - })(HEADER_STATE = exports.HEADER_STATE || (exports.HEADER_STATE = {})); - exports.SPECIAL_HEADERS = { - "connection": HEADER_STATE.CONNECTION, - "content-length": HEADER_STATE.CONTENT_LENGTH, - "proxy-connection": HEADER_STATE.CONNECTION, - "transfer-encoding": HEADER_STATE.TRANSFER_ENCODING, - "upgrade": HEADER_STATE.UPGRADE - }; + module2.exports = { FormData, makeEntry }; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/handler/RedirectHandler.js -var require_RedirectHandler = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/handler/RedirectHandler.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/formdata-parser.js +var require_formdata_parser = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/formdata-parser.js"(exports, module2) { "use strict"; - var util = require_util(); - var { kBodyUsed } = require_symbols(); + var { isUSVString, bufferToLowerCasedHeaderName } = require_util(); + var { utf8DecodeBytes } = require_util3(); + var { HTTP_TOKEN_CODEPOINTS, isomorphicDecode } = require_data_url(); + var { isFileLike, File: UndiciFile } = require_file(); + var { makeEntry } = require_formdata(); var assert3 = require("node:assert"); - var { InvalidArgumentError } = require_errors(); - var EE = require("node:events"); - var redirectableStatusCodes = [300, 301, 302, 303, 307, 308]; - var kBody = Symbol("body"); - var BodyAsyncIterable = class { - constructor(body) { - this[kBody] = body; - this[kBodyUsed] = false; + var { File: NodeFile } = require("node:buffer"); + var File = globalThis.File ?? NodeFile ?? UndiciFile; + var formDataNameBuffer = Buffer.from('form-data; name="'); + var filenameBuffer = Buffer.from("; filename"); + var dd = Buffer.from("--"); + var ddcrlf = Buffer.from("--\r\n"); + function isAsciiString(chars) { + for (let i = 0; i < chars.length; ++i) { + if ((chars.charCodeAt(i) & ~127) !== 0) { + return false; + } } - async *[Symbol.asyncIterator]() { - assert3(!this[kBodyUsed], "disturbed"); - this[kBodyUsed] = true; - yield* this[kBody]; + return true; + } + function validateBoundary(boundary) { + const length = boundary.length; + if (length < 27 || length > 70) { + return false; } - }; - var RedirectHandler = class { - constructor(dispatch, maxRedirections, opts, handler) { - if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { - throw new InvalidArgumentError("maxRedirections must be a positive number"); + for (let i = 0; i < length; ++i) { + const cp = boundary.charCodeAt(i); + if (!(cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 39 || cp === 45 || cp === 95)) { + return false; } - util.validateHandler(handler, opts.method, opts.upgrade); - this.dispatch = dispatch; - this.location = null; - this.abort = null; - this.opts = { ...opts, maxRedirections: 0 }; - this.maxRedirections = maxRedirections; - this.handler = handler; - this.history = []; - this.redirectionLimitReached = false; - if (util.isStream(this.opts.body)) { - if (util.bodyLength(this.opts.body) === 0) { - this.opts.body.on("data", function() { - assert3(false); - }); + } + return true; + } + function multipartFormDataParser(input, mimeType) { + assert3(mimeType !== "failure" && mimeType.essence === "multipart/form-data"); + const boundaryString = mimeType.parameters.get("boundary"); + if (boundaryString === void 0) { + return "failure"; + } + const boundary = Buffer.from(`--${boundaryString}`, "utf8"); + const entryList = []; + const position = { position: 0 }; + if (input[0] === 13 && input[1] === 10) { + position.position += 2; + } + while (true) { + if (input.subarray(position.position, position.position + boundary.length).equals(boundary)) { + position.position += boundary.length; + } else { + return "failure"; + } + if (position.position === input.length - 2 && bufferStartsWith(input, dd, position) || position.position === input.length - 4 && bufferStartsWith(input, ddcrlf, position)) { + return entryList; + } + if (input[position.position] !== 13 || input[position.position + 1] !== 10) { + return "failure"; + } + position.position += 2; + const result = parseMultipartFormDataHeaders(input, position); + if (result === "failure") { + return "failure"; + } + let { name, filename, contentType, encoding } = result; + position.position += 2; + let body; + { + const boundaryIndex = input.indexOf(boundary.subarray(2), position.position); + if (boundaryIndex === -1) { + return "failure"; } - if (typeof this.opts.body.readableDidRead !== "boolean") { - this.opts.body[kBodyUsed] = false; - EE.prototype.on.call(this.opts.body, "data", function() { - this[kBodyUsed] = true; - }); + body = input.subarray(position.position, boundaryIndex - 4); + position.position += body.length; + if (encoding === "base64") { + body = Buffer.from(body.toString(), "base64"); } - } else if (this.opts.body && typeof this.opts.body.pipeTo === "function") { - this.opts.body = new BodyAsyncIterable(this.opts.body); - } else if (this.opts.body && typeof this.opts.body !== "string" && !ArrayBuffer.isView(this.opts.body) && util.isIterable(this.opts.body)) { - this.opts.body = new BodyAsyncIterable(this.opts.body); } + if (input[position.position] !== 13 || input[position.position + 1] !== 10) { + return "failure"; + } else { + position.position += 2; + } + let value; + if (filename !== null) { + contentType ??= "text/plain"; + if (!isAsciiString(contentType)) { + contentType = ""; + } + value = new File([body], filename, { type: contentType }); + } else { + value = utf8DecodeBytes(Buffer.from(body)); + } + assert3(isUSVString(name)); + assert3(typeof value === "string" && isUSVString(value) || isFileLike(value)); + entryList.push(makeEntry(name, value, filename)); } - onConnect(abort) { - this.abort = abort; - this.handler.onConnect(abort, { history: this.history }); + } + function parseMultipartFormDataHeaders(input, position) { + let name = null; + let filename = null; + let contentType = null; + let encoding = null; + while (true) { + if (input[position.position] === 13 && input[position.position + 1] === 10) { + if (name === null) { + return "failure"; + } + return { name, filename, contentType, encoding }; + } + let headerName = collectASequenceOfBytes( + (char) => char !== 10 && char !== 13 && char !== 58, + input, + position + ); + headerName = removeChars(headerName, true, true, (char) => char === 9 || char === 32); + if (!HTTP_TOKEN_CODEPOINTS.test(headerName.toString())) { + return "failure"; + } + if (input[position.position] !== 58) { + return "failure"; + } + position.position++; + collectASequenceOfBytes( + (char) => char === 32 || char === 9, + input, + position + ); + switch (bufferToLowerCasedHeaderName(headerName)) { + case "content-disposition": { + name = filename = null; + if (!bufferStartsWith(input, formDataNameBuffer, position)) { + return "failure"; + } + position.position += 17; + name = parseMultipartFormDataName(input, position); + if (name === null) { + return "failure"; + } + if (bufferStartsWith(input, filenameBuffer, position)) { + let check = position.position + filenameBuffer.length; + if (input[check] === 42) { + position.position += 1; + check += 1; + } + if (input[check] !== 61 || input[check + 1] !== 34) { + return "failure"; + } + position.position += 12; + filename = parseMultipartFormDataName(input, position); + if (filename === null) { + return "failure"; + } + } + break; + } + case "content-type": { + let headerValue = collectASequenceOfBytes( + (char) => char !== 10 && char !== 13, + input, + position + ); + headerValue = removeChars(headerValue, false, true, (char) => char === 9 || char === 32); + contentType = isomorphicDecode(headerValue); + break; + } + case "content-transfer-encoding": { + let headerValue = collectASequenceOfBytes( + (char) => char !== 10 && char !== 13, + input, + position + ); + headerValue = removeChars(headerValue, false, true, (char) => char === 9 || char === 32); + encoding = isomorphicDecode(headerValue); + break; + } + default: { + collectASequenceOfBytes( + (char) => char !== 10 && char !== 13, + input, + position + ); + } + } + if (input[position.position] !== 13 && input[position.position + 1] !== 10) { + return "failure"; + } else { + position.position += 2; + } } - onUpgrade(statusCode, headers, socket) { - this.handler.onUpgrade(statusCode, headers, socket); + } + function parseMultipartFormDataName(input, position) { + assert3(input[position.position - 1] === 34); + let name = collectASequenceOfBytes( + (char) => char !== 10 && char !== 13 && char !== 34, + input, + position + ); + if (input[position.position] !== 34) { + return null; + } else { + position.position++; } - onError(error) { - this.handler.onError(error); + name = new TextDecoder().decode(name).replace(/%0A/ig, "\n").replace(/%0D/ig, "\r").replace(/%22/g, '"'); + return name; + } + function collectASequenceOfBytes(condition, input, position) { + let start = position.position; + while (start < input.length && condition(input[start])) { + ++start; } - onHeaders(statusCode, headers, resume, statusText) { - this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) ? null : parseLocation(statusCode, headers); - if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) { - if (this.request) { - this.request.abort(new Error("max redirects")); + return input.subarray(position.position, position.position = start); + } + function removeChars(buf, leading, trailing, predicate) { + let lead = 0; + let trail = buf.length - 1; + if (leading) { + while (lead < buf.length && predicate(buf[lead])) + lead++; + } + if (trailing) { + while (trail > 0 && predicate(buf[trail])) + trail--; + } + return lead === 0 && trail === buf.length - 1 ? buf : buf.subarray(lead, trail + 1); + } + function bufferStartsWith(buffer, start, position) { + if (buffer.length < start.length) { + return false; + } + for (let i = 0; i < start.length; i++) { + if (start[i] !== buffer[position.position + i]) { + return false; + } + } + return true; + } + module2.exports = { + multipartFormDataParser, + validateBoundary + }; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/body.js +var require_body = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/web/fetch/body.js"(exports, module2) { + "use strict"; + var util = require_util(); + var { + ReadableStreamFrom, + isBlobLike, + isReadableStreamLike, + readableStreamClose, + createDeferredPromise, + fullyReadBody, + extractMimeType, + utf8DecodeBytes + } = require_util3(); + var { FormData } = require_formdata(); + var { kState } = require_symbols2(); + var { webidl } = require_webidl(); + var { Blob: Blob2 } = require("node:buffer"); + var assert3 = require("node:assert"); + var { isErrored } = require_util(); + var { isArrayBuffer } = require("node:util/types"); + var { serializeAMimeType } = require_data_url(); + var { multipartFormDataParser } = require_formdata_parser(); + var textEncoder = new TextEncoder(); + function extractBody(object, keepalive = false) { + let stream = null; + if (object instanceof ReadableStream) { + stream = object; + } else if (isBlobLike(object)) { + stream = object.stream(); + } else { + stream = new ReadableStream({ + async pull(controller) { + const buffer = typeof source === "string" ? textEncoder.encode(source) : source; + if (buffer.byteLength) { + controller.enqueue(buffer); + } + queueMicrotask(() => readableStreamClose(controller)); + }, + start() { + }, + type: "bytes" + }); + } + assert3(isReadableStreamLike(stream)); + let action = null; + let source = null; + let length = null; + let type = null; + if (typeof object === "string") { + source = object; + type = "text/plain;charset=UTF-8"; + } else if (object instanceof URLSearchParams) { + source = object.toString(); + type = "application/x-www-form-urlencoded;charset=UTF-8"; + } else if (isArrayBuffer(object)) { + source = new Uint8Array(object.slice()); + } else if (ArrayBuffer.isView(object)) { + source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)); + } else if (util.isFormDataLike(object)) { + const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, "0")}`; + const prefix = `--${boundary}\r +Content-Disposition: form-data`; + const escape = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22"); + const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, "\r\n"); + const blobParts = []; + const rn = new Uint8Array([13, 10]); + length = 0; + let hasUnknownSizeValue = false; + for (const [name, value] of object) { + if (typeof value === "string") { + const chunk2 = textEncoder.encode(prefix + `; name="${escape(normalizeLinefeeds(name))}"\r +\r +${normalizeLinefeeds(value)}\r +`); + blobParts.push(chunk2); + length += chunk2.byteLength; + } else { + const chunk2 = textEncoder.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` + (value.name ? `; filename="${escape(value.name)}"` : "") + `\r +Content-Type: ${value.type || "application/octet-stream"}\r +\r +`); + blobParts.push(chunk2, value, rn); + if (typeof value.size === "number") { + length += chunk2.byteLength + value.size + rn.byteLength; + } else { + hasUnknownSizeValue = true; + } } - this.redirectionLimitReached = true; - this.abort(new Error("max redirects")); - return; - } - if (this.opts.origin) { - this.history.push(new URL(this.opts.path, this.opts.origin)); - } - if (!this.location) { - return this.handler.onHeaders(statusCode, headers, resume, statusText); } - const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); - const path10 = search ? `${pathname}${search}` : pathname; - this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); - this.opts.path = path10; - this.opts.origin = origin; - this.opts.maxRedirections = 0; - this.opts.query = null; - if (statusCode === 303 && this.opts.method !== "HEAD") { - this.opts.method = "GET"; - this.opts.body = null; + const chunk = textEncoder.encode(`--${boundary}--`); + blobParts.push(chunk); + length += chunk.byteLength; + if (hasUnknownSizeValue) { + length = null; } - } - onData(chunk) { - if (this.location) { - } else { - return this.handler.onData(chunk); + source = object; + action = async function* () { + for (const part of blobParts) { + if (part.stream) { + yield* part.stream(); + } else { + yield part; + } + } + }; + type = `multipart/form-data; boundary=${boundary}`; + } else if (isBlobLike(object)) { + source = object; + length = object.size; + if (object.type) { + type = object.type; } - } - onComplete(trailers) { - if (this.location) { - this.location = null; - this.abort = null; - this.dispatch(this.opts, this); - } else { - this.handler.onComplete(trailers); + } else if (typeof object[Symbol.asyncIterator] === "function") { + if (keepalive) { + throw new TypeError("keepalive"); } - } - onBodySent(chunk) { - if (this.handler.onBodySent) { - this.handler.onBodySent(chunk); + if (util.isDisturbed(object) || object.locked) { + throw new TypeError( + "Response body object should not be disturbed or locked" + ); } + stream = object instanceof ReadableStream ? object : ReadableStreamFrom(object); } - }; - function parseLocation(statusCode, headers) { - if (redirectableStatusCodes.indexOf(statusCode) === -1) { - return null; + if (typeof source === "string" || util.isBuffer(source)) { + length = Buffer.byteLength(source); } - for (let i = 0; i < headers.length; i += 2) { - if (headers[i].length === 8 && util.headerNameToString(headers[i]) === "location") { - return headers[i + 1]; - } + if (action != null) { + let iterator; + stream = new ReadableStream({ + async start() { + iterator = action(object)[Symbol.asyncIterator](); + }, + async pull(controller) { + const { value, done } = await iterator.next(); + if (done) { + queueMicrotask(() => { + controller.close(); + controller.byobRequest?.respond(0); + }); + } else { + if (!isErrored(stream)) { + const buffer = new Uint8Array(value); + if (buffer.byteLength) { + controller.enqueue(buffer); + } + } + } + return controller.desiredSize > 0; + }, + async cancel(reason) { + await iterator.return(); + }, + type: "bytes" + }); } + const body = { stream, source, length }; + return [body, type]; } - function shouldRemoveHeader(header, removeContent, unknownOrigin) { - if (header.length === 4) { - return util.headerNameToString(header) === "host"; - } - if (removeContent && util.headerNameToString(header).startsWith("content-")) { - return true; + function safelyExtractBody(object, keepalive = false) { + if (object instanceof ReadableStream) { + assert3(!util.isDisturbed(object), "The body has already been consumed."); + assert3(!object.locked, "The stream is locked."); } - if (unknownOrigin && (header.length === 13 || header.length === 6)) { - const name = util.headerNameToString(header); - return name === "authorization" || name === "cookie"; + return extractBody(object, keepalive); + } + function cloneBody(body) { + const [out1, out2] = body.stream.tee(); + body.stream = out1; + return { + stream: out2, + length: body.length, + source: body.source + }; + } + function throwIfAborted(state) { + if (state.aborted) { + throw new DOMException("The operation was aborted.", "AbortError"); } - return false; } - function cleanRequestHeaders(headers, removeContent, unknownOrigin) { - const ret = []; - if (Array.isArray(headers)) { - for (let i = 0; i < headers.length; i += 2) { - if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { - ret.push(headers[i], headers[i + 1]); - } + function bodyMixinMethods(instance) { + const methods = { + blob() { + return consumeBody(this, (bytes) => { + let mimeType = bodyMimeType(this); + if (mimeType === null) { + mimeType = ""; + } else if (mimeType) { + mimeType = serializeAMimeType(mimeType); + } + return new Blob2([bytes], { type: mimeType }); + }, instance); + }, + arrayBuffer() { + return consumeBody(this, (bytes) => { + return new Uint8Array(bytes).buffer; + }, instance); + }, + text() { + return consumeBody(this, utf8DecodeBytes, instance); + }, + json() { + return consumeBody(this, parseJSONFromBytes, instance); + }, + formData() { + return consumeBody(this, (value) => { + const mimeType = bodyMimeType(this); + if (mimeType !== null) { + switch (mimeType.essence) { + case "multipart/form-data": { + const parsed = multipartFormDataParser(value, mimeType); + if (parsed === "failure") { + throw new TypeError("Failed to parse body as FormData."); + } + const fd = new FormData(); + fd[kState] = parsed; + return fd; + } + case "application/x-www-form-urlencoded": { + const entries = new URLSearchParams(value.toString()); + const fd = new FormData(); + for (const [name, value2] of entries) { + fd.append(name, value2); + } + return fd; + } + } + } + throw new TypeError( + 'Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".' + ); + }, instance); } - } else if (headers && typeof headers === "object") { - for (const key of Object.keys(headers)) { - if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { - ret.push(key, headers[key]); - } + }; + return methods; + } + function mixinBody(prototype) { + Object.assign(prototype.prototype, bodyMixinMethods(prototype)); + } + async function consumeBody(object, convertBytesToJSValue, instance) { + webidl.brandCheck(object, instance); + if (bodyUnusable(object[kState].body)) { + throw new TypeError("Body is unusable"); + } + throwIfAborted(object[kState]); + const promise = createDeferredPromise(); + const errorSteps = (error) => promise.reject(error); + const successSteps = (data) => { + try { + promise.resolve(convertBytesToJSValue(data)); + } catch (e) { + errorSteps(e); } - } else { - assert3(headers == null, "headers must be an object or an array"); + }; + if (object[kState].body == null) { + successSteps(new Uint8Array()); + return promise.promise; } - return ret; + await fullyReadBody(object[kState].body, successSteps, errorSteps); + return promise.promise; } - module2.exports = RedirectHandler; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/interceptor/redirectInterceptor.js -var require_redirectInterceptor = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/interceptor/redirectInterceptor.js"(exports, module2) { - "use strict"; - var RedirectHandler = require_RedirectHandler(); - function createRedirectInterceptor({ maxRedirections: defaultMaxRedirections }) { - return (dispatch) => { - return function Intercept(opts, handler) { - const { maxRedirections = defaultMaxRedirections } = opts; - if (!maxRedirections) { - return dispatch(opts, handler); - } - const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler); - opts = { ...opts, maxRedirections: 0 }; - return dispatch(opts, redirectHandler); - }; - }; + function bodyUnusable(body) { + return body != null && (body.stream.locked || util.isDisturbed(body.stream)); } - module2.exports = createRedirectInterceptor; - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/llhttp/llhttp-wasm.js -var require_llhttp_wasm = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/llhttp/llhttp-wasm.js"(exports, module2) { - var { Buffer: Buffer2 } = require("node:buffer"); - module2.exports = Buffer2.from("AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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ADcDACAAQShqQgA3AwAgAEEgakIANwMAIABBEGpCADcDACAAQQhqQgA3AwAgAEHdATYCHEEAC3sBAX8CQCAAKAIMIgMNAAJAIAAoAgRFDQAgACABNgIECwJAIAAgASACEMSAgIAAIgMNACAAKAIMDwsgACADNgIcQQAhAyAAKAIEIgFFDQAgACABIAIgACgCCBGBgICAAAAiAUUNACAAIAI2AhQgACABNgIMIAEhAwsgAwvk8wEDDn8DfgR/I4CAgIAAQRBrIgMkgICAgAAgASEEIAEhBSABIQYgASEHIAEhCCABIQkgASEKIAEhCyABIQwgASENIAEhDiABIQ8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCHCIQQX9qDt0B2gEB2QECAwQFBgcICQoLDA0O2AEPENcBERLWARMUFRYXGBkaG+AB3wEcHR7VAR8gISIjJCXUASYnKCkqKyzTAdIBLS7RAdABLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVG2wFHSElKzwHOAUvNAUzMAU1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4ABgQGCAYMBhAGFAYYBhwGIAYkBigGLAYwBjQGOAY8BkAGRAZIBkwGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwHLAcoBuAHJAbkByAG6AbsBvAG9Ab4BvwHAAcEBwgHDAcQBxQHGAQDcAQtBACEQDMYBC0EOIRAMxQELQQ0hEAzEAQtBDyEQDMMBC0EQIRAMwgELQRMhEAzBAQtBFCEQDMABC0EVIRAMvwELQRYhEAy+AQtBFyEQDL0BC0EYIRAMvAELQRkhEAy7AQtBGiEQDLoBC0EbIRAMuQELQRwhEAy4AQtBCCEQDLcBC0EdIRAMtgELQSAhEAy1AQtBHyEQDLQBC0EHIRAMswELQSEhEAyyAQtBIiEQDLEBC0EeIRAMsAELQSMhEAyvAQtBEiEQDK4BC0ERIRAMrQELQSQhEAysAQtBJSEQDKsBC0EmIRAMqgELQSchEAypAQtBwwEhEAyoAQtBKSEQDKcBC0ErIRAMpgELQSwhEAylAQtBLSEQDKQBC0EuIRAMowELQS8hEAyiAQtBxAEhEAyhAQtBMCEQDKABC0E0IRAMnwELQQwhEAyeAQtBMSEQDJ0BC0EyIRAMnAELQTMhEAybAQtBOSEQDJoBC0E1IRAMmQELQcUBIRAMmAELQQshEAyXAQtBOiEQDJYBC0E2IRAMlQELQQohEAyUAQtBNyEQDJMBC0E4IRAMkgELQTwhEAyRAQtBOyEQDJABC0E9IRAMjwELQQkhEAyOAQtBKCEQDI0BC0E+IRAMjAELQT8hEAyLAQtBwAAhEAyKAQtBwQAhEAyJAQtBwgAhEAyIAQtBwwAhEAyHAQtBxAAhEAyGAQtBxQAhEAyFAQtBxgAhEAyEAQtBKiEQDIMBC0HHACEQDIIBC0HIACEQDIEBC0HJACEQDIABC0HKACEQDH8LQcsAIRAMfgtBzQAhEAx9C0HMACEQDHwLQc4AIRAMewtBzwAhEAx6C0HQACEQDHkLQdEAIRAMeAtB0gAhEAx3C0HTACEQDHYLQdQAIRAMdQtB1gAhEAx0C0HVACEQDHMLQQYhEAxyC0HXACEQDHELQQUhEAxwC0HYACEQDG8LQQQhEAxuC0HZACEQDG0LQdoAIRAMbAtB2wAhEAxrC0HcACEQDGoLQQMhEAxpC0HdACEQDGgLQd4AIRAMZwtB3wAhEAxmC0HhACEQDGULQeAAIRAMZAtB4gAhEAxjC0HjACEQDGILQQIhEAxhC0HkACEQDGALQeUAIRAMXwtB5gAhEAxeC0HnACEQDF0LQegAIRAMXAtB6QAhEAxbC0HqACEQDFoLQesAIRAMWQtB7AAhEAxYC0HtACEQDFcLQe4AIRAMVgtB7wAhEAxVC0HwACEQDFQLQfEAIRAMUwtB8gAhEAxSC0HzACEQDFELQfQAIRAMUAtB9QAhEAxPC0H2ACEQDE4LQfcAIRAMTQtB+AAhEAxMC0H5ACEQDEsLQfoAIRAMSgtB+wAhEAxJC0H8ACEQDEgLQf0AIRAMRwtB/gAhEAxGC0H/ACEQDEULQYABIRAMRAtBgQEhEAxDC0GCASEQDEILQYMBIRAMQQtBhAEhEAxAC0GFASEQDD8LQYYBIRAMPgtBhwEhEAw9C0GIASEQDDwLQYkBIRAMOwtBigEhEAw6C0GLASEQDDkLQYwBIRAMOAtBjQEhEAw3C0GOASEQDDYLQY8BIRAMNQtBkAEhEAw0C0GRASEQDDMLQZIBIRAMMgtBkwEhEAwxC0GUASEQDDALQZUBIRAMLwtBlgEhEAwuC0GXASEQDC0LQZgBIRAMLAtBmQEhEAwrC0GaASEQDCoLQZsBIRAMKQtBnAEhEAwoC0GdASEQDCcLQZ4BIRAMJgtBnwEhEAwlC0GgASEQDCQLQaEBIRAMIwtBogEhEAwiC0GjASEQDCELQaQBIRAMIAtBpQEhEAwfC0GmASEQDB4LQacBIRAMHQtBqAEhEAwcC0GpASEQDBsLQaoBIRAMGgtBqwEhEAwZC0GsASEQDBgLQa0BIRAMFwtBrgEhEAwWC0EBIRAMFQtBrwEhEAwUC0GwASEQDBMLQbEBIRAMEgtBswEhEAwRC0GyASEQDBALQbQBIRAMDwtBtQEhEAwOC0G2ASEQDA0LQbcBIRAMDAtBuAEhEAwLC0G5ASEQDAoLQboBIRAMCQtBuwEhEAwIC0HGASEQDAcLQbwBIRAMBgtBvQEhEAwFC0G+ASEQDAQLQb8BIRAMAwtBwAEhEAwCC0HCASEQDAELQcEBIRALA0ACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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FCAAIBA2AgxBACEQDLIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDLEBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxRCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLABCyAAQQA2AhwgACABNgIUIABBxoqAgAA2AhAgAEEHNgIMQQAhEAyvAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAyuAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAytAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMTQsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAysAQsgAEEANgIcIAAgATYCFCAAQdyIgIAANgIQIABBBzYCDEEAIRAMqwELIBBBP0cNASABQQFqIQELQQUhEAyQAQtBACEQIABBADYCHCAAIAE2AhQgAEH9koCAADYCECAAQQc2AgwMqAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMpwELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMpgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEYLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMpQELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0gA2AhwgACAUNgIUIAAgATYCDEEAIRAMpAELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0wA2AhwgACAUNgIUIAAgATYCDEEAIRAMowELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDEMLIABB5QA2AhwgACAU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YWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21ldGhvZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lYCBjYWxsYmFjayBlcnJvcgBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNlcnZlcgBJbnZhbGlkIGhlYWRlciB2YWx1ZSBjaGFyAEludmFsaWQgaGVhZGVyIGZpZWxkIGNoYXIAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl92ZXJzaW9uAEludmFsaWQgbWlub3IgdmVyc2lvbgBJbnZhbGlkIG1ham9yIHZlcnNpb24ARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgdmVyc2lvbgBFeHBlY3RlZCBDUkxGIGFmdGVyIHZlcnNpb24ASW52YWxpZCBIVFRQIHZlcnNpb24ASW52YWxpZCBoZWFkZXIgdG9rZW4AU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl91cmwASW52YWxpZCBjaGFyYWN0ZXJzIGluIHVybABVbmV4cGVjdGVkIHN0YXJ0IGNoYXIgaW4gdXJsAERvdWJsZSBAIGluIHVybABFbXB0eSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXJhY3RlciBpbiBDb250ZW50LUxlbmd0aABEdXBsaWNhdGUgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyIGluIHVybCBwYXRoAENvbnRlbnQtTGVuZ3RoIGNhbid0IGJlIHByZXNlbnQgd2l0aCBUcmFuc2Zlci1FbmNvZGluZwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBzaXplAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX3ZhbHVlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgdmFsdWUATWlzc2luZyBleHBlY3RlZCBMRiBhZnRlciBoZWFkZXIgdmFsdWUASW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fbmFtZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIG5hbWUAUGF1c2Ugb24gQ09OTkVDVC9VcGdyYWRlAFBhdXNlIG9uIFBSSS9VcGdyYWRlAEV4cGVjdGVkIEhUVFAvMiBDb25uZWN0aW9uIFByZWZhY2UAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9tZXRob2QARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgbWV0aG9kAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX2ZpZWxkAFBhdXNlZABJbnZhbGlkIHdvcmQgZW5jb3VudGVyZWQASW52YWxpZCBtZXRob2QgZW5jb3VudGVyZWQAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzY2hlbWEAUmVxdWVzdCBoYXMgaW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX0NIVU5LX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX05BTUVfQ09NUExFVEUASFBFX0NCX01FU1NBR0VfQ09NUExFVEUASFBFX0NCX01FVEhPRF9DT01QTEVURQBIUEVfQ0JfSEVBREVSX0ZJRUxEX0NPTVBMRVRFAERFTEVURQBIUEVfSU5WQUxJRF9FT0ZfU1RBVEUASU5WQUxJRF9TU0xfQ0VSVElGSUNBVEUAUEFVU0UATk9fUkVTUE9OU0UAVU5TVVBQT1JURURfTUVESUFfVFlQRQBHT05FAE5PVF9BQ0NFUFRBQkxFAFNFUlZJQ0VfVU5BVkFJTEFCTEUAUkFOR0VfTk9UX1NBVElTRklBQkxFAE9SSUdJTl9JU19VTlJFQUNIQUJMRQBSRVNQT05TRV9JU19TVEFMRQBQVVJHRQBNRVJHRQBSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFAFJFUVVFU1RfSEVBREVSX1RPT19MQVJHRQBQQVlMT0FEX1RPT19MQVJHRQBJTlNVRkZJQ0lFTlRfU1RPUkFHRQBIUEVfUEFVU0VEX1VQR1JBREUASFBFX1BBVVNFRF9IMl9VUEdSQURFAFNPVVJDRQBBTk5PVU5DRQBUUkFDRQBIUEVfVU5FWFBFQ1RFRF9TUEFDRQBERVNDUklCRQBVTlNVQlNDUklCRQBSRUNPUkQASFBFX0lOVkFMSURfTUVUSE9EAE5PVF9GT1VORABQUk9QRklORABVTkJJTkQAUkVCSU5EAFVOQVVUSE9SSVpFRABNRVRIT0RfTk9UX0FMTE9XRUQASFRUUF9WRVJTSU9OX05PVF9TVVBQT1JURUQAQUxSRUFEWV9SRVBPUlRFRABBQ0NFUFRFRABOT1RfSU1QTEVNRU5URUQATE9PUF9ERVRFQ1RFRABIUEVfQ1JfRVhQRUNURUQASFBFX0xGX0VYUEVDVEVEAENSRUFURUQASU1fVVNFRABIUEVfUEFVU0VEAFRJTUVPVVRfT0NDVVJFRABQQVlNRU5UX1JFUVVJUkVEAFBSRUNPTkRJVElPTl9SRVFVSVJFRABQUk9YWV9BVVRIRU5USUNBVElPTl9SRVFVSVJFRABORVRXT1JLX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAExFTkdUSF9SRVFVSVJFRABTU0xfQ0VSVElGSUNBVEVfUkVRVUlSRUQAVVBHUkFERV9SRVFVSVJFRABQQUdFX0VYUElSRUQAUFJFQ09ORElUSU9OX0ZBSUxFRABFWFBFQ1RBVElPTl9GQUlMRUQAUkVWQUxJREFUSU9OX0ZBSUxFRABTU0xfSEFORFNIQUtFX0ZBSUxFRABMT0NLRUQAVFJBTlNGT1JNQVRJT05fQVBQTElFRABOT1RfTU9ESUZJRUQATk9UX0VYVEVOREVEAEJBTkRXSURUSF9MSU1JVF9FWENFRURFRABTSVRFX0lTX09WRVJMT0FERUQASEVBRABFeHBlY3RlZCBIVFRQLwAAXhMAACYTAAAwEAAA8BcAAJ0TAAAVEgAAORcAAPASAAAKEAAAdRIAAK0SAACCEwAATxQAAH8QAACgFQAAIxQAAIkSAACLFAAATRUAANQRAADPFAAAEBgAAMkWAADcFgAAwREAAOAXAAC7FAAAdBQAAHwVAADlFAAACBcAAB8QAABlFQAAoxQAACgVAAACFQAAmRUAACwQAACLGQAATw8AANQOAABqEAAAzhAAAAIXAACJDgAAbhMAABwTAABmFAAAVhcAAMETAADNEwAAbBMAAGgXAABmFwAAXxcAACITAADODwAAaQ4AANgOAABjFgAAyxMAAKoOAAAoFwAAJhcAAMUTAABdFgAA6BEAAGcTAABlEwAA8hYAAHMTAAAdFwAA+RYAAPMRAADPDgAAzhUAAAwSAACzEQAApREAAGEQAAAyFwAAuxMAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIDAgICAgIAAAICAAICAAICAgICAgICAgIABAAAAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbG9zZWVlcC1hbGl2ZQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEAAAEBAAEBAAEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AAAAAAAAAAAAAAAAAAAByYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AAAAAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQIAAQMAAAAAAAAAAAAAAAAAAAAAAAAEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAIAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOT1VOQ0VFQ0tPVVRORUNURVRFQ1JJQkVMVVNIRVRFQURTRUFSQ0hSR0VDVElWSVRZTEVOREFSVkVPVElGWVBUSU9OU0NIU0VBWVNUQVRDSEdFT1JESVJFQ1RPUlRSQ0hQQVJBTUVURVJVUkNFQlNDUklCRUFSRE9XTkFDRUlORE5LQ0tVQlNDUklCRUhUVFAvQURUUC8=", "base64"); - } -}); - -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js -var require_llhttp_simd_wasm = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js"(exports, module2) { - var { Buffer: Buffer2 } = require("node:buffer"); - module2.exports = Buffer2.from("AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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IAH9CwMAIABBMGogAf0LAwAgAEEgaiAB/QsDACAAQd0BNgIcQQALewEBfwJAIAAoAgwiAw0AAkAgACgCBEUNACAAIAE2AgQLAkAgACABIAIQxICAgAAiAw0AIAAoAgwPCyAAIAM2AhxBACEDIAAoAgQiAUUNACAAIAEgAiAAKAIIEYGAgIAAACIBRQ0AIAAgAjYCFCAAIAE2AgwgASEDCyADC+TzAQMOfwN+BH8jgICAgABBEGsiAySAgICAACABIQQgASEFIAEhBiABIQcgASEIIAEhCSABIQogASELIAEhDCABIQ0gASEOIAEhDwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIcIhBBf2oO3QHaAQHZAQIDBAUGBwgJCgsMDQ7YAQ8Q1wEREtYBExQVFhcYGRob4AHfARwdHtUBHyAhIiMkJdQBJicoKSorLNMB0gEtLtEB0AEvMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUbbAUdISUrPAc4BS80BTMwBTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEBkgGTAZQBlQGWAZcBmAGZAZoBmwGcAZ0BngGfAaABoQGiAaMBpAGlAaYBpwGoAakBqgGrAawBrQGuAa8BsAGxAbIBswG0AbUBtgG3AcsBygG4AckBuQHIAboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBANwBC0EAIRAMxgELQQ4hEAzFAQtBDSEQDMQBC0EPIRAMwwELQRAhEAzCAQtBEyEQDMEBC0EUIRAMwAELQRUhEAy/AQtBFiEQDL4BC0EXIRAMvQELQRghEAy8AQtBGSEQDLsBC0EaIRAMugELQRshEAy5AQtBHCEQDLgBC0EIIRAMtwELQR0hEAy2AQtBICEQDLUBC0EfIRAMtAELQQchEAyzAQtBISEQDLIBC0EiIRAMsQELQR4hEAywAQtBIyEQDK8BC0ESIRAMrgELQREhEAytAQtBJCEQDKwBC0ElIRAMqwELQSYhEAyqAQtBJyEQDKkBC0HDASEQDKgBC0EpIRAMpwELQSshEAymAQtBLCEQDKUBC0EtIRAMpAELQS4hEAyjAQtBLyEQDKIBC0HEASEQDKEBC0EwIRAMoAELQTQhEAyfAQtBDCEQDJ4BC0ExIRAMnQELQTIhEAycAQtBMyEQDJsBC0E5IRAMmgELQTUhEAyZAQtBxQEhEAyYAQtBCyEQDJcBC0E6IRAMlgELQTYhEAyVAQtBCiEQDJQBC0E3IRAMkwELQTghEAySAQtBPCEQDJEBC0E7IRAMkAELQT0hEAyPAQtBCSEQDI4BC0EoIRAMjQELQT4hEAyMAQtBPyEQDIsBC0HAACEQDIoBC0HBACEQDIkBC0HCACEQDIgBC0HDACEQDIcBC0HEACEQDIYBC0HFACEQDIUBC0HGACEQDIQBC0EqIRAMgwELQccAIRAMggELQcgAIRAMgQELQckAIRAMgAELQcoAIRAMfwtBywAhEAx+C0HNACEQDH0LQcwAIRAMfAtBzgAhEAx7C0HPACEQDHoLQdAAIRAMeQtB0QAhEAx4C0HSACEQDHcLQdMAIRAMdgtB1AAhEAx1C0HWACEQDHQLQdUAIRAMcwtBBiEQDHILQdcAIRAMcQtBBSEQDHALQdgAIRAMbwtBBCEQDG4LQdkAIRAMbQtB2gAhEAxsC0HbACEQDGsLQdwAIRAMagtBAyEQDGkLQd0AIRAMaAtB3gAhEAxnC0HfACEQDGYLQeEAIRAMZQtB4AAhEAxkC0HiACEQDGMLQeMAIRAMYgtBAiEQDGELQeQAIRAMYAtB5QAhEAxfC0HmACEQDF4LQecAIRAMXQtB6AAhEAxcC0HpACEQDFsLQeoAIRAMWgtB6wAhEAxZC0HsACEQDFgLQe0AIRAMVwtB7gAhEAxWC0HvACEQDFULQfAAIRAMVAtB8QAhEAxTC0HyACEQDFILQfMAIRAMUQtB9AAhEAxQC0H1ACEQDE8LQfYAIRAMTgtB9wAhEAxNC0H4ACEQDEwLQfkAIRAMSwtB+gAhEAxKC0H7ACEQDEkLQfwAIRAMSAtB/QAhEAxHC0H+ACEQDEYLQf8AIRAMRQtBgAEhEAxEC0GBASEQDEMLQYIBIRAMQgtBgwEhEAxBC0GEASEQDEALQYUBIRAMPwtBhgEhEAw+C0GHASEQDD0LQYgBIRAMPAtBiQEhEAw7C0GKASEQDDoLQYsBIRAMOQtBjAEhEAw4C0GNASEQDDcLQY4BIRAMNgtBjwEhEAw1C0GQASEQDDQLQZEBIRAMMwtBkgEhEAwyC0GTASEQDDELQZQBIRAMMAtBlQEhEAwvC0GWASEQDC4LQZcBIRAMLQtBmAEhEAwsC0GZASEQDCsLQZoBIRAMKgtBmwEhEAwpC0GcASEQDCgLQZ0BIRAMJwtBngEhEAwmC0GfASEQDCULQaABIRAMJAtBoQEhEAwjC0GiASEQDCILQaMBIRAMIQtBpAEhEAwgC0GlASEQDB8LQaYBIRAMHgtBpwEhEAwdC0GoASEQDBwLQakBIRAMGwtBqgEhEAwaC0GrASEQDBkLQawBIRAMGAtBrQEhEAwXC0GuASEQDBYLQQEhEAwVC0GvASEQDBQLQbABIRAMEwtBsQEhEAwSC0GzASEQDBELQbIBIRAMEAtBtAEhEAwPC0G1ASEQDA4LQbYBIRAMDQtBtwEhEAwMC0G4ASEQDAsLQbkBIRAMCgtBugEhEAwJC0G7ASEQDAgLQcYBIRAMBwtBvAEhEAwGC0G9ASEQDAULQb4BIRAMBAtBvwEhEAwDC0HAASEQDAILQcIBIRAMAQtBwQEhEAsDQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAOxwEAAQID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YWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsb3NlZWVwLWFsaXZlAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgAAAAAAAAAAAAAAAAAAAHJhbnNmZXItZW5jb2RpbmdwZ3JhZGUNCg0KDQpTTQ0KDQpUVFAvQ0UvVFNQLwAAAAAAAAAAAAAAAAECAAEDAAAAAAAAAAAAAAAAAAAAAAAABAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAABAAACAAAAAAAAAAAAAAAAAAAAAAAAAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAACAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==", "base64"); + function parseJSONFromBytes(bytes) { + return JSON.parse(utf8DecodeBytes(bytes)); + } + function bodyMimeType(requestOrResponse) { + const headers = requestOrResponse[kState].headersList; + const mimeType = extractMimeType(headers); + if (mimeType === "failure") { + return null; + } + return mimeType; + } + module2.exports = { + extractBody, + safelyExtractBody, + cloneBody, + mixinBody + }; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/client.js -var require_client = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/client.js"(exports, module2) { +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/client-h1.js +var require_client_h1 = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/client-h1.js"(exports, module2) { "use strict"; var assert3 = require("node:assert"); - var net = require("node:net"); - var http = require("node:http"); - var { pipeline } = require("node:stream"); var util = require_util(); var { channels } = require_diagnostics(); var timers = require_timers(); - var Request = require_request(); - var DispatcherBase = require_dispatcher_base(); var { RequestContentLengthMismatchError, ResponseContentLengthMismatchError, - InvalidArgumentError, RequestAbortedError, HeadersTimeoutError, HeadersOverflowError, @@ -11411,28 +10693,19 @@ var require_client = __commonJS({ InformationalError, BodyTimeoutError, HTTPParserError, - ResponseExceededMaxSizeError, - ClientDestroyedError + ResponseExceededMaxSizeError } = require_errors(); - var buildConnector = require_connect(); var { kUrl, kReset, - kServerName, kClient, - kBusy, kParser, - kConnect, kBlocking, - kResuming, kRunning, kPending, kSize, kWriting, kQueue, - kConnected, - kConnecting, - kNeedDrain, kNoRef, kKeepAliveDefaultTimeout, kHostHeader, @@ -11448,1664 +10721,2159 @@ var require_client = __commonJS({ kHeadersTimeout, kBodyTimeout, kStrictContentLength, - kConnector, - kMaxRedirections, kMaxRequests, kCounter, - kClose, - kDestroy, - kDispatch, - kInterceptors, - kLocalAddress, kMaxResponseSize, - kHTTPConnVersion, - // HTTP2 - kHost, - kHTTP2Session, - kHTTP2SessionState, - kHTTP2BuildRequest, - kHTTP2CopyHeaders, - kHTTP1BuildRequest + kOnError, + kResume, + kHTTPContext } = require_symbols(); - var http2; - try { - http2 = require("node:http2"); - } catch { - http2 = { constants: {} }; + var constants = require_constants3(); + var EMPTY_BUF = Buffer.alloc(0); + var FastBuffer = Buffer[Symbol.species]; + var addListener = util.addListener; + var removeAllListeners = util.removeAllListeners; + var extractBody; + async function lazyllhttp() { + const llhttpWasmData = process.env.JEST_WORKER_ID ? require_llhttp_wasm() : void 0; + let mod; + try { + mod = await WebAssembly.compile(require_llhttp_simd_wasm()); + } catch (e) { + mod = await WebAssembly.compile(llhttpWasmData || require_llhttp_wasm()); + } + return await WebAssembly.instantiate(mod, { + env: { + /* eslint-disable camelcase */ + wasm_on_url: (p, at, len) => { + return 0; + }, + wasm_on_status: (p, at, len) => { + assert3.strictEqual(currentParser.ptr, p); + const start = at - currentBufferPtr + currentBufferRef.byteOffset; + return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + }, + wasm_on_message_begin: (p) => { + assert3.strictEqual(currentParser.ptr, p); + return currentParser.onMessageBegin() || 0; + }, + wasm_on_header_field: (p, at, len) => { + assert3.strictEqual(currentParser.ptr, p); + const start = at - currentBufferPtr + currentBufferRef.byteOffset; + return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + }, + wasm_on_header_value: (p, at, len) => { + assert3.strictEqual(currentParser.ptr, p); + const start = at - currentBufferPtr + currentBufferRef.byteOffset; + return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + }, + wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { + assert3.strictEqual(currentParser.ptr, p); + return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0; + }, + wasm_on_body: (p, at, len) => { + assert3.strictEqual(currentParser.ptr, p); + const start = at - currentBufferPtr + currentBufferRef.byteOffset; + return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + }, + wasm_on_message_complete: (p) => { + assert3.strictEqual(currentParser.ptr, p); + return currentParser.onMessageComplete() || 0; + } + /* eslint-enable camelcase */ + } + }); } - var { - constants: { - HTTP2_HEADER_AUTHORITY, - HTTP2_HEADER_METHOD, - HTTP2_HEADER_PATH, - HTTP2_HEADER_SCHEME, - HTTP2_HEADER_CONTENT_LENGTH, - HTTP2_HEADER_EXPECT, - HTTP2_HEADER_STATUS + var llhttpInstance = null; + var llhttpPromise = lazyllhttp(); + llhttpPromise.catch(); + var currentParser = null; + var currentBufferRef = null; + var currentBufferSize = 0; + var currentBufferPtr = null; + var TIMEOUT_HEADERS = 1; + var TIMEOUT_BODY = 2; + var TIMEOUT_IDLE = 3; + var Parser = class { + constructor(client, socket, { exports: exports2 }) { + assert3(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0); + this.llhttp = exports2; + this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE); + this.client = client; + this.socket = socket; + this.timeout = null; + this.timeoutValue = null; + this.timeoutType = null; + this.statusCode = null; + this.statusText = ""; + this.upgrade = false; + this.headers = []; + this.headersSize = 0; + this.headersMaxSize = client[kMaxHeadersSize]; + this.shouldKeepAlive = false; + this.paused = false; + this.resume = this.resume.bind(this); + this.bytesRead = 0; + this.keepAlive = ""; + this.contentLength = ""; + this.connection = ""; + this.maxResponseSize = client[kMaxResponseSize]; } - } = http2; - var h2ExperimentalWarned = false; - var FastBuffer = Buffer[Symbol.species]; - var kClosedResolve = Symbol("kClosedResolve"); - var Client = class extends DispatcherBase { - /** - * - * @param {string|URL} url - * @param {import('../types/client').Client.Options} options - */ - constructor(url, { - interceptors, - maxHeaderSize, - headersTimeout, - socketTimeout, - requestTimeout, - connectTimeout, - bodyTimeout, - idleTimeout, - keepAlive, - keepAliveTimeout, - maxKeepAliveTimeout, - keepAliveMaxTimeout, - keepAliveTimeoutThreshold, - socketPath, - pipelining, - tls, - strictContentLength, - maxCachedSessions, - maxRedirections, - connect: connect2, - maxRequestsPerClient, - localAddress, - maxResponseSize, - autoSelectFamily, - autoSelectFamilyAttemptTimeout, - // h2 - allowH2, - maxConcurrentStreams - } = {}) { - super(); - if (keepAlive !== void 0) { - throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); + setTimeout(value, type) { + this.timeoutType = type; + if (value !== this.timeoutValue) { + timers.clearTimeout(this.timeout); + if (value) { + this.timeout = timers.setTimeout(onParserTimeout, value, this); + if (this.timeout.unref) { + this.timeout.unref(); + } + } else { + this.timeout = null; + } + this.timeoutValue = value; + } else if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh(); + } } - if (socketTimeout !== void 0) { - throw new InvalidArgumentError("unsupported socketTimeout, use headersTimeout & bodyTimeout instead"); + } + resume() { + if (this.socket.destroyed || !this.paused) { + return; } - if (requestTimeout !== void 0) { - throw new InvalidArgumentError("unsupported requestTimeout, use headersTimeout & bodyTimeout instead"); + assert3(this.ptr != null); + assert3(currentParser == null); + this.llhttp.llhttp_resume(this.ptr); + assert3(this.timeoutType === TIMEOUT_BODY); + if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh(); + } + } + this.paused = false; + this.execute(this.socket.read() || EMPTY_BUF); + this.readMore(); + } + readMore() { + while (!this.paused && this.ptr) { + const chunk = this.socket.read(); + if (chunk === null) { + break; + } + this.execute(chunk); + } + } + execute(data) { + assert3(this.ptr != null); + assert3(currentParser == null); + assert3(!this.paused); + const { socket, llhttp } = this; + if (data.length > currentBufferSize) { + if (currentBufferPtr) { + llhttp.free(currentBufferPtr); + } + currentBufferSize = Math.ceil(data.length / 4096) * 4096; + currentBufferPtr = llhttp.malloc(currentBufferSize); + } + new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data); + try { + let ret; + try { + currentBufferRef = data; + currentParser = this; + ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length); + } catch (err) { + throw err; + } finally { + currentParser = null; + currentBufferRef = null; + } + const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr; + if (ret === constants.ERROR.PAUSED_UPGRADE) { + this.onUpgrade(data.slice(offset)); + } else if (ret === constants.ERROR.PAUSED) { + this.paused = true; + socket.unshift(data.slice(offset)); + } else if (ret !== constants.ERROR.OK) { + const ptr = llhttp.llhttp_get_error_reason(this.ptr); + let message = ""; + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0); + message = "Response does not match the HTTP/1.1 protocol (" + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + ")"; + } + throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset)); + } + } catch (err) { + util.destroy(socket, err); } - if (idleTimeout !== void 0) { - throw new InvalidArgumentError("unsupported idleTimeout, use keepAliveTimeout instead"); + } + destroy() { + assert3(this.ptr != null); + assert3(currentParser == null); + this.llhttp.llhttp_free(this.ptr); + this.ptr = null; + timers.clearTimeout(this.timeout); + this.timeout = null; + this.timeoutValue = null; + this.timeoutType = null; + this.paused = false; + } + onStatus(buf) { + this.statusText = buf.toString(); + } + onMessageBegin() { + const { socket, client } = this; + if (socket.destroyed) { + return -1; } - if (maxKeepAliveTimeout !== void 0) { - throw new InvalidArgumentError("unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead"); + const request = client[kQueue][client[kRunningIdx]]; + if (!request) { + return -1; } - if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) { - throw new InvalidArgumentError("invalid maxHeaderSize"); + request.onResponseStarted(); + } + onHeaderField(buf) { + const len = this.headers.length; + if ((len & 1) === 0) { + this.headers.push(buf); + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]); } - if (socketPath != null && typeof socketPath !== "string") { - throw new InvalidArgumentError("invalid socketPath"); + this.trackHeader(buf.length); + } + onHeaderValue(buf) { + let len = this.headers.length; + if ((len & 1) === 1) { + this.headers.push(buf); + len += 1; + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]); } - if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) { - throw new InvalidArgumentError("invalid connectTimeout"); + const key = this.headers[len - 2]; + if (key.length === 10) { + const headerName = util.bufferToLowerCasedHeaderName(key); + if (headerName === "keep-alive") { + this.keepAlive += buf.toString(); + } else if (headerName === "connection") { + this.connection += buf.toString(); + } + } else if (key.length === 14 && util.bufferToLowerCasedHeaderName(key) === "content-length") { + this.contentLength += buf.toString(); } - if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) { - throw new InvalidArgumentError("invalid keepAliveTimeout"); + this.trackHeader(buf.length); + } + trackHeader(len) { + this.headersSize += len; + if (this.headersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()); } - if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) { - throw new InvalidArgumentError("invalid keepAliveMaxTimeout"); + } + onUpgrade(head) { + const { upgrade, client, socket, headers, statusCode } = this; + assert3(upgrade); + const request = client[kQueue][client[kRunningIdx]]; + assert3(request); + assert3(!socket.destroyed); + assert3(socket === client[kSocket]); + assert3(!this.paused); + assert3(request.upgrade || request.method === "CONNECT"); + this.statusCode = null; + this.statusText = ""; + this.shouldKeepAlive = null; + assert3(this.headers.length % 2 === 0); + this.headers = []; + this.headersSize = 0; + socket.unshift(head); + socket[kParser].destroy(); + socket[kParser] = null; + socket[kClient] = null; + socket[kError] = null; + removeAllListeners(socket); + client[kSocket] = null; + client[kHTTPContext] = null; + client[kQueue][client[kRunningIdx]++] = null; + client.emit("disconnect", client[kUrl], [client], new InformationalError("upgrade")); + try { + request.onUpgrade(statusCode, headers, socket); + } catch (err) { + util.destroy(socket, err); } - if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) { - throw new InvalidArgumentError("invalid keepAliveTimeoutThreshold"); + client[kResume](); + } + onHeadersComplete(statusCode, upgrade, shouldKeepAlive) { + const { client, socket, headers, statusText } = this; + if (socket.destroyed) { + return -1; } - if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) { - throw new InvalidArgumentError("headersTimeout must be a positive integer or zero"); + const request = client[kQueue][client[kRunningIdx]]; + if (!request) { + return -1; } - if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) { - throw new InvalidArgumentError("bodyTimeout must be a positive integer or zero"); + assert3(!this.upgrade); + assert3(this.statusCode < 200); + if (statusCode === 100) { + util.destroy(socket, new SocketError("bad response", util.getSocketInfo(socket))); + return -1; } - if (connect2 != null && typeof connect2 !== "function" && typeof connect2 !== "object") { - throw new InvalidArgumentError("connect must be a function or an object"); + if (upgrade && !request.upgrade) { + util.destroy(socket, new SocketError("bad upgrade", util.getSocketInfo(socket))); + return -1; } - if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { - throw new InvalidArgumentError("maxRedirections must be a positive number"); + assert3.strictEqual(this.timeoutType, TIMEOUT_HEADERS); + this.statusCode = statusCode; + this.shouldKeepAlive = shouldKeepAlive || // Override llhttp value which does not allow keepAlive for HEAD. + request.method === "HEAD" && !socket[kReset] && this.connection.toLowerCase() === "keep-alive"; + if (this.statusCode >= 200) { + const bodyTimeout = request.bodyTimeout != null ? request.bodyTimeout : client[kBodyTimeout]; + this.setTimeout(bodyTimeout, TIMEOUT_BODY); + } else if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh(); + } } - if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { - throw new InvalidArgumentError("maxRequestsPerClient must be a positive number"); + if (request.method === "CONNECT") { + assert3(client[kRunning] === 1); + this.upgrade = true; + return 2; } - if (localAddress != null && (typeof localAddress !== "string" || net.isIP(localAddress) === 0)) { - throw new InvalidArgumentError("localAddress must be valid string IP address"); + if (upgrade) { + assert3(client[kRunning] === 1); + this.upgrade = true; + return 2; } - if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) { - throw new InvalidArgumentError("maxResponseSize must be a positive number"); + assert3(this.headers.length % 2 === 0); + this.headers = []; + this.headersSize = 0; + if (this.shouldKeepAlive && client[kPipelining]) { + const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null; + if (keepAliveTimeout != null) { + const timeout = Math.min( + keepAliveTimeout - client[kKeepAliveTimeoutThreshold], + client[kKeepAliveMaxTimeout] + ); + if (timeout <= 0) { + socket[kReset] = true; + } else { + client[kKeepAliveTimeoutValue] = timeout; + } + } else { + client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout]; + } + } else { + socket[kReset] = true; } - if (autoSelectFamilyAttemptTimeout != null && (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1)) { - throw new InvalidArgumentError("autoSelectFamilyAttemptTimeout must be a positive number"); + const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false; + if (request.aborted) { + return -1; } - if (allowH2 != null && typeof allowH2 !== "boolean") { - throw new InvalidArgumentError("allowH2 must be a valid boolean value"); + if (request.method === "HEAD") { + return 1; } - if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== "number" || maxConcurrentStreams < 1)) { - throw new InvalidArgumentError("maxConcurrentStreams must be a positive integer, greater than 0"); + if (statusCode < 200) { + return 1; } - if (typeof connect2 !== "function") { - connect2 = buildConnector({ - ...tls, - maxCachedSessions, - allowH2, - socketPath, - timeout: connectTimeout, - ...util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, - ...connect2 - }); + if (socket[kBlocking]) { + socket[kBlocking] = false; + client[kResume](); } - this[kInterceptors] = interceptors?.Client && Array.isArray(interceptors.Client) ? interceptors.Client : [createRedirectInterceptor({ maxRedirections })]; - this[kUrl] = util.parseOrigin(url); - this[kConnector] = connect2; - this[kSocket] = null; - this[kPipelining] = pipelining != null ? pipelining : 1; - this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize; - this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout; - this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 6e5 : keepAliveMaxTimeout; - this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 1e3 : keepAliveTimeoutThreshold; - this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout]; - this[kServerName] = null; - this[kLocalAddress] = localAddress != null ? localAddress : null; - this[kResuming] = 0; - this[kNeedDrain] = 0; - this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ""}\r -`; - this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 3e5; - this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 3e5; - this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength; - this[kMaxRedirections] = maxRedirections; - this[kMaxRequests] = maxRequestsPerClient; - this[kClosedResolve] = null; - this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1; - this[kHTTPConnVersion] = "h1"; - this[kHTTP2Session] = null; - this[kHTTP2SessionState] = !allowH2 ? null : { - // streams: null, // Fixed queue of streams - For future support of `push` - openStreams: 0, - // Keep track of them to decide whether or not unref the session - maxConcurrentStreams: maxConcurrentStreams != null ? maxConcurrentStreams : 100 - // Max peerConcurrentStreams for a Node h2 server - }; - this[kHost] = `${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ""}`; - this[kQueue] = []; - this[kRunningIdx] = 0; - this[kPendingIdx] = 0; - } - get pipelining() { - return this[kPipelining]; - } - set pipelining(value) { - this[kPipelining] = value; - resume(this, true); - } - get [kPending]() { - return this[kQueue].length - this[kPendingIdx]; - } - get [kRunning]() { - return this[kPendingIdx] - this[kRunningIdx]; - } - get [kSize]() { - return this[kQueue].length - this[kRunningIdx]; - } - get [kConnected]() { - return !!this[kSocket] && !this[kConnecting] && !this[kSocket].destroyed; - } - get [kBusy]() { - const socket = this[kSocket]; - return socket && (socket[kReset] || socket[kWriting] || socket[kBlocking]) || this[kSize] >= (this[kPipelining] || 1) || this[kPending] > 0; + return pause ? constants.ERROR.PAUSED : 0; } - /* istanbul ignore: only used for test */ - [kConnect](cb) { - connect(this); - this.once("connect", cb); + onBody(buf) { + const { client, socket, statusCode, maxResponseSize } = this; + if (socket.destroyed) { + return -1; + } + const request = client[kQueue][client[kRunningIdx]]; + assert3(request); + assert3.strictEqual(this.timeoutType, TIMEOUT_BODY); + if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh(); + } + } + assert3(statusCode >= 200); + if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { + util.destroy(socket, new ResponseExceededMaxSizeError()); + return -1; + } + this.bytesRead += buf.length; + if (request.onData(buf) === false) { + return constants.ERROR.PAUSED; + } } - [kDispatch](opts, handler) { - const origin = opts.origin || this[kUrl].origin; - const request = this[kHTTPConnVersion] === "h2" ? Request[kHTTP2BuildRequest](origin, opts, handler) : Request[kHTTP1BuildRequest](origin, opts, handler); - this[kQueue].push(request); - if (this[kResuming]) { - } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { - this[kResuming] = 1; - process.nextTick(resume, this); - } else { - resume(this, true); + onMessageComplete() { + const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this; + if (socket.destroyed && (!statusCode || shouldKeepAlive)) { + return -1; } - if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { - this[kNeedDrain] = 2; + if (upgrade) { + return; + } + const request = client[kQueue][client[kRunningIdx]]; + assert3(request); + assert3(statusCode >= 100); + this.statusCode = null; + this.statusText = ""; + this.bytesRead = 0; + this.contentLength = ""; + this.keepAlive = ""; + this.connection = ""; + assert3(this.headers.length % 2 === 0); + this.headers = []; + this.headersSize = 0; + if (statusCode < 200) { + return; + } + if (request.method !== "HEAD" && contentLength && bytesRead !== parseInt(contentLength, 10)) { + util.destroy(socket, new ResponseContentLengthMismatchError()); + return -1; + } + request.onComplete(headers); + client[kQueue][client[kRunningIdx]++] = null; + if (socket[kWriting]) { + assert3.strictEqual(client[kRunning], 0); + util.destroy(socket, new InformationalError("reset")); + return constants.ERROR.PAUSED; + } else if (!shouldKeepAlive) { + util.destroy(socket, new InformationalError("reset")); + return constants.ERROR.PAUSED; + } else if (socket[kReset] && client[kRunning] === 0) { + util.destroy(socket, new InformationalError("reset")); + return constants.ERROR.PAUSED; + } else if (client[kPipelining] == null || client[kPipelining] === 1) { + setImmediate(() => client[kResume]()); + } else { + client[kResume](); } - return this[kNeedDrain] < 2; } - async [kClose]() { - return new Promise((resolve) => { - if (this[kSize]) { - this[kClosedResolve] = resolve; - } else { - resolve(null); - } - }); + }; + function onParserTimeout(parser) { + const { socket, timeoutType, client } = parser; + if (timeoutType === TIMEOUT_HEADERS) { + if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { + assert3(!parser.paused, "cannot be paused while waiting for headers"); + util.destroy(socket, new HeadersTimeoutError()); + } + } else if (timeoutType === TIMEOUT_BODY) { + if (!parser.paused) { + util.destroy(socket, new BodyTimeoutError()); + } + } else if (timeoutType === TIMEOUT_IDLE) { + assert3(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]); + util.destroy(socket, new InformationalError("socket idle timeout")); } - async [kDestroy](err) { - return new Promise((resolve) => { - const requests = this[kQueue].splice(this[kPendingIdx]); + } + async function connectH1(client, socket) { + client[kSocket] = socket; + if (!llhttpInstance) { + llhttpInstance = await llhttpPromise; + llhttpPromise = null; + } + socket[kNoRef] = false; + socket[kWriting] = false; + socket[kReset] = false; + socket[kBlocking] = false; + socket[kParser] = new Parser(client, socket, llhttpInstance); + addListener(socket, "error", function(err) { + const parser = this[kParser]; + assert3(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); + if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { + parser.onMessageComplete(); + return; + } + this[kError] = err; + this[kClient][kOnError](err); + }); + addListener(socket, "readable", function() { + const parser = this[kParser]; + if (parser) { + parser.readMore(); + } + }); + addListener(socket, "end", function() { + const parser = this[kParser]; + if (parser.statusCode && !parser.shouldKeepAlive) { + parser.onMessageComplete(); + return; + } + util.destroy(this, new SocketError("other side closed", util.getSocketInfo(this))); + }); + addListener(socket, "close", function() { + const client2 = this[kClient]; + const parser = this[kParser]; + if (parser) { + if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { + parser.onMessageComplete(); + } + this[kParser].destroy(); + this[kParser] = null; + } + const err = this[kError] || new SocketError("closed", util.getSocketInfo(this)); + client2[kSocket] = null; + client2[kHTTPContext] = null; + if (client2.destroyed) { + assert3(client2[kPending] === 0); + const requests = client2[kQueue].splice(client2[kRunningIdx]); for (let i = 0; i < requests.length; i++) { const request = requests[i]; - errorRequest(this, request, err); - } - const callback = () => { - if (this[kClosedResolve]) { - this[kClosedResolve](); - this[kClosedResolve] = null; - } - resolve(); - }; - if (this[kHTTP2Session] != null) { - util.destroy(this[kHTTP2Session], err); - this[kHTTP2Session] = null; - this[kHTTP2SessionState] = null; + util.errorRequest(client2, request, err); } - if (this[kSocket]) { - util.destroy(this[kSocket].on("close", callback), err); - } else { + } else if (client2[kRunning] > 0 && err.code !== "UND_ERR_INFO") { + const request = client2[kQueue][client2[kRunningIdx]]; + client2[kQueue][client2[kRunningIdx]++] = null; + util.errorRequest(client2, request, err); + } + client2[kPendingIdx] = client2[kRunningIdx]; + assert3(client2[kRunning] === 0); + client2.emit("disconnect", client2[kUrl], [client2], err); + client2[kResume](); + }); + let closed = false; + socket.on("close", () => { + closed = true; + }); + return { + version: "h1", + defaultPipelining: 1, + write(...args) { + return writeH1(client, ...args); + }, + resume() { + resumeH1(client); + }, + destroy(err, callback) { + if (closed) { queueMicrotask(callback); + } else { + socket.destroy(err).on("close", callback); } - resume(this); - }); - } - }; - function onHttp2SessionError(err) { - assert3(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); - this[kSocket][kError] = err; - onError(this[kClient], err); + }, + get destroyed() { + return socket.destroyed; + }, + busy(request) { + if (socket[kWriting] || socket[kReset] || socket[kBlocking]) { + return true; + } + if (request) { + if (client[kRunning] > 0 && !request.idempotent) { + return true; + } + if (client[kRunning] > 0 && (request.upgrade || request.method === "CONNECT")) { + return true; + } + if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && (util.isStream(request.body) || util.isAsyncIterable(request.body) || util.isFormDataLike(request.body))) { + return true; + } + } + return false; + } + }; } - function onHttp2FrameError(type, code, id) { - const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`); - if (id === 0) { - this[kSocket][kError] = err; - onError(this[kClient], err); + function resumeH1(client) { + const socket = client[kSocket]; + if (socket && !socket.destroyed) { + if (client[kSize] === 0) { + if (!socket[kNoRef] && socket.unref) { + socket.unref(); + socket[kNoRef] = true; + } + } else if (socket[kNoRef] && socket.ref) { + socket.ref(); + socket[kNoRef] = false; + } + if (client[kSize] === 0) { + if (socket[kParser].timeoutType !== TIMEOUT_IDLE) { + socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_IDLE); + } + } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { + if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { + const request = client[kQueue][client[kRunningIdx]]; + const headersTimeout = request.headersTimeout != null ? request.headersTimeout : client[kHeadersTimeout]; + socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS); + } + } } } - function onHttp2SessionEnd() { - util.destroy(this, new SocketError("other side closed")); - util.destroy(this[kSocket], new SocketError("other side closed")); + function shouldSendContentLength(method) { + return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } - function onHTTP2GoAway(code) { - const client = this[kClient]; - const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`); - client[kSocket] = null; - client[kHTTP2Session] = null; - if (client.destroyed) { - assert3(this[kPending] === 0); - const requests = client[kQueue].splice(client[kRunningIdx]); - for (let i = 0; i < requests.length; i++) { - const request = requests[i]; - errorRequest(this, request, err); + function writeH1(client, request) { + const { method, path: path10, host, upgrade, blocking, reset } = request; + let { body, headers, contentLength } = request; + const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; + if (util.isFormDataLike(body)) { + if (!extractBody) { + extractBody = require_body().extractBody; } - } else if (client[kRunning] > 0) { - const request = client[kQueue][client[kRunningIdx]]; - client[kQueue][client[kRunningIdx]++] = null; - errorRequest(client, request, err); - } - client[kPendingIdx] = client[kRunningIdx]; - assert3(client[kRunning] === 0); - client.emit( - "disconnect", - client[kUrl], - [client], - err - ); - resume(client); - } - var constants = require_constants4(); - var createRedirectInterceptor = require_redirectInterceptor(); - var EMPTY_BUF = Buffer.alloc(0); - async function lazyllhttp() { - const llhttpWasmData = process.env.JEST_WORKER_ID ? require_llhttp_wasm() : void 0; - let mod; - try { - mod = await WebAssembly.compile(require_llhttp_simd_wasm()); - } catch (e) { - mod = await WebAssembly.compile(llhttpWasmData || require_llhttp_wasm()); + const [bodyStream, contentType] = extractBody(body); + if (request.contentType == null) { + headers.push("content-type", contentType); + } + body = bodyStream.stream; + contentLength = bodyStream.length; + } else if (util.isBlobLike(body) && request.contentType == null && body.type) { + headers.push("content-type", body.type); } - return await WebAssembly.instantiate(mod, { - env: { - /* eslint-disable camelcase */ - wasm_on_url: (p, at, len) => { - return 0; - }, - wasm_on_status: (p, at, len) => { - assert3.strictEqual(currentParser.ptr, p); - const start = at - currentBufferPtr + currentBufferRef.byteOffset; - return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; - }, - wasm_on_message_begin: (p) => { - assert3.strictEqual(currentParser.ptr, p); - return currentParser.onMessageBegin() || 0; - }, - wasm_on_header_field: (p, at, len) => { - assert3.strictEqual(currentParser.ptr, p); - const start = at - currentBufferPtr + currentBufferRef.byteOffset; - return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; - }, - wasm_on_header_value: (p, at, len) => { - assert3.strictEqual(currentParser.ptr, p); - const start = at - currentBufferPtr + currentBufferRef.byteOffset; - return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; - }, - wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { - assert3.strictEqual(currentParser.ptr, p); - return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0; - }, - wasm_on_body: (p, at, len) => { - assert3.strictEqual(currentParser.ptr, p); - const start = at - currentBufferPtr + currentBufferRef.byteOffset; - return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; - }, - wasm_on_message_complete: (p) => { - assert3.strictEqual(currentParser.ptr, p); - return currentParser.onMessageComplete() || 0; - } - /* eslint-enable camelcase */ + if (body && typeof body.read === "function") { + body.read(0); + } + const bodyLength = util.bodyLength(body); + contentLength = bodyLength ?? contentLength; + if (contentLength === null) { + contentLength = request.contentLength; + } + if (contentLength === 0 && !expectsPayload) { + contentLength = null; + } + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + util.errorRequest(client, request, new RequestContentLengthMismatchError()); + return false; } - }); - } - var llhttpInstance = null; - var llhttpPromise = lazyllhttp(); - llhttpPromise.catch(); - var currentParser = null; - var currentBufferRef = null; - var currentBufferSize = 0; - var currentBufferPtr = null; - var TIMEOUT_HEADERS = 1; - var TIMEOUT_BODY = 2; - var TIMEOUT_IDLE = 3; - var Parser = class { - constructor(client, socket, { exports: exports2 }) { - assert3(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0); - this.llhttp = exports2; - this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE); - this.client = client; - this.socket = socket; - this.timeout = null; - this.timeoutValue = null; - this.timeoutType = null; - this.statusCode = null; - this.statusText = ""; - this.upgrade = false; - this.headers = []; - this.headersSize = 0; - this.headersMaxSize = client[kMaxHeadersSize]; - this.shouldKeepAlive = false; - this.paused = false; - this.resume = this.resume.bind(this); - this.bytesRead = 0; - this.keepAlive = ""; - this.contentLength = ""; - this.connection = ""; - this.maxResponseSize = client[kMaxResponseSize]; + process.emitWarning(new RequestContentLengthMismatchError()); } - setTimeout(value, type) { - this.timeoutType = type; - if (value !== this.timeoutValue) { - timers.clearTimeout(this.timeout); - if (value) { - this.timeout = timers.setTimeout(onParserTimeout, value, this); - if (this.timeout.unref) { - this.timeout.unref(); + const socket = client[kSocket]; + const abort = (err) => { + if (request.aborted || request.completed) { + return; + } + util.errorRequest(client, request, err || new RequestAbortedError()); + util.destroy(body); + util.destroy(socket, new InformationalError("aborted")); + }; + try { + request.onConnect(abort); + } catch (err) { + util.errorRequest(client, request, err); + } + if (request.aborted) { + return false; + } + if (method === "HEAD") { + socket[kReset] = true; + } + if (upgrade || method === "CONNECT") { + socket[kReset] = true; + } + if (reset != null) { + socket[kReset] = reset; + } + if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { + socket[kReset] = true; + } + if (blocking) { + socket[kBlocking] = true; + } + let header = `${method} ${path10} HTTP/1.1\r +`; + if (typeof host === "string") { + header += `host: ${host}\r +`; + } else { + header += client[kHostHeader]; + } + if (upgrade) { + header += `connection: upgrade\r +upgrade: ${upgrade}\r +`; + } else if (client[kPipelining] && !socket[kReset]) { + header += "connection: keep-alive\r\n"; + } else { + header += "connection: close\r\n"; + } + if (Array.isArray(headers)) { + for (let n = 0; n < headers.length; n += 2) { + const key = headers[n + 0]; + const val = headers[n + 1]; + if (Array.isArray(val)) { + for (let i = 0; i < val.length; i++) { + header += `${key}: ${val[i]}\r +`; } } else { - this.timeout = null; - } - this.timeoutValue = value; - } else if (this.timeout) { - if (this.timeout.refresh) { - this.timeout.refresh(); + header += `${key}: ${val}\r +`; } } } - resume() { - if (this.socket.destroyed || !this.paused) { + if (channels.sendHeaders.hasSubscribers) { + channels.sendHeaders.publish({ request, headers: header, socket }); + } + if (!body || bodyLength === 0) { + writeBuffer({ abort, body: null, client, request, socket, contentLength, header, expectsPayload }); + } else if (util.isBuffer(body)) { + writeBuffer({ abort, body, client, request, socket, contentLength, header, expectsPayload }); + } else if (util.isBlobLike(body)) { + if (typeof body.stream === "function") { + writeIterable({ abort, body: body.stream(), client, request, socket, contentLength, header, expectsPayload }); + } else { + writeBlob({ abort, body, client, request, socket, contentLength, header, expectsPayload }); + } + } else if (util.isStream(body)) { + writeStream({ abort, body, client, request, socket, contentLength, header, expectsPayload }); + } else if (util.isIterable(body)) { + writeIterable({ abort, body, client, request, socket, contentLength, header, expectsPayload }); + } else { + assert3(false); + } + return true; + } + function writeStream({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { + assert3(contentLength !== 0 || client[kRunning] === 0, "stream body cannot be pipelined"); + let finished = false; + const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header }); + const onData = function(chunk) { + if (finished) { return; } - assert3(this.ptr != null); - assert3(currentParser == null); - this.llhttp.llhttp_resume(this.ptr); - assert3(this.timeoutType === TIMEOUT_BODY); - if (this.timeout) { - if (this.timeout.refresh) { - this.timeout.refresh(); + try { + if (!writer.write(chunk) && this.pause) { + this.pause(); } + } catch (err) { + util.destroy(this, err); } - this.paused = false; - this.execute(this.socket.read() || EMPTY_BUF); - this.readMore(); - } - readMore() { - while (!this.paused && this.ptr) { - const chunk = this.socket.read(); - if (chunk === null) { - break; - } - this.execute(chunk); + }; + const onDrain = function() { + if (finished) { + return; } - } - execute(data) { - assert3(this.ptr != null); - assert3(currentParser == null); - assert3(!this.paused); - const { socket, llhttp } = this; - if (data.length > currentBufferSize) { - if (currentBufferPtr) { - llhttp.free(currentBufferPtr); - } - currentBufferSize = Math.ceil(data.length / 4096) * 4096; - currentBufferPtr = llhttp.malloc(currentBufferSize); + if (body.resume) { + body.resume(); } - new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data); - try { - let ret; + }; + const onClose = function() { + queueMicrotask(() => { + body.removeListener("error", onFinished); + }); + if (!finished) { + const err = new RequestAbortedError(); + queueMicrotask(() => onFinished(err)); + } + }; + const onFinished = function(err) { + if (finished) { + return; + } + finished = true; + assert3(socket.destroyed || socket[kWriting] && client[kRunning] <= 1); + socket.off("drain", onDrain).off("error", onFinished); + body.removeListener("data", onData).removeListener("end", onFinished).removeListener("close", onClose); + if (!err) { try { - currentBufferRef = data; - currentParser = this; - ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length); - } catch (err) { - throw err; - } finally { - currentParser = null; - currentBufferRef = null; - } - const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr; - if (ret === constants.ERROR.PAUSED_UPGRADE) { - this.onUpgrade(data.slice(offset)); - } else if (ret === constants.ERROR.PAUSED) { - this.paused = true; - socket.unshift(data.slice(offset)); - } else if (ret !== constants.ERROR.OK) { - const ptr = llhttp.llhttp_get_error_reason(this.ptr); - let message = ""; - if (ptr) { - const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0); - message = "Response does not match the HTTP/1.1 protocol (" + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + ")"; - } - throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset)); + writer.end(); + } catch (er) { + err = er; } - } catch (err) { - util.destroy(socket, err); } + writer.destroy(err); + if (err && (err.code !== "UND_ERR_INFO" || err.message !== "reset")) { + util.destroy(body, err); + } else { + util.destroy(body); + } + }; + body.on("data", onData).on("end", onFinished).on("error", onFinished).on("close", onClose); + if (body.resume) { + body.resume(); } - destroy() { - assert3(this.ptr != null); - assert3(currentParser == null); - this.llhttp.llhttp_free(this.ptr); - this.ptr = null; - timers.clearTimeout(this.timeout); - this.timeout = null; - this.timeoutValue = null; - this.timeoutType = null; - this.paused = false; + socket.on("drain", onDrain).on("error", onFinished); + if (body.errorEmitted ?? body.errored) { + setImmediate(() => onFinished(body.errored)); + } else if (body.endEmitted ?? body.readableEnded) { + setImmediate(() => onFinished(null)); } - onStatus(buf) { - this.statusText = buf.toString(); + if (body.closeEmitted ?? body.closed) { + setImmediate(onClose); } - onMessageBegin() { - const { socket, client } = this; - if (socket.destroyed) { - return -1; + } + async function writeBuffer({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { + try { + if (!body) { + if (contentLength === 0) { + socket.write(`${header}content-length: 0\r +\r +`, "latin1"); + } else { + assert3(contentLength === null, "no body must not have content length"); + socket.write(`${header}\r +`, "latin1"); + } + } else if (util.isBuffer(body)) { + assert3(contentLength === body.byteLength, "buffer body must have content length"); + socket.cork(); + socket.write(`${header}content-length: ${contentLength}\r +\r +`, "latin1"); + socket.write(body); + socket.uncork(); + request.onBodySent(body); + if (!expectsPayload) { + socket[kReset] = true; + } } - const request = client[kQueue][client[kRunningIdx]]; - if (!request) { - return -1; + request.onRequestSent(); + client[kResume](); + } catch (err) { + abort(err); + } + } + async function writeBlob({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { + assert3(contentLength === body.size, "blob body must have content length"); + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError(); } - request.onResponseStarted(); + const buffer = Buffer.from(await body.arrayBuffer()); + socket.cork(); + socket.write(`${header}content-length: ${contentLength}\r +\r +`, "latin1"); + socket.write(buffer); + socket.uncork(); + request.onBodySent(buffer); + request.onRequestSent(); + if (!expectsPayload) { + socket[kReset] = true; + } + client[kResume](); + } catch (err) { + abort(err); } - onHeaderField(buf) { - const len = this.headers.length; - if ((len & 1) === 0) { - this.headers.push(buf); - } else { - this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]); + } + async function writeIterable({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { + assert3(contentLength !== 0 || client[kRunning] === 0, "iterator body cannot be pipelined"); + let callback = null; + function onDrain() { + if (callback) { + const cb = callback; + callback = null; + cb(); } - this.trackHeader(buf.length); } - onHeaderValue(buf) { - let len = this.headers.length; - if ((len & 1) === 1) { - this.headers.push(buf); - len += 1; + const waitForDrain = () => new Promise((resolve, reject) => { + assert3(callback === null); + if (socket[kError]) { + reject(socket[kError]); } else { - this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]); + callback = resolve; } - const key = this.headers[len - 2]; - if (key.length === 10) { - const headerName = util.bufferToLowerCasedHeaderName(key); - if (headerName === "keep-alive") { - this.keepAlive += buf.toString(); - } else if (headerName === "connection") { - this.connection += buf.toString(); + }); + socket.on("close", onDrain).on("drain", onDrain); + const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header }); + try { + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError]; + } + if (!writer.write(chunk)) { + await waitForDrain(); } - } else if (key.length === 14 && util.bufferToLowerCasedHeaderName(key) === "content-length") { - this.contentLength += buf.toString(); } - this.trackHeader(buf.length); + writer.end(); + } catch (err) { + writer.destroy(err); + } finally { + socket.off("close", onDrain).off("drain", onDrain); } - trackHeader(len) { - this.headersSize += len; - if (this.headersSize >= this.headersMaxSize) { - util.destroy(this.socket, new HeadersOverflowError()); - } + } + var AsyncWriter = class { + constructor({ abort, socket, request, contentLength, client, expectsPayload, header }) { + this.socket = socket; + this.request = request; + this.contentLength = contentLength; + this.client = client; + this.bytesWritten = 0; + this.expectsPayload = expectsPayload; + this.header = header; + this.abort = abort; + socket[kWriting] = true; } - onUpgrade(head) { - const { upgrade, client, socket, headers, statusCode } = this; - assert3(upgrade); - const request = client[kQueue][client[kRunningIdx]]; - assert3(request); - assert3(!socket.destroyed); - assert3(socket === client[kSocket]); - assert3(!this.paused); - assert3(request.upgrade || request.method === "CONNECT"); - this.statusCode = null; - this.statusText = ""; - this.shouldKeepAlive = null; - assert3(this.headers.length % 2 === 0); - this.headers = []; - this.headersSize = 0; - socket.unshift(head); - socket[kParser].destroy(); - socket[kParser] = null; - socket[kClient] = null; - socket[kError] = null; - socket.removeListener("error", onSocketError).removeListener("readable", onSocketReadable).removeListener("end", onSocketEnd).removeListener("close", onSocketClose); - client[kSocket] = null; - client[kQueue][client[kRunningIdx]++] = null; - client.emit("disconnect", client[kUrl], [client], new InformationalError("upgrade")); - try { - request.onUpgrade(statusCode, headers, socket); - } catch (err) { - util.destroy(socket, err); + write(chunk) { + const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this; + if (socket[kError]) { + throw socket[kError]; } - resume(client); - } - onHeadersComplete(statusCode, upgrade, shouldKeepAlive) { - const { client, socket, headers, statusText } = this; if (socket.destroyed) { - return -1; + return false; } - const request = client[kQueue][client[kRunningIdx]]; - if (!request) { - return -1; + const len = Buffer.byteLength(chunk); + if (!len) { + return true; } - assert3(!this.upgrade); - assert3(this.statusCode < 200); - if (statusCode === 100) { - util.destroy(socket, new SocketError("bad response", util.getSocketInfo(socket))); - return -1; + if (contentLength !== null && bytesWritten + len > contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError(); + } + process.emitWarning(new RequestContentLengthMismatchError()); } - if (upgrade && !request.upgrade) { - util.destroy(socket, new SocketError("bad upgrade", util.getSocketInfo(socket))); - return -1; + socket.cork(); + if (bytesWritten === 0) { + if (!expectsPayload) { + socket[kReset] = true; + } + if (contentLength === null) { + socket.write(`${header}transfer-encoding: chunked\r +`, "latin1"); + } else { + socket.write(`${header}content-length: ${contentLength}\r +\r +`, "latin1"); + } } - assert3.strictEqual(this.timeoutType, TIMEOUT_HEADERS); - this.statusCode = statusCode; - this.shouldKeepAlive = shouldKeepAlive || // Override llhttp value which does not allow keepAlive for HEAD. - request.method === "HEAD" && !socket[kReset] && this.connection.toLowerCase() === "keep-alive"; - if (this.statusCode >= 200) { - const bodyTimeout = request.bodyTimeout != null ? request.bodyTimeout : client[kBodyTimeout]; - this.setTimeout(bodyTimeout, TIMEOUT_BODY); - } else if (this.timeout) { - if (this.timeout.refresh) { - this.timeout.refresh(); + if (contentLength === null) { + socket.write(`\r +${len.toString(16)}\r +`, "latin1"); + } + this.bytesWritten += len; + const ret = socket.write(chunk); + socket.uncork(); + request.onBodySent(chunk); + if (!ret) { + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh(); + } } } - if (request.method === "CONNECT") { - assert3(client[kRunning] === 1); - this.upgrade = true; - return 2; + return ret; + } + end() { + const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this; + request.onRequestSent(); + socket[kWriting] = false; + if (socket[kError]) { + throw socket[kError]; } - if (upgrade) { - assert3(client[kRunning] === 1); - this.upgrade = true; - return 2; + if (socket.destroyed) { + return; } - assert3(this.headers.length % 2 === 0); - this.headers = []; - this.headersSize = 0; - if (this.shouldKeepAlive && client[kPipelining]) { - const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null; - if (keepAliveTimeout != null) { - const timeout = Math.min( - keepAliveTimeout - client[kKeepAliveTimeoutThreshold], - client[kKeepAliveMaxTimeout] - ); - if (timeout <= 0) { - socket[kReset] = true; - } else { - client[kKeepAliveTimeoutValue] = timeout; - } + if (bytesWritten === 0) { + if (expectsPayload) { + socket.write(`${header}content-length: 0\r +\r +`, "latin1"); } else { - client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout]; + socket.write(`${header}\r +`, "latin1"); + } + } else if (contentLength === null) { + socket.write("\r\n0\r\n\r\n", "latin1"); + } + if (contentLength !== null && bytesWritten !== contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError(); + } else { + process.emitWarning(new RequestContentLengthMismatchError()); + } + } + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh(); + } + } + client[kResume](); + } + destroy(err) { + const { socket, client, abort } = this; + socket[kWriting] = false; + if (err) { + assert3(client[kRunning] <= 1, "pipeline should only contain this request"); + abort(err); + } + } + }; + module2.exports = connectH1; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/client-h2.js +var require_client_h2 = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/client-h2.js"(exports, module2) { + "use strict"; + var assert3 = require("node:assert"); + var { pipeline } = require("node:stream"); + var util = require_util(); + var { + RequestContentLengthMismatchError, + RequestAbortedError, + SocketError, + InformationalError + } = require_errors(); + var { + kUrl, + kReset, + kClient, + kRunning, + kPending, + kQueue, + kPendingIdx, + kRunningIdx, + kError, + kSocket, + kStrictContentLength, + kOnError, + kMaxConcurrentStreams, + kHTTP2Session, + kResume + } = require_symbols(); + var kOpenStreams = Symbol("open streams"); + var h2ExperimentalWarned = false; + var http2; + try { + http2 = require("node:http2"); + } catch { + http2 = { constants: {} }; + } + var { + constants: { + HTTP2_HEADER_AUTHORITY, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_HEADER_SCHEME, + HTTP2_HEADER_CONTENT_LENGTH, + HTTP2_HEADER_EXPECT, + HTTP2_HEADER_STATUS + } + } = http2; + function parseH2Headers(headers) { + const result = []; + for (const [name, value] of Object.entries(headers)) { + if (Array.isArray(value)) { + for (const subvalue of value) { + result.push(Buffer.from(name), Buffer.from(subvalue)); } } else { - socket[kReset] = true; - } - const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false; - if (request.aborted) { - return -1; + result.push(Buffer.from(name), Buffer.from(value)); } - if (request.method === "HEAD") { - return 1; + } + return result; + } + async function connectH2(client, socket) { + client[kSocket] = socket; + if (!h2ExperimentalWarned) { + h2ExperimentalWarned = true; + process.emitWarning("H2 support is experimental, expect them to change at any time.", { + code: "UNDICI-H2" + }); + } + const session = http2.connect(client[kUrl], { + createConnection: () => socket, + peerMaxConcurrentStreams: client[kMaxConcurrentStreams] + }); + session[kOpenStreams] = 0; + session[kClient] = client; + session[kSocket] = socket; + util.addListener(session, "error", onHttp2SessionError); + util.addListener(session, "frameError", onHttp2FrameError); + util.addListener(session, "end", onHttp2SessionEnd); + util.addListener(session, "goaway", onHTTP2GoAway); + util.addListener(session, "close", function() { + const { [kClient]: client2 } = this; + const { [kSocket]: socket2 } = client2; + const err = this[kSocket][kError] || this[kError] || new SocketError("closed", util.getSocketInfo(socket2)); + client2[kHTTP2Session] = null; + if (client2.destroyed) { + assert3(client2[kPending] === 0); + const requests = client2[kQueue].splice(client2[kRunningIdx]); + for (let i = 0; i < requests.length; i++) { + const request = requests[i]; + util.errorRequest(client2, request, err); + } } - if (statusCode < 200) { - return 1; + }); + session.unref(); + client[kHTTP2Session] = session; + socket[kHTTP2Session] = session; + util.addListener(socket, "error", function(err) { + assert3(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); + this[kError] = err; + this[kClient][kOnError](err); + }); + util.addListener(socket, "end", function() { + util.destroy(this, new SocketError("other side closed", util.getSocketInfo(this))); + }); + util.addListener(socket, "close", function() { + const err = this[kError] || new SocketError("closed", util.getSocketInfo(this)); + client[kSocket] = null; + if (this[kHTTP2Session] != null) { + this[kHTTP2Session].destroy(err); } - if (socket[kBlocking]) { - socket[kBlocking] = false; - resume(client); + client[kPendingIdx] = client[kRunningIdx]; + assert3(client[kRunning] === 0); + client.emit("disconnect", client[kUrl], [client], err); + client[kResume](); + }); + let closed = false; + socket.on("close", () => { + closed = true; + }); + return { + version: "h2", + defaultPipelining: Infinity, + write(...args) { + writeH2(client, ...args); + }, + resume() { + }, + destroy(err, callback) { + if (closed) { + queueMicrotask(callback); + } else { + socket.destroy(err).on("close", callback); + } + }, + get destroyed() { + return socket.destroyed; + }, + busy() { + return false; } - return pause ? constants.ERROR.PAUSED : 0; + }; + } + function onHttp2SessionError(err) { + assert3(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); + this[kSocket][kError] = err; + this[kClient][kOnError](err); + } + function onHttp2FrameError(type, code, id) { + if (id === 0) { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`); + this[kSocket][kError] = err; + this[kClient][kOnError](err); } - onBody(buf) { - const { client, socket, statusCode, maxResponseSize } = this; - if (socket.destroyed) { - return -1; - } - const request = client[kQueue][client[kRunningIdx]]; - assert3(request); - assert3.strictEqual(this.timeoutType, TIMEOUT_BODY); - if (this.timeout) { - if (this.timeout.refresh) { - this.timeout.refresh(); + } + function onHttp2SessionEnd() { + const err = new SocketError("other side closed", util.getSocketInfo(this[kSocket])); + this.destroy(err); + util.destroy(this[kSocket], err); + } + function onHTTP2GoAway(code) { + const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`); + this[kSocket][kError] = err; + this[kClient][kOnError](err); + this.unref(); + this.destroy(); + util.destroy(this[kSocket], err); + } + function shouldSendContentLength(method) { + return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; + } + function writeH2(client, request) { + const session = client[kHTTP2Session]; + const { body, method, path: path10, host, upgrade, expectContinue, signal, headers: reqHeaders } = request; + if (upgrade) { + util.errorRequest(client, request, new Error("Upgrade not supported for H2")); + return false; + } + if (request.aborted) { + return false; + } + const headers = {}; + for (let n = 0; n < reqHeaders.length; n += 2) { + const key = reqHeaders[n + 0]; + const val = reqHeaders[n + 1]; + if (Array.isArray(val)) { + for (let i = 0; i < val.length; i++) { + if (headers[key]) { + headers[key] += `,${val[i]}`; + } else { + headers[key] = val[i]; + } } + } else { + headers[key] = val; } - assert3(statusCode >= 200); - if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { - util.destroy(socket, new ResponseExceededMaxSizeError()); - return -1; + } + let stream; + const { hostname, port } = client[kUrl]; + headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ""}`; + headers[HTTP2_HEADER_METHOD] = method; + const abort = (err) => { + if (request.aborted || request.completed) { + return; } - this.bytesRead += buf.length; - if (request.onData(buf) === false) { - return constants.ERROR.PAUSED; + err = err || new RequestAbortedError(); + util.errorRequest(client, request, err); + if (stream != null) { + util.destroy(stream, err); } + util.destroy(body, err); + }; + try { + request.onConnect(abort); + } catch (err) { + util.errorRequest(client, request, err); } - onMessageComplete() { - const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this; - if (socket.destroyed && (!statusCode || shouldKeepAlive)) { - return -1; + if (method === "CONNECT") { + session.ref(); + stream = session.request(headers, { endStream: false, signal }); + if (stream.id && !stream.pending) { + request.onUpgrade(null, null, stream); + ++session[kOpenStreams]; + } else { + stream.once("ready", () => { + request.onUpgrade(null, null, stream); + ++session[kOpenStreams]; + }); } - if (upgrade) { + stream.once("close", () => { + session[kOpenStreams] -= 1; + if (session[kOpenStreams] === 0) + session.unref(); + }); + return true; + } + headers[HTTP2_HEADER_PATH] = path10; + headers[HTTP2_HEADER_SCHEME] = "https"; + const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; + if (body && typeof body.read === "function") { + body.read(0); + } + let contentLength = util.bodyLength(body); + if (contentLength == null) { + contentLength = request.contentLength; + } + if (contentLength === 0 || !expectsPayload) { + contentLength = null; + } + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + util.errorRequest(client, request, new RequestContentLengthMismatchError()); + return false; + } + process.emitWarning(new RequestContentLengthMismatchError()); + } + if (contentLength != null) { + assert3(body, "no body must not have content length"); + headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}`; + } + session.ref(); + const shouldEndStream = method === "GET" || method === "HEAD" || body === null; + if (expectContinue) { + headers[HTTP2_HEADER_EXPECT] = "100-continue"; + stream = session.request(headers, { endStream: shouldEndStream, signal }); + stream.once("continue", writeBodyH2); + } else { + stream = session.request(headers, { + endStream: shouldEndStream, + signal + }); + writeBodyH2(); + } + ++session[kOpenStreams]; + stream.once("response", (headers2) => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers2; + request.onResponseStarted(); + if (request.aborted) { + const err = new RequestAbortedError(); + util.errorRequest(client, request, err); + util.destroy(stream, err); return; } - const request = client[kQueue][client[kRunningIdx]]; - assert3(request); - assert3(statusCode >= 100); - this.statusCode = null; - this.statusText = ""; - this.bytesRead = 0; - this.contentLength = ""; - this.keepAlive = ""; - this.connection = ""; - assert3(this.headers.length % 2 === 0); - this.headers = []; - this.headersSize = 0; - if (statusCode < 200) { + if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), "") === false) { + stream.pause(); + } + stream.on("data", (chunk) => { + if (request.onData(chunk) === false) { + stream.pause(); + } + }); + }); + stream.once("end", () => { + if (stream.state?.state == null || stream.state.state < 6) { + request.onComplete([]); return; } - if (request.method !== "HEAD" && contentLength && bytesRead !== parseInt(contentLength, 10)) { - util.destroy(socket, new ResponseContentLengthMismatchError()); - return -1; + if (session[kOpenStreams] === 0) { + session.unref(); } - request.onComplete(headers); - client[kQueue][client[kRunningIdx]++] = null; - if (socket[kWriting]) { - assert3.strictEqual(client[kRunning], 0); - util.destroy(socket, new InformationalError("reset")); - return constants.ERROR.PAUSED; - } else if (!shouldKeepAlive) { - util.destroy(socket, new InformationalError("reset")); - return constants.ERROR.PAUSED; - } else if (socket[kReset] && client[kRunning] === 0) { - util.destroy(socket, new InformationalError("reset")); - return constants.ERROR.PAUSED; - } else if (client[kPipelining] === 1) { - setImmediate(resume, client); + abort(new InformationalError("HTTP/2: stream half-closed (remote)")); + }); + stream.once("close", () => { + session[kOpenStreams] -= 1; + if (session[kOpenStreams] === 0) { + session.unref(); + } + }); + stream.once("error", function(err) { + abort(err); + }); + stream.once("frameError", (type, code) => { + abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)); + }); + return true; + function writeBodyH2() { + if (!body || contentLength === 0) { + writeBuffer({ + abort, + client, + request, + contentLength, + expectsPayload, + h2stream: stream, + body: null, + socket: client[kSocket] + }); + } else if (util.isBuffer(body)) { + writeBuffer({ + abort, + client, + request, + contentLength, + body, + expectsPayload, + h2stream: stream, + socket: client[kSocket] + }); + } else if (util.isBlobLike(body)) { + if (typeof body.stream === "function") { + writeIterable({ + abort, + client, + request, + contentLength, + expectsPayload, + h2stream: stream, + body: body.stream(), + socket: client[kSocket] + }); + } else { + writeBlob({ + abort, + body, + client, + request, + contentLength, + expectsPayload, + h2stream: stream, + socket: client[kSocket] + }); + } + } else if (util.isStream(body)) { + writeStream({ + body, + client, + request, + contentLength, + expectsPayload, + socket: client[kSocket], + h2stream: stream, + header: "" + }); + } else if (util.isIterable(body)) { + writeIterable({ + body, + client, + request, + contentLength, + expectsPayload, + header: "", + h2stream: stream, + socket: client[kSocket] + }); } else { - resume(client); + assert3(false); } } - }; - function onParserTimeout(parser) { - const { socket, timeoutType, client } = parser; - if (timeoutType === TIMEOUT_HEADERS) { - if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { - assert3(!parser.paused, "cannot be paused while waiting for headers"); - util.destroy(socket, new HeadersTimeoutError()); + } + function writeBuffer({ abort, h2stream, body, client, request, socket, contentLength, expectsPayload }) { + try { + if (body != null && util.isBuffer(body)) { + assert3(contentLength === body.byteLength, "buffer body must have content length"); + h2stream.cork(); + h2stream.write(body); + h2stream.uncork(); + h2stream.end(); + request.onBodySent(body); } - } else if (timeoutType === TIMEOUT_BODY) { - if (!parser.paused) { - util.destroy(socket, new BodyTimeoutError()); + if (!expectsPayload) { + socket[kReset] = true; } - } else if (timeoutType === TIMEOUT_IDLE) { - assert3(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]); - util.destroy(socket, new InformationalError("socket idle timeout")); - } - } - function onSocketReadable() { - const { [kParser]: parser } = this; - if (parser) { - parser.readMore(); + request.onRequestSent(); + client[kResume](); + } catch (error) { + abort(error); } } - function onSocketError(err) { - const { [kClient]: client, [kParser]: parser } = this; - assert3(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); - if (client[kHTTPConnVersion] !== "h2") { - if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { - parser.onMessageComplete(); - return; + function writeStream({ abort, socket, expectsPayload, h2stream, body, client, request, contentLength }) { + assert3(contentLength !== 0 || client[kRunning] === 0, "stream body cannot be pipelined"); + const pipe = pipeline( + body, + h2stream, + (err) => { + if (err) { + util.destroy(pipe, err); + abort(err); + } else { + util.removeAllListeners(pipe); + request.onRequestSent(); + if (!expectsPayload) { + socket[kReset] = true; + } + client[kResume](); + } } + ); + util.addListener(pipe, "data", onPipeData); + function onPipeData(chunk) { + request.onBodySent(chunk); } - this[kError] = err; - onError(this[kClient], err); } - function onError(client, err) { - if (client[kRunning] === 0 && err.code !== "UND_ERR_INFO" && err.code !== "UND_ERR_SOCKET") { - assert3(client[kPendingIdx] === client[kRunningIdx]); - const requests = client[kQueue].splice(client[kRunningIdx]); - for (let i = 0; i < requests.length; i++) { - const request = requests[i]; - errorRequest(client, request, err); + async function writeBlob({ abort, h2stream, body, client, request, socket, contentLength, expectsPayload }) { + assert3(contentLength === body.size, "blob body must have content length"); + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError(); } - assert3(client[kSize] === 0); - } - } - function onSocketEnd() { - const { [kParser]: parser, [kClient]: client } = this; - if (client[kHTTPConnVersion] !== "h2") { - if (parser.statusCode && !parser.shouldKeepAlive) { - parser.onMessageComplete(); - return; + const buffer = Buffer.from(await body.arrayBuffer()); + h2stream.cork(); + h2stream.write(buffer); + h2stream.uncork(); + h2stream.end(); + request.onBodySent(buffer); + request.onRequestSent(); + if (!expectsPayload) { + socket[kReset] = true; } + client[kResume](); + } catch (err) { + abort(err); } - util.destroy(this, new SocketError("other side closed", util.getSocketInfo(this))); } - function onSocketClose() { - const { [kClient]: client, [kParser]: parser } = this; - if (client[kHTTPConnVersion] === "h1" && parser) { - if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { - parser.onMessageComplete(); + async function writeIterable({ abort, h2stream, body, client, request, socket, contentLength, expectsPayload }) { + assert3(contentLength !== 0 || client[kRunning] === 0, "iterator body cannot be pipelined"); + let callback = null; + function onDrain() { + if (callback) { + const cb = callback; + callback = null; + cb(); } - this[kParser].destroy(); - this[kParser] = null; } - const err = this[kError] || new SocketError("closed", util.getSocketInfo(this)); - client[kSocket] = null; - if (client.destroyed) { - assert3(client[kPending] === 0); - const requests = client[kQueue].splice(client[kRunningIdx]); - for (let i = 0; i < requests.length; i++) { - const request = requests[i]; - errorRequest(client, request, err); + const waitForDrain = () => new Promise((resolve, reject) => { + assert3(callback === null); + if (socket[kError]) { + reject(socket[kError]); + } else { + callback = resolve; } - } else if (client[kRunning] > 0 && err.code !== "UND_ERR_INFO") { - const request = client[kQueue][client[kRunningIdx]]; - client[kQueue][client[kRunningIdx]++] = null; - errorRequest(client, request, err); + }); + h2stream.on("close", onDrain).on("drain", onDrain); + try { + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError]; + } + const res = h2stream.write(chunk); + request.onBodySent(chunk); + if (!res) { + await waitForDrain(); + } + } + h2stream.end(); + request.onRequestSent(); + if (!expectsPayload) { + socket[kReset] = true; + } + client[kResume](); + } catch (err) { + abort(err); + } finally { + h2stream.off("close", onDrain).off("drain", onDrain); } - client[kPendingIdx] = client[kRunningIdx]; - assert3(client[kRunning] === 0); - client.emit("disconnect", client[kUrl], [client], err); - resume(client); } - async function connect(client) { - assert3(!client[kConnecting]); - assert3(!client[kSocket]); - let { host, hostname, protocol, port } = client[kUrl]; - if (hostname[0] === "[") { - const idx = hostname.indexOf("]"); - assert3(idx !== -1); - const ip = hostname.substring(1, idx); - assert3(net.isIP(ip)); - hostname = ip; + module2.exports = connectH2; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/handler/redirect-handler.js +var require_redirect_handler = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/handler/redirect-handler.js"(exports, module2) { + "use strict"; + var util = require_util(); + var { kBodyUsed } = require_symbols(); + var assert3 = require("node:assert"); + var { InvalidArgumentError } = require_errors(); + var EE = require("node:events"); + var redirectableStatusCodes = [300, 301, 302, 303, 307, 308]; + var kBody = Symbol("body"); + var BodyAsyncIterable = class { + constructor(body) { + this[kBody] = body; + this[kBodyUsed] = false; } - client[kConnecting] = true; - if (channels.beforeConnect.hasSubscribers) { - channels.beforeConnect.publish({ - connectParams: { - host, - hostname, - protocol, - port, - version: client[kHTTPConnVersion], - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector] - }); + async *[Symbol.asyncIterator]() { + assert3(!this[kBodyUsed], "disturbed"); + this[kBodyUsed] = true; + yield* this[kBody]; } - try { - const socket = await new Promise((resolve, reject) => { - client[kConnector]({ - host, - hostname, - protocol, - port, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, (err, socket2) => { - if (err) { - reject(err); - } else { - resolve(socket2); - } - }); - }); - if (client.destroyed) { - util.destroy(socket.on("error", () => { - }), new ClientDestroyedError()); - return; + }; + var RedirectHandler = class { + constructor(dispatch, maxRedirections, opts, handler) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError("maxRedirections must be a positive number"); } - client[kConnecting] = false; - assert3(socket); - const isH2 = socket.alpnProtocol === "h2"; - if (isH2) { - if (!h2ExperimentalWarned) { - h2ExperimentalWarned = true; - process.emitWarning("H2 support is experimental, expect them to change at any time.", { - code: "UNDICI-H2" + util.validateHandler(handler, opts.method, opts.upgrade); + this.dispatch = dispatch; + this.location = null; + this.abort = null; + this.opts = { ...opts, maxRedirections: 0 }; + this.maxRedirections = maxRedirections; + this.handler = handler; + this.history = []; + this.redirectionLimitReached = false; + if (util.isStream(this.opts.body)) { + if (util.bodyLength(this.opts.body) === 0) { + this.opts.body.on("data", function() { + assert3(false); }); } - const session = http2.connect(client[kUrl], { - createConnection: () => socket, - peerMaxConcurrentStreams: client[kHTTP2SessionState].maxConcurrentStreams - }); - client[kHTTPConnVersion] = "h2"; - session[kClient] = client; - session[kSocket] = socket; - session.on("error", onHttp2SessionError); - session.on("frameError", onHttp2FrameError); - session.on("end", onHttp2SessionEnd); - session.on("goaway", onHTTP2GoAway); - session.on("close", onSocketClose); - session.unref(); - client[kHTTP2Session] = session; - socket[kHTTP2Session] = session; - } else { - if (!llhttpInstance) { - llhttpInstance = await llhttpPromise; - llhttpPromise = null; + if (typeof this.opts.body.readableDidRead !== "boolean") { + this.opts.body[kBodyUsed] = false; + EE.prototype.on.call(this.opts.body, "data", function() { + this[kBodyUsed] = true; + }); } - socket[kNoRef] = false; - socket[kWriting] = false; - socket[kReset] = false; - socket[kBlocking] = false; - socket[kParser] = new Parser(client, socket, llhttpInstance); - } - socket[kCounter] = 0; - socket[kMaxRequests] = client[kMaxRequests]; - socket[kClient] = client; - socket[kError] = null; - socket.on("error", onSocketError).on("readable", onSocketReadable).on("end", onSocketEnd).on("close", onSocketClose); - client[kSocket] = socket; - if (channels.connected.hasSubscribers) { - channels.connected.publish({ - connectParams: { - host, - hostname, - protocol, - port, - version: client[kHTTPConnVersion], - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector], - socket - }); + } else if (this.opts.body && typeof this.opts.body.pipeTo === "function") { + this.opts.body = new BodyAsyncIterable(this.opts.body); + } else if (this.opts.body && typeof this.opts.body !== "string" && !ArrayBuffer.isView(this.opts.body) && util.isIterable(this.opts.body)) { + this.opts.body = new BodyAsyncIterable(this.opts.body); } - client.emit("connect", client[kUrl], [client]); - } catch (err) { - if (client.destroyed) { + } + onConnect(abort) { + this.abort = abort; + this.handler.onConnect(abort, { history: this.history }); + } + onUpgrade(statusCode, headers, socket) { + this.handler.onUpgrade(statusCode, headers, socket); + } + onError(error) { + this.handler.onError(error); + } + onHeaders(statusCode, headers, resume, statusText) { + this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) ? null : parseLocation(statusCode, headers); + if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) { + if (this.request) { + this.request.abort(new Error("max redirects")); + } + this.redirectionLimitReached = true; + this.abort(new Error("max redirects")); return; } - client[kConnecting] = false; - if (channels.connectError.hasSubscribers) { - channels.connectError.publish({ - connectParams: { - host, - hostname, - protocol, - port, - version: client[kHTTPConnVersion], - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector], - error: err - }); + if (this.opts.origin) { + this.history.push(new URL(this.opts.path, this.opts.origin)); + } + if (!this.location) { + return this.handler.onHeaders(statusCode, headers, resume, statusText); } - if (err.code === "ERR_TLS_CERT_ALTNAME_INVALID") { - assert3(client[kRunning] === 0); - while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { - const request = client[kQueue][client[kPendingIdx]++]; - errorRequest(client, request, err); - } + const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); + const path10 = search ? `${pathname}${search}` : pathname; + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); + this.opts.path = path10; + this.opts.origin = origin; + this.opts.maxRedirections = 0; + this.opts.query = null; + if (statusCode === 303 && this.opts.method !== "HEAD") { + this.opts.method = "GET"; + this.opts.body = null; + } + } + onData(chunk) { + if (this.location) { } else { - onError(client, err); + return this.handler.onData(chunk); + } + } + onComplete(trailers) { + if (this.location) { + this.location = null; + this.abort = null; + this.dispatch(this.opts, this); + } else { + this.handler.onComplete(trailers); + } + } + onBodySent(chunk) { + if (this.handler.onBodySent) { + this.handler.onBodySent(chunk); + } + } + }; + function parseLocation(statusCode, headers) { + if (redirectableStatusCodes.indexOf(statusCode) === -1) { + return null; + } + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].length === 8 && util.headerNameToString(headers[i]) === "location") { + return headers[i + 1]; } - client.emit("connectionError", client[kUrl], [client], err); } - resume(client); - } - function emitDrain(client) { - client[kNeedDrain] = 0; - client.emit("drain", client[kUrl], [client]); } - function resume(client, sync) { - if (client[kResuming] === 2) { - return; + function shouldRemoveHeader(header, removeContent, unknownOrigin) { + if (header.length === 4) { + return util.headerNameToString(header) === "host"; } - client[kResuming] = 2; - _resume(client, sync); - client[kResuming] = 0; - if (client[kRunningIdx] > 256) { - client[kQueue].splice(0, client[kRunningIdx]); - client[kPendingIdx] -= client[kRunningIdx]; - client[kRunningIdx] = 0; + if (removeContent && util.headerNameToString(header).startsWith("content-")) { + return true; + } + if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { + const name = util.headerNameToString(header); + return name === "authorization" || name === "cookie" || name === "proxy-authorization"; } + return false; } - function _resume(client, sync) { - while (true) { - if (client.destroyed) { - assert3(client[kPending] === 0); - return; - } - if (client[kClosedResolve] && !client[kSize]) { - client[kClosedResolve](); - client[kClosedResolve] = null; - return; - } - const socket = client[kSocket]; - if (socket && !socket.destroyed && socket.alpnProtocol !== "h2") { - if (client[kSize] === 0) { - if (!socket[kNoRef] && socket.unref) { - socket.unref(); - socket[kNoRef] = true; - } - } else if (socket[kNoRef] && socket.ref) { - socket.ref(); - socket[kNoRef] = false; + function cleanRequestHeaders(headers, removeContent, unknownOrigin) { + const ret = []; + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { + ret.push(headers[i], headers[i + 1]); } - if (client[kSize] === 0) { - if (socket[kParser].timeoutType !== TIMEOUT_IDLE) { - socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_IDLE); - } - } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { - if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { - const request2 = client[kQueue][client[kRunningIdx]]; - const headersTimeout = request2.headersTimeout != null ? request2.headersTimeout : client[kHeadersTimeout]; - socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS); - } + } + } else if (headers && typeof headers === "object") { + for (const key of Object.keys(headers)) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, headers[key]); } } - if (client[kBusy]) { - client[kNeedDrain] = 2; - } else if (client[kNeedDrain] === 2) { - if (sync) { - client[kNeedDrain] = 1; - process.nextTick(emitDrain, client); - } else { - emitDrain(client); + } else { + assert3(headers == null, "headers must be an object or an array"); + } + return ret; + } + module2.exports = RedirectHandler; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/interceptor/redirect-interceptor.js +var require_redirect_interceptor = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/interceptor/redirect-interceptor.js"(exports, module2) { + "use strict"; + var RedirectHandler = require_redirect_handler(); + function createRedirectInterceptor({ maxRedirections: defaultMaxRedirections }) { + return (dispatch) => { + return function Intercept(opts, handler) { + const { maxRedirections = defaultMaxRedirections } = opts; + if (!maxRedirections) { + return dispatch(opts, handler); } - continue; + const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler); + opts = { ...opts, maxRedirections: 0 }; + return dispatch(opts, redirectHandler); + }; + }; + } + module2.exports = createRedirectInterceptor; + } +}); + +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/client.js +var require_client = __commonJS({ + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/client.js"(exports, module2) { + "use strict"; + var assert3 = require("node:assert"); + var net = require("node:net"); + var http = require("node:http"); + var util = require_util(); + var { channels } = require_diagnostics(); + var Request = require_request(); + var DispatcherBase = require_dispatcher_base(); + var { + InvalidArgumentError, + InformationalError, + ClientDestroyedError + } = require_errors(); + var buildConnector = require_connect(); + var { + kUrl, + kServerName, + kClient, + kBusy, + kConnect, + kResuming, + kRunning, + kPending, + kSize, + kQueue, + kConnected, + kConnecting, + kNeedDrain, + kKeepAliveDefaultTimeout, + kHostHeader, + kPendingIdx, + kRunningIdx, + kError, + kPipelining, + kKeepAliveTimeoutValue, + kMaxHeadersSize, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kHeadersTimeout, + kBodyTimeout, + kStrictContentLength, + kConnector, + kMaxRedirections, + kMaxRequests, + kCounter, + kClose, + kDestroy, + kDispatch, + kInterceptors, + kLocalAddress, + kMaxResponseSize, + kOnError, + kHTTPContext, + kMaxConcurrentStreams, + kResume + } = require_symbols(); + var connectH1 = require_client_h1(); + var connectH2 = require_client_h2(); + var deprecatedInterceptorWarned = false; + var kClosedResolve = Symbol("kClosedResolve"); + function getPipelining(client) { + return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1; + } + var Client = class extends DispatcherBase { + /** + * + * @param {string|URL} url + * @param {import('../../types/client.js').Client.Options} options + */ + constructor(url, { + interceptors, + maxHeaderSize, + headersTimeout, + socketTimeout, + requestTimeout, + connectTimeout, + bodyTimeout, + idleTimeout, + keepAlive, + keepAliveTimeout, + maxKeepAliveTimeout, + keepAliveMaxTimeout, + keepAliveTimeoutThreshold, + socketPath, + pipelining, + tls, + strictContentLength, + maxCachedSessions, + maxRedirections, + connect: connect2, + maxRequestsPerClient, + localAddress, + maxResponseSize, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + // h2 + maxConcurrentStreams, + allowH2 + } = {}) { + super(); + if (keepAlive !== void 0) { + throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); } - if (client[kPending] === 0) { - return; + if (socketTimeout !== void 0) { + throw new InvalidArgumentError("unsupported socketTimeout, use headersTimeout & bodyTimeout instead"); } - if (client[kRunning] >= (client[kPipelining] || 1)) { - return; + if (requestTimeout !== void 0) { + throw new InvalidArgumentError("unsupported requestTimeout, use headersTimeout & bodyTimeout instead"); } - const request = client[kQueue][client[kPendingIdx]]; - if (client[kUrl].protocol === "https:" && client[kServerName] !== request.servername) { - if (client[kRunning] > 0) { - return; - } - client[kServerName] = request.servername; - if (socket && socket.servername !== request.servername) { - util.destroy(socket, new InformationalError("servername changed")); - return; - } + if (idleTimeout !== void 0) { + throw new InvalidArgumentError("unsupported idleTimeout, use keepAliveTimeout instead"); + } + if (maxKeepAliveTimeout !== void 0) { + throw new InvalidArgumentError("unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead"); + } + if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) { + throw new InvalidArgumentError("invalid maxHeaderSize"); + } + if (socketPath != null && typeof socketPath !== "string") { + throw new InvalidArgumentError("invalid socketPath"); + } + if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) { + throw new InvalidArgumentError("invalid connectTimeout"); + } + if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) { + throw new InvalidArgumentError("invalid keepAliveTimeout"); + } + if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) { + throw new InvalidArgumentError("invalid keepAliveMaxTimeout"); + } + if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) { + throw new InvalidArgumentError("invalid keepAliveTimeoutThreshold"); } - if (client[kConnecting]) { - return; + if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError("headersTimeout must be a positive integer or zero"); } - if (!socket && !client[kHTTP2Session]) { - connect(client); - return; + if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError("bodyTimeout must be a positive integer or zero"); } - if (socket.destroyed || socket[kWriting] || socket[kReset] || socket[kBlocking]) { - return; + if (connect2 != null && typeof connect2 !== "function" && typeof connect2 !== "object") { + throw new InvalidArgumentError("connect must be a function or an object"); } - if (client[kRunning] > 0 && !request.idempotent) { - return; + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError("maxRedirections must be a positive number"); } - if (client[kRunning] > 0 && (request.upgrade || request.method === "CONNECT")) { - return; + if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { + throw new InvalidArgumentError("maxRequestsPerClient must be a positive number"); } - if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && (util.isStream(request.body) || util.isAsyncIterable(request.body))) { - return; + if (localAddress != null && (typeof localAddress !== "string" || net.isIP(localAddress) === 0)) { + throw new InvalidArgumentError("localAddress must be valid string IP address"); } - if (!request.aborted && write(client, request)) { - client[kPendingIdx]++; - } else { - client[kQueue].splice(client[kPendingIdx], 1); + if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) { + throw new InvalidArgumentError("maxResponseSize must be a positive number"); } - } - } - function shouldSendContentLength(method) { - return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; - } - function write(client, request) { - if (client[kHTTPConnVersion] === "h2") { - writeH2(client, client[kHTTP2Session], request); - return; - } - const { body, method, path: path10, host, upgrade, headers, blocking, reset } = request; - const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; - if (body && typeof body.read === "function") { - body.read(0); - } - const bodyLength = util.bodyLength(body); - let contentLength = bodyLength; - if (contentLength === null) { - contentLength = request.contentLength; - } - if (contentLength === 0 && !expectsPayload) { - contentLength = null; - } - if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { - if (client[kStrictContentLength]) { - errorRequest(client, request, new RequestContentLengthMismatchError()); - return false; + if (autoSelectFamilyAttemptTimeout != null && (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1)) { + throw new InvalidArgumentError("autoSelectFamilyAttemptTimeout must be a positive number"); } - process.emitWarning(new RequestContentLengthMismatchError()); - } - const socket = client[kSocket]; - try { - request.onConnect((err) => { - if (request.aborted || request.completed) { - return; - } - errorRequest(client, request, err || new RequestAbortedError()); - util.destroy(socket, new InformationalError("aborted")); - }); - } catch (err) { - errorRequest(client, request, err); - } - if (request.aborted) { - return false; - } - if (method === "HEAD") { - socket[kReset] = true; - } - if (upgrade || method === "CONNECT") { - socket[kReset] = true; - } - if (reset != null) { - socket[kReset] = reset; - } - if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { - socket[kReset] = true; - } - if (blocking) { - socket[kBlocking] = true; - } - let header = `${method} ${path10} HTTP/1.1\r -`; - if (typeof host === "string") { - header += `host: ${host}\r -`; - } else { - header += client[kHostHeader]; - } - if (upgrade) { - header += `connection: upgrade\r -upgrade: ${upgrade}\r -`; - } else if (client[kPipelining] && !socket[kReset]) { - header += "connection: keep-alive\r\n"; - } else { - header += "connection: close\r\n"; - } - if (headers) { - header += headers; - } - if (channels.sendHeaders.hasSubscribers) { - channels.sendHeaders.publish({ request, headers: header, socket }); - } - if (!body || bodyLength === 0) { - if (contentLength === 0) { - socket.write(`${header}content-length: 0\r -\r -`, "latin1"); - } else { - assert3(contentLength === null, "no body must not have content length"); - socket.write(`${header}\r -`, "latin1"); + if (allowH2 != null && typeof allowH2 !== "boolean") { + throw new InvalidArgumentError("allowH2 must be a valid boolean value"); } - request.onRequestSent(); - } else if (util.isBuffer(body)) { - assert3(contentLength === body.byteLength, "buffer body must have content length"); - socket.cork(); - socket.write(`${header}content-length: ${contentLength}\r -\r -`, "latin1"); - socket.write(body); - socket.uncork(); - request.onBodySent(body); - request.onRequestSent(); - if (!expectsPayload) { - socket[kReset] = true; + if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== "number" || maxConcurrentStreams < 1)) { + throw new InvalidArgumentError("maxConcurrentStreams must be a positive integer, greater than 0"); } - } else if (util.isBlobLike(body)) { - if (typeof body.stream === "function") { - writeIterable({ body: body.stream(), client, request, socket, contentLength, header, expectsPayload }); - } else { - writeBlob({ body, client, request, socket, contentLength, header, expectsPayload }); + if (typeof connect2 !== "function") { + connect2 = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, + ...connect2 + }); } - } else if (util.isStream(body)) { - writeStream({ body, client, request, socket, contentLength, header, expectsPayload }); - } else if (util.isIterable(body)) { - writeIterable({ body, client, request, socket, contentLength, header, expectsPayload }); - } else { - assert3(false); - } - return true; - } - function writeH2(client, session, request) { - const { body, method, path: path10, host, upgrade, expectContinue, signal, headers: reqHeaders } = request; - let headers; - if (typeof reqHeaders === "string") - headers = Request[kHTTP2CopyHeaders](reqHeaders.trim()); - else - headers = reqHeaders; - if (upgrade) { - errorRequest(client, request, new Error("Upgrade not supported for H2")); - return false; - } - if (request.aborted) { - return false; - } - let stream; - const h2State = client[kHTTP2SessionState]; - headers[HTTP2_HEADER_AUTHORITY] = host || client[kHost]; - headers[HTTP2_HEADER_METHOD] = method; - try { - request.onConnect((err) => { - if (request.aborted || request.completed) { - return; - } - err = err || new RequestAbortedError(); - if (stream != null) { - util.destroy(stream, err); - h2State.openStreams -= 1; - if (h2State.openStreams === 0) { - session.unref(); - } + if (interceptors?.Client && Array.isArray(interceptors.Client)) { + this[kInterceptors] = interceptors.Client; + if (!deprecatedInterceptorWarned) { + deprecatedInterceptorWarned = true; + process.emitWarning("Client.Options#interceptor is deprecated. Use Dispatcher#compose instead.", { + code: "UNDICI-CLIENT-INTERCEPTOR-DEPRECATED" + }); } - errorRequest(client, request, err); - }); - } catch (err) { - errorRequest(client, request, err); - } - if (method === "CONNECT") { - session.ref(); - stream = session.request(headers, { endStream: false, signal }); - if (stream.id && !stream.pending) { - request.onUpgrade(null, null, stream); - ++h2State.openStreams; } else { - stream.once("ready", () => { - request.onUpgrade(null, null, stream); - ++h2State.openStreams; - }); + this[kInterceptors] = [createRedirectInterceptor({ maxRedirections })]; } - stream.once("close", () => { - h2State.openStreams -= 1; - if (h2State.openStreams === 0) - session.unref(); - }); - return true; + this[kUrl] = util.parseOrigin(url); + this[kConnector] = connect2; + this[kPipelining] = pipelining != null ? pipelining : 1; + this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize; + this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout; + this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 6e5 : keepAliveMaxTimeout; + this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 1e3 : keepAliveTimeoutThreshold; + this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout]; + this[kServerName] = null; + this[kLocalAddress] = localAddress != null ? localAddress : null; + this[kResuming] = 0; + this[kNeedDrain] = 0; + this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ""}\r +`; + this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 3e5; + this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 3e5; + this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength; + this[kMaxRedirections] = maxRedirections; + this[kMaxRequests] = maxRequestsPerClient; + this[kClosedResolve] = null; + this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1; + this[kMaxConcurrentStreams] = maxConcurrentStreams != null ? maxConcurrentStreams : 100; + this[kHTTPContext] = null; + this[kQueue] = []; + this[kRunningIdx] = 0; + this[kPendingIdx] = 0; + this[kResume] = (sync) => resume(this, sync); + this[kOnError] = (err) => onError(this, err); } - headers[HTTP2_HEADER_PATH] = path10; - headers[HTTP2_HEADER_SCHEME] = "https"; - const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; - if (body && typeof body.read === "function") { - body.read(0); + get pipelining() { + return this[kPipelining]; } - let contentLength = util.bodyLength(body); - if (contentLength == null) { - contentLength = request.contentLength; + set pipelining(value) { + this[kPipelining] = value; + this[kResume](true); } - if (contentLength === 0 || !expectsPayload) { - contentLength = null; + get [kPending]() { + return this[kQueue].length - this[kPendingIdx]; } - if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { - if (client[kStrictContentLength]) { - errorRequest(client, request, new RequestContentLengthMismatchError()); - return false; - } - process.emitWarning(new RequestContentLengthMismatchError()); + get [kRunning]() { + return this[kPendingIdx] - this[kRunningIdx]; } - if (contentLength != null) { - assert3(body, "no body must not have content length"); - headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}`; + get [kSize]() { + return this[kQueue].length - this[kRunningIdx]; } - session.ref(); - const shouldEndStream = method === "GET" || method === "HEAD" || body === null; - if (expectContinue) { - headers[HTTP2_HEADER_EXPECT] = "100-continue"; - stream = session.request(headers, { endStream: shouldEndStream, signal }); - stream.once("continue", writeBodyH2); - } else { - stream = session.request(headers, { - endStream: shouldEndStream, - signal - }); - writeBodyH2(); + get [kConnected]() { + return !!this[kHTTPContext] && !this[kConnecting] && !this[kHTTPContext].destroyed; } - ++h2State.openStreams; - stream.once("response", (headers2) => { - const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers2; - request.onResponseStarted(); - if (request.onHeaders(Number(statusCode), realHeaders, stream.resume.bind(stream), "") === false) { - stream.pause(); - } - }); - stream.once("end", () => { - request.onComplete([]); - }); - stream.on("data", (chunk) => { - if (request.onData(chunk) === false) { - stream.pause(); - } - }); - stream.once("close", () => { - h2State.openStreams -= 1; - if (h2State.openStreams === 0) { - session.unref(); - } - }); - stream.once("error", function(err) { - if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { - h2State.streams -= 1; - util.destroy(stream, err); + get [kBusy]() { + return Boolean( + this[kHTTPContext]?.busy(null) || this[kSize] >= (getPipelining(this) || 1) || this[kPending] > 0 + ); + } + /* istanbul ignore: only used for test */ + [kConnect](cb) { + connect(this); + this.once("connect", cb); + } + [kDispatch](opts, handler) { + const origin = opts.origin || this[kUrl].origin; + const request = new Request(origin, opts, handler); + this[kQueue].push(request); + if (this[kResuming]) { + } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { + this[kResuming] = 1; + queueMicrotask(() => resume(this)); + } else { + this[kResume](true); } - }); - stream.once("frameError", (type, code) => { - const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`); - errorRequest(client, request, err); - if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { - h2State.streams -= 1; - util.destroy(stream, err); + if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { + this[kNeedDrain] = 2; } - }); - return true; - function writeBodyH2() { - if (!body) { - request.onRequestSent(); - } else if (util.isBuffer(body)) { - assert3(contentLength === body.byteLength, "buffer body must have content length"); - stream.cork(); - stream.write(body); - stream.uncork(); - stream.end(); - request.onBodySent(body); - request.onRequestSent(); - } else if (util.isBlobLike(body)) { - if (typeof body.stream === "function") { - writeIterable({ - client, - request, - contentLength, - h2stream: stream, - expectsPayload, - body: body.stream(), - socket: client[kSocket], - header: "" - }); + return this[kNeedDrain] < 2; + } + async [kClose]() { + return new Promise((resolve) => { + if (this[kSize]) { + this[kClosedResolve] = resolve; } else { - writeBlob({ - body, - client, - request, - contentLength, - expectsPayload, - h2stream: stream, - header: "", - socket: client[kSocket] - }); + resolve(null); } - } else if (util.isStream(body)) { - writeStream({ - body, - client, - request, - contentLength, - expectsPayload, - socket: client[kSocket], - h2stream: stream, - header: "" - }); - } else if (util.isIterable(body)) { - writeIterable({ - body, - client, - request, - contentLength, - expectsPayload, - header: "", - h2stream: stream, - socket: client[kSocket] - }); - } else { - assert3(false); + }); + } + async [kDestroy](err) { + return new Promise((resolve) => { + const requests = this[kQueue].splice(this[kPendingIdx]); + for (let i = 0; i < requests.length; i++) { + const request = requests[i]; + util.errorRequest(this, request, err); + } + const callback = () => { + if (this[kClosedResolve]) { + this[kClosedResolve](); + this[kClosedResolve] = null; + } + resolve(null); + }; + if (this[kHTTPContext]) { + this[kHTTPContext].destroy(err, callback); + this[kHTTPContext] = null; + } else { + queueMicrotask(callback); + } + this[kResume](); + }); + } + }; + var createRedirectInterceptor = require_redirect_interceptor(); + function onError(client, err) { + if (client[kRunning] === 0 && err.code !== "UND_ERR_INFO" && err.code !== "UND_ERR_SOCKET") { + assert3(client[kPendingIdx] === client[kRunningIdx]); + const requests = client[kQueue].splice(client[kRunningIdx]); + for (let i = 0; i < requests.length; i++) { + const request = requests[i]; + util.errorRequest(client, request, err); } + assert3(client[kSize] === 0); } } - function writeStream({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { - assert3(contentLength !== 0 || client[kRunning] === 0, "stream body cannot be pipelined"); - if (client[kHTTPConnVersion] === "h2") { - let onPipeData = function(chunk) { - request.onBodySent(chunk); - }; - const pipe = pipeline( - body, - h2stream, - (err) => { + async function connect(client) { + assert3(!client[kConnecting]); + assert3(!client[kHTTPContext]); + let { host, hostname, protocol, port } = client[kUrl]; + if (hostname[0] === "[") { + const idx = hostname.indexOf("]"); + assert3(idx !== -1); + const ip = hostname.substring(1, idx); + assert3(net.isIP(ip)); + hostname = ip; + } + client[kConnecting] = true; + if (channels.beforeConnect.hasSubscribers) { + channels.beforeConnect.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector] + }); + } + try { + const socket = await new Promise((resolve, reject) => { + client[kConnector]({ + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, (err, socket2) => { if (err) { - util.destroy(body, err); - util.destroy(h2stream, err); + reject(err); } else { - request.onRequestSent(); + resolve(socket2); } - } - ); - pipe.on("data", onPipeData); - pipe.once("end", () => { - pipe.removeListener("data", onPipeData); - util.destroy(pipe); + }); }); - return; - } - let finished = false; - const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }); - const onData = function(chunk) { - if (finished) { + if (client.destroyed) { + util.destroy(socket.on("error", () => { + }), new ClientDestroyedError()); return; } + assert3(socket); try { - if (!writer.write(chunk) && this.pause) { - this.pause(); - } + client[kHTTPContext] = socket.alpnProtocol === "h2" ? await connectH2(client, socket) : await connectH1(client, socket); } catch (err) { - util.destroy(this, err); - } - }; - const onDrain = function() { - if (finished) { - return; - } - if (body.resume) { - body.resume(); - } - }; - const onClose = function() { - queueMicrotask(() => { - body.removeListener("error", onFinished); - }); - if (!finished) { - const err = new RequestAbortedError(); - queueMicrotask(() => onFinished(err)); - } - }; - const onFinished = function(err) { - if (finished) { - return; - } - finished = true; - assert3(socket.destroyed || socket[kWriting] && client[kRunning] <= 1); - socket.off("drain", onDrain).off("error", onFinished); - body.removeListener("data", onData).removeListener("end", onFinished).removeListener("close", onClose); - if (!err) { - try { - writer.end(); - } catch (er) { - err = er; - } - } - writer.destroy(err); - if (err && (err.code !== "UND_ERR_INFO" || err.message !== "reset")) { - util.destroy(body, err); - } else { - util.destroy(body); - } - }; - body.on("data", onData).on("end", onFinished).on("error", onFinished).on("close", onClose); - if (body.resume) { - body.resume(); - } - socket.on("drain", onDrain).on("error", onFinished); - } - async function writeBlob({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { - assert3(contentLength === body.size, "blob body must have content length"); - const isH2 = client[kHTTPConnVersion] === "h2"; - try { - if (contentLength != null && contentLength !== body.size) { - throw new RequestContentLengthMismatchError(); - } - const buffer = Buffer.from(await body.arrayBuffer()); - if (isH2) { - h2stream.cork(); - h2stream.write(buffer); - h2stream.uncork(); - } else { - socket.cork(); - socket.write(`${header}content-length: ${contentLength}\r -\r -`, "latin1"); - socket.write(buffer); - socket.uncork(); - } - request.onBodySent(buffer); - request.onRequestSent(); - if (!expectsPayload) { - socket[kReset] = true; + socket.destroy().on("error", () => { + }); + throw err; } - resume(client); - } catch (err) { - util.destroy(isH2 ? h2stream : socket, err); - } - } - async function writeIterable({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { - assert3(contentLength !== 0 || client[kRunning] === 0, "iterator body cannot be pipelined"); - let callback = null; - function onDrain() { - if (callback) { - const cb = callback; - callback = null; - cb(); + client[kConnecting] = false; + socket[kCounter] = 0; + socket[kMaxRequests] = client[kMaxRequests]; + socket[kClient] = client; + socket[kError] = null; + if (channels.connected.hasSubscribers) { + channels.connected.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + socket + }); } - } - const waitForDrain = () => new Promise((resolve, reject) => { - assert3(callback === null); - if (socket[kError]) { - reject(socket[kError]); - } else { - callback = resolve; + client.emit("connect", client[kUrl], [client]); + } catch (err) { + if (client.destroyed) { + return; } - }); - if (client[kHTTPConnVersion] === "h2") { - h2stream.on("close", onDrain).on("drain", onDrain); - try { - for await (const chunk of body) { - if (socket[kError]) { - throw socket[kError]; - } - const res = h2stream.write(chunk); - request.onBodySent(chunk); - if (!res) { - await waitForDrain(); - } - } - } catch (err) { - h2stream.destroy(err); - } finally { - request.onRequestSent(); - h2stream.end(); - h2stream.off("close", onDrain).off("drain", onDrain); + client[kConnecting] = false; + if (channels.connectError.hasSubscribers) { + channels.connectError.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + error: err + }); } - return; - } - socket.on("close", onDrain).on("drain", onDrain); - const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }); - try { - for await (const chunk of body) { - if (socket[kError]) { - throw socket[kError]; - } - if (!writer.write(chunk)) { - await waitForDrain(); + if (err.code === "ERR_TLS_CERT_ALTNAME_INVALID") { + assert3(client[kRunning] === 0); + while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { + const request = client[kQueue][client[kPendingIdx]++]; + util.errorRequest(client, request, err); } + } else { + onError(client, err); } - writer.end(); - } catch (err) { - writer.destroy(err); - } finally { - socket.off("close", onDrain).off("drain", onDrain); + client.emit("connectionError", client[kUrl], [client], err); } + client[kResume](); } - var AsyncWriter = class { - constructor({ socket, request, contentLength, client, expectsPayload, header }) { - this.socket = socket; - this.request = request; - this.contentLength = contentLength; - this.client = client; - this.bytesWritten = 0; - this.expectsPayload = expectsPayload; - this.header = header; - socket[kWriting] = true; + function emitDrain(client) { + client[kNeedDrain] = 0; + client.emit("drain", client[kUrl], [client]); + } + function resume(client, sync) { + if (client[kResuming] === 2) { + return; } - write(chunk) { - const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this; - if (socket[kError]) { - throw socket[kError]; - } - if (socket.destroyed) { - return false; + client[kResuming] = 2; + _resume(client, sync); + client[kResuming] = 0; + if (client[kRunningIdx] > 256) { + client[kQueue].splice(0, client[kRunningIdx]); + client[kPendingIdx] -= client[kRunningIdx]; + client[kRunningIdx] = 0; + } + } + function _resume(client, sync) { + while (true) { + if (client.destroyed) { + assert3(client[kPending] === 0); + return; } - const len = Buffer.byteLength(chunk); - if (!len) { - return true; + if (client[kClosedResolve] && !client[kSize]) { + client[kClosedResolve](); + client[kClosedResolve] = null; + return; } - if (contentLength !== null && bytesWritten + len > contentLength) { - if (client[kStrictContentLength]) { - throw new RequestContentLengthMismatchError(); - } - process.emitWarning(new RequestContentLengthMismatchError()); + if (client[kHTTPContext]) { + client[kHTTPContext].resume(); } - socket.cork(); - if (bytesWritten === 0) { - if (!expectsPayload) { - socket[kReset] = true; - } - if (contentLength === null) { - socket.write(`${header}transfer-encoding: chunked\r -`, "latin1"); + if (client[kBusy]) { + client[kNeedDrain] = 2; + } else if (client[kNeedDrain] === 2) { + if (sync) { + client[kNeedDrain] = 1; + queueMicrotask(() => emitDrain(client)); } else { - socket.write(`${header}content-length: ${contentLength}\r -\r -`, "latin1"); + emitDrain(client); } + continue; } - if (contentLength === null) { - socket.write(`\r -${len.toString(16)}\r -`, "latin1"); + if (client[kPending] === 0) { + return; } - this.bytesWritten += len; - const ret = socket.write(chunk); - socket.uncork(); - request.onBodySent(chunk); - if (!ret) { - if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { - if (socket[kParser].timeout.refresh) { - socket[kParser].timeout.refresh(); - } - } + if (client[kRunning] >= (getPipelining(client) || 1)) { + return; } - return ret; - } - end() { - const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this; - request.onRequestSent(); - socket[kWriting] = false; - if (socket[kError]) { - throw socket[kError]; + const request = client[kQueue][client[kPendingIdx]]; + if (client[kUrl].protocol === "https:" && client[kServerName] !== request.servername) { + if (client[kRunning] > 0) { + return; + } + client[kServerName] = request.servername; + client[kHTTPContext]?.destroy(new InformationalError("servername changed"), () => { + client[kHTTPContext] = null; + resume(client); + }); } - if (socket.destroyed) { + if (client[kConnecting]) { return; } - if (bytesWritten === 0) { - if (expectsPayload) { - socket.write(`${header}content-length: 0\r -\r -`, "latin1"); - } else { - socket.write(`${header}\r -`, "latin1"); - } - } else if (contentLength === null) { - socket.write("\r\n0\r\n\r\n", "latin1"); + if (!client[kHTTPContext]) { + connect(client); + return; } - if (contentLength !== null && bytesWritten !== contentLength) { - if (client[kStrictContentLength]) { - throw new RequestContentLengthMismatchError(); - } else { - process.emitWarning(new RequestContentLengthMismatchError()); - } + if (client[kHTTPContext].destroyed) { + return; } - if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { - if (socket[kParser].timeout.refresh) { - socket[kParser].timeout.refresh(); - } + if (client[kHTTPContext].busy(request)) { + return; } - resume(client); - } - destroy(err) { - const { socket, client } = this; - socket[kWriting] = false; - if (err) { - assert3(client[kRunning] <= 1, "pipeline should only contain this request"); - util.destroy(socket, err); + if (!request.aborted && client[kHTTPContext].write(request)) { + client[kPendingIdx]++; + } else { + client[kQueue].splice(client[kPendingIdx], 1); } } - }; - function errorRequest(client, request, err) { - try { - request.onError(err); - assert3(request.aborted); - } catch (err2) { - client.emit("error", err2); - } } module2.exports = Client; } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/pool.js +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/pool.js var require_pool = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/pool.js"(exports, module2) { + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/pool.js"(exports, module2) { "use strict"; var { PoolBase, @@ -13186,9 +12954,9 @@ var require_pool = __commonJS({ } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/agent.js +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/agent.js var require_agent = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/agent.js"(exports, module2) { + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/agent.js"(exports, module2) { "use strict"; var { InvalidArgumentError } = require_errors(); var { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = require_symbols(); @@ -13196,7 +12964,7 @@ var require_agent = __commonJS({ var Pool = require_pool(); var Client = require_client(); var util = require_util(); - var createRedirectInterceptor = require_redirectInterceptor(); + var createRedirectInterceptor = require_redirect_interceptor(); var kOnConnect = Symbol("onConnect"); var kOnDisconnect = Symbol("onDisconnect"); var kOnConnectionError = Symbol("onConnectionError"); @@ -13283,16 +13051,16 @@ var require_agent = __commonJS({ } }); -// .yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/proxy-agent.js +// .yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/proxy-agent.js var require_proxy_agent = __commonJS({ - ".yarn/cache/undici-npm-6.6.2-a0bd6785a6-c8c8a43605.zip/node_modules/undici/lib/proxy-agent.js"(exports, module2) { + ".yarn/cache/undici-npm-6.13.0-1545cd855e-b1b0456e7d.zip/node_modules/undici/lib/dispatcher/proxy-agent.js"(exports, module2) { "use strict"; var { kProxy, kClose, kDestroy, kInterceptors } = require_symbols(); var { URL: URL2 } = require("node:url"); var Agent = require_agent(); var Pool = require_pool(); var DispatcherBase = require_dispatcher_base(); - var { InvalidArgumentError, RequestAbortedError } = require_errors(); + var { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError } = require_errors(); var buildConnector = require_connect(); var kAgent = Symbol("proxy agent"); var kClient = Symbol("proxy client"); @@ -13303,42 +13071,26 @@ var require_proxy_agent = __commonJS({ function defaultProtocolPort(protocol) { return protocol === "https:" ? 443 : 80; } - function buildProxyOptions(opts) { - if (typeof opts === "string") { - opts = { uri: opts }; - } - if (!opts || !opts.uri) { - throw new InvalidArgumentError("Proxy opts.uri is mandatory"); - } - return { - uri: opts.uri, - protocol: opts.protocol || "https" - }; - } function defaultFactory(origin, opts) { return new Pool(origin, opts); } - var ProxyAgent = class extends DispatcherBase { + var ProxyAgent2 = class extends DispatcherBase { constructor(opts) { - super(opts); - this[kProxy] = buildProxyOptions(opts); - this[kAgent] = new Agent(opts); - this[kInterceptors] = opts.interceptors?.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent) ? opts.interceptors.ProxyAgent : []; - if (typeof opts === "string") { - opts = { uri: opts }; - } - if (!opts || !opts.uri) { - throw new InvalidArgumentError("Proxy opts.uri is mandatory"); + super(); + if (!opts || typeof opts === "object" && !(opts instanceof URL2) && !opts.uri) { + throw new InvalidArgumentError("Proxy uri is mandatory"); } const { clientFactory = defaultFactory } = opts; if (typeof clientFactory !== "function") { throw new InvalidArgumentError("Proxy opts.clientFactory must be a function."); } + const url = this.#getUrl(opts); + const { href, origin, port, protocol, username, password, hostname: proxyHostname } = url; + this[kProxy] = { uri: href, protocol }; + this[kInterceptors] = opts.interceptors?.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent) ? opts.interceptors.ProxyAgent : []; this[kRequestTls] = opts.requestTls; this[kProxyTls] = opts.proxyTls; this[kProxyHeaders] = opts.headers || {}; - const resolvedUrl = new URL2(opts.uri); - const { origin, port, username, password } = resolvedUrl; if (opts.auth && opts.token) { throw new InvalidArgumentError("opts.auth cannot be used in combination with opts.token"); } else if (opts.auth) { @@ -13350,24 +13102,25 @@ var require_proxy_agent = __commonJS({ } const connect = buildConnector({ ...opts.proxyTls }); this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }); - this[kClient] = clientFactory(resolvedUrl, { connect }); + this[kClient] = clientFactory(url, { connect }); this[kAgent] = new Agent({ ...opts, connect: async (opts2, callback) => { - let requestedHost = opts2.host; + let requestedPath = opts2.host; if (!opts2.port) { - requestedHost += `:${defaultProtocolPort(opts2.protocol)}`; + requestedPath += `:${defaultProtocolPort(opts2.protocol)}`; } try { const { socket, statusCode } = await this[kClient].connect({ origin, port, - path: requestedHost, + path: requestedPath, signal: opts2.signal, headers: { ...this[kProxyHeaders], - host: requestedHost - } + host: opts2.host + }, + servername: this[kProxyTls]?.servername || proxyHostname }); if (statusCode !== 200) { socket.on("error", () => { @@ -13386,26 +13139,43 @@ var require_proxy_agent = __commonJS({ } this[kConnectEndpoint]({ ...opts2, servername, httpSocket: socket }, callback); } catch (err) { - callback(err); + if (err.code === "ERR_TLS_CERT_ALTNAME_INVALID") { + callback(new SecureProxyConnectionError(err)); + } else { + callback(err); + } } } }); } dispatch(opts, handler) { - const { host } = new URL2(opts.origin); const headers = buildHeaders(opts.headers); throwIfProxyAuthIsSent(headers); + if (headers && !("host" in headers) && !("Host" in headers)) { + const { host } = new URL2(opts.origin); + headers.host = host; + } return this[kAgent].dispatch( { ...opts, - headers: { - ...headers, - host - } + headers }, handler ); } + /** + * @param {import('../types/proxy-agent').ProxyAgent.Options | string | URL} opts + * @returns {URL} + */ + #getUrl(opts) { + if (typeof opts === "string") { + return new URL2(opts); + } else if (opts instanceof URL2) { + return opts; + } else { + return new URL2(opts.uri); + } + } async [kClose]() { await this[kAgent].close(); await this[kClient].close(); @@ -13431,13 +13201,13 @@ var require_proxy_agent = __commonJS({ throw new InvalidArgumentError("Proxy-Authorization should be sent in ProxyAgent constructor"); } } - module2.exports = ProxyAgent; + module2.exports = ProxyAgent2; } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/high-level-opt.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/high-level-opt.js var require_high_level_opt = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/high-level-opt.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/high-level-opt.js"(exports, module2) { "use strict"; var argmap = /* @__PURE__ */ new Map([ ["C", "cwd"], @@ -14978,17 +14748,17 @@ var require_minizlib = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/normalize-windows-path.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/normalize-windows-path.js var require_normalize_windows_path = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/normalize-windows-path.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/normalize-windows-path.js"(exports, module2) { var platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform; module2.exports = platform !== "win32" ? (p) => p : (p) => p && p.replace(/\\/g, "/"); } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/read-entry.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/read-entry.js var require_read_entry = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/read-entry.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/read-entry.js"(exports, module2) { "use strict"; var { Minipass } = require_minipass(); var normPath = require_normalize_windows_path(); @@ -15080,9 +14850,9 @@ var require_read_entry = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/types.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/types.js var require_types = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/types.js"(exports) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/types.js"(exports) { "use strict"; exports.name = /* @__PURE__ */ new Map([ ["0", "File"], @@ -15127,9 +14897,9 @@ var require_types = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/large-numbers.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/large-numbers.js var require_large_numbers = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/large-numbers.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/large-numbers.js"(exports, module2) { "use strict"; var encode = (num, buf) => { if (!Number.isSafeInteger(num)) { @@ -15217,9 +14987,9 @@ var require_large_numbers = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/header.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/header.js var require_header = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/header.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/header.js"(exports, module2) { "use strict"; var types = require_types(); var pathModule = require("path").posix; @@ -15437,9 +15207,9 @@ var require_header = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/pax.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/pax.js var require_pax = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/pax.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/pax.js"(exports, module2) { "use strict"; var Header = require_header(); var path10 = require("path"); @@ -15538,9 +15308,9 @@ var require_pax = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/strip-trailing-slashes.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/strip-trailing-slashes.js var require_strip_trailing_slashes = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/strip-trailing-slashes.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/strip-trailing-slashes.js"(exports, module2) { module2.exports = (str) => { let i = str.length - 1; let slashesStart = -1; @@ -15553,9 +15323,9 @@ var require_strip_trailing_slashes = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/warn-mixin.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/warn-mixin.js var require_warn_mixin = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/warn-mixin.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/warn-mixin.js"(exports, module2) { "use strict"; module2.exports = (Base) => class extends Base { warn(code, message, data = {}) { @@ -15583,9 +15353,9 @@ var require_warn_mixin = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/winchars.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/winchars.js var require_winchars = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/winchars.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/winchars.js"(exports, module2) { "use strict"; var raw = [ "|", @@ -15604,9 +15374,9 @@ var require_winchars = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/strip-absolute-path.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/strip-absolute-path.js var require_strip_absolute_path = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/strip-absolute-path.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/strip-absolute-path.js"(exports, module2) { var { isAbsolute, parse } = require("path").win32; module2.exports = (path10) => { let r = ""; @@ -15622,9 +15392,9 @@ var require_strip_absolute_path = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/mode-fix.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/mode-fix.js var require_mode_fix = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/mode-fix.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/mode-fix.js"(exports, module2) { "use strict"; module2.exports = (mode, isDir, portable) => { mode &= 4095; @@ -15647,14 +15417,14 @@ var require_mode_fix = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/write-entry.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/write-entry.js var require_write_entry = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/write-entry.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/write-entry.js"(exports, module2) { "use strict"; var { Minipass } = require_minipass(); var Pax = require_pax(); var Header = require_header(); - var fs9 = require("fs"); + var fs8 = require("fs"); var path10 = require("path"); var normPath = require_normalize_windows_path(); var stripSlash = require_strip_trailing_slashes(); @@ -15757,7 +15527,7 @@ var require_write_entry = __commonJS({ return super.emit(ev, ...data); } [LSTAT]() { - fs9.lstat(this.absolute, (er, stat) => { + fs8.lstat(this.absolute, (er, stat) => { if (er) { return this.emit("error", er); } @@ -15839,7 +15609,7 @@ var require_write_entry = __commonJS({ this.end(); } [SYMLINK]() { - fs9.readlink(this.absolute, (er, linkpath) => { + fs8.readlink(this.absolute, (er, linkpath) => { if (er) { return this.emit("error", er); } @@ -15876,7 +15646,7 @@ var require_write_entry = __commonJS({ this[OPENFILE](); } [OPENFILE]() { - fs9.open(this.absolute, "r", (er, fd) => { + fs8.open(this.absolute, "r", (er, fd) => { if (er) { return this.emit("error", er); } @@ -15900,7 +15670,7 @@ var require_write_entry = __commonJS({ } [READ]() { const { fd, buf, offset, length, pos } = this; - fs9.read(fd, buf, offset, length, pos, (er, bytesRead) => { + fs8.read(fd, buf, offset, length, pos, (er, bytesRead) => { if (er) { return this[CLOSE](() => this.emit("error", er)); } @@ -15908,7 +15678,7 @@ var require_write_entry = __commonJS({ }); } [CLOSE](cb) { - fs9.close(this.fd, cb); + fs8.close(this.fd, cb); } [ONREAD](bytesRead) { if (bytesRead <= 0 && this.remain > 0) { @@ -15972,19 +15742,19 @@ var require_write_entry = __commonJS({ }); var WriteEntrySync = class extends WriteEntry { [LSTAT]() { - this[ONLSTAT](fs9.lstatSync(this.absolute)); + this[ONLSTAT](fs8.lstatSync(this.absolute)); } [SYMLINK]() { - this[ONREADLINK](fs9.readlinkSync(this.absolute)); + this[ONREADLINK](fs8.readlinkSync(this.absolute)); } [OPENFILE]() { - this[ONOPENFILE](fs9.openSync(this.absolute, "r")); + this[ONOPENFILE](fs8.openSync(this.absolute, "r")); } [READ]() { let threw = true; try { const { fd, buf, offset, length, pos } = this; - const bytesRead = fs9.readSync(fd, buf, offset, length, pos); + const bytesRead = fs8.readSync(fd, buf, offset, length, pos); this[ONREAD](bytesRead); threw = false; } finally { @@ -16001,7 +15771,7 @@ var require_write_entry = __commonJS({ cb(); } [CLOSE](cb) { - fs9.closeSync(this.fd); + fs8.closeSync(this.fd); cb(); } }; @@ -16112,9 +15882,9 @@ var require_write_entry = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/pack.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/pack.js var require_pack = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/pack.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/pack.js"(exports, module2) { "use strict"; var PackJob = class { constructor(path11, absolute) { @@ -16156,7 +15926,7 @@ var require_pack = __commonJS({ var WRITEENTRYCLASS = Symbol("writeEntryClass"); var WRITE = Symbol("write"); var ONDRAIN = Symbol("ondrain"); - var fs9 = require("fs"); + var fs8 = require("fs"); var path10 = require("path"); var warner = require_warn_mixin(); var normPath = require_normalize_windows_path(); @@ -16266,7 +16036,7 @@ var require_pack = __commonJS({ job.pending = true; this[JOBS] += 1; const stat = this.follow ? "stat" : "lstat"; - fs9[stat](job.absolute, (er, stat2) => { + fs8[stat](job.absolute, (er, stat2) => { job.pending = false; this[JOBS] -= 1; if (er) { @@ -16287,7 +16057,7 @@ var require_pack = __commonJS({ [READDIR](job) { job.pending = true; this[JOBS] += 1; - fs9.readdir(job.absolute, (er, entries) => { + fs8.readdir(job.absolute, (er, entries) => { job.pending = false; this[JOBS] -= 1; if (er) { @@ -16449,10 +16219,10 @@ var require_pack = __commonJS({ } [STAT](job) { const stat = this.follow ? "statSync" : "lstatSync"; - this[ONSTAT](job, fs9[stat](job.absolute)); + this[ONSTAT](job, fs8[stat](job.absolute)); } [READDIR](job, stat) { - this[ONREADDIR](job, fs9.readdirSync(job.absolute)); + this[ONREADDIR](job, fs8.readdirSync(job.absolute)); } // gotta get it all in this tick [PIPE](job) { @@ -16487,8 +16257,8 @@ var require_fs_minipass = __commonJS({ "use strict"; var MiniPass = require_minipass2(); var EE = require("events").EventEmitter; - var fs9 = require("fs"); - var writev = fs9.writev; + var fs8 = require("fs"); + var writev = fs8.writev; if (!writev) { const binding = process.binding("fs"); const FSReqWrap = binding.FSReqWrap || binding.FSReqCallback; @@ -16561,7 +16331,7 @@ var require_fs_minipass = __commonJS({ throw new TypeError("this is a readable stream"); } [_open]() { - fs9.open(this[_path], "r", (er, fd) => this[_onopen](er, fd)); + fs8.open(this[_path], "r", (er, fd) => this[_onopen](er, fd)); } [_onopen](er, fd) { if (er) @@ -16581,7 +16351,7 @@ var require_fs_minipass = __commonJS({ const buf = this[_makeBuf](); if (buf.length === 0) return process.nextTick(() => this[_onread](null, 0, buf)); - fs9.read(this[_fd], buf, 0, buf.length, null, (er, br, buf2) => this[_onread](er, br, buf2)); + fs8.read(this[_fd], buf, 0, buf.length, null, (er, br, buf2) => this[_onread](er, br, buf2)); } } [_onread](er, br, buf) { @@ -16595,7 +16365,7 @@ var require_fs_minipass = __commonJS({ if (this[_autoClose] && typeof this[_fd] === "number") { const fd = this[_fd]; this[_fd] = null; - fs9.close(fd, (er) => er ? this.emit("error", er) : this.emit("close")); + fs8.close(fd, (er) => er ? this.emit("error", er) : this.emit("close")); } } [_onerror](er) { @@ -16638,7 +16408,7 @@ var require_fs_minipass = __commonJS({ [_open]() { let threw = true; try { - this[_onopen](null, fs9.openSync(this[_path], "r")); + this[_onopen](null, fs8.openSync(this[_path], "r")); threw = false; } finally { if (threw) @@ -16652,7 +16422,7 @@ var require_fs_minipass = __commonJS({ this[_reading] = true; do { const buf = this[_makeBuf](); - const br = buf.length === 0 ? 0 : fs9.readSync(this[_fd], buf, 0, buf.length, null); + const br = buf.length === 0 ? 0 : fs8.readSync(this[_fd], buf, 0, buf.length, null); if (!this[_handleChunk](br, buf)) break; } while (true); @@ -16668,7 +16438,7 @@ var require_fs_minipass = __commonJS({ if (this[_autoClose] && typeof this[_fd] === "number") { const fd = this[_fd]; this[_fd] = null; - fs9.closeSync(fd); + fs8.closeSync(fd); this.emit("close"); } } @@ -16715,7 +16485,7 @@ var require_fs_minipass = __commonJS({ this.emit("error", er); } [_open]() { - fs9.open( + fs8.open( this[_path], this[_flags], this[_mode], @@ -16759,7 +16529,7 @@ var require_fs_minipass = __commonJS({ return true; } [_write](buf) { - fs9.write(this[_fd], buf, 0, buf.length, this[_pos], (er, bw) => this[_onwrite](er, bw)); + fs8.write(this[_fd], buf, 0, buf.length, this[_pos], (er, bw) => this[_onwrite](er, bw)); } [_onwrite](er, bw) { if (er) @@ -16803,7 +16573,7 @@ var require_fs_minipass = __commonJS({ if (this[_autoClose] && typeof this[_fd] === "number") { const fd = this[_fd]; this[_fd] = null; - fs9.close(fd, (er) => er ? this.emit("error", er) : this.emit("close")); + fs8.close(fd, (er) => er ? this.emit("error", er) : this.emit("close")); } } }; @@ -16812,7 +16582,7 @@ var require_fs_minipass = __commonJS({ let fd; if (this[_defaultFlag] && this[_flags] === "r+") { try { - fd = fs9.openSync(this[_path], this[_flags], this[_mode]); + fd = fs8.openSync(this[_path], this[_flags], this[_mode]); } catch (er) { if (er.code === "ENOENT") { this[_flags] = "w"; @@ -16821,14 +16591,14 @@ var require_fs_minipass = __commonJS({ throw er; } } else - fd = fs9.openSync(this[_path], this[_flags], this[_mode]); + fd = fs8.openSync(this[_path], this[_flags], this[_mode]); this[_onopen](null, fd); } [_close]() { if (this[_autoClose] && typeof this[_fd] === "number") { const fd = this[_fd]; this[_fd] = null; - fs9.closeSync(fd); + fs8.closeSync(fd); this.emit("close"); } } @@ -16837,7 +16607,7 @@ var require_fs_minipass = __commonJS({ try { this[_onwrite]( null, - fs9.writeSync(this[_fd], buf, 0, buf.length, this[_pos]) + fs8.writeSync(this[_fd], buf, 0, buf.length, this[_pos]) ); threw = false; } finally { @@ -16856,9 +16626,9 @@ var require_fs_minipass = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/parse.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/parse.js var require_parse2 = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/parse.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/parse.js"(exports, module2) { "use strict"; var warner = require_warn_mixin(); var Header = require_header(); @@ -17280,13 +17050,13 @@ var require_parse2 = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/list.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/list.js var require_list = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/list.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/list.js"(exports, module2) { "use strict"; var hlo = require_high_level_opt(); var Parser = require_parse2(); - var fs9 = require("fs"); + var fs8 = require("fs"); var fsm = require_fs_minipass(); var path10 = require("path"); var stripSlash = require_strip_trailing_slashes(); @@ -17343,16 +17113,16 @@ var require_list = __commonJS({ let threw = true; let fd; try { - const stat = fs9.statSync(file); + const stat = fs8.statSync(file); const readSize = opt.maxReadSize || 16 * 1024 * 1024; if (stat.size < readSize) { - p.end(fs9.readFileSync(file)); + p.end(fs8.readFileSync(file)); } else { let pos = 0; const buf = Buffer.allocUnsafe(readSize); - fd = fs9.openSync(file, "r"); + fd = fs8.openSync(file, "r"); while (pos < stat.size) { - const bytesRead = fs9.readSync(fd, buf, 0, readSize, pos); + const bytesRead = fs8.readSync(fd, buf, 0, readSize, pos); pos += bytesRead; p.write(buf.slice(0, bytesRead)); } @@ -17362,7 +17132,7 @@ var require_list = __commonJS({ } finally { if (threw && fd) { try { - fs9.closeSync(fd); + fs8.closeSync(fd); } catch (er) { } } @@ -17375,7 +17145,7 @@ var require_list = __commonJS({ const p = new Promise((resolve, reject) => { parse.on("error", reject); parse.on("end", resolve); - fs9.stat(file, (er, stat) => { + fs8.stat(file, (er, stat) => { if (er) { reject(er); } else { @@ -17394,9 +17164,9 @@ var require_list = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/create.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/create.js var require_create = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/create.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/create.js"(exports, module2) { "use strict"; var hlo = require_high_level_opt(); var Pack = require_pack(); @@ -17488,13 +17258,13 @@ var require_create = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/replace.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/replace.js var require_replace = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/replace.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/replace.js"(exports, module2) { "use strict"; var hlo = require_high_level_opt(); var Pack = require_pack(); - var fs9 = require("fs"); + var fs8 = require("fs"); var fsm = require_fs_minipass(); var t = require_list(); var path10 = require("path"); @@ -17520,20 +17290,20 @@ var require_replace = __commonJS({ let position; try { try { - fd = fs9.openSync(opt.file, "r+"); + fd = fs8.openSync(opt.file, "r+"); } catch (er) { if (er.code === "ENOENT") { - fd = fs9.openSync(opt.file, "w+"); + fd = fs8.openSync(opt.file, "w+"); } else { throw er; } } - const st = fs9.fstatSync(fd); + const st = fs8.fstatSync(fd); const headBuf = Buffer.alloc(512); POSITION: for (position = 0; position < st.size; position += 512) { for (let bufPos = 0, bytes = 0; bufPos < 512; bufPos += bytes) { - bytes = fs9.readSync( + bytes = fs8.readSync( fd, headBuf, bufPos, @@ -17565,7 +17335,7 @@ var require_replace = __commonJS({ } finally { if (threw) { try { - fs9.closeSync(fd); + fs8.closeSync(fd); } catch (er) { } } @@ -17585,7 +17355,7 @@ var require_replace = __commonJS({ const getPos = (fd, size, cb_) => { const cb2 = (er, pos) => { if (er) { - fs9.close(fd, (_) => cb_(er)); + fs8.close(fd, (_) => cb_(er)); } else { cb_(null, pos); } @@ -17602,7 +17372,7 @@ var require_replace = __commonJS({ } bufPos += bytes; if (bufPos < 512 && bytes) { - return fs9.read( + return fs8.read( fd, headBuf, bufPos, @@ -17633,9 +17403,9 @@ var require_replace = __commonJS({ opt.mtimeCache.set(h.path, h.mtime); } bufPos = 0; - fs9.read(fd, headBuf, 0, 512, position, onread); + fs8.read(fd, headBuf, 0, 512, position, onread); }; - fs9.read(fd, headBuf, 0, 512, position, onread); + fs8.read(fd, headBuf, 0, 512, position, onread); }; const promise = new Promise((resolve, reject) => { p.on("error", reject); @@ -17643,14 +17413,14 @@ var require_replace = __commonJS({ const onopen = (er, fd) => { if (er && er.code === "ENOENT" && flag === "r+") { flag = "w+"; - return fs9.open(opt.file, flag, onopen); + return fs8.open(opt.file, flag, onopen); } if (er) { return reject(er); } - fs9.fstat(fd, (er2, st) => { + fs8.fstat(fd, (er2, st) => { if (er2) { - return fs9.close(fd, () => reject(er2)); + return fs8.close(fd, () => reject(er2)); } getPos(fd, st.size, (er3, position) => { if (er3) { @@ -17667,7 +17437,7 @@ var require_replace = __commonJS({ }); }); }; - fs9.open(opt.file, flag, onopen); + fs8.open(opt.file, flag, onopen); }); return cb ? promise.then(cb, cb) : promise; }; @@ -17704,9 +17474,9 @@ var require_replace = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/update.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/update.js var require_update = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/update.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/update.js"(exports, module2) { "use strict"; var hlo = require_high_level_opt(); var r = require_replace(); @@ -17739,24 +17509,24 @@ var require_update = __commonJS({ var require_opts_arg = __commonJS({ ".yarn/cache/mkdirp-npm-1.0.4-37f6ef56b9-46ea0f3ffa.zip/node_modules/mkdirp/lib/opts-arg.js"(exports, module2) { var { promisify } = require("util"); - var fs9 = require("fs"); + var fs8 = require("fs"); var optsArg = (opts) => { if (!opts) - opts = { mode: 511, fs: fs9 }; + opts = { mode: 511, fs: fs8 }; else if (typeof opts === "object") - opts = { mode: 511, fs: fs9, ...opts }; + opts = { mode: 511, fs: fs8, ...opts }; else if (typeof opts === "number") - opts = { mode: opts, fs: fs9 }; + opts = { mode: opts, fs: fs8 }; else if (typeof opts === "string") - opts = { mode: parseInt(opts, 8), fs: fs9 }; + opts = { mode: parseInt(opts, 8), fs: fs8 }; else throw new TypeError("invalid options argument"); - opts.mkdir = opts.mkdir || opts.fs.mkdir || fs9.mkdir; + opts.mkdir = opts.mkdir || opts.fs.mkdir || fs8.mkdir; opts.mkdirAsync = promisify(opts.mkdir); - opts.stat = opts.stat || opts.fs.stat || fs9.stat; + opts.stat = opts.stat || opts.fs.stat || fs8.stat; opts.statAsync = promisify(opts.stat); - opts.statSync = opts.statSync || opts.fs.statSync || fs9.statSync; - opts.mkdirSync = opts.mkdirSync || opts.fs.mkdirSync || fs9.mkdirSync; + opts.statSync = opts.statSync || opts.fs.statSync || fs8.statSync; + opts.mkdirSync = opts.mkdirSync || opts.fs.mkdirSync || fs8.mkdirSync; return opts; }; module2.exports = optsArg; @@ -17923,12 +17693,12 @@ var require_mkdirp_native = __commonJS({ // .yarn/cache/mkdirp-npm-1.0.4-37f6ef56b9-46ea0f3ffa.zip/node_modules/mkdirp/lib/use-native.js var require_use_native = __commonJS({ ".yarn/cache/mkdirp-npm-1.0.4-37f6ef56b9-46ea0f3ffa.zip/node_modules/mkdirp/lib/use-native.js"(exports, module2) { - var fs9 = require("fs"); + var fs8 = require("fs"); var version2 = process.env.__TESTING_MKDIRP_NODE_VERSION__ || process.version; var versArr = version2.replace(/^v/, "").split("."); var hasNative = +versArr[0] > 10 || +versArr[0] === 10 && +versArr[1] >= 12; - var useNative = !hasNative ? () => false : (opts) => opts.mkdir === fs9.mkdir; - var useNativeSync = !hasNative ? () => false : (opts) => opts.mkdirSync === fs9.mkdirSync; + var useNative = !hasNative ? () => false : (opts) => opts.mkdir === fs8.mkdir; + var useNativeSync = !hasNative ? () => false : (opts) => opts.mkdirSync === fs8.mkdirSync; module2.exports = { useNative, useNativeSync }; } }); @@ -17964,14 +17734,14 @@ var require_mkdirp = __commonJS({ var require_chownr = __commonJS({ ".yarn/cache/chownr-npm-2.0.0-638f1c9c61-594754e130.zip/node_modules/chownr/chownr.js"(exports, module2) { "use strict"; - var fs9 = require("fs"); + var fs8 = require("fs"); var path10 = require("path"); - var LCHOWN = fs9.lchown ? "lchown" : "chown"; - var LCHOWNSYNC = fs9.lchownSync ? "lchownSync" : "chownSync"; - var needEISDIRHandled = fs9.lchown && !process.version.match(/v1[1-9]+\./) && !process.version.match(/v10\.[6-9]/); + var LCHOWN = fs8.lchown ? "lchown" : "chown"; + var LCHOWNSYNC = fs8.lchownSync ? "lchownSync" : "chownSync"; + var needEISDIRHandled = fs8.lchown && !process.version.match(/v1[1-9]+\./) && !process.version.match(/v10\.[6-9]/); var lchownSync = (path11, uid, gid) => { try { - return fs9[LCHOWNSYNC](path11, uid, gid); + return fs8[LCHOWNSYNC](path11, uid, gid); } catch (er) { if (er.code !== "ENOENT") throw er; @@ -17979,7 +17749,7 @@ var require_chownr = __commonJS({ }; var chownSync = (path11, uid, gid) => { try { - return fs9.chownSync(path11, uid, gid); + return fs8.chownSync(path11, uid, gid); } catch (er) { if (er.code !== "ENOENT") throw er; @@ -17989,7 +17759,7 @@ var require_chownr = __commonJS({ if (!er || er.code !== "EISDIR") cb(er); else - fs9.chown(path11, uid, gid, cb); + fs8.chown(path11, uid, gid, cb); } : (_, __, ___, cb) => cb; var handleEISDirSync = needEISDIRHandled ? (path11, uid, gid) => { try { @@ -18001,18 +17771,18 @@ var require_chownr = __commonJS({ } } : (path11, uid, gid) => lchownSync(path11, uid, gid); var nodeVersion = process.version; - var readdir = (path11, options, cb) => fs9.readdir(path11, options, cb); - var readdirSync = (path11, options) => fs9.readdirSync(path11, options); + var readdir = (path11, options, cb) => fs8.readdir(path11, options, cb); + var readdirSync = (path11, options) => fs8.readdirSync(path11, options); if (/^v4\./.test(nodeVersion)) - readdir = (path11, options, cb) => fs9.readdir(path11, cb); + readdir = (path11, options, cb) => fs8.readdir(path11, cb); var chown = (cpath, uid, gid, cb) => { - fs9[LCHOWN](cpath, uid, gid, handleEISDIR(cpath, uid, gid, (er) => { + fs8[LCHOWN](cpath, uid, gid, handleEISDIR(cpath, uid, gid, (er) => { cb(er && er.code !== "ENOENT" ? er : null); })); }; var chownrKid = (p, child, uid, gid, cb) => { if (typeof child === "string") - return fs9.lstat(path10.resolve(p, child), (er, stats) => { + return fs8.lstat(path10.resolve(p, child), (er, stats) => { if (er) return cb(er.code !== "ENOENT" ? er : null); stats.name = child; @@ -18056,7 +17826,7 @@ var require_chownr = __commonJS({ var chownrKidSync = (p, child, uid, gid) => { if (typeof child === "string") { try { - const stats = fs9.lstatSync(path10.resolve(p, child)); + const stats = fs8.lstatSync(path10.resolve(p, child)); stats.name = child; child = stats; } catch (er) { @@ -18091,12 +17861,12 @@ var require_chownr = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/mkdir.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/mkdir.js var require_mkdir = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/mkdir.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/mkdir.js"(exports, module2) { "use strict"; var mkdirp = require_mkdirp(); - var fs9 = require("fs"); + var fs8 = require("fs"); var path10 = require("path"); var chownr = require_chownr(); var normPath = require_normalize_windows_path(); @@ -18123,7 +17893,7 @@ var require_mkdir = __commonJS({ var cGet = (cache, key) => cache.get(normPath(key)); var cSet = (cache, key, val) => cache.set(normPath(key), val); var checkCwd = (dir, cb) => { - fs9.stat(dir, (er, st) => { + fs8.stat(dir, (er, st) => { if (er || !st.isDirectory()) { er = new CwdError(dir, er && er.code || "ENOTDIR"); } @@ -18150,7 +17920,7 @@ var require_mkdir = __commonJS({ if (created && doChown) { chownr(created, uid, gid, (er2) => done(er2)); } else if (needChmod) { - fs9.chmod(dir, mode, cb); + fs8.chmod(dir, mode, cb); } else { cb(); } @@ -18178,22 +17948,22 @@ var require_mkdir = __commonJS({ if (cGet(cache, part)) { return mkdir_(part, parts, mode, cache, unlink, cwd, created, cb); } - fs9.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)); + fs8.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)); }; var onmkdir = (part, parts, mode, cache, unlink, cwd, created, cb) => (er) => { if (er) { - fs9.lstat(part, (statEr, st) => { + fs8.lstat(part, (statEr, st) => { if (statEr) { statEr.path = statEr.path && normPath(statEr.path); cb(statEr); } else if (st.isDirectory()) { mkdir_(part, parts, mode, cache, unlink, cwd, created, cb); } else if (unlink) { - fs9.unlink(part, (er2) => { + fs8.unlink(part, (er2) => { if (er2) { return cb(er2); } - fs9.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)); + fs8.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)); }); } else if (st.isSymbolicLink()) { return cb(new SymlinkError(part, part + "/" + parts.join("/"))); @@ -18210,7 +17980,7 @@ var require_mkdir = __commonJS({ let ok = false; let code = "ENOTDIR"; try { - ok = fs9.statSync(dir).isDirectory(); + ok = fs8.statSync(dir).isDirectory(); } catch (er) { code = er.code; } finally { @@ -18237,7 +18007,7 @@ var require_mkdir = __commonJS({ chownr.sync(created2, uid, gid); } if (needChmod) { - fs9.chmodSync(dir, mode); + fs8.chmodSync(dir, mode); } }; if (cache && cGet(cache, dir) === true) { @@ -18259,17 +18029,17 @@ var require_mkdir = __commonJS({ continue; } try { - fs9.mkdirSync(part, mode); + fs8.mkdirSync(part, mode); created = created || part; cSet(cache, part, true); } catch (er) { - const st = fs9.lstatSync(part); + const st = fs8.lstatSync(part); if (st.isDirectory()) { cSet(cache, part, true); continue; } else if (unlink) { - fs9.unlinkSync(part); - fs9.mkdirSync(part, mode); + fs8.unlinkSync(part); + fs8.mkdirSync(part, mode); created = created || part; cSet(cache, part, true); continue; @@ -18283,9 +18053,9 @@ var require_mkdir = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/normalize-unicode.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/normalize-unicode.js var require_normalize_unicode = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/normalize-unicode.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/normalize-unicode.js"(exports, module2) { var normalizeCache = /* @__PURE__ */ Object.create(null); var { hasOwnProperty } = Object.prototype; module2.exports = (s) => { @@ -18297,9 +18067,9 @@ var require_normalize_unicode = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/path-reservations.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/path-reservations.js var require_path_reservations = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/path-reservations.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/path-reservations.js"(exports, module2) { var assert3 = require("assert"); var normalize = require_normalize_unicode(); var stripSlashes = require_strip_trailing_slashes(); @@ -18411,13 +18181,13 @@ var require_path_reservations = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/get-write-flag.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/get-write-flag.js var require_get_write_flag = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/get-write-flag.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/get-write-flag.js"(exports, module2) { var platform = process.env.__FAKE_PLATFORM__ || process.platform; var isWindows = platform === "win32"; - var fs9 = global.__FAKE_TESTING_FS__ || require("fs"); - var { O_CREAT, O_TRUNC, O_WRONLY, UV_FS_O_FILEMAP = 0 } = fs9.constants; + var fs8 = global.__FAKE_TESTING_FS__ || require("fs"); + var { O_CREAT, O_TRUNC, O_WRONLY, UV_FS_O_FILEMAP = 0 } = fs8.constants; var fMapEnabled = isWindows && !!UV_FS_O_FILEMAP; var fMapLimit = 512 * 1024; var fMapFlag = UV_FS_O_FILEMAP | O_TRUNC | O_CREAT | O_WRONLY; @@ -18425,13 +18195,13 @@ var require_get_write_flag = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/unpack.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/unpack.js var require_unpack = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/unpack.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/unpack.js"(exports, module2) { "use strict"; var assert3 = require("assert"); var Parser = require_parse2(); - var fs9 = require("fs"); + var fs8 = require("fs"); var fsm = require_fs_minipass(); var path10 = require("path"); var mkdir4 = require_mkdir(); @@ -18470,25 +18240,26 @@ var require_unpack = __commonJS({ var getFlag = require_get_write_flag(); var platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform; var isWindows = platform === "win32"; + var DEFAULT_MAX_DEPTH = 1024; var unlinkFile = (path11, cb) => { if (!isWindows) { - return fs9.unlink(path11, cb); + return fs8.unlink(path11, cb); } const name = path11 + ".DELETE." + crypto.randomBytes(16).toString("hex"); - fs9.rename(path11, name, (er) => { + fs8.rename(path11, name, (er) => { if (er) { return cb(er); } - fs9.unlink(name, cb); + fs8.unlink(name, cb); }); }; var unlinkFileSync = (path11) => { if (!isWindows) { - return fs9.unlinkSync(path11); + return fs8.unlinkSync(path11); } const name = path11 + ".DELETE." + crypto.randomBytes(16).toString("hex"); - fs9.renameSync(path11, name); - fs9.unlinkSync(name); + fs8.renameSync(path11, name); + fs8.unlinkSync(name); }; var uint32 = (a, b, c) => a === a >>> 0 ? a : b === b >>> 0 ? b : c; var cacheKeyNormalize = (path11) => stripSlash(normPath(normalize(path11))).toLowerCase(); @@ -18548,6 +18319,7 @@ var require_unpack = __commonJS({ } this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ? process.getuid() : null; this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ? process.getgid() : null; + this.maxDepth = typeof opt.maxDepth === "number" ? opt.maxDepth : DEFAULT_MAX_DEPTH; this.forceChown = opt.forceChown === true; this.win32 = !!opt.win32 || isWindows; this.newer = !!opt.newer; @@ -18580,12 +18352,12 @@ var require_unpack = __commonJS({ } } [CHECKPATH](entry) { + const p = normPath(entry.path); + const parts = p.split("/"); if (this.strip) { - const parts = normPath(entry.path).split("/"); if (parts.length < this.strip) { return false; } - entry.path = parts.slice(this.strip).join("/"); if (entry.type === "Link") { const linkparts = normPath(entry.linkpath).split("/"); if (linkparts.length >= this.strip) { @@ -18594,10 +18366,19 @@ var require_unpack = __commonJS({ return false; } } + parts.splice(0, this.strip); + entry.path = parts.join("/"); + } + if (isFinite(this.maxDepth) && parts.length > this.maxDepth) { + this.warn("TAR_ENTRY_ERROR", "path excessively deep", { + entry, + path: p, + depth: parts.length, + maxDepth: this.maxDepth + }); + return false; } if (!this.preservePaths) { - const p = normPath(entry.path); - const parts = p.split("/"); if (parts.includes("..") || isWindows && /^[a-z]:\.\.$/i.test(parts[0])) { this.warn("TAR_ENTRY_ERROR", `path contains '..'`, { entry, @@ -18705,7 +18486,7 @@ var require_unpack = __commonJS({ }); stream.on("error", (er) => { if (stream.fd) { - fs9.close(stream.fd, () => { + fs8.close(stream.fd, () => { }); } stream.write = () => true; @@ -18716,7 +18497,7 @@ var require_unpack = __commonJS({ const done = (er) => { if (er) { if (stream.fd) { - fs9.close(stream.fd, () => { + fs8.close(stream.fd, () => { }); } this[ONERROR](er, entry); @@ -18724,7 +18505,7 @@ var require_unpack = __commonJS({ return; } if (--actions === 0) { - fs9.close(stream.fd, (er2) => { + fs8.close(stream.fd, (er2) => { if (er2) { this[ONERROR](er2, entry); } else { @@ -18741,13 +18522,13 @@ var require_unpack = __commonJS({ actions++; const atime = entry.atime || /* @__PURE__ */ new Date(); const mtime = entry.mtime; - fs9.futimes(fd, atime, mtime, (er) => er ? fs9.utimes(abs, atime, mtime, (er2) => done(er2 && er)) : done()); + fs8.futimes(fd, atime, mtime, (er) => er ? fs8.utimes(abs, atime, mtime, (er2) => done(er2 && er)) : done()); } if (this[DOCHOWN](entry)) { actions++; const uid = this[UID](entry); const gid = this[GID](entry); - fs9.fchown(fd, uid, gid, (er) => er ? fs9.chown(abs, uid, gid, (er2) => done(er2 && er)) : done()); + fs8.fchown(fd, uid, gid, (er) => er ? fs8.chown(abs, uid, gid, (er2) => done(er2 && er)) : done()); } done(); }); @@ -18779,11 +18560,11 @@ var require_unpack = __commonJS({ }; if (entry.mtime && !this.noMtime) { actions++; - fs9.utimes(entry.absolute, entry.atime || /* @__PURE__ */ new Date(), entry.mtime, done); + fs8.utimes(entry.absolute, entry.atime || /* @__PURE__ */ new Date(), entry.mtime, done); } if (this[DOCHOWN](entry)) { actions++; - fs9.chown(entry.absolute, this[UID](entry), this[GID](entry), done); + fs8.chown(entry.absolute, this[UID](entry), this[GID](entry), done); } done(); }); @@ -18871,7 +18652,7 @@ var require_unpack = __commonJS({ afterMakeParent(); }; const afterMakeParent = () => { - fs9.lstat(entry.absolute, (lstatEr, st) => { + fs8.lstat(entry.absolute, (lstatEr, st) => { if (st && (this.keep || this.newer && st.mtime > entry.mtime)) { this[SKIP](entry); done(); @@ -18887,10 +18668,10 @@ var require_unpack = __commonJS({ if (!needChmod) { return afterChmod(); } - return fs9.chmod(entry.absolute, entry.mode, afterChmod); + return fs8.chmod(entry.absolute, entry.mode, afterChmod); } if (entry.absolute !== this.cwd) { - return fs9.rmdir(entry.absolute, (er) => this[MAKEFS](er, entry, done)); + return fs8.rmdir(entry.absolute, (er) => this[MAKEFS](er, entry, done)); } } if (entry.absolute === this.cwd) { @@ -18926,7 +18707,7 @@ var require_unpack = __commonJS({ } } [LINK](entry, linkpath, link, done) { - fs9[link](linkpath, entry.absolute, (er) => { + fs8[link](linkpath, entry.absolute, (er) => { if (er) { this[ONERROR](er, entry); } else { @@ -18967,7 +18748,7 @@ var require_unpack = __commonJS({ } } } - const [lstatEr, st] = callSync(() => fs9.lstatSync(entry.absolute)); + const [lstatEr, st] = callSync(() => fs8.lstatSync(entry.absolute)); if (st && (this.keep || this.newer && st.mtime > entry.mtime)) { return this[SKIP](entry); } @@ -18978,11 +18759,11 @@ var require_unpack = __commonJS({ if (entry.type === "Directory") { const needChmod = !this.noChmod && entry.mode && (st.mode & 4095) !== entry.mode; const [er3] = needChmod ? callSync(() => { - fs9.chmodSync(entry.absolute, entry.mode); + fs8.chmodSync(entry.absolute, entry.mode); }) : []; return this[MAKEFS](er3, entry); } - const [er2] = callSync(() => fs9.rmdirSync(entry.absolute)); + const [er2] = callSync(() => fs8.rmdirSync(entry.absolute)); this[MAKEFS](er2, entry); } const [er] = entry.absolute === this.cwd ? [] : callSync(() => unlinkFileSync(entry.absolute)); @@ -18993,7 +18774,7 @@ var require_unpack = __commonJS({ const oner = (er) => { let closeError; try { - fs9.closeSync(fd); + fs8.closeSync(fd); } catch (e) { closeError = e; } @@ -19004,7 +18785,7 @@ var require_unpack = __commonJS({ }; let fd; try { - fd = fs9.openSync(entry.absolute, getFlag(entry.size), mode); + fd = fs8.openSync(entry.absolute, getFlag(entry.size), mode); } catch (er) { return oner(er); } @@ -19015,7 +18796,7 @@ var require_unpack = __commonJS({ } tx.on("data", (chunk) => { try { - fs9.writeSync(fd, chunk, 0, chunk.length); + fs8.writeSync(fd, chunk, 0, chunk.length); } catch (er) { oner(er); } @@ -19026,10 +18807,10 @@ var require_unpack = __commonJS({ const atime = entry.atime || /* @__PURE__ */ new Date(); const mtime = entry.mtime; try { - fs9.futimesSync(fd, atime, mtime); + fs8.futimesSync(fd, atime, mtime); } catch (futimeser) { try { - fs9.utimesSync(entry.absolute, atime, mtime); + fs8.utimesSync(entry.absolute, atime, mtime); } catch (utimeser) { er = futimeser; } @@ -19039,10 +18820,10 @@ var require_unpack = __commonJS({ const uid = this[UID](entry); const gid = this[GID](entry); try { - fs9.fchownSync(fd, uid, gid); + fs8.fchownSync(fd, uid, gid); } catch (fchowner) { try { - fs9.chownSync(entry.absolute, uid, gid); + fs8.chownSync(entry.absolute, uid, gid); } catch (chowner) { er = er || fchowner; } @@ -19061,13 +18842,13 @@ var require_unpack = __commonJS({ } if (entry.mtime && !this.noMtime) { try { - fs9.utimesSync(entry.absolute, entry.atime || /* @__PURE__ */ new Date(), entry.mtime); + fs8.utimesSync(entry.absolute, entry.atime || /* @__PURE__ */ new Date(), entry.mtime); } catch (er2) { } } if (this[DOCHOWN](entry)) { try { - fs9.chownSync(entry.absolute, this[UID](entry), this[GID](entry)); + fs8.chownSync(entry.absolute, this[UID](entry), this[GID](entry)); } catch (er2) { } } @@ -19094,7 +18875,7 @@ var require_unpack = __commonJS({ } [LINK](entry, linkpath, link, done) { try { - fs9[link + "Sync"](linkpath, entry.absolute); + fs8[link + "Sync"](linkpath, entry.absolute); done(); entry.resume(); } catch (er) { @@ -19107,13 +18888,13 @@ var require_unpack = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/extract.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/extract.js var require_extract = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/lib/extract.js"(exports, module2) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/lib/extract.js"(exports, module2) { "use strict"; var hlo = require_high_level_opt(); var Unpack = require_unpack(); - var fs9 = require("fs"); + var fs8 = require("fs"); var fsm = require_fs_minipass(); var path10 = require("path"); var stripSlash = require_strip_trailing_slashes(); @@ -19157,7 +18938,7 @@ var require_extract = __commonJS({ var extractFileSync = (opt) => { const u = new Unpack.Sync(opt); const file = opt.file; - const stat = fs9.statSync(file); + const stat = fs8.statSync(file); const readSize = opt.maxReadSize || 16 * 1024 * 1024; const stream = new fsm.ReadStreamSync(file, { readSize, @@ -19172,7 +18953,7 @@ var require_extract = __commonJS({ const p = new Promise((resolve, reject) => { u.on("error", reject); u.on("close", resolve); - fs9.stat(file, (er, stat) => { + fs8.stat(file, (er, stat) => { if (er) { reject(er); } else { @@ -19192,9 +18973,9 @@ var require_extract = __commonJS({ } }); -// .yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/index.js +// .yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/index.js var require_tar = __commonJS({ - ".yarn/cache/tar-npm-6.2.0-3eb25205a7-02ca064a1a.zip/node_modules/tar/index.js"(exports) { + ".yarn/cache/tar-npm-6.2.1-237800bb20-a5eca3eb50.zip/node_modules/tar/index.js"(exports) { "use strict"; exports.c = exports.create = require_create(); exports.r = exports.replace = require_replace(); @@ -19218,7 +18999,7 @@ var require_v8_compile_cache = __commonJS({ "use strict"; var Module2 = require("module"); var crypto = require("crypto"); - var fs9 = require("fs"); + var fs8 = require("fs"); var path10 = require("path"); var vm = require("vm"); var os3 = require("os"); @@ -19280,22 +19061,22 @@ var require_v8_compile_cache = __commonJS({ const mapToStore = JSON.stringify(dump[1]); try { mkdirpSync(this._directory); - fs9.writeFileSync(this._lockFilename, "LOCK", { flag: "wx" }); + fs8.writeFileSync(this._lockFilename, "LOCK", { flag: "wx" }); } catch (error) { return false; } try { - fs9.writeFileSync(this._blobFilename, blobToStore); - fs9.writeFileSync(this._mapFilename, mapToStore); + fs8.writeFileSync(this._blobFilename, blobToStore); + fs8.writeFileSync(this._mapFilename, mapToStore); } finally { - fs9.unlinkSync(this._lockFilename); + fs8.unlinkSync(this._lockFilename); } return true; } _load() { try { - this._storedBlob = fs9.readFileSync(this._blobFilename); - this._storedMap = JSON.parse(fs9.readFileSync(this._mapFilename)); + this._storedBlob = fs8.readFileSync(this._blobFilename); + this._storedMap = JSON.parse(fs8.readFileSync(this._mapFilename)); } catch (e) { this._storedBlob = Buffer.alloc(0); this._storedMap = {}; @@ -19416,14 +19197,14 @@ var require_v8_compile_cache = __commonJS({ } function _mkdirpSync(p, mode) { try { - fs9.mkdirSync(p, mode); + fs8.mkdirSync(p, mode); } catch (err0) { if (err0.code === "ENOENT") { _mkdirpSync(path10.dirname(p)); _mkdirpSync(p); } else { try { - const stat = fs9.statSync(p); + const stat = fs8.statSync(p); if (!stat.isDirectory()) { throw err0; } @@ -19810,56 +19591,56 @@ var require_polyfills = __commonJS({ } var chdir; module2.exports = patch; - function patch(fs9) { + function patch(fs8) { if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { - patchLchmod(fs9); - } - if (!fs9.lutimes) { - patchLutimes(fs9); - } - fs9.chown = chownFix(fs9.chown); - fs9.fchown = chownFix(fs9.fchown); - fs9.lchown = chownFix(fs9.lchown); - fs9.chmod = chmodFix(fs9.chmod); - fs9.fchmod = chmodFix(fs9.fchmod); - fs9.lchmod = chmodFix(fs9.lchmod); - fs9.chownSync = chownFixSync(fs9.chownSync); - fs9.fchownSync = chownFixSync(fs9.fchownSync); - fs9.lchownSync = chownFixSync(fs9.lchownSync); - fs9.chmodSync = chmodFixSync(fs9.chmodSync); - fs9.fchmodSync = chmodFixSync(fs9.fchmodSync); - fs9.lchmodSync = chmodFixSync(fs9.lchmodSync); - fs9.stat = statFix(fs9.stat); - fs9.fstat = statFix(fs9.fstat); - fs9.lstat = statFix(fs9.lstat); - fs9.statSync = statFixSync(fs9.statSync); - fs9.fstatSync = statFixSync(fs9.fstatSync); - fs9.lstatSync = statFixSync(fs9.lstatSync); - if (fs9.chmod && !fs9.lchmod) { - fs9.lchmod = function(path10, mode, cb) { + patchLchmod(fs8); + } + if (!fs8.lutimes) { + patchLutimes(fs8); + } + fs8.chown = chownFix(fs8.chown); + fs8.fchown = chownFix(fs8.fchown); + fs8.lchown = chownFix(fs8.lchown); + fs8.chmod = chmodFix(fs8.chmod); + fs8.fchmod = chmodFix(fs8.fchmod); + fs8.lchmod = chmodFix(fs8.lchmod); + fs8.chownSync = chownFixSync(fs8.chownSync); + fs8.fchownSync = chownFixSync(fs8.fchownSync); + fs8.lchownSync = chownFixSync(fs8.lchownSync); + fs8.chmodSync = chmodFixSync(fs8.chmodSync); + fs8.fchmodSync = chmodFixSync(fs8.fchmodSync); + fs8.lchmodSync = chmodFixSync(fs8.lchmodSync); + fs8.stat = statFix(fs8.stat); + fs8.fstat = statFix(fs8.fstat); + fs8.lstat = statFix(fs8.lstat); + fs8.statSync = statFixSync(fs8.statSync); + fs8.fstatSync = statFixSync(fs8.fstatSync); + fs8.lstatSync = statFixSync(fs8.lstatSync); + if (fs8.chmod && !fs8.lchmod) { + fs8.lchmod = function(path10, mode, cb) { if (cb) process.nextTick(cb); }; - fs9.lchmodSync = function() { + fs8.lchmodSync = function() { }; } - if (fs9.chown && !fs9.lchown) { - fs9.lchown = function(path10, uid, gid, cb) { + if (fs8.chown && !fs8.lchown) { + fs8.lchown = function(path10, uid, gid, cb) { if (cb) process.nextTick(cb); }; - fs9.lchownSync = function() { + fs8.lchownSync = function() { }; } if (platform === "win32") { - fs9.rename = typeof fs9.rename !== "function" ? fs9.rename : function(fs$rename) { + fs8.rename = typeof fs8.rename !== "function" ? fs8.rename : function(fs$rename) { function rename(from, to, cb) { var start = Date.now(); var backoff = 0; fs$rename(from, to, function CB(er) { if (er && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") && Date.now() - start < 6e4) { setTimeout(function() { - fs9.stat(to, function(stater, st) { + fs8.stat(to, function(stater, st) { if (stater && stater.code === "ENOENT") fs$rename(from, to, CB); else @@ -19877,9 +19658,9 @@ var require_polyfills = __commonJS({ if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename); return rename; - }(fs9.rename); + }(fs8.rename); } - fs9.read = typeof fs9.read !== "function" ? fs9.read : function(fs$read) { + fs8.read = typeof fs8.read !== "function" ? fs8.read : function(fs$read) { function read(fd, buffer, offset, length, position, callback_) { var callback; if (callback_ && typeof callback_ === "function") { @@ -19887,23 +19668,23 @@ var require_polyfills = __commonJS({ callback = function(er, _, __) { if (er && er.code === "EAGAIN" && eagCounter < 10) { eagCounter++; - return fs$read.call(fs9, fd, buffer, offset, length, position, callback); + return fs$read.call(fs8, fd, buffer, offset, length, position, callback); } callback_.apply(this, arguments); }; } - return fs$read.call(fs9, fd, buffer, offset, length, position, callback); + return fs$read.call(fs8, fd, buffer, offset, length, position, callback); } if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read); return read; - }(fs9.read); - fs9.readSync = typeof fs9.readSync !== "function" ? fs9.readSync : function(fs$readSync) { + }(fs8.read); + fs8.readSync = typeof fs8.readSync !== "function" ? fs8.readSync : function(fs$readSync) { return function(fd, buffer, offset, length, position) { var eagCounter = 0; while (true) { try { - return fs$readSync.call(fs9, fd, buffer, offset, length, position); + return fs$readSync.call(fs8, fd, buffer, offset, length, position); } catch (er) { if (er.code === "EAGAIN" && eagCounter < 10) { eagCounter++; @@ -19913,10 +19694,10 @@ var require_polyfills = __commonJS({ } } }; - }(fs9.readSync); - function patchLchmod(fs10) { - fs10.lchmod = function(path10, mode, callback) { - fs10.open( + }(fs8.readSync); + function patchLchmod(fs9) { + fs9.lchmod = function(path10, mode, callback) { + fs9.open( path10, constants.O_WRONLY | constants.O_SYMLINK, mode, @@ -19926,8 +19707,8 @@ var require_polyfills = __commonJS({ callback(err); return; } - fs10.fchmod(fd, mode, function(err2) { - fs10.close(fd, function(err22) { + fs9.fchmod(fd, mode, function(err2) { + fs9.close(fd, function(err22) { if (callback) callback(err2 || err22); }); @@ -19935,68 +19716,68 @@ var require_polyfills = __commonJS({ } ); }; - fs10.lchmodSync = function(path10, mode) { - var fd = fs10.openSync(path10, constants.O_WRONLY | constants.O_SYMLINK, mode); + fs9.lchmodSync = function(path10, mode) { + var fd = fs9.openSync(path10, constants.O_WRONLY | constants.O_SYMLINK, mode); var threw = true; var ret; try { - ret = fs10.fchmodSync(fd, mode); + ret = fs9.fchmodSync(fd, mode); threw = false; } finally { if (threw) { try { - fs10.closeSync(fd); + fs9.closeSync(fd); } catch (er) { } } else { - fs10.closeSync(fd); + fs9.closeSync(fd); } } return ret; }; } - function patchLutimes(fs10) { - if (constants.hasOwnProperty("O_SYMLINK") && fs10.futimes) { - fs10.lutimes = function(path10, at, mt, cb) { - fs10.open(path10, constants.O_SYMLINK, function(er, fd) { + function patchLutimes(fs9) { + if (constants.hasOwnProperty("O_SYMLINK") && fs9.futimes) { + fs9.lutimes = function(path10, at, mt, cb) { + fs9.open(path10, constants.O_SYMLINK, function(er, fd) { if (er) { if (cb) cb(er); return; } - fs10.futimes(fd, at, mt, function(er2) { - fs10.close(fd, function(er22) { + fs9.futimes(fd, at, mt, function(er2) { + fs9.close(fd, function(er22) { if (cb) cb(er2 || er22); }); }); }); }; - fs10.lutimesSync = function(path10, at, mt) { - var fd = fs10.openSync(path10, constants.O_SYMLINK); + fs9.lutimesSync = function(path10, at, mt) { + var fd = fs9.openSync(path10, constants.O_SYMLINK); var ret; var threw = true; try { - ret = fs10.futimesSync(fd, at, mt); + ret = fs9.futimesSync(fd, at, mt); threw = false; } finally { if (threw) { try { - fs10.closeSync(fd); + fs9.closeSync(fd); } catch (er) { } } else { - fs10.closeSync(fd); + fs9.closeSync(fd); } } return ret; }; - } else if (fs10.futimes) { - fs10.lutimes = function(_a, _b, _c, cb) { + } else if (fs9.futimes) { + fs9.lutimes = function(_a, _b, _c, cb) { if (cb) process.nextTick(cb); }; - fs10.lutimesSync = function() { + fs9.lutimesSync = function() { }; } } @@ -20004,7 +19785,7 @@ var require_polyfills = __commonJS({ if (!orig) return orig; return function(target, mode, cb) { - return orig.call(fs9, target, mode, function(er) { + return orig.call(fs8, target, mode, function(er) { if (chownErOk(er)) er = null; if (cb) @@ -20017,7 +19798,7 @@ var require_polyfills = __commonJS({ return orig; return function(target, mode) { try { - return orig.call(fs9, target, mode); + return orig.call(fs8, target, mode); } catch (er) { if (!chownErOk(er)) throw er; @@ -20028,7 +19809,7 @@ var require_polyfills = __commonJS({ if (!orig) return orig; return function(target, uid, gid, cb) { - return orig.call(fs9, target, uid, gid, function(er) { + return orig.call(fs8, target, uid, gid, function(er) { if (chownErOk(er)) er = null; if (cb) @@ -20041,7 +19822,7 @@ var require_polyfills = __commonJS({ return orig; return function(target, uid, gid) { try { - return orig.call(fs9, target, uid, gid); + return orig.call(fs8, target, uid, gid); } catch (er) { if (!chownErOk(er)) throw er; @@ -20066,14 +19847,14 @@ var require_polyfills = __commonJS({ if (cb) cb.apply(this, arguments); } - return options ? orig.call(fs9, target, options, callback) : orig.call(fs9, target, callback); + return options ? orig.call(fs8, target, options, callback) : orig.call(fs8, target, callback); }; } function statFixSync(orig) { if (!orig) return orig; return function(target, options) { - var stats = options ? orig.call(fs9, target, options) : orig.call(fs9, target); + var stats = options ? orig.call(fs8, target, options) : orig.call(fs8, target); if (stats) { if (stats.uid < 0) stats.uid += 4294967296; @@ -20104,7 +19885,7 @@ var require_legacy_streams = __commonJS({ ".yarn/cache/graceful-fs-npm-4.2.11-24bb648a68-386d011a55.zip/node_modules/graceful-fs/legacy-streams.js"(exports, module2) { var Stream = require("stream").Stream; module2.exports = legacy; - function legacy(fs9) { + function legacy(fs8) { return { ReadStream, WriteStream @@ -20149,7 +19930,7 @@ var require_legacy_streams = __commonJS({ }); return; } - fs9.open(this.path, this.flags, this.mode, function(err, fd) { + fs8.open(this.path, this.flags, this.mode, function(err, fd) { if (err) { self2.emit("error", err); self2.readable = false; @@ -20189,7 +19970,7 @@ var require_legacy_streams = __commonJS({ this.busy = false; this._queue = []; if (this.fd === null) { - this._open = fs9.open; + this._open = fs8.open; this._queue.push([this._open, this.path, this.flags, this.mode, void 0]); this.flush(); } @@ -20224,7 +20005,7 @@ var require_clone = __commonJS({ // .yarn/cache/graceful-fs-npm-4.2.11-24bb648a68-386d011a55.zip/node_modules/graceful-fs/graceful-fs.js var require_graceful_fs = __commonJS({ ".yarn/cache/graceful-fs-npm-4.2.11-24bb648a68-386d011a55.zip/node_modules/graceful-fs/graceful-fs.js"(exports, module2) { - var fs9 = require("fs"); + var fs8 = require("fs"); var polyfills = require_polyfills(); var legacy = require_legacy_streams(); var clone = require_clone(); @@ -20256,12 +20037,12 @@ var require_graceful_fs = __commonJS({ m = "GFS4: " + m.split(/\n/).join("\nGFS4: "); console.error(m); }; - if (!fs9[gracefulQueue]) { + if (!fs8[gracefulQueue]) { queue = global[gracefulQueue] || []; - publishQueue(fs9, queue); - fs9.close = function(fs$close) { + publishQueue(fs8, queue); + fs8.close = function(fs$close) { function close(fd, cb) { - return fs$close.call(fs9, fd, function(err) { + return fs$close.call(fs8, fd, function(err) { if (!err) { resetQueue(); } @@ -20273,40 +20054,40 @@ var require_graceful_fs = __commonJS({ value: fs$close }); return close; - }(fs9.close); - fs9.closeSync = function(fs$closeSync) { + }(fs8.close); + fs8.closeSync = function(fs$closeSync) { function closeSync(fd) { - fs$closeSync.apply(fs9, arguments); + fs$closeSync.apply(fs8, arguments); resetQueue(); } Object.defineProperty(closeSync, previousSymbol, { value: fs$closeSync }); return closeSync; - }(fs9.closeSync); + }(fs8.closeSync); if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) { process.on("exit", function() { - debug2(fs9[gracefulQueue]); - require("assert").equal(fs9[gracefulQueue].length, 0); + debug2(fs8[gracefulQueue]); + require("assert").equal(fs8[gracefulQueue].length, 0); }); } } var queue; if (!global[gracefulQueue]) { - publishQueue(global, fs9[gracefulQueue]); - } - module2.exports = patch(clone(fs9)); - if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs9.__patched) { - module2.exports = patch(fs9); - fs9.__patched = true; - } - function patch(fs10) { - polyfills(fs10); - fs10.gracefulify = patch; - fs10.createReadStream = createReadStream; - fs10.createWriteStream = createWriteStream; - var fs$readFile = fs10.readFile; - fs10.readFile = readFile; + publishQueue(global, fs8[gracefulQueue]); + } + module2.exports = patch(clone(fs8)); + if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs8.__patched) { + module2.exports = patch(fs8); + fs8.__patched = true; + } + function patch(fs9) { + polyfills(fs9); + fs9.gracefulify = patch; + fs9.createReadStream = createReadStream; + fs9.createWriteStream = createWriteStream; + var fs$readFile = fs9.readFile; + fs9.readFile = readFile; function readFile(path10, options, cb) { if (typeof options === "function") cb = options, options = null; @@ -20322,8 +20103,8 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$writeFile = fs10.writeFile; - fs10.writeFile = writeFile; + var fs$writeFile = fs9.writeFile; + fs9.writeFile = writeFile; function writeFile(path10, data, options, cb) { if (typeof options === "function") cb = options, options = null; @@ -20339,9 +20120,9 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$appendFile = fs10.appendFile; + var fs$appendFile = fs9.appendFile; if (fs$appendFile) - fs10.appendFile = appendFile; + fs9.appendFile = appendFile; function appendFile(path10, data, options, cb) { if (typeof options === "function") cb = options, options = null; @@ -20357,9 +20138,9 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$copyFile = fs10.copyFile; + var fs$copyFile = fs9.copyFile; if (fs$copyFile) - fs10.copyFile = copyFile; + fs9.copyFile = copyFile; function copyFile(src, dest, flags, cb) { if (typeof flags === "function") { cb = flags; @@ -20377,8 +20158,8 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$readdir = fs10.readdir; - fs10.readdir = readdir; + var fs$readdir = fs9.readdir; + fs9.readdir = readdir; var noReaddirOptionVersions = /^v[0-5]\./; function readdir(path10, options, cb) { if (typeof options === "function") @@ -20419,21 +20200,21 @@ var require_graceful_fs = __commonJS({ } } if (process.version.substr(0, 4) === "v0.8") { - var legStreams = legacy(fs10); + var legStreams = legacy(fs9); ReadStream = legStreams.ReadStream; WriteStream = legStreams.WriteStream; } - var fs$ReadStream = fs10.ReadStream; + var fs$ReadStream = fs9.ReadStream; if (fs$ReadStream) { ReadStream.prototype = Object.create(fs$ReadStream.prototype); ReadStream.prototype.open = ReadStream$open; } - var fs$WriteStream = fs10.WriteStream; + var fs$WriteStream = fs9.WriteStream; if (fs$WriteStream) { WriteStream.prototype = Object.create(fs$WriteStream.prototype); WriteStream.prototype.open = WriteStream$open; } - Object.defineProperty(fs10, "ReadStream", { + Object.defineProperty(fs9, "ReadStream", { get: function() { return ReadStream; }, @@ -20443,7 +20224,7 @@ var require_graceful_fs = __commonJS({ enumerable: true, configurable: true }); - Object.defineProperty(fs10, "WriteStream", { + Object.defineProperty(fs9, "WriteStream", { get: function() { return WriteStream; }, @@ -20454,7 +20235,7 @@ var require_graceful_fs = __commonJS({ configurable: true }); var FileReadStream = ReadStream; - Object.defineProperty(fs10, "FileReadStream", { + Object.defineProperty(fs9, "FileReadStream", { get: function() { return FileReadStream; }, @@ -20465,7 +20246,7 @@ var require_graceful_fs = __commonJS({ configurable: true }); var FileWriteStream = WriteStream; - Object.defineProperty(fs10, "FileWriteStream", { + Object.defineProperty(fs9, "FileWriteStream", { get: function() { return FileWriteStream; }, @@ -20514,13 +20295,13 @@ var require_graceful_fs = __commonJS({ }); } function createReadStream(path10, options) { - return new fs10.ReadStream(path10, options); + return new fs9.ReadStream(path10, options); } function createWriteStream(path10, options) { - return new fs10.WriteStream(path10, options); + return new fs9.WriteStream(path10, options); } - var fs$open = fs10.open; - fs10.open = open; + var fs$open = fs9.open; + fs9.open = open; function open(path10, flags, mode, cb) { if (typeof mode === "function") cb = mode, mode = null; @@ -20536,20 +20317,20 @@ var require_graceful_fs = __commonJS({ }); } } - return fs10; + return fs9; } function enqueue(elem) { debug2("ENQUEUE", elem[0].name, elem[1]); - fs9[gracefulQueue].push(elem); + fs8[gracefulQueue].push(elem); retry(); } var retryTimer; function resetQueue() { var now = Date.now(); - for (var i = 0; i < fs9[gracefulQueue].length; ++i) { - if (fs9[gracefulQueue][i].length > 2) { - fs9[gracefulQueue][i][3] = now; - fs9[gracefulQueue][i][4] = now; + for (var i = 0; i < fs8[gracefulQueue].length; ++i) { + if (fs8[gracefulQueue][i].length > 2) { + fs8[gracefulQueue][i][3] = now; + fs8[gracefulQueue][i][4] = now; } } retry(); @@ -20557,9 +20338,9 @@ var require_graceful_fs = __commonJS({ function retry() { clearTimeout(retryTimer); retryTimer = void 0; - if (fs9[gracefulQueue].length === 0) + if (fs8[gracefulQueue].length === 0) return; - var elem = fs9[gracefulQueue].shift(); + var elem = fs8[gracefulQueue].shift(); var fn2 = elem[0]; var args = elem[1]; var err = elem[2]; @@ -20581,7 +20362,7 @@ var require_graceful_fs = __commonJS({ debug2("RETRY", fn2.name, args); fn2.apply(null, args.concat([startTime])); } else { - fs9[gracefulQueue].push(elem); + fs8[gracefulQueue].push(elem); } } if (retryTimer === void 0) { @@ -20618,15 +20399,15 @@ var require_cmd_shim = __commonJS({ ]); function ingestOptions(opts) { const opts_ = { ...DEFAULT_OPTIONS, ...opts }; - const fs9 = opts_.fs; + const fs8 = opts_.fs; opts_.fs_ = { - chmod: fs9.chmod ? (0, util_1.promisify)(fs9.chmod) : async () => { + chmod: fs8.chmod ? (0, util_1.promisify)(fs8.chmod) : async () => { }, - mkdir: (0, util_1.promisify)(fs9.mkdir), - readFile: (0, util_1.promisify)(fs9.readFile), - stat: (0, util_1.promisify)(fs9.stat), - unlink: (0, util_1.promisify)(fs9.unlink), - writeFile: (0, util_1.promisify)(fs9.writeFile) + mkdir: (0, util_1.promisify)(fs8.mkdir), + readFile: (0, util_1.promisify)(fs8.readFile), + stat: (0, util_1.promisify)(fs8.stat), + unlink: (0, util_1.promisify)(fs8.unlink), + writeFile: (0, util_1.promisify)(fs8.writeFile) }; return opts_; } @@ -20638,7 +20419,7 @@ var require_cmd_shim = __commonJS({ return cmdShim2(src, to, opts).catch(() => { }); } - function rm2(path11, opts) { + function rm(path11, opts) { return opts.fs_.unlink(path11).catch(() => { }); } @@ -20662,7 +20443,7 @@ var require_cmd_shim = __commonJS({ return Promise.all(generatorAndExts.map((generatorAndExt) => writeShim(src, to + generatorAndExt.extension, srcRuntimeInfo, generatorAndExt.generator, opts_))); } function writeShimPre(target, opts) { - return rm2(target, opts); + return rm(target, opts); } function writeShimPost(target, opts) { return chmodShim(target, opts); @@ -22636,19 +22417,19 @@ function String2(descriptor, ...args) { } // package.json -var version = "0.25.2"; +var version = "0.28.0"; // sources/Engine.ts -var import_fs3 = __toESM(require("fs")); -var import_path3 = __toESM(require("path")); +var import_fs4 = __toESM(require("fs")); +var import_path4 = __toESM(require("path")); var import_process3 = __toESM(require("process")); -var import_semver3 = __toESM(require_semver2()); +var import_semver4 = __toESM(require_semver2()); // config.json var config_default = { definitions: { npm: { - default: "10.4.0+sha1.904025b4d932cfaed8799e644a1c5ae7f02729fc", + default: "10.5.2+sha1.0e9b72afaf5ecf8249b2abb4b7417db6739c1475", fetchLatestFrom: { type: "npm", package: "npm" @@ -22685,7 +22466,7 @@ var config_default = { } }, pnpm: { - default: "8.15.3+sha1.64838798f519c18029c1e8a1310e16101fc2eda0", + default: "9.0.3+sha1.ff3ad37177cbd0843e533aab13d5e40a05803b47", fetchLatestFrom: { type: "npm", package: "pnpm" @@ -22743,14 +22524,18 @@ var config_default = { } }, yarn: { - default: "1.22.21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72", + default: "1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610", fetchLatestFrom: { type: "npm", package: "yarn" }, transparent: { - default: "4.1.0+sha224.bc24d7f5afc738464f3d4e95f4e6e7829a35cee54a0fd527ea5baa83", + default: "4.1.1+sha224.00f08619463229f8ba40c4ee90e8c2e4ced1f11c3115c26f3b98432e", commands: [ + [ + "yarn", + "init" + ], [ "yarn", "dlx" @@ -22792,7 +22577,8 @@ var config_default = { }, npmRegistry: { type: "npm", - package: "@yarnpkg/cli-dist" + package: "@yarnpkg/cli-dist", + bin: "bin/yarn.js" }, commands: { use: [ @@ -22803,16 +22589,28 @@ var config_default = { } } } + }, + keys: { + npm: [ + { + expires: null, + keyid: "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", + keytype: "ecdsa-sha2-nistp256", + scheme: "ecdsa-sha2-nistp256", + key: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg==" + } + ] } }; // sources/corepackUtils.ts -var import_crypto = require("crypto"); +var import_crypto2 = require("crypto"); var import_events2 = require("events"); var import_fs2 = __toESM(require("fs")); var import_module = __toESM(require("module")); var import_path2 = __toESM(require("path")); var import_semver = __toESM(require_semver2()); +var import_promises = require("timers/promises"); // sources/debugUtils.ts var import_debug = __toESM(require_src()); @@ -22856,27 +22654,109 @@ function getTemporaryFolder(target = (0, import_os.tmpdir)()) { } } } - -// sources/fsUtils.ts -var import_promises = require("fs/promises"); -async function rimraf(path10) { - return (0, import_promises.rm)(path10, { recursive: true, force: true }); + +// sources/httpUtils.ts +var import_assert = __toESM(require("assert")); +var import_events = require("events"); +var import_process2 = require("process"); +var import_stream = require("stream"); + +// sources/npmRegistryUtils.ts +var import_crypto = require("crypto"); +var DEFAULT_HEADERS = { + [`Accept`]: `application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8` +}; +var DEFAULT_NPM_REGISTRY_URL = `https://registry.npmjs.org`; +async function fetchAsJson2(packageName, version2) { + const npmRegistryUrl = process.env.COREPACK_NPM_REGISTRY || DEFAULT_NPM_REGISTRY_URL; + if (process.env.COREPACK_ENABLE_NETWORK === `0`) + throw new UsageError(`Network access disabled by the environment; can't reach npm repository ${npmRegistryUrl}`); + const headers = { ...DEFAULT_HEADERS }; + if (`COREPACK_NPM_TOKEN` in process.env) { + headers.authorization = `Bearer ${process.env.COREPACK_NPM_TOKEN}`; + } else if (`COREPACK_NPM_USERNAME` in process.env && `COREPACK_NPM_PASSWORD` in process.env) { + const encodedCreds = Buffer.from(`${process.env.COREPACK_NPM_USERNAME}:${process.env.COREPACK_NPM_PASSWORD}`, `utf8`).toString(`base64`); + headers.authorization = `Basic ${encodedCreds}`; + } + return fetchAsJson(`${npmRegistryUrl}/${packageName}${version2 ? `/${version2}` : ``}`, { headers }); +} +function verifySignature({ signatures, integrity, packageName, version: version2 }) { + const { npm: keys } = process.env.COREPACK_INTEGRITY_KEYS ? JSON.parse(process.env.COREPACK_INTEGRITY_KEYS) : config_default.keys; + const key = keys.find(({ keyid }) => signatures.some((s) => s.keyid === keyid)); + const signature = signatures.find(({ keyid }) => keyid === key?.keyid); + if (key == null || signature == null) + throw new Error(`Cannot find matching keyid: ${JSON.stringify({ signatures, keys })}`); + const verifier = (0, import_crypto.createVerify)(`SHA256`); + verifier.end(`${packageName}@${version2}:${integrity}`); + const valid = verifier.verify( + `-----BEGIN PUBLIC KEY----- +${key.key} +-----END PUBLIC KEY-----`, + signature.sig, + `base64` + ); + if (!valid) { + throw new Error(`Signature does not match`); + } +} +async function fetchLatestStableVersion(packageName) { + const metadata = await fetchAsJson2(packageName, `latest`); + const { version: version2, dist: { integrity, signatures } } = metadata; + if (process.env.COREPACK_INTEGRITY_KEYS !== ``) { + verifySignature({ + packageName, + version: version2, + integrity, + signatures + }); + } + return `${version2}+sha512.${Buffer.from(integrity.slice(7), `base64`).toString(`hex`)}`; +} +async function fetchAvailableTags(packageName) { + const metadata = await fetchAsJson2(packageName); + return metadata[`dist-tags`]; +} +async function fetchAvailableVersions(packageName) { + const metadata = await fetchAsJson2(packageName); + return Object.keys(metadata.versions); +} +async function fetchTarballURLAndSignature(packageName, version2) { + const versionMetadata = await fetchAsJson2(packageName, version2); + const { tarball, signatures, integrity } = versionMetadata.dist; + if (tarball === void 0 || !tarball.startsWith(`http`)) + throw new Error(`${packageName}@${version2} does not have a valid tarball.`); + return { tarball, signatures, integrity }; } // sources/httpUtils.ts -var import_assert = __toESM(require("assert")); -var import_events = require("events"); -var import_process2 = require("process"); -var import_stream = require("stream"); async function fetch(input, init) { if (process.env.COREPACK_ENABLE_NETWORK === `0`) throw new UsageError(`Network access disabled by the environment; can't reach ${input}`); const agent = await getProxyAgent(input); + if (typeof input === `string`) + input = new URL(input); + let headers = init?.headers; + const username = input.username ?? process.env.COREPACK_NPM_USERNAME; + const password = input.password ?? process.env.COREPACK_NPM_PASSWORD; + if (username || password) { + headers = { + ...headers, + authorization: `Basic ${Buffer.from(`${username}:${password}`).toString(`base64`)}` + }; + input.username = input.password = ``; + } + if (input.origin === (process.env.COREPACK_NPM_REGISTRY || DEFAULT_NPM_REGISTRY_URL) && process.env.COREPACK_NPM_TOKEN) { + headers = { + ...headers, + authorization: `Bearer ${process.env.COREPACK_NPM_TOKEN}` + }; + } let response; try { response = await globalThis.fetch(input, { ...init, - dispatcher: agent + dispatcher: agent, + headers }); } catch (error) { throw new Error( @@ -22898,17 +22778,15 @@ async function fetchAsJson(input, init) { } async function fetchUrlStream(input, init) { if (process.env.COREPACK_ENABLE_DOWNLOAD_PROMPT === `1`) { - console.error(`Corepack is about to download ${input}.`); + console.error(`! Corepack is about to download ${input}`); if (import_process2.stdin.isTTY && !process.env.CI) { - import_process2.stderr.write(` -Do you want to continue? [Y/n] `); + import_process2.stderr.write(`? Do you want to continue? [Y/n] `); import_process2.stdin.resume(); const chars = await (0, import_events.once)(import_process2.stdin, `data`); import_process2.stdin.pause(); - if (chars[0][0] === 110 || // n - chars[0][0] === 78) { + if (chars[0][0] === 110 || chars[0][0] === 78) throw new UsageError(`Aborted by the user`); - } + console.error(); } } const response = await fetch(input, init); @@ -22917,48 +22795,25 @@ Do you want to continue? [Y/n] `); const stream = import_stream.Readable.fromWeb(webStream); return stream; } +var ProxyAgent; async function getProxyAgent(input) { const { getProxyForUrl } = await Promise.resolve().then(() => __toESM(require_proxy_from_env())); const proxy = getProxyForUrl(input); if (!proxy) return void 0; - const { default: ProxyAgent } = await Promise.resolve().then(() => __toESM(require_proxy_agent())); - return new ProxyAgent(proxy); -} - -// sources/npmRegistryUtils.ts -var DEFAULT_HEADERS = { - [`Accept`]: `application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8` -}; -var DEFAULT_NPM_REGISTRY_URL = `https://registry.npmjs.org`; -async function fetchAsJson2(packageName) { - const npmRegistryUrl = process.env.COREPACK_NPM_REGISTRY || DEFAULT_NPM_REGISTRY_URL; - if (process.env.COREPACK_ENABLE_NETWORK === `0`) - throw new UsageError(`Network access disabled by the environment; can't reach npm repository ${npmRegistryUrl}`); - const headers = { ...DEFAULT_HEADERS }; - if (`COREPACK_NPM_TOKEN` in process.env) { - headers.authorization = `Bearer ${process.env.COREPACK_NPM_TOKEN}`; - } else if (`COREPACK_NPM_USERNAME` in process.env && `COREPACK_NPM_PASSWORD` in process.env) { - const encodedCreds = Buffer.from(`${process.env.COREPACK_NPM_USERNAME}:${process.env.COREPACK_NPM_PASSWORD}`, `utf8`).toString(`base64`); - headers.authorization = `Basic ${encodedCreds}`; + if (ProxyAgent == null) { + const [api, Dispatcher, _ProxyAgent] = await Promise.all([ + // @ts-expect-error internal module is untyped + Promise.resolve().then(() => __toESM(require_api())), + // @ts-expect-error internal module is untyped + Promise.resolve().then(() => __toESM(require_dispatcher())), + // @ts-expect-error internal module is untyped + Promise.resolve().then(() => __toESM(require_proxy_agent())) + ]); + Object.assign(Dispatcher.default.prototype, api.default); + ProxyAgent = _ProxyAgent.default; } - return fetchAsJson(`${npmRegistryUrl}/${packageName}`, { headers }); -} -async function fetchLatestStableVersion(packageName) { - const metadata = await fetchAsJson2(packageName); - const { latest } = metadata[`dist-tags`]; - if (latest === void 0) - throw new Error(`${packageName} does not have a "latest" tag.`); - const { shasum } = metadata.versions[latest].dist; - return `${latest}+sha1.${shasum}`; -} -async function fetchAvailableTags(packageName) { - const metadata = await fetchAsJson2(packageName); - return metadata[`dist-tags`]; -} -async function fetchAvailableVersions(packageName) { - const metadata = await fetchAsJson2(packageName); - return Object.keys(metadata.versions); + return new ProxyAgent(proxy); } // sources/corepackUtils.ts @@ -23049,6 +22904,57 @@ function parseURLReference(locator) { } return { version: encodeURIComponent(href), build: [] }; } +function isValidBinList(x) { + return Array.isArray(x) && x.length > 0; +} +function isValidBinSpec(x) { + return typeof x === `object` && x !== null && !Array.isArray(x) && Object.keys(x).length > 0; +} +async function download(installTarget, url, algo, binPath = null) { + const tmpFolder = getTemporaryFolder(installTarget); + log(`Downloading to ${tmpFolder}`); + const stream = await fetchUrlStream(url); + const parsedUrl = new URL(url); + const ext = import_path2.default.posix.extname(parsedUrl.pathname); + let outputFile = null; + let sendTo; + if (ext === `.tgz`) { + const { default: tar } = await Promise.resolve().then(() => __toESM(require_tar())); + sendTo = tar.x({ + strip: 1, + cwd: tmpFolder, + filter: binPath ? (path10) => { + const pos = path10.indexOf(`/`); + return pos !== -1 && path10.slice(pos + 1) === binPath; + } : void 0 + }); + } else if (ext === `.js`) { + outputFile = import_path2.default.join(tmpFolder, import_path2.default.posix.basename(parsedUrl.pathname)); + sendTo = import_fs2.default.createWriteStream(outputFile); + } + stream.pipe(sendTo); + let hash = !binPath ? stream.pipe((0, import_crypto2.createHash)(algo)) : null; + await (0, import_events2.once)(sendTo, `finish`); + if (binPath) { + const downloadedBin = import_path2.default.join(tmpFolder, binPath); + outputFile = import_path2.default.join(tmpFolder, import_path2.default.basename(downloadedBin)); + try { + await renameSafe(downloadedBin, outputFile); + } catch (err) { + if (err?.code === `ENOENT`) + throw new Error(`Cannot locate '${binPath}' in downloaded tarball`, { cause: err }); + throw err; + } + const fileStream = import_fs2.default.createReadStream(outputFile); + hash = fileStream.pipe((0, import_crypto2.createHash)(algo)); + await (0, import_events2.once)(fileStream, `close`); + } + return { + tmpFolder, + outputFile, + hash: hash.digest(`hex`) + }; +} async function installVersion(installTarget, locator, { spec }) { const locatorIsASupportedPackageManager = isSupportedPackageManagerLocator(locator); const locatorReference = locatorIsASupportedPackageManager ? import_semver.default.parse(locator.reference) : parseURLReference(locator); @@ -23070,42 +22976,68 @@ async function installVersion(installTarget, locator, { spec }) { } } let url; + let signatures; + let integrity; + let binPath = null; if (locatorIsASupportedPackageManager) { - const defaultNpmRegistryURL = spec.url.replace(`{}`, version2); - url = process.env.COREPACK_NPM_REGISTRY ? defaultNpmRegistryURL.replace( - DEFAULT_NPM_REGISTRY_URL, - () => process.env.COREPACK_NPM_REGISTRY - ) : defaultNpmRegistryURL; + url = spec.url.replace(`{}`, version2); + if (process.env.COREPACK_NPM_REGISTRY) { + const registry = getRegistryFromPackageManagerSpec(spec); + if (registry.type === `npm`) { + ({ tarball: url, signatures, integrity } = await fetchTarballURLAndSignature(registry.package, version2)); + if (registry.bin) { + binPath = registry.bin; + } + } else { + url = url.replace( + DEFAULT_NPM_REGISTRY_URL, + () => process.env.COREPACK_NPM_REGISTRY + ); + } + } } else { url = decodeURIComponent(version2); + if (process.env.COREPACK_NPM_REGISTRY && url.startsWith(DEFAULT_NPM_REGISTRY_URL)) { + url = url.replace( + DEFAULT_NPM_REGISTRY_URL, + () => process.env.COREPACK_NPM_REGISTRY + ); + } } - const tmpFolder = getTemporaryFolder(installTarget); - log(`Installing ${locator.name}@${version2} from ${url} to ${tmpFolder}`); - const stream = await fetchUrlStream(url); - const parsedUrl = new URL(url); - const ext = import_path2.default.posix.extname(parsedUrl.pathname); - let outputFile = null; - let sendTo; - if (ext === `.tgz`) { - const { default: tar } = await Promise.resolve().then(() => __toESM(require_tar())); - sendTo = tar.x({ strip: 1, cwd: tmpFolder }); - } else if (ext === `.js`) { - outputFile = import_path2.default.join(tmpFolder, import_path2.default.posix.basename(parsedUrl.pathname)); - sendTo = import_fs2.default.createWriteStream(outputFile); - } - stream.pipe(sendTo); - const algo = build[0] ?? `sha256`; - const hash = stream.pipe((0, import_crypto.createHash)(algo)); - await (0, import_events2.once)(sendTo, `finish`); + log(`Installing ${locator.name}@${version2} from ${url}`); + const algo = build[0] ?? `sha512`; + const { tmpFolder, outputFile, hash: actualHash } = await download(installTarget, url, algo, binPath); let bin; - if (!locatorIsASupportedPackageManager) { - if (ext === `.tgz`) { - bin = require(import_path2.default.join(tmpFolder, `package.json`)).bin; - } else if (ext === `.js`) { + const isSingleFile = outputFile !== null; + if (isSingleFile) { + if (locatorIsASupportedPackageManager && isValidBinList(spec.bin)) { + bin = spec.bin; + } else { bin = [locator.name]; } + } else { + if (locatorIsASupportedPackageManager && isValidBinSpec(spec.bin)) { + bin = spec.bin; + } else { + const { name: packageName, bin: packageBin } = require(import_path2.default.join(tmpFolder, `package.json`)); + if (typeof packageBin === `string`) { + bin = { [packageName]: packageBin }; + } else if (isValidBinSpec(packageBin)) { + bin = packageBin; + } else { + throw new Error(`Unable to locate bin in package.json`); + } + } + } + if (!build[1]) { + const registry = getRegistryFromPackageManagerSpec(spec); + if (registry.type === `npm` && !registry.bin && process.env.COREPACK_INTEGRITY_KEYS !== ``) { + if (signatures == null || integrity == null) + ({ signatures, integrity } = await fetchTarballURLAndSignature(registry.package, version2)); + verifySignature({ signatures, integrity, packageName: registry.package, version: version2 }); + build[1] = Buffer.from(integrity.slice(`sha512-`.length), `base64`).toString(`hex`); + } } - const actualHash = hash.digest(`hex`); if (build[1] && actualHash !== build[1]) throw new Error(`Mismatch hashes. Expected ${build[1]}, got ${actualHash}`); const serializedHash = `${algo}.${actualHash}`; @@ -23116,35 +23048,29 @@ async function installVersion(installTarget, locator, { spec }) { })); await import_fs2.default.promises.mkdir(import_path2.default.dirname(installFolder), { recursive: true }); try { - await import_fs2.default.promises.rename(tmpFolder, installFolder); + if (process.platform === `win32`) { + await renameUnderWindows(tmpFolder, installFolder); + } else { + await import_fs2.default.promises.rename(tmpFolder, installFolder); + } } catch (err) { if (err.code === `ENOTEMPTY` || // On Windows the error code is EPERM so we check if it is a directory err.code === `EPERM` && (await import_fs2.default.promises.stat(installFolder)).isDirectory()) { log(`Another instance of corepack installed ${locator.name}@${locator.reference}`); - await rimraf(tmpFolder); + await import_fs2.default.promises.rm(tmpFolder, { recursive: true, force: true }); } else { throw err; } } if (locatorIsASupportedPackageManager && process.env.COREPACK_DEFAULT_TO_LATEST !== `0`) { - let lastKnownGoodFile; - try { - lastKnownGoodFile = await getLastKnownGoodFile(`r+`); - const lastKnownGood = await getJSONFileContent(lastKnownGoodFile); - const defaultVersion = getLastKnownGoodFromFileContent(lastKnownGood, locator.name); - if (defaultVersion) { - const currentDefault = import_semver.default.parse(defaultVersion); - const downloadedVersion = locatorReference; - if (currentDefault.major === downloadedVersion.major && import_semver.default.lt(currentDefault, downloadedVersion)) { - await activatePackageManagerFromFileHandle(lastKnownGoodFile, lastKnownGood, locator); - } - } - } catch (err) { - if (err?.code !== `ENOENT`) { - throw err; + const lastKnownGood = await getLastKnownGood(); + const defaultVersion = getLastKnownGoodFromFileContent(lastKnownGood, locator.name); + if (defaultVersion) { + const currentDefault = import_semver.default.parse(defaultVersion); + const downloadedVersion = locatorReference; + if (currentDefault.major === downloadedVersion.major && import_semver.default.lt(currentDefault, downloadedVersion)) { + await activatePackageManager(lastKnownGood, locator); } - } finally { - await lastKnownGoodFile?.close(); } } log(`Install finished`); @@ -23154,10 +23080,34 @@ async function installVersion(installTarget, locator, { spec }) { hash: serializedHash }; } +async function renameSafe(oldPath, newPath) { + if (process.platform === `win32`) { + await renameUnderWindows(oldPath, newPath); + } else { + await import_fs2.default.promises.rename(oldPath, newPath); + } +} +async function renameUnderWindows(oldPath, newPath) { + const retries = 5; + for (let i = 0; i < retries; i++) { + try { + await import_fs2.default.promises.rename(oldPath, newPath); + break; + } catch (err) { + if ((err.code === `ENOENT` || err.code === `EPERM`) && i < retries - 1) { + await (0, import_promises.setTimeout)(100 * 2 ** i); + continue; + } else { + throw err; + } + } + } +} async function runVersion(locator, installSpec, binName, args) { let binPath = null; - if (Array.isArray(installSpec.spec.bin)) { - if (installSpec.spec.bin.some((bin) => bin === binName)) { + const bin = installSpec.bin ?? installSpec.spec.bin; + if (Array.isArray(bin)) { + if (bin.some((name) => name === binName)) { const parsedUrl = new URL(installSpec.spec.url); const ext = import_path2.default.posix.extname(parsedUrl.pathname); if (ext === `.js`) { @@ -23165,7 +23115,7 @@ async function runVersion(locator, installSpec, binName, args) { } } } else { - for (const [name, dest] of Object.entries(installSpec.spec.bin)) { + for (const [name, dest] of Object.entries(bin)) { if (name === binName) { binPath = import_path2.default.join(installSpec.location, dest); break; @@ -23204,74 +23154,214 @@ function satisfiesWithPrereleases(version2, range, loose = false) { if (semverVersion.prerelease) { semverVersion.prerelease = []; } - } catch (err) { - return false; + } catch (err) { + return false; + } + return semverRange.set.some((comparatorSet) => { + for (const comparator of comparatorSet) + if (comparator.semver.prerelease) + comparator.semver.prerelease = []; + return comparatorSet.every((comparator) => { + return comparator.test(semverVersion); + }); + }); +} + +// sources/specUtils.ts +var import_fs3 = __toESM(require("fs")); +var import_path3 = __toESM(require("path")); +var import_semver3 = __toESM(require_semver2()); + +// sources/nodeUtils.ts +var import_os2 = __toESM(require("os")); +function getEndOfLine(content) { + const matches = content.match(/\r?\n/g); + if (matches === null) + return import_os2.default.EOL; + const crlf = matches.filter((nl) => nl === `\r +`).length; + const lf = matches.length - crlf; + return crlf > lf ? `\r +` : ` +`; +} +function normalizeLineEndings(originalContent, newContent) { + return newContent.replace(/\r?\n/g, getEndOfLine(originalContent)); +} +function getIndent(content) { + const indentMatch = content.match(/^[ \t]+/m); + if (indentMatch) { + return indentMatch[0]; + } else { + return ` `; + } +} +function stripBOM(content) { + if (content.charCodeAt(0) === 65279) { + return content.slice(1); + } else { + return content; + } +} +function readPackageJson(content) { + return { + data: JSON.parse(stripBOM(content) || `{}`), + indent: getIndent(content) + }; +} + +// sources/types.ts +var SupportedPackageManagers = /* @__PURE__ */ ((SupportedPackageManagers3) => { + SupportedPackageManagers3["Npm"] = `npm`; + SupportedPackageManagers3["Pnpm"] = `pnpm`; + SupportedPackageManagers3["Yarn"] = `yarn`; + return SupportedPackageManagers3; +})(SupportedPackageManagers || {}); +var SupportedPackageManagerSet = new Set( + Object.values(SupportedPackageManagers) +); +var SupportedPackageManagerSetWithoutNpm = new Set( + Object.values(SupportedPackageManagers) +); +SupportedPackageManagerSetWithoutNpm.delete("npm" /* Npm */); +function isSupportedPackageManager(value) { + return SupportedPackageManagerSet.has(value); +} + +// sources/specUtils.ts +var nodeModulesRegExp = /[\\/]node_modules[\\/](@[^\\/]*[\\/])?([^@\\/][^\\/]*)$/; +function parseSpec(raw, source, { enforceExactVersion = true } = {}) { + if (typeof raw !== `string`) + throw new UsageError(`Invalid package manager specification in ${source}; expected a string`); + const atIndex = raw.indexOf(`@`); + if (atIndex === -1 || atIndex === raw.length - 1) { + if (enforceExactVersion) + throw new UsageError(`No version specified for ${raw} in "packageManager" of ${source}`); + const name2 = atIndex === -1 ? raw : raw.slice(0, -1); + if (!isSupportedPackageManager(name2)) + throw new UsageError(`Unsupported package manager specification (${name2})`); + return { + name: name2, + range: `*` + }; + } + const name = raw.slice(0, atIndex); + const range = raw.slice(atIndex + 1); + const isURL = URL.canParse(range); + if (!isURL) { + if (enforceExactVersion && !import_semver3.default.valid(range)) + throw new UsageError(`Invalid package manager specification in ${source} (${raw}); expected a semver version${enforceExactVersion ? `` : `, range, or tag`}`); + if (!isSupportedPackageManager(name)) { + throw new UsageError(`Unsupported package manager specification (${raw})`); + } + } else if (isSupportedPackageManager(name) && process.env.COREPACK_ENABLE_UNSAFE_CUSTOM_URLS !== `1`) { + throw new UsageError(`Illegal use of URL for known package manager. Instead, select a specific version, or set COREPACK_ENABLE_UNSAFE_CUSTOM_URLS=1 in your environment (${raw})`); + } + return { + name, + range + }; +} +async function setLocalPackageManager(cwd, info) { + const lookup = await loadSpec(cwd); + const content = lookup.type !== `NoProject` ? await import_fs3.default.promises.readFile(lookup.target, `utf8`) : ``; + const { data, indent } = readPackageJson(content); + const previousPackageManager = data.packageManager ?? `unknown`; + data.packageManager = `${info.locator.name}@${info.locator.reference}`; + const newContent = normalizeLineEndings(content, `${JSON.stringify(data, null, indent)} +`); + await import_fs3.default.promises.writeFile(lookup.target, newContent, `utf8`); + return { + previousPackageManager + }; +} +async function loadSpec(initialCwd) { + let nextCwd = initialCwd; + let currCwd = ``; + let selection = null; + while (nextCwd !== currCwd && (!selection || !selection.data.packageManager)) { + currCwd = nextCwd; + nextCwd = import_path3.default.dirname(currCwd); + if (nodeModulesRegExp.test(currCwd)) + continue; + const manifestPath = import_path3.default.join(currCwd, `package.json`); + let content; + try { + content = await import_fs3.default.promises.readFile(manifestPath, `utf8`); + } catch (err) { + if (err?.code === `ENOENT`) + continue; + throw err; + } + let data; + try { + data = JSON.parse(content); + } catch { + } + if (typeof data !== `object` || data === null) + throw new UsageError(`Invalid package.json in ${import_path3.default.relative(initialCwd, manifestPath)}`); + selection = { data, manifestPath }; } - return semverRange.set.some((comparatorSet) => { - for (const comparator of comparatorSet) - if (comparator.semver.prerelease) - comparator.semver.prerelease = []; - return comparatorSet.every((comparator) => { - return comparator.test(semverVersion); - }); - }); -} - -// sources/types.ts -var SupportedPackageManagers = /* @__PURE__ */ ((SupportedPackageManagers3) => { - SupportedPackageManagers3["Npm"] = `npm`; - SupportedPackageManagers3["Pnpm"] = `pnpm`; - SupportedPackageManagers3["Yarn"] = `yarn`; - return SupportedPackageManagers3; -})(SupportedPackageManagers || {}); -var SupportedPackageManagerSet = new Set( - Object.values(SupportedPackageManagers) -); -var SupportedPackageManagerSetWithoutNpm = new Set( - Object.values(SupportedPackageManagers) -); -SupportedPackageManagerSetWithoutNpm.delete("npm" /* Npm */); -function isSupportedPackageManager(value) { - return SupportedPackageManagerSet.has(value); + if (selection === null) + return { type: `NoProject`, target: import_path3.default.join(initialCwd, `package.json`) }; + const rawPmSpec = selection.data.packageManager; + if (typeof rawPmSpec === `undefined`) + return { type: `NoSpec`, target: selection.manifestPath }; + return { + type: `Found`, + target: selection.manifestPath, + spec: parseSpec(rawPmSpec, import_path3.default.relative(initialCwd, selection.manifestPath)) + }; } // sources/Engine.ts -function getLastKnownGoodFile(flag = `r`) { - return import_fs3.default.promises.open(import_path3.default.join(getCorepackHomeFolder(), `lastKnownGood.json`), flag); +function getLastKnownGoodFilePath() { + return import_path4.default.join(getCorepackHomeFolder(), `lastKnownGood.json`); } -async function createLastKnownGoodFile() { - await import_fs3.default.promises.mkdir(getCorepackHomeFolder(), { recursive: true }); - return getLastKnownGoodFile(`w`); -} -async function getJSONFileContent(fh) { - let lastKnownGood; +async function getLastKnownGood() { + let raw; + try { + raw = await import_fs4.default.promises.readFile(getLastKnownGoodFilePath(), `utf8`); + } catch (err) { + if (err?.code === `ENOENT`) + return {}; + throw err; + } try { - lastKnownGood = JSON.parse(await fh.readFile(`utf8`)); + const parsed = JSON.parse(raw); + if (!parsed) + return {}; + if (typeof parsed !== `object`) + return {}; + Object.entries(parsed).forEach(([key, value]) => { + if (typeof value !== `string`) { + delete parsed[key]; + } + }); + return parsed; } catch { - return void 0; + return {}; } - return lastKnownGood; } -async function overwriteJSONFileContent(fh, content) { - await fh.truncate(0); - await fh.write(`${JSON.stringify(content, null, 2)} -`, 0); +async function createLastKnownGoodFile(lastKnownGood) { + const content = `${JSON.stringify(lastKnownGood, null, 2)} +`; + await import_fs4.default.promises.mkdir(getCorepackHomeFolder(), { recursive: true }); + await import_fs4.default.promises.writeFile(getLastKnownGoodFilePath(), content, `utf8`); } function getLastKnownGoodFromFileContent(lastKnownGood, packageManager) { - if (typeof lastKnownGood === `object` && lastKnownGood !== null && Object.hasOwn(lastKnownGood, packageManager)) { - const override = lastKnownGood[packageManager]; - if (typeof override === `string`) { - return override; - } - } + if (Object.hasOwn(lastKnownGood, packageManager)) + return lastKnownGood[packageManager]; return void 0; } -async function activatePackageManagerFromFileHandle(lastKnownGoodFile, lastKnownGood, locator) { - if (typeof lastKnownGood !== `object` || lastKnownGood === null) - lastKnownGood = {}; +async function activatePackageManager(lastKnownGood, locator) { + if (lastKnownGood[locator.name] === locator.reference) { + log(`${locator.name}@${locator.reference} is already Last Known Good version`); + return; + } lastKnownGood[locator.name] = locator.reference; log(`Setting ${locator.name}@${locator.reference} as Last Known Good version`); - await overwriteJSONFileContent(lastKnownGoodFile, lastKnownGood); + await createLastKnownGoodFile(lastKnownGood); } var Engine = class { constructor(config = config_default) { @@ -23334,60 +23424,126 @@ var Engine = class { const definition = this.config.definitions[packageManager]; if (typeof definition === `undefined`) throw new UsageError(`This package manager (${packageManager}) isn't supported by this corepack build`); - let lastKnownGoodFile = await getLastKnownGoodFile(`r+`).catch((err) => { - if (err?.code !== `ENOENT`) { - throw err; - } - }); + const lastKnownGood = await getLastKnownGood(); + const lastKnownGoodForThisPackageManager = getLastKnownGoodFromFileContent(lastKnownGood, packageManager); + if (lastKnownGoodForThisPackageManager) + return lastKnownGoodForThisPackageManager; + if (import_process3.default.env.COREPACK_DEFAULT_TO_LATEST === `0`) + return definition.default; + const reference = await fetchLatestStableVersion2(definition.fetchLatestFrom); try { - const lastKnownGood = lastKnownGoodFile == null || await getJSONFileContent(lastKnownGoodFile); - const lastKnownGoodForThisPackageManager = getLastKnownGoodFromFileContent(lastKnownGood, packageManager); - if (lastKnownGoodForThisPackageManager) - return lastKnownGoodForThisPackageManager; - if (import_process3.default.env.COREPACK_DEFAULT_TO_LATEST === `0`) - return definition.default; - const reference = await fetchLatestStableVersion2(definition.fetchLatestFrom); - try { - lastKnownGoodFile ??= await createLastKnownGoodFile(); - await activatePackageManagerFromFileHandle(lastKnownGoodFile, lastKnownGood, { - name: packageManager, - reference - }); - } catch { - } - return reference; - } finally { - await lastKnownGoodFile?.close(); + await activatePackageManager(lastKnownGood, { + name: packageManager, + reference + }); + } catch { } + return reference; } async activatePackageManager(locator) { - let emptyFile = false; - const lastKnownGoodFile = await getLastKnownGoodFile(`r+`).catch((err) => { - if (err?.code === `ENOENT`) { - emptyFile = true; - return getLastKnownGoodFile(`w`); - } - throw err; - }); - try { - await activatePackageManagerFromFileHandle(lastKnownGoodFile, emptyFile || await getJSONFileContent(lastKnownGoodFile), locator); - } finally { - await lastKnownGoodFile.close(); - } + const lastKnownGood = await getLastKnownGood(); + await activatePackageManager(lastKnownGood, locator); } async ensurePackageManager(locator) { const spec = this.getPackageManagerSpecFor(locator); const packageManagerInfo = await installVersion(getInstallFolder(), locator, { spec }); - spec.bin ??= packageManagerInfo.bin; + const noHashReference = locator.reference.replace(/\+.*/, ``); + const fixedHashReference = `${noHashReference}+${packageManagerInfo.hash}`; + const fixedHashLocator = { + name: locator.name, + reference: fixedHashReference + }; return { ...packageManagerInfo, - locator, + locator: fixedHashLocator, spec }; } - async fetchAvailableVersions() { + /** + * Locates the active project's package manager specification. + * + * If the specification exists but doesn't match the active package manager, + * an error is thrown to prevent users from using the wrong package manager, + * which would lead to inconsistent project layouts. + * + * If the project doesn't include a specification file, we just assume that + * whatever the user uses is exactly what they want to use. Since the version + * isn't explicited, we fallback on known good versions. + * + * Finally, if the project doesn't exist at all, we ask the user whether they + * want to create one in the current project. If they do, we initialize a new + * project using the default package managers, and configure it so that we + * don't need to ask again in the future. + */ + async findProjectSpec(initialCwd, locator, { transparent = false } = {}) { + const fallbackDescriptor = { name: locator.name, range: `${locator.reference}` }; + if (import_process3.default.env.COREPACK_ENABLE_PROJECT_SPEC === `0`) + return fallbackDescriptor; + if (import_process3.default.env.COREPACK_ENABLE_STRICT === `0`) + transparent = true; + while (true) { + const result = await loadSpec(initialCwd); + switch (result.type) { + case `NoProject`: + return fallbackDescriptor; + case `NoSpec`: { + if (import_process3.default.env.COREPACK_ENABLE_AUTO_PIN !== `0`) { + const resolved = await this.resolveDescriptor(fallbackDescriptor, { allowTags: true }); + if (resolved === null) + throw new UsageError(`Failed to successfully resolve '${fallbackDescriptor.range}' to a valid ${fallbackDescriptor.name} release`); + const installSpec = await this.ensurePackageManager(resolved); + console.error(`! The local project doesn't define a 'packageManager' field. Corepack will now add one referencing ${installSpec.locator.name}@${installSpec.locator.reference}.`); + console.error(`! For more details about this field, consult the documentation at https://nodejs.org/api/packages.html#packagemanager`); + console.error(); + await setLocalPackageManager(import_path4.default.dirname(result.target), installSpec); + } + return fallbackDescriptor; + } + case `Found`: { + if (result.spec.name !== locator.name) { + if (transparent) { + return fallbackDescriptor; + } else { + throw new UsageError(`This project is configured to use ${result.spec.name} because ${result.target} has a "packageManager" field`); + } + } else { + return result.spec; + } + } + } + } + } + async executePackageManagerRequest({ packageManager, binaryName, binaryVersion }, { cwd, args }) { + let fallbackLocator = { + name: binaryName, + reference: void 0 + }; + let isTransparentCommand = false; + if (packageManager != null) { + const defaultVersion = binaryVersion || await this.getDefaultVersion(packageManager); + const definition = this.config.definitions[packageManager]; + for (const transparentPath of definition.transparent.commands) { + if (transparentPath[0] === binaryName && transparentPath.slice(1).every((segment, index) => segment === args[index])) { + isTransparentCommand = true; + break; + } + } + const fallbackReference = isTransparentCommand ? definition.transparent.default ?? defaultVersion : defaultVersion; + fallbackLocator = { + name: packageManager, + reference: fallbackReference + }; + } + const descriptor = await this.findProjectSpec(cwd, fallbackLocator, { transparent: isTransparentCommand }); + if (binaryVersion) + descriptor.range = binaryVersion; + const resolved = await this.resolveDescriptor(descriptor, { allowTags: true }); + if (resolved === null) + throw new UsageError(`Failed to successfully resolve '${descriptor.range}' to a valid ${descriptor.name} release`); + const installSpec = await this.ensurePackageManager(resolved); + return await runVersion(resolved, installSpec, binaryName, args); } async resolveDescriptor(descriptor, { allowTags = false, useCache = true } = {}) { if (!isSupportedPackageManagerDescriptor(descriptor)) { @@ -23402,7 +23558,7 @@ var Engine = class { if (typeof definition === `undefined`) throw new UsageError(`This package manager (${descriptor.name}) isn't supported by this corepack build`); let finalDescriptor = descriptor; - if (!import_semver3.default.valid(descriptor.range) && !import_semver3.default.validRange(descriptor.range)) { + if (!import_semver4.default.valid(descriptor.range) && !import_semver4.default.validRange(descriptor.range)) { if (!allowTags) throw new UsageError(`Packages managers can't be referenced via tags in this context`); const ranges = Object.keys(definition.ranges); @@ -23420,7 +23576,7 @@ var Engine = class { const cachedVersion = await findInstalledVersion(getInstallFolder(), finalDescriptor); if (cachedVersion !== null && useCache) return { name: finalDescriptor.name, reference: cachedVersion }; - if (import_semver3.default.valid(finalDescriptor.range)) + if (import_semver4.default.valid(finalDescriptor.range)) return { name: finalDescriptor.name, reference: finalDescriptor.range }; const versions = await Promise.all(Object.keys(definition.ranges).map(async (range) => { const packageManagerSpec = definition.ranges[range]; @@ -23428,7 +23584,7 @@ var Engine = class { const versions2 = await fetchAvailableVersions2(registry); return versions2.filter((version2) => satisfiesWithPrereleases(version2, finalDescriptor.range)); })); - const highestVersion = [...new Set(versions.flat())].sort(import_semver3.default.rcompare); + const highestVersion = [...new Set(versions.flat())].sort(import_semver4.default.rcompare); if (highestVersion.length === 0) return null; return { name: finalDescriptor.name, reference: highestVersion[0] }; @@ -23436,7 +23592,7 @@ var Engine = class { }; // sources/commands/Cache.ts -var import_fs4 = __toESM(require("fs")); +var import_fs5 = __toESM(require("fs")); var CacheCommand = class extends Command { static paths = [ [`cache`, `clean`], @@ -23449,13 +23605,13 @@ var CacheCommand = class extends Command { ` }); async execute() { - await import_fs4.default.promises.rm(getInstallFolder(), { recursive: true, force: true }); + await import_fs5.default.promises.rm(getInstallFolder(), { recursive: true, force: true }); } }; // sources/commands/Disable.ts -var import_fs5 = __toESM(require("fs")); -var import_path4 = __toESM(require("path")); +var import_fs6 = __toESM(require("fs")); +var import_path5 = __toESM(require("path")); var import_which = __toESM(require_lib()); var DisableCommand = class extends Command { static paths = [ @@ -23486,7 +23642,7 @@ var DisableCommand = class extends Command { async execute() { let installDirectory = this.installDirectory; if (typeof installDirectory === `undefined`) - installDirectory = import_path4.default.dirname(await (0, import_which.default)(`corepack`)); + installDirectory = import_path5.default.dirname(await (0, import_which.default)(`corepack`)); const names = this.names.length === 0 ? SupportedPackageManagerSetWithoutNpm : this.names; for (const name of new Set(names)) { if (!isSupportedPackageManager(name)) @@ -23501,9 +23657,9 @@ var DisableCommand = class extends Command { } } async removePosixLink(installDirectory, binName) { - const file = import_path4.default.join(installDirectory, binName); + const file = import_path5.default.join(installDirectory, binName); try { - await import_fs5.default.promises.unlink(file); + await import_fs6.default.promises.unlink(file); } catch (err) { if (err.code !== `ENOENT`) { throw err; @@ -23512,9 +23668,9 @@ var DisableCommand = class extends Command { } async removeWin32Link(installDirectory, binName) { for (const ext of [``, `.ps1`, `.cmd`]) { - const file = import_path4.default.join(installDirectory, `${binName}${ext}`); + const file = import_path5.default.join(installDirectory, `${binName}${ext}`); try { - await import_fs5.default.promises.unlink(file); + await import_fs6.default.promises.unlink(file); } catch (err) { if (err.code !== `ENOENT`) { throw err; @@ -23526,8 +23682,8 @@ var DisableCommand = class extends Command { // sources/commands/Enable.ts var import_cmd_shim = __toESM(require_cmd_shim()); -var import_fs6 = __toESM(require("fs")); -var import_path5 = __toESM(require("path")); +var import_fs7 = __toESM(require("fs")); +var import_path6 = __toESM(require("path")); var import_which2 = __toESM(require_lib()); var EnableCommand = class extends Command { static paths = [ @@ -23558,11 +23714,11 @@ var EnableCommand = class extends Command { async execute() { let installDirectory = this.installDirectory; if (typeof installDirectory === `undefined`) - installDirectory = import_path5.default.dirname(await (0, import_which2.default)(`corepack`)); - installDirectory = import_fs6.default.realpathSync(installDirectory); + installDirectory = import_path6.default.dirname(await (0, import_which2.default)(`corepack`)); + installDirectory = import_fs7.default.realpathSync(installDirectory); const manifestPath = require.resolve("corepack/package.json"); - const distFolder = import_path5.default.join(import_path5.default.dirname(manifestPath), `dist`); - if (!import_fs6.default.existsSync(distFolder)) + const distFolder = import_path6.default.join(import_path6.default.dirname(manifestPath), `dist`); + if (!import_fs7.default.existsSync(distFolder)) throw new Error(`Assertion failed: The stub folder doesn't exist`); const names = this.names.length === 0 ? SupportedPackageManagerSetWithoutNpm : this.names; for (const name of new Set(names)) { @@ -23578,173 +23734,29 @@ var EnableCommand = class extends Command { } } async generatePosixLink(installDirectory, distFolder, binName) { - const file = import_path5.default.join(installDirectory, binName); - const symlink = import_path5.default.relative(installDirectory, import_path5.default.join(distFolder, `${binName}.js`)); - if (import_fs6.default.existsSync(file)) { - const currentSymlink = await import_fs6.default.promises.readlink(file); + const file = import_path6.default.join(installDirectory, binName); + const symlink = import_path6.default.relative(installDirectory, import_path6.default.join(distFolder, `${binName}.js`)); + if (import_fs7.default.existsSync(file)) { + const currentSymlink = await import_fs7.default.promises.readlink(file); if (currentSymlink !== symlink) { - await import_fs6.default.promises.unlink(file); + await import_fs7.default.promises.unlink(file); } else { return; } } - await import_fs6.default.promises.symlink(symlink, file); + await import_fs7.default.promises.symlink(symlink, file); } async generateWin32Link(installDirectory, distFolder, binName) { - const file = import_path5.default.join(installDirectory, binName); - await (0, import_cmd_shim.default)(import_path5.default.join(distFolder, `${binName}.js`), file, { + const file = import_path6.default.join(installDirectory, binName); + await (0, import_cmd_shim.default)(import_path6.default.join(distFolder, `${binName}.js`), file, { createCmdFile: true }); } }; // sources/commands/InstallGlobal.ts -var import_fs9 = __toESM(require("fs")); -var import_path7 = __toESM(require("path")); - -// sources/specUtils.ts -var import_fs7 = __toESM(require("fs")); -var import_path6 = __toESM(require("path")); -var import_semver4 = __toESM(require_semver2()); -var nodeModulesRegExp = /[\\/]node_modules[\\/](@[^\\/]*[\\/])?([^@\\/][^\\/]*)$/; -function parseSpec(raw, source, { enforceExactVersion = true } = {}) { - if (typeof raw !== `string`) - throw new UsageError(`Invalid package manager specification in ${source}; expected a string`); - const atIndex = raw.indexOf(`@`); - if (atIndex === -1 || atIndex === raw.length - 1) { - if (enforceExactVersion) - throw new UsageError(`No version specified for ${raw} in "packageManager" of ${source}`); - const name2 = atIndex === -1 ? raw : raw.slice(0, -1); - if (!isSupportedPackageManager(name2)) - throw new UsageError(`Unsupported package manager specification (${name2})`); - return { - name: name2, - range: `*` - }; - } - const name = raw.slice(0, atIndex); - const range = raw.slice(atIndex + 1); - const isURL = URL.canParse(range); - if (!isURL) { - if (enforceExactVersion && !import_semver4.default.valid(range)) - throw new UsageError(`Invalid package manager specification in ${source} (${raw}); expected a semver version${enforceExactVersion ? `` : `, range, or tag`}`); - if (!isSupportedPackageManager(name)) { - throw new UsageError(`Unsupported package manager specification (${raw})`); - } - } else if (isSupportedPackageManager(name) && process.env.COREPACK_ENABLE_UNSAFE_CUSTOM_URLS !== `1`) { - throw new UsageError(`Illegal use of URL for known package manager. Instead, select a specific version, or set COREPACK_ENABLE_UNSAFE_CUSTOM_URLS=1 in your environment (${raw})`); - } - return { - name, - range - }; -} -async function findProjectSpec(initialCwd, locator, { transparent = false } = {}) { - const fallbackLocator = { name: locator.name, range: `${locator.reference}` }; - if (process.env.COREPACK_ENABLE_PROJECT_SPEC === `0`) - return fallbackLocator; - if (process.env.COREPACK_ENABLE_STRICT === `0`) - transparent = true; - while (true) { - const result = await loadSpec(initialCwd); - switch (result.type) { - case `NoProject`: - case `NoSpec`: { - return fallbackLocator; - } - case `Found`: { - if (result.spec.name !== locator.name) { - if (transparent) { - return fallbackLocator; - } else { - throw new UsageError(`This project is configured to use ${result.spec.name}`); - } - } else { - return result.spec; - } - } - } - } -} -async function loadSpec(initialCwd) { - let nextCwd = initialCwd; - let currCwd = ``; - let selection = null; - while (nextCwd !== currCwd && (!selection || !selection.data.packageManager)) { - currCwd = nextCwd; - nextCwd = import_path6.default.dirname(currCwd); - if (nodeModulesRegExp.test(currCwd)) - continue; - const manifestPath = import_path6.default.join(currCwd, `package.json`); - let content; - try { - content = await import_fs7.default.promises.readFile(manifestPath, `utf8`); - } catch (err) { - if (err?.code === `ENOENT`) - continue; - throw err; - } - let data; - try { - data = JSON.parse(content); - } catch { - } - if (typeof data !== `object` || data === null) - throw new UsageError(`Invalid package.json in ${import_path6.default.relative(initialCwd, manifestPath)}`); - selection = { data, manifestPath }; - } - if (selection === null) - return { type: `NoProject`, target: import_path6.default.join(initialCwd, `package.json`) }; - const rawPmSpec = selection.data.packageManager; - if (typeof rawPmSpec === `undefined`) - return { type: `NoSpec`, target: selection.manifestPath }; - return { - type: `Found`, - target: selection.manifestPath, - spec: parseSpec(rawPmSpec, import_path6.default.relative(initialCwd, selection.manifestPath)) - }; -} - -// sources/commands/Base.ts var import_fs8 = __toESM(require("fs")); - -// sources/nodeUtils.ts -var import_os2 = __toESM(require("os")); -function getEndOfLine(content) { - const matches = content.match(/\r?\n/g); - if (matches === null) - return import_os2.default.EOL; - const crlf = matches.filter((nl) => nl === `\r -`).length; - const lf = matches.length - crlf; - return crlf > lf ? `\r -` : ` -`; -} -function normalizeLineEndings(originalContent, newContent) { - return newContent.replace(/\r?\n/g, getEndOfLine(originalContent)); -} -function getIndent(content) { - const indentMatch = content.match(/^[ \t]+/m); - if (indentMatch) { - return indentMatch[0]; - } else { - return ` `; - } -} -function stripBOM(content) { - if (content.charCodeAt(0) === 65279) { - return content.slice(1); - } else { - return content; - } -} -function readPackageJson(content) { - return { - data: JSON.parse(stripBOM(content) || `{}`), - indent: getIndent(content) - }; -} +var import_path7 = __toESM(require("path")); // sources/commands/Base.ts var BaseCommand = class extends Command { @@ -23764,15 +23776,10 @@ var BaseCommand = class extends Command { } return resolvedSpecs; } - async setLocalPackageManager(info) { - const lookup = await loadSpec(this.context.cwd); - const content = lookup.type !== `NoProject` ? await import_fs8.default.promises.readFile(lookup.target, `utf8`) : ``; - const { data, indent } = readPackageJson(content); - const previousPackageManager = data.packageManager ?? `unknown`; - data.packageManager = `${info.locator.name}@${info.locator.reference}+${info.hash}`; - const newContent = normalizeLineEndings(content, `${JSON.stringify(data, null, indent)} -`); - await import_fs8.default.promises.writeFile(lookup.target, newContent, `utf8`); + async setAndInstallLocalPackageManager(info) { + const { + previousPackageManager + } = await setLocalPackageManager(this.context.cwd, info); const command = this.context.engine.getPackageManagerSpecFor(info.locator).commands?.use ?? null; if (command === null) return 0; @@ -23866,7 +23873,7 @@ var InstallGlobalCommand = class extends BaseCommand { if (!isSupportedPackageManager(name)) throw new UsageError(`Unsupported package manager '${name}'`); this.log({ name, reference }); - await import_fs9.default.promises.mkdir(installFolder, { recursive: true }); + await import_fs8.default.promises.mkdir(installFolder, { recursive: true }); await tar.x({ file: p, cwd: installFolder }, [`${name}/${reference}`]); if (!this.cacheOnly) { await this.context.engine.activatePackageManager({ name, reference }); @@ -24009,7 +24016,7 @@ var UpCommand = class extends BaseCommand { this.context.stdout.write(`Installing ${highestVersion.name}@${highestVersion.reference} in the project... `); const packageManagerInfo = await this.context.engine.ensurePackageManager(highestVersion); - await this.setLocalPackageManager(packageManagerInfo); + await this.setAndInstallLocalPackageManager(packageManagerInfo); } }; @@ -24041,7 +24048,7 @@ var UseCommand = class extends BaseCommand { this.context.stdout.write(`Installing ${resolved.name}@${resolved.reference} in the project... `); const packageManagerInfo = await this.context.engine.ensurePackageManager(resolved); - await this.setLocalPackageManager(packageManagerInfo); + await this.setAndInstallLocalPackageManager(packageManagerInfo); } }; @@ -24173,22 +24180,15 @@ var PrepareCommand = class extends Command { } }; -// sources/miscUtils.ts -var Cancellation = class extends Error { - constructor() { - super(`Cancelled operation`); - } -}; - // sources/main.ts -function getPackageManagerRequestFromCli(parameter, context) { +function getPackageManagerRequestFromCli(parameter, engine) { if (!parameter) return null; const match = parameter.match(/^([^@]*)(?:@(.*))?$/); if (!match) return null; const [, binaryName, binaryVersion] = match; - const packageManager = context.engine.getPackageManagerFor(binaryName); + const packageManager = engine.getPackageManagerFor(binaryName); if (packageManager == null && binaryVersion == null) return null; return { @@ -24197,54 +24197,10 @@ function getPackageManagerRequestFromCli(parameter, context) { binaryVersion: binaryVersion || null }; } -async function executePackageManagerRequest({ packageManager, binaryName, binaryVersion }, args, context) { - let fallbackLocator = { - name: binaryName, - reference: void 0 - }; - let isTransparentCommand = false; - if (packageManager != null) { - const defaultVersion = await context.engine.getDefaultVersion(packageManager); - const definition = context.engine.config.definitions[packageManager]; - for (const transparentPath of definition.transparent.commands) { - if (transparentPath[0] === binaryName && transparentPath.slice(1).every((segment, index) => segment === args[index])) { - isTransparentCommand = true; - break; - } - } - const fallbackReference = isTransparentCommand ? definition.transparent.default ?? defaultVersion : defaultVersion; - fallbackLocator = { - name: packageManager, - reference: fallbackReference - }; - } - let descriptor; - try { - descriptor = await findProjectSpec(context.cwd, fallbackLocator, { transparent: isTransparentCommand }); - } catch (err) { - if (err instanceof Cancellation) { - return 1; - } else { - throw err; - } - } - if (binaryVersion) - descriptor.range = binaryVersion; - const resolved = await context.engine.resolveDescriptor(descriptor, { allowTags: true }); - if (resolved === null) - throw new UsageError(`Failed to successfully resolve '${descriptor.range}' to a valid ${descriptor.name} release`); - const installSpec = await context.engine.ensurePackageManager(resolved); - return await runVersion(resolved, installSpec, binaryName, args); -} async function runMain(argv) { - const context = { - ...Cli.defaultContext, - cwd: process.cwd(), - engine: new Engine() - }; + const engine = new Engine(); const [firstArg, ...restArgs] = argv; - const request = getPackageManagerRequestFromCli(firstArg, context); - let code; + const request = getPackageManagerRequestFromCli(firstArg, engine); if (!request) { const cli = new Cli({ binaryLabel: `Corepack`, @@ -24263,23 +24219,20 @@ async function runMain(argv) { cli.register(UseCommand); cli.register(HydrateCommand); cli.register(PrepareCommand); - code = await cli.run(argv, context); + const context = { + ...Cli.defaultContext, + cwd: process.cwd(), + engine + }; + const code = await cli.run(argv, context); + if (code !== 0) { + process.exitCode ??= code; + } } else { - const cli = new Cli({ - binaryLabel: `'${request.binaryName}', via Corepack`, - binaryName: request.binaryName, - binaryVersion: `corepack/${version}` - }); - cli.register(class BinaryCommand extends Command { - proxy = options_exports.Proxy(); - async execute() { - return executePackageManagerRequest(request, this.proxy, this.context); - } + await engine.executePackageManagerRequest(request, { + cwd: process.cwd(), + args: restArgs }); - code = await cli.run(restArgs, context); - } - if (code !== 0) { - process.exitCode ??= code; } } // Annotate the CommonJS export names for ESM import in node: @@ -24288,7 +24241,7 @@ async function runMain(argv) { }); /*! Bundled license information: -undici/lib/fetch/body.js: +undici/lib/web/fetch/body.js: (*! formdata-polyfill. MIT License. Jimmy Wärting *) is-windows/index.js: diff --git a/deps/corepack/package.json b/deps/corepack/package.json index 391eb749c82d65..5ca045e37041e0 100644 --- a/deps/corepack/package.json +++ b/deps/corepack/package.json @@ -1,6 +1,6 @@ { "name": "corepack", - "version": "0.25.2", + "version": "0.28.0", "homepage": "https://github.com/nodejs/corepack#readme", "bugs": { "url": "https://github.com/nodejs/corepack/issues" @@ -16,7 +16,7 @@ "./package.json": "./package.json" }, "license": "MIT", - "packageManager": "yarn@4.1.0+sha224.bc24d7f5afc738464f3d4e95f4e6e7829a35cee54a0fd527ea5baa83", + "packageManager": "yarn@4.1.1+sha224.00f08619463229f8ba40c4ee90e8c2e4ced1f11c3115c26f3b98432e", "devDependencies": { "@babel/core": "^7.14.3", "@babel/plugin-transform-modules-commonjs": "^7.14.0", @@ -35,6 +35,7 @@ "@yarnpkg/fslib": "^3.0.0-rc.48", "@zkochan/cmd-shim": "^6.0.0", "babel-plugin-dynamic-import-node": "^2.3.3", + "better-sqlite3": "^9.4.1", "clipanion": "^3.0.1", "debug": "^4.1.1", "esbuild": "0.19.5", @@ -44,13 +45,16 @@ "proxy-from-env": "^1.1.0", "semver": "^7.5.2", "supports-color": "^9.0.0", - "tar": "^6.0.1", + "tar": "^6.2.1", "ts-node": "^10.0.0", - "typescript": "^5.0.4", + "typescript": "^5.3.3", "undici": "^6.6.1", "v8-compile-cache": "^2.3.0", "which": "^4.0.0" }, + "resolutions": { + "undici-types": "6.x" + }, "scripts": { "build": "rm -rf dist shims && run build:bundle && ts-node ./mkshims.ts", "build:bundle": "esbuild ./sources/_lib.ts --bundle --platform=node --target=node18.17.0 --external:corepack --outfile='./dist/lib/corepack.cjs' --resolve-extensions='.ts,.mjs,.js'", diff --git a/deps/nghttp2/lib/CMakeLists.txt b/deps/nghttp2/lib/CMakeLists.txt index 7adba3a3ffa2da..fda8dcb7fc7f2a 100644 --- a/deps/nghttp2/lib/CMakeLists.txt +++ b/deps/nghttp2/lib/CMakeLists.txt @@ -14,7 +14,7 @@ set(NGHTTP2_SOURCES nghttp2_stream.c nghttp2_outbound_item.c nghttp2_session.c nghttp2_submit.c nghttp2_helper.c - nghttp2_npn.c + nghttp2_alpn.c nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c nghttp2_version.c nghttp2_priority_spec.c @@ -31,6 +31,12 @@ set(NGHTTP2_SOURCES ) set(NGHTTP2_RES "") +set(STATIC_LIB "nghttp2_static") +set(SHARED_LIB "nghttp2") + +if(BUILD_SHARED_LIBS AND BUILD_STATIC_LIBS AND MSVC AND NOT STATIC_LIB_SUFFIX) + set(STATIC_LIB_SUFFIX "_static") +endif() if(WIN32) configure_file( @@ -41,40 +47,61 @@ if(WIN32) set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc) endif() +set(EXPORT_SET "${PROJECT_NAME}-targets") + # Public shared library -if(ENABLE_SHARED_LIB) - add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES}) - set_target_properties(nghttp2 PROPERTIES +if(BUILD_SHARED_LIBS) + add_library(${SHARED_LIB} SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES}) + + set_target_properties(${SHARED_LIB} PROPERTIES COMPILE_FLAGS "${WARNCFLAGS}" VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION} C_VISIBILITY_PRESET hidden ) - target_include_directories(nghttp2 INTERFACE - "${CMAKE_CURRENT_BINARY_DIR}/includes" - "${CMAKE_CURRENT_SOURCE_DIR}/includes" + + target_include_directories(${SHARED_LIB} INTERFACE + $ + $ + $ ) - install(TARGETS nghttp2 - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") + install(TARGETS ${SHARED_LIB} EXPORT ${EXPORT_SET}) + list(APPEND nghttp2_exports ${SHARED_LIB}) endif() -if(HAVE_CUNIT OR ENABLE_STATIC_LIB) - # Static library (for unittests because of symbol visibility) - add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES}) - set_target_properties(nghttp2_static PROPERTIES +# Static library (for unittests because of symbol visibility) +if(BUILD_STATIC_LIBS) + add_library(${STATIC_LIB} STATIC ${NGHTTP2_SOURCES}) + + set_target_properties(${STATIC_LIB} PROPERTIES COMPILE_FLAGS "${WARNCFLAGS}" VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION} ARCHIVE_OUTPUT_NAME nghttp2${STATIC_LIB_SUFFIX} ) - target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB") - if(ENABLE_STATIC_LIB) - install(TARGETS nghttp2_static - DESTINATION "${CMAKE_INSTALL_LIBDIR}") - endif() + + target_include_directories(${STATIC_LIB} INTERFACE + $ + $ + $ + ) + + target_compile_definitions(${STATIC_LIB} PUBLIC "-DNGHTTP2_STATICLIB") + + install(TARGETS ${STATIC_LIB} EXPORT ${EXPORT_SET}) + list(APPEND nghttp2_exports ${STATIC_LIB}) endif() +if(BUILD_SHARED_LIBS) + set(LIB_SELECTED ${SHARED_LIB}) +else() + set(LIB_SELECTED ${STATIC_LIB}) +endif() + +add_library(${PROJECT_NAME}::nghttp2 ALIAS ${LIB_SELECTED}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + +install(EXPORT ${EXPORT_SET} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + NAMESPACE ${PROJECT_NAME}::) diff --git a/deps/nghttp2/lib/Makefile.am b/deps/nghttp2/lib/Makefile.am index c3ace4029a69b8..1168c1e6135661 100644 --- a/deps/nghttp2/lib/Makefile.am +++ b/deps/nghttp2/lib/Makefile.am @@ -41,7 +41,7 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \ nghttp2_stream.c nghttp2_outbound_item.c \ nghttp2_session.c nghttp2_submit.c \ nghttp2_helper.c \ - nghttp2_npn.c \ + nghttp2_alpn.c \ nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \ nghttp2_version.c \ nghttp2_priority_spec.c \ @@ -60,7 +60,7 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ nghttp2_frame.h \ nghttp2_buf.h \ nghttp2_session.h nghttp2_helper.h nghttp2_stream.h nghttp2_int.h \ - nghttp2_npn.h \ + nghttp2_alpn.h \ nghttp2_submit.h nghttp2_outbound_item.h \ nghttp2_net.h \ nghttp2_hd.h nghttp2_hd_huffman.h \ diff --git a/deps/nghttp2/lib/Makefile.in b/deps/nghttp2/lib/Makefile.in index 0b95613bc21808..a5653128884f26 100644 --- a/deps/nghttp2/lib/Makefile.in +++ b/deps/nghttp2/lib/Makefile.in @@ -153,7 +153,7 @@ am__objects_1 = am__objects_2 = nghttp2_pq.lo nghttp2_map.lo nghttp2_queue.lo \ nghttp2_frame.lo nghttp2_buf.lo nghttp2_stream.lo \ nghttp2_outbound_item.lo nghttp2_session.lo nghttp2_submit.lo \ - nghttp2_helper.lo nghttp2_npn.lo nghttp2_hd.lo \ + nghttp2_helper.lo nghttp2_alpn.lo nghttp2_hd.lo \ nghttp2_hd_huffman.lo nghttp2_hd_huffman_data.lo \ nghttp2_version.lo nghttp2_priority_spec.lo nghttp2_option.lo \ nghttp2_callbacks.lo nghttp2_mem.lo nghttp2_http.lo \ @@ -183,15 +183,15 @@ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles -am__depfiles_remade = ./$(DEPDIR)/nghttp2_buf.Plo \ - ./$(DEPDIR)/nghttp2_callbacks.Plo \ +am__depfiles_remade = ./$(DEPDIR)/nghttp2_alpn.Plo \ + ./$(DEPDIR)/nghttp2_buf.Plo ./$(DEPDIR)/nghttp2_callbacks.Plo \ ./$(DEPDIR)/nghttp2_debug.Plo ./$(DEPDIR)/nghttp2_extpri.Plo \ ./$(DEPDIR)/nghttp2_frame.Plo ./$(DEPDIR)/nghttp2_hd.Plo \ ./$(DEPDIR)/nghttp2_hd_huffman.Plo \ ./$(DEPDIR)/nghttp2_hd_huffman_data.Plo \ ./$(DEPDIR)/nghttp2_helper.Plo ./$(DEPDIR)/nghttp2_http.Plo \ ./$(DEPDIR)/nghttp2_map.Plo ./$(DEPDIR)/nghttp2_mem.Plo \ - ./$(DEPDIR)/nghttp2_npn.Plo ./$(DEPDIR)/nghttp2_option.Plo \ + ./$(DEPDIR)/nghttp2_option.Plo \ ./$(DEPDIR)/nghttp2_outbound_item.Plo \ ./$(DEPDIR)/nghttp2_pq.Plo \ ./$(DEPDIR)/nghttp2_priority_spec.Plo \ @@ -306,8 +306,6 @@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ -CUNIT_CFLAGS = @CUNIT_CFLAGS@ -CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ @@ -329,7 +327,6 @@ EXTRABPFCFLAGS = @EXTRABPFCFLAGS@ EXTRACFLAG = @EXTRACFLAG@ EXTRA_DEFS = @EXTRA_DEFS@ FGREP = @FGREP@ -FILECMD = @FILECMD@ GREP = @GREP@ HAVE_CXX14 = @HAVE_CXX14@ INSTALL = @INSTALL@ @@ -345,6 +342,10 @@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBBPF_CFLAGS = @LIBBPF_CFLAGS@ LIBBPF_LIBS = @LIBBPF_LIBS@ +LIBBROTLIDEC_CFLAGS = @LIBBROTLIDEC_CFLAGS@ +LIBBROTLIDEC_LIBS = @LIBBROTLIDEC_LIBS@ +LIBBROTLIENC_CFLAGS = @LIBBROTLIENC_CFLAGS@ +LIBBROTLIENC_LIBS = @LIBBROTLIENC_LIBS@ LIBCARES_CFLAGS = @LIBCARES_CFLAGS@ LIBCARES_LIBS = @LIBCARES_LIBS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ @@ -502,7 +503,7 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \ nghttp2_stream.c nghttp2_outbound_item.c \ nghttp2_session.c nghttp2_submit.c \ nghttp2_helper.c \ - nghttp2_npn.c \ + nghttp2_alpn.c \ nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \ nghttp2_version.c \ nghttp2_priority_spec.c \ @@ -521,7 +522,7 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ nghttp2_frame.h \ nghttp2_buf.h \ nghttp2_session.h nghttp2_helper.h nghttp2_stream.h nghttp2_int.h \ - nghttp2_npn.h \ + nghttp2_alpn.h \ nghttp2_submit.h nghttp2_outbound_item.h \ nghttp2_net.h \ nghttp2_hd.h nghttp2_hd_huffman.h \ @@ -621,6 +622,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_alpn.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_buf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_callbacks.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_debug.Plo@am__quote@ # am--include-marker @@ -633,7 +635,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_http.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_map.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_mem.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_npn.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_option.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_outbound_item.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_pq.Plo@am__quote@ # am--include-marker @@ -906,7 +907,8 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-recursive - -rm -f ./$(DEPDIR)/nghttp2_buf.Plo + -rm -f ./$(DEPDIR)/nghttp2_alpn.Plo + -rm -f ./$(DEPDIR)/nghttp2_buf.Plo -rm -f ./$(DEPDIR)/nghttp2_callbacks.Plo -rm -f ./$(DEPDIR)/nghttp2_debug.Plo -rm -f ./$(DEPDIR)/nghttp2_extpri.Plo @@ -918,7 +920,6 @@ distclean: distclean-recursive -rm -f ./$(DEPDIR)/nghttp2_http.Plo -rm -f ./$(DEPDIR)/nghttp2_map.Plo -rm -f ./$(DEPDIR)/nghttp2_mem.Plo - -rm -f ./$(DEPDIR)/nghttp2_npn.Plo -rm -f ./$(DEPDIR)/nghttp2_option.Plo -rm -f ./$(DEPDIR)/nghttp2_outbound_item.Plo -rm -f ./$(DEPDIR)/nghttp2_pq.Plo @@ -977,7 +978,8 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive - -rm -f ./$(DEPDIR)/nghttp2_buf.Plo + -rm -f ./$(DEPDIR)/nghttp2_alpn.Plo + -rm -f ./$(DEPDIR)/nghttp2_buf.Plo -rm -f ./$(DEPDIR)/nghttp2_callbacks.Plo -rm -f ./$(DEPDIR)/nghttp2_debug.Plo -rm -f ./$(DEPDIR)/nghttp2_extpri.Plo @@ -989,7 +991,6 @@ maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/nghttp2_http.Plo -rm -f ./$(DEPDIR)/nghttp2_map.Plo -rm -f ./$(DEPDIR)/nghttp2_mem.Plo - -rm -f ./$(DEPDIR)/nghttp2_npn.Plo -rm -f ./$(DEPDIR)/nghttp2_option.Plo -rm -f ./$(DEPDIR)/nghttp2_outbound_item.Plo -rm -f ./$(DEPDIR)/nghttp2_pq.Plo diff --git a/deps/nghttp2/lib/Makefile.msvc b/deps/nghttp2/lib/Makefile.msvc index 611b39d0b1d95e..752389e0fc485a 100644 --- a/deps/nghttp2/lib/Makefile.msvc +++ b/deps/nghttp2/lib/Makefile.msvc @@ -74,7 +74,7 @@ NGHTTP2_SRC := nghttp2_pq.c \ nghttp2_session.c \ nghttp2_submit.c \ nghttp2_helper.c \ - nghttp2_npn.c \ + nghttp2_alpn.c \ nghttp2_hd.c \ nghttp2_hd_huffman.c \ nghttp2_hd_huffman_data.c \ diff --git a/deps/nghttp2/lib/includes/Makefile.in b/deps/nghttp2/lib/includes/Makefile.in index 3de90d7bef3e3a..47f46764652434 100644 --- a/deps/nghttp2/lib/includes/Makefile.in +++ b/deps/nghttp2/lib/includes/Makefile.in @@ -211,8 +211,6 @@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ -CUNIT_CFLAGS = @CUNIT_CFLAGS@ -CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ @@ -234,7 +232,6 @@ EXTRABPFCFLAGS = @EXTRABPFCFLAGS@ EXTRACFLAG = @EXTRACFLAG@ EXTRA_DEFS = @EXTRA_DEFS@ FGREP = @FGREP@ -FILECMD = @FILECMD@ GREP = @GREP@ HAVE_CXX14 = @HAVE_CXX14@ INSTALL = @INSTALL@ @@ -250,6 +247,10 @@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBBPF_CFLAGS = @LIBBPF_CFLAGS@ LIBBPF_LIBS = @LIBBPF_LIBS@ +LIBBROTLIDEC_CFLAGS = @LIBBROTLIDEC_CFLAGS@ +LIBBROTLIDEC_LIBS = @LIBBROTLIDEC_LIBS@ +LIBBROTLIENC_CFLAGS = @LIBBROTLIENC_CFLAGS@ +LIBBROTLIENC_LIBS = @LIBBROTLIENC_LIBS@ LIBCARES_CFLAGS = @LIBCARES_CFLAGS@ LIBCARES_LIBS = @LIBCARES_LIBS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h index fa22081c517497..92c3ccc6e4855a 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h @@ -51,6 +51,7 @@ extern "C" { #endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ #include #include +#include #include @@ -71,6 +72,13 @@ extern "C" { # endif /* !BUILDING_NGHTTP2 */ #endif /* !defined(WIN32) */ +/** + * @typedef + * + * :type:`nghttp2_ssize` is a signed counterpart of size_t. + */ +typedef ptrdiff_t nghttp2_ssize; + /** * @macro * @@ -168,6 +176,12 @@ typedef struct { /** * @macro * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The default weight of stream dependency. */ #define NGHTTP2_DEFAULT_WEIGHT 16 @@ -175,6 +189,12 @@ typedef struct { /** * @macro * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The maximum weight of stream dependency. */ #define NGHTTP2_MAX_WEIGHT 256 @@ -182,6 +202,12 @@ typedef struct { /** * @macro * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The minimum weight of stream dependency. */ #define NGHTTP2_MIN_WEIGHT 1 @@ -255,7 +281,7 @@ typedef enum { */ NGHTTP2_ERR_UNSUPPORTED_VERSION = -503, /** - * Used as a return value from :type:`nghttp2_send_callback`, + * Used as a return value from :type:`nghttp2_send_callback2`, * :type:`nghttp2_recv_callback` and * :type:`nghttp2_send_data_callback` to indicate that the operation * would block. @@ -275,9 +301,9 @@ typedef enum { NGHTTP2_ERR_EOF = -507, /** * Used as a return value from - * :func:`nghttp2_data_source_read_callback` to indicate that data + * :func:`nghttp2_data_source_read_callback2` to indicate that data * transfer is postponed. See - * :func:`nghttp2_data_source_read_callback` for details. + * :func:`nghttp2_data_source_read_callback2` for details. */ NGHTTP2_ERR_DEFERRED = -508, /** @@ -440,7 +466,12 @@ typedef enum { * exhaustion on server side to send these frames forever and does * not read network. */ - NGHTTP2_ERR_FLOODED = -904 + NGHTTP2_ERR_FLOODED = -904, + /** + * When a local endpoint receives too many CONTINUATION frames + * following a HEADER frame. + */ + NGHTTP2_ERR_TOO_MANY_CONTINUATIONS = -905, } nghttp2_error; /** @@ -830,7 +861,7 @@ typedef struct { * @union * * This union represents the some kind of data source passed to - * :type:`nghttp2_data_source_read_callback`. + * :type:`nghttp2_data_source_read_callback2`. */ typedef union { /** @@ -847,7 +878,7 @@ typedef union { * @enum * * The flags used to set in |data_flags| output parameter in - * :type:`nghttp2_data_source_read_callback`. + * :type:`nghttp2_data_source_read_callback2`. */ typedef enum { /** @@ -861,8 +892,8 @@ typedef enum { /** * Indicates that END_STREAM flag must not be set even if * NGHTTP2_DATA_FLAG_EOF is set. Usually this flag is used to send - * trailer fields with `nghttp2_submit_request()` or - * `nghttp2_submit_response()`. + * trailer fields with `nghttp2_submit_request2()` or + * `nghttp2_submit_response2()`. */ NGHTTP2_DATA_FLAG_NO_END_STREAM = 0x02, /** @@ -872,9 +903,15 @@ typedef enum { NGHTTP2_DATA_FLAG_NO_COPY = 0x04 } nghttp2_data_flag; +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_data_source_read_callback2` + * instead. + * * Callback function invoked when the library wants to read data from * the |source|. The read data is sent in the stream |stream_id|. * The implementation of this function must read at most |length| @@ -939,9 +976,83 @@ typedef ssize_t (*nghttp2_data_source_read_callback)( nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when the library wants to read data from + * the |source|. The read data is sent in the stream |stream_id|. + * The implementation of this function must read at most |length| + * bytes of data from |source| (or possibly other places) and store + * them in |buf| and return number of data stored in |buf|. If EOF is + * reached, set :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_EOF` flag + * in |*data_flags|. + * + * Sometime it is desirable to avoid copying data into |buf| and let + * application to send data directly. To achieve this, set + * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_COPY` to + * |*data_flags| (and possibly other flags, just like when we do + * copy), and return the number of bytes to send without copying data + * into |buf|. The library, seeing + * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_COPY`, will invoke + * :type:`nghttp2_send_data_callback`. The application must send + * complete DATA frame in that callback. + * + * If this callback is set by `nghttp2_submit_request2()`, + * `nghttp2_submit_response2()` or `nghttp2_submit_headers()` and + * `nghttp2_submit_data2()` with flag parameter + * :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM` set, and + * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_EOF` flag is set to + * |*data_flags|, DATA frame will have END_STREAM flag set. Usually, + * this is expected behaviour and all are fine. One exception is send + * trailer fields. You cannot send trailer fields after sending frame + * with END_STREAM set. To avoid this problem, one can set + * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_END_STREAM` along + * with :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_EOF` to signal the + * library not to set END_STREAM in DATA frame. Then application can + * use `nghttp2_submit_trailer()` to send trailer fields. + * `nghttp2_submit_trailer()` can be called inside this callback. + * + * If the application wants to postpone DATA frames (e.g., + * asynchronous I/O, or reading data blocks for long time), it is + * achieved by returning :enum:`nghttp2_error.NGHTTP2_ERR_DEFERRED` + * without reading any data in this invocation. The library removes + * DATA frame from the outgoing queue temporarily. To move back + * deferred DATA frame to outgoing queue, call + * `nghttp2_session_resume_data()`. + * + * By default, |length| is limited to 16KiB at maximum. If peer + * allows larger frames, application can enlarge transmission buffer + * size. See :type:`nghttp2_data_source_read_length_callback` for + * more details. + * + * If the application just wants to return from + * `nghttp2_session_send()` or `nghttp2_session_mem_send2()` without + * sending anything, return :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE`. + * + * In case of error, there are 2 choices. Returning + * :enum:`nghttp2_error.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will + * close the stream by issuing RST_STREAM with + * :enum:`nghttp2_error_code.NGHTTP2_INTERNAL_ERROR`. If a different + * error code is desirable, use `nghttp2_submit_rst_stream()` with a + * desired error code and then return + * :enum:`nghttp2_error.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. + * Returning :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` will + * signal the entire session failure. + */ +typedef nghttp2_ssize (*nghttp2_data_source_read_callback2)( + nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, + uint32_t *data_flags, nghttp2_data_source *source, void *user_data); + +#ifndef NGHTTP2_NO_SSIZE_T /** * @struct * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_data_provider2` instead. + * * This struct represents the data source and the way to read a chunk * of data from it. */ @@ -956,6 +1067,25 @@ typedef struct { nghttp2_data_source_read_callback read_callback; } nghttp2_data_provider; +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @struct + * + * This struct represents the data source and the way to read a chunk + * of data from it. + */ +typedef struct { + /** + * The data source. + */ + nghttp2_data_source source; + /** + * The callback function to read a chunk of data from the |source|. + */ + nghttp2_data_source_read_callback2 read_callback; +} nghttp2_data_provider2; + /** * @struct * @@ -1008,6 +1138,12 @@ typedef enum { /** * @struct * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The structure to specify stream dependency. */ typedef struct { @@ -1042,6 +1178,12 @@ typedef struct { */ size_t padlen; /** + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The priority specification */ nghttp2_priority_spec pri_spec; @@ -1062,6 +1204,12 @@ typedef struct { /** * @struct * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The PRIORITY frame. It has the following members: */ typedef struct { @@ -1305,9 +1453,14 @@ typedef union { nghttp2_extension ext; } nghttp2_frame; +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_send_callback2` instead. + * * Callback function invoked when |session| wants to send data to the * remote peer. The implementation of this function must send at most * |length| bytes of data stored in |data|. The |flags| is currently @@ -1340,6 +1493,44 @@ typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session, const uint8_t *data, size_t length, int flags, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when |session| wants to send data to the + * remote peer. The implementation of this function must send at most + * |length| bytes of data stored in |data|. The |flags| is currently + * not used and always 0. It must return the number of bytes sent if + * it succeeds. If it cannot send any single byte without blocking, + * it must return :enum:`nghttp2_error.NGHTTP2_ERR_WOULDBLOCK`. For + * other errors, it must return + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. The + * |user_data| pointer is the third argument passed in to the call to + * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. + * + * This callback is required if the application uses + * `nghttp2_session_send()` to send data to the remote endpoint. If + * the application uses solely `nghttp2_session_mem_send2()` instead, + * this callback function is unnecessary. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_send_callback2()`. + * + * .. note:: + * + * The |length| may be very small. If that is the case, and + * application disables Nagle algorithm (``TCP_NODELAY``), then just + * writing |data| to the network stack leads to very small packet, + * and it is very inefficient. An application should be responsible + * to buffer up small chunks of data as necessary to avoid this + * situation. + */ +typedef nghttp2_ssize (*nghttp2_send_callback2)(nghttp2_session *session, + const uint8_t *data, + size_t length, int flags, + void *user_data); + /** * @functypedef * @@ -1370,7 +1561,7 @@ typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session, * error; if partial frame data has already sent, it is impossible to * send another data in that state, and all we can do is tear down * connection). When data is fully processed, but application wants - * to make `nghttp2_session_mem_send()` or `nghttp2_session_send()` + * to make `nghttp2_session_mem_send2()` or `nghttp2_session_send()` * return immediately without processing next frames, return * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE`. If application decided to * reset this stream, return @@ -1387,9 +1578,14 @@ typedef int (*nghttp2_send_data_callback)(nghttp2_session *session, nghttp2_data_source *source, void *user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_recv_callback2` instead. + * * Callback function invoked when |session| wants to receive data from * the remote peer. The implementation of this function must read at * most |length| bytes of data and store it in |buf|. The |flags| is @@ -1417,11 +1613,43 @@ typedef ssize_t (*nghttp2_recv_callback)(nghttp2_session *session, uint8_t *buf, size_t length, int flags, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when |session| wants to receive data from + * the remote peer. The implementation of this function must read at + * most |length| bytes of data and store it in |buf|. The |flags| is + * currently not used and always 0. It must return the number of + * bytes written in |buf| if it succeeds. If it cannot read any + * single byte without blocking, it must return + * :enum:`nghttp2_error.NGHTTP2_ERR_WOULDBLOCK`. If it gets EOF + * before it reads any single byte, it must return + * :enum:`nghttp2_error.NGHTTP2_ERR_EOF`. For other errors, it must + * return :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. + * Returning 0 is treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_WOULDBLOCK`. The |user_data| + * pointer is the third argument passed in to the call to + * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. + * + * This callback is required if the application uses + * `nghttp2_session_recv()` to receive data from the remote endpoint. + * If the application uses solely `nghttp2_session_mem_recv2()` + * instead, this callback function is unnecessary. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_recv_callback2()`. + */ +typedef nghttp2_ssize (*nghttp2_recv_callback2)(nghttp2_session *session, + uint8_t *buf, size_t length, + int flags, void *user_data); + /** * @functypedef * * Callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when a frame is received. The + * `nghttp2_session_mem_recv2()` when a frame is received. The * |user_data| pointer is the third argument passed in to the call to * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. * @@ -1439,8 +1667,8 @@ typedef ssize_t (*nghttp2_recv_callback)(nghttp2_session *session, uint8_t *buf, * * The implementation of this function must return 0 if it succeeds. * If nonzero value is returned, it is treated as fatal error and - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1454,7 +1682,7 @@ typedef int (*nghttp2_on_frame_recv_callback)(nghttp2_session *session, * @functypedef * * Callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is + * `nghttp2_session_mem_recv2()` when an invalid non-DATA frame is * received. The error is indicated by the |lib_error_code|, which is * one of the values defined in :type:`nghttp2_error`. When this * callback function is invoked, the library automatically submits @@ -1468,8 +1696,8 @@ typedef int (*nghttp2_on_frame_recv_callback)(nghttp2_session *session, * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1492,19 +1720,19 @@ typedef int (*nghttp2_on_invalid_frame_recv_callback)( * argument passed in to the call to `nghttp2_session_client_new()` or * `nghttp2_session_server_new()`. * - * If the application uses `nghttp2_session_mem_recv()`, it can return - * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` to make - * `nghttp2_session_mem_recv()` return without processing further + * If the application uses `nghttp2_session_mem_recv2()`, it can + * return :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` to make + * `nghttp2_session_mem_recv2()` return without processing further * input bytes. The memory by pointed by the |data| is retained until - * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is called. - * The application must retain the input bytes which was used to - * produce the |data| parameter, because it may refer to the memory + * `nghttp2_session_mem_recv2()` or `nghttp2_session_recv()` is + * called. The application must retain the input bytes which was used + * to produce the |data| parameter, because it may refer to the memory * region included in the input bytes. * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error, and - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1531,8 +1759,8 @@ typedef int (*nghttp2_on_data_chunk_recv_callback)(nghttp2_session *session, * If there is a fatal error while executing this callback, the * implementation should return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`, which makes - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - * immediately return + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * If the other value is returned, it is treated as if @@ -1556,8 +1784,8 @@ typedef int (*nghttp2_before_frame_send_callback)(nghttp2_session *session, * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - * immediately return + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1579,8 +1807,8 @@ typedef int (*nghttp2_on_frame_send_callback)(nghttp2_session *session, * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - * immediately return + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * `nghttp2_session_get_stream_user_data()` can be used to get @@ -1601,7 +1829,7 @@ typedef int (*nghttp2_on_frame_not_send_callback)(nghttp2_session *session, * The reason of closure is indicated by the |error_code|. The * |error_code| is usually one of :enum:`nghttp2_error_code`, but that * is not guaranteed. The stream_user_data, which was specified in - * `nghttp2_submit_request()` or `nghttp2_submit_headers()`, is still + * `nghttp2_submit_request2()` or `nghttp2_submit_headers()`, is still * available in this function. The |user_data| pointer is the third * argument passed in to the call to `nghttp2_session_client_new()` or * `nghttp2_session_server_new()`. @@ -1610,8 +1838,8 @@ typedef int (*nghttp2_on_frame_not_send_callback)(nghttp2_session *session, * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_recv()`, `nghttp2_session_mem_recv()`, - * `nghttp2_session_send()`, and `nghttp2_session_mem_send()` + * `nghttp2_session_recv()`, `nghttp2_session_mem_recv2()`, + * `nghttp2_session_send()`, and `nghttp2_session_mem_send2()` * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * @@ -1681,7 +1909,7 @@ typedef int (*nghttp2_on_stream_close_callback)(nghttp2_session *session, * value is returned, it is treated as if * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` is returned. If * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` is returned, - * `nghttp2_session_mem_recv()` function will immediately return + * `nghttp2_session_mem_recv2()` function will immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1726,11 +1954,11 @@ typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session, * performs validation based on HTTP Messaging rule, which is briefly * explained in :ref:`http-messaging` section. * - * If the application uses `nghttp2_session_mem_recv()`, it can return - * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` to make - * `nghttp2_session_mem_recv()` return without processing further + * If the application uses `nghttp2_session_mem_recv2()`, it can + * return :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` to make + * `nghttp2_session_mem_recv2()` return without processing further * input bytes. The memory pointed by |frame|, |name| and |value| - * parameters are retained until `nghttp2_session_mem_recv()` or + * parameters are retained until `nghttp2_session_mem_recv2()` or * `nghttp2_session_recv()` is called. The application must retain * the input bytes which was used to produce these parameters, because * it may refer to the memory region included in the input bytes. @@ -1757,8 +1985,8 @@ typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session, * nonzero value is returned, it is treated as * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` is returned, - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1873,9 +2101,15 @@ typedef int (*nghttp2_on_invalid_header_callback2)( nghttp2_session *session, const nghttp2_frame *frame, nghttp2_rcbuf *name, nghttp2_rcbuf *value, uint8_t flags, void *user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_select_padding_callback2` + * instead. + * * Callback function invoked when the library asks application how * many padding bytes are required for the transmission of the * |frame|. The application must choose the total length of payload @@ -1896,9 +2130,39 @@ typedef ssize_t (*nghttp2_select_padding_callback)(nghttp2_session *session, size_t max_payloadlen, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when the library asks application how + * many padding bytes are required for the transmission of the + * |frame|. The application must choose the total length of payload + * including padded bytes in range [frame->hd.length, max_payloadlen], + * inclusive. Choosing number not in this range will be treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. Returning + * ``frame->hd.length`` means no padding is added. Returning + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` will make + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_select_padding_callback2()`. + */ +typedef nghttp2_ssize (*nghttp2_select_padding_callback2)( + nghttp2_session *session, const nghttp2_frame *frame, size_t max_payloadlen, + void *user_data); + +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use + * :type:`nghttp2_data_source_read_length_callback2` instead. + * * Callback function invoked when library wants to get max length of * data to send data to the remote peer. The implementation of this * function should return a value in the following range. [1, @@ -1926,6 +2190,38 @@ typedef ssize_t (*nghttp2_data_source_read_length_callback)( int32_t session_remote_window_size, int32_t stream_remote_window_size, uint32_t remote_max_frame_size, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when library wants to get max length of + * data to send data to the remote peer. The implementation of this + * function should return a value in the following range. [1, + * min(|session_remote_window_size|, |stream_remote_window_size|, + * |remote_max_frame_size|)]. If a value greater than this range is + * returned than the max allow value will be used. Returning a value + * smaller than this range is treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. The + * |frame_type| is provided for future extensibility and identifies + * the type of frame (see :type:`nghttp2_frame_type`) for which to get + * the length for. Currently supported frame types are: + * :enum:`nghttp2_frame_type.NGHTTP2_DATA`. + * + * This callback can be used to control the length in bytes for which + * :type:`nghttp2_data_source_read_callback` is allowed to send to the + * remote endpoint. This callback is optional. Returning + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` will signal the + * entire session failure. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_data_source_read_length_callback2()`. + */ +typedef nghttp2_ssize (*nghttp2_data_source_read_length_callback2)( + nghttp2_session *session, uint8_t frame_type, int32_t stream_id, + int32_t session_remote_window_size, int32_t stream_remote_window_size, + uint32_t remote_max_frame_size, void *user_data); + /** * @functypedef * @@ -1942,8 +2238,8 @@ typedef ssize_t (*nghttp2_data_source_read_length_callback)( * * The implementation of this function must return 0 if it succeeds. * If nonzero value is returned, it is treated as fatal error and - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1967,8 +2263,8 @@ typedef int (*nghttp2_on_begin_frame_callback)(nghttp2_session *session, * * If fatal error occurred, application should return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If the other * values are returned, currently they are treated as * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. @@ -1997,7 +2293,7 @@ typedef int (*nghttp2_on_extension_chunk_recv_callback)( * ``NULL``. The |*payload| is available as ``frame->ext.payload`` in * :type:`nghttp2_on_frame_recv_callback`. Therefore if application * can free that memory inside :type:`nghttp2_on_frame_recv_callback` - * callback. Of course, application has a liberty not ot use + * callback. Of course, application has a liberty not to use * |*payload|, and do its own mechanism to process extension frames. * * To abort processing this extension frame, return @@ -2005,8 +2301,8 @@ typedef int (*nghttp2_on_extension_chunk_recv_callback)( * * If fatal error occurred, application should return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If the other * values are returned, currently they are treated as * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. @@ -2016,9 +2312,15 @@ typedef int (*nghttp2_unpack_extension_callback)(nghttp2_session *session, const nghttp2_frame_hd *hd, void *user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_pack_extension_callback2` + * instead. + * * Callback function invoked when library asks the application to pack * extension payload in its wire format. The frame header will be * packed by library. Application must pack payload only. @@ -2049,18 +2351,53 @@ typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + /** * @functypedef * - * Callback function invoked when library provides the error message + * Callback function invoked when library asks the application to pack + * extension payload in its wire format. The frame header will be + * packed by library. Application must pack payload only. + * ``frame->ext.payload`` is the object passed to + * `nghttp2_submit_extension()` as payload parameter. Application + * must pack extension payload to the |buf| of its capacity |len| + * bytes. The |len| is at least 16KiB. + * + * The implementation of this function should return the number of + * bytes written into |buf| when it succeeds. + * + * To abort processing this extension frame, return + * :enum:`nghttp2_error.NGHTTP2_ERR_CANCEL`, and + * :type:`nghttp2_on_frame_not_send_callback` will be invoked. + * + * If fatal error occurred, application should return + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If the other + * values are returned, currently they are treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If the return + * value is strictly larger than |len|, it is treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. + */ +typedef nghttp2_ssize (*nghttp2_pack_extension_callback2)( + nghttp2_session *session, uint8_t *buf, size_t len, + const nghttp2_frame *frame, void *user_data); + +/** + * @functypedef + * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_error_callback2` instead. + * + * Callback function invoked when library provides the error message * intended for human consumption. This callback is solely for * debugging purpose. The |msg| is typically NULL-terminated string * of length |len|. |len| does not include the sentinel NULL * character. * - * This function is deprecated. The new application should use - * :type:`nghttp2_error_callback2`. - * * The format of error message may change between nghttp2 library * versions. The application should not depend on the particular * format. @@ -2143,9 +2480,15 @@ nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr); NGHTTP2_EXTERN void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_session_callbacks_set_send_callback2()` + * with :type:`nghttp2_send_callback2` instead. + * * Sets callback function invoked when a session wants to send data to * the remote peer. This callback is not necessary if the application * uses solely `nghttp2_session_mem_send()` to serialize data to @@ -2154,9 +2497,28 @@ nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks); NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_callback( nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function invoked when a session wants to send data to + * the remote peer. This callback is not necessary if the application + * uses solely `nghttp2_session_mem_send2()` to serialize data to + * transmit. + */ +NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_callback2( + nghttp2_session_callbacks *cbs, nghttp2_send_callback2 send_callback); + +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_session_callbacks_set_recv_callback2()` + * with :type:`nghttp2_recv_callback2` instead. + * * Sets callback function invoked when the a session wants to receive * data from the remote peer. This callback is not necessary if the * application uses solely `nghttp2_session_mem_recv()` to process @@ -2165,11 +2527,24 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_callback( NGHTTP2_EXTERN void nghttp2_session_callbacks_set_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function invoked when the a session wants to receive + * data from the remote peer. This callback is not necessary if the + * application uses solely `nghttp2_session_mem_recv2()` to process + * received data. + */ +NGHTTP2_EXTERN void nghttp2_session_callbacks_set_recv_callback2( + nghttp2_session_callbacks *cbs, nghttp2_recv_callback2 recv_callback); + /** * @function * * Sets callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when a frame is received. + * `nghttp2_session_mem_recv2()` when a frame is received. */ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_recv_callback( nghttp2_session_callbacks *cbs, @@ -2179,7 +2554,7 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_recv_callback( * @function * * Sets callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is + * `nghttp2_session_mem_recv2()` when an invalid non-DATA frame is * received. */ NGHTTP2_EXTERN void @@ -2290,9 +2665,16 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback2( nghttp2_session_callbacks *cbs, nghttp2_on_invalid_header_callback2 on_invalid_header_callback2); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use + * `nghttp2_session_callbacks_set_select_padding_callback2()` with + * :type:`nghttp2_select_padding_callback2` instead. + * * Sets callback function invoked when the library asks application * how many padding bytes are required for the transmission of the * given frame. @@ -2301,9 +2683,29 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_select_padding_callback( nghttp2_session_callbacks *cbs, nghttp2_select_padding_callback select_padding_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function invoked when the library asks application + * how many padding bytes are required for the transmission of the + * given frame. + */ +NGHTTP2_EXTERN void nghttp2_session_callbacks_set_select_padding_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_select_padding_callback2 select_padding_callback); + +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use + * `nghttp2_session_callbacks_set_data_source_read_length_callback2()` + * with :type:`nghttp2_data_source_read_length_callback2` instead. + * * Sets callback function determine the length allowed in * :type:`nghttp2_data_source_read_callback`. */ @@ -2312,6 +2714,19 @@ nghttp2_session_callbacks_set_data_source_read_length_callback( nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback data_source_read_length_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function determine the length allowed in + * :type:`nghttp2_data_source_read_callback2`. + */ +NGHTTP2_EXTERN void +nghttp2_session_callbacks_set_data_source_read_length_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_data_source_read_length_callback2 data_source_read_length_callback); + /** * @function * @@ -2326,15 +2741,22 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_begin_frame_callback( * * Sets callback function invoked when * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_COPY` is used in - * :type:`nghttp2_data_source_read_callback` to avoid data copy. + * :type:`nghttp2_data_source_read_callback2` to avoid data copy. */ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_data_callback( nghttp2_session_callbacks *cbs, nghttp2_send_data_callback send_data_callback); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use + * `nghttp2_session_callbacks_set_pack_extension_callback2()` with + * :type:`nghttp2_pack_extension_callback2` instead. + * * Sets callback function invoked when the library asks the * application to pack extension frame payload in wire format. */ @@ -2342,6 +2764,18 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_pack_extension_callback( nghttp2_session_callbacks *cbs, nghttp2_pack_extension_callback pack_extension_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function invoked when the library asks the + * application to pack extension frame payload in wire format. + */ +NGHTTP2_EXTERN void nghttp2_session_callbacks_set_pack_extension_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_pack_extension_callback2 pack_extension_callback); + /** * @function * @@ -2366,12 +2800,15 @@ nghttp2_session_callbacks_set_on_extension_chunk_recv_callback( /** * @function * + * .. warning:: + * + * Deprecated. Use + * `nghttp2_session_callbacks_set_error_callback2()` with + * :type:`nghttp2_error_callback2` instead. + * * Sets callback function invoked when library tells error message to * the application. * - * This function is deprecated. The new application should use - * `nghttp2_session_callbacks_set_error_callback2()`. - * * If both :type:`nghttp2_error_callback` and * :type:`nghttp2_error_callback2` are set, the latter takes * precedence. @@ -2568,7 +3005,7 @@ nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option, * * If this option is not used or used with zero value, if MAGIC does * not match :macro:`NGHTTP2_CLIENT_MAGIC`, `nghttp2_session_recv()` - * and `nghttp2_session_mem_recv()` will return error + * and `nghttp2_session_mem_recv2()` will return error * :enum:`nghttp2_error.NGHTTP2_ERR_BAD_CLIENT_MAGIC`, which is fatal * error. */ @@ -2773,6 +3210,17 @@ NGHTTP2_EXTERN void nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option, uint64_t burst, uint64_t rate); +/** + * @function + * + * This function sets the maximum number of CONTINUATION frames + * following an incoming HEADER frame. If more than those frames are + * received, the remote endpoint is considered to be misbehaving and + * session will be closed. The default value is 8. + */ +NGHTTP2_EXTERN void nghttp2_option_set_max_continuations(nghttp2_option *option, + size_t val); + /** * @function * @@ -2781,7 +3229,7 @@ nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option, * does not store |callbacks|. The |user_data| is an arbitrary user * supplied data, which will be passed to the callback functions. * - * The :type:`nghttp2_send_callback` must be specified. If the + * The :type:`nghttp2_send_callback2` must be specified. If the * application code uses `nghttp2_session_recv()`, the * :type:`nghttp2_recv_callback` must be specified. The other members * of |callbacks| can be ``NULL``. @@ -2807,7 +3255,7 @@ nghttp2_session_client_new(nghttp2_session **session_ptr, * does not store |callbacks|. The |user_data| is an arbitrary user * supplied data, which will be passed to the callback functions. * - * The :type:`nghttp2_send_callback` must be specified. If the + * The :type:`nghttp2_send_callback2` must be specified. If the * application code uses `nghttp2_session_recv()`, the * :type:`nghttp2_recv_callback` must be specified. The other members * of |callbacks| can be ``NULL``. @@ -2943,7 +3391,7 @@ NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session); * This function retrieves the highest prioritized frame from the * outbound queue and sends it to the remote peer. It does this as * many times as possible until the user callback - * :type:`nghttp2_send_callback` returns + * :type:`nghttp2_send_callback2` returns * :enum:`nghttp2_error.NGHTTP2_ERR_WOULDBLOCK`, the outbound queue * becomes empty or flow control is triggered (remote window size * becomes depleted or maximum number of concurrent streams is @@ -2973,7 +3421,7 @@ NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session); * :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort * the following steps. * - * 8. :type:`nghttp2_send_callback` is invoked one or more times to + * 8. :type:`nghttp2_send_callback2` is invoked one or more times to * send the frame. * * 9. :type:`nghttp2_on_frame_send_callback` is invoked. @@ -2992,9 +3440,14 @@ NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session); */ NGHTTP2_EXTERN int nghttp2_session_send(nghttp2_session *session); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_session_mem_send2()` instead. + * * Returns the serialized data to send. * * This function behaves like `nghttp2_session_send()` except that it @@ -3034,6 +3487,50 @@ NGHTTP2_EXTERN int nghttp2_session_send(nghttp2_session *session); NGHTTP2_EXTERN ssize_t nghttp2_session_mem_send(nghttp2_session *session, const uint8_t **data_ptr); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Returns the serialized data to send. + * + * This function behaves like `nghttp2_session_send()` except that it + * does not use :type:`nghttp2_send_callback2` to transmit data. + * Instead, it assigns the pointer to the serialized data to the + * |*data_ptr| and returns its length. The other callbacks are called + * in the same way as they are in `nghttp2_session_send()`. + * + * If no data is available to send, this function returns 0. + * + * This function may not return all serialized data in one invocation. + * To get all data, call this function repeatedly until it returns 0 + * or one of negative error codes. + * + * The assigned |*data_ptr| is valid until the next call of + * `nghttp2_session_mem_send2()` or `nghttp2_session_send()`. + * + * The caller must send all data before sending the next chunk of + * data. + * + * This function returns the length of the data pointed by the + * |*data_ptr| if it succeeds, or one of the following negative error + * codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * + * .. note:: + * + * This function may produce very small byte string. If that is the + * case, and application disables Nagle algorithm (``TCP_NODELAY``), + * then writing this small chunk leads to very small packet, and it + * is very inefficient. An application should be responsible to + * buffer up small chunks of data as necessary to avoid this + * situation. + */ +NGHTTP2_EXTERN nghttp2_ssize +nghttp2_session_mem_send2(nghttp2_session *session, const uint8_t **data_ptr); + /** * @function * @@ -3104,9 +3601,14 @@ NGHTTP2_EXTERN ssize_t nghttp2_session_mem_send(nghttp2_session *session, */ NGHTTP2_EXTERN int nghttp2_session_recv(nghttp2_session *session); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_session_mem_recv2()` instead. + * * Processes data |in| as an input from the remote endpoint. The * |inlen| indicates the number of bytes to receive in the |in|. * @@ -3145,6 +3647,49 @@ NGHTTP2_EXTERN ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, size_t inlen); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Processes data |in| as an input from the remote endpoint. The + * |inlen| indicates the number of bytes to receive in the |in|. + * + * This function behaves like `nghttp2_session_recv()` except that it + * does not use :type:`nghttp2_recv_callback` to receive data; the + * |in| is the only data for the invocation of this function. If all + * bytes are processed, this function returns. The other callbacks + * are called in the same way as they are in `nghttp2_session_recv()`. + * + * In the current implementation, this function always tries to + * processes |inlen| bytes of input data unless either an error occurs or + * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` is returned from + * :type:`nghttp2_on_header_callback` or + * :type:`nghttp2_on_data_chunk_recv_callback`. If + * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` is used, the return value + * includes the number of bytes which was used to produce the data or + * frame for the callback. + * + * This function returns the number of processed bytes, or one of the + * following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` + * The callback function failed. + * :enum:`nghttp2_error.NGHTTP2_ERR_BAD_CLIENT_MAGIC` + * Invalid client magic was detected. This error only returns + * when |session| was configured as server and + * `nghttp2_option_set_no_recv_client_magic()` is not used with + * nonzero value. + * :enum:`nghttp2_error.NGHTTP2_ERR_FLOODED` + * Flooding was detected in this HTTP/2 session, and it must be + * closed. This is most likely caused by misbehaviour of peer. + */ +NGHTTP2_EXTERN nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + const uint8_t *in, + size_t inlen); + /** * @function * @@ -3190,7 +3735,7 @@ NGHTTP2_EXTERN int nghttp2_session_want_write(nghttp2_session *session); * @function * * Returns stream_user_data for the stream |stream_id|. The - * stream_user_data is provided by `nghttp2_submit_request()`, + * stream_user_data is provided by `nghttp2_submit_request2()`, * `nghttp2_submit_headers()` or * `nghttp2_session_set_stream_user_data()`. Unless it is set using * `nghttp2_session_set_stream_user_data()`, if the stream is @@ -3626,6 +4171,13 @@ NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session, /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return 0 without doing anything. + * * Changes priority of existing stream denoted by |stream_id|. The * new priority specification is |pri_spec|. * @@ -3665,6 +4217,13 @@ nghttp2_session_change_stream_priority(nghttp2_session *session, /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return 0 without doing anything. + * * Creates idle stream with the given |stream_id|, and priority * |pri_spec|. * @@ -3715,10 +4274,6 @@ nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id, /** * @function * - * Performs post-process of HTTP Upgrade request. This function can - * be called from both client and server, but the behavior is very - * different in each other. - * * .. warning:: * * This function is deprecated in favor of @@ -3730,6 +4285,10 @@ nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id, * HEAD is used in request, the length of response body must be 0 * regardless of value included in content-length header field. * + * Performs post-process of HTTP Upgrade request. This function can + * be called from both client and server, but the behavior is very + * different in each other. + * * If called from client side, the |settings_payload| must be the * value sent in ``HTTP2-Settings`` header field and must be decoded * by base64url decoder. The |settings_payloadlen| is the length of @@ -3809,9 +4368,14 @@ NGHTTP2_EXTERN int nghttp2_session_upgrade2(nghttp2_session *session, int head_request, void *stream_user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_pack_settings_payload2()` instead. + * * Serializes the SETTINGS values |iv| in the |buf|. The size of the * |buf| is specified by |buflen|. The number of entries in the |iv| * array is given by |niv|. The required space in |buf| for the |niv| @@ -3833,6 +4397,32 @@ NGHTTP2_EXTERN int nghttp2_session_upgrade2(nghttp2_session *session, NGHTTP2_EXTERN ssize_t nghttp2_pack_settings_payload( uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Serializes the SETTINGS values |iv| in the |buf|. The size of the + * |buf| is specified by |buflen|. The number of entries in the |iv| + * array is given by |niv|. The required space in |buf| for the |niv| + * entries is ``6*niv`` bytes and if the given buffer is too small, an + * error is returned. This function is used mainly for creating a + * SETTINGS payload to be sent with the ``HTTP2-Settings`` header + * field in an HTTP Upgrade request. The data written in |buf| is NOT + * base64url encoded and the application is responsible for encoding. + * + * This function returns the number of bytes written in |buf|, or one + * of the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * The |iv| contains duplicate settings ID or invalid value. + * + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE` + * The provided |buflen| size is too small to hold the output. + */ +NGHTTP2_EXTERN nghttp2_ssize nghttp2_pack_settings_payload2( + uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv); + /** * @function * @@ -3854,6 +4444,12 @@ NGHTTP2_EXTERN const char *nghttp2_http2_strerror(uint32_t error_code); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * Initializes |pri_spec| with the |stream_id| of the stream to depend * on with |weight| and its exclusive flag. If |exclusive| is * nonzero, exclusive flag is set. @@ -3868,6 +4464,12 @@ NGHTTP2_EXTERN void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec, /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * Initializes |pri_spec| with the default values. The default values * are: stream_id = 0, weight = :macro:`NGHTTP2_DEFAULT_WEIGHT` and * exclusive = 0. @@ -3878,18 +4480,29 @@ nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * Returns nonzero if the |pri_spec| is filled with default values. */ NGHTTP2_EXTERN int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_submit_request2()` instead. + * * Submits HEADERS frame and optionally one or more DATA frames. * - * The |pri_spec| is priority specification of this request. ``NULL`` - * means the default priority (see + * The |pri_spec| is a deprecated priority specification of this + * request. ``NULL`` means the default priority (see * `nghttp2_priority_spec_default_init()`). To specify the priority, * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``, * this function will copy its data members. @@ -3970,23 +4583,119 @@ NGHTTP2_EXTERN int32_t nghttp2_submit_request( const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd, void *stream_user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + /** * @function * - * Submits response HEADERS frame and optionally one or more DATA - * frames against the stream |stream_id|. + * Submits HEADERS frame and optionally one or more DATA frames. * - * The |nva| is an array of name/value pair :type:`nghttp2_nv` with - * |nvlen| elements. The application is responsible to include - * required pseudo-header fields (header field whose name starts with - * ":") in |nva| and must place pseudo-headers before regular header - * fields. + * The |pri_spec| is a deprecated priority specification of this + * request. ``NULL`` means the default priority (see + * `nghttp2_priority_spec_default_init()`). To specify the priority, + * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``, + * this function will copy its data members. In the future release + * after the end of 2024, this function will ignore |pri_spec| and + * behave as if ``NULL`` is given. * - * This function creates copies of all name/value pairs in |nva|. It - * also lower-cases all names in |nva|. The order of elements in - * |nva| is preserved. For header fields with - * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME` and - * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, + * The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`, + * :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` + * is strictly less than :macro:`NGHTTP2_MIN_WEIGHT`, it becomes + * :macro:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than + * :macro:`NGHTTP2_MAX_WEIGHT`, it becomes + * :macro:`NGHTTP2_MAX_WEIGHT`. + * + * If + * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES` + * of value of 1 is received by a remote endpoint, |pri_spec| is + * ignored, and treated as if ``NULL`` is specified. + * + * The |nva| is an array of name/value pair :type:`nghttp2_nv` with + * |nvlen| elements. The application is responsible to include + * required pseudo-header fields (header field whose name starts with + * ":") in |nva| and must place pseudo-headers before regular header + * fields. + * + * This function creates copies of all name/value pairs in |nva|. It + * also lower-cases all names in |nva|. The order of elements in + * |nva| is preserved. For header fields with + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME` and + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, + * header field name and value are not copied respectively. With + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME`, application + * is responsible to pass header field name in lowercase. The + * application should maintain the references to them until + * :type:`nghttp2_on_frame_send_callback` or + * :type:`nghttp2_on_frame_not_send_callback` is called. + * + * HTTP/2 specification has requirement about header fields in the + * request HEADERS. See the specification for more details. + * + * If |data_prd| is not ``NULL``, it provides data which will be sent + * in subsequent DATA frames. In this case, a method that allows + * request message bodies + * (https://tools.ietf.org/html/rfc7231#section-4) must be specified + * with ``:method`` key in |nva| (e.g. ``POST``). This function does + * not take ownership of the |data_prd|. The function copies the + * members of the |data_prd|. If |data_prd| is ``NULL``, HEADERS have + * END_STREAM set. The |stream_user_data| is data associated to the + * stream opened by this request and can be an arbitrary pointer, + * which can be retrieved later by + * `nghttp2_session_get_stream_user_data()`. + * + * This function returns assigned stream ID if it succeeds, or one of + * the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE` + * No stream ID is available because maximum stream ID was + * reached. + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * Trying to depend on itself (new stream ID equals + * ``pri_spec->stream_id``). + * :enum:`nghttp2_error.NGHTTP2_ERR_PROTO` + * The |session| is server session. + * + * .. warning:: + * + * This function returns assigned stream ID if it succeeds. But + * that stream is not created yet. The application must not submit + * frame to that stream ID before + * :type:`nghttp2_before_frame_send_callback` is called for this + * frame. This means `nghttp2_session_get_stream_user_data()` does + * not work before the callback. But + * `nghttp2_session_set_stream_user_data()` handles this situation + * specially, and it can set data to a stream during this period. + * + */ +NGHTTP2_EXTERN int32_t nghttp2_submit_request2( + nghttp2_session *session, const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider2 *data_prd, + void *stream_user_data); + +#ifndef NGHTTP2_NO_SSIZE_T +/** + * @function + * + * .. warning:: + * + * Deprecated. Use `nghttp2_submit_response2()` instead. + * + * Submits response HEADERS frame and optionally one or more DATA + * frames against the stream |stream_id|. + * + * The |nva| is an array of name/value pair :type:`nghttp2_nv` with + * |nvlen| elements. The application is responsible to include + * required pseudo-header fields (header field whose name starts with + * ":") in |nva| and must place pseudo-headers before regular header + * fields. + * + * This function creates copies of all name/value pairs in |nva|. It + * also lower-cases all names in |nva|. The order of elements in + * |nva| is preserved. For header fields with + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME` and + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, * header field name and value are not copied respectively. With * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME`, application * is responsible to pass header field name in lowercase. The @@ -4039,6 +4748,77 @@ nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Submits response HEADERS frame and optionally one or more DATA + * frames against the stream |stream_id|. + * + * The |nva| is an array of name/value pair :type:`nghttp2_nv` with + * |nvlen| elements. The application is responsible to include + * required pseudo-header fields (header field whose name starts with + * ":") in |nva| and must place pseudo-headers before regular header + * fields. + * + * This function creates copies of all name/value pairs in |nva|. It + * also lower-cases all names in |nva|. The order of elements in + * |nva| is preserved. For header fields with + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME` and + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, + * header field name and value are not copied respectively. With + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME`, application + * is responsible to pass header field name in lowercase. The + * application should maintain the references to them until + * :type:`nghttp2_on_frame_send_callback` or + * :type:`nghttp2_on_frame_not_send_callback` is called. + * + * HTTP/2 specification has requirement about header fields in the + * response HEADERS. See the specification for more details. + * + * If |data_prd| is not ``NULL``, it provides data which will be sent + * in subsequent DATA frames. This function does not take ownership + * of the |data_prd|. The function copies the members of the + * |data_prd|. If |data_prd| is ``NULL``, HEADERS will have + * END_STREAM flag set. + * + * This method can be used as normal HTTP response and push response. + * When pushing a resource using this function, the |session| must be + * configured using `nghttp2_session_server_new()` or its variants and + * the target stream denoted by the |stream_id| must be reserved using + * `nghttp2_submit_push_promise()`. + * + * To send non-final response headers (e.g., HTTP status 101), don't + * use this function because this function half-closes the outbound + * stream. Instead, use `nghttp2_submit_headers()` for this purpose. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * The |stream_id| is 0. + * :enum:`nghttp2_error.NGHTTP2_ERR_DATA_EXIST` + * DATA or HEADERS has been already submitted and not fully + * processed yet. Normally, this does not happen, but when + * application wrongly calls `nghttp2_submit_response2()` twice, + * this may happen. + * :enum:`nghttp2_error.NGHTTP2_ERR_PROTO` + * The |session| is client session. + * + * .. warning:: + * + * Calling this function twice for the same stream ID may lead to + * program crash. It is generally considered to a programming error + * to commit response twice. + */ +NGHTTP2_EXTERN int +nghttp2_submit_response2(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider2 *data_prd); + /** * @function * @@ -4064,22 +4844,23 @@ nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, * DATA without END_STREAM flat set. The library does not enforce * this requirement, and applications should do this for themselves. * If `nghttp2_submit_trailer()` is called before any response HEADERS - * submission (usually by `nghttp2_submit_response()`), the content of - * |nva| will be sent as response headers, which will result in error. + * submission (usually by `nghttp2_submit_response2()`), the content + * of |nva| will be sent as response headers, which will result in + * error. * * This function has the same effect with `nghttp2_submit_headers()`, * with flags = :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM` and both * pri_spec and stream_user_data to NULL. * - * To submit trailer fields after `nghttp2_submit_response()` is + * To submit trailer fields after `nghttp2_submit_response2()` is * called, the application has to specify - * :type:`nghttp2_data_provider` to `nghttp2_submit_response()`. - * Inside of :type:`nghttp2_data_source_read_callback`, when setting + * :type:`nghttp2_data_provider2` to `nghttp2_submit_response2()`. + * Inside of :type:`nghttp2_data_source_read_callback2`, when setting * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_EOF`, also set * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_END_STREAM`. After * that, the application can send trailer fields using * `nghttp2_submit_trailer()`. `nghttp2_submit_trailer()` can be used - * inside :type:`nghttp2_data_source_read_callback`. + * inside :type:`nghttp2_data_source_read_callback2`. * * This function returns 0 if it succeeds and |stream_id| is -1. * Otherwise, this function returns 0 if it succeeds, or one of the @@ -4114,11 +4895,13 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session, * assigned stream ID will be returned. Otherwise, specify stream ID * in |stream_id|. * - * The |pri_spec| is priority specification of this request. ``NULL`` - * means the default priority (see + * The |pri_spec| is a deprecated priority specification of this + * request. ``NULL`` means the default priority (see * `nghttp2_priority_spec_default_init()`). To specify the priority, * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``, - * this function will copy its data members. + * this function will copy its data members. In the future release + * after the end of 2024, this function will ignore |pri_spec| and + * behave as if ``NULL`` is given. * * The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`, * :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` @@ -4156,8 +4939,8 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session, * * This function is low-level in a sense that the application code can * specify flags directly. For usual HTTP request, - * `nghttp2_submit_request()` is useful. Likewise, for HTTP response, - * prefer `nghttp2_submit_response()`. + * `nghttp2_submit_request2()` is useful. Likewise, for HTTP + * response, prefer `nghttp2_submit_response2()`. * * This function returns newly assigned stream ID if it succeeds and * |stream_id| is -1. Otherwise, this function returns 0 if it @@ -4192,9 +4975,14 @@ NGHTTP2_EXTERN int32_t nghttp2_submit_headers( const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, void *stream_user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_submit_data2()` instead. + * * Submits one or more DATA frames to the stream |stream_id|. The * data to be sent are provided by |data_prd|. If |flags| contains * :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM`, the last DATA frame @@ -4237,19 +5025,73 @@ NGHTTP2_EXTERN int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_data_provider *data_prd); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Submits one or more DATA frames to the stream |stream_id|. The + * data to be sent are provided by |data_prd|. If |flags| contains + * :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM`, the last DATA frame + * has END_STREAM flag set. + * + * This function does not take ownership of the |data_prd|. The + * function copies the members of the |data_prd|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_DATA_EXIST` + * DATA or HEADERS has been already submitted and not fully + * processed yet. + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * The |stream_id| is 0. + * :enum:`nghttp2_error.NGHTTP2_ERR_STREAM_CLOSED` + * The stream was already closed; or the |stream_id| is invalid. + * + * .. note:: + * + * Currently, only one DATA or HEADERS is allowed for a stream at a + * time. Submitting these frames more than once before first DATA + * or HEADERS is finished results in + * :enum:`nghttp2_error.NGHTTP2_ERR_DATA_EXIST` error code. The + * earliest callback which tells that previous frame is done is + * :type:`nghttp2_on_frame_send_callback`. In side that callback, + * new data can be submitted using `nghttp2_submit_data2()`. Of + * course, all data except for last one must not have + * :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM` flag set in |flags|. + * This sounds a bit complicated, and we recommend to use + * `nghttp2_submit_request2()` and `nghttp2_submit_response2()` to + * avoid this cascading issue. The experience shows that for HTTP + * use, these two functions are enough to implement both client and + * server. + */ +NGHTTP2_EXTERN int nghttp2_submit_data2(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider2 *data_prd); + /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return 0 without doing anything. + * * Submits PRIORITY frame to change the priority of stream |stream_id| * to the priority specification |pri_spec|. * * The |flags| is currently ignored and should be * :enum:`nghttp2_flag.NGHTTP2_FLAG_NONE`. * - * The |pri_spec| is priority specification of this request. ``NULL`` - * is not allowed for this function. To specify the priority, use - * `nghttp2_priority_spec_init()`. This function will copy its data - * members. + * The |pri_spec| is a deprecated priority specification of this + * request. ``NULL`` is not allowed for this function. To specify the + * priority, use `nghttp2_priority_spec_init()`. This function will + * copy its data members. * * The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`, * :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` @@ -4429,7 +5271,7 @@ NGHTTP2_EXTERN int nghttp2_submit_settings(nghttp2_session *session, * The client side is not allowed to use this function. * * To submit response headers and data, use - * `nghttp2_submit_response()`. + * `nghttp2_submit_response2()`. * * This function returns assigned promised stream ID if it succeeds, * or one of the following negative error codes: @@ -4568,10 +5410,11 @@ nghttp2_session_get_last_proc_stream_id(nghttp2_session *session); * reasons are: session is server; stream ID has been spent; GOAWAY * has been sent or received. * - * The application can call `nghttp2_submit_request()` without - * consulting this function. In that case, `nghttp2_submit_request()` - * may return error. Or, request is failed to sent, and - * :type:`nghttp2_on_stream_close_callback` is called. + * The application can call `nghttp2_submit_request2()` without + * consulting this function. In that case, + * `nghttp2_submit_request2()` may return error. Or, request is + * failed to sent, and :type:`nghttp2_on_stream_close_callback` is + * called. */ NGHTTP2_EXTERN int nghttp2_session_check_request_allowed(nghttp2_session *session); @@ -4673,11 +5516,11 @@ nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags, * Application can pass arbitrary frame flags and stream ID in |flags| * and |stream_id| respectively. The |payload| is opaque pointer, and * it can be accessible though ``frame->ext.payload`` in - * :type:`nghttp2_pack_extension_callback`. The library will not own + * :type:`nghttp2_pack_extension_callback2`. The library will not own * passed |payload| pointer. * - * The application must set :type:`nghttp2_pack_extension_callback` - * using `nghttp2_session_callbacks_set_pack_extension_callback()`. + * The application must set :type:`nghttp2_pack_extension_callback2` + * using `nghttp2_session_callbacks_set_pack_extension_callback2()`. * * The application should retain the memory pointed by |payload| until * the transmission of extension frame is done (which is indicated by @@ -4685,7 +5528,7 @@ nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags, * (which is indicated by :type:`nghttp2_on_frame_not_send_callback`). * If application does not touch this memory region after packing it * into a wire format, application can free it inside - * :type:`nghttp2_pack_extension_callback`. + * :type:`nghttp2_pack_extension_callback2`. * * The standard HTTP/2 frame cannot be sent with this function, so * |type| must be strictly grater than 0x9. Otherwise, this function @@ -4696,7 +5539,7 @@ nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags, * negative error codes: * * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_STATE` - * If :type:`nghttp2_pack_extension_callback` is not set. + * If :type:`nghttp2_pack_extension_callback2` is not set. * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` * If |type| specifies standard HTTP/2 frame type. The frame * types in the rage [0x0, 0x9], both inclusive, are standard @@ -4958,6 +5801,55 @@ NGHTTP2_EXTERN int nghttp2_session_change_extpri_stream_priority( nghttp2_session *session, int32_t stream_id, const nghttp2_extpri *extpri, int ignore_client_signal); +/** + * @function + * + * Stores the stream priority of the existing stream denoted by + * |stream_id| in the object pointed by |extpri|. This function is + * meant to be used by server for :rfc:`9218` extensible + * prioritization scheme. + * + * If |session| is initialized as client, this function returns + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_STATE`. + * + * If + * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES` + * of value of 1 is not submitted via `nghttp2_submit_settings()`, + * this function does nothing and returns 0. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_STATE` + * The |session| is initialized as client. + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * |stream_id| is zero; or a stream denoted by |stream_id| is not + * found. + */ +NGHTTP2_EXTERN int nghttp2_session_get_extpri_stream_priority( + nghttp2_session *session, nghttp2_extpri *extpri, int32_t stream_id); + +/** + * @function + * + * Parses Priority header field value pointed by |value| of length + * |len|, and stores the result in the object pointed by |extpri|. + * Priority header field is defined in :rfc:`9218`. + * + * This function does not initialize the object pointed by |extpri| + * before storing the result. It only assigns the values that the + * parser correctly extracted to fields. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * Failed to parse the header field value. + */ +NGHTTP2_EXTERN int nghttp2_extpri_parse_priority(nghttp2_extpri *extpri, + const uint8_t *value, + size_t len); + /** * @function * @@ -4973,11 +5865,14 @@ NGHTTP2_EXTERN int nghttp2_nv_compare_name(const nghttp2_nv *lhs, /** * @function * - * A helper function for dealing with NPN in client side or ALPN in - * server side. The |in| contains peer's protocol list in preferable - * order. The format of |in| is length-prefixed and not - * null-terminated. For example, ``h2`` and - * ``http/1.1`` stored in |in| like this:: + * .. warning:: + * + * Deprecated. Use `nghttp2_select_alpn` instead. + * + * A helper function for dealing with ALPN in server side. The |in| + * contains peer's protocol list in preferable order. The format of + * |in| is length-prefixed and not null-terminated. For example, + * ``h2`` and ``http/1.1`` stored in |in| like this:: * * in[0] = 2 * in[1..2] = "h2" @@ -5002,20 +5897,18 @@ NGHTTP2_EXTERN int nghttp2_nv_compare_name(const nghttp2_nv *lhs, * * For ALPN, refer to https://tools.ietf.org/html/rfc7301 * - * See http://technotes.googlecode.com/git/nextprotoneg.html for more - * details about NPN. - * - * For NPN, to use this method you should do something like:: + * To use this method you should do something like:: * - * static int select_next_proto_cb(SSL* ssl, - * unsigned char **out, + * static int alpn_select_proto_cb(SSL* ssl, + * const unsigned char **out, * unsigned char *outlen, * const unsigned char *in, * unsigned int inlen, * void *arg) * { * int rv; - * rv = nghttp2_select_next_protocol(out, outlen, in, inlen); + * rv = nghttp2_select_next_protocol((unsigned char**)out, outlen, + * in, inlen); * if (rv == -1) { * return SSL_TLSEXT_ERR_NOACK; * } @@ -5025,7 +5918,7 @@ NGHTTP2_EXTERN int nghttp2_nv_compare_name(const nghttp2_nv *lhs, * return SSL_TLSEXT_ERR_OK; * } * ... - * SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj); + * SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, my_obj); * */ NGHTTP2_EXTERN int nghttp2_select_next_protocol(unsigned char **out, @@ -5033,6 +5926,65 @@ NGHTTP2_EXTERN int nghttp2_select_next_protocol(unsigned char **out, const unsigned char *in, unsigned int inlen); +/** + * @function + * + * A helper function for dealing with ALPN in server side. The |in| + * contains peer's protocol list in preferable order. The format of + * |in| is length-prefixed and not null-terminated. For example, + * ``h2`` and ``http/1.1`` stored in |in| like this:: + * + * in[0] = 2 + * in[1..2] = "h2" + * in[3] = 8 + * in[4..11] = "http/1.1" + * inlen = 12 + * + * The selection algorithm is as follows: + * + * 1. If peer's list contains HTTP/2 protocol the library supports, + * it is selected and returns 1. The following step is not taken. + * + * 2. If peer's list contains ``http/1.1``, this function selects + * ``http/1.1`` and returns 0. The following step is not taken. + * + * 3. This function selects nothing and returns -1 (So called + * non-overlap case). In this case, |out| and |outlen| are left + * untouched. + * + * Selecting ``h2`` means that ``h2`` is written into |*out| and its + * length (which is 2) is assigned to |*outlen|. + * + * For ALPN, refer to https://tools.ietf.org/html/rfc7301 + * + * To use this method you should do something like:: + * + * static int alpn_select_proto_cb(SSL* ssl, + * const unsigned char **out, + * unsigned char *outlen, + * const unsigned char *in, + * unsigned int inlen, + * void *arg) + * { + * int rv; + * rv = nghttp2_select_alpn(out, outlen, in, inlen); + * if (rv == -1) { + * return SSL_TLSEXT_ERR_NOACK; + * } + * if (rv == 1) { + * ((MyType*)arg)->http2_selected = 1; + * } + * return SSL_TLSEXT_ERR_OK; + * } + * ... + * SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, my_obj); + * + */ +NGHTTP2_EXTERN int nghttp2_select_alpn(const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen); + /** * @function * @@ -5208,9 +6160,14 @@ NGHTTP2_EXTERN int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_hd_deflate_hd2()` instead. + * * Deflates the |nva|, which has the |nvlen| name/value pairs, into * the |buf| of length |buflen|. * @@ -5240,9 +6197,47 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, const nghttp2_nv *nva, size_t nvlen); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Deflates the |nva|, which has the |nvlen| name/value pairs, into + * the |buf| of length |buflen|. + * + * If |buf| is not large enough to store the deflated header block, + * this function fails with + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller + * should use `nghttp2_hd_deflate_bound()` to know the upper bound of + * buffer size required to deflate given header name/value pairs. + * + * Once this function fails, subsequent call of this function always + * returns :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP`. + * + * After this function returns, it is safe to delete the |nva|. + * + * This function returns the number of bytes written to |buf| if it + * succeeds, or one of the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` + * Deflation process has failed. + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE` + * The provided |buflen| size is too small to hold the output. + */ +NGHTTP2_EXTERN nghttp2_ssize +nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater, uint8_t *buf, + size_t buflen, const nghttp2_nv *nva, size_t nvlen); + +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_hd_deflate_hd_vec2()` instead. + * * Deflates the |nva|, which has the |nvlen| name/value pairs, into * the |veclen| size of buf vector |vec|. The each size of buffer * must be set in len field of :type:`nghttp2_vec`. If and only if @@ -5274,6 +6269,40 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, const nghttp2_nv *nva, size_t nvlen); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Deflates the |nva|, which has the |nvlen| name/value pairs, into + * the |veclen| size of buf vector |vec|. The each size of buffer + * must be set in len field of :type:`nghttp2_vec`. If and only if + * one chunk is filled up completely, next chunk will be used. If + * |vec| is not large enough to store the deflated header block, this + * function fails with + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller + * should use `nghttp2_hd_deflate_bound()` to know the upper bound of + * buffer size required to deflate given header name/value pairs. + * + * Once this function fails, subsequent call of this function always + * returns :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP`. + * + * After this function returns, it is safe to delete the |nva|. + * + * This function returns the number of bytes written to |vec| if it + * succeeds, or one of the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` + * Deflation process has failed. + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE` + * The provided |buflen| size is too small to hold the output. + */ +NGHTTP2_EXTERN nghttp2_ssize nghttp2_hd_deflate_hd_vec2( + nghttp2_hd_deflater *deflater, const nghttp2_vec *vec, size_t veclen, + const nghttp2_nv *nva, size_t nvlen); + /** * @function * @@ -5387,7 +6416,7 @@ NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater); * This function must not be called while header block is being * inflated. In other words, this function must be called after * initialization of |inflater|, but before calling - * `nghttp2_hd_inflate_hd2()`, or after + * `nghttp2_hd_inflate_hd3()`, or after * `nghttp2_hd_inflate_end_headers()`. Otherwise, * `NGHTTP2_ERR_INVALID_STATE` was returned. * @@ -5425,6 +6454,7 @@ typedef enum { NGHTTP2_HD_INFLATE_EMIT = 0x02 } nghttp2_hd_inflate_flag; +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * @@ -5512,9 +6542,16 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, int *inflate_flags, uint8_t *in, size_t inlen, int in_final); +#endif /* NGHTTP2_NO_SSIZE_T */ + +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_hd_inflate_hd3()` instead. + * * Inflates name/value block stored in |in| with length |inlen|. This * function performs decompression. For each successful emission of * header name/value pair, @@ -5601,6 +6638,95 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, const uint8_t *in, size_t inlen, int in_final); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Inflates name/value block stored in |in| with length |inlen|. This + * function performs decompression. For each successful emission of + * header name/value pair, + * :enum:`nghttp2_hd_inflate_flag.NGHTTP2_HD_INFLATE_EMIT` is set in + * |*inflate_flags| and name/value pair is assigned to the |nv_out| + * and the function returns. The caller must not free the members of + * |nv_out|. + * + * The |nv_out| may include pointers to the memory region in the |in|. + * The caller must retain the |in| while the |nv_out| is used. + * + * The application should call this function repeatedly until the + * ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and + * return value is non-negative. If that happens, all given input + * data (|inlen| bytes) are processed successfully. Then the + * application must call `nghttp2_hd_inflate_end_headers()` to prepare + * for the next header block input. + * + * In other words, if |in_final| is nonzero, and this function returns + * |inlen|, you can assert that + * :enum:`nghttp2_hd_inflate_final.NGHTTP2_HD_INFLATE_FINAL` is set in + * |*inflate_flags|. + * + * The caller can feed complete compressed header block. It also can + * feed it in several chunks. The caller must set |in_final| to + * nonzero if the given input is the last block of the compressed + * header. + * + * This function returns the number of bytes processed if it succeeds, + * or one of the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` + * Inflation process has failed. + * :enum:`nghttp2_error.NGHTTP2_ERR_BUFFER_ERROR` + * The header field name or value is too large. + * + * Example follows:: + * + * int inflate_header_block(nghttp2_hd_inflater *hd_inflater, + * uint8_t *in, size_t inlen, int final) + * { + * nghttp2_ssize rv; + * + * for(;;) { + * nghttp2_nv nv; + * int inflate_flags = 0; + * + * rv = nghttp2_hd_inflate_hd3(hd_inflater, &nv, &inflate_flags, + * in, inlen, final); + * + * if(rv < 0) { + * fprintf(stderr, "inflate failed with error code %td", rv); + * return -1; + * } + * + * in += rv; + * inlen -= rv; + * + * if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { + * fwrite(nv.name, nv.namelen, 1, stderr); + * fprintf(stderr, ": "); + * fwrite(nv.value, nv.valuelen, 1, stderr); + * fprintf(stderr, "\n"); + * } + * if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) { + * nghttp2_hd_inflate_end_headers(hd_inflater); + * break; + * } + * if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && + * inlen == 0) { + * break; + * } + * } + * + * return 0; + * } + * + */ +NGHTTP2_EXTERN nghttp2_ssize nghttp2_hd_inflate_hd3( + nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, + const uint8_t *in, size_t inlen, int in_final); + /** * @function * @@ -5674,8 +6800,8 @@ typedef struct nghttp2_stream nghttp2_stream; * `nghttp2_session_get_root_stream()`) if 0 is given in |stream_id|. * * Unless |stream_id| == 0, the returned pointer is valid until next - * call of `nghttp2_session_send()`, `nghttp2_session_mem_send()`, - * `nghttp2_session_recv()`, and `nghttp2_session_mem_recv()`. + * call of `nghttp2_session_send()`, `nghttp2_session_mem_send2()`, + * `nghttp2_session_recv()`, and `nghttp2_session_mem_recv2()`. */ NGHTTP2_EXTERN nghttp2_stream * nghttp2_session_find_stream(nghttp2_session *session, int32_t stream_id); @@ -5729,6 +6855,12 @@ nghttp2_stream_get_state(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * Returns root of dependency tree, which is imaginary stream with * stream ID 0. The returned pointer is valid until |session| is * freed by `nghttp2_session_del()`. @@ -5739,6 +6871,13 @@ nghttp2_session_get_root_stream(nghttp2_session *session); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return NULL. + * * Returns the parent stream of |stream| in dependency tree. Returns * NULL if there is no such stream. */ @@ -5750,6 +6889,13 @@ NGHTTP2_EXTERN int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return NULL. + * * Returns the next sibling stream of |stream| in dependency tree. * Returns NULL if there is no such stream. */ @@ -5759,6 +6905,13 @@ nghttp2_stream_get_next_sibling(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return NULL. + * * Returns the previous sibling stream of |stream| in dependency tree. * Returns NULL if there is no such stream. */ @@ -5768,6 +6921,13 @@ nghttp2_stream_get_previous_sibling(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return NULL. + * * Returns the first child stream of |stream| in dependency tree. * Returns NULL if there is no such stream. */ @@ -5777,6 +6937,14 @@ nghttp2_stream_get_first_child(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return + * :macro:`NGHTTP2_DEFAULT_WEIGHT`. + * * Returns dependency weight to the parent stream of |stream|. */ NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream); @@ -5784,6 +6952,13 @@ NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return 0. + * * Returns the sum of the weight for |stream|'s children. */ NGHTTP2_EXTERN int32_t diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h index f56954e7fded45..a21d6a1605e010 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "1.57.0" +#define NGHTTP2_VERSION "1.61.0" /** * @macro @@ -37,6 +37,6 @@ * release. This is a 24 bit number with 8 bits for major number, 8 bits * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. */ -#define NGHTTP2_VERSION_NUM 0x013900 +#define NGHTTP2_VERSION_NUM 0x013d00 #endif /* NGHTTP2VER_H */ diff --git a/deps/nghttp2/lib/nghttp2_npn.c b/deps/nghttp2/lib/nghttp2_alpn.c similarity index 65% rename from deps/nghttp2/lib/nghttp2_npn.c rename to deps/nghttp2/lib/nghttp2_alpn.c index d1384c80758d9b..33c5885f8d889f 100644 --- a/deps/nghttp2/lib/nghttp2_npn.c +++ b/deps/nghttp2/lib/nghttp2_alpn.c @@ -22,13 +22,13 @@ * 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 "nghttp2_npn.h" +#include "nghttp2_alpn.h" #include -static int select_next_protocol(unsigned char **out, unsigned char *outlen, - const unsigned char *in, unsigned int inlen, - const char *key, unsigned int keylen) { +static int select_alpn(const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const char *key, unsigned int keylen) { unsigned int i; for (i = 0; i + keylen <= inlen; i += (unsigned int)(in[i] + 1)) { if (memcmp(&in[i], key, keylen) == 0) { @@ -45,12 +45,25 @@ static int select_next_protocol(unsigned char **out, unsigned char *outlen, int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen) { - if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_ALPN, - NGHTTP2_PROTO_ALPN_LEN) == 0) { + if (select_alpn((const unsigned char **)out, outlen, in, inlen, + NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN) == 0) { return 1; } - if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_HTTP_1_1_ALPN, - NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) { + if (select_alpn((const unsigned char **)out, outlen, in, inlen, + NGHTTP2_HTTP_1_1_ALPN, NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) { + return 0; + } + return -1; +} + +int nghttp2_select_alpn(const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen) { + if (select_alpn(out, outlen, in, inlen, NGHTTP2_PROTO_ALPN, + NGHTTP2_PROTO_ALPN_LEN) == 0) { + return 1; + } + if (select_alpn(out, outlen, in, inlen, NGHTTP2_HTTP_1_1_ALPN, + NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) { return 0; } return -1; diff --git a/deps/nghttp2/lib/nghttp2_npn.h b/deps/nghttp2/lib/nghttp2_alpn.h similarity index 94% rename from deps/nghttp2/lib/nghttp2_npn.h rename to deps/nghttp2/lib/nghttp2_alpn.h index c6f1c04b683594..09810fd821490a 100644 --- a/deps/nghttp2/lib/nghttp2_npn.h +++ b/deps/nghttp2/lib/nghttp2_alpn.h @@ -22,8 +22,8 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef NGHTTP2_NPN_H -#define NGHTTP2_NPN_H +#ifndef NGHTTP2_ALPN_H +#define NGHTTP2_ALPN_H #ifdef HAVE_CONFIG_H # include @@ -31,4 +31,4 @@ #include -#endif /* NGHTTP2_NPN_H */ +#endif /* NGHTTP2_ALPN_H */ diff --git a/deps/nghttp2/lib/nghttp2_buf.c b/deps/nghttp2/lib/nghttp2_buf.c index a32844712e4493..101035f923ec64 100644 --- a/deps/nghttp2/lib/nghttp2_buf.c +++ b/deps/nghttp2/lib/nghttp2_buf.c @@ -430,7 +430,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) { return 0; } -ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) { +nghttp2_ssize nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) { size_t len; nghttp2_buf_chain *chain; nghttp2_buf *buf; @@ -462,7 +462,7 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) { *out = res; - return (ssize_t)len; + return (nghttp2_ssize)len; } size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) { diff --git a/deps/nghttp2/lib/nghttp2_buf.h b/deps/nghttp2/lib/nghttp2_buf.h index 45f62f16e271dc..95ff3706a232a3 100644 --- a/deps/nghttp2/lib/nghttp2_buf.h +++ b/deps/nghttp2/lib/nghttp2_buf.h @@ -349,7 +349,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b); * NGHTTP2_ERR_NOMEM * Out of memory */ -ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out); +nghttp2_ssize nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out); /* * Copies all data stored in |bufs| to |out|. This function assumes diff --git a/deps/nghttp2/lib/nghttp2_callbacks.c b/deps/nghttp2/lib/nghttp2_callbacks.c index 3c38214859b17a..1776f7d276b79f 100644 --- a/deps/nghttp2/lib/nghttp2_callbacks.c +++ b/deps/nghttp2/lib/nghttp2_callbacks.c @@ -45,11 +45,21 @@ void nghttp2_session_callbacks_set_send_callback( cbs->send_callback = send_callback; } +void nghttp2_session_callbacks_set_send_callback2( + nghttp2_session_callbacks *cbs, nghttp2_send_callback2 send_callback) { + cbs->send_callback2 = send_callback; +} + void nghttp2_session_callbacks_set_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) { cbs->recv_callback = recv_callback; } +void nghttp2_session_callbacks_set_recv_callback2( + nghttp2_session_callbacks *cbs, nghttp2_recv_callback2 recv_callback) { + cbs->recv_callback2 = recv_callback; +} + void nghttp2_session_callbacks_set_on_frame_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_on_frame_recv_callback on_frame_recv_callback) { @@ -128,12 +138,24 @@ void nghttp2_session_callbacks_set_select_padding_callback( cbs->select_padding_callback = select_padding_callback; } +void nghttp2_session_callbacks_set_select_padding_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_select_padding_callback2 select_padding_callback) { + cbs->select_padding_callback2 = select_padding_callback; +} + void nghttp2_session_callbacks_set_data_source_read_length_callback( nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback data_source_read_length_callback) { cbs->read_length_callback = data_source_read_length_callback; } +void nghttp2_session_callbacks_set_data_source_read_length_callback2( + nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback2 + data_source_read_length_callback) { + cbs->read_length_callback2 = data_source_read_length_callback; +} + void nghttp2_session_callbacks_set_on_begin_frame_callback( nghttp2_session_callbacks *cbs, nghttp2_on_begin_frame_callback on_begin_frame_callback) { @@ -152,6 +174,12 @@ void nghttp2_session_callbacks_set_pack_extension_callback( cbs->pack_extension_callback = pack_extension_callback; } +void nghttp2_session_callbacks_set_pack_extension_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_pack_extension_callback2 pack_extension_callback) { + cbs->pack_extension_callback2 = pack_extension_callback; +} + void nghttp2_session_callbacks_set_unpack_extension_callback( nghttp2_session_callbacks *cbs, nghttp2_unpack_extension_callback unpack_extension_callback) { diff --git a/deps/nghttp2/lib/nghttp2_callbacks.h b/deps/nghttp2/lib/nghttp2_callbacks.h index 61e51fa53638de..a611f485481e7c 100644 --- a/deps/nghttp2/lib/nghttp2_callbacks.h +++ b/deps/nghttp2/lib/nghttp2_callbacks.h @@ -35,20 +35,34 @@ * Callback functions. */ struct nghttp2_session_callbacks { + /** + * Deprecated. Use send_callback2 instead. Callback function + * invoked when the session wants to send data to the remote peer. + * This callback is not necessary if the application uses solely + * `nghttp2_session_mem_send()` to serialize data to transmit. + */ + nghttp2_send_callback send_callback; /** * Callback function invoked when the session wants to send data to * the remote peer. This callback is not necessary if the - * application uses solely `nghttp2_session_mem_send()` to serialize - * data to transmit. + * application uses solely `nghttp2_session_mem_send2()` to + * serialize data to transmit. */ - nghttp2_send_callback send_callback; + nghttp2_send_callback2 send_callback2; + /** + * Deprecated. Use recv_callback2 instead. Callback function + * invoked when the session wants to receive data from the remote + * peer. This callback is not necessary if the application uses + * solely `nghttp2_session_mem_recv()` to process received data. + */ + nghttp2_recv_callback recv_callback; /** * Callback function invoked when the session wants to receive data * from the remote peer. This callback is not necessary if the - * application uses solely `nghttp2_session_mem_recv()` to process + * application uses solely `nghttp2_session_mem_recv2()` to process * received data. */ - nghttp2_recv_callback recv_callback; + nghttp2_recv_callback2 recv_callback2; /** * Callback function invoked by `nghttp2_session_recv()` when a * frame is received. @@ -99,23 +113,40 @@ struct nghttp2_session_callbacks { */ nghttp2_on_invalid_header_callback on_invalid_header_callback; nghttp2_on_invalid_header_callback2 on_invalid_header_callback2; + /** + * Deprecated. Use select_padding_callback2 instead. Callback + * function invoked when the library asks application how many + * padding bytes are required for the transmission of the given + * frame. + */ + nghttp2_select_padding_callback select_padding_callback; /** * Callback function invoked when the library asks application how * many padding bytes are required for the transmission of the given * frame. */ - nghttp2_select_padding_callback select_padding_callback; + nghttp2_select_padding_callback2 select_padding_callback2; /** - * The callback function used to determine the length allowed in + * Deprecated. Use read_length_callback2 instead. The callback + * function used to determine the length allowed in * `nghttp2_data_source_read_callback()` */ nghttp2_data_source_read_length_callback read_length_callback; + /** + * The callback function used to determine the length allowed in + * `nghttp2_data_source_read_callback2()` + */ + nghttp2_data_source_read_length_callback2 read_length_callback2; /** * Sets callback function invoked when a frame header is received. */ nghttp2_on_begin_frame_callback on_begin_frame_callback; nghttp2_send_data_callback send_data_callback; + /** + * Deprecated. Use pack_extension_callback2 instead. + */ nghttp2_pack_extension_callback pack_extension_callback; + nghttp2_pack_extension_callback2 pack_extension_callback2; nghttp2_unpack_extension_callback unpack_extension_callback; nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback; nghttp2_error_callback error_callback; diff --git a/deps/nghttp2/lib/nghttp2_extpri.c b/deps/nghttp2/lib/nghttp2_extpri.c index 3fd9b78163e323..ba0263e7c8eb28 100644 --- a/deps/nghttp2/lib/nghttp2_extpri.c +++ b/deps/nghttp2/lib/nghttp2_extpri.c @@ -24,6 +24,7 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "nghttp2_extpri.h" +#include "nghttp2_http.h" uint8_t nghttp2_extpri_to_uint8(const nghttp2_extpri *extpri) { return (uint8_t)((uint32_t)extpri->inc << 7 | extpri->urgency); @@ -33,3 +34,8 @@ void nghttp2_extpri_from_uint8(nghttp2_extpri *extpri, uint8_t u8extpri) { extpri->urgency = nghttp2_extpri_uint8_urgency(u8extpri); extpri->inc = nghttp2_extpri_uint8_inc(u8extpri); } + +int nghttp2_extpri_parse_priority(nghttp2_extpri *extpri, const uint8_t *value, + size_t len) { + return nghttp2_http_parse_priority(extpri, value, len); +} diff --git a/deps/nghttp2/lib/nghttp2_hd.c b/deps/nghttp2/lib/nghttp2_hd.c index 8a2bda64c1fe46..1b0c71331ae61f 100644 --- a/deps/nghttp2/lib/nghttp2_hd.c +++ b/deps/nghttp2/lib/nghttp2_hd.c @@ -850,9 +850,10 @@ static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) { * in the next call will be stored in |*shift_ptr|) and returns number * of bytes processed, or returns -1, indicating decoding error. */ -static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin, - uint32_t initial, size_t shift, const uint8_t *in, - const uint8_t *last, size_t prefix) { +static nghttp2_ssize decode_length(uint32_t *res, size_t *shift_ptr, int *fin, + uint32_t initial, size_t shift, + const uint8_t *in, const uint8_t *last, + size_t prefix) { uint32_t k = (uint8_t)((1 << prefix) - 1); uint32_t n = initial; const uint8_t *start = in; @@ -871,7 +872,7 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin, if (++in == last) { *res = n; - return (ssize_t)(in - start); + return (nghttp2_ssize)(in - start); } } @@ -906,12 +907,12 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin, if (in == last) { *res = n; - return (ssize_t)(in - start); + return (nghttp2_ssize)(in - start); } *res = n; *fin = 1; - return (ssize_t)(in + 1 - start); + return (nghttp2_ssize)(in + 1 - start); } static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) { @@ -1164,7 +1165,7 @@ static int add_hd_table_incremental(nghttp2_hd_context *context, } typedef struct { - ssize_t index; + nghttp2_ssize index; /* Nonzero if both name and value are matched. */ int name_value_match; } search_result; @@ -1213,8 +1214,8 @@ static search_result search_hd_table(nghttp2_hd_context *context, return res; } - res.index = - (ssize_t)(context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH); + res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq + + NGHTTP2_STATIC_TABLE_LENGTH); res.name_value_match = exact_match; return res; @@ -1343,7 +1344,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, const nghttp2_nv *nv) { int rv; search_result res; - ssize_t idx; + nghttp2_ssize idx; int indexing_mode; int32_t token; nghttp2_mem *mem; @@ -1379,7 +1380,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, if (res.name_value_match) { - DEBUGF("deflatehd: name/value match index=%zd\n", idx); + DEBUGF("deflatehd: name/value match index=%td\n", idx); rv = emit_indexed_block(bufs, (size_t)idx); if (rv != 0) { @@ -1390,7 +1391,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, } if (res.index != -1) { - DEBUGF("deflatehd: name match index=%zd\n", res.index); + DEBUGF("deflatehd: name match index=%td\n", res.index); } if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) { @@ -1491,6 +1492,12 @@ int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater, ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, size_t buflen, const nghttp2_nv *nv, size_t nvlen) { + return (ssize_t)nghttp2_hd_deflate_hd2(deflater, buf, buflen, nv, nvlen); +} + +nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater, + uint8_t *buf, size_t buflen, + const nghttp2_nv *nv, size_t nvlen) { nghttp2_bufs bufs; int rv; nghttp2_mem *mem; @@ -1517,12 +1524,18 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, return rv; } - return (ssize_t)buflen; + return (nghttp2_ssize)buflen; } ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, const nghttp2_vec *vec, size_t veclen, const nghttp2_nv *nv, size_t nvlen) { + return (ssize_t)nghttp2_hd_deflate_hd_vec2(deflater, vec, veclen, nv, nvlen); +} + +nghttp2_ssize nghttp2_hd_deflate_hd_vec2(nghttp2_hd_deflater *deflater, + const nghttp2_vec *vec, size_t veclen, + const nghttp2_nv *nv, size_t nvlen) { nghttp2_bufs bufs; int rv; nghttp2_mem *mem; @@ -1550,7 +1563,7 @@ ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, return rv; } - return (ssize_t)buflen; + return (nghttp2_ssize)buflen; } size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, @@ -1643,10 +1656,11 @@ static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater, * NGHTTP2_ERR_HEADER_COMP * Integer decoding failed */ -static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin, - const uint8_t *in, const uint8_t *last, - size_t prefix, size_t maxlen) { - ssize_t rv; +static nghttp2_ssize hd_inflate_read_len(nghttp2_hd_inflater *inflater, + int *rfin, const uint8_t *in, + const uint8_t *last, size_t prefix, + size_t maxlen) { + nghttp2_ssize rv; uint32_t out; *rfin = 0; @@ -1684,10 +1698,10 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin, * NGHTTP2_ERR_HEADER_COMP * Huffman decoding failed */ -static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater, - nghttp2_buf *buf, const uint8_t *in, - const uint8_t *last) { - ssize_t readlen; +static nghttp2_ssize hd_inflate_read_huff(nghttp2_hd_inflater *inflater, + nghttp2_buf *buf, const uint8_t *in, + const uint8_t *last) { + nghttp2_ssize readlen; int fin = 0; if ((size_t)(last - in) >= inflater->left) { last = in + inflater->left; @@ -1721,14 +1735,15 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater, * NGHTTP2_ERR_HEADER_COMP * Header decompression failed */ -static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf, - const uint8_t *in, const uint8_t *last) { +static nghttp2_ssize hd_inflate_read(nghttp2_hd_inflater *inflater, + nghttp2_buf *buf, const uint8_t *in, + const uint8_t *last) { size_t len = nghttp2_min((size_t)(last - in), inflater->left); buf->last = nghttp2_cpymem(buf->last, in, len); inflater->left -= len; - return (ssize_t)len; + return (nghttp2_ssize)len; } /* @@ -1843,7 +1858,15 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, const uint8_t *in, size_t inlen, int in_final) { - ssize_t rv; + return (nghttp2_ssize)nghttp2_hd_inflate_hd3(inflater, nv_out, inflate_flags, + in, inlen, in_final); +} + +nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater, + nghttp2_nv *nv_out, int *inflate_flags, + const uint8_t *in, size_t inlen, + int in_final) { + nghttp2_ssize rv; nghttp2_hd_nv hd_nv; rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen, @@ -1866,11 +1889,11 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, return rv; } -ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, - nghttp2_hd_nv *nv_out, int *inflate_flags, - const uint8_t *in, size_t inlen, - int in_final) { - ssize_t rv = 0; +nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, + nghttp2_hd_nv *nv_out, + int *inflate_flags, const uint8_t *in, + size_t inlen, int in_final) { + nghttp2_ssize rv = 0; const uint8_t *first = in; const uint8_t *last = in + inlen; int rfin = 0; @@ -1992,7 +2015,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, inflater->state = NGHTTP2_HD_STATE_OPCODE; *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } else { inflater->index = inflater->left; --inflater->index; @@ -2050,7 +2073,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, in += rv; - DEBUGF("inflatehd: %zd bytes read\n", rv); + DEBUGF("inflatehd: %td bytes read\n", rv); if (inflater->left) { DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left); @@ -2072,7 +2095,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, in += rv; - DEBUGF("inflatehd: %zd bytes read\n", rv); + DEBUGF("inflatehd: %td bytes read\n", rv); if (inflater->left) { DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left); @@ -2138,7 +2161,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, in += rv; - DEBUGF("inflatehd: %zd bytes read\n", rv); + DEBUGF("inflatehd: %td bytes read\n", rv); if (inflater->left) { DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left); @@ -2162,18 +2185,18 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, inflater->state = NGHTTP2_HD_STATE_OPCODE; *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); case NGHTTP2_HD_STATE_READ_VALUE: rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last); if (rv < 0) { - DEBUGF("inflatehd: value read failure %zd: %s\n", rv, + DEBUGF("inflatehd: value read failure %td: %s\n", rv, nghttp2_strerror((int)rv)); goto fail; } in += rv; - DEBUGF("inflatehd: %zd bytes read\n", rv); + DEBUGF("inflatehd: %td bytes read\n", rv); if (inflater->left) { DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left); @@ -2196,7 +2219,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, inflater->state = NGHTTP2_HD_STATE_OPCODE; *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } } @@ -2216,7 +2239,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, } *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL; } - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); almost_ok: if (in_final) { @@ -2226,10 +2249,10 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, goto fail; } - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); fail: - DEBUGF("inflatehd: error return %zd\n", rv); + DEBUGF("inflatehd: error return %td\n", rv); inflater->ctx.bad = 1; return rv; @@ -2297,9 +2320,10 @@ int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) { return emit_table_size(bufs, table_size); } -ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin, - uint32_t initial, size_t shift, uint8_t *in, - uint8_t *last, size_t prefix) { +nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, + int *fin, uint32_t initial, size_t shift, + uint8_t *in, uint8_t *last, + size_t prefix) { return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix); } diff --git a/deps/nghttp2/lib/nghttp2_hd.h b/deps/nghttp2/lib/nghttp2_hd.h index 6de0052aaea6cd..38a31a83c3891d 100644 --- a/deps/nghttp2/lib/nghttp2_hd.h +++ b/deps/nghttp2/lib/nghttp2_hd.h @@ -357,9 +357,10 @@ void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater); * that return values and semantics are the same as * nghttp2_hd_inflate_hd(). */ -ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, - nghttp2_hd_nv *nv_out, int *inflate_flags, - const uint8_t *in, size_t inlen, int in_final); +nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, + nghttp2_hd_nv *nv_out, + int *inflate_flags, const uint8_t *in, + size_t inlen, int in_final); /* For unittesting purpose */ int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index, @@ -376,9 +377,10 @@ int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size); nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index); /* For unittesting purpose */ -ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin, - uint32_t initial, size_t shift, uint8_t *in, - uint8_t *last, size_t prefix); +nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, + int *fin, uint32_t initial, size_t shift, + uint8_t *in, uint8_t *last, + size_t prefix); /* Huffman encoding/decoding functions */ @@ -427,9 +429,9 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx); * NGHTTP2_ERR_HEADER_COMP * Decoding process has failed. */ -ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, - nghttp2_buf *buf, const uint8_t *src, - size_t srclen, int fin); +nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, + nghttp2_buf *buf, const uint8_t *src, + size_t srclen, int fin); /* * nghttp2_hd_huff_decode_failure_state returns nonzero if |ctx| diff --git a/deps/nghttp2/lib/nghttp2_hd_huffman.c b/deps/nghttp2/lib/nghttp2_hd_huffman.c index ac90f49c44f147..959053f774eda3 100644 --- a/deps/nghttp2/lib/nghttp2_hd_huffman.c +++ b/deps/nghttp2/lib/nghttp2_hd_huffman.c @@ -107,9 +107,9 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) { ctx->fstate = NGHTTP2_HUFF_ACCEPTED; } -ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, - nghttp2_buf *buf, const uint8_t *src, - size_t srclen, int final) { +nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, + nghttp2_buf *buf, const uint8_t *src, + size_t srclen, int final) { const uint8_t *end = src + srclen; nghttp2_huff_decode node = {ctx->fstate, 0}; const nghttp2_huff_decode *t = &node; @@ -136,7 +136,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, return NGHTTP2_ERR_HEADER_COMP; } - return (ssize_t)srclen; + return (nghttp2_ssize)srclen; } int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx) { diff --git a/deps/nghttp2/lib/nghttp2_helper.c b/deps/nghttp2/lib/nghttp2_helper.c index 93dd4754b7f304..b3563d98e0d910 100644 --- a/deps/nghttp2/lib/nghttp2_helper.c +++ b/deps/nghttp2/lib/nghttp2_helper.c @@ -336,6 +336,8 @@ const char *nghttp2_strerror(int error_code) { "closed"; case NGHTTP2_ERR_TOO_MANY_SETTINGS: return "SETTINGS frame contained more than the maximum allowed entries"; + case NGHTTP2_ERR_TOO_MANY_CONTINUATIONS: + return "Too many CONTINUATION frames following a HEADER frame"; default: return "Unknown error code"; } diff --git a/deps/nghttp2/lib/nghttp2_map.c b/deps/nghttp2/lib/nghttp2_map.c index 5f63fc2bb87e99..0aaaf29155cd02 100644 --- a/deps/nghttp2/lib/nghttp2_map.c +++ b/deps/nghttp2/lib/nghttp2_map.c @@ -126,6 +126,7 @@ static void map_bucket_set_data(nghttp2_map_bucket *bkt, uint32_t hash, bkt->data = data; } +#ifndef WIN32 void nghttp2_map_print_distance(nghttp2_map *map) { uint32_t i; size_t idx; @@ -145,6 +146,7 @@ void nghttp2_map_print_distance(nghttp2_map *map) { distance(map->tablelen, map->tablelenbits, bkt, idx)); } } +#endif /* !WIN32 */ static int insert(nghttp2_map_bucket *table, uint32_t tablelen, uint32_t tablelenbits, uint32_t hash, diff --git a/deps/nghttp2/lib/nghttp2_map.h b/deps/nghttp2/lib/nghttp2_map.h index d90245aab74c97..236d28296e31da 100644 --- a/deps/nghttp2/lib/nghttp2_map.h +++ b/deps/nghttp2/lib/nghttp2_map.h @@ -131,6 +131,8 @@ size_t nghttp2_map_size(nghttp2_map *map); int nghttp2_map_each(nghttp2_map *map, int (*func)(void *data, void *ptr), void *ptr); +#ifndef WIN32 void nghttp2_map_print_distance(nghttp2_map *map); +#endif /* !WIN32 */ #endif /* NGHTTP2_MAP_H */ diff --git a/deps/nghttp2/lib/nghttp2_option.c b/deps/nghttp2/lib/nghttp2_option.c index 43d4e952291ba4..53144b9b75c289 100644 --- a/deps/nghttp2/lib/nghttp2_option.c +++ b/deps/nghttp2/lib/nghttp2_option.c @@ -150,3 +150,8 @@ void nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option, option->stream_reset_burst = burst; option->stream_reset_rate = rate; } + +void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val) { + option->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS; + option->max_continuations = val; +} diff --git a/deps/nghttp2/lib/nghttp2_option.h b/deps/nghttp2/lib/nghttp2_option.h index 2259e1849d810f..c89cb97f8bb685 100644 --- a/deps/nghttp2/lib/nghttp2_option.h +++ b/deps/nghttp2/lib/nghttp2_option.h @@ -71,6 +71,7 @@ typedef enum { NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 13, NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14, NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15, + NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16, } nghttp2_option_flag; /** @@ -98,6 +99,10 @@ struct nghttp2_option { * NGHTTP2_OPT_MAX_SETTINGS */ size_t max_settings; + /** + * NGHTTP2_OPT_MAX_CONTINUATIONS + */ + size_t max_continuations; /** * Bitwise OR of nghttp2_option_flag to determine that which fields * are specified. diff --git a/deps/nghttp2/lib/nghttp2_outbound_item.c b/deps/nghttp2/lib/nghttp2_outbound_item.c index 2a3041db195355..a9e9f7693eda8c 100644 --- a/deps/nghttp2/lib/nghttp2_outbound_item.c +++ b/deps/nghttp2/lib/nghttp2_outbound_item.c @@ -27,6 +27,32 @@ #include #include +nghttp2_data_provider_wrap * +nghttp2_data_provider_wrap_v1(nghttp2_data_provider_wrap *dpw, + const nghttp2_data_provider *data_prd) { + if (!data_prd) { + return NULL; + } + + dpw->version = NGHTTP2_DATA_PROVIDER_V1; + dpw->data_prd.v1 = *data_prd; + + return dpw; +} + +nghttp2_data_provider_wrap * +nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw, + const nghttp2_data_provider2 *data_prd) { + if (!data_prd) { + return NULL; + } + + dpw->version = NGHTTP2_DATA_PROVIDER_V2; + dpw->data_prd.v2 = *data_prd; + + return dpw; +} + void nghttp2_outbound_item_init(nghttp2_outbound_item *item) { item->cycle = 0; item->qnext = NULL; diff --git a/deps/nghttp2/lib/nghttp2_outbound_item.h b/deps/nghttp2/lib/nghttp2_outbound_item.h index bd4611b551bbbd..4e91750088f809 100644 --- a/deps/nghttp2/lib/nghttp2_outbound_item.h +++ b/deps/nghttp2/lib/nghttp2_outbound_item.h @@ -33,9 +33,32 @@ #include "nghttp2_frame.h" #include "nghttp2_mem.h" +#define NGHTTP2_DATA_PROVIDER_V1 1 +#define NGHTTP2_DATA_PROVIDER_V2 2 + +typedef struct nghttp2_data_provider_wrap { + int version; + union { + struct { + nghttp2_data_source source; + void *read_callback; + }; + nghttp2_data_provider v1; + nghttp2_data_provider2 v2; + } data_prd; +} nghttp2_data_provider_wrap; + +nghttp2_data_provider_wrap * +nghttp2_data_provider_wrap_v1(nghttp2_data_provider_wrap *dpw, + const nghttp2_data_provider *data_prd); + +nghttp2_data_provider_wrap * +nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw, + const nghttp2_data_provider2 *data_prd); + /* struct used for HEADERS and PUSH_PROMISE frame */ typedef struct { - nghttp2_data_provider data_prd; + nghttp2_data_provider_wrap dpw; void *stream_user_data; /* error code when request HEADERS is canceled by RST_STREAM while it is in queue. */ @@ -50,7 +73,7 @@ typedef struct { /** * The data to be sent for this DATA frame. */ - nghttp2_data_provider data_prd; + nghttp2_data_provider_wrap dpw; /** * The flags of DATA frame. We use separate flags here and * nghttp2_data frame. The latter contains flags actually sent to diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c index ec5024d0f2168e..004a4dffaa7903 100644 --- a/deps/nghttp2/lib/nghttp2_session.c +++ b/deps/nghttp2/lib/nghttp2_session.c @@ -39,6 +39,7 @@ #include "nghttp2_extpri.h" #include "nghttp2_time.h" #include "nghttp2_debug.h" +#include "nghttp2_submit.h" /* * Returns non-zero if the number of outgoing opened streams is larger @@ -496,6 +497,7 @@ static int session_new(nghttp2_session **session_ptr, (*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN; (*session_ptr)->max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; (*session_ptr)->max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS; + (*session_ptr)->max_continuations = NGHTTP2_DEFAULT_MAX_CONTINUATIONS; if (option) { if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) && @@ -584,6 +586,10 @@ static int session_new(nghttp2_session **session_ptr, option->stream_reset_burst, option->stream_reset_rate); } + + if (option->opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS) { + (*session_ptr)->max_continuations = option->max_continuations; + } } rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater, @@ -978,7 +984,14 @@ static int session_attach_stream_item(nghttp2_session *session, return 0; } - return session_ob_data_push(session, stream); + rv = session_ob_data_push(session, stream); + if (rv != 0) { + nghttp2_stream_detach_item(stream); + + return rv; + } + + return 0; } static void session_detach_stream_item(nghttp2_session *session, @@ -1308,9 +1321,11 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, assert((stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) || nghttp2_stream_in_dep_tree(stream)); + nghttp2_session_detach_idle_stream(session, stream); + if (nghttp2_stream_in_dep_tree(stream)) { assert(!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)); - nghttp2_session_detach_idle_stream(session, stream); + rv = nghttp2_stream_dep_remove(stream); if (rv != 0) { return NULL; @@ -1470,6 +1485,21 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, DEBUGF("stream: stream(%p)=%d close\n", stream, stream->stream_id); + /* We call on_stream_close_callback even if stream->state is + NGHTTP2_STREAM_INITIAL. This will happen while sending request + HEADERS, a local endpoint receives RST_STREAM for that stream. It + may be PROTOCOL_ERROR, but without notifying stream closure will + hang the stream in a local endpoint. + */ + + if (session->callbacks.on_stream_close_callback) { + if (session->callbacks.on_stream_close_callback( + session, stream_id, error_code, session->user_data) != 0) { + + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + if (stream->item) { nghttp2_outbound_item *item; @@ -1487,21 +1517,6 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, } } - /* We call on_stream_close_callback even if stream->state is - NGHTTP2_STREAM_INITIAL. This will happen while sending request - HEADERS, a local endpoint receives RST_STREAM for that stream. It - may be PROTOCOL_ERROR, but without notifying stream closure will - hang the stream in a local endpoint. - */ - - if (session->callbacks.on_stream_close_callback) { - if (session->callbacks.on_stream_close_callback( - session, stream_id, error_code, session->user_data) != 0) { - - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - } - is_my_stream_id = nghttp2_session_is_my_stream_id(session, stream_id); /* pushed streams which is not opened yet is not counted toward max @@ -1558,6 +1573,11 @@ int nghttp2_session_destroy_stream(nghttp2_session *session, } } + if (stream->queued && + (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)) { + session_ob_data_remove(session, stream); + } + nghttp2_map_remove(&session->streams, stream->stream_id); nghttp2_stream_free(stream); nghttp2_mem_free(mem, stream); @@ -2103,10 +2123,9 @@ static int session_predicate_priority_update_send(nghttp2_session *session, /* Take into account settings max frame size and both connection-level flow control here */ -static ssize_t -nghttp2_session_enforce_flow_control_limits(nghttp2_session *session, - nghttp2_stream *stream, - ssize_t requested_window_size) { +static nghttp2_ssize nghttp2_session_enforce_flow_control_limits( + nghttp2_session *session, nghttp2_stream *stream, + nghttp2_ssize requested_window_size) { DEBUGF("send: remote windowsize connection=%d, remote maxframsize=%u, " "stream(id %d)=%d\n", session->remote_window_size, session->remote_settings.max_frame_size, @@ -2126,12 +2145,12 @@ nghttp2_session_enforce_flow_control_limits(nghttp2_session *session, */ static size_t nghttp2_session_next_data_read(nghttp2_session *session, nghttp2_stream *stream) { - ssize_t window_size; + nghttp2_ssize window_size; window_size = nghttp2_session_enforce_flow_control_limits( session, stream, NGHTTP2_DATA_PAYLOADLEN); - DEBUGF("send: available window=%zd\n", window_size); + DEBUGF("send: available window=%td\n", window_size); return window_size > 0 ? (size_t)window_size : 0; } @@ -2186,29 +2205,33 @@ static int nghttp2_session_predicate_data_send(nghttp2_session *session, return NGHTTP2_ERR_INVALID_STREAM_STATE; } -static ssize_t session_call_select_padding(nghttp2_session *session, - const nghttp2_frame *frame, - size_t max_payloadlen) { - ssize_t rv; +static nghttp2_ssize session_call_select_padding(nghttp2_session *session, + const nghttp2_frame *frame, + size_t max_payloadlen) { + nghttp2_ssize rv; + size_t max_paddedlen; - if (frame->hd.length >= max_payloadlen) { - return (ssize_t)frame->hd.length; + if (frame->hd.length >= max_payloadlen || + (!session->callbacks.select_padding_callback2 && + !session->callbacks.select_padding_callback)) { + return (nghttp2_ssize)frame->hd.length; } - if (session->callbacks.select_padding_callback) { - size_t max_paddedlen; - - max_paddedlen = - nghttp2_min(frame->hd.length + NGHTTP2_MAX_PADLEN, max_payloadlen); + max_paddedlen = + nghttp2_min(frame->hd.length + NGHTTP2_MAX_PADLEN, max_payloadlen); - rv = session->callbacks.select_padding_callback( + if (session->callbacks.select_padding_callback2) { + rv = session->callbacks.select_padding_callback2( session, frame, max_paddedlen, session->user_data); - if (rv < (ssize_t)frame->hd.length || rv > (ssize_t)max_paddedlen) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return rv; + } else { + rv = (nghttp2_ssize)session->callbacks.select_padding_callback( + session, frame, max_paddedlen, session->user_data); + } + if (rv < (nghttp2_ssize)frame->hd.length || + rv > (nghttp2_ssize)max_paddedlen) { + return NGHTTP2_ERR_CALLBACK_FAILURE; } - return (ssize_t)frame->hd.length; + return rv; } /* Add padding to HEADERS or PUSH_PROMISE. We use @@ -2216,7 +2239,7 @@ static ssize_t session_call_select_padding(nghttp2_session *session, frame->push_promise has also padlen in the same position. */ static int session_headers_add_pad(nghttp2_session *session, nghttp2_frame *frame) { - ssize_t padded_payloadlen; + nghttp2_ssize padded_payloadlen; nghttp2_active_outbound_item *aob; nghttp2_bufs *framebufs; size_t padlen; @@ -2237,7 +2260,7 @@ static int session_headers_add_pad(nghttp2_session *session, padlen = (size_t)padded_payloadlen - frame->hd.length; - DEBUGF("send: padding selected: payloadlen=%zd, padlen=%zu\n", + DEBUGF("send: padding selected: payloadlen=%td, padlen=%zu\n", padded_payloadlen, padlen); nghttp2_frame_add_pad(framebufs, &frame->hd, padlen, 0); @@ -2257,18 +2280,24 @@ static size_t session_estimate_headers_payload(nghttp2_session *session, static int session_pack_extension(nghttp2_session *session, nghttp2_bufs *bufs, nghttp2_frame *frame) { - ssize_t rv; + nghttp2_ssize rv; nghttp2_buf *buf; size_t buflen; size_t framelen; - assert(session->callbacks.pack_extension_callback); + assert(session->callbacks.pack_extension_callback2 || + session->callbacks.pack_extension_callback); buf = &bufs->head->buf; buflen = nghttp2_min(nghttp2_buf_avail(buf), NGHTTP2_MAX_PAYLOADLEN); - rv = session->callbacks.pack_extension_callback(session, buf->last, buflen, - frame, session->user_data); + if (session->callbacks.pack_extension_callback2) { + rv = session->callbacks.pack_extension_callback2(session, buf->last, buflen, + frame, session->user_data); + } else { + rv = (nghttp2_ssize)session->callbacks.pack_extension_callback( + session, buf->last, buflen, frame, session->user_data); + } if (rv == NGHTTP2_ERR_CANCEL) { return (int)rv; } @@ -2451,7 +2480,7 @@ static int session_prep_frame(nghttp2_session *session, return rv; } - DEBUGF("send: before padding, HEADERS serialized in %zd bytes\n", + DEBUGF("send: before padding, HEADERS serialized in %zu bytes\n", nghttp2_bufs_len(&session->aob.framebufs)); rv = session_headers_add_pad(session, frame); @@ -2460,7 +2489,7 @@ static int session_prep_frame(nghttp2_session *session, return rv; } - DEBUGF("send: HEADERS finally serialized in %zd bytes\n", + DEBUGF("send: HEADERS finally serialized in %zu bytes\n", nghttp2_bufs_len(&session->aob.framebufs)); if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { @@ -2877,7 +2906,7 @@ static int session_after_frame_sent1(nghttp2_session *session) { /* Call on_frame_send_callback after nghttp2_stream_detach_item(), so that application can issue - nghttp2_submit_data() in the callback. */ + nghttp2_submit_data2() in the callback. */ if (session->callbacks.on_frame_send_callback) { rv = session_call_on_frame_send(session, frame); if (nghttp2_is_fatal(rv)) { @@ -2949,15 +2978,17 @@ static int session_after_frame_sent1(nghttp2_session *session) { } /* We assume aux_data is a pointer to nghttp2_headers_aux_data */ aux_data = &item->aux_data.headers; - if (aux_data->data_prd.read_callback) { - /* nghttp2_submit_data() makes a copy of aux_data->data_prd */ - rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, - frame->hd.stream_id, &aux_data->data_prd); + if (aux_data->dpw.data_prd.read_callback) { + /* nghttp2_submit_data_shared() makes a copy of + aux_data->dpw */ + rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM, + frame->hd.stream_id, &aux_data->dpw); if (nghttp2_is_fatal(rv)) { return rv; } - /* TODO nghttp2_submit_data() may fail if stream has already - DATA frame item. We might have to handle it here. */ + /* TODO nghttp2_submit_data_shared() may fail if stream has + already DATA frame item. We might have to handle it + here. */ } return 0; } @@ -2978,14 +3009,15 @@ static int session_after_frame_sent1(nghttp2_session *session) { } /* We assume aux_data is a pointer to nghttp2_headers_aux_data */ aux_data = &item->aux_data.headers; - if (aux_data->data_prd.read_callback) { - rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, - frame->hd.stream_id, &aux_data->data_prd); + if (aux_data->dpw.data_prd.read_callback) { + rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM, + frame->hd.stream_id, &aux_data->dpw); if (nghttp2_is_fatal(rv)) { return rv; } - /* TODO nghttp2_submit_data() may fail if stream has already - DATA frame item. We might have to handle it here. */ + /* TODO nghttp2_submit_data_shared() may fail if stream has + already DATA frame item. We might have to handle it + here. */ } return 0; default: @@ -3144,7 +3176,7 @@ static void session_after_frame_sent2(nghttp2_session *session) { aux_data = &item->aux_data.data; /* On EOF, we have already detached data. Please note that - application may issue nghttp2_submit_data() in + application may issue nghttp2_submit_data2() in on_frame_send_callback (call from session_after_frame_sent1), which attach data to stream. We don't want to detach it. */ if (aux_data->eof) { @@ -3191,7 +3223,7 @@ static int session_call_send_data(nghttp2_session *session, aux_data = &item->aux_data.data; rv = session->callbacks.send_data_callback(session, frame, buf->pos, length, - &aux_data->data_prd.source, + &aux_data->dpw.data_prd.source, session->user_data); switch (rv) { @@ -3205,9 +3237,9 @@ static int session_call_send_data(nghttp2_session *session, } } -static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, - const uint8_t **data_ptr, - int fast_cb) { +static nghttp2_ssize nghttp2_session_mem_send_internal(nghttp2_session *session, + const uint8_t **data_ptr, + int fast_cb) { int rv; nghttp2_active_outbound_item *aob; nghttp2_bufs *framebufs; @@ -3302,7 +3334,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, } if (rv == NGHTTP2_ERR_HEADER_COMP) { - /* If header compression error occurred, should terminiate + /* If header compression error occurred, should terminate connection. */ rv = nghttp2_session_terminate_session(session, NGHTTP2_INTERNAL_ERROR); @@ -3385,7 +3417,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, } } - DEBUGF("send: start transmitting frame type=%u, length=%zd\n", + DEBUGF("send: start transmitting frame type=%u, length=%td\n", framebufs->cur->buf.pos[3], framebufs->cur->buf.last - framebufs->cur->buf.pos); @@ -3425,7 +3457,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, everything, we will adjust it. */ buf->pos += datalen; - return (ssize_t)datalen; + return (nghttp2_ssize)datalen; } case NGHTTP2_OB_SEND_NO_COPY: { nghttp2_stream *stream; @@ -3502,7 +3534,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, buf->pos += datalen; - return (ssize_t)datalen; + return (nghttp2_ssize)datalen; } } } @@ -3510,8 +3542,13 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, ssize_t nghttp2_session_mem_send(nghttp2_session *session, const uint8_t **data_ptr) { + return (ssize_t)nghttp2_session_mem_send2(session, data_ptr); +} + +nghttp2_ssize nghttp2_session_mem_send2(nghttp2_session *session, + const uint8_t **data_ptr) { int rv; - ssize_t len; + nghttp2_ssize len; *data_ptr = NULL; @@ -3528,7 +3565,7 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session, rv = session_after_frame_sent1(session); if (rv < 0) { assert(nghttp2_is_fatal(rv)); - return (ssize_t)rv; + return (nghttp2_ssize)rv; } } @@ -3537,8 +3574,8 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session, int nghttp2_session_send(nghttp2_session *session) { const uint8_t *data = NULL; - ssize_t datalen; - ssize_t sentlen; + nghttp2_ssize datalen; + nghttp2_ssize sentlen; nghttp2_bufs *framebufs; framebufs = &session->aob.framebufs; @@ -3548,8 +3585,13 @@ int nghttp2_session_send(nghttp2_session *session) { if (datalen <= 0) { return (int)datalen; } - sentlen = session->callbacks.send_callback(session, data, (size_t)datalen, - 0, session->user_data); + if (session->callbacks.send_callback2) { + sentlen = session->callbacks.send_callback2( + session, data, (size_t)datalen, 0, session->user_data); + } else { + sentlen = (nghttp2_ssize)session->callbacks.send_callback( + session, data, (size_t)datalen, 0, session->user_data); + } if (sentlen < 0) { if (sentlen == NGHTTP2_ERR_WOULDBLOCK) { /* Transmission canceled. Rewind the offset */ @@ -3564,11 +3606,17 @@ int nghttp2_session_send(nghttp2_session *session) { } } -static ssize_t session_recv(nghttp2_session *session, uint8_t *buf, - size_t len) { - ssize_t rv; - rv = session->callbacks.recv_callback(session, buf, len, 0, - session->user_data); +static nghttp2_ssize session_recv(nghttp2_session *session, uint8_t *buf, + size_t len) { + nghttp2_ssize rv; + + if (session->callbacks.recv_callback2) { + rv = session->callbacks.recv_callback2(session, buf, len, 0, + session->user_data); + } else { + rv = (nghttp2_ssize)session->callbacks.recv_callback(session, buf, len, 0, + session->user_data); + } if (rv > 0) { if ((size_t)rv > len) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -3870,7 +3918,7 @@ static int session_inflate_handle_invalid_connection(nghttp2_session *session, static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, size_t *readlen_ptr, uint8_t *in, size_t inlen, int final, int call_header_cb) { - ssize_t proclen; + nghttp2_ssize proclen; int rv; int inflate_flags; nghttp2_hd_nv nv; @@ -3923,7 +3971,7 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, inlen -= (size_t)proclen; *readlen_ptr += (size_t)proclen; - DEBUGF("recv: proclen=%zd\n", proclen); + DEBUGF("recv: proclen=%td\n", proclen); if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) { rv = 0; @@ -5763,7 +5811,7 @@ static int inbound_frame_handle_pad(nghttp2_inbound_frame *iframe, * Computes number of padding based on flags. This function returns * the calculated length if it succeeds, or -1. */ -static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) { +static nghttp2_ssize inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) { size_t padlen; /* 1 for Pad Length field */ @@ -5778,7 +5826,7 @@ static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) { iframe->padlen = padlen; - return (ssize_t)padlen; + return (nghttp2_ssize)padlen; } /* @@ -5787,9 +5835,9 @@ static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) { * |payloadleft| does not include |readlen|. If padding was started * strictly before this data chunk, this function returns -1. */ -static ssize_t inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe, - size_t payloadleft, - size_t readlen) { +static nghttp2_ssize +inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe, + size_t payloadleft, size_t readlen) { size_t trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen); @@ -5799,19 +5847,24 @@ static ssize_t inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe, if (readlen < padlen) { return -1; } - return (ssize_t)(readlen - padlen); + return (nghttp2_ssize)(readlen - padlen); } - return (ssize_t)(readlen); + return (nghttp2_ssize)(readlen); } static const uint8_t static_in[] = {0}; ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, size_t inlen) { + return (ssize_t)nghttp2_session_mem_recv2(session, in, inlen); +} + +nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + const uint8_t *in, size_t inlen) { const uint8_t *first, *last; nghttp2_inbound_frame *iframe = &session->iframe; size_t readlen; - ssize_t padlen; + nghttp2_ssize padlen; int rv; int busy = 0; nghttp2_frame_hd cont_hd; @@ -5841,7 +5894,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (!nghttp2_session_want_read(session)) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } for (;;) { @@ -5871,7 +5924,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, in += readlen; if (nghttp2_buf_mark_avail(&iframe->sbuf)) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS || @@ -5893,7 +5946,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->state = NGHTTP2_IB_READ_HEAD; @@ -5908,7 +5961,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, in += readlen; if (nghttp2_buf_mark_avail(&iframe->sbuf)) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } nghttp2_frame_unpack_frame_hd(&iframe->frame.hd, iframe->sbuf.pos); @@ -5929,7 +5982,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } switch (iframe->frame.hd.type) { @@ -5944,7 +5997,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, rv = session_on_data_received_fail_fast(session); if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_IGN_PAYLOAD) { DEBUGF("recv: DATA not allowed stream_id=%d\n", @@ -5966,7 +6019,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == 1) { @@ -5993,7 +6046,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == 1) { @@ -6036,7 +6089,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, busy = 1; if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -6137,7 +6190,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) * @@ -6175,7 +6228,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == 1) { @@ -6235,7 +6288,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; default: DEBUGF("recv: extension frame\n"); @@ -6346,7 +6399,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (iframe->payloadleft < 4) { @@ -6404,11 +6457,11 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, in += readlen; iframe->payloadleft -= readlen; - DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zd\n", readlen, + DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zu\n", readlen, iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf)); if (nghttp2_buf_mark_avail(&iframe->sbuf)) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } switch (iframe->frame.hd.type) { @@ -6424,7 +6477,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->frame.headers.padlen = (size_t)padlen; @@ -6451,7 +6504,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, busy = 1; if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -6481,7 +6534,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } } @@ -6495,7 +6548,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6513,7 +6566,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->frame.push_promise.padlen = (size_t)padlen; @@ -6539,7 +6592,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, busy = 1; if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -6568,7 +6621,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6603,7 +6656,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6661,7 +6714,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, break; case NGHTTP2_IB_READ_HEADER_BLOCK: case NGHTTP2_IB_IGN_HEADER_BLOCK: { - ssize_t data_readlen; + nghttp2_ssize data_readlen; size_t trail_padlen; int final; #ifdef DEBUGBUILD @@ -6705,14 +6758,14 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_PAUSE) { in += hd_proclen; iframe->payloadleft -= hd_proclen; - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -6778,6 +6831,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } } session_inbound_frame_reset(session); + + session->num_continuations = 0; } break; } @@ -6819,7 +6874,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, assert(iframe->state == NGHTTP2_IB_IGN_ALL); - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; case NGHTTP2_IB_READ_SETTINGS: DEBUGF("recv: [IB_READ_SETTINGS]\n"); @@ -6849,7 +6904,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6883,7 +6938,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6899,11 +6954,15 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } #endif /* DEBUGBUILD */ + if (++session->num_continuations > session->max_continuations) { + return NGHTTP2_ERR_TOO_MANY_CONTINUATIONS; + } + readlen = inbound_frame_buf_read(iframe, in, last); in += readlen; if (nghttp2_buf_mark_avail(&iframe->sbuf)) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } nghttp2_frame_unpack_frame_hd(&cont_hd, iframe->sbuf.pos); @@ -6925,7 +6984,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } /* CONTINUATION won't bear NGHTTP2_PADDED flag */ @@ -6961,7 +7020,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf)); if (nghttp2_buf_mark_avail(&iframe->sbuf)) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } /* Pad Length field is subject to flow control */ @@ -6971,7 +7030,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } /* Pad Length field is consumed immediately */ @@ -6983,7 +7042,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id); @@ -7006,7 +7065,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->frame.data.padlen = (size_t)padlen; @@ -7033,7 +7092,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, iframe->payloadleft); if (readlen > 0) { - ssize_t data_readlen; + nghttp2_ssize data_readlen; rv = nghttp2_session_update_recv_connection_window_size(session, readlen); @@ -7042,7 +7101,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } rv = nghttp2_session_update_recv_stream_window_size( @@ -7061,7 +7120,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, data_readlen = 0; } - padlen = (ssize_t)readlen - data_readlen; + padlen = (nghttp2_ssize)readlen - data_readlen; if (padlen > 0) { /* Padding is considered as "consumed" immediately */ @@ -7073,11 +7132,11 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } } - DEBUGF("recv: data_readlen=%zd\n", data_readlen); + DEBUGF("recv: data_readlen=%td\n", data_readlen); if (data_readlen > 0) { if (session_enforce_http_messaging(session)) { @@ -7092,7 +7151,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_DATA) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } } @@ -7111,7 +7170,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, session, iframe->frame.hd.flags, iframe->frame.hd.stream_id, in - readlen, (size_t)data_readlen, session->user_data); if (rv == NGHTTP2_ERR_PAUSE) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } if (nghttp2_is_fatal(rv)) { @@ -7153,7 +7212,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { @@ -7166,7 +7225,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } } } @@ -7179,7 +7238,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, break; case NGHTTP2_IB_IGN_ALL: - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; case NGHTTP2_IB_READ_EXTENSION_PAYLOAD: DEBUGF("recv: [IB_READ_EXTENSION_PAYLOAD]\n"); @@ -7274,7 +7333,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -7291,16 +7350,17 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, assert(in == last); - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } int nghttp2_session_recv(nghttp2_session *session) { uint8_t buf[NGHTTP2_INBOUND_BUFFER_LENGTH]; while (1) { - ssize_t readlen; + nghttp2_ssize readlen; readlen = session_recv(session, buf, sizeof(buf)); if (readlen > 0) { - ssize_t proclen = nghttp2_session_mem_recv(session, buf, (size_t)readlen); + nghttp2_ssize proclen = + nghttp2_session_mem_recv2(session, buf, (size_t)readlen); if (proclen < 0) { return (int)proclen; } @@ -7642,8 +7702,8 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, nghttp2_stream *stream) { int rv; uint32_t data_flags; - ssize_t payloadlen; - ssize_t padded_payloadlen; + nghttp2_ssize payloadlen; + nghttp2_ssize padded_payloadlen; nghttp2_buf *buf; size_t max_payloadlen; @@ -7651,19 +7711,26 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, buf = &bufs->cur->buf; - if (session->callbacks.read_length_callback) { - - payloadlen = session->callbacks.read_length_callback( - session, frame->hd.type, stream->stream_id, session->remote_window_size, - stream->remote_window_size, session->remote_settings.max_frame_size, - session->user_data); + if (session->callbacks.read_length_callback2 || + session->callbacks.read_length_callback) { + if (session->callbacks.read_length_callback2) { + payloadlen = session->callbacks.read_length_callback2( + session, frame->hd.type, stream->stream_id, + session->remote_window_size, stream->remote_window_size, + session->remote_settings.max_frame_size, session->user_data); + } else { + payloadlen = (nghttp2_ssize)session->callbacks.read_length_callback( + session, frame->hd.type, stream->stream_id, + session->remote_window_size, stream->remote_window_size, + session->remote_settings.max_frame_size, session->user_data); + } - DEBUGF("send: read_length_callback=%zd\n", payloadlen); + DEBUGF("send: read_length_callback=%td\n", payloadlen); payloadlen = nghttp2_session_enforce_flow_control_limits(session, stream, payloadlen); - DEBUGF("send: read_length_callback after flow control=%zd\n", payloadlen); + DEBUGF("send: read_length_callback after flow control=%td\n", payloadlen); if (payloadlen <= 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -7679,9 +7746,9 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, DEBUGF("send: realloc buffer failed rv=%d", rv); /* If reallocation failed, old buffers are still in tact. So use safe limit. */ - payloadlen = (ssize_t)datamax; + payloadlen = (nghttp2_ssize)datamax; - DEBUGF("send: use safe limit payloadlen=%zd", payloadlen); + DEBUGF("send: use safe limit payloadlen=%td", payloadlen); } else { assert(&session->aob.framebufs == bufs); @@ -7695,9 +7762,23 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, assert(nghttp2_buf_avail(buf) >= datamax); data_flags = NGHTTP2_DATA_FLAG_NONE; - payloadlen = aux_data->data_prd.read_callback( - session, frame->hd.stream_id, buf->pos, datamax, &data_flags, - &aux_data->data_prd.source, session->user_data); + switch (aux_data->dpw.version) { + case NGHTTP2_DATA_PROVIDER_V1: + payloadlen = (nghttp2_ssize)aux_data->dpw.data_prd.v1.read_callback( + session, frame->hd.stream_id, buf->pos, datamax, &data_flags, + &aux_data->dpw.data_prd.source, session->user_data); + + break; + case NGHTTP2_DATA_PROVIDER_V2: + payloadlen = aux_data->dpw.data_prd.v2.read_callback( + session, frame->hd.stream_id, buf->pos, datamax, &data_flags, + &aux_data->dpw.data_prd.source, session->user_data); + + break; + default: + assert(0); + abort(); + } if (payloadlen == NGHTTP2_ERR_DEFERRED || payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE || @@ -8275,7 +8356,7 @@ int nghttp2_session_change_stream_priority( /* We don't intentionally call nghttp2_session_adjust_idle_stream() so that idle stream created by this function, and existing ones are kept for application. We will adjust number of idle stream - in nghttp2_session_mem_send or nghttp2_session_mem_recv is + in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is called. */ return 0; } @@ -8313,7 +8394,7 @@ int nghttp2_session_create_idle_stream(nghttp2_session *session, /* We don't intentionally call nghttp2_session_adjust_idle_stream() so that idle stream created by this function, and existing ones are kept for application. We will adjust number of idle stream - in nghttp2_session_mem_send or nghttp2_session_mem_recv is + in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is called. */ return 0; } @@ -8366,3 +8447,30 @@ int nghttp2_session_change_extpri_stream_priority( return session_update_stream_priority(session, stream, nghttp2_extpri_to_uint8(&extpri)); } + +int nghttp2_session_get_extpri_stream_priority(nghttp2_session *session, + nghttp2_extpri *extpri, + int32_t stream_id) { + nghttp2_stream *stream; + + if (!session->server) { + return NGHTTP2_ERR_INVALID_STATE; + } + + if (session->pending_no_rfc7540_priorities != 1) { + return 0; + } + + if (stream_id == 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + stream = nghttp2_session_get_stream_raw(session, stream_id); + if (!stream) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + nghttp2_extpri_from_uint8(extpri, stream->extpri); + + return 0; +} diff --git a/deps/nghttp2/lib/nghttp2_session.h b/deps/nghttp2/lib/nghttp2_session.h index b119329a04da45..ef8f7b27d67261 100644 --- a/deps/nghttp2/lib/nghttp2_session.h +++ b/deps/nghttp2/lib/nghttp2_session.h @@ -110,6 +110,10 @@ typedef struct { #define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000 #define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33 +/* The default max number of CONTINUATION frames following an incoming + HEADER frame. */ +#define NGHTTP2_DEFAULT_MAX_CONTINUATIONS 8 + /* Internal state when receiving incoming frame */ typedef enum { /* Receiving frame header */ @@ -290,6 +294,12 @@ struct nghttp2_session { size_t max_send_header_block_length; /* The maximum number of settings accepted per SETTINGS frame. */ size_t max_settings; + /* The maximum number of CONTINUATION frames following an incoming + HEADER frame. */ + size_t max_continuations; + /* The number of CONTINUATION frames following an incoming HEADER + frame. This variable is reset when END_HEADERS flag is seen. */ + size_t num_continuations; /* Next Stream ID. Made unsigned int to detect >= (1 << 31). */ uint32_t next_stream_id; /* The last stream ID this session initiated. For client session, diff --git a/deps/nghttp2/lib/nghttp2_submit.c b/deps/nghttp2/lib/nghttp2_submit.c index f5554eb56494ed..f947969cd99c1f 100644 --- a/deps/nghttp2/lib/nghttp2_submit.c +++ b/deps/nghttp2/lib/nghttp2_submit.c @@ -68,7 +68,7 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_priority_spec *pri_spec, nghttp2_nv *nva_copy, size_t nvlen, - const nghttp2_data_provider *data_prd, + const nghttp2_data_provider_wrap *dpw, void *stream_user_data) { int rv; uint8_t flags_copy; @@ -87,8 +87,8 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags, nghttp2_outbound_item_init(item); - if (data_prd != NULL && data_prd->read_callback != NULL) { - item->aux_data.headers.data_prd = *data_prd; + if (dpw != NULL && dpw->data_prd.read_callback != NULL) { + item->aux_data.headers.dpw = *dpw; } item->aux_data.headers.stream_user_data = stream_user_data; @@ -143,7 +143,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, - const nghttp2_data_provider *data_prd, + const nghttp2_data_provider_wrap *dpw, void *stream_user_data) { int rv; nghttp2_nv *nva_copy; @@ -165,7 +165,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session, } return submit_headers_shared(session, flags, stream_id, ©_pri_spec, - nva_copy, nvlen, data_prd, stream_user_data); + nva_copy, nvlen, dpw, stream_user_data); } int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id, @@ -740,9 +740,9 @@ int nghttp2_submit_priority_update(nghttp2_session *session, uint8_t flags, } static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec, - const nghttp2_data_provider *data_prd) { + const nghttp2_data_provider_wrap *dpw) { uint8_t flags = NGHTTP2_FLAG_NONE; - if (data_prd == NULL || data_prd->read_callback == NULL) { + if (dpw == NULL || dpw->data_prd.read_callback == NULL) { flags |= NGHTTP2_FLAG_END_STREAM; } @@ -753,11 +753,11 @@ static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec, return flags; } -int32_t nghttp2_submit_request(nghttp2_session *session, - const nghttp2_priority_spec *pri_spec, - const nghttp2_nv *nva, size_t nvlen, - const nghttp2_data_provider *data_prd, - void *stream_user_data) { +static int32_t submit_request_shared(nghttp2_session *session, + const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider_wrap *dpw, + void *stream_user_data) { uint8_t flags; int rv; @@ -775,23 +775,47 @@ int32_t nghttp2_submit_request(nghttp2_session *session, pri_spec = NULL; } - flags = set_request_flags(pri_spec, data_prd); + flags = set_request_flags(pri_spec, dpw); return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen, - data_prd, stream_user_data); + dpw, stream_user_data); +} + +int32_t nghttp2_submit_request(nghttp2_session *session, + const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider *data_prd, + void *stream_user_data) { + nghttp2_data_provider_wrap dpw; + + return submit_request_shared(session, pri_spec, nva, nvlen, + nghttp2_data_provider_wrap_v1(&dpw, data_prd), + stream_user_data); +} + +int32_t nghttp2_submit_request2(nghttp2_session *session, + const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider2 *data_prd, + void *stream_user_data) { + nghttp2_data_provider_wrap dpw; + + return submit_request_shared(session, pri_spec, nva, nvlen, + nghttp2_data_provider_wrap_v2(&dpw, data_prd), + stream_user_data); } -static uint8_t set_response_flags(const nghttp2_data_provider *data_prd) { +static uint8_t set_response_flags(const nghttp2_data_provider_wrap *dpw) { uint8_t flags = NGHTTP2_FLAG_NONE; - if (data_prd == NULL || data_prd->read_callback == NULL) { + if (dpw == NULL || dpw->data_prd.read_callback == NULL) { flags |= NGHTTP2_FLAG_END_STREAM; } return flags; } -int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, - const nghttp2_nv *nva, size_t nvlen, - const nghttp2_data_provider *data_prd) { +static int submit_response_shared(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider_wrap *dpw) { uint8_t flags; if (stream_id <= 0) { @@ -802,14 +826,32 @@ int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, return NGHTTP2_ERR_PROTO; } - flags = set_response_flags(data_prd); + flags = set_response_flags(dpw); return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen, - data_prd, NULL); + dpw, NULL); } -int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, - int32_t stream_id, - const nghttp2_data_provider *data_prd) { +int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider *data_prd) { + nghttp2_data_provider_wrap dpw; + + return submit_response_shared(session, stream_id, nva, nvlen, + nghttp2_data_provider_wrap_v1(&dpw, data_prd)); +} + +int nghttp2_submit_response2(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider2 *data_prd) { + nghttp2_data_provider_wrap dpw; + + return submit_response_shared(session, stream_id, nva, nvlen, + nghttp2_data_provider_wrap_v2(&dpw, data_prd)); +} + +int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider_wrap *dpw) { int rv; nghttp2_outbound_item *item; nghttp2_frame *frame; @@ -832,7 +874,7 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, frame = &item->frame; aux_data = &item->aux_data.data; - aux_data->data_prd = *data_prd; + aux_data->dpw = *dpw; aux_data->eof = 0; aux_data->flags = nflags; @@ -848,9 +890,37 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, return 0; } +int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider *data_prd) { + nghttp2_data_provider_wrap dpw; + + assert(data_prd); + + return nghttp2_submit_data_shared( + session, flags, stream_id, nghttp2_data_provider_wrap_v1(&dpw, data_prd)); +} + +int nghttp2_submit_data2(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider2 *data_prd) { + nghttp2_data_provider_wrap dpw; + + assert(data_prd); + + return nghttp2_submit_data_shared( + session, flags, stream_id, nghttp2_data_provider_wrap_v2(&dpw, data_prd)); +} + ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv) { + return (ssize_t)nghttp2_pack_settings_payload2(buf, buflen, iv, niv); +} + +nghttp2_ssize nghttp2_pack_settings_payload2(uint8_t *buf, size_t buflen, + const nghttp2_settings_entry *iv, + size_t niv) { if (!nghttp2_iv_check(iv, niv)) { return NGHTTP2_ERR_INVALID_ARGUMENT; } @@ -859,7 +929,7 @@ ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen, return NGHTTP2_ERR_INSUFF_BUFSIZE; } - return (ssize_t)nghttp2_frame_pack_settings_payload(buf, iv, niv); + return (nghttp2_ssize)nghttp2_frame_pack_settings_payload(buf, iv, niv); } int nghttp2_submit_extension(nghttp2_session *session, uint8_t type, @@ -875,7 +945,8 @@ int nghttp2_submit_extension(nghttp2_session *session, uint8_t type, return NGHTTP2_ERR_INVALID_ARGUMENT; } - if (!session->callbacks.pack_extension_callback) { + if (!session->callbacks.pack_extension_callback2 && + !session->callbacks.pack_extension_callback) { return NGHTTP2_ERR_INVALID_STATE; } diff --git a/deps/nghttp2/lib/nghttp2_submit.h b/deps/nghttp2/lib/nghttp2_submit.h index 74d702fbcf077e..96781d2a274515 100644 --- a/deps/nghttp2/lib/nghttp2_submit.h +++ b/deps/nghttp2/lib/nghttp2_submit.h @@ -31,4 +31,10 @@ #include +typedef struct nghttp2_data_provider_wrap nghttp2_data_provider_wrap; + +int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider_wrap *dpw); + #endif /* NGHTTP2_SUBMIT_H */ diff --git a/deps/nghttp2/lib/nghttp2_time.c b/deps/nghttp2/lib/nghttp2_time.c index 2a5f1a6ff524df..947b5449e5ac6d 100644 --- a/deps/nghttp2/lib/nghttp2_time.c +++ b/deps/nghttp2/lib/nghttp2_time.c @@ -24,15 +24,13 @@ */ #include "nghttp2_time.h" -#ifdef HAVE_TIME_H -# include -#endif /* HAVE_TIME_H */ +#ifdef HAVE_WINDOWS_H +# include +#endif /* HAVE_WINDOWS_H */ -#ifdef HAVE_SYSINFOAPI_H -# include -#endif /* HAVE_SYSINFOAPI_H */ +#include -#ifndef HAVE_GETTICKCOUNT64 +#if !defined(HAVE_GETTICKCOUNT64) || defined(__CYGWIN__) static uint64_t time_now_sec(void) { time_t t = time(NULL); @@ -42,9 +40,12 @@ static uint64_t time_now_sec(void) { return (uint64_t)t; } -#endif /* HAVE_GETTICKCOUNT64 */ +#endif /* !HAVE_GETTICKCOUNT64 || __CYGWIN__ */ -#ifdef HAVE_CLOCK_GETTIME +#if defined(HAVE_GETTICKCOUNT64) && !defined(__CYGWIN__) +uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; } +#elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_DECL_CLOCK_MONOTONIC) && \ + HAVE_DECL_CLOCK_MONOTONIC uint64_t nghttp2_time_now_sec(void) { struct timespec tp; int rv = clock_gettime(CLOCK_MONOTONIC, &tp); @@ -55,8 +56,8 @@ uint64_t nghttp2_time_now_sec(void) { return (uint64_t)tp.tv_sec; } -#elif defined(HAVE_GETTICKCOUNT64) -uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; } -#else /* !HAVE_CLOCK_GETTIME && !HAVE_GETTICKCOUNT64 */ +#else /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \ + (!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */ uint64_t nghttp2_time_now_sec(void) { return time_now_sec(); } -#endif /* !HAVE_CLOCK_GETTIME && !HAVE_GETTICKCOUNT64 */ +#endif /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \ + (!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */ diff --git a/deps/nghttp2/nghttp2.gyp b/deps/nghttp2/nghttp2.gyp index 87909c5f296a2c..2601342f9e6f75 100644 --- a/deps/nghttp2/nghttp2.gyp +++ b/deps/nghttp2/nghttp2.gyp @@ -13,7 +13,7 @@ 'lib/nghttp2_http.c', 'lib/nghttp2_map.c', 'lib/nghttp2_mem.c', - 'lib/nghttp2_npn.c', + 'lib/nghttp2_alpn.c', 'lib/nghttp2_option.c', 'lib/nghttp2_outbound_item.c', 'lib/nghttp2_pq.c', diff --git a/deps/ngtcp2/.gitignore b/deps/ngtcp2/.gitignore index 40909a37dd7c69..1ccf3c1c44daf8 100644 --- a/deps/ngtcp2/.gitignore +++ b/deps/ngtcp2/.gitignore @@ -6,3 +6,4 @@ Makefile *gnutls* ngtcp2/**/.gitignore ngtcp2/**/.deps +nghttp3/**/.deps diff --git a/deps/ngtcp2/nghttp3/lib/includes/nghttp3/nghttp3.h b/deps/ngtcp2/nghttp3/lib/includes/nghttp3/nghttp3.h index cd10e4def7019b..77eb1fbf263815 100644 --- a/deps/ngtcp2/nghttp3/lib/includes/nghttp3/nghttp3.h +++ b/deps/ngtcp2/nghttp3/lib/includes/nghttp3/nghttp3.h @@ -68,6 +68,12 @@ extern "C" { # endif /* !BUILDING_NGHTTP3 */ #endif /* !defined(WIN32) */ +#ifdef _MSC_VER +# define NGHTTP3_ALIGN(N) __declspec(align(N)) +#else /* !_MSC_VER */ +# define NGHTTP3_ALIGN(N) __attribute__((aligned(N))) +#endif /* !_MSC_VER */ + /** * @typedef * @@ -97,166 +103,159 @@ typedef ptrdiff_t nghttp3_ssize; * argument is invalid. */ #define NGHTTP3_ERR_INVALID_ARGUMENT -101 -/** - * @macro - * - * :macro:`NGHTTP3_ERR_NOBUF` indicates that a provided buffer does - * not have enough space to store data. - */ -#define NGHTTP3_ERR_NOBUF -102 /** * @macro * * :macro:`NGHTTP3_ERR_INVALID_STATE` indicates that a requested * operation is not allowed at the current connection state. */ -#define NGHTTP3_ERR_INVALID_STATE -103 +#define NGHTTP3_ERR_INVALID_STATE -102 /** * @macro * * :macro:`NGHTTP3_ERR_WOULDBLOCK` indicates that an operation might * block. */ -#define NGHTTP3_ERR_WOULDBLOCK -104 +#define NGHTTP3_ERR_WOULDBLOCK -103 /** * @macro * * :macro:`NGHTTP3_ERR_STREAM_IN_USE` indicates that a stream ID is * already in use. */ -#define NGHTTP3_ERR_STREAM_IN_USE -105 +#define NGHTTP3_ERR_STREAM_IN_USE -104 /** * @macro * * :macro:`NGHTTP3_ERR_MALFORMED_HTTP_HEADER` indicates that an HTTP * header field is malformed. */ -#define NGHTTP3_ERR_MALFORMED_HTTP_HEADER -107 +#define NGHTTP3_ERR_MALFORMED_HTTP_HEADER -105 /** * @macro * * :macro:`NGHTTP3_ERR_REMOVE_HTTP_HEADER` indicates that an HTTP * header field is discarded. */ -#define NGHTTP3_ERR_REMOVE_HTTP_HEADER -108 +#define NGHTTP3_ERR_REMOVE_HTTP_HEADER -106 /** * @macro * * :macro:`NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING` indicates that HTTP * messaging is malformed. */ -#define NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING -109 +#define NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING -107 /** * @macro * * :macro:`NGHTTP3_ERR_QPACK_FATAL` indicates that a fatal error is - * occurred during QPACK processing and it cannot be recoverable. + * occurred during QPACK processing, and it cannot be recoverable. */ -#define NGHTTP3_ERR_QPACK_FATAL -111 +#define NGHTTP3_ERR_QPACK_FATAL -108 /** * @macro * * :macro:`NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE` indicates that a header * field is too large to process. */ -#define NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE -112 +#define NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE -109 /** * @macro * * :macro:`NGHTTP3_ERR_STREAM_NOT_FOUND` indicates that a stream is * not found. */ -#define NGHTTP3_ERR_STREAM_NOT_FOUND -114 +#define NGHTTP3_ERR_STREAM_NOT_FOUND -110 /** * @macro * * :macro:`NGHTTP3_ERR_CONN_CLOSING` indicates that a connection is * closing state. */ -#define NGHTTP3_ERR_CONN_CLOSING -116 +#define NGHTTP3_ERR_CONN_CLOSING -111 /** * @macro * * :macro:`NGHTTP3_ERR_STREAM_DATA_OVERFLOW` indicates that the length - * of stream data is too long and causes overflow. + * of stream data is too long, and causes overflow. */ -#define NGHTTP3_ERR_STREAM_DATA_OVERFLOW -117 +#define NGHTTP3_ERR_STREAM_DATA_OVERFLOW -112 /** * @macro * * :macro:`NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED` indicates that a * QPACK decompression failed. */ -#define NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED -402 +#define NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED -401 /** * @macro * * :macro:`NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR` indicates that an * error occurred while reading QPACK encoder stream. */ -#define NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR -403 +#define NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR -402 /** * @macro * * :macro:`NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR` indicates that an * error occurred while reading QPACK decoder stream. */ -#define NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR -404 +#define NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR -403 /** * @macro * * :macro:`NGHTTP3_ERR_H3_FRAME_UNEXPECTED` indicates that an * unexpected HTTP/3 frame is received. */ -#define NGHTTP3_ERR_H3_FRAME_UNEXPECTED -408 +#define NGHTTP3_ERR_H3_FRAME_UNEXPECTED -601 /** * @macro * * :macro:`NGHTTP3_ERR_H3_FRAME_ERROR` indicates that an HTTP/3 frame * is malformed. */ -#define NGHTTP3_ERR_H3_FRAME_ERROR -409 +#define NGHTTP3_ERR_H3_FRAME_ERROR -602 /** * @macro * * :macro:`NGHTTP3_ERR_H3_MISSING_SETTINGS` indicates that an HTTP/3 * SETTINGS frame is missing. */ -#define NGHTTP3_ERR_H3_MISSING_SETTINGS -665 +#define NGHTTP3_ERR_H3_MISSING_SETTINGS -603 /** * @macro * * :macro:`NGHTTP3_ERR_H3_INTERNAL_ERROR` indicates an internal error. */ -#define NGHTTP3_ERR_H3_INTERNAL_ERROR -667 +#define NGHTTP3_ERR_H3_INTERNAL_ERROR -604 /** * @macro * * :macro:`NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM` indicates that a * critical stream is closed. */ -#define NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM -668 +#define NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM -605 /** * @macro * * :macro:`NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR` indicates a general * protocol error. This is typically a catch-all error. */ -#define NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR -669 +#define NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR -606 /** * @macro * * :macro:`NGHTTP3_ERR_H3_ID_ERROR` indicates that an ID related error * occurred. */ -#define NGHTTP3_ERR_H3_ID_ERROR -670 +#define NGHTTP3_ERR_H3_ID_ERROR -607 /** * @macro * * :macro:`NGHTTP3_ERR_H3_SETTINGS_ERROR` indicates that an HTTP/3 * SETTINGS frame is malformed. */ -#define NGHTTP3_ERR_H3_SETTINGS_ERROR -671 +#define NGHTTP3_ERR_H3_SETTINGS_ERROR -608 /** * @macro * @@ -264,7 +263,7 @@ typedef ptrdiff_t nghttp3_ssize; * remote endpoint attempts to create a new stream which is not * allowed. */ -#define NGHTTP3_ERR_H3_STREAM_CREATION_ERROR -672 +#define NGHTTP3_ERR_H3_STREAM_CREATION_ERROR -609 /** * @macro * @@ -479,7 +478,7 @@ typedef void *(*nghttp3_realloc)(void *ptr, size_t size, void *user_data); * per-session memory pool. * * In the following example code, ``my_malloc``, ``my_free``, - * ``my_calloc`` and ``my_realloc`` are the replacement of the + * ``my_calloc``, and ``my_realloc`` are the replacement of the * standard allocators :manpage:`malloc(3)`, :manpage:`free(3)`, * :manpage:`calloc(3)` and :manpage:`realloc(3)` respectively:: * @@ -512,8 +511,8 @@ typedef void *(*nghttp3_realloc)(void *ptr, size_t size, void *user_data); */ typedef struct nghttp3_mem { /** - * :member:`user_data` is an arbitrary user supplied data. This - * is passed to each allocator function. + * :member:`user_data` is an arbitrary user supplied data. This is + * passed to each allocator function. */ void *user_data; /** @@ -559,7 +558,7 @@ typedef struct nghttp3_vec { uint8_t *base; /** * :member:`len` is the number of bytes which the buffer pointed by - * base contains. + * :member:`base` contains. */ size_t len; } nghttp3_vec; @@ -626,8 +625,8 @@ typedef struct nghttp3_buf { uint8_t *end; /** * :member:`pos` pointers to the start of data. Typically, this - * points to the point that next data should be read. Initially, it - * points to :member:`begin`. + * points to the address that next data should be read. Initially, + * it points to :member:`begin`. */ uint8_t *pos; /** @@ -685,7 +684,7 @@ NGHTTP3_EXTERN void nghttp3_buf_reset(nghttp3_buf *buf); /** * @macrosection * - * Flags for header field name/value pair + * Flags for HTTP field name/value pair */ /** @@ -708,8 +707,8 @@ NGHTTP3_EXTERN void nghttp3_buf_reset(nghttp3_buf *buf); * @macro * * :macro:`NGHTTP3_NV_FLAG_NO_COPY_NAME` is set solely by application. - * If this flag is set, the library does not make a copy of header - * field name. This could improve performance. + * If this flag is set, the library does not make a copy of field + * name. This could improve performance. */ #define NGHTTP3_NV_FLAG_NO_COPY_NAME 0x02u @@ -718,25 +717,35 @@ NGHTTP3_EXTERN void nghttp3_buf_reset(nghttp3_buf *buf); * * :macro:`NGHTTP3_NV_FLAG_NO_COPY_VALUE` is set solely by * application. If this flag is set, the library does not make a copy - * of header field value. This could improve performance. + * of field value. This could improve performance. */ #define NGHTTP3_NV_FLAG_NO_COPY_VALUE 0x04u +/** + * @macro + * + * :macro:`NGHTTP3_NV_FLAG_TRY_INDEX` gives a hint to QPACK encoder to + * index an HTTP field which is not indexed by default. This is just + * a hint, and QPACK encoder might not encode the field in various + * reasons. + */ +#define NGHTTP3_NV_FLAG_TRY_INDEX 0x08u + /** * @struct * * :type:`nghttp3_nv` is the name/value pair, which mainly used to - * represent header fields. + * represent HTTP fields. */ typedef struct nghttp3_nv { /** - * :member:`name` is the header field name. + * :member:`name` is the HTTP field name. */ - uint8_t *name; + const uint8_t *name; /** - * :member:`value` is the header field value. + * :member:`value` is the HTTP field value. */ - uint8_t *value; + const uint8_t *value; /** * :member:`namelen` is the length of the |name|, excluding * terminating NULL. @@ -758,8 +767,8 @@ typedef struct nghttp3_nv { /** * @enum * - * :type:`nghttp3_qpack_token` defines HTTP header field name tokens - * to identify field name quickly. It appears in + * :type:`nghttp3_qpack_token` defines HTTP field name tokens to + * identify field name quickly. It appears in * :member:`nghttp3_qpack_nv.token`. */ typedef enum nghttp3_qpack_token { @@ -1005,7 +1014,7 @@ typedef enum nghttp3_qpack_token { */ NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS = 96, - /* Additional header fields for HTTP messaging validation */ + /* Additional HTTP fields for HTTP messaging validation */ /** * :enum:`NGHTTP3_QPACK_TOKEN_HOST` is a token for ``host``. @@ -1053,26 +1062,25 @@ typedef enum nghttp3_qpack_token { /** * @struct * - * :type:`nghttp3_qpack_nv` represents header field name/value pair - * just like :type:`nghttp3_nv`. It is an extended version of - * :type:`nghttp3_nv` and has reference counted buffers and tokens - * which might be useful for applications. + * :type:`nghttp3_qpack_nv` represents HTTP field name/value pair just + * like :type:`nghttp3_nv`. It is an extended version of + * :type:`nghttp3_nv`, and has reference counted buffers and tokens. */ typedef struct nghttp3_qpack_nv { /** - * :member:`name` is the buffer containing header field name. + * :member:`name` is the buffer containing HTTP field name. * NULL-termination is guaranteed. */ nghttp3_rcbuf *name; /** - * :member:`value` is the buffer containing header field value. + * :member:`value` is the buffer containing HTTP field value. * NULL-termination is guaranteed. */ nghttp3_rcbuf *value; /** * :member:`token` is :type:`nghttp3_qpack_token` value of - * :member:`name`. It could be -1 if we have no token for that - * header field name. + * :member:`name`. It could be -1 if we have no token for that HTTP + * field name. */ int32_t token; /** @@ -1085,7 +1093,8 @@ typedef struct nghttp3_qpack_nv { /** * @struct * - * :type:`nghttp3_qpack_encoder` is QPACK encoder. + * :type:`nghttp3_qpack_encoder` is QPACK encoder. The details of + * this structure are intentionally hidden from the public API. */ typedef struct nghttp3_qpack_encoder nghttp3_qpack_encoder; @@ -1096,7 +1105,7 @@ typedef struct nghttp3_qpack_encoder nghttp3_qpack_encoder; * must be non-NULL pointer. |hard_max_dtable_capacity| is the upper * bound of the dynamic table capacity. |mem| is a memory allocator. * This function allocates memory for :type:`nghttp3_qpack_encoder` - * itself and assigns its pointer to |*pencoder| if it succeeds. + * itself, and assigns its pointer to |*pencoder| if it succeeds. * * The maximum dynamic table capacity is still 0. In order to change * the maximum dynamic table capacity, call @@ -1116,21 +1125,22 @@ NGHTTP3_EXTERN int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder, * @function * * `nghttp3_qpack_encoder_del` frees memory allocated for |encoder|. - * This function frees memory pointed by |encoder| itself. + * This function also frees memory pointed by |encoder| itself. This + * function does nothing if |encoder| is NULL. */ NGHTTP3_EXTERN void nghttp3_qpack_encoder_del(nghttp3_qpack_encoder *encoder); /** * @function * - * `nghttp3_qpack_encoder_encode` encodes the list of header fields + * `nghttp3_qpack_encoder_encode` encodes the list of HTTP fields * |nva|. |nvlen| is the length of |nva|. |stream_id| is the - * identifier of the stream which this header fields belong to. This - * function writes header block prefix, encoded header fields, and - * encoder stream to |pbuf|, |rbuf|, and |ebuf| respectively. The - * :member:`nghttp3_buf.last` will be adjusted when data is written. - * An application should write |pbuf| and |rbuf| to the request stream - * in this order. + * identifier of the stream which these HTTP fields belong to. This + * function writes field section prefix, encoded HTTP field section, + * and encoder stream to |pbuf|, |rbuf|, and |ebuf| respectively. + * Each :member:`nghttp3_buf.last` will be adjusted when data is + * written. An application should write |pbuf| and |rbuf| to the + * request stream in this order. * * The buffer pointed by |pbuf|, |rbuf|, and |ebuf| can be empty * buffer. It is fine to pass a buffer initialized by @@ -1139,7 +1149,7 @@ NGHTTP3_EXTERN void nghttp3_qpack_encoder_del(nghttp3_qpack_encoder *encoder); * frees and expands buffer if the current capacity of buffer is not * enough. If :member:`nghttp3_buf.begin` of any buffer is not NULL, * it must be allocated by the same memory allocator passed to - * `nghttp3_qpack_encoder_new()`. + * `nghttp3_qpack_encoder_new`. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -1147,7 +1157,7 @@ NGHTTP3_EXTERN void nghttp3_qpack_encoder_del(nghttp3_qpack_encoder *encoder); * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory * :macro:`NGHTTP3_ERR_QPACK_FATAL` - * |encoder| is in unrecoverable error state and cannot be used + * |encoder| is in unrecoverable error state, and cannot be used * anymore. */ NGHTTP3_EXTERN int nghttp3_qpack_encoder_encode( @@ -1166,7 +1176,7 @@ NGHTTP3_EXTERN int nghttp3_qpack_encoder_encode( * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory * :macro:`NGHTTP3_ERR_QPACK_FATAL` - * |encoder| is in unrecoverable error state and cannot be used + * |encoder| is in unrecoverable error state, and cannot be used * anymore. * :macro:`NGHTTP3_ERR_QPACK_DECODER_STREAM` * |encoder| is unable to process input because it is malformed. @@ -1178,8 +1188,8 @@ NGHTTP3_EXTERN nghttp3_ssize nghttp3_qpack_encoder_read_decoder( * @function * * `nghttp3_qpack_encoder_set_max_dtable_capacity` sets max dynamic - * table capacity to |max_dtable_capacity|. If |max_dtable_capacity| is - * larger than ``hard_max_dtable_capacity`` parameter of + * table capacity to |max_dtable_capacity|. If |max_dtable_capacity| + * is larger than ``hard_max_dtable_capacity`` parameter of * `nghttp3_qpack_encoder_new`, it is truncated to the latter. */ NGHTTP3_EXTERN void @@ -1200,9 +1210,10 @@ nghttp3_qpack_encoder_set_max_blocked_streams(nghttp3_qpack_encoder *encoder, * @function * * `nghttp3_qpack_encoder_ack_everything` tells |encoder| that all - * encoded header blocks are acknowledged. This function is provided - * for debugging purpose only. In HTTP/3, |encoder| knows this by - * reading decoder stream with `nghttp3_qpack_encoder_read_decoder()`. + * encoded HTTP field sections are acknowledged. This function is + * provided for debugging purpose only. In HTTP/3, |encoder| knows + * this by reading decoder stream with + * `nghttp3_qpack_encoder_read_decoder`. */ NGHTTP3_EXTERN void nghttp3_qpack_encoder_ack_everything(nghttp3_qpack_encoder *encoder); @@ -1220,9 +1231,10 @@ nghttp3_qpack_encoder_get_num_blocked_streams(nghttp3_qpack_encoder *encoder); * @struct * * :type:`nghttp3_qpack_stream_context` is a decoder context for an - * individual stream. Its state is per header block. In order to - * reuse this object for another header block, call - * `nghttp3_qpack_stream_context_reset`. + * individual stream. Its state is per HTTP field section. In order + * to reuse this object for another HTTP field section, call + * `nghttp3_qpack_stream_context_reset`. The details of this + * structure are intentionally hidden from the public API. */ typedef struct nghttp3_qpack_stream_context nghttp3_qpack_stream_context; @@ -1232,8 +1244,8 @@ typedef struct nghttp3_qpack_stream_context nghttp3_qpack_stream_context; * `nghttp3_qpack_stream_context_new` initializes stream context. * |psctx| must be non-NULL pointer. |stream_id| is stream ID. |mem| * is a memory allocator. This function allocates memory for - * :type:`nghttp3_qpack_stream_context` itself and assigns its pointer - * to |*psctx| if it succeeds. + * :type:`nghttp3_qpack_stream_context` itself, and assigns its + * pointer to |*psctx| if it succeeds. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -1249,7 +1261,8 @@ nghttp3_qpack_stream_context_new(nghttp3_qpack_stream_context **psctx, * @function * * `nghttp3_qpack_stream_context_del` frees memory allocated for - * |sctx|. This function frees memory pointed by |sctx| itself. + * |sctx|. This function frees memory pointed by |sctx| itself. This + * function does nothing if |sctx| is NULL. */ NGHTTP3_EXTERN void nghttp3_qpack_stream_context_del(nghttp3_qpack_stream_context *sctx); @@ -1267,8 +1280,8 @@ nghttp3_qpack_stream_context_get_ricnt(nghttp3_qpack_stream_context *sctx); * @function * * `nghttp3_qpack_stream_context_reset` resets the state of |sctx|. - * Then it can be reused for an another header block in the same - * stream. + * Then it can be reused for decoding an another HTTP field section in + * the same stream. */ NGHTTP3_EXTERN void nghttp3_qpack_stream_context_reset(nghttp3_qpack_stream_context *sctx); @@ -1276,7 +1289,8 @@ void nghttp3_qpack_stream_context_reset(nghttp3_qpack_stream_context *sctx); /** * @struct * - * :type:`nghttp3_qpack_decoder` is QPACK decoder. + * :type:`nghttp3_qpack_decoder` is QPACK decoder. The details of + * this structure are intentionally hidden from the public API. */ typedef struct nghttp3_qpack_decoder nghttp3_qpack_decoder; @@ -1288,7 +1302,7 @@ typedef struct nghttp3_qpack_decoder nghttp3_qpack_decoder; * bound of the dynamic table capacity. |max_blocked_streams| is the * maximum number of streams which can be blocked. |mem| is a memory * allocator. This function allocates memory for - * :type:`nghttp3_qpack_decoder` itself and assigns its pointer to + * :type:`nghttp3_qpack_decoder` itself, and assigns its pointer to * |*pdecoder| if it succeeds. * * This function returns 0 if it succeeds, or one of the following @@ -1306,7 +1320,8 @@ NGHTTP3_EXTERN int nghttp3_qpack_decoder_new(nghttp3_qpack_decoder **pdecoder, * @function * * `nghttp3_qpack_decoder_del` frees memory allocated for |decoder|. - * This function frees memory pointed by |decoder| itself. + * This function frees memory pointed by |decoder| itself. This + * function does nothing if |decoder| is NULL. */ NGHTTP3_EXTERN void nghttp3_qpack_decoder_del(nghttp3_qpack_decoder *decoder); @@ -1322,7 +1337,7 @@ NGHTTP3_EXTERN void nghttp3_qpack_decoder_del(nghttp3_qpack_decoder *decoder); * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory. * :macro:`NGHTTP3_ERR_QPACK_FATAL` - * |decoder| is in unrecoverable error state and cannot be used + * |decoder| is in unrecoverable error state, and cannot be used * anymore. * :macro:`NGHTTP3_ERR_QPACK_ENCODER_STREAM` * Could not interpret encoder stream instruction. @@ -1354,7 +1369,7 @@ nghttp3_qpack_decoder_get_icnt(const nghttp3_qpack_decoder *decoder); /** * @macro * - * :macro:`NGHTTP3_QPACK_DECODE_FLAG_EMIT` indicates that a header + * :macro:`NGHTTP3_QPACK_DECODE_FLAG_EMIT` indicates that an HTTP * field is successfully decoded. */ #define NGHTTP3_QPACK_DECODE_FLAG_EMIT 0x01u @@ -1362,8 +1377,8 @@ nghttp3_qpack_decoder_get_icnt(const nghttp3_qpack_decoder *decoder); /** * @macro * - * :macro:`NGHTTP3_QPACK_DECODE_FLAG_FINAL` indicates that all header - * fields have been decoded. + * :macro:`NGHTTP3_QPACK_DECODE_FLAG_FINAL` indicates that an entire + * HTTP field section has been decoded. */ #define NGHTTP3_QPACK_DECODE_FLAG_FINAL 0x02u @@ -1380,32 +1395,32 @@ nghttp3_qpack_decoder_get_icnt(const nghttp3_qpack_decoder *decoder); * * `nghttp3_qpack_decoder_read_request` reads request stream. The * request stream is given as the buffer pointed by |src| of length - * |srclen|. |sctx| is the stream context and it must be created by - * `nghttp3_qpack_stream_context_new()`. |*pflags| must be non-NULL + * |srclen|. |sctx| is the stream context, and it must be created by + * `nghttp3_qpack_stream_context_new`. |*pflags| must be non-NULL * pointer. |nv| must be non-NULL pointer. * * If this function succeeds, it assigns flags to |*pflags|. If * |*pflags| has :macro:`NGHTTP3_QPACK_DECODE_FLAG_EMIT` set, a - * decoded header field is assigned to |nv|. If |*pflags| has - * :macro:`NGHTTP3_QPACK_DECODE_FLAG_FINAL` set, all header fields - * have been successfully decoded. If |*pflags| has + * decoded HTTP field is assigned to |nv|. If |*pflags| has + * :macro:`NGHTTP3_QPACK_DECODE_FLAG_FINAL` set, an entire HTTP field + * section has been successfully decoded. If |*pflags| has * :macro:`NGHTTP3_QPACK_DECODE_FLAG_BLOCKED` set, decoding is blocked * due to required insert count. * - * When a header field is decoded, an application receives it in |nv|. + * When an HTTP field is decoded, an application receives it in |nv|. * :member:`nv->name ` and :member:`nv->value * ` are reference counted buffer, and their * reference counts are already incremented for application use. - * Therefore, when application finishes processing the header field, - * it must call `nghttp3_rcbuf_decref(nv->name) - * ` and `nghttp3_rcbuf_decref(nv->value) - * ` or memory leak might occur. These - * :type:`nghttp3_rcbuf` objects hold the pointer to - * :type:`nghttp3_mem` that is passed to `nghttp3_qpack_decoder_new` - * (or either `nghttp3_conn_client_new` or `nghttp3_conn_server_new` - * if it is used indirectly). As long as these objects are alive, the - * pointed :type:`nghttp3_mem` object must be available. Otherwise, - * `nghttp3_rcbuf_decref` will cause undefined behavior. + * Therefore, when application finishes processing |nv|, it must call + * `nghttp3_rcbuf_decref(nv->name) ` and + * `nghttp3_rcbuf_decref(nv->value) `, or memory + * leak might occur. These :type:`nghttp3_rcbuf` objects hold the + * pointer to :type:`nghttp3_mem` that is passed to + * `nghttp3_qpack_decoder_new` (or either `nghttp3_conn_client_new` or + * `nghttp3_conn_server_new` if it is used indirectly). As long as + * these objects are alive, the pointed :type:`nghttp3_mem` object + * must be available. Otherwise, `nghttp3_rcbuf_decref` will cause + * undefined behavior. * * This function returns the number of bytes read, or one of the * following negative error codes: @@ -1413,12 +1428,12 @@ nghttp3_qpack_decoder_get_icnt(const nghttp3_qpack_decoder *decoder); * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory. * :macro:`NGHTTP3_ERR_QPACK_FATAL` - * |decoder| is in unrecoverable error state and cannot be used + * |decoder| is in unrecoverable error state, and cannot be used * anymore. * :macro:`NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED` - * Could not interpret header block instruction. + * Could not interpret field line representations. * :macro:`NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE` - * Header field is too large. + * HTTP field is too large. */ NGHTTP3_EXTERN nghttp3_ssize nghttp3_qpack_decoder_read_request( nghttp3_qpack_decoder *decoder, nghttp3_qpack_stream_context *sctx, @@ -1444,7 +1459,7 @@ nghttp3_qpack_decoder_write_decoder(nghttp3_qpack_decoder *decoder, * @function * * `nghttp3_qpack_decoder_get_decoder_streamlen` returns the length of - * decoder stream. + * decoder stream that is currently pending. */ NGHTTP3_EXTERN size_t nghttp3_qpack_decoder_get_decoder_streamlen(nghttp3_qpack_decoder *decoder); @@ -1452,8 +1467,8 @@ nghttp3_qpack_decoder_get_decoder_streamlen(nghttp3_qpack_decoder *decoder); /** * @function * - * `nghttp3_qpack_decoder_cancel_stream` cancels header decoding for - * stream denoted by |stream_id|. + * `nghttp3_qpack_decoder_cancel_stream` cancels HTTP field section + * decoding for stream denoted by |stream_id|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -1472,14 +1487,14 @@ nghttp3_qpack_decoder_cancel_stream(nghttp3_qpack_decoder *decoder, * * `nghttp3_qpack_decoder_set_max_dtable_capacity` sets * |max_dtable_capacity| as maximum dynamic table size. - * |max_dtable_capacity| must be equal to or smaller than + * |max_dtable_capacity| must be equal to, or smaller than * ``hard_max_dtable_capacity`` parameter of * `nghttp3_qpack_decoder_new`. Normally, the maximum capacity is * communicated in encoder stream. This function is provided for * debugging and testing purpose. * - * This function returns 0 if it succeeds, or one of the - * following negative error codes: + * This function returns 0 if it succeeds, or one of the following + * negative error codes: * * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` * |max_dtable_capacity| exceeds the upper bound of the dynamic @@ -1535,8 +1550,8 @@ typedef void (*nghttp3_debug_vprintf_callback)(const char *format, * * `nghttp3_set_debug_vprintf_callback` sets a debug output callback * called by the library when built with :macro:`DEBUGBUILD` macro - * defined. If this option is not used, debug log is written into - * standard error output. + * defined. If a callback function is not set by this function, debug + * log is written into standard error output. * * For builds without :macro:`DEBUGBUILD` macro defined, this function * is noop. @@ -1564,7 +1579,7 @@ NGHTTP3_EXTERN void nghttp3_set_debug_vprintf_callback( /** * @macro * - * :macro:`NGHTTP3_SHUTDOWN_NOTICE_STREAM_ID` specifies stream id sent + * :macro:`NGHTTP3_SHUTDOWN_NOTICE_STREAM_ID` specifies stream ID sent * by a server when it initiates graceful shutdown of the connection * via `nghttp3_conn_submit_shutdown_notice`. */ @@ -1573,19 +1588,72 @@ NGHTTP3_EXTERN void nghttp3_set_debug_vprintf_callback( /** * @macro * - * :macro:`NGHTTP3_SHUTDOWN_NOTICE_PUSH_ID` specifies push id sent - * by a client when it initiates graceful shutdown of the connection - * via `nghttp3_conn_submit_shutdown_notice`. + * :macro:`NGHTTP3_SHUTDOWN_NOTICE_PUSH_ID` specifies push ID sent by + * a client when it initiates graceful shutdown of the connection via + * `nghttp3_conn_submit_shutdown_notice`. Note that libnghttp3 does + * not implement HTTP/3 Server Push. */ #define NGHTTP3_SHUTDOWN_NOTICE_PUSH_ID ((1ull << 62) - 1) /** * @struct * - * :type:`nghttp3_conn` represents a single HTTP/3 connection. + * :type:`nghttp3_conn` represents a single HTTP/3 connection. The + * details of this structure are intentionally hidden from the public + * API. */ typedef struct nghttp3_conn nghttp3_conn; +#define NGHTTP3_SETTINGS_V1 1 +#define NGHTTP3_SETTINGS_VERSION NGHTTP3_SETTINGS_V1 + +/** + * @struct + * + * :type:`nghttp3_settings` defines HTTP/3 settings. + */ +typedef struct nghttp3_settings { + /** + * :member:`max_field_section_size` specifies the maximum header + * section (block) size. + */ + uint64_t max_field_section_size; + /** + * :member:`qpack_max_dtable_capacity` is the maximum size of QPACK + * dynamic table. + */ + size_t qpack_max_dtable_capacity; + /** + * :member:`qpack_encoder_max_dtable_capacity` is the upper bound of + * QPACK dynamic table capacity that the QPACK encoder is willing to + * use. The effective maximum dynamic table capacity is the minimum + * of this field and the value of the received + * SETTINGS_QPACK_MAX_TABLE_CAPACITY. If this field is set to 0, + * the encoder does not use the dynamic table. + * + * When :type:`nghttp3_settings` is passed to + * :member:`nghttp3_callbacks.recv_settings` callback, this field + * should be ignored. + */ + size_t qpack_encoder_max_dtable_capacity; + /** + * :member:`qpack_blocked_streams` is the maximum number of streams + * which can be blocked while they are being decoded. + */ + size_t qpack_blocked_streams; + /** + * :member:`enable_connect_protocol`, if set to nonzero, enables + * Extended CONNECT Method (see :rfc:`9220`). Client ignores this + * field. + */ + uint8_t enable_connect_protocol; + /** + * :member:`h3_datagram`, if set to nonzero, enables HTTP/3 + * Datagrams (see :rfc:`9297`). + */ + uint8_t h3_datagram; +} nghttp3_settings; + /** * @functypedef * @@ -1607,8 +1675,9 @@ typedef int (*nghttp3_acked_stream_data)(nghttp3_conn *conn, int64_t stream_id, * @functypedef * * :type:`nghttp3_conn_stream_close` is a callback function which is - * invoked when a stream identified by |stream_id| is closed. - * |app_error_code| indicates the reason of this closure. + * invoked when a stream identified by |stream_id| is closed. QUIC + * application error code |app_error_code| indicates the reason of + * this closure. * * The implementation of this callback must return 0 if it succeeds. * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the @@ -1625,11 +1694,11 @@ typedef int (*nghttp3_stream_close)(nghttp3_conn *conn, int64_t stream_id, * * :type:`nghttp3_recv_data` is a callback function which is invoked * when a part of request or response body on stream identified by - * |stream_id| is received. |data| points to the received data and + * |stream_id| is received. |data| points to the received data, and * its length is |datalen|. * * The application is responsible for increasing flow control credit - * by |datalen| bytes. + * (say, increasing by |datalen| bytes). * * The implementation of this callback must return 0 if it succeeds. * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the @@ -1646,9 +1715,9 @@ typedef int (*nghttp3_recv_data)(nghttp3_conn *conn, int64_t stream_id, * :type:`nghttp3_deferred_consume` is a callback function which is * invoked when the library consumed |consumed| bytes for a stream * identified by |stream_id|. This callback is used to notify the - * consumed bytes for stream blocked by QPACK decoder. The - * application is responsible for increasing flow control credit by - * |consumed| bytes. + * consumed bytes for stream blocked due to synchronization between + * streams. The application is responsible for increasing flow + * control credit by |consumed| bytes. * * The implementation of this callback must return 0 if it succeeds. * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the @@ -1663,11 +1732,11 @@ typedef int (*nghttp3_deferred_consume)(nghttp3_conn *conn, int64_t stream_id, * @functypedef * * :type:`nghttp3_begin_headers` is a callback function which is - * invoked when an incoming header block section is started on a - * stream denoted by |stream_id|. Each header field is passed to - * application by :type:`nghttp3_recv_header` callback. And then - * :type:`nghttp3_end_headers` is called when a whole header block is - * processed. + * invoked when an incoming HTTP field section is started on a stream + * denoted by |stream_id|. Each HTTP field is passed to application + * by :type:`nghttp3_recv_header` callback. And then + * :type:`nghttp3_end_headers` is called when a whole HTTP field + * section is processed. * * The implementation of this callback must return 0 if it succeeds. * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the @@ -1682,8 +1751,8 @@ typedef int (*nghttp3_begin_headers)(nghttp3_conn *conn, int64_t stream_id, * @functypedef * * :type:`nghttp3_recv_header` is a callback function which is invoked - * when a header field is received on a stream denoted by |stream_id|. - * |name| contains a field name and |value| contains a field value. + * when an HTTP field is received on a stream denoted by |stream_id|. + * |name| contains a field name, and |value| contains a field value. * |token| is one of token defined in :type:`nghttp3_qpack_token` or * -1 if no token is defined for |name|. |flags| is bitwise OR of * zero or more of :macro:`NGHTTP3_NV_FLAG_* `. @@ -1708,9 +1777,10 @@ typedef int (*nghttp3_recv_header)(nghttp3_conn *conn, int64_t stream_id, * @functypedef * * :type:`nghttp3_end_headers` is a callback function which is invoked - * when an incoming header block has ended. + * when an incoming HTTP field section has ended. * - * If the stream ends with this header block, |fin| is set to nonzero. + * If the stream ends with this HTTP field section, |fin| is set to + * nonzero. * * The implementation of this callback must return 0 if it succeeds. * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the @@ -1743,8 +1813,8 @@ typedef int (*nghttp3_end_stream)(nghttp3_conn *conn, int64_t stream_id, * * :type:`nghttp3_stop_sending` is a callback function which is * invoked when the library asks application to send STOP_SENDING to - * the stream identified by |stream_id|. |app_error_code| indicates - * the reason for this action. + * the stream identified by |stream_id|. QUIC application error code + * |app_error_code| indicates the reason for this action. * * The implementation of this callback must return 0 if it succeeds. * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the @@ -1761,8 +1831,8 @@ typedef int (*nghttp3_stop_sending)(nghttp3_conn *conn, int64_t stream_id, * * :type:`nghttp3_reset_stream` is a callback function which is * invoked when the library asks application to reset stream - * identified by |stream_id|. |app_error_code| indicates the reason - * for this action. + * identified by |stream_id|. QUIC application error code + * |app_error_code| indicates the reason for this action. * * The implementation of this callback must return 0 if it succeeds. * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the @@ -1779,13 +1849,14 @@ typedef int (*nghttp3_reset_stream)(nghttp3_conn *conn, int64_t stream_id, * * :type:`nghttp3_shutdown` is a callback function which is invoked * when a shutdown is initiated by the remote endpoint. For client, - * |id| contains a stream id of a client initiated stream, for server, - * it contains a push id. All client streams with stream id or pushes - * with push id equal to or larger than |id| are guaranteed to not be - * processed by the remote endpoint. + * |id| contains a stream ID of a client initiated stream, for server, + * it contains a push ID. All client streams with stream ID, or pushes + * with push ID equal to, or larger than |ID| are guaranteed to not be + * processed by the remote endpoint. Note that libnghttp3 does not + * implement Server Push. * * Parameter |id| for client can contain a special value - * :macro:`NGHTTP3_SHUTDOWN_NOTICE_STREAM_ID` and for server it can + * :macro:`NGHTTP3_SHUTDOWN_NOTICE_STREAM_ID`, and for server it can * contain special value * :macro:`NGHTTP3_SHUTDOWN_NOTICE_PUSH_ID`. These values signal * request for graceful shutdown of the connection, triggered by @@ -1804,8 +1875,24 @@ typedef int (*nghttp3_reset_stream)(nghttp3_conn *conn, int64_t stream_id, typedef int (*nghttp3_shutdown)(nghttp3_conn *conn, int64_t id, void *conn_user_data); -#define NGHTTP3_CALLBACKS_VERSION_V1 1 -#define NGHTTP3_CALLBACKS_VERSION NGHTTP3_CALLBACKS_VERSION_V1 +/** + * @functypedef + * + * :type:`nghttp3_recv_settings` is a callback function which is + * invoked when SETTINGS frame is received. |settings| is a received + * remote HTTP/3 settings. + * + * The implementation of this callback must return 0 if it succeeds. + * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the + * caller immediately. Any values other than 0 is treated as + * :macro:`NGHTTP3_ERR_CALLBACK_FAILURE`. + */ +typedef int (*nghttp3_recv_settings)(nghttp3_conn *conn, + const nghttp3_settings *settings, + void *conn_user_data); + +#define NGHTTP3_CALLBACKS_V1 1 +#define NGHTTP3_CALLBACKS_VERSION NGHTTP3_CALLBACKS_V1 /** * @struct @@ -1837,32 +1924,38 @@ typedef struct nghttp3_callbacks { nghttp3_deferred_consume deferred_consume; /** * :member:`begin_headers` is a callback function which is invoked - * when a header block has started on a particular stream. + * when an HTTP header field section has started on a particular + * stream. */ nghttp3_begin_headers begin_headers; /** * :member:`recv_header` is a callback function which is invoked - * when a single header field is received on a particular stream. + * when a single HTTP header field is received on a particular + * stream. */ nghttp3_recv_header recv_header; /** * :member:`end_headers` is a callback function which is invoked - * when a header block has ended on a particular stream. + * when an HTTP header field section has ended on a particular + * stream. */ nghttp3_end_headers end_headers; /** * :member:`begin_trailers` is a callback function which is invoked - * when a trailer block has started on a particular stream. + * when an HTTP trailer field section has started on a particular + * stream. */ nghttp3_begin_headers begin_trailers; /** * :member:`recv_trailer` is a callback function which is invoked - * when a single trailer field is received on a particular stream. + * when a single HTTP trailer field is received on a particular + * stream. */ nghttp3_recv_header recv_trailer; /** * :member:`end_trailers` is a callback function which is invoked - * when a trailer block has ended on a particular stream. + * when an HTTP trailer field section has ended on a particular + * stream. */ nghttp3_end_headers end_trailers; /** @@ -1884,52 +1977,16 @@ typedef struct nghttp3_callbacks { nghttp3_reset_stream reset_stream; /** * :member:`shutdown` is a callback function which is invoked when - * the remote endpoint has signalled initiation of connection shutdown. + * the remote endpoint has signalled initiation of connection + * shutdown. */ nghttp3_shutdown shutdown; -} nghttp3_callbacks; - -#define NGHTTP3_SETTINGS_VERSION_V1 1 -#define NGHTTP3_SETTINGS_VERSION NGHTTP3_SETTINGS_VERSION_V1 - -/** - * @struct - * - * :type:`nghttp3_settings` defines HTTP/3 settings. - */ -typedef struct nghttp3_settings { - /** - * :member:`max_field_section_size` specifies the maximum header - * section (block) size. - */ - uint64_t max_field_section_size; - /** - * :member:`qpack_max_dtable_capacity` is the maximum size of QPACK - * dynamic table. - */ - size_t qpack_max_dtable_capacity; - /** - * :member:`qpack_encoder_max_dtable_capacity` is the upper bound of - * QPACK dynamic table capacity that the QPACK encoder is willing to - * use. The effective maximum dynamic table capacity is the minimum - * of this field and the value of the received - * SETTINGS_QPACK_MAX_TABLE_CAPACITY. If this field is set to 0, - * the encoder does not use the dynamic table. - */ - size_t qpack_encoder_max_dtable_capacity; /** - * :member:`qpack_blocked_streams` is the maximum number of streams - * which can be blocked while they are being decoded. + * :member:`recv_settings` is a callback function which is invoked + * when SETTINGS frame is received. */ - size_t qpack_blocked_streams; - /** - * :member:`enable_connect_protocol`, if set to nonzero, enables - * Extended CONNECT Method (see - * https://www.ietf.org/archive/id/draft-ietf-httpbis-h3-websockets-00.html). - * Client ignores this field. - */ - int enable_connect_protocol; -} nghttp3_settings; + nghttp3_recv_settings recv_settings; +} nghttp3_callbacks; /** * @function @@ -1955,10 +2012,16 @@ nghttp3_settings_default_versioned(int settings_version, /** * @function * - * `nghttp3_conn_client_new` creates :type:`nghttp3_conn` and + * `nghttp3_conn_client_new` creates :type:`nghttp3_conn`, and * initializes it for client use. The pointer to the object is stored * in |*pconn|. If |mem| is ``NULL``, the memory allocator returned * by `nghttp3_mem_default` is used. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_client_new_versioned(nghttp3_conn **pconn, int callbacks_version, @@ -1970,10 +2033,16 @@ nghttp3_conn_client_new_versioned(nghttp3_conn **pconn, int callbacks_version, /** * @function * - * `nghttp3_conn_server_new` creates :type:`nghttp3_conn` and + * `nghttp3_conn_server_new` creates :type:`nghttp3_conn`, and * initializes it for server use. The pointer to the object is stored * in |*pconn|. If |mem| is ``NULL``, the memory allocator returned * by `nghttp3_mem_default` is used. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_server_new_versioned(nghttp3_conn **pconn, int callbacks_version, @@ -1985,7 +2054,9 @@ nghttp3_conn_server_new_versioned(nghttp3_conn **pconn, int callbacks_version, /** * @function * - * `nghttp3_conn_del` frees resources allocated for |conn|. + * `nghttp3_conn_del` frees resources allocated for |conn|. This + * function also frees memory pointed by |conn| itself. This function + * does nothing if |conn| is NULL. */ NGHTTP3_EXTERN void nghttp3_conn_del(nghttp3_conn *conn); @@ -2000,8 +2071,8 @@ NGHTTP3_EXTERN void nghttp3_conn_del(nghttp3_conn *conn); * * :macro:`NGHTTP3_ERR_INVALID_STATE` * Control stream has already corresponding stream ID. - * - * TBD + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_bind_control_stream(nghttp3_conn *conn, int64_t stream_id); @@ -2010,7 +2081,7 @@ NGHTTP3_EXTERN int nghttp3_conn_bind_control_stream(nghttp3_conn *conn, * @function * * `nghttp3_conn_bind_qpack_streams` binds stream denoted by - * |qenc_stream_id| to outgoing QPACK encoder stream and stream + * |qenc_stream_id| to outgoing QPACK encoder stream, and stream * denoted by |qdec_stream_id| to outgoing QPACK encoder stream. * * This function returns 0 if it succeeds, or one of the following @@ -2019,8 +2090,8 @@ NGHTTP3_EXTERN int nghttp3_conn_bind_control_stream(nghttp3_conn *conn, * :macro:`NGHTTP3_ERR_INVALID_STATE` * QPACK encoder/decoder stream have already corresponding stream * IDs. - * - * TBD + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_bind_qpack_streams(nghttp3_conn *conn, int64_t qenc_stream_id, @@ -2038,6 +2109,18 @@ NGHTTP3_EXTERN int nghttp3_conn_bind_qpack_streams(nghttp3_conn *conn, * any control or QPACK unidirectional streams) . See * :type:`nghttp3_recv_data` to handle those bytes. If |fin| is * nonzero, this is the last data from remote endpoint in this stream. + * + * This function returns the number of bytes consumed, or one of the + * following negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. + * :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` + * User callback failed. + * + * It may return the other error codes. In general, the negative + * error code means that |conn| encountered a connection error, and + * the connection should be closed. */ NGHTTP3_EXTERN nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id, @@ -2048,18 +2131,30 @@ NGHTTP3_EXTERN nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, * @function * * `nghttp3_conn_writev_stream` stores stream data to send to |vec| of - * length |veccnt| and returns the number of nghttp3_vec object in + * length |veccnt|, and returns the number of nghttp3_vec object in * which it stored data. It stores stream ID to |*pstream_id|. An * application has to call `nghttp3_conn_add_write_offset` to inform * |conn| of the actual number of bytes that underlying QUIC stack * accepted. |*pfin| will be nonzero if this is the last data to * send. If there is no stream to write data or send fin, this * function returns 0, and -1 is assigned to |*pstream_id|. This - * function may return 0 and |*pstream_id| is not -1 and |*pfin| is - * nonzero. It means 0 length data to |*pstream_id| and it is the + * function may return 0, and |*pstream_id| is not -1, and |*pfin| is + * nonzero. It means 0 length data to |*pstream_id|, and it is the * last data to the stream. They must be passed to QUIC stack, and * they are accepted, the application has to call - * `nghttp3_conn_add_write_offset`. + * `nghttp3_conn_add_write_offset` with 0 byte. + * + * This function returns the number of bytes consumed, or one of the + * following negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. + * :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` + * User callback failed. + * + * It may return the other error codes. In general, the negative + * error code means that |conn| encountered a connection error, and + * the connection should be closed. */ NGHTTP3_EXTERN nghttp3_ssize nghttp3_conn_writev_stream(nghttp3_conn *conn, int64_t *pstream_id, @@ -2081,6 +2176,15 @@ NGHTTP3_EXTERN nghttp3_ssize nghttp3_conn_writev_stream(nghttp3_conn *conn, * `nghttp3_conn_writev_stream` must be called before calling this * function to get data to send, and those data must be fed into QUIC * stack. + * + * If a stream denoted by |stream_id| is not found, this function + * returns 0. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_add_write_offset(nghttp3_conn *conn, int64_t stream_id, size_t n); @@ -2090,6 +2194,15 @@ NGHTTP3_EXTERN int nghttp3_conn_add_write_offset(nghttp3_conn *conn, * * `nghttp3_conn_add_ack_offset` tells |conn| the number of bytes |n| * for stream denoted by |stream_id| QUIC stack has acknowledged. + * + * If a stream denoted by |stream_id| is not found, this function + * returns 0. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` + * User callback failed. */ NGHTTP3_EXTERN int nghttp3_conn_add_ack_offset(nghttp3_conn *conn, int64_t stream_id, uint64_t n); @@ -2107,8 +2220,17 @@ NGHTTP3_EXTERN void nghttp3_conn_block_stream(nghttp3_conn *conn, * @function * * `nghttp3_conn_unblock_stream` tells the library that stream - * identified by |stream_id| which was blocked by QUIC flow control is - * unblocked. + * identified by |stream_id| which was blocked by QUIC flow control + * (see `nghttp3_conn_block_stream`) is unblocked. + * + * If a stream denoted by |stream_id| is not found, this function + * returns 0. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_unblock_stream(nghttp3_conn *conn, int64_t stream_id); @@ -2148,9 +2270,24 @@ NGHTTP3_EXTERN void nghttp3_conn_shutdown_stream_write(nghttp3_conn *conn, * @function * * `nghttp3_conn_shutdown_stream_read` tells the library that - * read-side of stream denoted by |stream_id| is abruptly closed and + * read-side of stream denoted by |stream_id| is abruptly closed, and * any further incoming data and pending stream data should be * discarded. + * + * If a stream denoted by |stream_id| is not client bidirectional + * stream, this function returns 0. If the stream has already + * shutdown read-side stream, this function returns 0. + * + * This function does not fail if a stream denoted by |stream_id| is + * not found, although it may fail with the other reasons. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. + * :macro:`NGHTTP3_ERR_QPACK_FATAL` + * QPACK decoder stream overflow. */ NGHTTP3_EXTERN int nghttp3_conn_shutdown_stream_read(nghttp3_conn *conn, int64_t stream_id); @@ -2159,7 +2296,17 @@ NGHTTP3_EXTERN int nghttp3_conn_shutdown_stream_read(nghttp3_conn *conn, * @function * * `nghttp3_conn_resume_stream` resumes stream identified by - * |stream_id| which was previously unable to provide data. + * |stream_id| which was previously unable to provide data. See + * :type:`nghttp3_read_data_callback`. + * + * If a stream denoted by |stream_id| is not found, this function + * returns 0. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_resume_stream(nghttp3_conn *conn, int64_t stream_id); @@ -2168,7 +2315,8 @@ NGHTTP3_EXTERN int nghttp3_conn_resume_stream(nghttp3_conn *conn, * @function * * `nghttp3_conn_close_stream` closes stream identified by - * |stream_id|. |app_error_code| is the reason of the closure. + * |stream_id|. QUIC application error code |app_error_code| is the + * reason of the closure. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -2213,9 +2361,9 @@ NGHTTP3_EXTERN int nghttp3_conn_close_stream(nghttp3_conn *conn, * :macro:`NGHTTP3_DATA_FLAG_NO_END_STREAM` indicates that sending * side of stream is not closed even if :macro:`NGHTTP3_DATA_FLAG_EOF` * is set. Usually this flag is used to send trailer fields with - * `nghttp3_conn_submit_trailers()`. If - * `nghttp3_conn_submit_trailers()` has been called, regardless of - * this flag, the submitted trailer fields are sent. + * `nghttp3_conn_submit_trailers`. If `nghttp3_conn_submit_trailers` + * has been called, regardless of this flag, the submitted trailer + * fields are sent. */ #define NGHTTP3_DATA_FLAG_NO_END_STREAM 0x02u @@ -2260,8 +2408,8 @@ nghttp3_conn_set_max_concurrent_streams(nghttp3_conn *conn, * :macro:`NGHTTP3_DATA_FLAG_EOF` to |*pflags|. * * If the application is unable to provide data temporarily, return - * :macro:`NGHTTP3_ERR_WOULDBLOCK`. When it is ready to provide - * data, call `nghttp3_conn_resume_stream()`. + * :macro:`NGHTTP3_ERR_WOULDBLOCK`. When it is ready to provide data, + * call `nghttp3_conn_resume_stream`. * * The callback should return the number of objects in |vec| that the * application filled if it succeeds, or @@ -2298,6 +2446,18 @@ typedef struct nghttp3_data_reader { * request body, specify NULL. If |dr| is NULL, it implies the end of * stream. |stream_user_data| is an opaque pointer attached to the * stream. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` + * |stream_id| identifies unidirectional stream. + * :macro:`NGHTTP3_ERR_CONN_CLOSING` + * Connection is shutting down, and no new stream is allowed. + * :macro:`NGHTTP3_ERR_STREAM_IN_USE` + * Stream has already been opened. + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_submit_request( nghttp3_conn *conn, int64_t stream_id, const nghttp3_nv *nva, size_t nvlen, @@ -2309,6 +2469,14 @@ NGHTTP3_EXTERN int nghttp3_conn_submit_request( * `nghttp3_conn_submit_info` submits HTTP non-final response header * fields on the stream identified by |stream_id|. |nva| of length * |nvlen| specifies HTTP response header fields. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_STREAM_NOT_FOUND` + * Stream not found + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_submit_info(nghttp3_conn *conn, int64_t stream_id, @@ -2323,6 +2491,14 @@ NGHTTP3_EXTERN int nghttp3_conn_submit_info(nghttp3_conn *conn, * |nvlen| specifies HTTP response header fields. |dr| specifies a * response body. If there is no response body, specify NULL. If * |dr| is NULL, it implies the end of stream. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_STREAM_NOT_FOUND` + * Stream not found + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_submit_response(nghttp3_conn *conn, int64_t stream_id, @@ -2337,6 +2513,16 @@ NGHTTP3_EXTERN int nghttp3_conn_submit_response(nghttp3_conn *conn, * stream identified by |stream_id|. |nva| of length |nvlen| * specifies HTTP trailer fields. Calling this function implies the * end of stream. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_STREAM_NOT_FOUND` + * Stream not found + * :macro:`NGHTTP3_ERR_INVALID_STATE` + * Application has already submitted fin to stream. + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_submit_trailers(nghttp3_conn *conn, int64_t stream_id, @@ -2349,6 +2535,12 @@ NGHTTP3_EXTERN int nghttp3_conn_submit_trailers(nghttp3_conn *conn, * `nghttp3_conn_submit_shutdown_notice` notifies the other endpoint * to stop creating new stream. After a couple of RTTs later, call * `nghttp3_conn_shutdown` to start graceful shutdown. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_submit_shutdown_notice(nghttp3_conn *conn); @@ -2357,9 +2549,15 @@ NGHTTP3_EXTERN int nghttp3_conn_submit_shutdown_notice(nghttp3_conn *conn); * * `nghttp3_conn_shutdown` starts graceful shutdown. It should be * called after `nghttp3_conn_submit_shutdown_notice` and a couple of - * RTT. After calling this function, the local endpoint starts + * RTTs. After calling this function, the local endpoint starts * rejecting new incoming streams. The existing streams are processed - * normally. + * normally. See also `nghttp3_conn_is_drained`. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ NGHTTP3_EXTERN int nghttp3_conn_shutdown(nghttp3_conn *conn); @@ -2368,6 +2566,12 @@ NGHTTP3_EXTERN int nghttp3_conn_shutdown(nghttp3_conn *conn); * * `nghttp3_conn_set_stream_user_data` sets |stream_user_data| to the * stream identified by |stream_id|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_STREAM_NOT_FOUND` + * Stream not found. */ NGHTTP3_EXTERN int nghttp3_conn_set_stream_user_data(nghttp3_conn *conn, int64_t stream_id, @@ -2378,7 +2582,9 @@ NGHTTP3_EXTERN int nghttp3_conn_set_stream_user_data(nghttp3_conn *conn, * * `nghttp3_conn_get_frame_payload_left` returns the number of bytes * left to read current frame payload for a stream denoted by - * |stream_id|. If no such stream is found, it returns 0. + * |stream_id|. If no such stream is found, or |stream_id| identifies + * neither client bidirectional stream nor remote control stream, it + * returns 0. */ NGHTTP3_EXTERN uint64_t nghttp3_conn_get_frame_payload_left(nghttp3_conn *conn, int64_t stream_id); @@ -2417,12 +2623,15 @@ NGHTTP3_EXTERN uint64_t nghttp3_conn_get_frame_payload_left(nghttp3_conn *conn, */ #define NGHTTP3_URGENCY_LEVELS (NGHTTP3_URGENCY_LOW + 1) +#define NGHTTP3_PRI_V1 1 +#define NGHTTP3_PRI_VERSION NGHTTP3_PRI_V1 + /** * @struct * * :type:`nghttp3_pri` represents HTTP priority. */ -typedef struct nghttp3_pri { +typedef struct NGHTTP3_ALIGN(8) nghttp3_pri { /** * :member:`urgency` is the urgency of a stream, it must be in * [:macro:`NGHTTP3_URGENCY_HIGH`, :macro:`NGHTTP3_URGENCY_LOW`], @@ -2431,11 +2640,11 @@ typedef struct nghttp3_pri { uint32_t urgency; /** * :member:`inc` indicates that a content can be processed - * incrementally or not. If inc is 0, it cannot be processed - * incrementally. If inc is 1, it can be processed incrementally. + * incrementally or not. If it is 0, it cannot be processed + * incrementally. If it is 1, it can be processed incrementally. * Other value is not permitted. */ - int inc; + uint8_t inc; } nghttp3_pri; /** @@ -2452,26 +2661,25 @@ typedef struct nghttp3_pri { * This function returns 0 if it succeeds, or one of the following * negative error codes: * + * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` + * |stream_id| is not a client initiated bidirectional stream ID. * :macro:`NGHTTP3_ERR_STREAM_NOT_FOUND` * Stream not found. */ -NGHTTP3_EXTERN int nghttp3_conn_get_stream_priority(nghttp3_conn *conn, - nghttp3_pri *dest, - int64_t stream_id); +NGHTTP3_EXTERN int nghttp3_conn_get_stream_priority_versioned( + nghttp3_conn *conn, int pri_version, nghttp3_pri *dest, int64_t stream_id); /** * @function * - * `nghttp3_conn_set_stream_priority` updates priority of a stream - * denoted by |stream_id| with the value pointed by |pri|. - * |stream_id| must identify client initiated bidirectional stream. - * - * Both client and server can update stream priority with this - * function. + * `nghttp3_conn_set_client_stream_priority` updates priority of a + * stream denoted by |stream_id| with the value pointed by |data| of + * length |datalen|, which should be a serialized :rfc:`9218` priority + * field value. |stream_id| must identify client initiated + * bidirectional stream. * - * If server updates stream priority with this function, it completely - * overrides stream priority set by client and the attempts to update - * priority by client are ignored. + * This function must not be called if |conn| is initialized as + * server. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -2483,20 +2691,37 @@ NGHTTP3_EXTERN int nghttp3_conn_get_stream_priority(nghttp3_conn *conn, * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory. */ -NGHTTP3_EXTERN int nghttp3_conn_set_stream_priority(nghttp3_conn *conn, - int64_t stream_id, - const nghttp3_pri *pri); +NGHTTP3_EXTERN int nghttp3_conn_set_client_stream_priority(nghttp3_conn *conn, + int64_t stream_id, + const uint8_t *data, + size_t datalen); /** * @function * - * `nghttp3_conn_is_remote_qpack_encoder_stream` returns nonzero if a - * stream denoted by |stream_id| is QPACK encoder stream of a remote - * endpoint. + * `nghttp3_conn_set_server_stream_priority` updates priority of a + * stream denoted by |stream_id| with the value pointed by |pri|. + * |stream_id| must identify client initiated bidirectional stream. + * + * This function must not be called if |conn| is initialized as + * client. + * + * This function completely overrides stream priority set by client, + * and any attempts to update priority by client are ignored. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` + * |stream_id| is not a client initiated bidirectional stream ID. + * :macro:`NGHTTP3_ERR_STREAM_NOT_FOUND` + * Stream not found. + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. */ -NGHTTP3_EXTERN int -nghttp3_conn_is_remote_qpack_encoder_stream(nghttp3_conn *conn, - int64_t stream_id); +NGHTTP3_EXTERN int nghttp3_conn_set_server_stream_priority_versioned( + nghttp3_conn *conn, int64_t stream_id, int pri_version, + const nghttp3_pri *pri); /** * @function @@ -2509,11 +2734,11 @@ NGHTTP3_EXTERN uint64_t nghttp3_vec_len(const nghttp3_vec *vec, size_t cnt); /** * @function * - * `nghttp3_check_header_name` returns nonzero if HTTP header field - * name |name| of length |len| is valid according to + * `nghttp3_check_header_name` returns nonzero if HTTP field name + * |name| of length |len| is valid according to * :rfc:`7230#section-3.2`. * - * Because this is a header field name in HTTP/3, the upper cased + * Because this is an HTTP field name in HTTP/3, the upper cased * alphabet is treated as error. */ NGHTTP3_EXTERN int nghttp3_check_header_name(const uint8_t *name, size_t len); @@ -2521,8 +2746,8 @@ NGHTTP3_EXTERN int nghttp3_check_header_name(const uint8_t *name, size_t len); /** * @function * - * `nghttp3_check_header_value` returns nonzero if HTTP header field - * value |value| of length |len| is valid according to + * `nghttp3_check_header_value` returns nonzero if HTTP field value + * |value| of length |len| is valid according to * :rfc:`7230#section-3.2`. */ NGHTTP3_EXTERN int nghttp3_check_header_value(const uint8_t *value, size_t len); @@ -2530,21 +2755,34 @@ NGHTTP3_EXTERN int nghttp3_check_header_value(const uint8_t *value, size_t len); /** * @function * - * `nghttp3_http_parse_priority` parses priority HTTP header field - * stored in the buffer pointed by |value| of length |len|. If it - * successfully processed header field value, it stores the result - * into |*dest|. This function just overwrites what it sees in the - * header field value and does not initialize any field in |*dest|. + * `nghttp3_conn_is_drained` returns nonzero if + * `nghttp3_conn_shutdown` has been called, and there is no active + * remote streams. This function is for server use only. + */ +NGHTTP3_EXTERN int nghttp3_conn_is_drained(nghttp3_conn *conn); + +/** + * @function + * + * `nghttp3_pri_parse_priority` parses Priority header field value + * pointed by |value| of length |len|, and stores the result in the + * object pointed by |dest|. Priority header field is defined in + * :rfc:`9218`. + * + * This function does not initialize the object pointed by |dest| + * before storing the result. It only assigns the values that the + * parser correctly extracted to fields. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` - * The function could not parse the provided value. + * Failed to parse the header field value. */ -NGHTTP3_EXTERN int nghttp3_http_parse_priority(nghttp3_pri *dest, - const uint8_t *value, - size_t len); +NGHTTP3_EXTERN int nghttp3_pri_parse_priority_versioned(int pri_version, + nghttp3_pri *dest, + const uint8_t *value, + size_t len); /** * @macrosection @@ -2562,7 +2800,7 @@ NGHTTP3_EXTERN int nghttp3_http_parse_priority(nghttp3_pri *dest, /** * @struct * - * :type:`nghttp3_info` is what `nghttp3_version()` returns. It holds + * :type:`nghttp3_info` is what `nghttp3_version` returns. It holds * information about the particular nghttp3 version. */ typedef struct nghttp3_info { @@ -2574,7 +2812,7 @@ typedef struct nghttp3_info { int age; /** * :member:`version_num` is the :macro:`NGHTTP3_VERSION_NUM` number - * (since age ==1) + * (since age == 1) */ int version_num; /** @@ -2591,7 +2829,7 @@ typedef struct nghttp3_info { * `nghttp3_version` returns a pointer to a :type:`nghttp3_info` * struct with version information about the run-time library in use. * The |least_version| argument can be set to a 24 bit numerical value - * for the least accepted version number and if the condition is not + * for the least accepted version number, and if the condition is not * met, this function will return a ``NULL``. Pass in 0 to skip the * version checking. */ @@ -2639,6 +2877,33 @@ NGHTTP3_EXTERN int nghttp3_err_is_fatal(int liberr); (CALLBACKS), NGHTTP3_SETTINGS_VERSION, \ (SETTINGS), (MEM), (USER_DATA)) +/* + * `nghttp3_conn_set_server_stream_priority` is a wrapper around + * `nghttp3_conn_set_server_stream_priority_versioned` to set the + * correct struct version. + */ +#define nghttp3_conn_set_server_stream_priority(CONN, STREAM_ID, PRI) \ + nghttp3_conn_set_server_stream_priority_versioned( \ + (CONN), (STREAM_ID), NGHTTP3_PRI_VERSION, (PRI)) + +/* + * `nghttp3_conn_get_stream_priority` is a wrapper around + * `nghttp3_conn_get_stream_priority_versioned` to set the correct + * struct version. + */ +#define nghttp3_conn_get_stream_priority(CONN, DEST, STREAM_ID) \ + nghttp3_conn_get_stream_priority_versioned((CONN), NGHTTP3_PRI_VERSION, \ + (DEST), (STREAM_ID)) + +/* + * `nghttp3_pri_parse_priority` is a wrapper around + * `nghttp3_pri_parse_priority_versioned` to set the correct struct + * version. + */ +#define nghttp3_pri_parse_priority(DEST, VALUE, LEN) \ + nghttp3_pri_parse_priority_versioned(NGHTTP3_PRI_VERSION, (DEST), (VALUE), \ + (LEN)) + #ifdef __cplusplus } #endif diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_conn.c b/deps/ngtcp2/nghttp3/lib/nghttp3_conn.c index 1fbb72c98af2f2..25aaf685734cb1 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_conn.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_conn.c @@ -33,11 +33,14 @@ #include "nghttp3_err.h" #include "nghttp3_conv.h" #include "nghttp3_http.h" +#include "nghttp3_unreachable.h" /* NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY is the upper bound of the dynamic table capacity that QPACK encoder is willing to use. */ #define NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY 4096 +nghttp3_objalloc_def(chunk, nghttp3_chunk, oplent); + /* * conn_remote_stream_uni returns nonzero if |stream_id| is remote * unidirectional stream ID. @@ -56,7 +59,7 @@ static int conn_call_begin_headers(nghttp3_conn *conn, nghttp3_stream *stream) { return 0; } - rv = conn->callbacks.begin_headers(conn, stream->node.nid.id, conn->user_data, + rv = conn->callbacks.begin_headers(conn, stream->node.id, conn->user_data, stream->user_data); if (rv != 0) { /* TODO Allow ignore headers */ @@ -74,8 +77,8 @@ static int conn_call_end_headers(nghttp3_conn *conn, nghttp3_stream *stream, return 0; } - rv = conn->callbacks.end_headers(conn, stream->node.nid.id, fin, - conn->user_data, stream->user_data); + rv = conn->callbacks.end_headers(conn, stream->node.id, fin, conn->user_data, + stream->user_data); if (rv != 0) { /* TODO Allow ignore headers */ return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -92,8 +95,8 @@ static int conn_call_begin_trailers(nghttp3_conn *conn, return 0; } - rv = conn->callbacks.begin_trailers(conn, stream->node.nid.id, - conn->user_data, stream->user_data); + rv = conn->callbacks.begin_trailers(conn, stream->node.id, conn->user_data, + stream->user_data); if (rv != 0) { /* TODO Allow ignore headers */ return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -110,8 +113,8 @@ static int conn_call_end_trailers(nghttp3_conn *conn, nghttp3_stream *stream, return 0; } - rv = conn->callbacks.end_trailers(conn, stream->node.nid.id, fin, - conn->user_data, stream->user_data); + rv = conn->callbacks.end_trailers(conn, stream->node.id, fin, conn->user_data, + stream->user_data); if (rv != 0) { /* TODO Allow ignore headers */ return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -127,7 +130,7 @@ static int conn_call_end_stream(nghttp3_conn *conn, nghttp3_stream *stream) { return 0; } - rv = conn->callbacks.end_stream(conn, stream->node.nid.id, conn->user_data, + rv = conn->callbacks.end_stream(conn, stream->node.id, conn->user_data, stream->user_data); if (rv != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -144,7 +147,7 @@ static int conn_call_stop_sending(nghttp3_conn *conn, nghttp3_stream *stream, return 0; } - rv = conn->callbacks.stop_sending(conn, stream->node.nid.id, app_error_code, + rv = conn->callbacks.stop_sending(conn, stream->node.id, app_error_code, conn->user_data, stream->user_data); if (rv != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -161,7 +164,7 @@ static int conn_call_reset_stream(nghttp3_conn *conn, nghttp3_stream *stream, return 0; } - rv = conn->callbacks.reset_stream(conn, stream->node.nid.id, app_error_code, + rv = conn->callbacks.reset_stream(conn, stream->node.id, app_error_code, conn->user_data, stream->user_data); if (rv != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -179,7 +182,7 @@ static int conn_call_deferred_consume(nghttp3_conn *conn, return 0; } - rv = conn->callbacks.deferred_consume(conn, stream->node.nid.id, nconsumed, + rv = conn->callbacks.deferred_consume(conn, stream->node.id, nconsumed, conn->user_data, stream->user_data); if (rv != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -188,6 +191,22 @@ static int conn_call_deferred_consume(nghttp3_conn *conn, return 0; } +static int conn_call_recv_settings(nghttp3_conn *conn) { + int rv; + + if (!conn->callbacks.recv_settings) { + return 0; + } + + rv = conn->callbacks.recv_settings(conn, &conn->remote.settings, + conn->user_data); + if (rv != 0) { + return NGHTTP3_ERR_CALLBACK_FAILURE; + } + + return 0; +} + static int ricnt_less(const nghttp3_pq_entry *lhsx, const nghttp3_pq_entry *rhsx) { nghttp3_stream *lhs = @@ -204,7 +223,7 @@ static int cycle_less(const nghttp3_pq_entry *lhsx, const nghttp3_tnode *rhs = nghttp3_struct_of(rhsx, nghttp3_tnode, pe); if (lhs->cycle == rhs->cycle) { - return lhs->seq < rhs->seq; + return lhs->id < rhs->id; } return rhs->cycle - lhs->cycle <= NGHTTP3_TNODE_MAX_CYCLE_GAP; @@ -264,7 +283,6 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version, nghttp3_settings_default(&conn->remote.settings); conn->mem = mem; conn->user_data = user_data; - conn->next_seq = 0; conn->server = server; conn->rx.goaway_id = NGHTTP3_VARINT_MAX + 1; conn->tx.goaway_id = NGHTTP3_VARINT_MAX + 1; @@ -454,12 +472,6 @@ nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id, stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL; } } - } else if (nghttp3_stream_uni(stream_id) && - stream->type == NGHTTP3_STREAM_TYPE_PUSH) { - if (stream->rx.hstate == NGHTTP3_HTTP_STATE_NONE) { - stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL; - stream->tx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL; - } } if (srclen == 0 && !fin) { @@ -603,8 +615,7 @@ nghttp3_ssize nghttp3_conn_read_uni(nghttp3_conn *conn, nghttp3_stream *stream, } break; default: - /* unreachable */ - assert(0); + nghttp3_unreachable(); } if (nconsumed < 0) { @@ -686,6 +697,11 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, case NGHTTP3_FRAME_SETTINGS: /* SETTINGS frame might be empty. */ if (rstate->left == 0) { + rv = conn_call_recv_settings(conn); + if (rv != 0) { + return rv; + } + nghttp3_stream_read_state_reset(rstate); break; } @@ -735,11 +751,21 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, } break; case NGHTTP3_CTRL_STREAM_STATE_SETTINGS: - for (; p != end;) { + for (;;) { if (rstate->left == 0) { + rv = conn_call_recv_settings(conn); + if (rv != 0) { + return rv; + } + nghttp3_stream_read_state_reset(rstate); break; } + + if (p == end) { + return (nghttp3_ssize)nconsumed; + } + /* Read Identifier */ len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p)); assert(len > 0); @@ -845,6 +871,11 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, break; } + rv = conn_call_recv_settings(conn); + if (rv != 0) { + return rv; + } + nghttp3_stream_read_state_reset(rstate); break; case NGHTTP3_CTRL_STREAM_STATE_GOAWAY: @@ -1013,8 +1044,7 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, nghttp3_stream_read_state_reset(rstate); break; default: - /* unreachable */ - assert(0); + nghttp3_unreachable(); } } @@ -1022,7 +1052,7 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, } static int conn_delete_stream(nghttp3_conn *conn, nghttp3_stream *stream) { - int bidi = nghttp3_client_stream_bidi(stream->node.nid.id); + int bidi = nghttp3_client_stream_bidi(stream->node.id); int rv; rv = conn_call_deferred_consume(conn, stream, @@ -1032,16 +1062,21 @@ static int conn_delete_stream(nghttp3_conn *conn, nghttp3_stream *stream) { } if (bidi && conn->callbacks.stream_close) { - rv = conn->callbacks.stream_close(conn, stream->node.nid.id, - stream->error_code, conn->user_data, - stream->user_data); + rv = conn->callbacks.stream_close(conn, stream->node.id, stream->error_code, + conn->user_data, stream->user_data); if (rv != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; } } - rv = nghttp3_map_remove(&conn->streams, - (nghttp3_map_key_type)stream->node.nid.id); + if (conn->server && nghttp3_client_stream_bidi(stream->node.id)) { + assert(conn->remote.bidi.num_streams > 0); + + --conn->remote.bidi.num_streams; + } + + rv = + nghttp3_map_remove(&conn->streams, (nghttp3_map_key_type)stream->node.id); assert(0 == rv); @@ -1058,7 +1093,7 @@ static int conn_process_blocked_stream_data(nghttp3_conn *conn, int rv; size_t len; - assert(nghttp3_client_stream_bidi(stream->node.nid.id)); + assert(nghttp3_client_stream_bidi(stream->node.id)); for (;;) { len = nghttp3_ringbuf_len(&stream->inq); @@ -1149,16 +1184,17 @@ static nghttp3_tnode *stream_get_sched_node(nghttp3_stream *stream) { } static int conn_update_stream_priority(nghttp3_conn *conn, - nghttp3_stream *stream, uint8_t pri) { - assert(nghttp3_client_stream_bidi(stream->node.nid.id)); + nghttp3_stream *stream, + const nghttp3_pri *pri) { + assert(nghttp3_client_stream_bidi(stream->node.id)); - if (stream->node.pri == pri) { + if (nghttp3_pri_eq(&stream->node.pri, pri)) { return 0; } nghttp3_conn_unschedule_stream(conn, stream); - stream->node.pri = pri; + stream->node.pri = *pri; if (nghttp3_stream_require_schedule(stream)) { return nghttp3_conn_schedule_stream(conn, stream); @@ -1286,8 +1322,7 @@ nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc, rv = conn_call_begin_trailers(conn, stream); break; default: - /* Unreachable */ - assert(0); + nghttp3_unreachable(); } if (rv != 0) { @@ -1377,9 +1412,7 @@ nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc, rv = 0; break; default: - /* Unreachable */ - assert(0); - abort(); + nghttp3_unreachable(); } if (rv != 0) { @@ -1398,7 +1431,7 @@ nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc, (stream->rx.http.flags & NGHTTP3_HTTP_FLAG_PRIORITY) && !(stream->flags & NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED) && !(stream->flags & NGHTTP3_STREAM_FLAG_SERVER_PRIORITY_SET)) { - rv = conn_update_stream_priority(conn, stream, stream->rx.http.pri); + rv = conn_update_stream_priority(conn, stream, &stream->rx.http.pri); if (rv != 0) { return rv; } @@ -1412,8 +1445,7 @@ nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc, rv = conn_call_end_trailers(conn, stream, p == end && fin); break; default: - /* Unreachable */ - assert(0); + nghttp3_unreachable(); } if (rv != 0) { @@ -1505,7 +1537,7 @@ int nghttp3_conn_on_data(nghttp3_conn *conn, nghttp3_stream *stream, return 0; } - rv = conn->callbacks.recv_data(conn, stream->node.nid.id, data, datalen, + rv = conn->callbacks.recv_data(conn, stream->node.id, data, datalen, conn->user_data, stream->user_data); if (rv != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -1515,11 +1547,9 @@ int nghttp3_conn_on_data(nghttp3_conn *conn, nghttp3_stream *stream, } static nghttp3_pq *conn_get_sched_pq(nghttp3_conn *conn, nghttp3_tnode *tnode) { - uint32_t urgency = nghttp3_pri_uint8_urgency(tnode->pri); + assert(tnode->pri.urgency < NGHTTP3_URGENCY_LEVELS); - assert(urgency < NGHTTP3_URGENCY_LEVELS); - - return &conn->sched[urgency].spq; + return &conn->sched[tnode->pri.urgency].spq; } static nghttp3_ssize conn_decode_headers(nghttp3_conn *conn, @@ -1552,8 +1582,7 @@ static nghttp3_ssize conn_decode_headers(nghttp3_conn *conn, recv_header = conn->callbacks.recv_trailer; break; default: - /* Unreachable */ - assert(0); + nghttp3_unreachable(); } http = &stream->rx.http; @@ -1606,17 +1635,15 @@ static nghttp3_ssize conn_decode_headers(nghttp3_conn *conn, break; case 0: if (recv_header) { - rv = recv_header(conn, stream->node.nid.id, nv.token, nv.name, - nv.value, nv.flags, conn->user_data, - stream->user_data); + rv = recv_header(conn, stream->node.id, nv.token, nv.name, nv.value, + nv.flags, conn->user_data, stream->user_data); if (rv != 0) { rv = NGHTTP3_ERR_CALLBACK_FAILURE; } } break; default: - /* Unreachable */ - assert(0); + nghttp3_unreachable(); } nghttp3_rcbuf_decref(nv.name); @@ -1684,13 +1711,32 @@ int nghttp3_conn_on_settings_entry_received(nghttp3_conn *conn, if (!conn->server) { break; } - if (ent->value != 0 && ent->value != 1) { + + switch (ent->value) { + case 0: + if (dest->enable_connect_protocol) { + return NGHTTP3_ERR_H3_SETTINGS_ERROR; + } + + break; + case 1: + break; + default: return NGHTTP3_ERR_H3_SETTINGS_ERROR; } - if (ent->value == 0 && dest->enable_connect_protocol) { + + dest->enable_connect_protocol = (uint8_t)ent->value; + break; + case NGHTTP3_SETTINGS_ID_H3_DATAGRAM: + switch (ent->value) { + case 0: + case 1: + break; + default: return NGHTTP3_ERR_H3_SETTINGS_ERROR; } - dest->enable_connect_protocol = (int)ent->value; + + dest->h3_datagram = (uint8_t)ent->value; break; case NGHTTP3_H2_SETTINGS_ID_ENABLE_PUSH: case NGHTTP3_H2_SETTINGS_ID_MAX_CONCURRENT_STREAMS: @@ -1744,7 +1790,7 @@ conn_on_priority_update_stream(nghttp3_conn *conn, return rv; } - stream->node.pri = nghttp3_pri_to_uint8(&fr->pri); + stream->node.pri = fr->pri; stream->flags |= NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED; return 0; @@ -1756,8 +1802,7 @@ conn_on_priority_update_stream(nghttp3_conn *conn, stream->flags |= NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED; - return conn_update_stream_priority(conn, stream, - nghttp3_pri_to_uint8(&fr->pri)); + return conn_update_stream_priority(conn, stream, &fr->pri); } int nghttp3_conn_on_priority_update(nghttp3_conn *conn, @@ -1794,7 +1839,7 @@ int nghttp3_conn_create_stream(nghttp3_conn *conn, nghttp3_stream **pstream, conn_stream_acked_data, }; - rv = nghttp3_stream_new(&stream, stream_id, conn->next_seq, &callbacks, + rv = nghttp3_stream_new(&stream, stream_id, &callbacks, &conn->out_chunk_objalloc, &conn->stream_objalloc, conn->mem); if (rv != 0) { @@ -1803,14 +1848,17 @@ int nghttp3_conn_create_stream(nghttp3_conn *conn, nghttp3_stream **pstream, stream->conn = conn; - rv = nghttp3_map_insert(&conn->streams, - (nghttp3_map_key_type)stream->node.nid.id, stream); + rv = nghttp3_map_insert(&conn->streams, (nghttp3_map_key_type)stream->node.id, + stream); if (rv != 0) { nghttp3_stream_del(stream); return rv; } - ++conn->next_seq; + if (conn->server && nghttp3_client_stream_bidi(stream_id)) { + ++conn->remote.bidi.num_streams; + } + *pstream = stream; return 0; @@ -1897,7 +1945,7 @@ static nghttp3_ssize conn_writev_stream(nghttp3_conn *conn, int64_t *pstream_id, int *pfin, nghttp3_vec *vec, size_t veccnt, nghttp3_stream *stream) { int rv; - nghttp3_ssize n; + size_t n; assert(veccnt > 0); @@ -1910,31 +1958,25 @@ static nghttp3_ssize conn_writev_stream(nghttp3_conn *conn, int64_t *pstream_id, } } - if (!nghttp3_stream_uni(stream->node.nid.id) && conn->tx.qenc && + if (!nghttp3_stream_uni(stream->node.id) && conn->tx.qenc && !nghttp3_stream_is_blocked(conn->tx.qenc)) { n = nghttp3_stream_writev(conn->tx.qenc, pfin, vec, veccnt); - if (n < 0) { - return n; - } if (n) { - *pstream_id = conn->tx.qenc->node.nid.id; - return n; + *pstream_id = conn->tx.qenc->node.id; + return (nghttp3_ssize)n; } } n = nghttp3_stream_writev(stream, pfin, vec, veccnt); - if (n < 0) { - return n; - } /* We might just want to write stream fin without sending any stream data. */ if (n == 0 && *pfin == 0) { return 0; } - *pstream_id = stream->node.nid.id; + *pstream_id = stream->node.id; - return n; + return (nghttp3_ssize)n; } nghttp3_ssize nghttp3_conn_writev_stream(nghttp3_conn *conn, @@ -1990,7 +2032,7 @@ nghttp3_ssize nghttp3_conn_writev_stream(nghttp3_conn *conn, return ncnt; } - if (nghttp3_client_stream_bidi(stream->node.nid.id) && + if (nghttp3_client_stream_bidi(stream->node.id) && !nghttp3_stream_require_schedule(stream)) { nghttp3_conn_unschedule_stream(conn, stream); } @@ -2020,20 +2062,16 @@ nghttp3_stream *nghttp3_conn_get_next_tx_stream(nghttp3_conn *conn) { int nghttp3_conn_add_write_offset(nghttp3_conn *conn, int64_t stream_id, size_t n) { nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id); - int rv; if (stream == NULL) { return 0; } - rv = nghttp3_stream_add_outq_offset(stream, n); - if (rv != 0) { - return rv; - } + nghttp3_stream_add_outq_offset(stream, n); stream->unscheduled_nwrite += n; - if (!nghttp3_client_stream_bidi(stream->node.nid.id)) { + if (!nghttp3_client_stream_bidi(stream->node.id)) { return 0; } @@ -2065,7 +2103,7 @@ static int conn_submit_headers_data(nghttp3_conn *conn, nghttp3_stream *stream, const nghttp3_data_reader *dr) { int rv; nghttp3_nv *nnva; - nghttp3_frame_entry frent; + nghttp3_frame_entry frent = {0}; rv = nghttp3_nva_copy(&nnva, nva, nvlen, conn->mem); if (rv != 0) { @@ -2235,7 +2273,7 @@ int nghttp3_conn_submit_trailers(nghttp3_conn *conn, int64_t stream_id, } int nghttp3_conn_submit_shutdown_notice(nghttp3_conn *conn) { - nghttp3_frame_entry frent; + nghttp3_frame_entry frent = {0}; int rv; assert(conn->tx.ctrl); @@ -2258,7 +2296,7 @@ int nghttp3_conn_submit_shutdown_notice(nghttp3_conn *conn) { } int nghttp3_conn_shutdown(nghttp3_conn *conn) { - nghttp3_frame_entry frent; + nghttp3_frame_entry frent = {0}; int rv; assert(conn->tx.ctrl); @@ -2279,7 +2317,8 @@ int nghttp3_conn_shutdown(nghttp3_conn *conn) { } conn->tx.goaway_id = frent.fr.goaway.id; - conn->flags |= NGHTTP3_CONN_FLAG_GOAWAY_QUEUED; + conn->flags |= + NGHTTP3_CONN_FLAG_GOAWAY_QUEUED | NGHTTP3_CONN_FLAG_SHUTDOWN_COMMENCED; return 0; } @@ -2305,7 +2344,7 @@ void nghttp3_conn_block_stream(nghttp3_conn *conn, int64_t stream_id) { stream->flags |= NGHTTP3_STREAM_FLAG_FC_BLOCKED; stream->unscheduled_nwrite = 0; - if (nghttp3_client_stream_bidi(stream->node.nid.id)) { + if (nghttp3_client_stream_bidi(stream->node.id)) { nghttp3_conn_unschedule_stream(conn, stream); } } @@ -2320,7 +2359,7 @@ void nghttp3_conn_shutdown_stream_write(nghttp3_conn *conn, int64_t stream_id) { stream->flags |= NGHTTP3_STREAM_FLAG_SHUT_WR; stream->unscheduled_nwrite = 0; - if (nghttp3_client_stream_bidi(stream->node.nid.id)) { + if (nghttp3_client_stream_bidi(stream->node.id)) { nghttp3_conn_unschedule_stream(conn, stream); } } @@ -2334,7 +2373,7 @@ int nghttp3_conn_unblock_stream(nghttp3_conn *conn, int64_t stream_id) { stream->flags &= (uint16_t)~NGHTTP3_STREAM_FLAG_FC_BLOCKED; - if (nghttp3_client_stream_bidi(stream->node.nid.id) && + if (nghttp3_client_stream_bidi(stream->node.id) && nghttp3_stream_require_schedule(stream)) { return nghttp3_conn_ensure_stream_scheduled(conn, stream); } @@ -2364,7 +2403,7 @@ int nghttp3_conn_resume_stream(nghttp3_conn *conn, int64_t stream_id) { stream->flags &= (uint16_t)~NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED; - if (nghttp3_client_stream_bidi(stream->node.nid.id) && + if (nghttp3_client_stream_bidi(stream->node.id) && nghttp3_stream_require_schedule(stream)) { return nghttp3_conn_ensure_stream_scheduled(conn, stream); } @@ -2381,7 +2420,6 @@ int nghttp3_conn_close_stream(nghttp3_conn *conn, int64_t stream_id, } if (nghttp3_stream_uni(stream_id) && - stream->type != NGHTTP3_STREAM_TYPE_PUSH && stream->type != NGHTTP3_STREAM_TYPE_UNKNOWN) { return NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM; } @@ -2459,18 +2497,34 @@ int nghttp3_conn_set_stream_user_data(nghttp3_conn *conn, int64_t stream_id, uint64_t nghttp3_conn_get_frame_payload_left(nghttp3_conn *conn, int64_t stream_id) { - nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id); + nghttp3_stream *stream; + int uni = 0; + + if (!nghttp3_client_stream_bidi(stream_id)) { + uni = conn_remote_stream_uni(conn, stream_id); + if (!uni) { + return 0; + } + } + stream = nghttp3_conn_find_stream(conn, stream_id); if (stream == NULL) { return 0; } + if (uni && stream->type != NGHTTP3_STREAM_TYPE_CONTROL) { + return 0; + } + return (uint64_t)stream->rstate.left; } -int nghttp3_conn_get_stream_priority(nghttp3_conn *conn, nghttp3_pri *dest, - int64_t stream_id) { +int nghttp3_conn_get_stream_priority_versioned(nghttp3_conn *conn, + int pri_version, + nghttp3_pri *dest, + int64_t stream_id) { nghttp3_stream *stream; + (void)pri_version; assert(conn->server); @@ -2483,19 +2537,20 @@ int nghttp3_conn_get_stream_priority(nghttp3_conn *conn, nghttp3_pri *dest, return NGHTTP3_ERR_STREAM_NOT_FOUND; } - dest->urgency = nghttp3_pri_uint8_urgency(stream->node.pri); - dest->inc = nghttp3_pri_uint8_inc(stream->node.pri); + *dest = stream->node.pri; return 0; } -int nghttp3_conn_set_stream_priority(nghttp3_conn *conn, int64_t stream_id, - const nghttp3_pri *pri) { +int nghttp3_conn_set_client_stream_priority(nghttp3_conn *conn, + int64_t stream_id, + const uint8_t *data, + size_t datalen) { nghttp3_stream *stream; - nghttp3_frame_entry frent; + nghttp3_frame_entry frent = {0}; + uint8_t *buf = NULL; - assert(pri->urgency < NGHTTP3_URGENCY_LEVELS); - assert(pri->inc == 0 || pri->inc == 1); + assert(!conn->server); if (!nghttp3_client_stream_bidi(stream_id)) { return NGHTTP3_ERR_INVALID_ARGUMENT; @@ -2506,29 +2561,55 @@ int nghttp3_conn_set_stream_priority(nghttp3_conn *conn, int64_t stream_id, return NGHTTP3_ERR_STREAM_NOT_FOUND; } - if (conn->server) { - stream->flags |= NGHTTP3_STREAM_FLAG_SERVER_PRIORITY_SET; + if (datalen) { + buf = nghttp3_mem_malloc(conn->mem, datalen); + if (buf == NULL) { + return NGHTTP3_ERR_NOMEM; + } - return conn_update_stream_priority(conn, stream, nghttp3_pri_to_uint8(pri)); + memcpy(buf, data, datalen); } frent.fr.hd.type = NGHTTP3_FRAME_PRIORITY_UPDATE; frent.fr.priority_update.pri_elem_id = stream_id; - frent.fr.priority_update.pri = *pri; + frent.fr.priority_update.data = buf; + frent.fr.priority_update.datalen = datalen; return nghttp3_stream_frq_add(conn->tx.ctrl, &frent); } -int nghttp3_conn_is_remote_qpack_encoder_stream(nghttp3_conn *conn, - int64_t stream_id) { +int nghttp3_conn_set_server_stream_priority_versioned(nghttp3_conn *conn, + int64_t stream_id, + int pri_version, + const nghttp3_pri *pri) { nghttp3_stream *stream; + (void)pri_version; - if (!conn_remote_stream_uni(conn, stream_id)) { - return 0; + assert(conn->server); + assert(pri->urgency < NGHTTP3_URGENCY_LEVELS); + assert(pri->inc == 0 || pri->inc == 1); + + if (!nghttp3_client_stream_bidi(stream_id)) { + return NGHTTP3_ERR_INVALID_ARGUMENT; } stream = nghttp3_conn_find_stream(conn, stream_id); - return stream && stream->type == NGHTTP3_STREAM_TYPE_QPACK_ENCODER; + if (stream == NULL) { + return NGHTTP3_ERR_STREAM_NOT_FOUND; + } + + stream->flags |= NGHTTP3_STREAM_FLAG_SERVER_PRIORITY_SET; + + return conn_update_stream_priority(conn, stream, pri); +} + +int nghttp3_conn_is_drained(nghttp3_conn *conn) { + assert(conn->server); + + return (conn->flags & NGHTTP3_CONN_FLAG_SHUTDOWN_COMMENCED) && + conn->remote.bidi.num_streams == 0 && + nghttp3_stream_outq_write_done(conn->tx.ctrl) && + nghttp3_ringbuf_len(&conn->tx.ctrl->frq) == 0; } void nghttp3_settings_default_versioned(int settings_version, diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_conn.h b/deps/ngtcp2/nghttp3/lib/nghttp3_conn.h index fa7071e4b1ddb7..74f47583ce825c 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_conn.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_conn.h @@ -62,6 +62,9 @@ /* NGHTTP3_CONN_FLAG_QPACK_DECODER_OPENED is set when a QPACK decoder stream has opened. */ #define NGHTTP3_CONN_FLAG_QPACK_DECODER_OPENED 0x0008u +/* NGHTTP3_CONN_FLAG_SHUTDOWN_COMMENCED is set when graceful shutdown + has started. */ +#define NGHTTP3_CONN_FLAG_SHUTDOWN_COMMENCED 0x0010u /* NGHTTP3_CONN_FLAG_GOAWAY_RECVED indicates that GOAWAY frame has received. */ #define NGHTTP3_CONN_FLAG_GOAWAY_RECVED 0x0020u @@ -73,7 +76,7 @@ typedef struct nghttp3_chunk { nghttp3_opl_entry oplent; } nghttp3_chunk; -nghttp3_objalloc_def(chunk, nghttp3_chunk, oplent); +nghttp3_objalloc_decl(chunk, nghttp3_chunk, oplent); struct nghttp3_conn { nghttp3_objalloc out_chunk_objalloc; @@ -90,7 +93,6 @@ struct nghttp3_conn { void *user_data; int server; uint16_t flags; - uint64_t next_seq; struct { nghttp3_settings settings; @@ -109,6 +111,10 @@ struct nghttp3_conn { initiated bidirectional stream ID the remote endpoint can issue. This field is used on server side only. */ uint64_t max_client_streams; + /* num_streams is the number of client initiated bidirectional + streams that are currently open. This field is for server + use only. */ + size_t num_streams; } bidi; nghttp3_settings settings; } remote; diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_conv.c b/deps/ngtcp2/nghttp3/lib/nghttp3_conv.c index cb340ab5a11363..edd0adc4d0ff0a 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_conv.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_conv.c @@ -29,6 +29,7 @@ #include #include "nghttp3_str.h" +#include "nghttp3_unreachable.h" int64_t nghttp3_get_varint(size_t *plen, const uint8_t *p) { union { @@ -38,7 +39,7 @@ int64_t nghttp3_get_varint(size_t *plen, const uint8_t *p) { uint64_t n64; } n; - *plen = 1u << (*p >> 6); + *plen = (size_t)(1u << (*p >> 6)); switch (*plen) { case 1: @@ -57,34 +58,25 @@ int64_t nghttp3_get_varint(size_t *plen, const uint8_t *p) { return (int64_t)nghttp3_ntohl64(n.n64); } - assert(0); - abort(); + nghttp3_unreachable(); } int64_t nghttp3_get_varint_fb(const uint8_t *p) { return *p & 0x3f; } -size_t nghttp3_get_varint_len(const uint8_t *p) { return 1u << (*p >> 6); } +size_t nghttp3_get_varintlen(const uint8_t *p) { + return (size_t)(1u << (*p >> 6)); +} uint8_t *nghttp3_put_uint64be(uint8_t *p, uint64_t n) { n = nghttp3_htonl64(n); return nghttp3_cpymem(p, (const uint8_t *)&n, sizeof(n)); } -uint8_t *nghttp3_put_uint48be(uint8_t *p, uint64_t n) { - n = nghttp3_htonl64(n); - return nghttp3_cpymem(p, ((const uint8_t *)&n) + 2, 6); -} - uint8_t *nghttp3_put_uint32be(uint8_t *p, uint32_t n) { n = htonl(n); return nghttp3_cpymem(p, (const uint8_t *)&n, sizeof(n)); } -uint8_t *nghttp3_put_uint24be(uint8_t *p, uint32_t n) { - n = htonl(n); - return nghttp3_cpymem(p, ((const uint8_t *)&n) + 1, 3); -} - uint8_t *nghttp3_put_uint16be(uint8_t *p, uint16_t n) { n = htons(n); return nghttp3_cpymem(p, (const uint8_t *)&n, sizeof(n)); @@ -112,7 +104,7 @@ uint8_t *nghttp3_put_varint(uint8_t *p, int64_t n) { return rv; } -size_t nghttp3_put_varint_len(int64_t n) { +size_t nghttp3_put_varintlen(int64_t n) { if (n < 64) { return 1; } @@ -129,7 +121,3 @@ size_t nghttp3_put_varint_len(int64_t n) { uint64_t nghttp3_ord_stream_id(int64_t stream_id) { return (uint64_t)(stream_id >> 2) + 1; } - -uint8_t nghttp3_pri_to_uint8(const nghttp3_pri *pri) { - return (uint8_t)((uint32_t)pri->inc << 7 | pri->urgency); -} diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_conv.h b/deps/ngtcp2/nghttp3/lib/nghttp3_conv.h index 23555be7cac027..5522bc735bfd37 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_conv.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_conv.h @@ -50,15 +50,11 @@ # include #endif /* HAVE_SYS_ENDIAN_H */ -#include +#if defined(__APPLE__) +# include +#endif // __APPLE__ -#if defined(HAVE_BSWAP_64) || \ - (defined(HAVE_DECL_BSWAP_64) && HAVE_DECL_BSWAP_64 > 0) -# define nghttp3_bswap64 bswap_64 -#else /* !HAVE_BSWAP_64 */ -# define nghttp3_bswap64(N) \ - ((uint64_t)(ntohl((uint32_t)(N))) << 32 | ntohl((uint32_t)((N) >> 32))) -#endif /* !HAVE_BSWAP_64 */ +#include #if defined(HAVE_BE64TOH) || \ (defined(HAVE_DECL_BE64TOH) && HAVE_DECL_BE64TOH > 0) @@ -69,6 +65,17 @@ # define nghttp3_ntohl64(N) (N) # define nghttp3_htonl64(N) (N) # else /* !WORDS_BIGENDIAN */ +# if defined(HAVE_BSWAP_64) || \ + (defined(HAVE_DECL_BSWAP_64) && HAVE_DECL_BSWAP_64 > 0) +# define nghttp3_bswap64 bswap_64 +# elif defined(WIN32) +# define nghttp3_bswap64 _byteswap_uint64 +# elif defined(__APPLE__) +# define nghttp3_bswap64 OSSwapInt64 +# else /* !HAVE_BSWAP_64 && !WIN32 && !__APPLE__ */ +# define nghttp3_bswap64(N) \ + ((uint64_t)(ntohl((uint32_t)(N))) << 32 | ntohl((uint32_t)((N) >> 32))) +# endif /* !HAVE_BSWAP_64 && !WIN32 && !__APPLE__ */ # define nghttp3_ntohl64(N) nghttp3_bswap64(N) # define nghttp3_htonl64(N) nghttp3_bswap64(N) # endif /* !WORDS_BIGENDIAN */ @@ -106,9 +113,9 @@ STIN uint16_t htons(uint16_t hostshort) { STIN uint32_t ntohl(uint32_t netlong) { uint32_t res; unsigned char *p = (unsigned char *)&netlong; - res = *p++ << 24; - res += *p++ << 16; - res += *p++ << 8; + res = (uint32_t)(*p++ << 24); + res += (uint32_t)(*p++ << 16); + res += (uint32_t)(*p++ << 8); res += *p; return res; } @@ -116,7 +123,7 @@ STIN uint32_t ntohl(uint32_t netlong) { STIN uint16_t ntohs(uint16_t netshort) { uint16_t res; unsigned char *p = (unsigned char *)&netshort; - res = *p++ << 8; + res = (uint16_t)(*p++ << 8); res += *p; return res; } @@ -137,10 +144,10 @@ int64_t nghttp3_get_varint(size_t *plen, const uint8_t *p); int64_t nghttp3_get_varint_fb(const uint8_t *p); /* - * nghttp3_get_varint_len returns the required number of bytes to read + * nghttp3_get_varintlen returns the required number of bytes to read * variable-length integer starting at |p|. */ -size_t nghttp3_get_varint_len(const uint8_t *p); +size_t nghttp3_get_varintlen(const uint8_t *p); /* * nghttp3_put_uint64be writes |n| in host byte order in |p| in @@ -149,13 +156,6 @@ size_t nghttp3_get_varint_len(const uint8_t *p); */ uint8_t *nghttp3_put_uint64be(uint8_t *p, uint64_t n); -/* - * nghttp3_put_uint48be writes |n| in host byte order in |p| in - * network byte order. It writes only least significant 48 bits. It - * returns the one beyond of the last written position. - */ -uint8_t *nghttp3_put_uint48be(uint8_t *p, uint64_t n); - /* * nghttp3_put_uint32be writes |n| in host byte order in |p| in * network byte order. It returns the one beyond of the last written @@ -163,13 +163,6 @@ uint8_t *nghttp3_put_uint48be(uint8_t *p, uint64_t n); */ uint8_t *nghttp3_put_uint32be(uint8_t *p, uint32_t n); -/* - * nghttp3_put_uint24be writes |n| in host byte order in |p| in - * network byte order. It writes only least significant 24 bits. It - * returns the one beyond of the last written position. - */ -uint8_t *nghttp3_put_uint24be(uint8_t *p, uint32_t n); - /* * nghttp3_put_uint16be writes |n| in host byte order in |p| in * network byte order. It returns the one beyond of the last written @@ -184,10 +177,10 @@ uint8_t *nghttp3_put_uint16be(uint8_t *p, uint16_t n); uint8_t *nghttp3_put_varint(uint8_t *p, int64_t n); /* - * nghttp3_put_varint_len returns the required number of bytes to + * nghttp3_put_varintlen returns the required number of bytes to * encode |n|. */ -size_t nghttp3_put_varint_len(int64_t n); +size_t nghttp3_put_varintlen(int64_t n); /* * nghttp3_ord_stream_id returns the ordinal number of |stream_id|. @@ -200,22 +193,4 @@ uint64_t nghttp3_ord_stream_id(int64_t stream_id); */ #define NGHTTP3_PRI_INC_MASK (1 << 7) -/* - * nghttp3_pri_to_uint8 encodes |pri| into uint8_t variable. - */ -uint8_t nghttp3_pri_to_uint8(const nghttp3_pri *pri); - -/* - * nghttp3_pri_uint8_urgency extracts urgency from |PRI| which is - * supposed to be constructed by nghttp3_pri_to_uint8. - */ -#define nghttp3_pri_uint8_urgency(PRI) \ - ((uint32_t)((PRI) & ~NGHTTP3_PRI_INC_MASK)) - -/* - * nghttp3_pri_uint8_inc extracts inc from |PRI| which is supposed to - * be constructed by nghttp3_pri_to_uint8. - */ -#define nghttp3_pri_uint8_inc(PRI) (((PRI)&NGHTTP3_PRI_INC_MASK) != 0) - #endif /* NGHTTP3_CONV_H */ diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_err.c b/deps/ngtcp2/nghttp3/lib/nghttp3_err.c index 5cf94db852f71f..0d596bfab6d29d 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_err.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_err.c @@ -28,8 +28,6 @@ const char *nghttp3_strerror(int liberr) { switch (liberr) { case NGHTTP3_ERR_INVALID_ARGUMENT: return "ERR_INVALID_ARGUMENT"; - case NGHTTP3_ERR_NOBUF: - return "ERR_NOBUF"; case NGHTTP3_ERR_INVALID_STATE: return "ERR_INVALID_STATE"; case NGHTTP3_ERR_WOULDBLOCK: @@ -104,6 +102,9 @@ uint64_t nghttp3_err_infer_quic_app_error_code(int liberr) { case NGHTTP3_ERR_H3_INTERNAL_ERROR: case NGHTTP3_ERR_NOMEM: case NGHTTP3_ERR_CALLBACK_FAILURE: + case NGHTTP3_ERR_QPACK_FATAL: + case NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE: + case NGHTTP3_ERR_STREAM_DATA_OVERFLOW: return NGHTTP3_H3_INTERNAL_ERROR; case NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM: return NGHTTP3_H3_CLOSED_CRITICAL_STREAM; diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_frame.c b/deps/ngtcp2/nghttp3/lib/nghttp3_frame.c index 38c395ebe16162..923a78f90f826f 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_frame.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_frame.c @@ -38,7 +38,7 @@ uint8_t *nghttp3_frame_write_hd(uint8_t *p, const nghttp3_frame_hd *hd) { } size_t nghttp3_frame_write_hd_len(const nghttp3_frame_hd *hd) { - return nghttp3_put_varint_len(hd->type) + nghttp3_put_varint_len(hd->length); + return nghttp3_put_varintlen(hd->type) + nghttp3_put_varintlen(hd->length); } uint8_t *nghttp3_frame_write_settings(uint8_t *p, @@ -61,14 +61,14 @@ size_t nghttp3_frame_write_settings_len(int64_t *ppayloadlen, size_t i; for (i = 0; i < fr->niv; ++i) { - payloadlen += nghttp3_put_varint_len((int64_t)fr->iv[i].id) + - nghttp3_put_varint_len((int64_t)fr->iv[i].value); + payloadlen += nghttp3_put_varintlen((int64_t)fr->iv[i].id) + + nghttp3_put_varintlen((int64_t)fr->iv[i].value); } *ppayloadlen = (int64_t)payloadlen; - return nghttp3_put_varint_len(NGHTTP3_FRAME_SETTINGS) + - nghttp3_put_varint_len((int64_t)payloadlen) + payloadlen; + return nghttp3_put_varintlen(NGHTTP3_FRAME_SETTINGS) + + nghttp3_put_varintlen((int64_t)payloadlen) + payloadlen; } uint8_t *nghttp3_frame_write_goaway(uint8_t *p, @@ -81,12 +81,12 @@ uint8_t *nghttp3_frame_write_goaway(uint8_t *p, size_t nghttp3_frame_write_goaway_len(int64_t *ppayloadlen, const nghttp3_frame_goaway *fr) { - size_t payloadlen = nghttp3_put_varint_len(fr->id); + size_t payloadlen = nghttp3_put_varintlen(fr->id); *ppayloadlen = (int64_t)payloadlen; - return nghttp3_put_varint_len(NGHTTP3_FRAME_GOAWAY) + - nghttp3_put_varint_len((int64_t)payloadlen) + payloadlen; + return nghttp3_put_varintlen(NGHTTP3_FRAME_GOAWAY) + + nghttp3_put_varintlen((int64_t)payloadlen) + payloadlen; } uint8_t * @@ -94,17 +94,8 @@ nghttp3_frame_write_priority_update(uint8_t *p, const nghttp3_frame_priority_update *fr) { p = nghttp3_frame_write_hd(p, &fr->hd); p = nghttp3_put_varint(p, fr->pri_elem_id); - - assert(fr->pri.urgency <= NGHTTP3_URGENCY_LOW); - - *p++ = 'u'; - *p++ = '='; - *p++ = (uint8_t)('0' + fr->pri.urgency); - - if (fr->pri.inc) { -#define NGHTTP3_PRIORITY_INCREMENTAL ", i" - p = nghttp3_cpymem(p, (const uint8_t *)NGHTTP3_PRIORITY_INCREMENTAL, - sizeof(NGHTTP3_PRIORITY_INCREMENTAL) - 1); + if (fr->datalen) { + p = nghttp3_cpymem(p, fr->data, fr->datalen); } return p; @@ -112,13 +103,12 @@ nghttp3_frame_write_priority_update(uint8_t *p, size_t nghttp3_frame_write_priority_update_len( int64_t *ppayloadlen, const nghttp3_frame_priority_update *fr) { - size_t payloadlen = nghttp3_put_varint_len(fr->pri_elem_id) + sizeof("u=U") - - 1 + (fr->pri.inc ? sizeof(", i") - 1 : 0); + size_t payloadlen = nghttp3_put_varintlen(fr->pri_elem_id) + fr->datalen; *ppayloadlen = (int64_t)payloadlen; - return nghttp3_put_varint_len(fr->hd.type) + - nghttp3_put_varint_len((int64_t)payloadlen) + payloadlen; + return nghttp3_put_varintlen(fr->hd.type) + + nghttp3_put_varintlen((int64_t)payloadlen) + payloadlen; } int nghttp3_nva_copy(nghttp3_nv **pnva, const nghttp3_nv *nva, size_t nvlen, @@ -164,11 +154,11 @@ int nghttp3_nva_copy(nghttp3_nv **pnva, const nghttp3_nv *nva, size_t nvlen, } else { if (nva[i].namelen) { memcpy(data, nva[i].name, nva[i].namelen); + nghttp3_downcase(data, nva[i].namelen); } p->name = data; p->namelen = nva[i].namelen; data[p->namelen] = '\0'; - nghttp3_downcase(p->name, p->namelen); data += nva[i].namelen + 1; } @@ -202,3 +192,12 @@ void nghttp3_frame_headers_free(nghttp3_frame_headers *fr, nghttp3_nva_del(fr->nva, mem); } + +void nghttp3_frame_priority_update_free(nghttp3_frame_priority_update *fr, + const nghttp3_mem *mem) { + if (fr == NULL) { + return; + } + + nghttp3_mem_free(mem, fr->data); +} diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_frame.h b/deps/ngtcp2/nghttp3/lib/nghttp3_frame.h index b64bbc4ecb9667..1079673d150ce3 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_frame.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_frame.h @@ -34,26 +34,23 @@ #include "nghttp3_buf.h" -typedef enum nghttp3_frame_type { - NGHTTP3_FRAME_DATA = 0x00, - NGHTTP3_FRAME_HEADERS = 0x01, - NGHTTP3_FRAME_CANCEL_PUSH = 0x03, - NGHTTP3_FRAME_SETTINGS = 0x04, - NGHTTP3_FRAME_PUSH_PROMISE = 0x05, - NGHTTP3_FRAME_GOAWAY = 0x07, - NGHTTP3_FRAME_MAX_PUSH_ID = 0x0d, - /* PRIORITY_UPDATE: - https://tools.ietf.org/html/draft-ietf-httpbis-priority-03 */ - NGHTTP3_FRAME_PRIORITY_UPDATE = 0x0f0700, - NGHTTP3_FRAME_PRIORITY_UPDATE_PUSH_ID = 0x0f0701, -} nghttp3_frame_type; - -typedef enum nghttp3_h2_reserved_type { - NGHTTP3_H2_FRAME_PRIORITY = 0x02, - NGHTTP3_H2_FRAME_PING = 0x06, - NGHTTP3_H2_FRAME_WINDOW_UPDATE = 0x08, - NGHTTP3_H2_FRAME_CONTINUATION = 0x9, -} nghttp3_h2_reserved_type; +#define NGHTTP3_FRAME_DATA 0x00 +#define NGHTTP3_FRAME_HEADERS 0x01 +#define NGHTTP3_FRAME_CANCEL_PUSH 0x03 +#define NGHTTP3_FRAME_SETTINGS 0x04 +#define NGHTTP3_FRAME_PUSH_PROMISE 0x05 +#define NGHTTP3_FRAME_GOAWAY 0x07 +#define NGHTTP3_FRAME_MAX_PUSH_ID 0x0d +/* PRIORITY_UPDATE: https://datatracker.ietf.org/doc/html/rfc9218 */ +#define NGHTTP3_FRAME_PRIORITY_UPDATE 0x0f0700 +#define NGHTTP3_FRAME_PRIORITY_UPDATE_PUSH_ID 0x0f0701 + +/* Frame types that are reserved for HTTP/2, and must not be used in + HTTP/3. */ +#define NGHTTP3_H2_FRAME_PRIORITY 0x02 +#define NGHTTP3_H2_FRAME_PING 0x06 +#define NGHTTP3_H2_FRAME_WINDOW_UPDATE 0x08 +#define NGHTTP3_H2_FRAME_CONTINUATION 0x9 typedef struct nghttp3_frame_hd { int64_t type; @@ -74,6 +71,7 @@ typedef struct nghttp3_frame_headers { #define NGHTTP3_SETTINGS_ID_QPACK_MAX_TABLE_CAPACITY 0x01 #define NGHTTP3_SETTINGS_ID_QPACK_BLOCKED_STREAMS 0x07 #define NGHTTP3_SETTINGS_ID_ENABLE_CONNECT_PROTOCOL 0x08 +#define NGHTTP3_SETTINGS_ID_H3_DATAGRAM 0x33 #define NGHTTP3_H2_SETTINGS_ID_ENABLE_PUSH 0x2 #define NGHTTP3_H2_SETTINGS_ID_MAX_CONCURRENT_STREAMS 0x3 @@ -103,7 +101,17 @@ typedef struct nghttp3_frame_priority_update { NGHTTP3_FRAME_PRIORITY_UPDATE_PUSH_ID. It is undefined otherwise. */ int64_t pri_elem_id; - nghttp3_pri pri; + /* When sending this frame, data should point to the buffer + containing a serialized priority field value and its length is + set to datalen. On reception, pri contains the decoded priority + header value. */ + union { + nghttp3_pri pri; + struct { + uint8_t *data; + size_t datalen; + }; + }; } nghttp3_frame_priority_update; typedef union nghttp3_frame { @@ -212,4 +220,11 @@ void nghttp3_nva_del(nghttp3_nv *nva, const nghttp3_mem *mem); void nghttp3_frame_headers_free(nghttp3_frame_headers *fr, const nghttp3_mem *mem); +/* + * nghttp3_frame_priority_update_free frees memory allocated for |fr|. + * This function should only be called for an outgoing frame. + */ +void nghttp3_frame_priority_update_free(nghttp3_frame_priority_update *fr, + const nghttp3_mem *mem); + #endif /* NGHTTP3_FRAME_H */ diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_http.c b/deps/ngtcp2/nghttp3/lib/nghttp3_http.c index 5e06d8c47658e1..963134f13df946 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_http.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_http.c @@ -31,6 +31,8 @@ #include "nghttp3_stream.h" #include "nghttp3_macro.h" #include "nghttp3_conv.h" +#include "nghttp3_unreachable.h" +#include "sfparse.h" static uint8_t downcase(uint8_t c) { return 'A' <= c && c <= 'Z' ? (uint8_t)(c - 'A' + 'a') : c; @@ -105,722 +107,74 @@ static int check_path_flags(nghttp3_http_state *http) { (http->flags & NGHTTP3_HTTP_FLAG_PATH_ASTERISK))); } -/* Generated by genchartbl.py */ -static const int SF_KEY_CHARS[] = { - 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, - 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, - 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, - 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, - 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, - 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, - 0 /* RS */, 0 /* US */, 0 /* SPC */, 0 /* ! */, 0 /* " */, - 0 /* # */, 0 /* $ */, 0 /* % */, 0 /* & */, 0 /* ' */, - 0 /* ( */, 0 /* ) */, 1 /* * */, 0 /* + */, 0 /* , */, - 1 /* - */, 1 /* . */, 0 /* / */, 1 /* 0 */, 1 /* 1 */, - 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, - 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */, - 0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */, - 0 /* A */, 0 /* B */, 0 /* C */, 0 /* D */, 0 /* E */, - 0 /* F */, 0 /* G */, 0 /* H */, 0 /* I */, 0 /* J */, - 0 /* K */, 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */, - 0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */, 0 /* T */, - 0 /* U */, 0 /* V */, 0 /* W */, 0 /* X */, 0 /* Y */, - 0 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 0 /* ^ */, - 1 /* _ */, 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, - 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */, - 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */, - 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */, - 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, - 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 0 /* | */, - 0 /* } */, 0 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */, - 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, - 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, - 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */, - 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */, - 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, - 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, - 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */, - 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */, - 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, - 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, - 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */, - 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */, - 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, - 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, - 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */, - 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */, - 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, - 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */, - 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */, - 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */, - 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, - 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */, - 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */, - 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */, - 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, - 0 /* 0xff */, -}; - -static nghttp3_ssize sf_parse_key(const uint8_t *begin, const uint8_t *end) { - const uint8_t *p = begin; - - if ((*p < 'a' || 'z' < *p) && *p != '*') { - return -1; - } - - for (; p != end && SF_KEY_CHARS[*p]; ++p) - ; - - return p - begin; -} - -static nghttp3_ssize sf_parse_integer_or_decimal(nghttp3_sf_value *dest, - const uint8_t *begin, - const uint8_t *end) { - const uint8_t *p = begin; - int sign = 1; - int64_t value = 0; - int type = NGHTTP3_SF_VALUE_TYPE_INTEGER; - size_t len = 0; - size_t fpos = 0; - size_t i; - - if (*p == '-') { - if (++p == end) { - return -1; - } - - sign = -1; - } - - if (*p < '0' || '9' < *p) { - return -1; - } - - for (; p != end; ++p) { - switch (*p) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - value *= 10; - value += *p - '0'; - - if (++len > 15) { - return -1; - } - - break; - case '.': - if (type != NGHTTP3_SF_VALUE_TYPE_INTEGER) { - goto fin; - } - - if (len > 12) { - return -1; - } - fpos = len; - type = NGHTTP3_SF_VALUE_TYPE_DECIMAL; - - break; - default: - goto fin; - }; - } - -fin: - switch (type) { - case NGHTTP3_SF_VALUE_TYPE_INTEGER: - if (dest) { - dest->type = (uint8_t)type; - dest->i = value * sign; - } - - return p - begin; - case NGHTTP3_SF_VALUE_TYPE_DECIMAL: - if (fpos == len || len - fpos > 3) { - return -1; - } - - if (dest) { - dest->type = (uint8_t)type; - dest->d = (double)value; - for (i = len - fpos; i > 0; --i) { - dest->d /= (double)10; - } - dest->d *= sign; - } - - return p - begin; - default: - assert(0); - abort(); - } -} - -/* Generated by genchartbl.py */ -static const int SF_DQUOTE_CHARS[] = { - 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, - 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, - 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, - 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, - 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, - 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, - 0 /* RS */, 0 /* US */, 1 /* SPC */, 1 /* ! */, 0 /* " */, - 1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */, - 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* , */, - 1 /* - */, 1 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */, - 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, - 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */, - 1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */, 1 /* @ */, - 1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */, - 1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */, - 1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */, - 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */, - 1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */, - 1 /* Z */, 1 /* [ */, 0 /* \ */, 1 /* ] */, 1 /* ^ */, - 1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, - 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */, - 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */, - 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */, - 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, - 1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */, 1 /* | */, - 1 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */, - 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, - 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, - 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */, - 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */, - 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, - 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, - 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */, - 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */, - 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, - 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, - 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */, - 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */, - 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, - 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, - 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */, - 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */, - 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, - 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */, - 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */, - 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */, - 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, - 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */, - 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */, - 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */, - 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, - 0 /* 0xff */, -}; - -static nghttp3_ssize sf_parse_string(nghttp3_sf_value *dest, - const uint8_t *begin, const uint8_t *end) { - const uint8_t *p = begin; - - if (*p++ != '"') { - return -1; - } - - for (; p != end; ++p) { - switch (*p) { - case '\\': - if (++p == end) { - return -1; - } - - switch (*p) { - case '"': - case '\\': - break; - default: - return -1; - } - - break; - case '"': - if (dest) { - dest->type = NGHTTP3_SF_VALUE_TYPE_STRING; - dest->s.base = begin + 1; - dest->s.len = (size_t)(p - dest->s.base); - } - - ++p; - - return p - begin; - default: - if (!SF_DQUOTE_CHARS[*p]) { - return -1; - } - } - } - - return -1; -} - -/* Generated by genchartbl.py */ -static const int SF_TOKEN_CHARS[] = { - 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, - 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, - 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, - 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, - 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, - 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, - 0 /* RS */, 0 /* US */, 0 /* SPC */, 1 /* ! */, 0 /* " */, - 1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */, - 0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */, 0 /* , */, - 1 /* - */, 1 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */, - 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, - 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 0 /* ; */, - 0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */, - 1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */, - 1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */, - 1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */, - 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */, - 1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */, - 1 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 1 /* ^ */, - 1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, - 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */, - 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */, - 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */, - 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, - 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 1 /* | */, - 0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */, - 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, - 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, - 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */, - 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */, - 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, - 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, - 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */, - 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */, - 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, - 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, - 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */, - 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */, - 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, - 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, - 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */, - 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */, - 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, - 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */, - 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */, - 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */, - 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, - 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */, - 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */, - 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */, - 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, - 0 /* 0xff */, -}; - -static nghttp3_ssize sf_parse_token(nghttp3_sf_value *dest, - const uint8_t *begin, const uint8_t *end) { - const uint8_t *p = begin; - - if ((*p < 'A' || 'Z' < *p) && (*p < 'a' || 'z' < *p) && *p != '*') { - return -1; - } - - for (; p != end && SF_TOKEN_CHARS[*p]; ++p) - ; - - if (dest) { - dest->type = NGHTTP3_SF_VALUE_TYPE_TOKEN; - dest->s.base = begin; - dest->s.len = (size_t)(p - begin); - } - - return p - begin; -} - -/* Generated by genchartbl.py */ -static const int SF_BYTESEQ_CHARS[] = { - 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, - 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, - 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, - 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, - 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, - 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, - 0 /* RS */, 0 /* US */, 0 /* SPC */, 0 /* ! */, 0 /* " */, - 0 /* # */, 0 /* $ */, 0 /* % */, 0 /* & */, 0 /* ' */, - 0 /* ( */, 0 /* ) */, 0 /* * */, 1 /* + */, 0 /* , */, - 0 /* - */, 0 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */, - 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, - 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */, - 0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */, - 1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */, - 1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */, - 1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */, - 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */, - 1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */, - 1 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 0 /* ^ */, - 0 /* _ */, 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, - 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */, - 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */, - 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */, - 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, - 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 0 /* | */, - 0 /* } */, 0 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */, - 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, - 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, - 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */, - 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */, - 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, - 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, - 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */, - 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */, - 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, - 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, - 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */, - 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */, - 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, - 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, - 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */, - 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */, - 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, - 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */, - 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */, - 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */, - 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, - 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */, - 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */, - 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */, - 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, - 0 /* 0xff */, -}; - -static nghttp3_ssize sf_parse_byteseq(nghttp3_sf_value *dest, - const uint8_t *begin, - const uint8_t *end) { - const uint8_t *p = begin; - - if (*p++ != ':') { - return -1; - } - - for (; p != end; ++p) { - switch (*p) { - case ':': - if (dest) { - dest->type = NGHTTP3_SF_VALUE_TYPE_BYTESEQ; - dest->s.base = begin + 1; - dest->s.len = (size_t)(p - dest->s.base); - } - - ++p; - - return p - begin; - default: - if (!SF_BYTESEQ_CHARS[*p]) { - return -1; - } - } - } - - return -1; -} - -static nghttp3_ssize sf_parse_boolean(nghttp3_sf_value *dest, - const uint8_t *begin, - const uint8_t *end) { - const uint8_t *p = begin; - int b; - - if (*p++ != '?') { - return -1; - } - - if (p == end) { - return -1; - } - - switch (*p++) { - case '0': - b = 0; - break; - case '1': - b = 1; - break; - default: - return -1; - } - - if (dest) { - dest->type = NGHTTP3_SF_VALUE_TYPE_BOOLEAN; - dest->b = b; - } - - return p - begin; -} - -static nghttp3_ssize sf_parse_bare_item(nghttp3_sf_value *dest, - const uint8_t *begin, - const uint8_t *end) { - switch (*begin) { - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return sf_parse_integer_or_decimal(dest, begin, end); - case '"': - return sf_parse_string(dest, begin, end); - case '*': - return sf_parse_token(dest, begin, end); - case ':': - return sf_parse_byteseq(dest, begin, end); - case '?': - return sf_parse_boolean(dest, begin, end); +static int is_ws(uint8_t c) { + switch (c) { + case ' ': + case '\t': + return 1; default: - if (('A' <= *begin && *begin <= 'Z') || ('a' <= *begin && *begin <= 'z')) { - return sf_parse_token(dest, begin, end); - } - return -1; - } -} - -#define sf_discard_sp_end_err(BEGIN, END, ERR) \ - for (;; ++(BEGIN)) { \ - if ((BEGIN) == (END)) { \ - return (ERR); \ - } \ - if (*(BEGIN) != ' ') { \ - break; \ - } \ - } - -static nghttp3_ssize sf_parse_params(const uint8_t *begin, const uint8_t *end) { - const uint8_t *p = begin; - nghttp3_ssize slen; - - for (; p != end && *p == ';';) { - ++p; - - sf_discard_sp_end_err(p, end, -1); - - slen = sf_parse_key(p, end); - if (slen < 0) { - return -1; - } - - p += slen; - - if (p == end || *p != '=') { - /* Boolean true */ - } else if (++p == end) { - return -1; - } else { - slen = sf_parse_bare_item(NULL, p, end); - if (slen < 0) { - return -1; - } - - p += slen; - } - } - - return p - begin; -} - -static nghttp3_ssize sf_parse_item(nghttp3_sf_value *dest, const uint8_t *begin, - const uint8_t *end) { - const uint8_t *p = begin; - nghttp3_ssize slen; - - slen = sf_parse_bare_item(dest, p, end); - if (slen < 0) { - return -1; - } - - p += slen; - - slen = sf_parse_params(p, end); - if (slen < 0) { - return -1; - } - - p += slen; - - return p - begin; -} - -nghttp3_ssize nghttp3_sf_parse_item(nghttp3_sf_value *dest, - const uint8_t *begin, const uint8_t *end) { - return sf_parse_item(dest, begin, end); -} - -static nghttp3_ssize sf_parse_inner_list(nghttp3_sf_value *dest, - const uint8_t *begin, - const uint8_t *end) { - const uint8_t *p = begin; - nghttp3_ssize slen; - - if (*p++ != '(') { - return -1; - } - - for (;;) { - sf_discard_sp_end_err(p, end, -1); - - if (*p == ')') { - ++p; - - slen = sf_parse_params(p, end); - if (slen < 0) { - return -1; - } - - p += slen; - - if (dest) { - dest->type = NGHTTP3_SF_VALUE_TYPE_INNER_LIST; - } - - return p - begin; - } - - slen = sf_parse_item(NULL, p, end); - if (slen < 0) { - return -1; - } - - p += slen; - - if (p == end || (*p != ' ' && *p != ')')) { - return -1; - } - } -} - -nghttp3_ssize nghttp3_sf_parse_inner_list(nghttp3_sf_value *dest, - const uint8_t *begin, - const uint8_t *end) { - return sf_parse_inner_list(dest, begin, end); -} - -static nghttp3_ssize sf_parse_item_or_inner_list(nghttp3_sf_value *dest, - const uint8_t *begin, - const uint8_t *end) { - if (*begin == '(') { - return sf_parse_inner_list(dest, begin, end); + return 0; } - - return sf_parse_item(dest, begin, end); } -#define sf_discard_ows(BEGIN, END) \ - for (;; ++(BEGIN)) { \ - if ((BEGIN) == (END)) { \ - goto fin; \ - } \ - if (*(BEGIN) != ' ' && *(BEGIN) != '\t') { \ - break; \ - } \ - } - -#define sf_discard_ows_end_err(BEGIN, END, ERR) \ - for (;; ++(BEGIN)) { \ - if ((BEGIN) == (END)) { \ - return (ERR); \ - } \ - if (*(BEGIN) != ' ' && *(BEGIN) != '\t') { \ - break; \ - } \ - } - int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value, size_t valuelen) { - const uint8_t *p = value, *end = value + valuelen; - nghttp3_ssize slen; - nghttp3_sf_value val; nghttp3_pri pri = *dest; - const uint8_t *key; - size_t keylen; + sf_parser sfp; + sf_vec key; + sf_value val; + int rv; - for (; p != end && *p == ' '; ++p) - ; + sf_parser_init(&sfp, value, valuelen); + + for (;;) { + rv = sf_parser_dict(&sfp, &key, &val); + if (rv != 0) { + if (rv == SF_ERR_EOF) { + break; + } - for (; p != end;) { - slen = sf_parse_key(p, end); - if (slen < 0) { return NGHTTP3_ERR_INVALID_ARGUMENT; } - key = p; - keylen = (size_t)slen; - - p += slen; - - if (p == end || *p != '=') { - /* Boolean true */ - val.type = NGHTTP3_SF_VALUE_TYPE_BOOLEAN; - val.b = 1; + if (key.len != 1) { + continue; + } - slen = sf_parse_params(p, end); - if (slen < 0) { + switch (key.base[0]) { + case 'i': + if (val.type != SF_TYPE_BOOLEAN) { return NGHTTP3_ERR_INVALID_ARGUMENT; } - } else if (++p == end) { - return NGHTTP3_ERR_INVALID_ARGUMENT; - } else { - slen = sf_parse_item_or_inner_list(&val, p, end); - if (slen < 0) { - return NGHTTP3_ERR_INVALID_ARGUMENT; - } - } - - p += slen; - - if (keylen == 1) { - switch (key[0]) { - case 'i': - if (val.type != NGHTTP3_SF_VALUE_TYPE_BOOLEAN) { - return NGHTTP3_ERR_INVALID_ARGUMENT; - } - - pri.inc = val.b; - - break; - case 'u': - if (val.type != NGHTTP3_SF_VALUE_TYPE_INTEGER || - val.i < NGHTTP3_URGENCY_HIGH || NGHTTP3_URGENCY_LOW < val.i) { - return NGHTTP3_ERR_INVALID_ARGUMENT; - } - pri.urgency = (uint32_t)val.i; + pri.inc = (uint8_t)val.boolean; - break; + break; + case 'u': + if (val.type != SF_TYPE_INTEGER || val.integer < NGHTTP3_URGENCY_HIGH || + NGHTTP3_URGENCY_LOW < val.integer) { + return NGHTTP3_ERR_INVALID_ARGUMENT; } - } - sf_discard_ows(p, end); + pri.urgency = (uint32_t)val.integer; - if (*p++ != ',') { - return NGHTTP3_ERR_INVALID_ARGUMENT; + break; } - - sf_discard_ows_end_err(p, end, NGHTTP3_ERR_INVALID_ARGUMENT); } -fin: *dest = pri; return 0; } +int nghttp3_pri_parse_priority_versioned(int pri_version, nghttp3_pri *dest, + const uint8_t *value, + size_t valuelen) { + (void)pri_version; + + return nghttp3_http_parse_priority(dest, value, valuelen); +} + static int http_request_on_header(nghttp3_http_state *http, nghttp3_qpack_nv *nv, int trailers, int connect_protocol) { @@ -931,11 +285,10 @@ static int http_request_on_header(nghttp3_http_state *http, break; case NGHTTP3_QPACK_TOKEN_PRIORITY: if (!trailers && !(http->flags & NGHTTP3_HTTP_FLAG_BAD_PRIORITY)) { - pri.urgency = nghttp3_pri_uint8_urgency(http->pri); - pri.inc = nghttp3_pri_uint8_inc(http->pri); + pri = http->pri; if (nghttp3_http_parse_priority(&pri, nv->value->base, nv->value->len) == 0) { - http->pri = nghttp3_pri_to_uint8(&pri); + http->pri = pri; http->flags |= NGHTTP3_HTTP_FLAG_PRIORITY; } else { http->flags &= ~NGHTTP3_HTTP_FLAG_PRIORITY; @@ -1637,10 +990,9 @@ int nghttp3_check_header_value(const uint8_t *value, size_t len) { case 0: return 1; case 1: - return !(*value == ' ' || *value == '\t'); + return !is_ws(*value); default: - if (*value == ' ' || *value == '\t' || *(value + len - 1) == ' ' || - *(value + len - 1) == '\t') { + if (is_ws(*value) || is_ws(*(value + len - 1))) { return 0; } } @@ -1652,3 +1004,7 @@ int nghttp3_check_header_value(const uint8_t *value, size_t len) { } return 1; } + +int nghttp3_pri_eq(const nghttp3_pri *a, const nghttp3_pri *b) { + return a->urgency == b->urgency && a->inc == b->inc; +} diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_http.h b/deps/ngtcp2/nghttp3/lib/nghttp3_http.h index 1617348ad14d78..575d9c267e1b68 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_http.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_http.h @@ -150,53 +150,24 @@ int nghttp3_http_on_data_chunk(nghttp3_stream *stream, size_t n); void nghttp3_http_record_request_method(nghttp3_stream *stream, const nghttp3_nv *nva, size_t nvlen); -/* - * RFC 8941 Structured Field Values. - */ -typedef enum nghttp3_sf_value_type { - NGHTTP3_SF_VALUE_TYPE_BOOLEAN, - NGHTTP3_SF_VALUE_TYPE_INTEGER, - NGHTTP3_SF_VALUE_TYPE_DECIMAL, - NGHTTP3_SF_VALUE_TYPE_STRING, - NGHTTP3_SF_VALUE_TYPE_TOKEN, - NGHTTP3_SF_VALUE_TYPE_BYTESEQ, - NGHTTP3_SF_VALUE_TYPE_INNER_LIST, -} nghttp3_sf_value_type; - -/* - * nghttp3_sf_value stores Structured Field Values item. For Inner - * List, only type is set to NGHTTP3_SF_VALUE_TYPE_INNER_LIST. - */ -typedef struct nghttp3_sf_value { - uint8_t type; - union { - int b; - int64_t i; - double d; - struct { - const uint8_t *base; - size_t len; - } s; - }; -} nghttp3_sf_value; - -/* - * nghttp3_sf_parse_item parses the input sequence [|begin|, |end|) - * and stores the parsed an Item in |dest|. It returns the number of - * bytes consumed if it succeeds, or -1. This function is declared - * here for unit tests. +/** + * @function + * + * `nghttp3_http_parse_priority` parses priority HTTP header field + * stored in the buffer pointed by |value| of length |len|. If it + * successfully processed header field value, it stores the result + * into |*dest|. This function just overwrites what it sees in the + * header field value and does not initialize any field in |*dest|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` + * The function could not parse the provided value. */ -nghttp3_ssize nghttp3_sf_parse_item(nghttp3_sf_value *dest, - const uint8_t *begin, const uint8_t *end); +int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value, + size_t len); -/* - * nghttp3_sf_parse_inner_list parses the input sequence [|begin|, |end|) - * and stores the parsed an Inner List in |dest|. It returns the number of - * bytes consumed if it succeeds, or -1. This function is declared - * here for unit tests. - */ -nghttp3_ssize nghttp3_sf_parse_inner_list(nghttp3_sf_value *dest, - const uint8_t *begin, - const uint8_t *end); +int nghttp3_pri_eq(const nghttp3_pri *a, const nghttp3_pri *b); #endif /* NGHTTP3_HTTP_H */ diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_ksl.c b/deps/ngtcp2/nghttp3/lib/nghttp3_ksl.c index adea677abe1f1c..d7420a5d8a1e5d 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_ksl.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_ksl.c @@ -36,6 +36,8 @@ static nghttp3_ksl_blk null_blk = {{{NULL, NULL, 0, 0, {0}}}}; +nghttp3_objalloc_def(ksl_blk, nghttp3_ksl_blk, oplent); + static size_t ksl_nodelen(size_t keylen) { return (sizeof(nghttp3_ksl_node) + keylen - sizeof(uint64_t) + 0xfu) & ~(uintptr_t)0xfu; @@ -722,6 +724,24 @@ void nghttp3_ksl_update_key(nghttp3_ksl *ksl, const nghttp3_ksl_key *old_key, } } +size_t nghttp3_ksl_len(nghttp3_ksl *ksl) { return ksl->n; } + +void nghttp3_ksl_clear(nghttp3_ksl *ksl) { + if (!ksl->head) { + return; + } + +#ifdef NOMEMPOOL + ksl_free_blk(ksl, ksl->head); +#endif /* NOMEMPOOL */ + + ksl->front = ksl->back = ksl->head = NULL; + ksl->n = 0; + + nghttp3_objalloc_clear(&ksl->blkalloc); +} + +#ifndef WIN32 static void ksl_print(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t level) { size_t i; nghttp3_ksl_node *node; @@ -742,23 +762,6 @@ static void ksl_print(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t level) { } } -size_t nghttp3_ksl_len(nghttp3_ksl *ksl) { return ksl->n; } - -void nghttp3_ksl_clear(nghttp3_ksl *ksl) { - if (!ksl->head) { - return; - } - -#ifdef NOMEMPOOL - ksl_free_blk(ksl, ksl->head); -#endif /* NOMEMPOOL */ - - ksl->front = ksl->back = ksl->head = NULL; - ksl->n = 0; - - nghttp3_objalloc_clear(&ksl->blkalloc); -} - void nghttp3_ksl_print(nghttp3_ksl *ksl) { if (!ksl->head) { return; @@ -766,6 +769,7 @@ void nghttp3_ksl_print(nghttp3_ksl *ksl) { ksl_print(ksl, ksl->head, 0); } +#endif /* !WIN32 */ nghttp3_ksl_it nghttp3_ksl_begin(const nghttp3_ksl *ksl) { nghttp3_ksl_it it; diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_ksl.h b/deps/ngtcp2/nghttp3/lib/nghttp3_ksl.h index 0bc10e846fe418..d513bdd672c750 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_ksl.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_ksl.h @@ -108,7 +108,7 @@ struct nghttp3_ksl_blk { }; }; -nghttp3_objalloc_def(ksl_blk, nghttp3_ksl_blk, oplent); +nghttp3_objalloc_decl(ksl_blk, nghttp3_ksl_blk, oplent); /* * nghttp3_ksl_compar is a function type which returns nonzero if key @@ -265,12 +265,14 @@ void nghttp3_ksl_clear(nghttp3_ksl *ksl); #define nghttp3_ksl_nth_node(KSL, BLK, N) \ ((nghttp3_ksl_node *)(void *)((BLK)->nodes + (KSL)->nodelen * (N))) +#ifndef WIN32 /* * nghttp3_ksl_print prints its internal state in stderr. It assumes * that the key is of type int64_t. This function should be used for * the debugging purpose only. */ void nghttp3_ksl_print(nghttp3_ksl *ksl); +#endif /* !WIN32 */ /* * nghttp3_ksl_it_init initializes |it|. diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_map.c b/deps/ngtcp2/nghttp3/lib/nghttp3_map.c index fcfc31ae41e8e0..b93fdfd3d488f5 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_map.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_map.c @@ -127,6 +127,7 @@ static void map_bucket_set_data(nghttp3_map_bucket *bkt, uint32_t hash, bkt->data = data; } +#ifndef WIN32 void nghttp3_map_print_distance(nghttp3_map *map) { uint32_t i; size_t idx; @@ -146,6 +147,7 @@ void nghttp3_map_print_distance(nghttp3_map *map) { distance(map->tablelen, map->tablelenbits, bkt, idx)); } } +#endif /* !WIN32 */ static int insert(nghttp3_map_bucket *table, uint32_t tablelen, uint32_t tablelenbits, uint32_t hash, diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_map.h b/deps/ngtcp2/nghttp3/lib/nghttp3_map.h index 79dff0286bc3cc..7683cfeef3f33e 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_map.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_map.h @@ -132,6 +132,8 @@ size_t nghttp3_map_size(nghttp3_map *map); int nghttp3_map_each(nghttp3_map *map, int (*func)(void *data, void *ptr), void *ptr); +#ifndef WIN32 void nghttp3_map_print_distance(nghttp3_map *map); +#endif /* !WIN32 */ #endif /* NGHTTP3_MAP_H */ diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_objalloc.h b/deps/ngtcp2/nghttp3/lib/nghttp3_objalloc.h index da39447a872b02..02dff285f24060 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_objalloc.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_objalloc.h @@ -66,15 +66,25 @@ void nghttp3_objalloc_free(nghttp3_objalloc *objalloc); void nghttp3_objalloc_clear(nghttp3_objalloc *objalloc); #ifndef NOMEMPOOL -# define nghttp3_objalloc_def(NAME, TYPE, OPLENTFIELD) \ +# define nghttp3_objalloc_decl(NAME, TYPE, OPLENTFIELD) \ inline static void nghttp3_objalloc_##NAME##_init( \ nghttp3_objalloc *objalloc, size_t nmemb, const nghttp3_mem *mem) { \ nghttp3_objalloc_init( \ objalloc, ((sizeof(TYPE) + 0xfu) & ~(uintptr_t)0xfu) * nmemb, mem); \ } \ \ - inline static TYPE *nghttp3_objalloc_##NAME##_get( \ - nghttp3_objalloc *objalloc) { \ + TYPE *nghttp3_objalloc_##NAME##_get(nghttp3_objalloc *objalloc); \ + \ + TYPE *nghttp3_objalloc_##NAME##_len_get(nghttp3_objalloc *objalloc, \ + size_t len); \ + \ + inline static void nghttp3_objalloc_##NAME##_release( \ + nghttp3_objalloc *objalloc, TYPE *obj) { \ + nghttp3_opl_push(&objalloc->opl, &obj->OPLENTFIELD); \ + } + +# define nghttp3_objalloc_def(NAME, TYPE, OPLENTFIELD) \ + TYPE *nghttp3_objalloc_##NAME##_get(nghttp3_objalloc *objalloc) { \ nghttp3_opl_entry *oplent = nghttp3_opl_pop(&objalloc->opl); \ TYPE *obj; \ int rv; \ @@ -92,8 +102,8 @@ void nghttp3_objalloc_clear(nghttp3_objalloc *objalloc); return nghttp3_struct_of(oplent, TYPE, OPLENTFIELD); \ } \ \ - inline static TYPE *nghttp3_objalloc_##NAME##_len_get( \ - nghttp3_objalloc *objalloc, size_t len) { \ + TYPE *nghttp3_objalloc_##NAME##_len_get(nghttp3_objalloc *objalloc, \ + size_t len) { \ nghttp3_opl_entry *oplent = nghttp3_opl_pop(&objalloc->opl); \ TYPE *obj; \ int rv; \ @@ -108,14 +118,9 @@ void nghttp3_objalloc_clear(nghttp3_objalloc *objalloc); } \ \ return nghttp3_struct_of(oplent, TYPE, OPLENTFIELD); \ - } \ - \ - inline static void nghttp3_objalloc_##NAME##_release( \ - nghttp3_objalloc *objalloc, TYPE *obj) { \ - nghttp3_opl_push(&objalloc->opl, &obj->OPLENTFIELD); \ } #else /* NOMEMPOOL */ -# define nghttp3_objalloc_def(NAME, TYPE, OPLENTFIELD) \ +# define nghttp3_objalloc_decl(NAME, TYPE, OPLENTFIELD) \ inline static void nghttp3_objalloc_##NAME##_init( \ nghttp3_objalloc *objalloc, size_t nmemb, const nghttp3_mem *mem) { \ nghttp3_objalloc_init( \ @@ -136,6 +141,8 @@ void nghttp3_objalloc_clear(nghttp3_objalloc *objalloc); nghttp3_objalloc *objalloc, TYPE *obj) { \ nghttp3_mem_free(objalloc->balloc.mem, obj); \ } + +# define nghttp3_objalloc_def(NAME, TYPE, OPLENTFIELD) #endif /* NOMEMPOOL */ #endif /* NGHTTP3_OBJALLOC_H */ diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_qpack.c b/deps/ngtcp2/nghttp3/lib/nghttp3_qpack.c index ddb3dd6d84bf8a..428c06a82c6bfb 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_qpack.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_qpack.c @@ -32,6 +32,7 @@ #include "nghttp3_str.h" #include "nghttp3_macro.h" #include "nghttp3_debug.h" +#include "nghttp3_unreachable.h" /* NGHTTP3_QPACK_MAX_QPACK_STREAMS is the maximum number of concurrent nghttp3_qpack_stream object to handle a client which never cancel @@ -1099,7 +1100,7 @@ static void qpack_encoder_remove_stream(nghttp3_qpack_encoder *encoder, /* * reserve_buf_internal ensures that |buf| contains at least * |extra_size| of free space. In other words, if this function - * succeeds, nghttp2_buf_left(buf) >= extra_size holds. |min_size| is + * succeeds, nghttp3_buf_left(buf) >= extra_size holds. |min_size| is * the minimum size of buffer. The allocated buffer has at least * |min_size| bytes. * @@ -1281,6 +1282,19 @@ int nghttp3_qpack_encoder_stream_is_blocked(nghttp3_qpack_encoder *encoder, return stream && encoder->krcnt < nghttp3_qpack_stream_get_max_cnt(stream); } +static uint32_t qpack_hash_name(const nghttp3_nv *nv) { + /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */ + uint32_t h = 2166136261u; + size_t i; + + for (i = 0; i < nv->namelen; ++i) { + h ^= nv->name[i]; + h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24); + } + + return h; +} + /* * qpack_encoder_decide_indexing_mode determines and returns indexing * mode for header field |nv|. |token| is a token of header field @@ -1310,6 +1324,10 @@ qpack_encoder_decide_indexing_mode(nghttp3_qpack_encoder *encoder, case NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH: case NGHTTP3_QPACK_TOKEN_LOCATION: case NGHTTP3_QPACK_TOKEN_SET_COOKIE: + if (nv->flags & NGHTTP3_NV_FLAG_TRY_INDEX) { + break; + } + return NGHTTP3_QPACK_INDEXING_MODE_LITERAL; case NGHTTP3_QPACK_TOKEN_HOST: case NGHTTP3_QPACK_TOKEN_TE: @@ -1317,6 +1335,10 @@ qpack_encoder_decide_indexing_mode(nghttp3_qpack_encoder *encoder, case NGHTTP3_QPACK_TOKEN_PRIORITY: break; default: + if (nv->flags & NGHTTP3_NV_FLAG_TRY_INDEX) { + break; + } + if (token >= 1000) { return NGHTTP3_QPACK_INDEXING_MODE_LITERAL; } @@ -1428,6 +1450,17 @@ int nghttp3_qpack_encoder_encode_nv(nghttp3_qpack_encoder *encoder, token = qpack_lookup_token(nv->name, nv->namelen); static_entry = token != -1 && (size_t)token < nghttp3_arraylen(token_stable); + + indexing_mode = qpack_encoder_decide_indexing_mode(encoder, nv, token); + + if (static_entry) { + sres = nghttp3_qpack_lookup_stable(nv, token, indexing_mode); + if (sres.index != -1 && sres.name_value_match) { + return nghttp3_qpack_encoder_write_static_indexed(encoder, rbuf, + (size_t)sres.index); + } + } + if (static_entry) { hash = token_stable[token].hash; } else { @@ -1444,21 +1477,12 @@ int nghttp3_qpack_encoder_encode_nv(nghttp3_qpack_encoder *encoder, case NGHTTP3_QPACK_TOKEN_PRIORITY: hash = 2498028297u; break; + default: + hash = qpack_hash_name(nv); } } - indexing_mode = qpack_encoder_decide_indexing_mode(encoder, nv, token); - - if (static_entry) { - sres = nghttp3_qpack_lookup_stable(nv, token, indexing_mode); - if (sres.index != -1 && sres.name_value_match) { - return nghttp3_qpack_encoder_write_static_indexed(encoder, rbuf, - (size_t)sres.index); - } - } - - if (hash && - nghttp3_map_size(&encoder->streams) < NGHTTP3_QPACK_MAX_QPACK_STREAMS) { + if (nghttp3_map_size(&encoder->streams) < NGHTTP3_QPACK_MAX_QPACK_STREAMS) { dres = nghttp3_qpack_encoder_lookup_dtable(encoder, nv, token, hash, indexing_mode, encoder->krcnt, allow_blocking); @@ -2552,18 +2576,14 @@ nghttp3_ssize nghttp3_qpack_encoder_read_decoder(nghttp3_qpack_encoder *encoder, (int64_t)encoder->rstate.left); break; default: - /* unreachable */ - assert(0); - break; + nghttp3_unreachable(); } encoder->state = NGHTTP3_QPACK_DS_STATE_OPCODE; nghttp3_qpack_read_state_reset(&encoder->rstate); break; default: - /* unreachable */ - assert(0); - break; + nghttp3_unreachable(); } } @@ -2838,24 +2858,26 @@ nghttp3_ssize nghttp3_qpack_decoder_read_encoder(nghttp3_qpack_decoder *decoder, goto fail; } - if (decoder->opcode == NGHTTP3_QPACK_ES_OPCODE_DUPLICATE) { + switch (decoder->opcode) { + case NGHTTP3_QPACK_ES_OPCODE_DUPLICATE: rv = nghttp3_qpack_decoder_dtable_duplicate_add(decoder); if (rv != 0) { goto fail; } + decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE; nghttp3_qpack_read_state_reset(&decoder->rstate); - break; - } - if (decoder->opcode == NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED) { + break; + case NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED: decoder->rstate.prefix = 7; decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN; + break; + default: + nghttp3_unreachable(); } - /* Unreachable */ - assert(0); break; case NGHTTP3_QPACK_ES_STATE_CHECK_NAME_HUFFMAN: qpack_read_state_check_huffman(&decoder->rstate, *p); @@ -3010,9 +3032,7 @@ nghttp3_ssize nghttp3_qpack_decoder_read_encoder(nghttp3_qpack_decoder *decoder, rv = nghttp3_qpack_decoder_dtable_literal_add(decoder); break; default: - /* Unreachable */ - assert(0); - abort(); + nghttp3_unreachable(); } if (rv != 0) { goto fail; @@ -3045,9 +3065,7 @@ nghttp3_ssize nghttp3_qpack_decoder_read_encoder(nghttp3_qpack_decoder *decoder, rv = nghttp3_qpack_decoder_dtable_literal_add(decoder); break; default: - /* Unreachable */ - assert(0); - abort(); + nghttp3_unreachable(); } if (rv != 0) { goto fail; @@ -3430,8 +3448,7 @@ nghttp3_qpack_decoder_read_request(nghttp3_qpack_decoder *decoder, sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN; break; default: - /* Unreachable */ - assert(0); + nghttp3_unreachable(); } break; case NGHTTP3_QPACK_RS_STATE_CHECK_NAME_HUFFMAN: @@ -3589,8 +3606,7 @@ nghttp3_qpack_decoder_read_request(nghttp3_qpack_decoder *decoder, nghttp3_qpack_decoder_emit_literal(decoder, sctx, nv); break; default: - /* Unreachable */ - assert(0); + nghttp3_unreachable(); } *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT; @@ -3627,8 +3643,7 @@ nghttp3_qpack_decoder_read_request(nghttp3_qpack_decoder *decoder, nghttp3_qpack_decoder_emit_literal(decoder, sctx, nv); break; default: - /* Unreachable */ - assert(0); + nghttp3_unreachable(); } *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT; diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_ringbuf.c b/deps/ngtcp2/nghttp3/lib/nghttp3_ringbuf.c index 5e7775f1a5a597..61a7d06cad306f 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_ringbuf.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_ringbuf.c @@ -33,7 +33,8 @@ #include "nghttp3_macro.h" -#if defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || defined(_M_ARM64)) +#if defined(_MSC_VER) && !defined(__clang__) && \ + (defined(_M_ARM) || defined(_M_ARM64)) unsigned int __popcnt(unsigned int x) { unsigned int c = 0; for (; x; ++c) { diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_stream.c b/deps/ngtcp2/nghttp3/lib/nghttp3_stream.c index e655a7ec01d10b..6188a141dd123b 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_stream.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_stream.c @@ -35,6 +35,7 @@ #include "nghttp3_str.h" #include "nghttp3_http.h" #include "nghttp3_vec.h" +#include "nghttp3_unreachable.h" /* NGHTTP3_STREAM_MAX_COPY_THRES is the maximum size of buffer which makes a copy to outq. */ @@ -43,13 +44,14 @@ /* NGHTTP3_MIN_RBLEN is the minimum length of nghttp3_ringbuf */ #define NGHTTP3_MIN_RBLEN 4 +nghttp3_objalloc_def(stream, nghttp3_stream, oplent); + int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id, - uint64_t seq, const nghttp3_stream_callbacks *callbacks, + const nghttp3_stream_callbacks *callbacks, nghttp3_objalloc *out_chunk_objalloc, nghttp3_objalloc *stream_objalloc, const nghttp3_mem *mem) { nghttp3_stream *stream = nghttp3_objalloc_stream_get(stream_objalloc); - nghttp3_node_id nid; if (stream == NULL) { return NGHTTP3_ERR_NOMEM; @@ -60,10 +62,7 @@ int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id, stream->out_chunk_objalloc = out_chunk_objalloc; stream->stream_objalloc = stream_objalloc; - nghttp3_tnode_init( - &stream->node, - nghttp3_node_id_init(&nid, NGHTTP3_NODE_ID_TYPE_STREAM, stream_id), seq, - NGHTTP3_DEFAULT_URGENCY); + nghttp3_tnode_init(&stream->node, stream_id); nghttp3_ringbuf_init(&stream->frq, 0, sizeof(nghttp3_frame_entry), mem); nghttp3_ringbuf_init(&stream->chunks, 0, sizeof(nghttp3_buf), mem); @@ -77,7 +76,7 @@ int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id, stream->tx.offset = 0; stream->rx.http.status_code = -1; stream->rx.http.content_length = -1; - stream->rx.http.pri = NGHTTP3_DEFAULT_URGENCY; + stream->rx.http.pri.urgency = NGHTTP3_DEFAULT_URGENCY; stream->error_code = NGHTTP3_H3_NO_ERROR; if (callbacks) { @@ -146,6 +145,9 @@ static void delete_frq(nghttp3_ringbuf *frq, const nghttp3_mem *mem) { case NGHTTP3_FRAME_HEADERS: nghttp3_frame_headers_free(&frent->fr.headers, mem); break; + case NGHTTP3_FRAME_PRIORITY_UPDATE: + nghttp3_frame_priority_update_free(&frent->fr.priority_update, mem); + break; default: break; } @@ -188,7 +190,7 @@ nghttp3_ssize nghttp3_read_varint(nghttp3_varint_read_state *rvint, if (rvint->left == 0) { assert(rvint->acc == 0); - rvint->left = nghttp3_get_varint_len(src); + rvint->left = nghttp3_get_varintlen(src); if (rvint->left <= srclen) { rvint->acc = nghttp3_get_varint(&nread, src); rvint->left = 0; @@ -248,7 +250,7 @@ int nghttp3_stream_fill_outq(nghttp3_stream *stream) { int data_eof; int rv; - for (; nghttp3_ringbuf_len(frq) && !nghttp3_stream_outq_is_full(stream) && + for (; nghttp3_ringbuf_len(frq) && stream->unsent_bytes < NGHTTP3_MIN_UNSENT_BYTES;) { frent = nghttp3_ringbuf_get(frq, 0); @@ -289,6 +291,8 @@ int nghttp3_stream_fill_outq(nghttp3_stream *stream) { if (rv != 0) { return rv; } + nghttp3_frame_priority_update_free(&frent->fr.priority_update, + stream->mem); break; default: /* TODO Not implemented */ @@ -308,7 +312,7 @@ static void typed_buf_shared_init(nghttp3_typed_buf *tbuf, } int nghttp3_stream_write_stream_type(nghttp3_stream *stream) { - size_t len = nghttp3_put_varint_len((int64_t)stream->type); + size_t len = nghttp3_put_varintlen((int64_t)stream->type); nghttp3_buf *chunk; nghttp3_typed_buf tbuf; int rv; @@ -351,10 +355,18 @@ int nghttp3_stream_write_settings(nghttp3_stream *stream, iv[2].id = NGHTTP3_SETTINGS_ID_QPACK_BLOCKED_STREAMS; iv[2].value = local_settings->qpack_blocked_streams; + if (local_settings->h3_datagram) { + iv[fr.settings.niv].id = NGHTTP3_SETTINGS_ID_H3_DATAGRAM; + iv[fr.settings.niv].value = 1; + + ++fr.settings.niv; + } + if (local_settings->enable_connect_protocol) { + iv[fr.settings.niv].id = NGHTTP3_SETTINGS_ID_ENABLE_CONNECT_PROTOCOL; + iv[fr.settings.niv].value = 1; + ++fr.settings.niv; - iv[3].id = NGHTTP3_SETTINGS_ID_ENABLE_CONNECT_PROTOCOL; - iv[3].value = 1; } len = nghttp3_frame_write_settings_len(&fr.settings.hd.length, &fr.settings); @@ -453,8 +465,8 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream, nghttp3_buf_wrap_init(&pbuf, raw_pbuf, sizeof(raw_pbuf)); - rv = nghttp3_qpack_encoder_encode(qenc, &pbuf, rbuf, ebuf, - stream->node.nid.id, nva, nvlen); + rv = nghttp3_qpack_encoder_encode(qenc, &pbuf, rbuf, ebuf, stream->node.id, + nva, nvlen); if (rv != 0) { goto fail; } @@ -574,8 +586,8 @@ int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof, *peof = 0; - sveccnt = read_data(conn, stream->node.nid.id, vec, nghttp3_arraylen(vec), - &flags, conn->user_data, stream->user_data); + sveccnt = read_data(conn, stream->node.id, vec, nghttp3_arraylen(vec), &flags, + conn->user_data, stream->user_data); if (sveccnt < 0) { if (sveccnt == NGHTTP3_ERR_WOULDBLOCK) { stream->flags |= NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED; @@ -691,11 +703,6 @@ int nghttp3_stream_write_qpack_decoder_stream(nghttp3_stream *stream) { return nghttp3_stream_outq_add(stream, &tbuf); } -int nghttp3_stream_outq_is_full(nghttp3_stream *stream) { - /* TODO Verify that the limit is reasonable. */ - return nghttp3_ringbuf_len(&stream->outq) >= 1024; -} - int nghttp3_stream_outq_add(nghttp3_stream *stream, const nghttp3_typed_buf *tbuf) { nghttp3_ringbuf *outq = &stream->outq; @@ -809,11 +816,11 @@ int nghttp3_stream_require_schedule(nghttp3_stream *stream) { !(stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED)); } -nghttp3_ssize nghttp3_stream_writev(nghttp3_stream *stream, int *pfin, - nghttp3_vec *vec, size_t veccnt) { +size_t nghttp3_stream_writev(nghttp3_stream *stream, int *pfin, + nghttp3_vec *vec, size_t veccnt) { nghttp3_ringbuf *outq = &stream->outq; size_t len = nghttp3_ringbuf_len(outq); - size_t i; + size_t i = stream->outq_idx; uint64_t offset = stream->outq_offset; size_t buflen; nghttp3_vec *vbegin = vec, *vend = vec + veccnt; @@ -821,25 +828,27 @@ nghttp3_ssize nghttp3_stream_writev(nghttp3_stream *stream, int *pfin, assert(veccnt > 0); - for (i = stream->outq_idx; i < len; ++i) { + if (i < len) { tbuf = nghttp3_ringbuf_get(outq, i); buflen = nghttp3_buf_len(&tbuf->buf); - if (offset >= buflen) { - offset -= buflen; - continue; + + if (offset < buflen) { + vec->base = tbuf->buf.pos + offset; + vec->len = (size_t)(buflen - offset); + ++vec; + } else { + /* This is the only case that satisfies offset >= buflen */ + assert(0 == offset); + assert(0 == buflen); } - vec->base = tbuf->buf.pos + offset; - vec->len = (size_t)(buflen - offset); - ++vec; ++i; - break; - } - for (; i < len && vec != vend; ++i, ++vec) { - tbuf = nghttp3_ringbuf_get(outq, i); - vec->base = tbuf->buf.pos; - vec->len = nghttp3_buf_len(&tbuf->buf); + for (; i < len && vec != vend; ++i, ++vec) { + tbuf = nghttp3_ringbuf_get(outq, i); + vec->base = tbuf->buf.pos; + vec->len = nghttp3_buf_len(&tbuf->buf); + } } /* TODO Rework this if we have finished implementing HTTP @@ -847,10 +856,10 @@ nghttp3_ssize nghttp3_stream_writev(nghttp3_stream *stream, int *pfin, *pfin = nghttp3_ringbuf_len(&stream->frq) == 0 && i == len && (stream->flags & NGHTTP3_STREAM_FLAG_WRITE_END_STREAM); - return vec - vbegin; + return (size_t)(vec - vbegin); } -int nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n) { +void nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n) { nghttp3_ringbuf *outq = &stream->outq; size_t i; size_t len = nghttp3_ringbuf_len(outq); @@ -874,8 +883,6 @@ int nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n) { stream->unsent_bytes -= n; stream->outq_idx = i; stream->outq_offset = offset; - - return 0; } int nghttp3_stream_outq_write_done(nghttp3_stream *stream) { @@ -885,8 +892,8 @@ int nghttp3_stream_outq_write_done(nghttp3_stream *stream) { return len == 0 || stream->outq_idx >= len; } -static int stream_pop_outq_entry(nghttp3_stream *stream, - nghttp3_typed_buf *tbuf) { +static void stream_pop_outq_entry(nghttp3_stream *stream, + nghttp3_typed_buf *tbuf) { nghttp3_ringbuf *chunks = &stream->chunks; nghttp3_buf *chunk; @@ -915,13 +922,10 @@ static int stream_pop_outq_entry(nghttp3_stream *stream, } break; default: - assert(0); - abort(); + nghttp3_unreachable(); }; nghttp3_ringbuf_pop_front(&stream->outq); - - return 0; } int nghttp3_stream_add_ack_offset(nghttp3_stream *stream, uint64_t n) { @@ -940,7 +944,7 @@ int nghttp3_stream_add_ack_offset(nghttp3_stream *stream, uint64_t n) { if (tbuf->type == NGHTTP3_BUF_TYPE_ALIEN) { nack = nghttp3_min(offset, (uint64_t)buflen) - stream->ack_done; if (stream->callbacks.acked_data) { - rv = stream->callbacks.acked_data(stream, stream->node.nid.id, nack, + rv = stream->callbacks.acked_data(stream, stream->node.id, nack, stream->user_data); if (rv != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -950,10 +954,7 @@ int nghttp3_stream_add_ack_offset(nghttp3_stream *stream, uint64_t n) { } if (offset >= buflen) { - rv = stream_pop_outq_entry(stream, tbuf); - if (rv != 0) { - return rv; - } + stream_pop_outq_entry(stream, tbuf); offset -= buflen; ++npopped; @@ -1221,8 +1222,7 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream, case NGHTTP3_HTTP_STATE_RESP_END: return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING; default: - assert(0); - abort(); + nghttp3_unreachable(); } } diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_stream.h b/deps/ngtcp2/nghttp3/lib/nghttp3_stream.h index 06292738a17e93..03a57697b232b3 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_stream.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_stream.h @@ -50,13 +50,13 @@ #define NGHTTP3_STREAM_MIN_WRITELEN 800 /* nghttp3_stream_type is unidirectional stream type. */ -typedef enum nghttp3_stream_type { - NGHTTP3_STREAM_TYPE_CONTROL = 0x00, - NGHTTP3_STREAM_TYPE_PUSH = 0x01, - NGHTTP3_STREAM_TYPE_QPACK_ENCODER = 0x02, - NGHTTP3_STREAM_TYPE_QPACK_DECODER = 0x03, - NGHTTP3_STREAM_TYPE_UNKNOWN = UINT64_MAX, -} nghttp3_stream_type; +typedef uint64_t nghttp3_stream_type; + +#define NGHTTP3_STREAM_TYPE_CONTROL 0x00 +#define NGHTTP3_STREAM_TYPE_PUSH 0x01 +#define NGHTTP3_STREAM_TYPE_QPACK_ENCODER 0x02 +#define NGHTTP3_STREAM_TYPE_QPACK_DECODER 0x03 +#define NGHTTP3_STREAM_TYPE_UNKNOWN UINT64_MAX typedef enum nghttp3_ctrl_stream_state { NGHTTP3_CTRL_STREAM_STATE_FRAME_TYPE, @@ -195,9 +195,8 @@ typedef struct nghttp3_http_state { /* recv_content_length is the number of body bytes received so far. */ int64_t recv_content_length; + nghttp3_pri pri; uint32_t flags; - /* pri is a stream priority produced by nghttp3_pri_to_uint8. */ - uint8_t pri; } nghttp3_http_state; struct nghttp3_stream { @@ -257,7 +256,7 @@ struct nghttp3_stream { }; }; -nghttp3_objalloc_def(stream, nghttp3_stream, oplent); +nghttp3_objalloc_decl(stream, nghttp3_stream, oplent); typedef struct nghttp3_frame_entry { nghttp3_frame fr; @@ -272,7 +271,7 @@ typedef struct nghttp3_frame_entry { } nghttp3_frame_entry; int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id, - uint64_t seq, const nghttp3_stream_callbacks *callbacks, + const nghttp3_stream_callbacks *callbacks, nghttp3_objalloc *out_chunk_objalloc, nghttp3_objalloc *stream_objalloc, const nghttp3_mem *mem); @@ -293,13 +292,11 @@ int nghttp3_stream_fill_outq(nghttp3_stream *stream); int nghttp3_stream_write_stream_type(nghttp3_stream *stream); -nghttp3_ssize nghttp3_stream_writev(nghttp3_stream *stream, int *pfin, - nghttp3_vec *vec, size_t veccnt); +size_t nghttp3_stream_writev(nghttp3_stream *stream, int *pfin, + nghttp3_vec *vec, size_t veccnt); int nghttp3_stream_write_qpack_decoder_stream(nghttp3_stream *stream); -int nghttp3_stream_outq_is_full(nghttp3_stream *stream); - int nghttp3_stream_outq_add(nghttp3_stream *stream, const nghttp3_typed_buf *tbuf); @@ -331,7 +328,7 @@ nghttp3_buf *nghttp3_stream_get_chunk(nghttp3_stream *stream); int nghttp3_stream_is_blocked(nghttp3_stream *stream); -int nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n); +void nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n); /* * nghttp3_stream_outq_write_done returns nonzero if all contents in diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_tnode.c b/deps/ngtcp2/nghttp3/lib/nghttp3_tnode.c index 36e738c3469aca..d9c5e598699512 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_tnode.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_tnode.c @@ -31,26 +31,12 @@ #include "nghttp3_conn.h" #include "nghttp3_conv.h" -nghttp3_node_id *nghttp3_node_id_init(nghttp3_node_id *nid, - nghttp3_node_id_type type, int64_t id) { - nid->type = type; - nid->id = id; - return nid; -} - -int nghttp3_node_id_eq(const nghttp3_node_id *a, const nghttp3_node_id *b) { - return a->type == b->type && a->id == b->id; -} - -void nghttp3_tnode_init(nghttp3_tnode *tnode, const nghttp3_node_id *nid, - uint64_t seq, uint8_t pri) { - assert(nghttp3_pri_uint8_urgency(pri) < NGHTTP3_URGENCY_LEVELS); - +void nghttp3_tnode_init(nghttp3_tnode *tnode, int64_t id) { tnode->pe.index = NGHTTP3_PQ_BAD_INDEX; - tnode->nid = *nid; - tnode->seq = seq; + tnode->id = id; tnode->cycle = 0; - tnode->pri = pri; + tnode->pri.urgency = NGHTTP3_DEFAULT_URGENCY; + tnode->pri.inc = 0; } void nghttp3_tnode_free(nghttp3_tnode *tnode) { (void)tnode; } @@ -86,12 +72,11 @@ int nghttp3_tnode_schedule(nghttp3_tnode *tnode, nghttp3_pq *pq, uint64_t penalty = nwrite / NGHTTP3_STREAM_MIN_WRITELEN; if (tnode->pe.index == NGHTTP3_PQ_BAD_INDEX) { - tnode->cycle = pq_get_first_cycle(pq) + - ((nwrite == 0 || !nghttp3_pri_uint8_inc(tnode->pri)) - ? 0 - : nghttp3_max(1, penalty)); + tnode->cycle = + pq_get_first_cycle(pq) + + ((nwrite == 0 || !tnode->pri.inc) ? 0 : nghttp3_max(1, penalty)); } else if (nwrite > 0) { - if (!nghttp3_pri_uint8_inc(tnode->pri) || nghttp3_pq_size(pq) == 1) { + if (!tnode->pri.inc || nghttp3_pq_size(pq) == 1) { return 0; } diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_tnode.h b/deps/ngtcp2/nghttp3/lib/nghttp3_tnode.h index f71dcf5ee31ad6..1abc1e62519381 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_tnode.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_tnode.h @@ -35,33 +35,16 @@ #define NGHTTP3_TNODE_MAX_CYCLE_GAP (1llu << 24) -typedef enum nghttp3_node_id_type { - NGHTTP3_NODE_ID_TYPE_STREAM = 0x00, - NGHTTP3_NODE_ID_TYPE_PUSH = 0x01, -} nghttp3_node_id_type; - -typedef struct nghttp3_node_id { - nghttp3_node_id_type type; - int64_t id; -} nghttp3_node_id; - -nghttp3_node_id *nghttp3_node_id_init(nghttp3_node_id *nid, - nghttp3_node_id_type type, int64_t id); - -int nghttp3_node_id_eq(const nghttp3_node_id *a, const nghttp3_node_id *b); - typedef struct nghttp3_tnode { nghttp3_pq_entry pe; size_t num_children; - nghttp3_node_id nid; - uint64_t seq; + int64_t id; uint64_t cycle; /* pri is a stream priority produced by nghttp3_pri_to_uint8. */ - uint8_t pri; + nghttp3_pri pri; } nghttp3_tnode; -void nghttp3_tnode_init(nghttp3_tnode *tnode, const nghttp3_node_id *nid, - uint64_t seq, uint8_t pri); +void nghttp3_tnode_init(nghttp3_tnode *tnode, int64_t id); void nghttp3_tnode_free(nghttp3_tnode *tnode); diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.c b/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.c new file mode 100644 index 00000000000000..6fea89b802b12d --- /dev/null +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.c @@ -0,0 +1,72 @@ +/* + * nghttp3 + * + * Copyright (c) 2022 nghttp3 contributors + * Copyright (c) 2022 ngtcp2 contributors + * + * 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 "nghttp3_unreachable.h" + +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#ifdef WIN32 +# include +#endif /* WIN32 */ + +void nghttp3_unreachable_fail(const char *file, int line, const char *func) { + char *buf; + size_t buflen; + int rv; + +#define NGHTTP3_UNREACHABLE_TEMPLATE "%s:%d %s: Unreachable.\n" + + rv = snprintf(NULL, 0, NGHTTP3_UNREACHABLE_TEMPLATE, file, line, func); + if (rv < 0) { + abort(); + } + + /* here we explicitly use system malloc */ + buflen = (size_t)rv + 1; + buf = malloc(buflen); + if (buf == NULL) { + abort(); + } + + rv = snprintf(buf, buflen, NGHTTP3_UNREACHABLE_TEMPLATE, file, line, func); + if (rv < 0) { + abort(); + } + +#ifndef WIN32 + while (write(STDERR_FILENO, buf, (size_t)rv) == -1 && errno == EINTR) + ; +#else /* WIN32 */ + _write(_fileno(stderr), buf, (unsigned int)rv); +#endif /* WIN32 */ + + free(buf); + + abort(); +} diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.h b/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.h new file mode 100644 index 00000000000000..6360f52d3aa857 --- /dev/null +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.h @@ -0,0 +1,53 @@ +/* + * nghttp3 + * + * Copyright (c) 2022 nghttp3 contributors + * Copyright (c) 2022 ngtcp2 contributors + * + * 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. + */ +#ifndef NGHTTP3_UNREACHABLE_H +#define NGHTTP3_UNREACHABLE_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +#ifdef __FILE_NAME__ +# define NGHTTP3_FILE_NAME __FILE_NAME__ +#else /* !__FILE_NAME__ */ +# define NGHTTP3_FILE_NAME "(file)" +#endif /* !__FILE_NAME__ */ + +#define nghttp3_unreachable() \ + nghttp3_unreachable_fail(NGHTTP3_FILE_NAME, __LINE__, __func__) + +#ifdef _MSC_VER +__declspec(noreturn) +#endif /* _MSC_VER */ + void nghttp3_unreachable_fail(const char *file, int line, const char *func) +#ifndef _MSC_VER + __attribute__((noreturn)) +#endif /* !_MSC_VER */ + ; + +#endif /* NGHTTP3_UNREACHABLE_H */ diff --git a/deps/ngtcp2/nghttp3/lib/sfparse.c b/deps/ngtcp2/nghttp3/lib/sfparse.c new file mode 100644 index 00000000000000..efa2850c9d661d --- /dev/null +++ b/deps/ngtcp2/nghttp3/lib/sfparse.c @@ -0,0 +1,1146 @@ +/* + * sfparse + * + * Copyright (c) 2023 sfparse contributors + * Copyright (c) 2019 nghttp3 contributors + * Copyright (c) 2015 nghttp2 contributors + * + * 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 "sfparse.h" + +#include +#include +#include + +#define SF_STATE_DICT 0x08u +#define SF_STATE_LIST 0x10u +#define SF_STATE_ITEM 0x18u + +#define SF_STATE_INNER_LIST 0x04u + +#define SF_STATE_BEFORE 0x00u +#define SF_STATE_BEFORE_PARAMS 0x01u +#define SF_STATE_PARAMS 0x02u +#define SF_STATE_AFTER 0x03u + +#define SF_STATE_OP_MASK 0x03u + +#define SF_SET_STATE_AFTER(NAME) (SF_STATE_##NAME | SF_STATE_AFTER) +#define SF_SET_STATE_BEFORE_PARAMS(NAME) \ + (SF_STATE_##NAME | SF_STATE_BEFORE_PARAMS) +#define SF_SET_STATE_INNER_LIST_BEFORE(NAME) \ + (SF_STATE_##NAME | SF_STATE_INNER_LIST | SF_STATE_BEFORE) + +#define SF_STATE_DICT_AFTER SF_SET_STATE_AFTER(DICT) +#define SF_STATE_DICT_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(DICT) +#define SF_STATE_DICT_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(DICT) + +#define SF_STATE_LIST_AFTER SF_SET_STATE_AFTER(LIST) +#define SF_STATE_LIST_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(LIST) +#define SF_STATE_LIST_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(LIST) + +#define SF_STATE_ITEM_AFTER SF_SET_STATE_AFTER(ITEM) +#define SF_STATE_ITEM_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(ITEM) +#define SF_STATE_ITEM_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(ITEM) + +#define SF_STATE_INITIAL 0x00u + +#define DIGIT_CASES \ + case '0': \ + case '1': \ + case '2': \ + case '3': \ + case '4': \ + case '5': \ + case '6': \ + case '7': \ + case '8': \ + case '9' + +#define LCALPHA_CASES \ + case 'a': \ + case 'b': \ + case 'c': \ + case 'd': \ + case 'e': \ + case 'f': \ + case 'g': \ + case 'h': \ + case 'i': \ + case 'j': \ + case 'k': \ + case 'l': \ + case 'm': \ + case 'n': \ + case 'o': \ + case 'p': \ + case 'q': \ + case 'r': \ + case 's': \ + case 't': \ + case 'u': \ + case 'v': \ + case 'w': \ + case 'x': \ + case 'y': \ + case 'z' + +#define UCALPHA_CASES \ + case 'A': \ + case 'B': \ + case 'C': \ + case 'D': \ + case 'E': \ + case 'F': \ + case 'G': \ + case 'H': \ + case 'I': \ + case 'J': \ + case 'K': \ + case 'L': \ + case 'M': \ + case 'N': \ + case 'O': \ + case 'P': \ + case 'Q': \ + case 'R': \ + case 'S': \ + case 'T': \ + case 'U': \ + case 'V': \ + case 'W': \ + case 'X': \ + case 'Y': \ + case 'Z' + +#define ALPHA_CASES \ + UCALPHA_CASES: \ + LCALPHA_CASES + +#define X20_21_CASES \ + case ' ': \ + case '!' + +#define X23_5B_CASES \ + case '#': \ + case '$': \ + case '%': \ + case '&': \ + case '\'': \ + case '(': \ + case ')': \ + case '*': \ + case '+': \ + case ',': \ + case '-': \ + case '.': \ + case '/': \ + DIGIT_CASES: \ + case ':': \ + case ';': \ + case '<': \ + case '=': \ + case '>': \ + case '?': \ + case '@': \ + UCALPHA_CASES: \ + case '[' + +#define X5D_7E_CASES \ + case ']': \ + case '^': \ + case '_': \ + case '`': \ + LCALPHA_CASES: \ + case '{': \ + case '|': \ + case '}': \ + case '~' + +static int is_ws(uint8_t c) { + switch (c) { + case ' ': + case '\t': + return 1; + default: + return 0; + } +} + +static int parser_eof(sf_parser *sfp) { return sfp->pos == sfp->end; } + +static void parser_discard_ows(sf_parser *sfp) { + for (; !parser_eof(sfp) && is_ws(*sfp->pos); ++sfp->pos) + ; +} + +static void parser_discard_sp(sf_parser *sfp) { + for (; !parser_eof(sfp) && *sfp->pos == ' '; ++sfp->pos) + ; +} + +static void parser_set_op_state(sf_parser *sfp, uint32_t op) { + sfp->state &= ~SF_STATE_OP_MASK; + sfp->state |= op; +} + +static void parser_unset_inner_list_state(sf_parser *sfp) { + sfp->state &= ~SF_STATE_INNER_LIST; +} + +static int parser_key(sf_parser *sfp, sf_vec *dest) { + const uint8_t *base; + + switch (*sfp->pos) { + case '*': + LCALPHA_CASES: + break; + default: + return SF_ERR_PARSE_ERROR; + } + + base = sfp->pos++; + + for (; !parser_eof(sfp); ++sfp->pos) { + switch (*sfp->pos) { + case '_': + case '-': + case '.': + case '*': + DIGIT_CASES: + LCALPHA_CASES: + continue; + } + + break; + } + + if (dest) { + dest->base = (uint8_t *)base; + dest->len = (size_t)(sfp->pos - dest->base); + } + + return 0; +} + +static int parser_number(sf_parser *sfp, sf_value *dest) { + int sign = 1; + int64_t value = 0; + size_t len = 0; + size_t fpos = 0; + + if (*sfp->pos == '-') { + ++sfp->pos; + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + sign = -1; + } + + assert(!parser_eof(sfp)); + + for (; !parser_eof(sfp); ++sfp->pos) { + switch (*sfp->pos) { + DIGIT_CASES: + if (++len > 15) { + return SF_ERR_PARSE_ERROR; + } + + value *= 10; + value += *sfp->pos - '0'; + + continue; + } + + break; + } + + if (len == 0) { + return SF_ERR_PARSE_ERROR; + } + + if (parser_eof(sfp) || *sfp->pos != '.') { + if (dest) { + dest->type = SF_TYPE_INTEGER; + dest->flags = SF_VALUE_FLAG_NONE; + dest->integer = value * sign; + } + + return 0; + } + + /* decimal */ + + if (len > 12) { + return SF_ERR_PARSE_ERROR; + } + + fpos = len; + + ++sfp->pos; + + for (; !parser_eof(sfp); ++sfp->pos) { + switch (*sfp->pos) { + DIGIT_CASES: + if (++len > 15) { + return SF_ERR_PARSE_ERROR; + } + + value *= 10; + value += *sfp->pos - '0'; + + continue; + } + + break; + } + + if (fpos == len || len - fpos > 3) { + return SF_ERR_PARSE_ERROR; + } + + if (dest) { + dest->type = SF_TYPE_DECIMAL; + dest->flags = SF_VALUE_FLAG_NONE; + dest->decimal.numer = value * sign; + + switch (len - fpos) { + case 1: + dest->decimal.denom = 10; + + break; + case 2: + dest->decimal.denom = 100; + + break; + case 3: + dest->decimal.denom = 1000; + + break; + } + } + + return 0; +} + +static int parser_date(sf_parser *sfp, sf_value *dest) { + int rv; + sf_value val; + + /* The first byte has already been validated by the caller. */ + assert('@' == *sfp->pos); + + ++sfp->pos; + + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + rv = parser_number(sfp, &val); + if (rv != 0) { + return rv; + } + + if (val.type != SF_TYPE_INTEGER) { + return SF_ERR_PARSE_ERROR; + } + + if (dest) { + *dest = val; + dest->type = SF_TYPE_DATE; + } + + return 0; +} + +static int parser_string(sf_parser *sfp, sf_value *dest) { + const uint8_t *base; + uint32_t flags = SF_VALUE_FLAG_NONE; + + /* The first byte has already been validated by the caller. */ + assert('"' == *sfp->pos); + + base = ++sfp->pos; + + for (; !parser_eof(sfp); ++sfp->pos) { + switch (*sfp->pos) { + X20_21_CASES: + X23_5B_CASES: + X5D_7E_CASES: + break; + case '\\': + ++sfp->pos; + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + switch (*sfp->pos) { + case '"': + case '\\': + flags = SF_VALUE_FLAG_ESCAPED_STRING; + + break; + default: + return SF_ERR_PARSE_ERROR; + } + + break; + case '"': + if (dest) { + dest->type = SF_TYPE_STRING; + dest->flags = flags; + dest->vec.len = (size_t)(sfp->pos - base); + dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base; + } + + ++sfp->pos; + + return 0; + default: + return SF_ERR_PARSE_ERROR; + } + } + + return SF_ERR_PARSE_ERROR; +} + +static int parser_token(sf_parser *sfp, sf_value *dest) { + const uint8_t *base; + + /* The first byte has already been validated by the caller. */ + base = sfp->pos++; + + for (; !parser_eof(sfp); ++sfp->pos) { + switch (*sfp->pos) { + case '!': + case '#': + case '$': + case '%': + case '&': + case '\'': + case '*': + case '+': + case '-': + case '.': + case '^': + case '_': + case '`': + case '|': + case '~': + case ':': + case '/': + DIGIT_CASES: + ALPHA_CASES: + continue; + } + + break; + } + + if (dest) { + dest->type = SF_TYPE_TOKEN; + dest->flags = SF_VALUE_FLAG_NONE; + dest->vec.base = (uint8_t *)base; + dest->vec.len = (size_t)(sfp->pos - base); + } + + return 0; +} + +static int parser_byteseq(sf_parser *sfp, sf_value *dest) { + const uint8_t *base; + + /* The first byte has already been validated by the caller. */ + assert(':' == *sfp->pos); + + base = ++sfp->pos; + + for (; !parser_eof(sfp); ++sfp->pos) { + switch (*sfp->pos) { + case '+': + case '/': + DIGIT_CASES: + ALPHA_CASES: + continue; + case '=': + switch ((sfp->pos - base) & 0x3) { + case 0: + case 1: + return SF_ERR_PARSE_ERROR; + case 2: + switch (*(sfp->pos - 1)) { + case 'A': + case 'Q': + case 'g': + case 'w': + break; + default: + return SF_ERR_PARSE_ERROR; + } + + ++sfp->pos; + + if (parser_eof(sfp) || *sfp->pos != '=') { + return SF_ERR_PARSE_ERROR; + } + + break; + case 3: + switch (*(sfp->pos - 1)) { + case 'A': + case 'E': + case 'I': + case 'M': + case 'Q': + case 'U': + case 'Y': + case 'c': + case 'g': + case 'k': + case 'o': + case 's': + case 'w': + case '0': + case '4': + case '8': + break; + default: + return SF_ERR_PARSE_ERROR; + } + + break; + } + + ++sfp->pos; + + if (parser_eof(sfp) || *sfp->pos != ':') { + return SF_ERR_PARSE_ERROR; + } + + goto fin; + case ':': + if ((sfp->pos - base) & 0x3) { + return SF_ERR_PARSE_ERROR; + } + + goto fin; + default: + return SF_ERR_PARSE_ERROR; + } + } + + return SF_ERR_PARSE_ERROR; + +fin: + if (dest) { + dest->type = SF_TYPE_BYTESEQ; + dest->flags = SF_VALUE_FLAG_NONE; + dest->vec.len = (size_t)(sfp->pos - base); + dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base; + } + + ++sfp->pos; + + return 0; +} + +static int parser_boolean(sf_parser *sfp, sf_value *dest) { + int b; + + /* The first byte has already been validated by the caller. */ + assert('?' == *sfp->pos); + + ++sfp->pos; + + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + switch (*sfp->pos) { + case '0': + b = 0; + + break; + case '1': + b = 1; + + break; + default: + return SF_ERR_PARSE_ERROR; + } + + ++sfp->pos; + + if (dest) { + dest->type = SF_TYPE_BOOLEAN; + dest->flags = SF_VALUE_FLAG_NONE; + dest->boolean = b; + } + + return 0; +} + +static int parser_bare_item(sf_parser *sfp, sf_value *dest) { + switch (*sfp->pos) { + case '"': + return parser_string(sfp, dest); + case '-': + DIGIT_CASES: + return parser_number(sfp, dest); + case '@': + return parser_date(sfp, dest); + case ':': + return parser_byteseq(sfp, dest); + case '?': + return parser_boolean(sfp, dest); + case '*': + ALPHA_CASES: + return parser_token(sfp, dest); + default: + return SF_ERR_PARSE_ERROR; + } +} + +static int parser_skip_inner_list(sf_parser *sfp); + +int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) { + int rv; + + switch (sfp->state & SF_STATE_OP_MASK) { + case SF_STATE_BEFORE: + rv = parser_skip_inner_list(sfp); + if (rv != 0) { + return rv; + } + + /* fall through */ + case SF_STATE_BEFORE_PARAMS: + parser_set_op_state(sfp, SF_STATE_PARAMS); + + break; + case SF_STATE_PARAMS: + break; + default: + assert(0); + abort(); + } + + if (parser_eof(sfp) || *sfp->pos != ';') { + parser_set_op_state(sfp, SF_STATE_AFTER); + + return SF_ERR_EOF; + } + + ++sfp->pos; + + parser_discard_sp(sfp); + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + rv = parser_key(sfp, dest_key); + if (rv != 0) { + return rv; + } + + if (parser_eof(sfp) || *sfp->pos != '=') { + if (dest_value) { + dest_value->type = SF_TYPE_BOOLEAN; + dest_value->flags = SF_VALUE_FLAG_NONE; + dest_value->boolean = 1; + } + + return 0; + } + + ++sfp->pos; + + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + return parser_bare_item(sfp, dest_value); +} + +static int parser_skip_params(sf_parser *sfp) { + int rv; + + for (;;) { + rv = sf_parser_param(sfp, NULL, NULL); + switch (rv) { + case 0: + break; + case SF_ERR_EOF: + return 0; + case SF_ERR_PARSE_ERROR: + return rv; + default: + assert(0); + abort(); + } + } +} + +int sf_parser_inner_list(sf_parser *sfp, sf_value *dest) { + int rv; + + switch (sfp->state & SF_STATE_OP_MASK) { + case SF_STATE_BEFORE: + parser_discard_sp(sfp); + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + break; + case SF_STATE_BEFORE_PARAMS: + rv = parser_skip_params(sfp); + if (rv != 0) { + return rv; + } + + /* Technically, we are entering SF_STATE_AFTER, but we will set + another state without reading the state. */ + /* parser_set_op_state(sfp, SF_STATE_AFTER); */ + + /* fall through */ + case SF_STATE_AFTER: + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + switch (*sfp->pos) { + case ' ': + parser_discard_sp(sfp); + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + break; + case ')': + break; + default: + return SF_ERR_PARSE_ERROR; + } + + break; + default: + assert(0); + abort(); + } + + if (*sfp->pos == ')') { + ++sfp->pos; + + parser_unset_inner_list_state(sfp); + parser_set_op_state(sfp, SF_STATE_BEFORE_PARAMS); + + return SF_ERR_EOF; + } + + rv = parser_bare_item(sfp, dest); + if (rv != 0) { + return rv; + } + + parser_set_op_state(sfp, SF_STATE_BEFORE_PARAMS); + + return 0; +} + +static int parser_skip_inner_list(sf_parser *sfp) { + int rv; + + for (;;) { + rv = sf_parser_inner_list(sfp, NULL); + switch (rv) { + case 0: + break; + case SF_ERR_EOF: + return 0; + case SF_ERR_PARSE_ERROR: + return rv; + default: + assert(0); + abort(); + } + } +} + +static int parser_next_key_or_item(sf_parser *sfp) { + parser_discard_ows(sfp); + + if (parser_eof(sfp)) { + return SF_ERR_EOF; + } + + if (*sfp->pos != ',') { + return SF_ERR_PARSE_ERROR; + } + + ++sfp->pos; + + parser_discard_ows(sfp); + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + return 0; +} + +static int parser_dict_value(sf_parser *sfp, sf_value *dest) { + int rv; + + if (parser_eof(sfp) || *(sfp->pos) != '=') { + /* Boolean true */ + if (dest) { + dest->type = SF_TYPE_BOOLEAN; + dest->flags = SF_VALUE_FLAG_NONE; + dest->boolean = 1; + } + + sfp->state = SF_STATE_DICT_BEFORE_PARAMS; + + return 0; + } + + ++sfp->pos; + + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + if (*sfp->pos == '(') { + if (dest) { + dest->type = SF_TYPE_INNER_LIST; + dest->flags = SF_VALUE_FLAG_NONE; + } + + ++sfp->pos; + + sfp->state = SF_STATE_DICT_INNER_LIST_BEFORE; + + return 0; + } + + rv = parser_bare_item(sfp, dest); + if (rv != 0) { + return rv; + } + + sfp->state = SF_STATE_DICT_BEFORE_PARAMS; + + return 0; +} + +int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) { + int rv; + + switch (sfp->state) { + case SF_STATE_DICT_INNER_LIST_BEFORE: + rv = parser_skip_inner_list(sfp); + if (rv != 0) { + return rv; + } + + /* fall through */ + case SF_STATE_DICT_BEFORE_PARAMS: + rv = parser_skip_params(sfp); + if (rv != 0) { + return rv; + } + + /* fall through */ + case SF_STATE_DICT_AFTER: + rv = parser_next_key_or_item(sfp); + if (rv != 0) { + return rv; + } + + break; + case SF_STATE_INITIAL: + parser_discard_sp(sfp); + + if (parser_eof(sfp)) { + return SF_ERR_EOF; + } + + break; + default: + assert(0); + abort(); + } + + rv = parser_key(sfp, dest_key); + if (rv != 0) { + return rv; + } + + return parser_dict_value(sfp, dest_value); +} + +int sf_parser_list(sf_parser *sfp, sf_value *dest) { + int rv; + + switch (sfp->state) { + case SF_STATE_LIST_INNER_LIST_BEFORE: + rv = parser_skip_inner_list(sfp); + if (rv != 0) { + return rv; + } + + /* fall through */ + case SF_STATE_LIST_BEFORE_PARAMS: + rv = parser_skip_params(sfp); + if (rv != 0) { + return rv; + } + + /* fall through */ + case SF_STATE_LIST_AFTER: + rv = parser_next_key_or_item(sfp); + if (rv != 0) { + return rv; + } + + break; + case SF_STATE_INITIAL: + parser_discard_sp(sfp); + + if (parser_eof(sfp)) { + return SF_ERR_EOF; + } + + break; + default: + assert(0); + abort(); + } + + if (*sfp->pos == '(') { + if (dest) { + dest->type = SF_TYPE_INNER_LIST; + dest->flags = SF_VALUE_FLAG_NONE; + } + + ++sfp->pos; + + sfp->state = SF_STATE_LIST_INNER_LIST_BEFORE; + + return 0; + } + + rv = parser_bare_item(sfp, dest); + if (rv != 0) { + return rv; + } + + sfp->state = SF_STATE_LIST_BEFORE_PARAMS; + + return 0; +} + +int sf_parser_item(sf_parser *sfp, sf_value *dest) { + int rv; + + switch (sfp->state) { + case SF_STATE_INITIAL: + parser_discard_sp(sfp); + + if (parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + break; + case SF_STATE_ITEM_INNER_LIST_BEFORE: + rv = parser_skip_inner_list(sfp); + if (rv != 0) { + return rv; + } + + /* fall through */ + case SF_STATE_ITEM_BEFORE_PARAMS: + rv = parser_skip_params(sfp); + if (rv != 0) { + return rv; + } + + /* fall through */ + case SF_STATE_ITEM_AFTER: + parser_discard_sp(sfp); + + if (!parser_eof(sfp)) { + return SF_ERR_PARSE_ERROR; + } + + return SF_ERR_EOF; + default: + assert(0); + abort(); + } + + if (*sfp->pos == '(') { + if (dest) { + dest->type = SF_TYPE_INNER_LIST; + dest->flags = SF_VALUE_FLAG_NONE; + } + + ++sfp->pos; + + sfp->state = SF_STATE_ITEM_INNER_LIST_BEFORE; + + return 0; + } + + rv = parser_bare_item(sfp, dest); + if (rv != 0) { + return rv; + } + + sfp->state = SF_STATE_ITEM_BEFORE_PARAMS; + + return 0; +} + +void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen) { + if (datalen == 0) { + sfp->pos = sfp->end = NULL; + } else { + sfp->pos = data; + sfp->end = data + datalen; + } + + sfp->state = SF_STATE_INITIAL; +} + +void sf_unescape(sf_vec *dest, const sf_vec *src) { + const uint8_t *p, *q; + uint8_t *o; + size_t len, slen; + + if (src->len == 0) { + *dest = *src; + + return; + } + + o = dest->base; + p = src->base; + len = src->len; + + for (;;) { + q = memchr(p, '\\', len); + if (q == NULL) { + if (len == src->len) { + *dest = *src; + + return; + } + + memcpy(o, p, len); + o += len; + + break; + } + + slen = (size_t)(q - p); + memcpy(o, p, slen); + o += slen; + + p = q + 1; + *o++ = *p++; + len -= slen + 2; + } + + dest->len = (size_t)(o - dest->base); +} + +void sf_base64decode(sf_vec *dest, const sf_vec *src) { + static const int index_tbl[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1}; + uint8_t *o; + const uint8_t *p, *end; + uint32_t n; + size_t i; + int idx; + + assert((src->len & 0x3) == 0); + + if (src->len == 0) { + *dest = *src; + + return; + } + + o = dest->base; + p = src->base; + end = src->base + src->len; + + for (; p != end;) { + n = 0; + + for (i = 1; i <= 4; ++i, ++p) { + idx = index_tbl[*p]; + + if (idx == -1) { + assert(i > 2); + + if (i == 3) { + assert(*p == '=' && *(p + 1) == '=' && p + 2 == end); + + *o++ = (uint8_t)(n >> 16); + + goto fin; + } + + assert(*p == '=' && p + 1 == end); + + *o++ = (uint8_t)(n >> 16); + *o++ = (n >> 8) & 0xffu; + + goto fin; + } + + n += (uint32_t)(idx << (24 - i * 6)); + } + + *o++ = (uint8_t)(n >> 16); + *o++ = (n >> 8) & 0xffu; + *o++ = n & 0xffu; + } + +fin: + dest->len = (size_t)(o - dest->base); +} diff --git a/deps/ngtcp2/nghttp3/lib/sfparse.h b/deps/ngtcp2/nghttp3/lib/sfparse.h new file mode 100644 index 00000000000000..1474db1429acea --- /dev/null +++ b/deps/ngtcp2/nghttp3/lib/sfparse.h @@ -0,0 +1,409 @@ +/* + * sfparse + * + * Copyright (c) 2023 sfparse contributors + * Copyright (c) 2019 nghttp3 contributors + * Copyright (c) 2015 nghttp2 contributors + * + * 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. + */ +#ifndef SFPARSE_H +#define SFPARSE_H + +/* Define WIN32 when build target is Win32 API (borrowed from + libcurl) */ +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1800) +/* MSVC < 2013 does not have inttypes.h because it is not C99 + compliant. See compiler macros and version number in + https://sourceforge.net/p/predef/wiki/Compilers/ */ +# include +#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ +# include +#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ +#include +#include + +/** + * @enum + * + * :type:`sf_type` defines value type. + */ +typedef enum sf_type { + /** + * :enum:`SF_TYPE_BOOLEAN` indicates boolean type. + */ + SF_TYPE_BOOLEAN, + /** + * :enum:`SF_TYPE_INTEGER` indicates integer type. + */ + SF_TYPE_INTEGER, + /** + * :enum:`SF_TYPE_DECIMAL` indicates decimal type. + */ + SF_TYPE_DECIMAL, + /** + * :enum:`SF_TYPE_STRING` indicates string type. + */ + SF_TYPE_STRING, + /** + * :enum:`SF_TYPE_TOKEN` indicates token type. + */ + SF_TYPE_TOKEN, + /** + * :enum:`SF_TYPE_BYTESEQ` indicates byte sequence type. + */ + SF_TYPE_BYTESEQ, + /** + * :enum:`SF_TYPE_INNER_LIST` indicates inner list type. + */ + SF_TYPE_INNER_LIST, + /** + * :enum:`SF_TYPE_DATE` indicates date type. + */ + SF_TYPE_DATE +} sf_type; + +/** + * @macro + * + * :macro:`SF_ERR_PARSE_ERROR` indicates fatal parse error has + * occurred, and it is not possible to continue the processing. + */ +#define SF_ERR_PARSE_ERROR -1 + +/** + * @macro + * + * :macro:`SF_ERR_EOF` indicates that there is nothing left to read. + * The context of this error varies depending on the function that + * returns this error code. + */ +#define SF_ERR_EOF -2 + +/** + * @struct + * + * :type:`sf_vec` stores sequence of bytes. + */ +typedef struct sf_vec { + /** + * :member:`base` points to the beginning of the sequence of bytes. + */ + uint8_t *base; + /** + * :member:`len` is the number of bytes contained in this sequence. + */ + size_t len; +} sf_vec; + +/** + * @macro + * + * :macro:`SF_VALUE_FLAG_NONE` indicates no flag set. + */ +#define SF_VALUE_FLAG_NONE 0x0u + +/** + * @macro + * + * :macro:`SF_VALUE_FLAG_ESCAPED_STRING` indicates that a string + * contains escaped character(s). + */ +#define SF_VALUE_FLAG_ESCAPED_STRING 0x1u + +/** + * @struct + * + * :type:`sf_decimal` contains decimal value. + */ +typedef struct sf_decimal { + /** + * :member:`numer` contains numerator of the decimal value. + */ + int64_t numer; + /** + * :member:`denom` contains denominator of the decimal value. + */ + int64_t denom; +} sf_decimal; + +/** + * @struct + * + * :type:`sf_value` stores a Structured Field item. For Inner List, + * only type is set to :enum:`sf_type.SF_TYPE_INNER_LIST`. In order + * to read the items contained in an inner list, call + * `sf_parser_inner_list`. + */ +typedef struct sf_value { + /** + * :member:`type` is the type of the value contained in this + * particular object. + */ + sf_type type; + /** + * :member:`flags` is bitwise OR of one or more of + * :macro:`SF_VALUE_FLAG_* `. + */ + uint32_t flags; + /** + * @anonunion_start + * + * @sf_value_value + */ + union { + /** + * :member:`boolean` contains boolean value if :member:`type` == + * :enum:`sf_type.SF_TYPE_BOOLEAN`. 1 indicates true, and 0 + * indicates false. + */ + int boolean; + /** + * :member:`integer` contains integer value if :member:`type` is + * either :enum:`sf_type.SF_TYPE_INTEGER` or + * :enum:`sf_type.SF_TYPE_DATE`. + */ + int64_t integer; + /** + * :member:`decimal` contains decimal value if :member:`type` == + * :enum:`sf_type.SF_TYPE_DECIMAL`. + */ + sf_decimal decimal; + /** + * :member:`vec` contains sequence of bytes if :member:`type` is + * either :enum:`sf_type.SF_TYPE_STRING`, + * :enum:`sf_type.SF_TYPE_TOKEN`, or + * :enum:`sf_type.SF_TYPE_BYTESEQ`. + * + * For :enum:`sf_type.SF_TYPE_STRING`, this field contains one or + * more escaped characters if :member:`flags` has + * :macro:`SF_VALUE_FLAG_ESCAPED_STRING` set. To unescape the + * string, use `sf_unescape`. + * + * For :enum:`sf_type.SF_TYPE_BYTESEQ`, this field contains base64 + * encoded string. To decode this byte string, use + * `sf_base64decode`. + * + * If :member:`vec.len ` == 0, :member:`vec.base + * ` is guaranteed to be NULL. + */ + sf_vec vec; + /** + * @anonunion_end + */ + }; +} sf_value; + +/** + * @struct + * + * :type:`sf_parser` is the Structured Field Values parser. Use + * `sf_parser_init` to initialize it. + */ +typedef struct sf_parser { + /* all fields are private */ + const uint8_t *pos; + const uint8_t *end; + uint32_t state; +} sf_parser; + +/** + * @function + * + * `sf_parser_init` initializes |sfp| with the given buffer pointed by + * |data| of length |datalen|. + */ +void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen); + +/** + * @function + * + * `sf_parser_param` reads a parameter. If this function returns 0, + * it stores parameter key and value in |dest_key| and |dest_value| + * respectively, if they are not NULL. + * + * This function does no effort to find duplicated keys. Same key may + * be reported more than once. + * + * Caller should keep calling this function until it returns negative + * error code. If it returns :macro:`SF_ERR_EOF`, all parameters have + * read, and caller can continue to read rest of the values. If it + * returns :macro:`SF_ERR_PARSE_ERROR`, it encountered fatal error + * while parsing field value. + */ +int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value); + +/** + * @function + * + * `sf_parser_dict` reads the next dictionary key and value pair. If + * this function returns 0, it stores the key and value in |dest_key| + * and |dest_value| respectively, if they are not NULL. + * + * Caller can optionally read parameters attached to the pair by + * calling `sf_parser_param`. + * + * This function does no effort to find duplicated keys. Same key may + * be reported more than once. + * + * Caller should keep calling this function until it returns negative + * error code. If it returns :macro:`SF_ERR_EOF`, all key and value + * pairs have been read, and there is nothing left to read. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`SF_ERR_EOF` + * All values in the dictionary have read. + * :macro:`SF_ERR_PARSE_ERROR` + * It encountered fatal error while parsing field value. + */ +int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value); + +/** + * @function + * + * `sf_parser_list` reads the next list item. If this function + * returns 0, it stores the item in |dest| if it is not NULL. + * + * Caller can optionally read parameters attached to the item by + * calling `sf_parser_param`. + * + * Caller should keep calling this function until it returns negative + * error code. If it returns :macro:`SF_ERR_EOF`, all values in the + * list have been read, and there is nothing left to read. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`SF_ERR_EOF` + * All values in the list have read. + * :macro:`SF_ERR_PARSE_ERROR` + * It encountered fatal error while parsing field value. + */ +int sf_parser_list(sf_parser *sfp, sf_value *dest); + +/** + * @function + * + * `sf_parser_item` reads a single item. If this function returns 0, + * it stores the item in |dest| if it is not NULL. + * + * This function is only used for the field value that consists of a + * single item. + * + * Caller can optionally read parameters attached to the item by + * calling `sf_parser_param`. + * + * Caller should call this function again to make sure that there is + * nothing left to read. If this 2nd function call returns + * :macro:`SF_ERR_EOF`, all data have been processed successfully. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`SF_ERR_EOF` + * There is nothing left to read. + * :macro:`SF_ERR_PARSE_ERROR` + * It encountered fatal error while parsing field value. + */ +int sf_parser_item(sf_parser *sfp, sf_value *dest); + +/** + * @function + * + * `sf_parser_inner_list` reads the next inner list item. If this + * function returns 0, it stores the item in |dest| if it is not NULL. + * + * Caller can optionally read parameters attached to the item by + * calling `sf_parser_param`. + * + * Caller should keep calling this function until it returns negative + * error code. If it returns :macro:`SF_ERR_EOF`, all values in this + * inner list have been read, and caller can optionally read + * parameters attached to this inner list by calling + * `sf_parser_param`. Then caller can continue to read rest of the + * values. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`SF_ERR_EOF` + * All values in the inner list have read. + * :macro:`SF_ERR_PARSE_ERROR` + * It encountered fatal error while parsing field value. + */ +int sf_parser_inner_list(sf_parser *sfp, sf_value *dest); + +/** + * @function + * + * `sf_unescape` copies |src| to |dest| by removing escapes (``\``). + * |src| should be the pointer to :member:`sf_value.vec` of type + * :enum:`sf_type.SF_TYPE_STRING` produced by either `sf_parser_dict`, + * `sf_parser_list`, `sf_parser_inner_list`, `sf_parser_item`, or + * `sf_parser_param`, otherwise the behavior is undefined. + * + * :member:`dest->base ` must point to the buffer that + * has sufficient space to store the unescaped string. + * + * If there is no escape character in |src|, |*src| is assigned to + * |*dest|. This includes the case that :member:`src->len + * ` == 0. + * + * This function sets the length of unescaped string to + * :member:`dest->len `. + */ +void sf_unescape(sf_vec *dest, const sf_vec *src); + +/** + * @function + * + * `sf_base64decode` decodes Base64 encoded string |src| and writes + * the result into |dest|. |src| should be the pointer to + * :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_BYTESEQ` + * produced by either `sf_parser_dict`, `sf_parser_list`, + * `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`, + * otherwise the behavior is undefined. + * + * :member:`dest->base ` must point to the buffer that + * has sufficient space to store the decoded byte string. + * + * If :member:`src->len ` == 0, |*src| is assigned to + * |*dest|. + * + * This function sets the length of decoded byte string to + * :member:`dest->len `. + */ +void sf_base64decode(sf_vec *dest, const sf_vec *src); + +#ifdef __cplusplus +} +#endif + +#endif /* SFPARSE_H */ diff --git a/deps/ngtcp2/ngtcp2.gyp b/deps/ngtcp2/ngtcp2.gyp index e53b7f61ea387b..0f2929b75478f1 100644 --- a/deps/ngtcp2/ngtcp2.gyp +++ b/deps/ngtcp2/ngtcp2.gyp @@ -8,14 +8,15 @@ 'ngtcp2/lib/ngtcp2_addr.c', 'ngtcp2/lib/ngtcp2_balloc.c', 'ngtcp2/lib/ngtcp2_bbr.c', - 'ngtcp2/lib/ngtcp2_bbr2.c', 'ngtcp2/lib/ngtcp2_buf.c', 'ngtcp2/lib/ngtcp2_cc.c', 'ngtcp2/lib/ngtcp2_cid.c', 'ngtcp2/lib/ngtcp2_conn.c', 'ngtcp2/lib/ngtcp2_conv.c', + 'ngtcp2/lib/ngtcp2_conversion.c', 'ngtcp2/lib/ngtcp2_crypto.c', 'ngtcp2/lib/ngtcp2_err.c', + 'ngtcp2/lib/ngtcp2_frame_chain.c', 'ngtcp2/lib/ngtcp2_gaptr.c', 'ngtcp2/lib/ngtcp2_idtr.c', 'ngtcp2/lib/ngtcp2_ksl.c', @@ -38,13 +39,14 @@ 'ngtcp2/lib/ngtcp2_rtb.c', 'ngtcp2/lib/ngtcp2_str.c', 'ngtcp2/lib/ngtcp2_strm.c', + 'ngtcp2/lib/ngtcp2_unreachable.c', 'ngtcp2/lib/ngtcp2_vec.c', 'ngtcp2/lib/ngtcp2_version.c', 'ngtcp2/lib/ngtcp2_window_filter.c', 'ngtcp2/crypto/shared.c' ], - 'ngtcp2_sources_openssl': [ - 'ngtcp2/crypto/openssl/openssl.c' + 'ngtcp2_sources_quictls': [ + 'ngtcp2/crypto/quictls/quictls.c' ], 'ngtcp2_sources_boringssl': [ 'ngtcp2/crypto/boringssl/boringssl.c' @@ -75,8 +77,11 @@ 'nghttp3/lib/nghttp3_str.c', 'nghttp3/lib/nghttp3_stream.c', 'nghttp3/lib/nghttp3_tnode.c', + 'nghttp3/lib/nghttp3_unreachable.c', 'nghttp3/lib/nghttp3_vec.c', - 'nghttp3/lib/nghttp3_version.c' + 'nghttp3/lib/nghttp3_version.c', + # sfparse is also used by nghttp2 and is included by nghttp2.gyp + # 'nghttp3/lib/sfparse.c' ] }, 'targets': [ @@ -100,6 +105,9 @@ '../openssl/openssl.gyp:openssl' ] }], + ['OS!="win"', { + 'defines': ['HAVE_UNISTD_H'] + }], ['OS=="win"', { 'defines': [ 'WIN32', @@ -132,7 +140,7 @@ }, 'sources': [ '<@(ngtcp2_sources)', - '<@(ngtcp2_sources_openssl)', + '<@(ngtcp2_sources_quictls)', ] }, { @@ -144,7 +152,7 @@ ], 'defines': [ 'BUILDING_NGHTTP3', - 'NGHTTP3_STATICLIB' + 'NGHTTP3_STATICLIB', ], 'dependencies': [ 'ngtcp2' @@ -162,6 +170,9 @@ }, }, }], + ['OS!="win"', { + 'defines': ['HAVE_UNISTD_H'] + }], ['OS=="linux" or OS=="android"', { 'defines': [ 'HAVE_ARPA_INET_H', diff --git a/deps/ngtcp2/ngtcp2/crypto/boringssl/boringssl.c b/deps/ngtcp2/ngtcp2/crypto/boringssl/boringssl.c index 015032d41ca0ce..50b89110e36ff7 100644 --- a/deps/ngtcp2/ngtcp2/crypto/boringssl/boringssl.c +++ b/deps/ngtcp2/ngtcp2/crypto/boringssl/boringssl.c @@ -92,8 +92,8 @@ ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead) { return ngtcp2_crypto_aead_init(aead, (void *)EVP_aead_aes_128_gcm()); } -static const EVP_AEAD *crypto_ssl_get_aead(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static const EVP_AEAD *crypto_cipher_id_get_aead(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_CK_AES_128_GCM_SHA256: return EVP_aead_aes_128_gcm(); case TLS1_CK_AES_256_GCM_SHA384: @@ -105,8 +105,8 @@ static const EVP_AEAD *crypto_ssl_get_aead(SSL *ssl) { } } -static uint64_t crypto_ssl_get_aead_max_encryption(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static uint64_t crypto_cipher_id_get_aead_max_encryption(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_CK_AES_128_GCM_SHA256: case TLS1_CK_AES_256_GCM_SHA384: return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM; @@ -117,8 +117,9 @@ static uint64_t crypto_ssl_get_aead_max_encryption(SSL *ssl) { } } -static uint64_t crypto_ssl_get_aead_max_decryption_failure(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static uint64_t +crypto_cipher_id_get_aead_max_decryption_failure(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_CK_AES_128_GCM_SHA256: case TLS1_CK_AES_256_GCM_SHA384: return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM; @@ -129,8 +130,9 @@ static uint64_t crypto_ssl_get_aead_max_decryption_failure(SSL *ssl) { } } -static const ngtcp2_crypto_boringssl_cipher *crypto_ssl_get_hp(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static const ngtcp2_crypto_boringssl_cipher * +crypto_cipher_id_get_hp(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_CK_AES_128_GCM_SHA256: return &crypto_cipher_aes_128; case TLS1_CK_AES_256_GCM_SHA384: @@ -142,8 +144,8 @@ static const ngtcp2_crypto_boringssl_cipher *crypto_ssl_get_hp(SSL *ssl) { } } -static const EVP_MD *crypto_ssl_get_md(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static const EVP_MD *crypto_cipher_id_get_md(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_CK_AES_128_GCM_SHA256: case TLS1_CK_CHACHA20_POLY1305_SHA256: return EVP_sha256(); @@ -154,15 +156,47 @@ static const EVP_MD *crypto_ssl_get_md(SSL *ssl) { } } +static int supported_cipher_id(uint32_t cipher_id) { + switch (cipher_id) { + case TLS1_CK_AES_128_GCM_SHA256: + case TLS1_CK_AES_256_GCM_SHA384: + case TLS1_CK_CHACHA20_POLY1305_SHA256: + return 1; + default: + return 0; + } +} + +static ngtcp2_crypto_ctx *crypto_ctx_cipher_id(ngtcp2_crypto_ctx *ctx, + uint32_t cipher_id) { + ngtcp2_crypto_aead_init(&ctx->aead, + (void *)crypto_cipher_id_get_aead(cipher_id)); + ctx->md.native_handle = (void *)crypto_cipher_id_get_md(cipher_id); + ctx->hp.native_handle = (void *)crypto_cipher_id_get_hp(cipher_id); + ctx->max_encryption = crypto_cipher_id_get_aead_max_encryption(cipher_id); + ctx->max_decryption_failure = + crypto_cipher_id_get_aead_max_decryption_failure(cipher_id); + + return ctx; +} + ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, void *tls_native_handle) { SSL *ssl = tls_native_handle; - ngtcp2_crypto_aead_init(&ctx->aead, (void *)crypto_ssl_get_aead(ssl)); - ctx->md.native_handle = (void *)crypto_ssl_get_md(ssl); - ctx->hp.native_handle = (void *)crypto_ssl_get_hp(ssl); - ctx->max_encryption = crypto_ssl_get_aead_max_encryption(ssl); - ctx->max_decryption_failure = crypto_ssl_get_aead_max_decryption_failure(ssl); - return ctx; + const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); + uint32_t cipher_id; + + if (cipher == NULL) { + return NULL; + } + + cipher_id = SSL_CIPHER_get_id(cipher); + + if (!supported_cipher_id(cipher_id)) { + return NULL; + } + + return crypto_ctx_cipher_id(ctx, cipher_id); } ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls_early(ngtcp2_crypto_ctx *ctx, @@ -394,15 +428,17 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, } } -int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, - const uint8_t *data, size_t datalen) { +int ngtcp2_crypto_read_write_crypto_data( + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, + const uint8_t *data, size_t datalen) { SSL *ssl = ngtcp2_conn_get_tls_native_handle(conn); int rv; int err; if (SSL_provide_quic_data( - ssl, ngtcp2_crypto_boringssl_from_ngtcp2_crypto_level(crypto_level), + ssl, + ngtcp2_crypto_boringssl_from_ngtcp2_encryption_level( + encryption_level), data, datalen) != 1) { return -1; } @@ -423,7 +459,10 @@ int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, SSL_reset_early_data_reject(ssl); - ngtcp2_conn_early_data_rejected(conn); + rv = ngtcp2_conn_tls_early_data_rejected(conn); + if (rv != 0) { + return -1; + } goto retry; default: @@ -435,7 +474,7 @@ int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, return 0; } - ngtcp2_conn_handshake_completed(conn); + ngtcp2_conn_tls_handshake_completed(conn); } rv = SSL_process_quic_post_handshake(ssl); @@ -464,7 +503,7 @@ int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls) { SSL_get_peer_quic_transport_params(ssl, &tp, &tplen); - rv = ngtcp2_conn_decode_remote_transport_params(conn, tp, tplen); + rv = ngtcp2_conn_decode_and_set_remote_transport_params(conn, tp, tplen); if (rv != 0) { ngtcp2_conn_set_tls_error(conn, rv); return -1; @@ -482,33 +521,34 @@ int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf, return 0; } -ngtcp2_crypto_level ngtcp2_crypto_boringssl_from_ssl_encryption_level( +ngtcp2_encryption_level ngtcp2_crypto_boringssl_from_ssl_encryption_level( enum ssl_encryption_level_t ssl_level) { switch (ssl_level) { case ssl_encryption_initial: - return NGTCP2_CRYPTO_LEVEL_INITIAL; + return NGTCP2_ENCRYPTION_LEVEL_INITIAL; case ssl_encryption_early_data: - return NGTCP2_CRYPTO_LEVEL_EARLY; + return NGTCP2_ENCRYPTION_LEVEL_0RTT; case ssl_encryption_handshake: - return NGTCP2_CRYPTO_LEVEL_HANDSHAKE; + return NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE; case ssl_encryption_application: - return NGTCP2_CRYPTO_LEVEL_APPLICATION; + return NGTCP2_ENCRYPTION_LEVEL_1RTT; default: assert(0); abort(); } } -enum ssl_encryption_level_t ngtcp2_crypto_boringssl_from_ngtcp2_crypto_level( - ngtcp2_crypto_level crypto_level) { - switch (crypto_level) { - case NGTCP2_CRYPTO_LEVEL_INITIAL: +enum ssl_encryption_level_t +ngtcp2_crypto_boringssl_from_ngtcp2_encryption_level( + ngtcp2_encryption_level encryption_level) { + switch (encryption_level) { + case NGTCP2_ENCRYPTION_LEVEL_INITIAL: return ssl_encryption_initial; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: return ssl_encryption_handshake; - case NGTCP2_CRYPTO_LEVEL_APPLICATION: + case NGTCP2_ENCRYPTION_LEVEL_1RTT: return ssl_encryption_application; - case NGTCP2_CRYPTO_LEVEL_EARLY: + case NGTCP2_ENCRYPTION_LEVEL_0RTT: return ssl_encryption_early_data; default: assert(0); @@ -541,7 +581,7 @@ static int set_read_secret(SSL *ssl, enum ssl_encryption_level_t bssl_level, size_t secretlen) { ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); - ngtcp2_crypto_level level = + ngtcp2_encryption_level level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(bssl_level); (void)cipher; @@ -558,7 +598,7 @@ static int set_write_secret(SSL *ssl, enum ssl_encryption_level_t bssl_level, size_t secretlen) { ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); - ngtcp2_crypto_level level = + ngtcp2_encryption_level level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(bssl_level); (void)cipher; @@ -574,7 +614,7 @@ static int add_handshake_data(SSL *ssl, enum ssl_encryption_level_t bssl_level, const uint8_t *data, size_t datalen) { ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); - ngtcp2_crypto_level level = + ngtcp2_encryption_level level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(bssl_level); int rv; diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h index 4736b51c3cb48d..06427d7a7cac70 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h @@ -38,39 +38,16 @@ extern "C" { # include #endif /* WIN32 */ -/** - * @macro - * - * :macro:`NGTCP2_CRYPTO_INITIAL_SECRETLEN` is the length of secret - * for Initial packets. - */ -#define NGTCP2_CRYPTO_INITIAL_SECRETLEN 32 - -/** - * @macro - * - * :macro:`NGTCP2_CRYPTO_INITIAL_KEYLEN` is the length of key for - * Initial packets. - */ -#define NGTCP2_CRYPTO_INITIAL_KEYLEN 16 - -/** - * @macro - * - * :macro:`NGTCP2_CRYPTO_INITIAL_IVLEN` is the length of IV for - * Initial packets. - */ -#define NGTCP2_CRYPTO_INITIAL_IVLEN 12 - /** * @function * * `ngtcp2_crypto_ctx_tls` initializes |ctx| by extracting negotiated * ciphers and message digests from native TLS session * |tls_native_handle|. This is used for encrypting/decrypting - * Handshake and Short header packets. + * Handshake and 1-RTT packets. If it is unable to obtain necessary + * data from |tls_native_handle|, this function returns NULL. * - * If libngtcp2_crypto_openssl is linked, |tls_native_handle| must be + * If libngtcp2_crypto_quictls is linked, |tls_native_handle| must be * a pointer to SSL object. */ NGTCP2_EXTERN ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, @@ -81,10 +58,11 @@ NGTCP2_EXTERN ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, * * `ngtcp2_crypto_ctx_tls_early` initializes |ctx| by extracting early * ciphers and message digests from native TLS session - * |tls_native_handle|. This is used for encrypting/decrypting 0RTT - * packets. + * |tls_native_handle|. This is used for encrypting/decrypting 0-RTT + * packets. If it is unable to obtain necessary data from + * |tls_native_handle|, this function returns NULL. * - * If libngtcp2_crypto_openssl is linked, |tls_native_handle| must be + * If libngtcp2_crypto_quictls is linked, |tls_native_handle| must be * a pointer to SSL object. */ NGTCP2_EXTERN ngtcp2_crypto_ctx * @@ -96,7 +74,7 @@ ngtcp2_crypto_ctx_tls_early(ngtcp2_crypto_ctx *ctx, void *tls_native_handle); * `ngtcp2_crypto_md_init` initializes |md| with the provided * |md_native_handle| which is an underlying message digest object. * - * If libngtcp2_crypto_openssl is linked, |md_native_handle| must be a + * If libngtcp2_crypto_quictls is linked, |md_native_handle| must be a * pointer to EVP_MD. * * If libngtcp2_crypto_gnutls is linked, |md_native_handle| must be @@ -134,10 +112,12 @@ ngtcp2_crypto_aead_noncelen(const ngtcp2_crypto_aead *aead); /** * @function * - * `ngtcp2_crypto_hkdf_extract` performs HKDF extract operation. The - * result is the length of |md| and is stored to the buffer pointed by - * |dest|. The caller is responsible to specify the buffer that can - * store the output. + * `ngtcp2_crypto_hkdf_extract` performs HKDF extract operation. + * + * The length of output is `ngtcp2_crypto_md_hashlen(md) + * `. The output is stored in the buffer + * pointed by |dest|. The caller is responsible to specify the buffer + * that has enough capacity to store the output. * * This function returns 0 if it succeeds, or -1. */ @@ -150,7 +130,7 @@ ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md, * @function * * `ngtcp2_crypto_hkdf_expand` performs HKDF expand operation. The - * result is |destlen| bytes long and is stored to the buffer pointed + * result is |destlen| bytes long, and is stored in the buffer pointed * by |dest|. * * This function returns 0 if it succeeds, or -1. @@ -166,7 +146,8 @@ NGTCP2_EXTERN int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen, * @function * * `ngtcp2_crypto_hkdf` performs HKDF operation. The result is - * |destlen| bytes long and is stored to the buffer pointed by |dest|. + * |destlen| bytes long, and is stored in the buffer pointed by + * |dest|. * * This function returns 0 if it succeeds, or -1. */ @@ -176,41 +157,6 @@ NGTCP2_EXTERN int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen, const uint8_t *salt, size_t saltlen, const uint8_t *info, size_t infolen); -/** - * @function - * - * `ngtcp2_crypto_hkdf_expand_label` performs HKDF expand label. The - * result is |destlen| bytes long and is stored to the buffer pointed - * by |dest|. - * - * This function returns 0 if it succeeds, or -1. - */ -NGTCP2_EXTERN int ngtcp2_crypto_hkdf_expand_label(uint8_t *dest, size_t destlen, - const ngtcp2_crypto_md *md, - const uint8_t *secret, - size_t secretlen, - const uint8_t *label, - size_t labellen); - -/** - * @enum - * - * :type:`ngtcp2_crypto_side` indicates which side the application - * implements; client or server. - */ -typedef enum ngtcp2_crypto_side { - /** - * :enum:`NGTCP2_CRYPTO_SIDE_CLIENT` indicates that the application - * is client. - */ - NGTCP2_CRYPTO_SIDE_CLIENT, - /** - * :enum:`NGTCP2_CRYPTO_SIDE_SERVER` indicates that the application - * is server. - */ - NGTCP2_CRYPTO_SIDE_SERVER -} ngtcp2_crypto_side; - /** * @function * @@ -225,11 +171,10 @@ ngtcp2_crypto_packet_protection_ivlen(const ngtcp2_crypto_aead *aead); * * `ngtcp2_crypto_encrypt` encrypts |plaintext| of length * |plaintextlen| and writes the ciphertext into the buffer pointed by - * |dest|. The length of ciphertext is plaintextlen + + * |dest|. The length of ciphertext is |plaintextlen| + * :member:`aead->max_overhead ` * bytes long. |dest| must have enough capacity to store the - * ciphertext. It is allowed to specify the same value to |dest| and - * |plaintext|. + * ciphertext. |dest| and |plaintext| may point to the same buffer. * * This function returns 0 if it succeeds, or -1. */ @@ -263,11 +208,10 @@ ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead, * * `ngtcp2_crypto_decrypt` decrypts |ciphertext| of length * |ciphertextlen| and writes the plaintext into the buffer pointed by - * |dest|. The length of plaintext is ciphertextlen - + * |dest|. The length of plaintext is |ciphertextlen| - * :member:`aead->max_overhead ` * bytes long. |dest| must have enough capacity to store the - * plaintext. It is allowed to specify the same value to |dest| and - * |ciphertext|. + * plaintext. |dest| and |ciphertext| may point to the same buffer. * * This function returns 0 if it succeeds, or -1. */ @@ -299,7 +243,7 @@ ngtcp2_crypto_decrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead, /** * @function * - * `ngtcp2_crypto_hp_mask` generates mask which is used in packet + * `ngtcp2_crypto_hp_mask` generates a mask which is used in packet * header encryption. The mask is written to the buffer pointed by * |dest|. The sample is passed as |sample| which is * :macro:`NGTCP2_HP_SAMPLELEN` bytes long. The length of mask must @@ -333,15 +277,14 @@ ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp, /** * @function * - * `ngtcp2_crypto_derive_and_install_rx_key` derives the rx keys from - * |secret| and installs new keys to |conn|. + * `ngtcp2_crypto_derive_and_install_rx_key` derives the decryption + * keying materials from |secret|, and installs them to |conn|. * - * If |key| is not NULL, the derived packet protection key for - * decryption is written to the buffer pointed by |key|. If |iv| is - * not NULL, the derived packet protection IV for decryption is - * written to the buffer pointed by |iv|. If |hp| is not NULL, the - * derived header protection key for decryption is written to the - * buffer pointed by |hp|. + * If |key| is not NULL, the derived packet protection key is written + * to the buffer pointed by |key|. If |iv| is not NULL, the derived + * packet protection IV is written to the buffer pointed by |iv|. If + * |hp| is not NULL, the derived header protection key is written to + * the buffer pointed by |hp|. * * |secretlen| specifies the length of |secret|. * @@ -351,44 +294,44 @@ ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp, * `ngtcp2_crypto_packet_protection_ivlen(ctx->aead) * ` where ctx is obtained by * `ngtcp2_crypto_ctx_tls` (or `ngtcp2_crypto_ctx_tls_early` if - * |level| == :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`). + * |level| == + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`). * * In the first call of this function, it calls * `ngtcp2_conn_set_crypto_ctx` (or `ngtcp2_conn_set_early_crypto_ctx` * if |level| == - * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`) to set - * negotiated AEAD and message digest algorithm. After the successful - * call of this function, application can use + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`) to + * set negotiated AEAD and message digest algorithm. After the + * successful call of this function, application can use * `ngtcp2_conn_get_crypto_ctx` (or `ngtcp2_conn_get_early_crypto_ctx` * if |level| == - * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`) to get - * :type:`ngtcp2_crypto_ctx`. + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`) to + * get :type:`ngtcp2_crypto_ctx`. * * If |conn| is initialized as client, and |level| is - * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_APPLICATION`, this + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_1RTT`, this * function retrieves a remote QUIC transport parameters extension - * from an object obtained by `ngtcp2_conn_get_tls_native_handle` and + * from an object obtained by `ngtcp2_conn_get_tls_native_handle`, and * sets it to |conn| by calling - * `ngtcp2_conn_decode_remote_transport_params`. + * `ngtcp2_conn_decode_and_set_remote_transport_params`. * * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_rx_key( ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp, - ngtcp2_crypto_level level, const uint8_t *secret, size_t secretlen); + ngtcp2_encryption_level level, const uint8_t *secret, size_t secretlen); /** * @function * - * `ngtcp2_crypto_derive_and_install_tx_key` derives the tx keys from - * |secret| and installs new keys to |conn|. + * `ngtcp2_crypto_derive_and_install_tx_key` derives the encryption + * keying materials from |secret|, and installs new keys to |conn|. * - * If |key| is not NULL, the derived packet protection key for - * encryption is written to the buffer pointed by |key|. If |iv| is - * not NULL, the derived packet protection IV for encryption is - * written to the buffer pointed by |iv|. If |hp| is not NULL, the - * derived header protection key for encryption is written to the - * buffer pointed by |hp|. + * If |key| is not NULL, the derived packet protection key is written + * to the buffer pointed by |key|. If |iv| is not NULL, the derived + * packet protection IV is written to the buffer pointed by |iv|. If + * |hp| is not NULL, the derived header protection key is written to + * the buffer pointed by |hp|. * * |secretlen| specifies the length of |secret|. * @@ -398,58 +341,59 @@ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_rx_key( * `ngtcp2_crypto_packet_protection_ivlen(ctx->aead) * ` where ctx is obtained by * `ngtcp2_crypto_ctx_tls` (or `ngtcp2_crypto_ctx_tls_early` if - * |level| == :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`). + * |level| == + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`). * * In the first call of this function, it calls * `ngtcp2_conn_set_crypto_ctx` (or `ngtcp2_conn_set_early_crypto_ctx` * if |level| == - * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`) to set - * negotiated AEAD and message digest algorithm. After the successful - * call of this function, application can use + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`) to + * set negotiated AEAD and message digest algorithm. After the + * successful call of this function, application can use * `ngtcp2_conn_get_crypto_ctx` (or `ngtcp2_conn_get_early_crypto_ctx` * if |level| == - * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`) to get - * :type:`ngtcp2_crypto_ctx`. + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`) to + * get :type:`ngtcp2_crypto_ctx`. * * If |conn| is initialized as server, and |level| is - * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_APPLICATION`, this + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_1RTT`, this * function retrieves a remote QUIC transport parameters extension - * from an object obtained by `ngtcp2_conn_get_tls_native_handle` and + * from an object obtained by `ngtcp2_conn_get_tls_native_handle`, and * sets it to |conn| by calling - * `ngtcp2_conn_decode_remote_transport_params`. + * `ngtcp2_conn_decode_and_set_remote_transport_params`. * * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_tx_key( ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp, - ngtcp2_crypto_level level, const uint8_t *secret, size_t secretlen); + ngtcp2_encryption_level level, const uint8_t *secret, size_t secretlen); /** * @function * * `ngtcp2_crypto_update_key` updates traffic keying materials. * - * The new traffic secret for decryption is written to the buffer - * pointed by |rx_secret|. The length of secret is |secretlen| bytes, - * and |rx_secret| must point to the buffer which has enough capacity. + * The new decryption traffic secret is written to the buffer pointed + * by |rx_secret|. The length of secret is |secretlen| bytes, and + * |rx_secret| must point to the buffer which has enough capacity. * - * The new traffic secret for encryption is written to the buffer - * pointed by |tx_secret|. The length of secret is |secretlen| bytes, - * and |tx_secret| must point to the buffer which has enough capacity. + * The new encryption traffic secret is written to the buffer pointed + * by |tx_secret|. The length of secret is |secretlen| bytes, and + * |tx_secret| must point to the buffer which has enough capacity. * - * The derived packet protection key for decryption is written to the - * buffer pointed by |rx_key|. The derived packet protection IV for - * decryption is written to the buffer pointed by |rx_iv|. - * |rx_aead_ctx| must be constructed with |rx_key|. + * The derived decryption packet protection key is written to the + * buffer pointed by |rx_key|. The derived decryption packet + * protection IV is written to the buffer pointed by |rx_iv|. + * |rx_aead_ctx| is initialized with the derived key and IV. * - * The derived packet protection key for encryption is written to the - * buffer pointed by |tx_key|. The derived packet protection IV for - * encryption is written to the buffer pointed by |tx_iv|. - * |tx_aead_ctx| must be constructed with |rx_key|. + * The derived encryption packet protection key is written to the + * buffer pointed by |tx_key|. The derived encryption packet + * protection IV is written to the buffer pointed by |tx_iv|. + * |tx_aead_ctx| is initialized with the derived key and IV. * - * |current_rx_secret| and |current_tx_secret| are the current traffic - * secrets for decryption and encryption. |secretlen| specifies the - * length of |rx_secret| and |tx_secret|. + * |current_rx_secret| and |current_tx_secret| are the current + * decryption and encryption traffic secrets respectively. They share + * the same length with |rx_secret| and |tx_secret|. * * The length of packet protection key and header protection key is * `ngtcp2_crypto_aead_keylen(ctx->aead) `, @@ -488,7 +432,7 @@ NGTCP2_EXTERN int ngtcp2_crypto_update_key_cb( * @function * * `ngtcp2_crypto_client_initial_cb` installs initial secrets and - * encryption keys and sets QUIC transport parameters. + * encryption keys, and sets QUIC transport parameters. * * This function can be directly passed to * :member:`ngtcp2_callbacks.client_initial` field. It is only used @@ -507,8 +451,8 @@ NGTCP2_EXTERN int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn, * response to incoming Retry packet. * * This function can be directly passed to - * :member:`ngtcp2_callbacks.recv_retry` field. It is only used - * by client. + * :member:`ngtcp2_callbacks.recv_retry` field. It is only used by + * client. * * This function returns 0 if it succeeds, or * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`. @@ -525,8 +469,8 @@ NGTCP2_EXTERN int ngtcp2_crypto_recv_retry_cb(ngtcp2_conn *conn, * transport parameters. * * This function can be directly passed to - * :member:`ngtcp2_callbacks.recv_client_initial` field. It is - * only used by server. + * :member:`ngtcp2_callbacks.recv_client_initial` field. It is only + * used by server. * * This function returns 0 if it succeeds, or * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`. @@ -539,21 +483,21 @@ NGTCP2_EXTERN int ngtcp2_crypto_recv_client_initial_cb(ngtcp2_conn *conn, * @function * * `ngtcp2_crypto_read_write_crypto_data` reads CRYPTO data |data| of - * length |datalen| in encryption level |crypto_level| and may feed - * outgoing CRYPTO data to |conn|. This function can drive handshake. - * This function can be also used after handshake completes. It is - * allowed to call this function with |datalen| == 0. In this case, - * no additional read operation is done. + * length |datalen| in an encryption level |encryption_level|, and may + * feed outgoing CRYPTO data to |conn|. This function can drive + * handshake. This function can be also used after handshake + * completes. It is allowed to call this function with |datalen| == + * 0. In this case, no additional read operation is done. * * This function returns 0 if it succeeds, or a negative error code. * The generic error code is -1 if a specific error code is not * suitable. The error codes less than -10000 are specific to - * underlying TLS implementation. For OpenSSL, the error codes are - * defined in *ngtcp2_crypto_openssl.h*. + * underlying TLS implementation. For quictls, the error codes are + * defined in *ngtcp2_crypto_quictls.h*. */ NGTCP2_EXTERN int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, + ngtcp2_encryption_level encryption_level, const uint8_t *data, size_t datalen); /** @@ -570,17 +514,17 @@ ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, * codes. */ NGTCP2_EXTERN int ngtcp2_crypto_recv_crypto_data_cb( - ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, uint64_t offset, - const uint8_t *data, size_t datalen, void *user_data); + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, + uint64_t offset, const uint8_t *data, size_t datalen, void *user_data); /** * @function * * `ngtcp2_crypto_generate_stateless_reset_token` generates a * stateless reset token using HKDF extraction using the given |cid| - * and static key |secret| as input. The token will be written to - * the buffer pointed by |token| and it must have a capacity of at - * least :macro:`NGTCP2_STATELESS_RESET_TOKENLEN` bytes. + * and |secret| as input. The token will be written to the buffer + * pointed by |token|, and it must have a capacity of at least + * :macro:`NGTCP2_STATELESS_RESET_TOKENLEN` bytes. * * This function returns 0 if it succeeds, or -1. */ @@ -644,12 +588,12 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( * :macro:`NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN` bytes long. The * successfully generated token starts with * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY`. |secret| of length - * |secretlen| is an initial keying material to generate keys to - * encrypt the token. |version| is QUIC version. |remote_addr| of - * length |remote_addrlen| is an address of client. |retry_scid| is a - * Source Connection ID chosen by server and set in Retry packet. - * |odcid| is a Destination Connection ID in Initial packet sent by - * client. |ts| is the timestamp when the token is generated. + * |secretlen| is a keying material to generate keys to encrypt the + * token. |version| is QUIC version. |remote_addr| of length + * |remote_addrlen| is an address of client. |retry_scid| is a Source + * Connection ID chosen by server, and set in Retry packet. |odcid| + * is a Destination Connection ID in Initial packet sent by client. + * |ts| is the timestamp when the token is generated. * * This function returns the length of generated token if it succeeds, * or -1. @@ -664,16 +608,16 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_retry_token( * * `ngtcp2_crypto_verify_retry_token` verifies Retry token stored in * the buffer pointed by |token| of length |tokenlen|. |secret| of - * length |secretlen| is an initial keying material to generate keys - * to decrypt the token. |version| is QUIC version of the Initial - * packet that contains this token. |remote_addr| of length - * |remote_addrlen| is an address of client. |dcid| is a Destination - * Connection ID in Initial packet sent by client. |timeout| is the - * period during which the token is valid. |ts| is the current - * timestamp. When validation succeeds, the extracted Destination - * Connection ID (which is the Destination Connection ID in Initial - * packet sent by client that triggered Retry packet) is stored to the - * buffer pointed by |odcid|. + * length |secretlen| is a keying material to generate keys to decrypt + * the token. |version| is QUIC version of the Initial packet that + * contains this token. |remote_addr| of length |remote_addrlen| is + * an address of client. |dcid| is a Destination Connection ID in + * Initial packet sent by client. |timeout| is the period during + * which the token is valid. |ts| is the current timestamp. When + * validation succeeds, the extracted Destination Connection ID (which + * is the Destination Connection ID in Initial packet sent by client + * that triggered Retry packet) is stored in the buffer pointed by + * |odcid|. * * This function returns 0 if it succeeds, or -1. */ @@ -692,10 +636,9 @@ NGTCP2_EXTERN int ngtcp2_crypto_verify_retry_token( * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` bytes long. The * successfully generated token starts with * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR`. |secret| of length - * |secretlen| is an initial keying material to generate keys to - * encrypt the token. |remote_addr| of length |remote_addrlen| is an - * address of client. |ts| is the timestamp when the token is - * generated. + * |secretlen| is a keying material to generate keys to encrypt the + * token. |remote_addr| of length |remote_addrlen| is an address of + * client. |ts| is the timestamp when the token is generated. * * This function returns the length of generated token if it succeeds, * or -1. @@ -710,8 +653,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_regular_token( * * `ngtcp2_crypto_verify_regular_token` verifies a regular token * stored in the buffer pointed by |token| of length |tokenlen|. - * |secret| of length |secretlen| is an initial keying material to - * generate keys to decrypt the token. |remote_addr| of length + * |secret| of length |secretlen| is a keying material to generate + * keys to decrypt the token. |remote_addr| of length * |remote_addrlen| is an address of client. |timeout| is the period * during which the token is valid. |ts| is the current timestamp. * @@ -750,9 +693,12 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_write_connection_close( * @function * * `ngtcp2_crypto_write_retry` writes Retry packet to the buffer - * pointed by |dest| of length |destlen|. |odcid| specifies Original - * Destination Connection ID. |token| specifies Retry Token, and - * |tokenlen| specifies its length. + * pointed by |dest| of length |destlen|. |dcid| is the Connection ID + * which appeared in a packet as a Source Connection ID sent by + * client. |scid| is a server chosen Source Connection ID. |odcid| + * specifies Original Destination Connection ID which appeared in a + * packet as a Destination Connection ID sent by client. |token| + * specifies Retry Token, and |tokenlen| specifies its length. * * This function wraps around `ngtcp2_pkt_write_retry` for easier use. * @@ -783,7 +729,7 @@ ngtcp2_crypto_aead_ctx_encrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx, * * `ngtcp2_crypto_aead_ctx_decrypt_init` initializes |aead_ctx| with * new AEAD cipher context object for decryption which is constructed - * to use |key| as encryption key. |aead| specifies AEAD cipher to + * to use |key| as decryption key. |aead| specifies AEAD cipher to * use. |noncelen| is the length of nonce. * * This function returns 0 if it succeeds, or -1. @@ -806,7 +752,8 @@ ngtcp2_crypto_aead_ctx_free(ngtcp2_crypto_aead_ctx *aead_ctx); /** * @function * - * `ngtcp2_crypto_delete_crypto_aead_ctx_cb` deletes the given |aead_ctx|. + * `ngtcp2_crypto_delete_crypto_aead_ctx_cb` deletes the given + * |aead_ctx|. * * This function can be directly passed to * :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` field. @@ -845,7 +792,8 @@ NGTCP2_EXTERN int ngtcp2_crypto_get_path_challenge_data_cb(ngtcp2_conn *conn, * * `ngtcp2_crypto_version_negotiation_cb` installs Initial keys for * |version| which is negotiated or being negotiated. |client_dcid| - * is the destination connection ID in first Initial packet of client. + * is the destination connection ID in first Initial packet from + * client. * * This function can be directly passed to * :member:`ngtcp2_callbacks.version_negotiation` field. @@ -872,7 +820,7 @@ typedef ngtcp2_conn *(*ngtcp2_crypto_get_conn)( * * :type:`ngtcp2_crypto_conn_ref` is a structure to get a pointer to * :type:`ngtcp2_conn`. It is meant to be set to TLS native handle as - * an application specific data (e.g. SSL_set_app_data in OpenSSL). + * an application specific data (e.g. SSL_set_app_data in quictls). */ typedef struct ngtcp2_crypto_conn_ref { /** diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h index 6497c09e79840d..43a3c36f03a382 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h @@ -37,23 +37,23 @@ extern "C" { * @function * * `ngtcp2_crypto_boringssl_from_ssl_encryption_level` translates - * |ssl_level| to :type:`ngtcp2_crypto_level`. This function is only - * available for BoringSSL backend. + * |ssl_level| to :type:`ngtcp2_encryption_level`. This function is + * only available for BoringSSL backend. */ -NGTCP2_EXTERN ngtcp2_crypto_level +NGTCP2_EXTERN ngtcp2_encryption_level ngtcp2_crypto_boringssl_from_ssl_encryption_level( enum ssl_encryption_level_t ssl_level); /** * @function * - * `ngtcp2_crypto_boringssl_from_ngtcp2_crypto_level` translates - * |crypto_level| to ssl_encryption_level_t. This function is only - * available for BoringSSL backend. + * `ngtcp2_crypto_boringssl_from_ngtcp2_encryption_level` translates + * |encryption_level| to ssl_encryption_level_t. This function is + * only available for BoringSSL backend. */ NGTCP2_EXTERN enum ssl_encryption_level_t -ngtcp2_crypto_boringssl_from_ngtcp2_crypto_level( - ngtcp2_crypto_level crypto_level); +ngtcp2_crypto_boringssl_from_ngtcp2_encryption_level( + ngtcp2_encryption_level encryption_level); /** * @function diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h index d4b551c382fd69..61020bb3a8f376 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h @@ -36,8 +36,8 @@ extern "C" { /** * @struct * - * :type:`ngtcp2_crypto_picotls_ctx` contains per-connection state - * of Picotls objects and must be an object to bet set to + * :type:`ngtcp2_crypto_picotls_ctx` contains per-connection state of + * Picotls objects and must be an object to bet set to * `ngtcp2_conn_set_tls_native_handle`. */ typedef struct ngtcp2_crypto_picotls_ctx { @@ -65,21 +65,21 @@ ngtcp2_crypto_picotls_ctx_init(ngtcp2_crypto_picotls_ctx *cptls); * @function * * `ngtcp2_crypto_picotls_from_epoch` translates |epoch| to - * :type:`ngtcp2_crypto_level`. This function is only available for - * Picotls backend. + * :type:`ngtcp2_encryption_level`. This function is only available + * for Picotls backend. */ -NGTCP2_EXTERN ngtcp2_crypto_level +NGTCP2_EXTERN ngtcp2_encryption_level ngtcp2_crypto_picotls_from_epoch(size_t epoch); /** * @function * - * `ngtcp2_crypto_picotls_from_ngtcp2_crypto_level` translates - * |crypto_level| to epoch. This function is only available for + * `ngtcp2_crypto_picotls_from_ngtcp2_encryption_level` translates + * |encryption_level| to epoch. This function is only available for * Picotls backend. */ -NGTCP2_EXTERN size_t ngtcp2_crypto_picotls_from_ngtcp2_crypto_level( - ngtcp2_crypto_level crypto_level); +NGTCP2_EXTERN size_t ngtcp2_crypto_picotls_from_ngtcp2_encryption_level( + ngtcp2_encryption_level encryption_level); /** * @function @@ -206,7 +206,7 @@ ngtcp2_crypto_picotls_configure_client_session(ngtcp2_crypto_picotls_ctx *cptls, * * `ngtcp2_crypto_picotls_deconfigure_session` frees the resources * allocated for |cptls| during QUIC connection. It frees the - * following data using :manpage:`free(3)`. + * following data using :manpage:`free(3)`: * * - handshake_properties.max_early_data_size * - handshake_properties.additional_extensions[0].data.base diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_openssl.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_quictls.h similarity index 63% rename from deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_openssl.h rename to deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_quictls.h index 844081bfa8b055..b25c13b81c8b18 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_openssl.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_quictls.h @@ -22,8 +22,8 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef NGTCP2_CRYPTO_OPENSSL_H -#define NGTCP2_CRYPTO_OPENSSL_H +#ifndef NGTCP2_CRYPTO_QUICTLS_H +#define NGTCP2_CRYPTO_QUICTLS_H #include @@ -36,57 +36,57 @@ extern "C" { /** * @macrosection * - * OpenSSL specific error codes + * quictls specific error codes */ /** * @macro * - * :macro:`NGTCP2_CRYPTO_OPENSSL_ERR_TLS_WANT_X509_LOOKUP` is the + * :macro:`NGTCP2_CRYPTO_QUICTLS_ERR_TLS_WANT_X509_LOOKUP` is the * error code which indicates that TLS handshake routine is * interrupted by X509 certificate lookup. See * :macro:`SSL_ERROR_WANT_X509_LOOKUP` error description from * `SSL_do_handshake`. */ -#define NGTCP2_CRYPTO_OPENSSL_ERR_TLS_WANT_X509_LOOKUP -10001 +#define NGTCP2_CRYPTO_QUICTLS_ERR_TLS_WANT_X509_LOOKUP -10001 /** * @macro * - * :macro:`NGTCP2_CRYPTO_OPENSSL_ERR_TLS_WANT_CLIENT_HELLO_CB` is the + * :macro:`NGTCP2_CRYPTO_QUICTLS_ERR_TLS_WANT_CLIENT_HELLO_CB` is the * error code which indicates that TLS handshake routine is * interrupted by client hello callback. See * :macro:`SSL_ERROR_WANT_CLIENT_HELLO_CB` error description from * `SSL_do_handshake`. */ -#define NGTCP2_CRYPTO_OPENSSL_ERR_TLS_WANT_CLIENT_HELLO_CB -10002 +#define NGTCP2_CRYPTO_QUICTLS_ERR_TLS_WANT_CLIENT_HELLO_CB -10002 /** * @function * - * `ngtcp2_crypto_openssl_from_ossl_encryption_level` translates - * |ossl_level| to :type:`ngtcp2_crypto_level`. This function is only - * available for OpenSSL backend. + * `ngtcp2_crypto_quictls_from_ossl_encryption_level` translates + * |ossl_level| to :type:`ngtcp2_encryption_level`. This function is + * only available for quictls backend. */ -NGTCP2_EXTERN ngtcp2_crypto_level -ngtcp2_crypto_openssl_from_ossl_encryption_level( +NGTCP2_EXTERN ngtcp2_encryption_level +ngtcp2_crypto_quictls_from_ossl_encryption_level( OSSL_ENCRYPTION_LEVEL ossl_level); /** * @function * - * `ngtcp2_crypto_openssl_from_ngtcp2_crypto_level` translates - * |crypto_level| to OSSL_ENCRYPTION_LEVEL. This function is only - * available for OpenSSL backend. + * `ngtcp2_crypto_quictls_from_ngtcp2_encryption_level` translates + * |encryption_level| to OSSL_ENCRYPTION_LEVEL. This function is only + * available for quictls backend. */ NGTCP2_EXTERN OSSL_ENCRYPTION_LEVEL -ngtcp2_crypto_openssl_from_ngtcp2_crypto_level( - ngtcp2_crypto_level crypto_level); +ngtcp2_crypto_quictls_from_ngtcp2_encryption_level( + ngtcp2_encryption_level encryption_level); /** * @function * - * `ngtcp2_crypto_openssl_configure_server_context` configures + * `ngtcp2_crypto_quictls_configure_server_context` configures * |ssl_ctx| for server side QUIC connection. It performs the * following modifications: * @@ -102,12 +102,12 @@ ngtcp2_crypto_openssl_from_ngtcp2_crypto_level( * It returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int -ngtcp2_crypto_openssl_configure_server_context(SSL_CTX *ssl_ctx); +ngtcp2_crypto_quictls_configure_server_context(SSL_CTX *ssl_ctx); /** * @function * - * `ngtcp2_crypto_openssl_configure_client_context` configures + * `ngtcp2_crypto_quictls_configure_client_context` configures * |ssl_ctx| for client side QUIC connection. It performs the * following modifications: * @@ -123,10 +123,25 @@ ngtcp2_crypto_openssl_configure_server_context(SSL_CTX *ssl_ctx); * It returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int -ngtcp2_crypto_openssl_configure_client_context(SSL_CTX *ssl_ctx); +ngtcp2_crypto_quictls_configure_client_context(SSL_CTX *ssl_ctx); + +/** + * @function + * + * `ngtcp2_crypto_quictls_init` initializes libngtcp2_crypto_quictls + * library. This initialization is optional. For quictls >= 3.0, it + * is highly recommended to call this function before any use of + * libngtcp2_crypto library API to workaround the performance + * regression. Note that calling this function does not solve all + * performance issues introduced in 3.x. For quictls 1.1.1, this + * function does nothing, and always succeeds. + * + * This function returns 0 if it succeeds, or -1. + */ +NGTCP2_EXTERN int ngtcp2_crypto_quictls_init(void); #ifdef __cplusplus } #endif -#endif /* NGTCP2_CRYPTO_OPENSSL_H */ +#endif /* NGTCP2_CRYPTO_QUICTLS_H */ diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h index 3b10802c25b5e8..e1d621adce94d8 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h @@ -39,23 +39,23 @@ extern "C" { * @function * * `ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level` translates - * |wolfssl_level| to :type:`ngtcp2_crypto_level`. This function is only - * available for wolfSSL backend. + * |wolfssl_level| to :type:`ngtcp2_encryption_level`. This function + * is only available for wolfSSL backend. */ -NGTCP2_EXTERN ngtcp2_crypto_level +NGTCP2_EXTERN ngtcp2_encryption_level ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level( WOLFSSL_ENCRYPTION_LEVEL wolfssl_level); /** * @function * - * `ngtcp2_crypto_wolfssl_from_ngtcp2_crypto_level` translates - * |crypto_level| to WOLFSSL_ENCRYPTION_LEVEL. This function is only - * available for wolfSSL backend. + * `ngtcp2_crypto_wolfssl_from_ngtcp2_encryption_level` translates + * |encryption_level| to WOLFSSL_ENCRYPTION_LEVEL. This function is + * only available for wolfSSL backend. */ NGTCP2_EXTERN WOLFSSL_ENCRYPTION_LEVEL -ngtcp2_crypto_wolfssl_from_ngtcp2_crypto_level( - ngtcp2_crypto_level crypto_level); +ngtcp2_crypto_wolfssl_from_ngtcp2_encryption_level( + ngtcp2_encryption_level encryption_level); /** * @function diff --git a/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c b/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c index 32d17adc6c3a35..35bfb7b2f8fa19 100644 --- a/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c +++ b/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c @@ -68,45 +68,40 @@ ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead) { return ngtcp2_crypto_aead_init(aead, (void *)&ptls_openssl_aes128gcm); } -static const ptls_aead_algorithm_t *crypto_ptls_get_aead(ptls_t *ptls) { - ptls_cipher_suite_t *cs = ptls_get_cipher(ptls); - - return cs->aead; -} - -static uint64_t crypto_ptls_get_aead_max_encryption(ptls_t *ptls) { - ptls_cipher_suite_t *cs = ptls_get_cipher(ptls); - +static uint64_t +crypto_cipher_suite_get_aead_max_encryption(ptls_cipher_suite_t *cs) { if (cs->aead == &ptls_openssl_aes128gcm || cs->aead == &ptls_openssl_aes256gcm) { return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM; } +#ifdef PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 if (cs->aead == &ptls_openssl_chacha20poly1305) { return NGTCP2_CRYPTO_MAX_ENCRYPTION_CHACHA20_POLY1305; } +#endif /* PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 */ return 0; } -static uint64_t crypto_ptls_get_aead_max_decryption_failure(ptls_t *ptls) { - ptls_cipher_suite_t *cs = ptls_get_cipher(ptls); - +static uint64_t +crypto_cipher_suite_get_aead_max_decryption_failure(ptls_cipher_suite_t *cs) { if (cs->aead == &ptls_openssl_aes128gcm || cs->aead == &ptls_openssl_aes256gcm) { return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM; } +#ifdef PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 if (cs->aead == &ptls_openssl_chacha20poly1305) { return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305; } +#endif /* PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 */ return 0; } -static const ptls_cipher_algorithm_t *crypto_ptls_get_hp(ptls_t *ptls) { - ptls_cipher_suite_t *cs = ptls_get_cipher(ptls); - +static const ptls_cipher_algorithm_t * +crypto_cipher_suite_get_hp(ptls_cipher_suite_t *cs) { if (cs->aead == &ptls_openssl_aes128gcm) { return &ptls_openssl_aes128ctr; } @@ -115,29 +110,43 @@ static const ptls_cipher_algorithm_t *crypto_ptls_get_hp(ptls_t *ptls) { return &ptls_openssl_aes256ctr; } +#ifdef PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 if (cs->aead == &ptls_openssl_chacha20poly1305) { return &ptls_openssl_chacha20; } +#endif /* PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 */ return NULL; } -static const ptls_hash_algorithm_t *crypto_ptls_get_md(ptls_t *ptls) { - ptls_cipher_suite_t *cs = ptls_get_cipher(ptls); - - return cs->hash; +static int supported_cipher_suite(ptls_cipher_suite_t *cs) { + return cs->aead == &ptls_openssl_aes128gcm || + cs->aead == &ptls_openssl_aes256gcm +#ifdef PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 + || cs->aead == &ptls_openssl_chacha20poly1305 +#endif /* PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 */ + ; } ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, void *tls_native_handle) { ngtcp2_crypto_picotls_ctx *cptls = tls_native_handle; - ngtcp2_crypto_aead_init(&ctx->aead, - (void *)crypto_ptls_get_aead(cptls->ptls)); - ctx->md.native_handle = (void *)crypto_ptls_get_md(cptls->ptls); - ctx->hp.native_handle = (void *)crypto_ptls_get_hp(cptls->ptls); - ctx->max_encryption = crypto_ptls_get_aead_max_encryption(cptls->ptls); + ptls_cipher_suite_t *cs = ptls_get_cipher(cptls->ptls); + + if (cs == NULL) { + return NULL; + } + + if (!supported_cipher_suite(cs)) { + return NULL; + } + + ngtcp2_crypto_aead_init(&ctx->aead, (void *)cs->aead); + ctx->md.native_handle = (void *)cs->hash; + ctx->hp.native_handle = (void *)crypto_cipher_suite_get_hp(cs); + ctx->max_encryption = crypto_cipher_suite_get_aead_max_encryption(cs); ctx->max_decryption_failure = - crypto_ptls_get_aead_max_decryption_failure(cptls->ptls); + crypto_cipher_suite_get_aead_max_decryption_failure(cs); return ctx; } @@ -350,13 +359,14 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, return 0; } -int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, - const uint8_t *data, size_t datalen) { +int ngtcp2_crypto_read_write_crypto_data( + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, + const uint8_t *data, size_t datalen) { ngtcp2_crypto_picotls_ctx *cptls = ngtcp2_conn_get_tls_native_handle(conn); ptls_buffer_t sendbuf; size_t epoch_offsets[5] = {0}; - size_t epoch = ngtcp2_crypto_picotls_from_ngtcp2_crypto_level(crypto_level); + size_t epoch = + ngtcp2_crypto_picotls_from_ngtcp2_encryption_level(encryption_level); size_t epoch_datalen; size_t i; int rv; @@ -379,7 +389,11 @@ int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, if (!ngtcp2_conn_is_server(conn) && cptls->handshake_properties.client.early_data_acceptance == PTLS_EARLY_DATA_REJECTED) { - ngtcp2_conn_early_data_rejected(conn); + rv = ngtcp2_conn_tls_early_data_rejected(conn); + if (rv != 0) { + rv = -1; + goto fin; + } } for (i = 0; i < 4; ++i) { @@ -399,7 +413,7 @@ int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, } if (rv == 0) { - ngtcp2_conn_handshake_completed(conn); + ngtcp2_conn_tls_handshake_completed(conn); } rv = 0; @@ -432,32 +446,32 @@ int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf, return 0; } -ngtcp2_crypto_level ngtcp2_crypto_picotls_from_epoch(size_t epoch) { +ngtcp2_encryption_level ngtcp2_crypto_picotls_from_epoch(size_t epoch) { switch (epoch) { case 0: - return NGTCP2_CRYPTO_LEVEL_INITIAL; + return NGTCP2_ENCRYPTION_LEVEL_INITIAL; case 1: - return NGTCP2_CRYPTO_LEVEL_EARLY; + return NGTCP2_ENCRYPTION_LEVEL_0RTT; case 2: - return NGTCP2_CRYPTO_LEVEL_HANDSHAKE; + return NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE; case 3: - return NGTCP2_CRYPTO_LEVEL_APPLICATION; + return NGTCP2_ENCRYPTION_LEVEL_1RTT; default: assert(0); abort(); } } -size_t ngtcp2_crypto_picotls_from_ngtcp2_crypto_level( - ngtcp2_crypto_level crypto_level) { - switch (crypto_level) { - case NGTCP2_CRYPTO_LEVEL_INITIAL: +size_t ngtcp2_crypto_picotls_from_ngtcp2_encryption_level( + ngtcp2_encryption_level encryption_level) { + switch (encryption_level) { + case NGTCP2_ENCRYPTION_LEVEL_INITIAL: return 0; - case NGTCP2_CRYPTO_LEVEL_EARLY: + case NGTCP2_ENCRYPTION_LEVEL_0RTT: return 1; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: return 2; - case NGTCP2_CRYPTO_LEVEL_APPLICATION: + case NGTCP2_ENCRYPTION_LEVEL_1RTT: return 3; default: assert(0); @@ -543,8 +557,8 @@ int ngtcp2_crypto_picotls_collected_extensions( conn_ref = *ptls_get_data_ptr(ptls); conn = conn_ref->get_conn(conn_ref); - rv = ngtcp2_conn_decode_remote_transport_params(conn, extensions->data.base, - extensions->data.len); + rv = ngtcp2_conn_decode_and_set_remote_transport_params( + conn, extensions->data.base, extensions->data.len); if (rv != 0) { ngtcp2_conn_set_tls_error(conn, rv); return -1; @@ -561,7 +575,7 @@ static int update_traffic_key_server_cb(ptls_update_traffic_key_t *self, const void *secret) { ngtcp2_crypto_conn_ref *conn_ref = *ptls_get_data_ptr(ptls); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); - ngtcp2_crypto_level level = ngtcp2_crypto_picotls_from_epoch(epoch); + ngtcp2_encryption_level level = ngtcp2_crypto_picotls_from_epoch(epoch); ptls_cipher_suite_t *cipher = ptls_get_cipher(ptls); size_t secretlen = cipher->hash->digest_size; ngtcp2_crypto_picotls_ctx *cptls; @@ -574,7 +588,7 @@ static int update_traffic_key_server_cb(ptls_update_traffic_key_t *self, return -1; } - if (level == NGTCP2_CRYPTO_LEVEL_HANDSHAKE) { + if (level == NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE) { /* libngtcp2 allows an application to change QUIC transport * parameters before installing Handshake tx key. We need to * wait for the key to get the correct local transport @@ -606,7 +620,7 @@ static int update_traffic_key_cb(ptls_update_traffic_key_t *self, ptls_t *ptls, int is_enc, size_t epoch, const void *secret) { ngtcp2_crypto_conn_ref *conn_ref = *ptls_get_data_ptr(ptls); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); - ngtcp2_crypto_level level = ngtcp2_crypto_picotls_from_epoch(epoch); + ngtcp2_encryption_level level = ngtcp2_crypto_picotls_from_epoch(epoch); ptls_cipher_suite_t *cipher = ptls_get_cipher(ptls); size_t secretlen = cipher->hash->digest_size; @@ -660,7 +674,7 @@ int ngtcp2_crypto_picotls_configure_client_session( ngtcp2_crypto_picotls_ctx *cptls, ngtcp2_conn *conn) { ptls_handshake_properties_t *hsprops = &cptls->handshake_properties; - hsprops->client.max_early_data_size = calloc(1, sizeof(uint32_t)); + hsprops->client.max_early_data_size = calloc(1, sizeof(size_t)); if (hsprops->client.max_early_data_size == NULL) { return -1; } diff --git a/deps/ngtcp2/ngtcp2/crypto/openssl/openssl.c b/deps/ngtcp2/ngtcp2/crypto/quictls/quictls.c similarity index 73% rename from deps/ngtcp2/ngtcp2/crypto/openssl/openssl.c rename to deps/ngtcp2/ngtcp2/crypto/quictls/quictls.c index 466d9e11ca6415..330ca687b44666 100644 --- a/deps/ngtcp2/ngtcp2/crypto/openssl/openssl.c +++ b/deps/ngtcp2/ngtcp2/crypto/quictls/quictls.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -42,6 +42,168 @@ #include "shared.h" +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +static int crypto_initialized; +static EVP_CIPHER *crypto_aes_128_gcm; +static EVP_CIPHER *crypto_aes_256_gcm; +static EVP_CIPHER *crypto_chacha20_poly1305; +static EVP_CIPHER *crypto_aes_128_ccm; +static EVP_CIPHER *crypto_aes_128_ctr; +static EVP_CIPHER *crypto_aes_256_ctr; +static EVP_CIPHER *crypto_chacha20; +static EVP_MD *crypto_sha256; +static EVP_MD *crypto_sha384; +static EVP_KDF *crypto_hkdf; + +int ngtcp2_crypto_quictls_init(void) { + crypto_aes_128_gcm = EVP_CIPHER_fetch(NULL, "AES-128-GCM", NULL); + if (crypto_aes_128_gcm == NULL) { + return -1; + } + + crypto_aes_256_gcm = EVP_CIPHER_fetch(NULL, "AES-256-GCM", NULL); + if (crypto_aes_256_gcm == NULL) { + return -1; + } + + crypto_chacha20_poly1305 = EVP_CIPHER_fetch(NULL, "ChaCha20-Poly1305", NULL); + if (crypto_chacha20_poly1305 == NULL) { + return -1; + } + + crypto_aes_128_ccm = EVP_CIPHER_fetch(NULL, "AES-128-CCM", NULL); + if (crypto_aes_128_ccm == NULL) { + return -1; + } + + crypto_aes_128_ctr = EVP_CIPHER_fetch(NULL, "AES-128-CTR", NULL); + if (crypto_aes_128_ctr == NULL) { + return -1; + } + + crypto_aes_256_ctr = EVP_CIPHER_fetch(NULL, "AES-256-CTR", NULL); + if (crypto_aes_256_ctr == NULL) { + return -1; + } + + crypto_chacha20 = EVP_CIPHER_fetch(NULL, "ChaCha20", NULL); + if (crypto_chacha20 == NULL) { + return -1; + } + + crypto_sha256 = EVP_MD_fetch(NULL, "sha256", NULL); + if (crypto_sha256 == NULL) { + return -1; + } + + crypto_sha384 = EVP_MD_fetch(NULL, "sha384", NULL); + if (crypto_sha384 == NULL) { + return -1; + } + + crypto_hkdf = EVP_KDF_fetch(NULL, "hkdf", NULL); + if (crypto_hkdf == NULL) { + return -1; + } + + crypto_initialized = 1; + + return 0; +} + +static const EVP_CIPHER *crypto_aead_aes_128_gcm(void) { + if (crypto_aes_128_gcm) { + return crypto_aes_128_gcm; + } + + return EVP_aes_128_gcm(); +} + +static const EVP_CIPHER *crypto_aead_aes_256_gcm(void) { + if (crypto_aes_256_gcm) { + return crypto_aes_256_gcm; + } + + return EVP_aes_256_gcm(); +} + +static const EVP_CIPHER *crypto_aead_chacha20_poly1305(void) { + if (crypto_chacha20_poly1305) { + return crypto_chacha20_poly1305; + } + + return EVP_chacha20_poly1305(); +} + +static const EVP_CIPHER *crypto_aead_aes_128_ccm(void) { + if (crypto_aes_128_ccm) { + return crypto_aes_128_ccm; + } + + return EVP_aes_128_ccm(); +} + +static const EVP_CIPHER *crypto_cipher_aes_128_ctr(void) { + if (crypto_aes_128_ctr) { + return crypto_aes_128_ctr; + } + + return EVP_aes_128_ctr(); +} + +static const EVP_CIPHER *crypto_cipher_aes_256_ctr(void) { + if (crypto_aes_256_ctr) { + return crypto_aes_256_ctr; + } + + return EVP_aes_256_ctr(); +} + +static const EVP_CIPHER *crypto_cipher_chacha20(void) { + if (crypto_chacha20) { + return crypto_chacha20; + } + + return EVP_chacha20(); +} + +static const EVP_MD *crypto_md_sha256(void) { + if (crypto_sha256) { + return crypto_sha256; + } + + return EVP_sha256(); +} + +static const EVP_MD *crypto_md_sha384(void) { + if (crypto_sha384) { + return crypto_sha384; + } + + return EVP_sha384(); +} + +static EVP_KDF *crypto_kdf_hkdf(void) { + if (crypto_hkdf) { + return crypto_hkdf; + } + + return EVP_KDF_fetch(NULL, "hkdf", NULL); +} +#else /* !(OPENSSL_VERSION_NUMBER >= 0x30000000L) */ +# define crypto_aead_aes_128_gcm EVP_aes_128_gcm +# define crypto_aead_aes_256_gcm EVP_aes_256_gcm +# define crypto_aead_chacha20_poly1305 EVP_chacha20_poly1305 +# define crypto_aead_aes_128_ccm EVP_aes_128_ccm +# define crypto_cipher_aes_128_ctr EVP_aes_128_ctr +# define crypto_cipher_aes_256_ctr EVP_aes_256_ctr +# define crypto_cipher_chacha20 EVP_chacha20 +# define crypto_md_sha256 EVP_sha256 +# define crypto_md_sha384 EVP_sha384 + +int ngtcp2_crypto_quictls_init(void) { return 0; } +#endif /* !(OPENSSL_VERSION_NUMBER >= 0x30000000L) */ + static size_t crypto_aead_max_overhead(const EVP_CIPHER *aead) { switch (EVP_CIPHER_nid(aead)) { case NID_aes_128_gcm: @@ -58,18 +220,18 @@ static size_t crypto_aead_max_overhead(const EVP_CIPHER *aead) { } ngtcp2_crypto_aead *ngtcp2_crypto_aead_aes_128_gcm(ngtcp2_crypto_aead *aead) { - return ngtcp2_crypto_aead_init(aead, (void *)EVP_aes_128_gcm()); + return ngtcp2_crypto_aead_init(aead, (void *)crypto_aead_aes_128_gcm()); } ngtcp2_crypto_md *ngtcp2_crypto_md_sha256(ngtcp2_crypto_md *md) { - md->native_handle = (void *)EVP_sha256(); + md->native_handle = (void *)crypto_md_sha256(); return md; } ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx *ctx) { - ngtcp2_crypto_aead_init(&ctx->aead, (void *)EVP_aes_128_gcm()); - ctx->md.native_handle = (void *)EVP_sha256(); - ctx->hp.native_handle = (void *)EVP_aes_128_ctr(); + ngtcp2_crypto_aead_init(&ctx->aead, (void *)crypto_aead_aes_128_gcm()); + ctx->md.native_handle = (void *)crypto_md_sha256(); + ctx->hp.native_handle = (void *)crypto_cipher_aes_128_ctr(); ctx->max_encryption = 0; ctx->max_decryption_failure = 0; return ctx; @@ -83,26 +245,26 @@ ngtcp2_crypto_aead *ngtcp2_crypto_aead_init(ngtcp2_crypto_aead *aead, } ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead) { - return ngtcp2_crypto_aead_init(aead, (void *)EVP_aes_128_gcm()); + return ngtcp2_crypto_aead_init(aead, (void *)crypto_aead_aes_128_gcm()); } -static const EVP_CIPHER *crypto_ssl_get_aead(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static const EVP_CIPHER *crypto_cipher_id_get_aead(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_3_CK_AES_128_GCM_SHA256: - return EVP_aes_128_gcm(); + return crypto_aead_aes_128_gcm(); case TLS1_3_CK_AES_256_GCM_SHA384: - return EVP_aes_256_gcm(); + return crypto_aead_aes_256_gcm(); case TLS1_3_CK_CHACHA20_POLY1305_SHA256: - return EVP_chacha20_poly1305(); + return crypto_aead_chacha20_poly1305(); case TLS1_3_CK_AES_128_CCM_SHA256: - return EVP_aes_128_ccm(); + return crypto_aead_aes_128_ccm(); default: return NULL; } } -static uint64_t crypto_ssl_get_aead_max_encryption(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static uint64_t crypto_cipher_id_get_aead_max_encryption(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_3_CK_AES_128_GCM_SHA256: case TLS1_3_CK_AES_256_GCM_SHA384: return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM; @@ -115,8 +277,9 @@ static uint64_t crypto_ssl_get_aead_max_encryption(SSL *ssl) { } } -static uint64_t crypto_ssl_get_aead_max_decryption_failure(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static uint64_t +crypto_cipher_id_get_aead_max_decryption_failure(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_3_CK_AES_128_GCM_SHA256: case TLS1_3_CK_AES_256_GCM_SHA384: return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM; @@ -129,42 +292,75 @@ static uint64_t crypto_ssl_get_aead_max_decryption_failure(SSL *ssl) { } } -static const EVP_CIPHER *crypto_ssl_get_hp(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static const EVP_CIPHER *crypto_cipher_id_get_hp(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_3_CK_AES_128_GCM_SHA256: case TLS1_3_CK_AES_128_CCM_SHA256: - return EVP_aes_128_ctr(); + return crypto_cipher_aes_128_ctr(); case TLS1_3_CK_AES_256_GCM_SHA384: - return EVP_aes_256_ctr(); + return crypto_cipher_aes_256_ctr(); case TLS1_3_CK_CHACHA20_POLY1305_SHA256: - return EVP_chacha20(); + return crypto_cipher_chacha20(); default: return NULL; } } -static const EVP_MD *crypto_ssl_get_md(SSL *ssl) { - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { +static const EVP_MD *crypto_cipher_id_get_md(uint32_t cipher_id) { + switch (cipher_id) { case TLS1_3_CK_AES_128_GCM_SHA256: case TLS1_3_CK_CHACHA20_POLY1305_SHA256: case TLS1_3_CK_AES_128_CCM_SHA256: - return EVP_sha256(); + return crypto_md_sha256(); case TLS1_3_CK_AES_256_GCM_SHA384: - return EVP_sha384(); + return crypto_md_sha384(); default: return NULL; } } +static int supported_cipher_id(uint32_t cipher_id) { + switch (cipher_id) { + case TLS1_3_CK_AES_128_GCM_SHA256: + case TLS1_3_CK_AES_256_GCM_SHA384: + case TLS1_3_CK_CHACHA20_POLY1305_SHA256: + case TLS1_3_CK_AES_128_CCM_SHA256: + return 1; + default: + return 0; + } +} + +static ngtcp2_crypto_ctx *crypto_ctx_cipher_id(ngtcp2_crypto_ctx *ctx, + uint32_t cipher_id) { + ngtcp2_crypto_aead_init(&ctx->aead, + (void *)crypto_cipher_id_get_aead(cipher_id)); + ctx->md.native_handle = (void *)crypto_cipher_id_get_md(cipher_id); + ctx->hp.native_handle = (void *)crypto_cipher_id_get_hp(cipher_id); + ctx->max_encryption = crypto_cipher_id_get_aead_max_encryption(cipher_id); + ctx->max_decryption_failure = + crypto_cipher_id_get_aead_max_decryption_failure(cipher_id); + + return ctx; +} + ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, void *tls_native_handle) { SSL *ssl = tls_native_handle; - ngtcp2_crypto_aead_init(&ctx->aead, (void *)crypto_ssl_get_aead(ssl)); - ctx->md.native_handle = (void *)crypto_ssl_get_md(ssl); - ctx->hp.native_handle = (void *)crypto_ssl_get_hp(ssl); - ctx->max_encryption = crypto_ssl_get_aead_max_encryption(ssl); - ctx->max_decryption_failure = crypto_ssl_get_aead_max_decryption_failure(ssl); - return ctx; + const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); + uint32_t cipher_id; + + if (cipher == NULL) { + return NULL; + } + + cipher_id = (uint32_t)SSL_CIPHER_get_id(cipher); + + if (!supported_cipher_id(cipher_id)) { + return NULL; + } + + return crypto_ctx_cipher_id(ctx, cipher_id); } ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls_early(ngtcp2_crypto_ctx *ctx, @@ -327,7 +523,7 @@ int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md, const uint8_t *salt, size_t saltlen) { #if OPENSSL_VERSION_NUMBER >= 0x30000000L const EVP_MD *prf = md->native_handle; - EVP_KDF *kdf = EVP_KDF_fetch(NULL, "hkdf", NULL); + EVP_KDF *kdf = crypto_kdf_hkdf(); EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf); int mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY; OSSL_PARAM params[] = { @@ -342,7 +538,9 @@ int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md, }; int rv = 0; - EVP_KDF_free(kdf); + if (!crypto_initialized) { + EVP_KDF_free(kdf); + } if (EVP_KDF_derive(kctx, dest, (size_t)EVP_MD_size(prf), params) <= 0) { rv = -1; @@ -382,7 +580,7 @@ int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen, size_t infolen) { #if OPENSSL_VERSION_NUMBER >= 0x30000000L const EVP_MD *prf = md->native_handle; - EVP_KDF *kdf = EVP_KDF_fetch(NULL, "hkdf", NULL); + EVP_KDF *kdf = crypto_kdf_hkdf(); EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf); int mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY; OSSL_PARAM params[] = { @@ -397,7 +595,9 @@ int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen, }; int rv = 0; - EVP_KDF_free(kdf); + if (!crypto_initialized) { + EVP_KDF_free(kdf); + } if (EVP_KDF_derive(kctx, dest, destlen, params) <= 0) { rv = -1; @@ -436,7 +636,7 @@ int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen, const uint8_t *info, size_t infolen) { #if OPENSSL_VERSION_NUMBER >= 0x30000000L const EVP_MD *prf = md->native_handle; - EVP_KDF *kdf = EVP_KDF_fetch(NULL, "hkdf", NULL); + EVP_KDF *kdf = crypto_kdf_hkdf(); EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf); OSSL_PARAM params[] = { OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, @@ -451,7 +651,9 @@ int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen, }; int rv = 0; - EVP_KDF_free(kdf); + if (!crypto_initialized) { + EVP_KDF_free(kdf); + } if (EVP_KDF_derive(kctx, dest, destlen, params) <= 0) { rv = -1; @@ -591,15 +793,16 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, return 0; } -int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, - const uint8_t *data, size_t datalen) { +int ngtcp2_crypto_read_write_crypto_data( + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, + const uint8_t *data, size_t datalen) { SSL *ssl = ngtcp2_conn_get_tls_native_handle(conn); int rv; int err; if (SSL_provide_quic_data( - ssl, ngtcp2_crypto_openssl_from_ngtcp2_crypto_level(crypto_level), + ssl, + ngtcp2_crypto_quictls_from_ngtcp2_encryption_level(encryption_level), data, datalen) != 1) { return -1; } @@ -613,9 +816,9 @@ int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, case SSL_ERROR_WANT_WRITE: return 0; case SSL_ERROR_WANT_CLIENT_HELLO_CB: - return NGTCP2_CRYPTO_OPENSSL_ERR_TLS_WANT_CLIENT_HELLO_CB; + return NGTCP2_CRYPTO_QUICTLS_ERR_TLS_WANT_CLIENT_HELLO_CB; case SSL_ERROR_WANT_X509_LOOKUP: - return NGTCP2_CRYPTO_OPENSSL_ERR_TLS_WANT_X509_LOOKUP; + return NGTCP2_CRYPTO_QUICTLS_ERR_TLS_WANT_X509_LOOKUP; case SSL_ERROR_SSL: return -1; default: @@ -623,7 +826,7 @@ int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, } } - ngtcp2_conn_handshake_completed(conn); + ngtcp2_conn_tls_handshake_completed(conn); } rv = SSL_process_quic_post_handshake(ssl); @@ -652,7 +855,7 @@ int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls) { SSL_get_peer_quic_transport_params(ssl, &tp, &tplen); - rv = ngtcp2_conn_decode_remote_transport_params(conn, tp, tplen); + rv = ngtcp2_conn_decode_and_set_remote_transport_params(conn, tp, tplen); if (rv != 0) { ngtcp2_conn_set_tls_error(conn, rv); return -1; @@ -670,17 +873,17 @@ int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf, return 0; } -ngtcp2_crypto_level ngtcp2_crypto_openssl_from_ossl_encryption_level( +ngtcp2_encryption_level ngtcp2_crypto_quictls_from_ossl_encryption_level( OSSL_ENCRYPTION_LEVEL ossl_level) { switch (ossl_level) { case ssl_encryption_initial: - return NGTCP2_CRYPTO_LEVEL_INITIAL; + return NGTCP2_ENCRYPTION_LEVEL_INITIAL; case ssl_encryption_early_data: - return NGTCP2_CRYPTO_LEVEL_EARLY; + return NGTCP2_ENCRYPTION_LEVEL_0RTT; case ssl_encryption_handshake: - return NGTCP2_CRYPTO_LEVEL_HANDSHAKE; + return NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE; case ssl_encryption_application: - return NGTCP2_CRYPTO_LEVEL_APPLICATION; + return NGTCP2_ENCRYPTION_LEVEL_1RTT; default: assert(0); abort(); /* if NDEBUG is set */ @@ -688,16 +891,16 @@ ngtcp2_crypto_level ngtcp2_crypto_openssl_from_ossl_encryption_level( } OSSL_ENCRYPTION_LEVEL -ngtcp2_crypto_openssl_from_ngtcp2_crypto_level( - ngtcp2_crypto_level crypto_level) { - switch (crypto_level) { - case NGTCP2_CRYPTO_LEVEL_INITIAL: +ngtcp2_crypto_quictls_from_ngtcp2_encryption_level( + ngtcp2_encryption_level encryption_level) { + switch (encryption_level) { + case NGTCP2_ENCRYPTION_LEVEL_INITIAL: return ssl_encryption_initial; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: return ssl_encryption_handshake; - case NGTCP2_CRYPTO_LEVEL_APPLICATION: + case NGTCP2_ENCRYPTION_LEVEL_1RTT: return ssl_encryption_application; - case NGTCP2_CRYPTO_LEVEL_EARLY: + case NGTCP2_ENCRYPTION_LEVEL_0RTT: return ssl_encryption_early_data; default: assert(0); @@ -730,8 +933,8 @@ static int set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, const uint8_t *tx_secret, size_t secretlen) { ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); - ngtcp2_crypto_level level = - ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); + ngtcp2_encryption_level level = + ngtcp2_crypto_quictls_from_ossl_encryption_level(ossl_level); if (rx_secret && ngtcp2_crypto_derive_and_install_rx_key(conn, NULL, NULL, NULL, level, @@ -752,8 +955,8 @@ static int add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, const uint8_t *data, size_t datalen) { ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); - ngtcp2_crypto_level level = - ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); + ngtcp2_encryption_level level = + ngtcp2_crypto_quictls_from_ossl_encryption_level(ossl_level); int rv; rv = ngtcp2_conn_submit_crypto_data(conn, level, data, datalen); @@ -786,22 +989,26 @@ static SSL_QUIC_METHOD quic_method = { add_handshake_data, flush_flight, send_alert, +#ifdef LIBRESSL_VERSION_NUMBER + NULL, + NULL, +#endif /* LIBRESSL_VERSION_NUMBER */ }; -static void crypto_openssl_configure_context(SSL_CTX *ssl_ctx) { +static void crypto_quictls_configure_context(SSL_CTX *ssl_ctx) { SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION); SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION); SSL_CTX_set_quic_method(ssl_ctx, &quic_method); } -int ngtcp2_crypto_openssl_configure_server_context(SSL_CTX *ssl_ctx) { - crypto_openssl_configure_context(ssl_ctx); +int ngtcp2_crypto_quictls_configure_server_context(SSL_CTX *ssl_ctx) { + crypto_quictls_configure_context(ssl_ctx); return 0; } -int ngtcp2_crypto_openssl_configure_client_context(SSL_CTX *ssl_ctx) { - crypto_openssl_configure_context(ssl_ctx); +int ngtcp2_crypto_quictls_configure_client_context(SSL_CTX *ssl_ctx) { + crypto_quictls_configure_context(ssl_ctx); return 0; } diff --git a/deps/ngtcp2/ngtcp2/crypto/shared.c b/deps/ngtcp2/ngtcp2/crypto/shared.c index 78252b852b4fab..162094a375cb8b 100644 --- a/deps/ngtcp2/ngtcp2/crypto/shared.c +++ b/deps/ngtcp2/ngtcp2/crypto/shared.c @@ -64,11 +64,9 @@ int ngtcp2_crypto_hkdf_expand_label(uint8_t *dest, size_t destlen, (size_t)(p - info)); } -#define NGTCP2_CRYPTO_INITIAL_SECRETLEN 32 - -int ngtcp2_crypto_derive_initial_secrets(uint32_t version, uint8_t *rx_secret, - uint8_t *tx_secret, +int ngtcp2_crypto_derive_initial_secrets(uint8_t *rx_secret, uint8_t *tx_secret, uint8_t *initial_secret, + uint32_t version, const ngtcp2_cid *client_dcid, ngtcp2_crypto_side side) { static const uint8_t CLABEL[] = "client in"; @@ -88,16 +86,14 @@ int ngtcp2_crypto_derive_initial_secrets(uint32_t version, uint8_t *rx_secret, switch (version) { case NGTCP2_PROTO_VER_V1: + default: salt = (const uint8_t *)NGTCP2_INITIAL_SALT_V1; saltlen = sizeof(NGTCP2_INITIAL_SALT_V1) - 1; break; - case NGTCP2_PROTO_VER_V2_DRAFT: - salt = (const uint8_t *)NGTCP2_INITIAL_SALT_V2_DRAFT; - saltlen = sizeof(NGTCP2_INITIAL_SALT_V2_DRAFT) - 1; + case NGTCP2_PROTO_VER_V2: + salt = (const uint8_t *)NGTCP2_INITIAL_SALT_V2; + saltlen = sizeof(NGTCP2_INITIAL_SALT_V2) - 1; break; - default: - salt = (const uint8_t *)NGTCP2_INITIAL_SALT_DRAFT; - saltlen = sizeof(NGTCP2_INITIAL_SALT_DRAFT) - 1; } if (ngtcp2_crypto_hkdf_extract(initial_secret, &ctx.md, client_dcid->data, @@ -139,9 +135,9 @@ int ngtcp2_crypto_derive_packet_protection_key( static const uint8_t KEY_LABEL_V1[] = "quic key"; static const uint8_t IV_LABEL_V1[] = "quic iv"; static const uint8_t HP_KEY_LABEL_V1[] = "quic hp"; - static const uint8_t KEY_LABEL_V2_DRAFT[] = "quicv2 key"; - static const uint8_t IV_LABEL_V2_DRAFT[] = "quicv2 iv"; - static const uint8_t HP_KEY_LABEL_V2_DRAFT[] = "quicv2 hp"; + static const uint8_t KEY_LABEL_V2[] = "quicv2 key"; + static const uint8_t IV_LABEL_V2[] = "quicv2 iv"; + static const uint8_t HP_KEY_LABEL_V2[] = "quicv2 hp"; size_t keylen = ngtcp2_crypto_aead_keylen(aead); size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(aead); const uint8_t *key_label; @@ -152,13 +148,13 @@ int ngtcp2_crypto_derive_packet_protection_key( size_t hp_key_labellen; switch (version) { - case NGTCP2_PROTO_VER_V2_DRAFT: - key_label = KEY_LABEL_V2_DRAFT; - key_labellen = sizeof(KEY_LABEL_V2_DRAFT) - 1; - iv_label = IV_LABEL_V2_DRAFT; - iv_labellen = sizeof(IV_LABEL_V2_DRAFT) - 1; - hp_key_label = HP_KEY_LABEL_V2_DRAFT; - hp_key_labellen = sizeof(HP_KEY_LABEL_V2_DRAFT) - 1; + case NGTCP2_PROTO_VER_V2: + key_label = KEY_LABEL_V2; + key_labellen = sizeof(KEY_LABEL_V2) - 1; + iv_label = IV_LABEL_V2; + iv_labellen = sizeof(IV_LABEL_V2) - 1; + hp_key_label = HP_KEY_LABEL_V2; + hp_key_labellen = sizeof(HP_KEY_LABEL_V2) - 1; break; default: key_label = KEY_LABEL_V1; @@ -188,14 +184,27 @@ int ngtcp2_crypto_derive_packet_protection_key( return 0; } -int ngtcp2_crypto_update_traffic_secret(uint8_t *dest, +int ngtcp2_crypto_update_traffic_secret(uint8_t *dest, uint32_t version, const ngtcp2_crypto_md *md, const uint8_t *secret, size_t secretlen) { static const uint8_t LABEL[] = "quic ku"; + static const uint8_t LABEL_V2[] = "quicv2 ku"; + const uint8_t *label; + size_t labellen; + + switch (version) { + case NGTCP2_PROTO_VER_V2: + label = LABEL_V2; + labellen = sizeof(LABEL_V2) - 1; + break; + default: + label = LABEL; + labellen = sizeof(LABEL) - 1; + } if (ngtcp2_crypto_hkdf_expand_label(dest, secretlen, md, secret, secretlen, - LABEL, sizeof(LABEL) - 1) != 0) { + label, labellen) != 0) { return -1; } @@ -204,7 +213,7 @@ int ngtcp2_crypto_update_traffic_secret(uint8_t *dest, int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp_key, - ngtcp2_crypto_level level, + ngtcp2_encryption_level level, const uint8_t *secret, size_t secretlen) { const ngtcp2_crypto_ctx *ctx; @@ -220,7 +229,7 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key, ngtcp2_crypto_ctx cctx; uint32_t version; - if (level == NGTCP2_CRYPTO_LEVEL_EARLY && !ngtcp2_conn_is_server(conn)) { + if (level == NGTCP2_ENCRYPTION_LEVEL_0RTT && !ngtcp2_conn_is_server(conn)) { return 0; } @@ -235,13 +244,16 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key, } switch (level) { - case NGTCP2_CRYPTO_LEVEL_EARLY: - ngtcp2_crypto_ctx_tls_early(&cctx, tls); - ngtcp2_conn_set_early_crypto_ctx(conn, &cctx); - ctx = ngtcp2_conn_get_early_crypto_ctx(conn); + case NGTCP2_ENCRYPTION_LEVEL_0RTT: + if (ngtcp2_crypto_ctx_tls_early(&cctx, tls) == NULL) { + return -1; + } + + ngtcp2_conn_set_0rtt_crypto_ctx(conn, &cctx); + ctx = ngtcp2_conn_get_0rtt_crypto_ctx(conn); version = ngtcp2_conn_get_client_chosen_version(conn); break; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: if (ngtcp2_conn_is_server(conn) && !ngtcp2_conn_get_negotiated_version(conn)) { rv = ngtcp2_crypto_set_remote_transport_params(conn, tls); @@ -250,15 +262,21 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key, } } /* fall through */ - default: + case NGTCP2_ENCRYPTION_LEVEL_1RTT: ctx = ngtcp2_conn_get_crypto_ctx(conn); version = ngtcp2_conn_get_negotiated_version(conn); if (!ctx->aead.native_handle) { - ngtcp2_crypto_ctx_tls(&cctx, tls); + if (ngtcp2_crypto_ctx_tls(&cctx, tls) == NULL) { + return -1; + } + ngtcp2_conn_set_crypto_ctx(conn, &cctx); ctx = ngtcp2_conn_get_crypto_ctx(conn); } + break; + default: + return -1; } aead = &ctx->aead; @@ -280,20 +298,20 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key, } switch (level) { - case NGTCP2_CRYPTO_LEVEL_EARLY: - rv = ngtcp2_conn_install_early_key(conn, &aead_ctx, iv, ivlen, &hp_ctx); + case NGTCP2_ENCRYPTION_LEVEL_0RTT: + rv = ngtcp2_conn_install_0rtt_key(conn, &aead_ctx, iv, ivlen, &hp_ctx); if (rv != 0) { goto fail; } break; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: rv = ngtcp2_conn_install_rx_handshake_key(conn, &aead_ctx, iv, ivlen, &hp_ctx); if (rv != 0) { goto fail; } break; - case NGTCP2_CRYPTO_LEVEL_APPLICATION: + case NGTCP2_ENCRYPTION_LEVEL_1RTT: if (!ngtcp2_conn_is_server(conn)) { rv = ngtcp2_crypto_set_remote_transport_params(conn, tls); if (rv != 0) { @@ -345,7 +363,7 @@ static int crypto_set_local_transport_params(ngtcp2_conn *conn, void *tls) { int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp_key, - ngtcp2_crypto_level level, + ngtcp2_encryption_level level, const uint8_t *secret, size_t secretlen) { const ngtcp2_crypto_ctx *ctx; @@ -361,7 +379,7 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, ngtcp2_crypto_ctx cctx; uint32_t version; - if (level == NGTCP2_CRYPTO_LEVEL_EARLY && ngtcp2_conn_is_server(conn)) { + if (level == NGTCP2_ENCRYPTION_LEVEL_0RTT && ngtcp2_conn_is_server(conn)) { return 0; } @@ -376,13 +394,16 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, } switch (level) { - case NGTCP2_CRYPTO_LEVEL_EARLY: - ngtcp2_crypto_ctx_tls_early(&cctx, tls); - ngtcp2_conn_set_early_crypto_ctx(conn, &cctx); - ctx = ngtcp2_conn_get_early_crypto_ctx(conn); + case NGTCP2_ENCRYPTION_LEVEL_0RTT: + if (ngtcp2_crypto_ctx_tls_early(&cctx, tls) == NULL) { + return -1; + } + + ngtcp2_conn_set_0rtt_crypto_ctx(conn, &cctx); + ctx = ngtcp2_conn_get_0rtt_crypto_ctx(conn); version = ngtcp2_conn_get_client_chosen_version(conn); break; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: if (ngtcp2_conn_is_server(conn) && !ngtcp2_conn_get_negotiated_version(conn)) { rv = ngtcp2_crypto_set_remote_transport_params(conn, tls); @@ -391,15 +412,21 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, } } /* fall through */ - default: + case NGTCP2_ENCRYPTION_LEVEL_1RTT: ctx = ngtcp2_conn_get_crypto_ctx(conn); version = ngtcp2_conn_get_negotiated_version(conn); if (!ctx->aead.native_handle) { - ngtcp2_crypto_ctx_tls(&cctx, tls); + if (ngtcp2_crypto_ctx_tls(&cctx, tls) == NULL) { + return -1; + } + ngtcp2_conn_set_crypto_ctx(conn, &cctx); ctx = ngtcp2_conn_get_crypto_ctx(conn); } + break; + default: + return -1; } aead = &ctx->aead; @@ -421,13 +448,13 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, } switch (level) { - case NGTCP2_CRYPTO_LEVEL_EARLY: - rv = ngtcp2_conn_install_early_key(conn, &aead_ctx, iv, ivlen, &hp_ctx); + case NGTCP2_ENCRYPTION_LEVEL_0RTT: + rv = ngtcp2_conn_install_0rtt_key(conn, &aead_ctx, iv, ivlen, &hp_ctx); if (rv != 0) { goto fail; } break; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: rv = ngtcp2_conn_install_tx_handshake_key(conn, &aead_ctx, iv, ivlen, &hp_ctx); if (rv != 0) { @@ -440,7 +467,7 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, } break; - case NGTCP2_CRYPTO_LEVEL_APPLICATION: + case NGTCP2_ENCRYPTION_LEVEL_1RTT: rv = ngtcp2_conn_install_tx_key(conn, secret, secretlen, &aead_ctx, iv, ivlen, &hp_ctx); if (rv != 0) { @@ -521,7 +548,7 @@ int ngtcp2_crypto_derive_and_install_initial_key( ngtcp2_conn_set_initial_crypto_ctx(conn, &ctx); if (ngtcp2_crypto_derive_initial_secrets( - version, rx_secret, tx_secret, initial_secret, client_dcid, + rx_secret, tx_secret, initial_secret, version, client_dcid, server ? NGTCP2_CRYPTO_SIDE_SERVER : NGTCP2_CRYPTO_SIDE_CLIENT) != 0) { return -1; @@ -564,16 +591,14 @@ int ngtcp2_crypto_derive_and_install_initial_key( switch (version) { case NGTCP2_PROTO_VER_V1: + default: retry_key = (const uint8_t *)NGTCP2_RETRY_KEY_V1; retry_noncelen = sizeof(NGTCP2_RETRY_NONCE_V1) - 1; break; - case NGTCP2_PROTO_VER_V2_DRAFT: - retry_key = (const uint8_t *)NGTCP2_RETRY_KEY_V2_DRAFT; - retry_noncelen = sizeof(NGTCP2_RETRY_NONCE_V2_DRAFT) - 1; + case NGTCP2_PROTO_VER_V2: + retry_key = (const uint8_t *)NGTCP2_RETRY_KEY_V2; + retry_noncelen = sizeof(NGTCP2_RETRY_NONCE_V2) - 1; break; - default: - retry_key = (const uint8_t *)NGTCP2_RETRY_KEY_DRAFT; - retry_noncelen = sizeof(NGTCP2_RETRY_NONCE_DRAFT) - 1; } if (ngtcp2_crypto_aead_ctx_encrypt_init(&retry_aead_ctx, &retry_aead, @@ -657,7 +682,7 @@ int ngtcp2_crypto_derive_and_install_vneg_initial_key( } if (ngtcp2_crypto_derive_initial_secrets( - version, rx_secret, tx_secret, initial_secret, client_dcid, + rx_secret, tx_secret, initial_secret, version, client_dcid, server ? NGTCP2_CRYPTO_SIDE_SERVER : NGTCP2_CRYPTO_SIDE_CLIENT) != 0) { return -1; @@ -725,8 +750,8 @@ int ngtcp2_crypto_update_key( size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(aead); uint32_t version = ngtcp2_conn_get_negotiated_version(conn); - if (ngtcp2_crypto_update_traffic_secret(rx_secret, md, current_rx_secret, - secretlen) != 0) { + if (ngtcp2_crypto_update_traffic_secret(rx_secret, version, md, + current_rx_secret, secretlen) != 0) { return -1; } @@ -735,8 +760,8 @@ int ngtcp2_crypto_update_key( return -1; } - if (ngtcp2_crypto_update_traffic_secret(tx_secret, md, current_tx_secret, - secretlen) != 0) { + if (ngtcp2_crypto_update_traffic_secret(tx_secret, version, md, + current_tx_secret, secretlen) != 0) { return -1; } @@ -883,6 +908,7 @@ static size_t crypto_generate_retry_token_aad(uint8_t *dest, uint32_t version, version = ngtcp2_htonl(version); memcpy(p, &version, sizeof(version)); + p += sizeof(version); memcpy(p, sa, (size_t)salen); p += salen; memcpy(p, retry_scid->data, retry_scid->datalen); @@ -907,13 +933,15 @@ ngtcp2_ssize ngtcp2_crypto_generate_retry_token( ngtcp2_crypto_md md; ngtcp2_crypto_aead_ctx aead_ctx; size_t plaintextlen; - uint8_t aad[sizeof(version) + sizeof(ngtcp2_sockaddr_storage) + - NGTCP2_MAX_CIDLEN]; + uint8_t + aad[sizeof(version) + sizeof(ngtcp2_sockaddr_union) + NGTCP2_MAX_CIDLEN]; size_t aadlen; uint8_t *p = plaintext; ngtcp2_tstamp ts_be = ngtcp2_htonl64(ts); int rv; + assert((size_t)remote_addrlen <= sizeof(ngtcp2_sockaddr_union)); + memset(plaintext, 0, sizeof(plaintext)); *p++ = (uint8_t)odcid->datalen; @@ -984,8 +1012,8 @@ int ngtcp2_crypto_verify_retry_token( ngtcp2_crypto_aead_ctx aead_ctx; ngtcp2_crypto_aead aead; ngtcp2_crypto_md md; - uint8_t aad[sizeof(version) + sizeof(ngtcp2_sockaddr_storage) + - NGTCP2_MAX_CIDLEN]; + uint8_t + aad[sizeof(version) + sizeof(ngtcp2_sockaddr_union) + NGTCP2_MAX_CIDLEN]; size_t aadlen; const uint8_t *rand_data; const uint8_t *ciphertext; @@ -994,6 +1022,8 @@ int ngtcp2_crypto_verify_retry_token( int rv; ngtcp2_tstamp gen_ts; + assert((size_t)remote_addrlen <= sizeof(ngtcp2_sockaddr_union)); + if (tokenlen != NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN || token[0] != NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY) { return -1; @@ -1034,7 +1064,9 @@ int ngtcp2_crypto_verify_retry_token( cil = plaintext[0]; - assert(cil == 0 || (cil >= NGTCP2_MIN_CIDLEN && cil <= NGTCP2_MAX_CIDLEN)); + if (cil != 0 && (cil < NGTCP2_MIN_CIDLEN || cil > NGTCP2_MAX_CIDLEN)) { + return -1; + } memcpy(&gen_ts, plaintext + /* cid len = */ 1 + NGTCP2_MAX_CIDLEN, sizeof(gen_ts)); @@ -1055,11 +1087,11 @@ static size_t crypto_generate_regular_token_aad(uint8_t *dest, size_t addrlen; switch (sa->sa_family) { - case AF_INET: + case NGTCP2_AF_INET: addr = (const uint8_t *)&((const ngtcp2_sockaddr_in *)(void *)sa)->sin_addr; addrlen = sizeof(((const ngtcp2_sockaddr_in *)(void *)sa)->sin_addr); break; - case AF_INET6: + case NGTCP2_AF_INET6: addr = (const uint8_t *)&((const ngtcp2_sockaddr_in6 *)(void *)sa)->sin6_addr; addrlen = sizeof(((const ngtcp2_sockaddr_in6 *)(void *)sa)->sin6_addr); @@ -1234,8 +1266,8 @@ ngtcp2_ssize ngtcp2_crypto_write_connection_close( ngtcp2_crypto_ctx_initial(&ctx); - if (ngtcp2_crypto_derive_initial_secrets(version, rx_secret, tx_secret, - initial_secret, scid, + if (ngtcp2_crypto_derive_initial_secrets(rx_secret, tx_secret, initial_secret, + version, scid, NGTCP2_CRYPTO_SIDE_SERVER) != 0) { return -1; } @@ -1287,16 +1319,14 @@ ngtcp2_ssize ngtcp2_crypto_write_retry(uint8_t *dest, size_t destlen, switch (version) { case NGTCP2_PROTO_VER_V1: + default: key = (const uint8_t *)NGTCP2_RETRY_KEY_V1; noncelen = sizeof(NGTCP2_RETRY_NONCE_V1) - 1; break; - case NGTCP2_PROTO_VER_V2_DRAFT: - key = (const uint8_t *)NGTCP2_RETRY_KEY_V2_DRAFT; - noncelen = sizeof(NGTCP2_RETRY_NONCE_V2_DRAFT) - 1; + case NGTCP2_PROTO_VER_V2: + key = (const uint8_t *)NGTCP2_RETRY_KEY_V2; + noncelen = sizeof(NGTCP2_RETRY_NONCE_V2) - 1; break; - default: - key = (const uint8_t *)NGTCP2_RETRY_KEY_DRAFT; - noncelen = sizeof(NGTCP2_RETRY_NONCE_DRAFT) - 1; } if (ngtcp2_crypto_aead_ctx_encrypt_init(&aead_ctx, &aead, key, noncelen) != @@ -1331,8 +1361,8 @@ int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn, void *user_data) { return NGTCP2_ERR_CALLBACK_FAILURE; } - if (ngtcp2_crypto_read_write_crypto_data(conn, NGTCP2_CRYPTO_LEVEL_INITIAL, - NULL, 0) != 0) { + if (ngtcp2_crypto_read_write_crypto_data( + conn, NGTCP2_ENCRYPTION_LEVEL_INITIAL, NULL, 0) != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -1398,15 +1428,15 @@ void ngtcp2_crypto_delete_crypto_cipher_ctx_cb( } int ngtcp2_crypto_recv_crypto_data_cb(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, + ngtcp2_encryption_level encryption_level, uint64_t offset, const uint8_t *data, size_t datalen, void *user_data) { int rv; (void)offset; (void)user_data; - if (ngtcp2_crypto_read_write_crypto_data(conn, crypto_level, data, datalen) != - 0) { + if (ngtcp2_crypto_read_write_crypto_data(conn, encryption_level, data, + datalen) != 0) { rv = ngtcp2_conn_get_tls_error(conn); if (rv) { return rv; diff --git a/deps/ngtcp2/ngtcp2/crypto/shared.h b/deps/ngtcp2/ngtcp2/crypto/shared.h index 02b948901ae40e..d69fd21212d7d2 100644 --- a/deps/ngtcp2/ngtcp2/crypto/shared.h +++ b/deps/ngtcp2/ngtcp2/crypto/shared.h @@ -31,16 +31,6 @@ #include -/** - * @macro - * - * :macro:`NGTCP2_INITIAL_SALT_DRAFT` is a salt value which is used to - * derive initial secret. It is used for QUIC draft versions. - */ -#define NGTCP2_INITIAL_SALT_DRAFT \ - "\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97\x86\xf1\x9c\x61\x11\xe0\x43\x90" \ - "\xa8\x99" - /** * @macro * @@ -54,12 +44,12 @@ /** * @macro * - * :macro:`NGTCP2_INITIAL_SALT_V2_DRAFT` is a salt value which is used to - * derive initial secret. It is used for QUIC v2 draft. + * :macro:`NGTCP2_INITIAL_SALT_V2` is a salt value which is used to + * derive initial secret. It is used for QUIC v2. */ -#define NGTCP2_INITIAL_SALT_V2_DRAFT \ - "\xa7\x07\xc2\x03\xa5\x9b\x47\x18\x4a\x1d\x62\xca\x57\x04\x06\xea\x7a\xe3" \ - "\xe5\xd3" +#define NGTCP2_INITIAL_SALT_V2 \ + "\x0d\xed\xe3\xde\xf7\x00\xa6\xdb\x81\x93\x81\xbe\x6e\x26\x9d\xcb\xf9\xbd" \ + "\x2e\xd9" /* Maximum key usage (encryption) limits */ #define NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM (1ULL << 23) @@ -72,6 +62,30 @@ #define NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305 (1ULL << 36) #define NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_CCM (2965820ULL) +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_INITIAL_SECRETLEN` is the length of secret + * for Initial packets. + */ +#define NGTCP2_CRYPTO_INITIAL_SECRETLEN 32 + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_INITIAL_KEYLEN` is the length of key for + * Initial packets. + */ +#define NGTCP2_CRYPTO_INITIAL_KEYLEN 16 + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_INITIAL_IVLEN` is the length of IV for + * Initial packets. + */ +#define NGTCP2_CRYPTO_INITIAL_IVLEN 12 + /** * @function * @@ -86,7 +100,7 @@ ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx *ctx); * `ngtcp2_crypto_aead_init` initializes |aead| with the provided * |aead_native_handle| which is an underlying AEAD object. * - * If libngtcp2_crypto_openssl is linked, |aead_native_handle| must be + * If libngtcp2_crypto_quictls is linked, |aead_native_handle| must be * a pointer to EVP_CIPHER. * * If libngtcp2_crypto_gnutls is linked, |aead_native_handle| must be @@ -106,6 +120,25 @@ ngtcp2_crypto_aead *ngtcp2_crypto_aead_init(ngtcp2_crypto_aead *aead, */ ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead); +/** + * @enum + * + * :type:`ngtcp2_crypto_side` indicates which side the application + * implements; client or server. + */ +typedef enum ngtcp2_crypto_side { + /** + * :enum:`NGTCP2_CRYPTO_SIDE_CLIENT` indicates that the application + * is client. + */ + NGTCP2_CRYPTO_SIDE_CLIENT, + /** + * :enum:`NGTCP2_CRYPTO_SIDE_SERVER` indicates that the application + * is server. + */ + NGTCP2_CRYPTO_SIDE_SERVER +} ngtcp2_crypto_side; + /** * @function * @@ -122,9 +155,9 @@ ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead); * * This function returns 0 if it succeeds, or -1. */ -int ngtcp2_crypto_derive_initial_secrets(uint32_t version, uint8_t *rx_secret, - uint8_t *tx_secret, +int ngtcp2_crypto_derive_initial_secrets(uint8_t *rx_secret, uint8_t *tx_secret, uint8_t *initial_secret, + uint32_t version, const ngtcp2_cid *client_dcid, ngtcp2_crypto_side side); @@ -168,7 +201,7 @@ int ngtcp2_crypto_derive_packet_protection_key(uint8_t *key, uint8_t *iv, * * This function returns 0 if it succeeds, or -1. */ -int ngtcp2_crypto_update_traffic_secret(uint8_t *dest, +int ngtcp2_crypto_update_traffic_secret(uint8_t *dest, uint32_t version, const ngtcp2_crypto_md *md, const uint8_t *secret, size_t secretlen); @@ -181,7 +214,7 @@ int ngtcp2_crypto_update_traffic_secret(uint8_t *dest, * pointed by |buf| of length |len|, to the native handle |tls|. * * |tls| points to a implementation dependent TLS session object. If - * libngtcp2_crypto_openssl is linked, |tls| must be a pointer to SSL + * libngtcp2_crypto_quictls is linked, |tls| must be a pointer to SSL * object. * * This function returns 0 if it succeeds, or -1. @@ -197,7 +230,7 @@ int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf, * `ngtcp2_conn_set_remote_transport_params`. * * |tls| points to a implementation dependent TLS session object. If - * libngtcp2_crypto_openssl is linked, |tls| must be a pointer to SSL + * libngtcp2_crypto_quictls is linked, |tls| must be a pointer to SSL * object. * * This function returns 0 if it succeeds, or -1. @@ -347,4 +380,18 @@ ngtcp2_crypto_aead *ngtcp2_crypto_aead_aes_128_gcm(ngtcp2_crypto_aead *aead); */ int ngtcp2_crypto_random(uint8_t *data, size_t datalen); +/** + * @function + * + * `ngtcp2_crypto_hkdf_expand_label` performs HKDF expand label. The + * result is |destlen| bytes long, and is stored to the buffer pointed + * by |dest|. + * + * This function returns 0 if it succeeds, or -1. + */ +int ngtcp2_crypto_hkdf_expand_label(uint8_t *dest, size_t destlen, + const ngtcp2_crypto_md *md, + const uint8_t *secret, size_t secretlen, + const uint8_t *label, size_t labellen); + #endif /* NGTCP2_SHARED_H */ diff --git a/deps/ngtcp2/ngtcp2/crypto/wolfssl/wolfssl.c b/deps/ngtcp2/ngtcp2/crypto/wolfssl/wolfssl.c index 9a58b9be2b76e9..2b7b5321863915 100644 --- a/deps/ngtcp2/ngtcp2/crypto/wolfssl/wolfssl.c +++ b/deps/ngtcp2/ngtcp2/crypto/wolfssl/wolfssl.c @@ -73,9 +73,8 @@ ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead) { return ngtcp2_crypto_aead_init(aead, (void *)wolfSSL_EVP_aes_128_gcm()); } -static uint64_t crypto_wolfssl_get_aead_max_encryption(WOLFSSL *ssl) { - const WOLFSSL_EVP_CIPHER *aead = wolfSSL_quic_get_aead(ssl); - +static uint64_t +crypto_aead_get_aead_max_encryption(const WOLFSSL_EVP_CIPHER *aead) { if (wolfSSL_quic_aead_is_gcm(aead)) { return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM; } @@ -88,9 +87,8 @@ static uint64_t crypto_wolfssl_get_aead_max_encryption(WOLFSSL *ssl) { return 0; } -static uint64_t crypto_wolfssl_get_aead_max_decryption_failure(WOLFSSL *ssl) { - const WOLFSSL_EVP_CIPHER *aead = wolfSSL_quic_get_aead(ssl); - +static uint64_t +crypto_aead_get_aead_max_decryption_failure(const WOLFSSL_EVP_CIPHER *aead) { if (wolfSSL_quic_aead_is_gcm(aead)) { return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM; } @@ -103,16 +101,30 @@ static uint64_t crypto_wolfssl_get_aead_max_decryption_failure(WOLFSSL *ssl) { return 0; } +static int supported_aead(const WOLFSSL_EVP_CIPHER *aead) { + return wolfSSL_quic_aead_is_gcm(aead) || + wolfSSL_quic_aead_is_chacha20(aead) || wolfSSL_quic_aead_is_ccm(aead); +} + ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, void *tls_native_handle) { WOLFSSL *ssl = tls_native_handle; + const WOLFSSL_EVP_CIPHER *aead = wolfSSL_quic_get_aead(ssl); - ngtcp2_crypto_aead_init(&ctx->aead, (void *)wolfSSL_quic_get_aead(ssl)); + if (aead == NULL) { + return NULL; + } + + if (!supported_aead(aead)) { + return NULL; + } + + ngtcp2_crypto_aead_init(&ctx->aead, (void *)aead); ctx->md.native_handle = (void *)wolfSSL_quic_get_md(ssl); ctx->hp.native_handle = (void *)wolfSSL_quic_get_hp(ssl); - ctx->max_encryption = crypto_wolfssl_get_aead_max_encryption(ssl); + ctx->max_encryption = crypto_aead_get_aead_max_encryption(aead); ctx->max_decryption_failure = - crypto_wolfssl_get_aead_max_decryption_failure(ssl); + crypto_aead_get_aead_max_decryption_failure(aead); return ctx; } @@ -211,6 +223,7 @@ int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md, const uint8_t *salt, size_t saltlen) { if (wolfSSL_quic_hkdf_extract(dest, md->native_handle, secret, secretlen, salt, saltlen) != WOLFSSL_SUCCESS) { + DEBUG_MSG("WOLFSSL: wolfSSL_quic_hkdf_extract FAILED\n"); return -1; } return 0; @@ -222,6 +235,7 @@ int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen, size_t infolen) { if (wolfSSL_quic_hkdf_expand(dest, destlen, md->native_handle, secret, secretlen, info, infolen) != WOLFSSL_SUCCESS) { + DEBUG_MSG("WOLFSSL: wolfSSL_quic_hkdf_expand FAILED\n"); return -1; } return 0; @@ -233,6 +247,7 @@ int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen, const uint8_t *info, size_t infolen) { if (wolfSSL_quic_hkdf(dest, destlen, md->native_handle, secret, secretlen, salt, saltlen, info, infolen) != WOLFSSL_SUCCESS) { + DEBUG_MSG("WOLFSSL: wolfSSL_quic_hkdf FAILED\n"); return -1; } return 0; @@ -286,18 +301,19 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, sizeof(PLAINTEXT) - 1) != WOLFSSL_SUCCESS || wolfSSL_EVP_EncryptFinal_ex(actx, dest + sizeof(PLAINTEXT) - 1, &len) != WOLFSSL_SUCCESS) { + DEBUG_MSG("WOLFSSL: hp_mask FAILED\n"); return -1; } return 0; } -int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, - const uint8_t *data, size_t datalen) { +int ngtcp2_crypto_read_write_crypto_data( + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, + const uint8_t *data, size_t datalen) { WOLFSSL *ssl = ngtcp2_conn_get_tls_native_handle(conn); WOLFSSL_ENCRYPTION_LEVEL level = - ngtcp2_crypto_wolfssl_from_ngtcp2_crypto_level(crypto_level); + ngtcp2_crypto_wolfssl_from_ngtcp2_encryption_level(encryption_level); int rv; int err; @@ -313,9 +329,9 @@ int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, if (!ngtcp2_conn_get_handshake_completed(conn)) { rv = wolfSSL_quic_do_handshake(ssl); - DEBUG_MSG("WOLFSSL: do_handshake, rv=%d\n", rv); if (rv <= 0) { err = wolfSSL_get_error(ssl, rv); + DEBUG_MSG("WOLFSSL: do_handshake, rv=%d, err=%d\n", rv, err); switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: @@ -328,7 +344,7 @@ int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, } DEBUG_MSG("WOLFSSL: handshake done\n"); - ngtcp2_conn_handshake_completed(conn); + ngtcp2_conn_tls_handshake_completed(conn); } rv = wolfSSL_process_quic_post_handshake(ssl); @@ -359,7 +375,7 @@ int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls) { wolfSSL_get_peer_quic_transport_params(ssl, &tp, &tplen); DEBUG_MSG("WOLFSSL: get peer transport params, len=%lu\n", tplen); - rv = ngtcp2_conn_decode_remote_transport_params(conn, tp, tplen); + rv = ngtcp2_conn_decode_and_set_remote_transport_params(conn, tp, tplen); if (rv != 0) { DEBUG_MSG("WOLFSSL: decode peer transport params failed, rv=%d\n", rv); ngtcp2_conn_set_tls_error(conn, rv); @@ -380,17 +396,17 @@ int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf, return 0; } -ngtcp2_crypto_level ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level( +ngtcp2_encryption_level ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level( WOLFSSL_ENCRYPTION_LEVEL wolfssl_level) { switch (wolfssl_level) { case wolfssl_encryption_initial: - return NGTCP2_CRYPTO_LEVEL_INITIAL; + return NGTCP2_ENCRYPTION_LEVEL_INITIAL; case wolfssl_encryption_early_data: - return NGTCP2_CRYPTO_LEVEL_EARLY; + return NGTCP2_ENCRYPTION_LEVEL_0RTT; case wolfssl_encryption_handshake: - return NGTCP2_CRYPTO_LEVEL_HANDSHAKE; + return NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE; case wolfssl_encryption_application: - return NGTCP2_CRYPTO_LEVEL_APPLICATION; + return NGTCP2_ENCRYPTION_LEVEL_1RTT; default: assert(0); abort(); /* if NDEBUG is set */ @@ -398,16 +414,16 @@ ngtcp2_crypto_level ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level( } WOLFSSL_ENCRYPTION_LEVEL -ngtcp2_crypto_wolfssl_from_ngtcp2_crypto_level( - ngtcp2_crypto_level crypto_level) { - switch (crypto_level) { - case NGTCP2_CRYPTO_LEVEL_INITIAL: +ngtcp2_crypto_wolfssl_from_ngtcp2_encryption_level( + ngtcp2_encryption_level encryption_level) { + switch (encryption_level) { + case NGTCP2_ENCRYPTION_LEVEL_INITIAL: return wolfssl_encryption_initial; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: return wolfssl_encryption_handshake; - case NGTCP2_CRYPTO_LEVEL_APPLICATION: + case NGTCP2_ENCRYPTION_LEVEL_1RTT: return wolfssl_encryption_application; - case NGTCP2_CRYPTO_LEVEL_EARLY: + case NGTCP2_ENCRYPTION_LEVEL_0RTT: return wolfssl_encryption_early_data; default: assert(0); @@ -441,7 +457,7 @@ static int set_encryption_secrets(WOLFSSL *ssl, const uint8_t *tx_secret, size_t secretlen) { ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); - ngtcp2_crypto_level level = + ngtcp2_encryption_level level = ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level(wolfssl_level); DEBUG_MSG("WOLFSSL: set encryption secrets, level=%d, rxlen=%lu, txlen=%lu\n", @@ -467,7 +483,7 @@ static int add_handshake_data(WOLFSSL *ssl, const uint8_t *data, size_t datalen) { ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); - ngtcp2_crypto_level level = + ngtcp2_encryption_level level = ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level(wolfssl_level); int rv; @@ -514,11 +530,17 @@ static void crypto_wolfssl_configure_context(WOLFSSL_CTX *ssl_ctx) { int ngtcp2_crypto_wolfssl_configure_server_context(WOLFSSL_CTX *ssl_ctx) { crypto_wolfssl_configure_context(ssl_ctx); +#if PRINTF_DEBUG + wolfSSL_Debugging_ON(); +#endif return 0; } int ngtcp2_crypto_wolfssl_configure_client_context(WOLFSSL_CTX *ssl_ctx) { crypto_wolfssl_configure_context(ssl_ctx); wolfSSL_CTX_UseSessionTicket(ssl_ctx); +#if PRINTF_DEBUG + wolfSSL_Debugging_ON(); +#endif return 0; } diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h index ed71cb3ea0cb37..72c8142a5a5aa7 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h @@ -54,26 +54,13 @@ # ifdef WIN32 # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN -# endif +# endif /* WIN32_LEAN_AND_MEAN */ # include -# else +# else /* !WIN32 */ # include # include -# endif -#endif - -#ifdef AF_INET -# define NGTCP2_AF_INET AF_INET -#else -# define NGTCP2_AF_INET 2 -#endif - -#ifdef AF_INET6 -# define NGTCP2_AF_INET6 AF_INET6 -#else -# define NGTCP2_AF_INET6 23 -# define NGTCP2_USE_GENERIC_IPV6_SOCKADDR -#endif +# endif /* !WIN32 */ +#endif /* NGTCP2_USE_GENERIC_SOCKADDR */ #include @@ -181,7 +168,7 @@ typedef void *(*ngtcp2_realloc)(void *ptr, size_t size, void *user_data); * * void conn_new() { * ngtcp2_mem mem = {NULL, my_malloc_cb, my_free_cb, my_calloc_cb, - * my_realloc_cb}; + * my_realloc_cb}; * * ... * } @@ -223,7 +210,8 @@ typedef struct ngtcp2_mem { /** * @macro * - * :macro:`NGTCP2_SECONDS` is a count of tick which corresponds to 1 second. + * :macro:`NGTCP2_SECONDS` is a count of tick which corresponds to 1 + * second. */ #define NGTCP2_SECONDS ((ngtcp2_duration)1000000000ULL) @@ -267,34 +255,16 @@ typedef struct ngtcp2_mem { /** * @macro * - * :macro:`NGTCP2_PROTO_VER_V2_DRAFT` is the provisional version - * number for QUIC version 2 draft. - * - * https://quicwg.org/quic-v2/draft-ietf-quic-v2.html + * :macro:`NGTCP2_PROTO_VER_V2` is the QUIC version 2. See + * :rfc:`9369`. */ -#define NGTCP2_PROTO_VER_V2_DRAFT ((uint32_t)0x709a50c4u) - -/** - * @macro - * - * :macro:`NGTCP2_PROTO_VER_DRAFT_MAX` is the maximum QUIC draft - * version that this library supports. - */ -#define NGTCP2_PROTO_VER_DRAFT_MAX 0xff000020u - -/** - * @macro - * - * :macro:`NGTCP2_PROTO_VER_DRAFT_MIN` is the minimum QUIC draft - * version that this library supports. - */ -#define NGTCP2_PROTO_VER_DRAFT_MIN 0xff00001du +#define NGTCP2_PROTO_VER_V2 ((uint32_t)0x6b3343cfu) /** * @macro * * :macro:`NGTCP2_PROTO_VER_MAX` is the highest QUIC version that this - * library supports. + * library supports. Deprecated since v1.1.0. */ #define NGTCP2_PROTO_VER_MAX NGTCP2_PROTO_VER_V1 @@ -302,9 +272,9 @@ typedef struct ngtcp2_mem { * @macro * * :macro:`NGTCP2_PROTO_VER_MIN` is the lowest QUIC version that this - * library supports. + * library supports. Deprecated since v1.1.0. */ -#define NGTCP2_PROTO_VER_MIN NGTCP2_PROTO_VER_DRAFT_MIN +#define NGTCP2_PROTO_VER_MIN NGTCP2_PROTO_VER_V1 /** * @macro @@ -324,7 +294,7 @@ typedef struct ngtcp2_mem { * @macro * * :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE` is the default maximum UDP - * datagram payload size that this endpoint transmits. + * datagram payload size that the local endpoint transmits. */ #define NGTCP2_MAX_UDP_PAYLOAD_SIZE 1200 @@ -362,7 +332,7 @@ typedef struct ngtcp2_mem { * @macro * * :macro:`NGTCP2_MIN_STATELESS_RESET_RANDLEN` is the minimum length - * of random bytes (Unpredictable Bits) in Stateless Reset packet + * of random bytes (Unpredictable Bits) in Stateless Reset packet. */ #define NGTCP2_MIN_STATELESS_RESET_RANDLEN 5 @@ -374,24 +344,6 @@ typedef struct ngtcp2_mem { */ #define NGTCP2_PATH_CHALLENGE_DATALEN 8 -/** - * @macro - * - * :macro:`NGTCP2_RETRY_KEY_DRAFT` is an encryption key to create - * integrity tag of Retry packet. It is used for QUIC draft versions. - */ -#define NGTCP2_RETRY_KEY_DRAFT \ - "\xcc\xce\x18\x7e\xd0\x9a\x09\xd0\x57\x28\x15\x5a\x6c\xb9\x6b\xe1" - -/** - * @macro - * - * :macro:`NGTCP2_RETRY_NONCE_DRAFT` is nonce used when generating - * integrity tag of Retry packet. It is used for QUIC draft versions. - */ -#define NGTCP2_RETRY_NONCE_DRAFT \ - "\xe5\x49\x30\xf9\x7f\x21\x36\xf0\x53\x0a\x8c\x1c" - /** * @macro * @@ -404,32 +356,29 @@ typedef struct ngtcp2_mem { /** * @macro * - * :macro:`NGTCP2_RETRY_NONCE_V1` is nonce used when generating integrity - * tag of Retry packet. It is used for QUIC v1. + * :macro:`NGTCP2_RETRY_NONCE_V1` is nonce used when generating + * integrity tag of Retry packet. It is used for QUIC v1. */ #define NGTCP2_RETRY_NONCE_V1 "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb" /** * @macro * - * :macro:`NGTCP2_RETRY_KEY_V2_DRAFT` is an encryption key to create - * integrity tag of Retry packet. It is used for QUIC v2 draft. - * - * https://quicwg.org/quic-v2/draft-ietf-quic-v2.html + * :macro:`NGTCP2_RETRY_KEY_V2` is an encryption key to create + * integrity tag of Retry packet. It is used for QUIC v2. See + * :rfc:`9369`. */ -#define NGTCP2_RETRY_KEY_V2_DRAFT \ - "\xba\x85\x8d\xc7\xb4\x3d\xe5\xdb\xf8\x76\x17\xff\x4a\xb2\x53\xdb" +#define NGTCP2_RETRY_KEY_V2 \ + "\x8f\xb4\xb0\x1b\x56\xac\x48\xe2\x60\xfb\xcb\xce\xad\x7c\xcc\x92" /** * @macro * - * :macro:`NGTCP2_RETRY_NONCE_V2_DRAFT` is nonce used when generating - * integrity tag of Retry packet. It is used for QUIC v2 draft. - * - * https://quicwg.org/quic-v2/draft-ietf-quic-v2.html + * :macro:`NGTCP2_RETRY_NONCE_V2` is nonce used when generating + * integrity tag of Retry packet. It is used for QUIC v2. See + * :rfc:`9369`. */ -#define NGTCP2_RETRY_NONCE_V2_DRAFT \ - "\x14\x1b\x99\xc2\x39\xb0\x3e\x78\x5d\x6a\x2e\x9f" +#define NGTCP2_RETRY_NONCE_V2 "\xd8\x69\x69\xbc\x2d\x7c\x6d\x99\x90\xef\xb0\x4a" /** * @macro @@ -476,14 +425,6 @@ typedef struct ngtcp2_mem { */ #define NGTCP2_MIN_INITIAL_DCIDLEN 8 -/** - * @macro - * - * :macro:`NGTCP2_DEFAULT_HANDSHAKE_TIMEOUT` is the default handshake - * timeout. - */ -#define NGTCP2_DEFAULT_HANDSHAKE_TIMEOUT (10 * NGTCP2_SECONDS) - /** * @macrosection * @@ -525,8 +466,8 @@ typedef struct ngtcp2_mem { */ #define NGTCP2_ECN_MASK 0x3 -#define NGTCP2_PKT_INFO_VERSION_V1 1 -#define NGTCP2_PKT_INFO_VERSION NGTCP2_PKT_INFO_VERSION_V1 +#define NGTCP2_PKT_INFO_V1 1 +#define NGTCP2_PKT_INFO_VERSION NGTCP2_PKT_INFO_V1 /** * @struct @@ -535,12 +476,12 @@ typedef struct ngtcp2_mem { */ typedef struct NGTCP2_ALIGN(8) ngtcp2_pkt_info { /** - * :member:`ecn` is ECN marking and when passing - * `ngtcp2_conn_read_pkt()`, and it should be either + * :member:`ecn` is ECN marking, and when it is passed to + * `ngtcp2_conn_read_pkt()`, it should be either * :macro:`NGTCP2_ECN_NOT_ECT`, :macro:`NGTCP2_ECN_ECT_1`, * :macro:`NGTCP2_ECN_ECT_0`, or :macro:`NGTCP2_ECN_CE`. */ - uint32_t ecn; + uint8_t ecn; } ngtcp2_pkt_info; /** @@ -562,190 +503,190 @@ typedef struct NGTCP2_ALIGN(8) ngtcp2_pkt_info { * :macro:`NGTCP2_ERR_NOBUF` indicates that a provided buffer does not * have enough space to store data. */ -#define NGTCP2_ERR_NOBUF -203 +#define NGTCP2_ERR_NOBUF -202 /** * @macro * * :macro:`NGTCP2_ERR_PROTO` indicates a general protocol error. */ -#define NGTCP2_ERR_PROTO -205 +#define NGTCP2_ERR_PROTO -203 /** * @macro * * :macro:`NGTCP2_ERR_INVALID_STATE` indicates that a requested * operation is not allowed at the current connection state. */ -#define NGTCP2_ERR_INVALID_STATE -206 +#define NGTCP2_ERR_INVALID_STATE -204 /** * @macro * * :macro:`NGTCP2_ERR_ACK_FRAME` indicates that an invalid ACK frame * is received. */ -#define NGTCP2_ERR_ACK_FRAME -207 +#define NGTCP2_ERR_ACK_FRAME -205 /** * @macro * * :macro:`NGTCP2_ERR_STREAM_ID_BLOCKED` indicates that there is no * spare stream ID available. */ -#define NGTCP2_ERR_STREAM_ID_BLOCKED -208 +#define NGTCP2_ERR_STREAM_ID_BLOCKED -206 /** * @macro * * :macro:`NGTCP2_ERR_STREAM_IN_USE` indicates that a stream ID is * already in use. */ -#define NGTCP2_ERR_STREAM_IN_USE -209 +#define NGTCP2_ERR_STREAM_IN_USE -207 /** * @macro * * :macro:`NGTCP2_ERR_STREAM_DATA_BLOCKED` indicates that stream data * cannot be sent because of flow control. */ -#define NGTCP2_ERR_STREAM_DATA_BLOCKED -210 +#define NGTCP2_ERR_STREAM_DATA_BLOCKED -208 /** * @macro * * :macro:`NGTCP2_ERR_FLOW_CONTROL` indicates flow control error. */ -#define NGTCP2_ERR_FLOW_CONTROL -211 +#define NGTCP2_ERR_FLOW_CONTROL -209 /** * @macro * * :macro:`NGTCP2_ERR_CONNECTION_ID_LIMIT` indicates that the number * of received Connection ID exceeds acceptable limit. */ -#define NGTCP2_ERR_CONNECTION_ID_LIMIT -212 +#define NGTCP2_ERR_CONNECTION_ID_LIMIT -210 /** * @macro * * :macro:`NGTCP2_ERR_STREAM_LIMIT` indicates that a remote endpoint * opens more streams that is permitted. */ -#define NGTCP2_ERR_STREAM_LIMIT -213 +#define NGTCP2_ERR_STREAM_LIMIT -211 /** * @macro * * :macro:`NGTCP2_ERR_FINAL_SIZE` indicates that inconsistent final * size of a stream. */ -#define NGTCP2_ERR_FINAL_SIZE -214 +#define NGTCP2_ERR_FINAL_SIZE -212 /** * @macro * * :macro:`NGTCP2_ERR_CRYPTO` indicates crypto (TLS) related error. */ -#define NGTCP2_ERR_CRYPTO -215 +#define NGTCP2_ERR_CRYPTO -213 /** * @macro * * :macro:`NGTCP2_ERR_PKT_NUM_EXHAUSTED` indicates that packet number * is exhausted. */ -#define NGTCP2_ERR_PKT_NUM_EXHAUSTED -216 +#define NGTCP2_ERR_PKT_NUM_EXHAUSTED -214 /** * @macro * * :macro:`NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM` indicates that a * required transport parameter is missing. */ -#define NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM -217 +#define NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM -215 /** * @macro * * :macro:`NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM` indicates that a * transport parameter is malformed. */ -#define NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM -218 +#define NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM -216 /** * @macro * * :macro:`NGTCP2_ERR_FRAME_ENCODING` indicates there is an error in * frame encoding. */ -#define NGTCP2_ERR_FRAME_ENCODING -219 +#define NGTCP2_ERR_FRAME_ENCODING -217 /** * @macro * * :macro:`NGTCP2_ERR_DECRYPT` indicates a decryption failure. */ -#define NGTCP2_ERR_DECRYPT -220 +#define NGTCP2_ERR_DECRYPT -218 /** * @macro * * :macro:`NGTCP2_ERR_STREAM_SHUT_WR` indicates no more data can be * sent to a stream. */ -#define NGTCP2_ERR_STREAM_SHUT_WR -221 +#define NGTCP2_ERR_STREAM_SHUT_WR -219 /** * @macro * - * :macro:`NGTCP2_ERR_STREAM_NOT_FOUND` indicates that a stream was not - * found. + * :macro:`NGTCP2_ERR_STREAM_NOT_FOUND` indicates that a stream was + * not found. */ -#define NGTCP2_ERR_STREAM_NOT_FOUND -222 +#define NGTCP2_ERR_STREAM_NOT_FOUND -220 /** * @macro * * :macro:`NGTCP2_ERR_STREAM_STATE` indicates that a requested * operation is not allowed at the current stream state. */ -#define NGTCP2_ERR_STREAM_STATE -226 +#define NGTCP2_ERR_STREAM_STATE -221 /** * @macro * * :macro:`NGTCP2_ERR_RECV_VERSION_NEGOTIATION` indicates that Version * Negotiation packet was received. */ -#define NGTCP2_ERR_RECV_VERSION_NEGOTIATION -229 +#define NGTCP2_ERR_RECV_VERSION_NEGOTIATION -222 /** * @macro * * :macro:`NGTCP2_ERR_CLOSING` indicates that connection is in closing * state. */ -#define NGTCP2_ERR_CLOSING -230 +#define NGTCP2_ERR_CLOSING -223 /** * @macro * * :macro:`NGTCP2_ERR_DRAINING` indicates that connection is in * draining state. */ -#define NGTCP2_ERR_DRAINING -231 +#define NGTCP2_ERR_DRAINING -224 /** * @macro * * :macro:`NGTCP2_ERR_TRANSPORT_PARAM` indicates a general transport * parameter error. */ -#define NGTCP2_ERR_TRANSPORT_PARAM -234 +#define NGTCP2_ERR_TRANSPORT_PARAM -225 /** * @macro * * :macro:`NGTCP2_ERR_DISCARD_PKT` indicates a packet was discarded. */ -#define NGTCP2_ERR_DISCARD_PKT -235 +#define NGTCP2_ERR_DISCARD_PKT -226 /** * @macro * * :macro:`NGTCP2_ERR_CONN_ID_BLOCKED` indicates that there is no * spare Connection ID available. */ -#define NGTCP2_ERR_CONN_ID_BLOCKED -237 +#define NGTCP2_ERR_CONN_ID_BLOCKED -227 /** * @macro * * :macro:`NGTCP2_ERR_INTERNAL` indicates an internal error. */ -#define NGTCP2_ERR_INTERNAL -238 +#define NGTCP2_ERR_INTERNAL -228 /** * @macro * * :macro:`NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED` indicates that a crypto * buffer exceeded. */ -#define NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED -239 +#define NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED -229 /** * @macro * @@ -753,21 +694,21 @@ typedef struct NGTCP2_ALIGN(8) ngtcp2_pkt_info { * :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE` is used and a function call * succeeded. */ -#define NGTCP2_ERR_WRITE_MORE -240 +#define NGTCP2_ERR_WRITE_MORE -230 /** * @macro * * :macro:`NGTCP2_ERR_RETRY` indicates that server should send Retry * packet. */ -#define NGTCP2_ERR_RETRY -241 +#define NGTCP2_ERR_RETRY -231 /** * @macro * * :macro:`NGTCP2_ERR_DROP_CONN` indicates that an endpoint should * drop connection immediately. */ -#define NGTCP2_ERR_DROP_CONN -242 +#define NGTCP2_ERR_DROP_CONN -232 /** * @macro * @@ -775,7 +716,7 @@ typedef struct NGTCP2_ALIGN(8) ngtcp2_pkt_info { * limit is reached and key update is not available. An endpoint * should drop connection immediately. */ -#define NGTCP2_ERR_AEAD_LIMIT_REACHED -243 +#define NGTCP2_ERR_AEAD_LIMIT_REACHED -233 /** * @macro * @@ -783,41 +724,41 @@ typedef struct NGTCP2_ALIGN(8) ngtcp2_pkt_info { * could not probe that a path is capable of sending UDP datagram * payload of size at least 1200 bytes. */ -#define NGTCP2_ERR_NO_VIABLE_PATH -244 +#define NGTCP2_ERR_NO_VIABLE_PATH -234 /** * @macro * * :macro:`NGTCP2_ERR_VERSION_NEGOTIATION` indicates that server * should send Version Negotiation packet. */ -#define NGTCP2_ERR_VERSION_NEGOTIATION -245 +#define NGTCP2_ERR_VERSION_NEGOTIATION -235 /** * @macro * * :macro:`NGTCP2_ERR_HANDSHAKE_TIMEOUT` indicates that QUIC * connection is not established before the specified deadline. */ -#define NGTCP2_ERR_HANDSHAKE_TIMEOUT -246 +#define NGTCP2_ERR_HANDSHAKE_TIMEOUT -236 /** * @macro * * :macro:`NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE` indicates the * version negotiation failed. */ -#define NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE -247 +#define NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE -237 /** * @macro * * :macro:`NGTCP2_ERR_IDLE_CLOSE` indicates the connection should be * closed silently because of idle timeout. */ -#define NGTCP2_ERR_IDLE_CLOSE -248 +#define NGTCP2_ERR_IDLE_CLOSE -238 /** * @macro * * :macro:`NGTCP2_ERR_FATAL` indicates that error codes less than this * value is fatal error. When this error is returned, an endpoint - * should drop connection immediately. + * should close connection immediately. */ #define NGTCP2_ERR_FATAL -500 /** @@ -892,7 +833,7 @@ typedef enum ngtcp2_pkt_type { */ NGTCP2_PKT_INITIAL = 0x10, /** - * :enum:`NGTCP2_PKT_0RTT` indicates 0RTT packet. + * :enum:`NGTCP2_PKT_0RTT` indicates 0-RTT packet. */ NGTCP2_PKT_0RTT = 0x11, /** @@ -1061,12 +1002,10 @@ typedef enum ngtcp2_pkt_type { /** * @macro * - * :macro:`NGTCP2_VERSION_NEGOTIATION_ERROR_DRAFT` is QUIC transport - * error code ``VERSION_NEGOTIATION_ERROR``. - * - * https://quicwg.org/quic-v2/draft-ietf-quic-v2.html + * :macro:`NGTCP2_VERSION_NEGOTIATION_ERROR` is QUIC transport error + * code ``VERSION_NEGOTIATION_ERROR``. See :rfc:`9368`. */ -#define NGTCP2_VERSION_NEGOTIATION_ERROR_DRAFT 0x53f8u +#define NGTCP2_VERSION_NEGOTIATION_ERROR 0x11 /** * @enum @@ -1096,6 +1035,8 @@ typedef enum ngtcp2_path_validation_result { * @typedef * * :type:`ngtcp2_tstamp` is a timestamp with nanosecond resolution. + * ``UINT64_MAX`` is an invalid value, and it is often used to + * indicate that no value is set. */ typedef uint64_t ngtcp2_tstamp; @@ -1103,7 +1044,8 @@ typedef uint64_t ngtcp2_tstamp; * @typedef * * :type:`ngtcp2_duration` is a period of time in nanosecond - * resolution. + * resolution. ``UINT64_MAX`` is an invalid value, and it is often + * used to indicate that no value is set. */ typedef uint64_t ngtcp2_duration; @@ -1178,10 +1120,15 @@ typedef struct ngtcp2_pkt_hd { */ int64_t pkt_num; /** - * :member:`token` contains token for Initial - * packet. + * :member:`token` contains token. Only Initial packet may contain + * token. NULL if no token is present. */ - ngtcp2_vec token; + const uint8_t *token; + /** + * :member:`tokenlen` is the length of :member:`token`. 0 if no + * token is present. + */ + size_t tokenlen; /** * :member:`pkt_numlen` is the number of bytes spent to encode * :member:`pkt_num`. @@ -1197,8 +1144,10 @@ typedef struct ngtcp2_pkt_hd { */ uint32_t version; /** - * :member:`type` is a type of QUIC packet. See - * :type:`ngtcp2_pkt_type`. + * :member:`type` is a type of QUIC packet. This field does not + * have a QUIC packet type defined for a specific QUIC version. + * Instead, it contains version independent packet type defined by + * this library. See :type:`ngtcp2_pkt_type`. */ uint8_t type; /** @@ -1229,25 +1178,6 @@ typedef struct ngtcp2_pkt_stateless_reset { size_t randlen; } ngtcp2_pkt_stateless_reset; -/** - * @enum - * - * :type:`ngtcp2_transport_params_type` defines TLS message type which - * carries transport parameters. - */ -typedef enum ngtcp2_transport_params_type { - /** - * :enum:`NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO` is Client Hello - * TLS message. - */ - NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO, - /** - * :enum:`NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS` is - * Encrypted Extensions TLS message. - */ - NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS -} ngtcp2_transport_params_type; - /** * @macrosection * @@ -1296,14 +1226,96 @@ typedef enum ngtcp2_transport_params_type { */ #define NGTCP2_TLSEXT_QUIC_TRANSPORT_PARAMETERS_V1 0x39u +#ifdef NGTCP2_USE_GENERIC_SOCKADDR +# ifndef NGTCP2_AF_INET +# error NGTCP2_AF_INET must be defined +# endif /* !NGTCP2_AF_INET */ + +# ifndef NGTCP2_AF_INET6 +# error NGTCP2_AF_INET6 must be defined +# endif /* !NGTCP2_AF_INET6 */ + +typedef unsigned short int ngtcp2_sa_family; +typedef uint16_t ngtcp2_in_port; + +typedef struct ngtcp2_sockaddr { + ngtcp2_sa_family sa_family; + uint8_t sa_data[14]; +} ngtcp2_sockaddr; + +typedef struct ngtcp2_in_addr { + uint32_t s_addr; +} ngtcp2_in_addr; + +typedef struct ngtcp2_sockaddr_in { + ngtcp2_sa_family sin_family; + ngtcp2_in_port sin_port; + ngtcp2_in_addr sin_addr; + uint8_t sin_zero[8]; +} ngtcp2_sockaddr_in; + +typedef struct ngtcp2_in6_addr { + uint8_t in6_addr[16]; +} ngtcp2_in6_addr; + +typedef struct ngtcp2_sockaddr_in6 { + ngtcp2_sa_family sin6_family; + ngtcp2_in_port sin6_port; + uint32_t sin6_flowinfo; + ngtcp2_in6_addr sin6_addr; + uint32_t sin6_scope_id; +} ngtcp2_sockaddr_in6; + +typedef uint32_t ngtcp2_socklen; +#else /* !NGTCP2_USE_GENERIC_SOCKADDR */ +# define NGTCP2_AF_INET AF_INET +# define NGTCP2_AF_INET6 AF_INET6 + /** - * @macro + * @typedef * - * :macro:`NGTCP2_TLSEXT_QUIC_TRANSPORT_PARAMETERS_DRAFT` is TLS - * extension type of quic_transport_parameters used during draft - * development. + * :type:`ngtcp2_sockaddr` is typedefed to struct sockaddr. If + * :macro:`NGTCP2_USE_GENERIC_SOCKADDR` is defined, it is typedefed to + * the generic struct sockaddr defined in ngtcp2.h. + */ +typedef struct sockaddr ngtcp2_sockaddr; +/** + * @typedef + * + * :type:`ngtcp2_sockaddr_in` is typedefed to struct sockaddr_in. If + * :macro:`NGTCP2_USE_GENERIC_SOCKADDR` is defined, it is typedefed to + * the generic struct sockaddr_in defined in ngtcp2.h. + */ +typedef struct sockaddr_in ngtcp2_sockaddr_in; +/** + * @typedef + * + * :type:`ngtcp2_sockaddr_in6` is typedefed to struct sockaddr_in6. + * If :macro:`NGTCP2_USE_GENERIC_SOCKADDR` is defined, it is typedefed + * to the generic struct sockaddr_in6 defined in ngtcp2.h. + */ +typedef struct sockaddr_in6 ngtcp2_sockaddr_in6; +/** + * @typedef + * + * :type:`ngtcp2_socklen` is typedefed to socklen_t. If + * :macro:`NGTCP2_USE_GENERIC_SOCKADDR` is defined, it is typedefed to + * uint32_t. + */ +typedef socklen_t ngtcp2_socklen; +#endif /* !NGTCP2_USE_GENERIC_SOCKADDR */ + +/** + * @struct + * + * :type:`ngtcp2_sockaddr_union` conveniently includes all supported + * address types. */ -#define NGTCP2_TLSEXT_QUIC_TRANSPORT_PARAMETERS_DRAFT 0xffa5u +typedef union ngtcp2_sockaddr_union { + ngtcp2_sockaddr sa; + ngtcp2_sockaddr_in in; + ngtcp2_sockaddr_in6 in6; +} ngtcp2_sockaddr_union; /** * @struct @@ -1317,29 +1329,21 @@ typedef struct ngtcp2_preferred_addr { */ ngtcp2_cid cid; /** - * :member:`ipv4_port` is a port of IPv4 address. - */ - uint16_t ipv4_port; - /** - * :member:`ipv6_port` is a port of IPv6 address. + * :member:`ipv4` contains IPv4 address and port. */ - uint16_t ipv6_port; + ngtcp2_sockaddr_in ipv4; /** - * :member:`ipv4_addr` contains IPv4 address in network byte order. + * :member:`ipv6` contains IPv6 address and port. */ - uint8_t ipv4_addr[4]; + ngtcp2_sockaddr_in6 ipv6; /** - * :member:`ipv6_addr` contains IPv6 address in network byte order. - */ - uint8_t ipv6_addr[16]; - /** - * :member:`ipv4_present` indicates that :member:`ipv4_addr` and - * :member:`ipv4_port` contain IPv4 address and port respectively. + * :member:`ipv4_present` indicates that :member:`ipv4` contains + * IPv4 address and port. */ uint8_t ipv4_present; /** - * :member:`ipv6_present` indicates that :member:`ipv6_addr` and - * :member:`ipv6_port` contain IPv6 address and port respectively. + * :member:`ipv6_present` indicates that :member:`ipv6` contains + * IPv6 address and port. */ uint8_t ipv6_present; /** @@ -1352,7 +1356,7 @@ typedef struct ngtcp2_preferred_addr { * @struct * * :type:`ngtcp2_version_info` represents version_information - * structure. + * structure. See :rfc:`9368`. */ typedef struct ngtcp2_version_info { /** @@ -1360,19 +1364,21 @@ typedef struct ngtcp2_version_info { */ uint32_t chosen_version; /** - * :member:`other_versions` points the wire image of other_versions - * field. The each version is therefore in network byte order. + * :member:`available_versions` points the wire image of + * available_versions field. The each version is therefore in + * network byte order. */ - uint8_t *other_versions; + const uint8_t *available_versions; /** - * :member:`other_versionslen` is the number of bytes pointed by - * :member:`other_versions`, not the number of versions included. + * :member:`available_versionslen` is the number of bytes pointed by + * :member:`available_versions`, not the number of versions + * included. */ - size_t other_versionslen; + size_t available_versionslen; } ngtcp2_version_info; -#define NGTCP2_TRANSPORT_PARAMS_VERSION_V1 1 -#define NGTCP2_TRANSPORT_PARAMS_VERSION NGTCP2_TRANSPORT_PARAMS_VERSION_V1 +#define NGTCP2_TRANSPORT_PARAMS_V1 1 +#define NGTCP2_TRANSPORT_PARAMS_VERSION NGTCP2_TRANSPORT_PARAMS_V1 /** * @struct @@ -1382,55 +1388,58 @@ typedef struct ngtcp2_version_info { */ typedef struct ngtcp2_transport_params { /** - * :member:`preferred_address` contains preferred address if - * :member:`preferred_address_present` is nonzero. + * :member:`preferred_addr` contains preferred address if + * :member:`preferred_addr_present` is nonzero. */ - ngtcp2_preferred_addr preferred_address; + ngtcp2_preferred_addr preferred_addr; /** * :member:`original_dcid` is the Destination Connection ID field * from the first Initial packet from client. Server must specify - * this field. It is expected that application knows the original - * Destination Connection ID even if it sends Retry packet, for - * example, by including it in retry token. Otherwise, application - * should not specify this field. + * this field and set :member:`original_dcid_present` to nonzero. + * It is expected that application knows the original Destination + * Connection ID even if it sends Retry packet, for example, by + * including it in retry token. Otherwise, application should not + * specify this field. */ ngtcp2_cid original_dcid; /** * :member:`initial_scid` is the Source Connection ID field from the - * first Initial packet the endpoint sends. Application should not - * specify this field. + * first Initial packet the local endpoint sends. Application + * should not specify this field. If :member:`initial_scid_present` + * is set to nonzero, it indicates this field is set. */ ngtcp2_cid initial_scid; /** * :member:`retry_scid` is the Source Connection ID field from Retry * packet. Only server uses this field. If server application - * received Initial packet with retry token from client and server - * verified its token, server application must set Destination - * Connection ID field from the Initial packet to this field and set - * :member:`retry_scid_present` to nonzero. Server application must - * verify that the Destination Connection ID from Initial packet was - * sent in Retry packet by, for example, including the Connection ID - * in a token, or including it in AAD when encrypting a token. + * received Initial packet with retry token from client, and server + * successfully verified its token, server application must set + * Destination Connection ID field from the Initial packet to this + * field, and set :member:`retry_scid_present` to nonzero. Server + * application must verify that the Destination Connection ID from + * Initial packet was sent in Retry packet by, for example, + * including the Connection ID in a token, or including it in AAD + * when encrypting a token. */ ngtcp2_cid retry_scid; /** * :member:`initial_max_stream_data_bidi_local` is the size of flow * control window of locally initiated stream. This is the number - * of bytes that the remote endpoint can send and the local endpoint - * must ensure that it has enough buffer to receive them. + * of bytes that the remote endpoint can send, and the local + * endpoint must ensure that it has enough buffer to receive them. */ uint64_t initial_max_stream_data_bidi_local; /** * :member:`initial_max_stream_data_bidi_remote` is the size of flow * control window of remotely initiated stream. This is the number - * of bytes that the remote endpoint can send and the local endpoint - * must ensure that it has enough buffer to receive them. + * of bytes that the remote endpoint can send, and the local + * endpoint must ensure that it has enough buffer to receive them. */ uint64_t initial_max_stream_data_bidi_remote; /** * :member:`initial_max_stream_data_uni` is the size of flow control * window of remotely initiated unidirectional stream. This is the - * number of bytes that the remote endpoint can send and the local + * number of bytes that the remote endpoint can send, and the local * endpoint must ensure that it has enough buffer to receive them. */ uint64_t initial_max_stream_data_uni; @@ -1451,12 +1460,13 @@ typedef struct ngtcp2_transport_params { uint64_t initial_max_streams_uni; /** * :member:`max_idle_timeout` is a duration during which sender - * allows quiescent. + * allows quiescent. 0 means no idle timeout. It must not be + * UINT64_MAX. */ ngtcp2_duration max_idle_timeout; /** - * :member:`max_udp_payload_size` is the maximum datagram size that - * the endpoint can receive. + * :member:`max_udp_payload_size` is the maximum UDP payload size + * that the local endpoint can receive. */ uint64_t max_udp_payload_size; /** @@ -1471,14 +1481,16 @@ typedef struct ngtcp2_transport_params { uint64_t ack_delay_exponent; /** * :member:`max_ack_delay` is the maximum acknowledgement delay by - * which the endpoint will delay sending acknowledgements. + * which the local endpoint will delay sending acknowledgements. It + * must be strictly less than (1 << 14) milliseconds. + * Sub-millisecond part is dropped when sending it in a QUIC + * transport parameter. */ ngtcp2_duration max_ack_delay; /** * :member:`max_datagram_frame_size` is the maximum size of DATAGRAM - * frame that this endpoint willingly receives. Specifying 0 - * disables DATAGRAM support. See - * https://datatracker.ietf.org/doc/html/rfc9221 + * frame that the local endpoint willingly receives. Specifying 0 + * disables DATAGRAM support. See :rfc:`9221`. */ uint64_t max_datagram_frame_size; /** @@ -1487,30 +1499,37 @@ typedef struct ngtcp2_transport_params { */ uint8_t stateless_reset_token_present; /** - * :member:`disable_active_migration` is nonzero if the endpoint - * does not support active connection migration. + * :member:`disable_active_migration` is nonzero if the local + * endpoint does not support active connection migration. */ uint8_t disable_active_migration; + /** + * :member:`original_dcid_present` is nonzero if + * :member:`original_dcid` field is set. + */ + uint8_t original_dcid_present; + /** + * :member:`initial_scid_present` is nonzero if + * :member:`initial_scid` field is set. + */ + uint8_t initial_scid_present; /** * :member:`retry_scid_present` is nonzero if :member:`retry_scid` * field is set. */ uint8_t retry_scid_present; /** - * :member:`preferred_address_present` is nonzero if + * :member:`preferred_addr_present` is nonzero if * :member:`preferred_address` is set. */ - uint8_t preferred_address_present; + uint8_t preferred_addr_present; /** * :member:`stateless_reset_token` contains stateless reset token. */ uint8_t stateless_reset_token[NGTCP2_STATELESS_RESET_TOKENLEN]; /** * :member:`grease_quic_bit` is nonzero if sender supports "Greasing - * the QUIC Bit" extension. See - * https://datatracker.ietf.org/doc/html/draft-ietf-quic-bit-grease. - * Note that the local endpoint always enables greasing QUIC bit - * regardless of this field value. + * the QUIC Bit" extension. See :rfc:`9287`. */ uint8_t grease_quic_bit; /** @@ -1527,44 +1546,15 @@ typedef struct ngtcp2_transport_params { uint8_t version_info_present; } ngtcp2_transport_params; -/** - * @enum - * - * :type:`ngtcp2_pktns_id` defines packet number space identifier. - */ -typedef enum ngtcp2_pktns_id { - /** - * :enum:`NGTCP2_PKTNS_ID_INITIAL` is the Initial packet number - * space. - */ - NGTCP2_PKTNS_ID_INITIAL, - /** - * :enum:`NGTCP2_PKTNS_ID_HANDSHAKE` is the Handshake packet number - * space. - */ - NGTCP2_PKTNS_ID_HANDSHAKE, - /** - * :enum:`NGTCP2_PKTNS_ID_APPLICATION` is the Application data - * packet number space. - */ - NGTCP2_PKTNS_ID_APPLICATION, - /** - * :enum:`NGTCP2_PKTNS_ID_MAX` is defined to get the number of - * packet number spaces. - */ - NGTCP2_PKTNS_ID_MAX -} ngtcp2_pktns_id; - -#define NGTCP2_CONN_STAT_VERSION_V1 1 -#define NGTCP2_CONN_STAT_VERSION NGTCP2_CONN_STAT_VERSION_V1 +#define NGTCP2_CONN_INFO_V1 1 +#define NGTCP2_CONN_INFO_VERSION NGTCP2_CONN_INFO_V1 /** * @struct * - * :type:`ngtcp2_conn_stat` holds various connection statistics, and - * computed data for recovery and congestion controller. + * :type:`ngtcp2_conn_info` holds various connection statistics. */ -typedef struct ngtcp2_conn_stat { +typedef struct ngtcp2_conn_info { /** * :member:`latest_rtt` is the latest RTT sample which is not * adjusted by acknowledgement delay. @@ -1583,35 +1573,6 @@ typedef struct ngtcp2_conn_stat { * :member:`rttvar` is a mean deviation of observed RTT. */ ngtcp2_duration rttvar; - /** - * :member:`initial_rtt` is the initial RTT which is used when no - * RTT sample is available. - */ - ngtcp2_duration initial_rtt; - /** - * :member:`first_rtt_sample_ts` is the timestamp when the first RTT - * sample is obtained. - */ - ngtcp2_tstamp first_rtt_sample_ts; - /** - * :member:`pto_count` is the count of successive PTO timer - * expiration. - */ - size_t pto_count; - /** - * :member:`loss_detection_timer` is the deadline of the current - * loss detection timer. - */ - ngtcp2_tstamp loss_detection_timer; - /** - * :member:`last_tx_pkt_ts` corresponds to - * time_of_last_ack_eliciting_packet in :rfc:`9002`. - */ - ngtcp2_tstamp last_tx_pkt_ts[NGTCP2_PKTNS_ID_MAX]; - /** - * :member:`loss_time` corresponds to loss_time in :rfc:`9002`. - */ - ngtcp2_tstamp loss_time[NGTCP2_PKTNS_ID_MAX]; /** * :member:`cwnd` is the size of congestion window. */ @@ -1620,38 +1581,12 @@ typedef struct ngtcp2_conn_stat { * :member:`ssthresh` is slow start threshold. */ uint64_t ssthresh; - /** - * :member:`congestion_recovery_start_ts` is the timestamp when - * congestion recovery started. - */ - ngtcp2_tstamp congestion_recovery_start_ts; /** * :member:`bytes_in_flight` is the number in bytes of all sent * packets which have not been acknowledged. */ uint64_t bytes_in_flight; - /** - * :member:`max_udp_payload_size` is the maximum size of UDP - * datagram payload that this endpoint transmits. It is used by - * congestion controller to compute congestion window. - */ - size_t max_udp_payload_size; - /** - * :member:`delivery_rate_sec` is the current sending rate measured - * in byte per second. - */ - uint64_t delivery_rate_sec; - /** - * :member:`pacing_rate` is the current packet sending rate. If - * pacing is disabled, 0 is set. - */ - double pacing_rate; - /** - * :member:`send_quantum` is the maximum size of a data aggregate - * scheduled and transmitted together. - */ - size_t send_quantum; -} ngtcp2_conn_stat; +} ngtcp2_conn_info; /** * @enum @@ -1668,15 +1603,9 @@ typedef enum ngtcp2_cc_algo { */ NGTCP2_CC_ALGO_CUBIC = 0x01, /** - * :enum:`NGTCP2_CC_ALGO_BBR` represents BBR. If BBR is chosen, - * packet pacing is enabled. + * :enum:`NGTCP2_CC_ALGO_BBR` represents BBR v2. */ - NGTCP2_CC_ALGO_BBR = 0x02, - /** - * :enum:`NGTCP2_CC_ALGO_BBR2` represents BBR v2. If BBR v2 is - * chosen, packet pacing is enabled. - */ - NGTCP2_CC_ALGO_BBR2 = 0x03 + NGTCP2_CC_ALGO_BBR = 0x02 } ngtcp2_cc_algo; /** @@ -1737,27 +1666,30 @@ typedef void (*ngtcp2_qlog_write)(void *user_data, uint32_t flags, const void *data, size_t datalen); /** - * @struct + * @enum * - * :type:`ngtcp2_qlog_settings` is a set of settings for qlog. + * :type:`ngtcp2_token_type` defines the type of token. */ -typedef struct ngtcp2_qlog_settings { +typedef enum ngtcp2_token_type { + /** + * :enum:`NGTCP2_TOKEN_TYPE_UNKNOWN` indicates that the type of + * token is unknown. + */ + NGTCP2_TOKEN_TYPE_UNKNOWN, /** - * :member:`odcid` is Original Destination Connection ID sent by - * client. It is used as group_id and ODCID fields. Client ignores - * this field and uses dcid parameter passed to - * `ngtcp2_conn_client_new()`. + * :enum:`NGTCP2_TOKEN_TYPE_RETRY` indicates that a token comes from + * Retry packet. */ - ngtcp2_cid odcid; + NGTCP2_TOKEN_TYPE_RETRY, /** - * :member:`write` is a callback function to write qlog. Setting - * ``NULL`` disables qlog. + * :enum:`NGTCP2_TOKEN_TYPE_NEW_TOKEN` indicates that a token comes + * from NEW_TOKEN frame. */ - ngtcp2_qlog_write write; -} ngtcp2_qlog_settings; + NGTCP2_TOKEN_TYPE_NEW_TOKEN +} ngtcp2_token_type; -#define NGTCP2_SETTINGS_VERSION_V1 1 -#define NGTCP2_SETTINGS_VERSION NGTCP2_SETTINGS_VERSION_V1 +#define NGTCP2_SETTINGS_V1 1 +#define NGTCP2_SETTINGS_VERSION NGTCP2_SETTINGS_V1 /** * @struct @@ -1766,9 +1698,10 @@ typedef struct ngtcp2_qlog_settings { */ typedef struct ngtcp2_settings { /** - * :member:`qlog` is qlog settings. + * :member:`qlog_write` is a callback function to write qlog. + * Setting ``NULL`` disables qlog. */ - ngtcp2_qlog_settings qlog; + ngtcp2_qlog_write qlog_write; /** * :member:`cc_algo` specifies congestion control algorithm. */ @@ -1789,24 +1722,37 @@ typedef struct ngtcp2_settings { */ ngtcp2_printf log_printf; /** - * :member:`max_udp_payload_size` is the maximum size of UDP - * datagram payload that this endpoint transmits. It is used by - * congestion controller to compute congestion window. + * :member:`max_tx_udp_payload_size` is the maximum size of UDP + * datagram payload that the local endpoint transmits. It is used + * by congestion controller to compute congestion window. */ - size_t max_udp_payload_size; + size_t max_tx_udp_payload_size; /** * :member:`token` is a token from Retry packet or NEW_TOKEN frame. * * Server sets this field if it received the token in Client Initial - * packet and successfully validated. + * packet and successfully validated. It should also set + * :member:`token_type` field. * * Client sets this field if it intends to send token in its Initial * packet. * * `ngtcp2_conn_server_new` and `ngtcp2_conn_client_new` make a copy * of token. + * + * Set NULL if there is no token. */ - ngtcp2_vec token; + const uint8_t *token; + /** + * :member:`tokenlen` is the length of :member:`token`. Set 0 if + * there is no token. + */ + size_t tokenlen; + /** + * :member:`token_type` is the type of token. Server application + * should set this field. + */ + ngtcp2_token_type token_type; /** * :member:`rand_ctx` is an optional random number generator to be * passed to :type:`ngtcp2_rand` callback. @@ -1834,20 +1780,20 @@ typedef struct ngtcp2_settings { */ uint64_t max_stream_window; /** - * :member:`ack_thresh` is the maximum number of unacknowledged - * packets before sending acknowledgement. It triggers the - * immediate acknowledgement. + * :member:`ack_thresh` is the minimum number of the received ACK + * eliciting packets that trigger the immediate acknowledgement from + * the local endpoint. */ size_t ack_thresh; /** - * :member:`no_udp_payload_size_shaping`, if set to nonzero, + * :member:`no_tx_udp_payload_size_shaping`, if set to nonzero, * instructs the library not to limit the UDP payload size to * :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE` (which can be extended by - * Path MTU Discovery) and instead use the mininum size among the - * given buffer size, :member:`max_udp_payload_size`, and the - * received max_udp_payload QUIC transport parameter. + * Path MTU Discovery), and instead use the minimum size among the + * given buffer size, :member:`max_tx_udp_payload_size`, and the + * received max_udp_payload_size QUIC transport parameter. */ - int no_udp_payload_size_shaping; + uint8_t no_tx_udp_payload_size_shaping; /** * :member:`handshake_timeout` is the period of time before giving * up QUIC connection establishment. If QUIC handshake is not @@ -1865,10 +1811,13 @@ typedef struct ngtcp2_settings { * of preference. * * On compatible version negotiation, server will negotiate one of - * those versions contained in this array if a client initially - * chooses a less preferred version. This version set corresponds - * to Offered Versions in QUIC Version Negotiation draft, and it should - * be sent in Version Negotiation packet. + * those versions contained in this array if there is some overlap + * between these versions and the versions offered by the client. + * If there is no overlap, but the client chosen version is + * supported by the library, the server chooses the client chosen + * version as the negotiated version. This version set corresponds + * to Offered Versions described in :rfc:`9368`, and it should be + * included in Version Negotiation packet. * * Client uses this field and :member:`original_version` to prevent * version downgrade attack if it reacted upon Version Negotiation @@ -1876,7 +1825,7 @@ typedef struct ngtcp2_settings { * |client_chosen_version| passed to `ngtcp2_conn_client_new` unless * |client_chosen_version| is a reserved version. */ - uint32_t *preferred_versions; + const uint32_t *preferred_versions; /** * :member:`preferred_versionslen` is the number of versions that * are contained in the array pointed by @@ -1884,13 +1833,14 @@ typedef struct ngtcp2_settings { */ size_t preferred_versionslen; /** - * :member:`other_versions` is the array of versions that are set in - * :member:`other_versions ` - * field of outgoing version_information QUIC transport parameter. + * :member:`available_versions` is the array of versions that are + * going to be set in :member:`available_versions + * ` field of outgoing + * version_information QUIC transport parameter. * - * For server, this corresponds to Fully-Deployed Versions in QUIC - * Version Negotiation draft. If this field is set not, it is set - * to :member:`preferred_versions` internally if + * For server, this corresponds to Fully-Deployed Versions described + * in :rfc:`9368`. If this field is not set, it is set to + * :member:`preferred_versions` internally if * :member:`preferred_versionslen` is not zero. If this field is * not set, and :member:`preferred_versionslen` is zero, this field * is set to :macro:`NGTCP2_PROTO_VER_V1` internally. @@ -1902,12 +1852,13 @@ typedef struct ngtcp2_settings { * `ngtcp2_conn_client_new` will be set in this field internally * unless |client_chosen_version| is a reserved version. */ - uint32_t *other_versions; + const uint32_t *available_versions; /** - * :member:`other_versionslen` is the number of versions that are - * contained in the array pointed by :member:`other_versions`. + * :member:`available_versionslen` is the number of versions that + * are contained in the array pointed by + * :member:`available_versions`. */ - size_t other_versionslen; + size_t available_versionslen; /** * :member:`original_version` is the original version that client * initially used to make a connection attempt. If it is set, and @@ -1920,92 +1871,14 @@ typedef struct ngtcp2_settings { * :member:`no_pmtud`, if set to nonzero, disables Path MTU * Discovery. */ - int no_pmtud; + uint8_t no_pmtud; + /** + * :member:`pkt_num` is the initial packet number for each packet + * number space. It must be in range [0, INT32_MAX], inclusive. + */ + uint32_t initial_pkt_num; } ngtcp2_settings; -#ifdef NGTCP2_USE_GENERIC_SOCKADDR -typedef struct ngtcp2_sockaddr { - uint16_t sa_family; - uint8_t sa_data[14]; -} ngtcp2_sockaddr; - -typedef struct ngtcp2_in_addr { - uint32_t s_addr; -} ngtcp2_in_addr; - -typedef struct ngtcp2_sockaddr_in { - uint16_t sin_family; - uint16_t sin_port; - ngtcp2_in_addr sin_addr; - uint8_t sin_zero[8]; -} ngtcp2_sockaddr_in; - -# define NGTCP2_SS_MAXSIZE 128 -# define NGTCP2_SS_ALIGNSIZE (sizeof(uint64_t)) -# define NGTCP2_SS_PAD1SIZE (NGTCP2_SS_ALIGNSIZE - sizeof(uint16_t)) -# define NGTCP2_SS_PAD2SIZE \ - (NGTCP2_SS_MAXSIZE - \ - (sizeof(uint16_t) + NGTCP2_SS_PAD1SIZE + NGTCP2_SS_ALIGNSIZE)) - -typedef struct ngtcp2_sockaddr_storage { - uint16_t ss_family; - uint8_t _ss_pad1[NGTCP2_SS_PAD1SIZE]; - uint64_t _ss_align; - uint8_t _ss_pad2[NGTCP2_SS_PAD2SIZE]; -} ngtcp2_sockaddr_storage; - -# undef NGTCP2_SS_PAD2SIZE -# undef NGTCP2_SS_PAD1SIZE -# undef NGTCP2_SS_ALIGNSIZE -# undef NGTCP2_SS_MAXSIZE - -typedef uint32_t ngtcp2_socklen; -#else -/** - * @typedef - * - * :type:`ngtcp2_sockaddr` is typedefed to struct sockaddr. If - * :macro:`NGTCP2_USE_GENERIC_SOCKADDR` is defined, it is typedefed to - * the generic struct sockaddr defined in ngtcp2.h. - */ -typedef struct sockaddr ngtcp2_sockaddr; -/** - * @typedef - * - * :type:`ngtcp2_sockaddr_storage` is typedefed to struct - * sockaddr_storage. If :macro:`NGTCP2_USE_GENERIC_SOCKADDR` is - * defined, it is typedefed to the generic struct sockaddr_storage - * defined in ngtcp2.h. - */ -typedef struct sockaddr_storage ngtcp2_sockaddr_storage; -typedef struct sockaddr_in ngtcp2_sockaddr_in; -/** - * @typedef - * - * :type:`ngtcp2_socklen` is typedefed to socklen_t. If - * :macro:`NGTCP2_USE_GENERIC_SOCKADDR` is defined, it is typedefed to - * uint32_t. - */ -typedef socklen_t ngtcp2_socklen; -#endif - -#if defined(NGTCP2_USE_GENERIC_SOCKADDR) || \ - defined(NGTCP2_USE_GENERIC_IPV6_SOCKADDR) -typedef struct ngtcp2_in6_addr { - uint8_t in6_addr[16]; -} ngtcp2_in6_addr; - -typedef struct ngtcp2_sockaddr_in6 { - uint16_t sin6_family; - uint16_t sin6_port; - uint32_t sin6_flowinfo; - ngtcp2_in6_addr sin6_addr; - uint32_t sin6_scope_id; -} ngtcp2_sockaddr_in6; -#else -typedef struct sockaddr_in6 ngtcp2_sockaddr_in6; -#endif - /** * @struct * @@ -2018,7 +1891,8 @@ typedef struct ngtcp2_addr { */ ngtcp2_sockaddr *addr; /** - * :member:`addrlen` is the length of addr. + * :member:`addrlen` is the length of :member:`addr`. It must not + * be longer than sizeof(:type:`ngtcp2_sockaddr_union`). */ ngtcp2_socklen addrlen; } ngtcp2_addr; @@ -2045,7 +1919,7 @@ typedef struct ngtcp2_path { * Note that :type:`ngtcp2_path` is generally passed to * :type:`ngtcp2_conn` by an application, and :type:`ngtcp2_conn` * stores their copies. Unfortunately, there is no way for the - * application to know when :type:`ngtcp2_conn` finishes using a + * application to know when :type:`ngtcp2_conn` finished using a * specific :type:`ngtcp2_path` object in mid connection, which * means that the application cannot free the data pointed by this * field. Therefore, it is advised to use this field only when the @@ -2069,11 +1943,11 @@ typedef struct ngtcp2_path_storage { /** * :member:`local_addrbuf` is a buffer to store local address. */ - ngtcp2_sockaddr_storage local_addrbuf; + ngtcp2_sockaddr_union local_addrbuf; /** * :member:`remote_addrbuf` is a buffer to store remote address. */ - ngtcp2_sockaddr_storage remote_addrbuf; + ngtcp2_sockaddr_union remote_addrbuf; } ngtcp2_path_storage; /** @@ -2160,8 +2034,9 @@ typedef struct ngtcp2_crypto_cipher_ctx { * :type:`ngtcp2_crypto_ctx` is a convenient structure to bind all * crypto related objects in one place. Use * `ngtcp2_crypto_ctx_initial` to initialize this struct for Initial - * packet encryption. For Handshake and 1RTT packets, use - * `ngtcp2_crypto_ctx_tls`. + * packet encryption. For Handshake and 1-RTT packets, use + * `ngtcp2_crypto_ctx_tls`. For 0-RTT packets, use + * `ngtcp2_crypto_ctx_tls_early`. */ typedef struct ngtcp2_crypto_ctx { /** @@ -2191,60 +2066,56 @@ typedef struct ngtcp2_crypto_ctx { /** * @function * - * `ngtcp2_encode_transport_params` encodes |params| in |dest| of + * `ngtcp2_transport_params_encode` encodes |params| in |dest| of * length |destlen|. * * If |dest| is NULL, and |destlen| is zero, this function just * returns the number of bytes required to store the encoded transport * parameters. * - * This function returns the number of written, or one of the + * This function returns the number of bytes written, or one of the * following negative error codes: * * :macro:`NGTCP2_ERR_NOBUF` * Buffer is too small. - * :macro:`NGTCP2_ERR_INVALID_ARGUMENT` - * |exttype| is invalid. */ -NGTCP2_EXTERN ngtcp2_ssize ngtcp2_encode_transport_params_versioned( - uint8_t *dest, size_t destlen, ngtcp2_transport_params_type exttype, - int transport_params_version, const ngtcp2_transport_params *params); +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_transport_params_encode_versioned( + uint8_t *dest, size_t destlen, int transport_params_version, + const ngtcp2_transport_params *params); /** * @function * - * `ngtcp2_decode_transport_params` decodes transport parameters in + * `ngtcp2_transport_params_decode` decodes transport parameters in * |data| of length |datalen|, and stores the result in the object * pointed by |params|. * - * If the optional parameters are missing, the default value is - * assigned. + * If an optional parameter is missing, the default value is assigned. * * The following fields may point to somewhere inside the buffer * pointed by |data| of length |datalen|: * - * - :member:`ngtcp2_transport_params.version_info.other_versions - * ` + * - :member:`ngtcp2_transport_params.version_info.available_versions + * ` * * This function returns 0 if it succeeds, or one of the following * negative error codes: * - * :macro:`NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM` - * The required parameter is missing. * :macro:`NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM` * The input is malformed. */ -NGTCP2_EXTERN int ngtcp2_decode_transport_params_versioned( - int transport_params_version, ngtcp2_transport_params *params, - ngtcp2_transport_params_type exttype, const uint8_t *data, size_t datalen); +NGTCP2_EXTERN int +ngtcp2_transport_params_decode_versioned(int transport_params_version, + ngtcp2_transport_params *params, + const uint8_t *data, size_t datalen); /** * @function * - * `ngtcp2_decode_transport_params_new` decodes transport parameters + * `ngtcp2_transport_params_decode_new` decodes transport parameters * in |data| of length |datalen|, and stores the result in the object * allocated dynamically. The pointer to the allocated object is - * assigned to |*pparams|. Unlike `ngtcp2_decode_transport_params`, + * assigned to |*pparams|. Unlike `ngtcp2_transport_params_decode`, * all direct and indirect fields are also allocated dynamically if * needed. * @@ -2261,22 +2132,21 @@ NGTCP2_EXTERN int ngtcp2_decode_transport_params_versioned( * This function returns 0 if it succeeds, or one of the following * negative error codes: * - * :macro:`NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM` - * The required parameter is missing. * :macro:`NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM` * The input is malformed. * :macro:`NGTCP2_ERR_NOMEM` * Out of memory. */ -NGTCP2_EXTERN int ngtcp2_decode_transport_params_new( - ngtcp2_transport_params **pparams, ngtcp2_transport_params_type exttype, - const uint8_t *data, size_t datalen, const ngtcp2_mem *mem); +NGTCP2_EXTERN int +ngtcp2_transport_params_decode_new(ngtcp2_transport_params **pparams, + const uint8_t *data, size_t datalen, + const ngtcp2_mem *mem); /** * @function * * `ngtcp2_transport_params_del` frees the |params| which must be - * dynamically allocated by `ngtcp2_decode_transport_params_new`. + * dynamically allocated by `ngtcp2_transport_params_decode_new`. * * |mem| is a memory allocator that allocated |params|. If |mem| is * ``NULL``, the memory allocator returned by `ngtcp2_mem_default()` @@ -2331,15 +2201,16 @@ typedef struct ngtcp2_version_cid { * QUIC version. * * If the given packet is Long header packet, this function extracts - * the version from the packet and assigns it to + * the version from the packet, and assigns it to * :member:`dest->version `. It also * extracts the pointer to the Destination Connection ID and its - * length and assigns them to :member:`dest->dcid + * length, and assigns them to :member:`dest->dcid * ` and :member:`dest->dcidlen * ` respectively. Similarly, it extracts - * the pointer to the Source Connection ID and its length and assigns + * the pointer to the Source Connection ID and its length, and assigns * them to :member:`dest->scid ` and * :member:`dest->scidlen ` respectively. + * |short_dcidlen| is ignored. * * If the given packet is Short header packet, :member:`dest->version * ` will be 0, :member:`dest->scid @@ -2348,7 +2219,7 @@ typedef struct ngtcp2_version_cid { * Because the Short header packet does not have the length of * Destination Connection ID, the caller has to pass the length in * |short_dcidlen|. This function extracts the pointer to the - * Destination Connection ID and assigns it to :member:`dest->dcid + * Destination Connection ID, and assigns it to :member:`dest->dcid * `. |short_dcidlen| is assigned to * :member:`dest->dcidlen `. * @@ -2408,12 +2279,12 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, /** * @function * - * `ngtcp2_pkt_decode_hd_short` decodes QUIC short header packet - * header in |pkt| of length |pktlen|. |dcidlen| is the length of - * DCID in packet header. Short header packet does not encode the - * length of connection ID, thus we need the input from the outside. - * This function only parses the input just before packet number - * field. This function can handle Connection ID up to + * `ngtcp2_pkt_decode_hd_short` decodes QUIC short header in |pkt| of + * length |pktlen|. Short header packet does not encode the length of + * Connection ID, thus we need the input from the outside. |dcidlen| + * is the length of Destination Connection ID in packet header. This + * function only parses the input just before packet number field. + * This function can handle Connection ID up to * :macro:`NGTCP2_MAX_CIDLEN`. Consider to use * `ngtcp2_pkt_decode_version_cid` to get longer Connection ID. It * stores the result in the object pointed by |dest|, and returns the @@ -2461,13 +2332,13 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_stateless_reset( * * `ngtcp2_pkt_write_version_negotiation` writes Version Negotiation * packet in the buffer pointed by |dest| whose length is |destlen|. - * |unused_random| should be generated randomly. |dcid| is the - * destination connection ID which appears in a packet as a source - * connection ID sent by client which caused version negotiation. - * Similarly, |scid| is the source connection ID which appears in a - * packet as a destination connection ID sent by client. |sv| is a - * list of supported versions, and |nsv| specifies the number of - * supported versions included in |sv|. + * |unused_random| should be generated randomly. |dcid| is a + * Connection ID which appeared in a packet as a Source Connection ID + * sent by client which caused version negotiation. Similarly, |scid| + * is a Connection ID which appeared in a packet as a Destination + * Connection ID sent by client. |sv| is a list of supported + * versions, and |nsv| specifies the number of supported versions + * included in |sv|. * * This function returns the number of bytes written to the buffer, or * one of the following negative error codes: @@ -2494,7 +2365,7 @@ typedef struct ngtcp2_conn ngtcp2_conn; * asks TLS stack to produce first TLS cryptographic handshake data. * * This implementation of this callback must get the first handshake - * data from TLS stack and pass it to ngtcp2 library using + * data from TLS stack, and pass it to ngtcp2 library using * `ngtcp2_conn_submit_crypto_data` function. Make sure that before * calling `ngtcp2_conn_submit_crypto_data` function, client * application must create initial packet protection keys and IVs, and @@ -2514,9 +2385,9 @@ typedef int (*ngtcp2_client_initial)(ngtcp2_conn *conn, void *user_data); * Initial packet from client. An server application must implement * this callback, and generate initial keys and IVs for both * transmission and reception. Install them using - * `ngtcp2_conn_install_initial_key`. |dcid| is the destination - * connection ID which client generated randomly. It is used to - * derive initial packet protection keys. + * `ngtcp2_conn_install_initial_key`. |dcid| is the Destination + * Connection ID in Initial packet received from client. It is used + * to derive initial packet protection keys. * * The callback function must return 0 if it succeeds. If an error * occurs, return :macro:`NGTCP2_ERR_CALLBACK_FAILURE` which makes the @@ -2529,45 +2400,42 @@ typedef int (*ngtcp2_recv_client_initial)(ngtcp2_conn *conn, /** * @enum * - * :type:`ngtcp2_crypto_level` is encryption level. + * :type:`ngtcp2_encryption_level` is QUIC encryption level. */ -typedef enum ngtcp2_crypto_level { +typedef enum ngtcp2_encryption_level { /** - * :enum:`NGTCP2_CRYPTO_LEVEL_INITIAL` is Initial Keys encryption + * :enum:`NGTCP2_ENCRYPTION_LEVEL_INITIAL` is Initial encryption * level. */ - NGTCP2_CRYPTO_LEVEL_INITIAL, + NGTCP2_ENCRYPTION_LEVEL_INITIAL, /** - * :enum:`NGTCP2_CRYPTO_LEVEL_HANDSHAKE` is Handshake Keys - * encryption level. + * :enum:`NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE` is Handshake encryption + * level. */ - NGTCP2_CRYPTO_LEVEL_HANDSHAKE, + NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE, /** - * :enum:`NGTCP2_CRYPTO_LEVEL_APPLICATION` is Application Data - * (1-RTT) Keys encryption level. + * :enum:`NGTCP2_ENCRYPTION_LEVEL_1RTT` is 1-RTT encryption level. */ - NGTCP2_CRYPTO_LEVEL_APPLICATION, + NGTCP2_ENCRYPTION_LEVEL_1RTT, /** - * :enum:`NGTCP2_CRYPTO_LEVEL_EARLY` is Early Data (0-RTT) Keys - * encryption level. + * :enum:`NGTCP2_ENCRYPTION_LEVEL_0RTT` is 0-RTT encryption level. */ - NGTCP2_CRYPTO_LEVEL_EARLY -} ngtcp2_crypto_level; + NGTCP2_ENCRYPTION_LEVEL_0RTT +} ngtcp2_encryption_level; /** * @functypedef * * :type`ngtcp2_recv_crypto_data` is invoked when crypto data is - * received. The received data is pointed to by |data|, and its - * length is |datalen|. The |offset| specifies the offset where - * |data| is positioned. |user_data| is the arbitrary pointer passed - * to `ngtcp2_conn_client_new` or `ngtcp2_conn_server_new`. The - * ngtcp2 library ensures that the crypto data is passed to the - * application in the increasing order of |offset|. |datalen| is - * always strictly greater than 0. |crypto_level| indicates the - * encryption level where this data is received. Crypto data can - * never be received in - * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_EARLY`. + * received. The received data is pointed by |data|, and its length + * is |datalen|. The |offset| specifies the offset where |data| is + * positioned. |user_data| is the arbitrary pointer passed to + * `ngtcp2_conn_client_new` or `ngtcp2_conn_server_new`. The ngtcp2 + * library ensures that the crypto data is passed to the application + * in the increasing order of |offset|. |datalen| is always strictly + * greater than 0. |encryption_level| indicates the encryption level + * where this data is received. Crypto data can never be received in + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`. * * The application should provide the given data to TLS stack. * @@ -2591,7 +2459,7 @@ typedef enum ngtcp2_crypto_level { * return immediately. */ typedef int (*ngtcp2_recv_crypto_data)(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, + ngtcp2_encryption_level encryption_level, uint64_t offset, const uint8_t *data, size_t datalen, void *user_data); @@ -2645,9 +2513,9 @@ typedef int (*ngtcp2_recv_version_negotiation)(ngtcp2_conn *conn, * This callback is client use only. * * Application must regenerate packet protection key, IV, and header - * protection key for Initial packets using the destination connection - * ID obtained by :member:`hd->scid ` and install - * them by calling `ngtcp2_conn_install_initial_key()`. + * protection key for Initial packets using the Destination Connection + * ID obtained by :member:`hd->scid `, and install + * them by calling `ngtcp2_conn_install_initial_key`. * * 0-RTT data accepted by the ngtcp2 library will be automatically * retransmitted as 0-RTT data by the library. @@ -2666,12 +2534,12 @@ typedef int (*ngtcp2_recv_retry)(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, * application to encrypt packet payload. The packet payload to * encrypt is passed as |plaintext| of length |plaintextlen|. The * AEAD cipher is |aead|. |aead_ctx| is the AEAD cipher context - * object which is initialized with encryption key. The nonce is - * passed as |nonce| of length |noncelen|. The Additional + * object which is initialized with the specific encryption key. The + * nonce is passed as |nonce| of length |noncelen|. The Additional * Authenticated Data is passed as |aad| of length |aadlen|. * * The implementation of this callback must encrypt |plaintext| using - * the negotiated cipher suite and write the ciphertext into the + * the negotiated cipher suite, and write the ciphertext into the * buffer pointed by |dest|. |dest| has enough capacity to store the * ciphertext and any additional AEAD tag data. * @@ -2694,12 +2562,12 @@ typedef int (*ngtcp2_encrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead, * application to decrypt packet payload. The packet payload to * decrypt is passed as |ciphertext| of length |ciphertextlen|. The * AEAD cipher is |aead|. |aead_ctx| is the AEAD cipher context - * object which is initialized with decryption key. The nonce is - * passed as |nonce| of length |noncelen|. The Additional + * object which is initialized with the specific decryption key. The + * nonce is passed as |nonce| of length |noncelen|. The Additional * Authenticated Data is passed as |aad| of length |aadlen|. * * The implementation of this callback must decrypt |ciphertext| using - * the negotiated cipher suite and write the ciphertext into the + * the negotiated cipher suite, and write the ciphertext into the * buffer pointed by |dest|. |dest| has enough capacity to store the * cleartext. * @@ -2722,12 +2590,12 @@ typedef int (*ngtcp2_decrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead, * :type:`ngtcp2_hp_mask` is invoked when the ngtcp2 library asks the * application to produce a mask to encrypt or decrypt packet header. * The encryption cipher is |hp|. |hp_ctx| is the cipher context - * object which is initialized with header protection key. The sample - * is passed as |sample| which is :macro:`NGTCP2_HP_SAMPLELEN` bytes - * long. + * object which is initialized with the specific header protection + * key. The sample is passed as |sample| which is + * :macro:`NGTCP2_HP_SAMPLELEN` bytes long. * * The implementation of this callback must produce a mask using the - * header protection cipher suite specified by QUIC specification and + * header protection cipher suite specified by QUIC specification, and * write the result into the buffer pointed by |dest|. The length of * the mask must be at least :macro:`NGTCP2_HP_MASKLEN`. The library * only uses the first :macro:`NGTCP2_HP_MASKLEN` bytes of the @@ -2746,7 +2614,7 @@ typedef int (*ngtcp2_hp_mask)(uint8_t *dest, const ngtcp2_crypto_cipher *hp, /** * @macrosection * - * Stream data flags + * STREAM frame data flags */ /** @@ -2767,11 +2635,11 @@ typedef int (*ngtcp2_hp_mask)(uint8_t *dest, const ngtcp2_crypto_cipher *hp, /** * @macro * - * :macro:`NGTCP2_STREAM_DATA_FLAG_EARLY` indicates that this chunk of - * data contains data received in 0RTT packet and the handshake has + * :macro:`NGTCP2_STREAM_DATA_FLAG_0RTT` indicates that this chunk of + * data contains data received in 0-RTT packet, and the handshake has * not completed yet, which means that the data might be replayed. */ -#define NGTCP2_STREAM_DATA_FLAG_EARLY 0x02u +#define NGTCP2_STREAM_DATA_FLAG_0RTT 0x02u /** * @functypedef @@ -2787,9 +2655,9 @@ typedef int (*ngtcp2_hp_mask)(uint8_t *dest, const ngtcp2_crypto_cipher *hp, * overlap. The data is passed as |data| of length |datalen|. * |datalen| may be 0 if and only if |fin| is nonzero. * - * If :macro:`NGTCP2_STREAM_DATA_FLAG_EARLY` is set in |flags|, it - * indicates that a part of or whole data was received in 0RTT packet - * and a handshake has not completed yet. + * If :macro:`NGTCP2_STREAM_DATA_FLAG_0RTT` is set in |flags|, it + * indicates that a part of or whole data was received in 0-RTT + * packet, and a handshake has not completed yet. * * The callback function must return 0 if it succeeds, or * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` which makes the library return @@ -2804,9 +2672,9 @@ typedef int (*ngtcp2_recv_stream_data)(ngtcp2_conn *conn, uint32_t flags, * @functypedef * * :type:`ngtcp2_stream_open` is a callback function which is called - * when remote stream is opened by peer. This function is not called - * if stream is opened by implicitly (we might reconsider this - * behaviour). + * when remote stream is opened by a remote endpoint. This function + * is not called if stream is opened by implicitly (we might + * reconsider this behaviour later). * * The implementation of this callback should return 0 if it succeeds. * Returning :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library @@ -2883,16 +2751,19 @@ typedef int (*ngtcp2_stream_reset)(ngtcp2_conn *conn, int64_t stream_id, * @functypedef * * :type:`ngtcp2_acked_stream_data_offset` is a callback function - * which is called when stream data is acked, and application can free - * the data. The acked range of data is [offset, offset + datalen). - * For a given stream_id, this callback is called sequentially in - * increasing order of |offset| without any overlap. |datalen| is - * normally strictly greater than 0. One exception is that when a - * packet which includes STREAM frame which has fin flag set, and 0 - * length data, this callback is invoked with 0 passed as |datalen|. - * - * If a stream is closed prematurely and stream data is still + * which is called when stream data in range [|offset|, |offset| + + * |datalen|) is acknowledged, and application can free the portion of + * data. For a given |stream_id|, this callback is called + * sequentially in increasing order of |offset| without any overlap. + * |datalen| is normally strictly greater than 0. One exception is + * that when a STREAM frame has fin flag set and 0 length data, this + * callback is invoked with |datalen| == 0. + * + * If a stream is closed prematurely, and stream data is still * in-flight, this callback function is not called for those data. + * After :member:`ngtcp2_callbacks.stream_close` is called for a + * particular stream, |conn| does not touch data for the closed stream + * again, and application can free all unacknowledged stream data. * * The implementation of this callback should return 0 if it succeeds. * Returning :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library @@ -2938,7 +2809,7 @@ typedef int (*ngtcp2_extend_max_streams)(ngtcp2_conn *conn, * :type:`ngtcp2_extend_max_stream_data` is a callback function which * is invoked when max stream data is extended. |stream_id| * identifies the stream. |max_data| is a cumulative number of bytes - * the endpoint can send on this stream. + * an endpoint can send on this stream. * * The callback function must return 0 if it succeeds. Returning * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return @@ -2952,10 +2823,10 @@ typedef int (*ngtcp2_extend_max_stream_data)(ngtcp2_conn *conn, /** * @functypedef * - * :type:`ngtcp2_rand` is a callback function to get randomized byte - * string from application. Application must fill random |destlen| - * bytes to the buffer pointed by |dest|. The generated bytes are - * used only in non-cryptographic context. + * :type:`ngtcp2_rand` is a callback function to get random data of + * length |destlen|. Application must fill random |destlen| bytes to + * the buffer pointed by |dest|. The generated data is used only in + * non-cryptographic context. */ typedef void (*ngtcp2_rand)(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx); @@ -2965,11 +2836,11 @@ typedef void (*ngtcp2_rand)(uint8_t *dest, size_t destlen, * * :type:`ngtcp2_get_new_connection_id` is a callback function to ask * an application for new connection ID. Application must generate - * new unused connection ID with the exact |cidlen| bytes and store it - * in |cid|. It also has to generate stateless reset token into - * |token|. The length of stateless reset token is + * new unused connection ID with the exact |cidlen| bytes, and store + * it in |cid|. It also has to generate a stateless reset token, and + * store it in |token|. The length of stateless reset token is * :macro:`NGTCP2_STATELESS_RESET_TOKENLEN` and it is guaranteed that - * the buffer pointed by |cid| has the sufficient space to store the + * the buffer pointed by |token| has the sufficient space to store the * token. * * The callback function must return 0 if it succeeds. Returning @@ -2985,7 +2856,9 @@ typedef int (*ngtcp2_get_new_connection_id)(ngtcp2_conn *conn, ngtcp2_cid *cid, * * :type:`ngtcp2_remove_connection_id` is a callback function which * notifies the application that connection ID |cid| is no longer used - * by remote endpoint. + * by a remote endpoint. This Connection ID was previously offered by + * a local endpoint, and a remote endpoint could use it as Destination + * Connection ID when sending QUIC packet. * * The callback function must return 0 if it succeeds. Returning * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return @@ -3005,15 +2878,15 @@ typedef int (*ngtcp2_remove_connection_id)(ngtcp2_conn *conn, * |current_tx_secret| of length |secretlen|. They are decryption and * encryption secrets respectively. * - * The application has to generate new secrets and keys for both - * encryption and decryption, and write decryption secret and IV to - * the buffer pointed by |rx_secret| and |rx_iv| respectively. It - * also has to create new AEAD cipher context object with new - * decryption key and initialize |rx_aead_ctx| with it. Similarly, - * write encryption secret and IV to the buffer pointed by |tx_secret| - * and |tx_iv|. Create new AEAD cipher context object with new - * encryption key and initialize |tx_aead_ctx| with it. All given - * buffers have the enough capacity to store secret, key and IV. + * The application must generate new secrets and keys for both + * encryption and decryption. It must write decryption secret and IV + * to the buffer pointed by |rx_secret| and |rx_iv| respectively. It + * also must create new AEAD cipher context object with new decryption + * key and initialize |rx_aead_ctx| with it. Similarly, write + * encryption secret and IV to the buffer pointed by |tx_secret| and + * |tx_iv|. Create new AEAD cipher context object with new encryption + * key and initialize |tx_aead_ctx| with it. All given buffers have + * the enough capacity to store secret, key and IV. * * The callback function must return 0 if it succeeds. Returning * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return @@ -3048,14 +2921,25 @@ typedef int (*ngtcp2_update_key)( */ #define NGTCP2_PATH_VALIDATION_FLAG_PREFERRED_ADDR 0x01u +/** + * @macro + * + * :macro:`NGTCP2_PATH_VALIDATION_FLAG_NEW_TOKEN` indicates that + * server should send NEW_TOKEN frame for the new remote address. + * This flag is only set for server. + */ +#define NGTCP2_PATH_VALIDATION_FLAG_NEW_TOKEN 0x02u + /** * @functypedef * * :type:`ngtcp2_path_validation` is a callback function which tells - * the application the outcome of path validation. |flags| is zero or + * an application the outcome of path validation. |flags| is zero or * more of :macro:`NGTCP2_PATH_VALIDATION_FLAG_* * `. |path| is the path that was - * validated. If |res| is + * validated. |old_path| is the path that is previously used before a + * local endpoint has migrated to |path| if |old_path| is not NULL. + * If |res| is * :enum:`ngtcp2_path_validation_result.NGTCP2_PATH_VALIDATION_RESULT_SUCCESS`, * the path validation succeeded. If |res| is * :enum:`ngtcp2_path_validation_result.NGTCP2_PATH_VALIDATION_RESULT_FAILURE`, @@ -3067,6 +2951,7 @@ typedef int (*ngtcp2_update_key)( */ typedef int (*ngtcp2_path_validation)(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path, + const ngtcp2_path *old_path, ngtcp2_path_validation_result res, void *user_data); @@ -3087,10 +2972,10 @@ typedef int (*ngtcp2_path_validation)(ngtcp2_conn *conn, uint32_t flags, * from `ngtcp2_conn_get_path()`. Both :member:`dest->local.addr * ` and :member:`dest->remote.addr * ` point to buffers which are at least - * ``sizeof(struct sockaddr_storage)`` bytes long, respectively. If + * sizeof(:type:`ngtcp2_sockaddr_union`) bytes long, respectively. If * an application denies the preferred addresses, just leave |dest| * unmodified (or set :member:`dest->remote.addrlen - * ` to 0) and return 0. + * ` to 0), and return 0. * * The callback function must return 0 if it succeeds. Returning * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return @@ -3110,12 +2995,12 @@ typedef int (*ngtcp2_select_preferred_addr)(ngtcp2_conn *conn, typedef enum ngtcp2_connection_id_status_type { /** * :enum:`NGTCP2_CONNECTION_ID_STATUS_TYPE_ACTIVATE` indicates that - * a local endpoint starts using new destination Connection ID. + * a local endpoint starts using new Destination Connection ID. */ NGTCP2_CONNECTION_ID_STATUS_TYPE_ACTIVATE, /** * :enum:`NGTCP2_CONNECTION_ID_STATUS_TYPE_DEACTIVATE` indicates - * that a local endpoint stops using a given destination Connection + * that a local endpoint stops using a given Destination Connection * ID. */ NGTCP2_CONNECTION_ID_STATUS_TYPE_DEACTIVATE @@ -3125,9 +3010,9 @@ typedef enum ngtcp2_connection_id_status_type { * @functypedef * * :type:`ngtcp2_connection_id_status` is a callback function which is - * called when the status of Connection ID changes. + * called when the status of Destination Connection ID changes. * - * |token| is the associated stateless reset token and it is ``NULL`` + * |token| is the associated stateless reset token, and it is ``NULL`` * if no token is present. * * |type| is the one of the value defined in @@ -3138,25 +3023,25 @@ typedef enum ngtcp2_connection_id_status_type { * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return * immediately. */ -typedef int (*ngtcp2_connection_id_status)(ngtcp2_conn *conn, int type, - uint64_t seq, const ngtcp2_cid *cid, - const uint8_t *token, - void *user_data); +typedef int (*ngtcp2_connection_id_status)( + ngtcp2_conn *conn, ngtcp2_connection_id_status_type type, uint64_t seq, + const ngtcp2_cid *cid, const uint8_t *token, void *user_data); /** * @functypedef * * :type:`ngtcp2_recv_new_token` is a callback function which is - * called when new token is received from server. + * called when new token is received from server. This callback is + * client use only. * - * |token| is the received token. + * |token| is the received token of length |tokenlen| bytes long. * * The callback function must return 0 if it succeeds. Returning * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return * immediately. */ -typedef int (*ngtcp2_recv_new_token)(ngtcp2_conn *conn, const ngtcp2_vec *token, - void *user_data); +typedef int (*ngtcp2_recv_new_token)(ngtcp2_conn *conn, const uint8_t *token, + size_t tokenlen, void *user_data); /** * @functypedef @@ -3184,7 +3069,7 @@ typedef void (*ngtcp2_delete_crypto_cipher_ctx)( /** * @macrosection * - * Datagram flags + * DATAGRAM frame flags */ /** @@ -3197,11 +3082,11 @@ typedef void (*ngtcp2_delete_crypto_cipher_ctx)( /** * @macro * - * :macro:`NGTCP2_DATAGRAM_FLAG_EARLY` indicates that DATAGRAM frame - * is received in 0RTT packet and the handshake has not completed yet, + * :macro:`NGTCP2_DATAGRAM_FLAG_0RTT` indicates that DATAGRAM frame is + * received in 0-RTT packet, and the handshake has not completed yet, * which means that the data might be replayed. */ -#define NGTCP2_DATAGRAM_FLAG_EARLY 0x01u +#define NGTCP2_DATAGRAM_FLAG_0RTT 0x01u /** * @functypedef @@ -3210,8 +3095,8 @@ typedef void (*ngtcp2_delete_crypto_cipher_ctx)( * received. |flags| is bitwise-OR of zero or more of * :macro:`NGTCP2_DATAGRAM_FLAG_* `. * - * If :macro:`NGTCP2_DATAGRAM_FLAG_EARLY` is set in |flags|, it - * indicates that DATAGRAM frame was received in 0RTT packet and a + * If :macro:`NGTCP2_DATAGRAM_FLAG_0RTT` is set in |flags|, it + * indicates that DATAGRAM frame was received in 0-RTT packet, and a * handshake has not completed yet. * * The callback function must return 0 if it succeeds, or @@ -3257,8 +3142,8 @@ typedef int (*ngtcp2_lost_datagram)(ngtcp2_conn *conn, uint64_t dgram_id, * * :type:`ngtcp2_get_path_challenge_data` is a callback function to * ask an application for new data that is sent in PATH_CHALLENGE - * frame. Application must generate new unpredictable exactly - * :macro:`NGTCP2_PATH_CHALLENGE_DATALEN` bytes of random data and + * frame. Application must generate new unpredictable, exactly + * :macro:`NGTCP2_PATH_CHALLENGE_DATALEN` bytes of random data, and * store them into the buffer pointed by |data|. * * The callback function must return 0 if it succeeds. Returning @@ -3296,8 +3181,9 @@ typedef int (*ngtcp2_stream_stop_sending)(ngtcp2_conn *conn, int64_t stream_id, * server, it is called once when the version is negotiated. * * The implementation of this callback must install new Initial keys - * for |version|. Use `ngtcp2_conn_install_vneg_initial_key` to - * install keys. + * for |version| and Destination Connection ID |client_dcid| from + * client. Use `ngtcp2_conn_install_vneg_initial_key` to install + * keys. * * The callback function must return 0 if it succeeds. Returning * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return @@ -3317,11 +3203,25 @@ typedef int (*ngtcp2_version_negotiation)(ngtcp2_conn *conn, uint32_t version, * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return * immediately. */ -typedef int (*ngtcp2_recv_key)(ngtcp2_conn *conn, ngtcp2_crypto_level level, +typedef int (*ngtcp2_recv_key)(ngtcp2_conn *conn, ngtcp2_encryption_level level, void *user_data); -#define NGTCP2_CALLBACKS_VERSION_V1 1 -#define NGTCP2_CALLBACKS_VERSION NGTCP2_CALLBACKS_VERSION_V1 +/** + * @functypedef + * + * :type:`ngtcp2_tls_early_data_rejected` is invoked when early data + * was rejected by server during TLS handshake, or client decided not + * to attempt early data. + * + * The callback function must return 0 if it succeeds. Returning + * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return + * immediately. + */ +typedef int (*ngtcp2_tls_early_data_rejected)(ngtcp2_conn *conn, + void *user_data); + +#define NGTCP2_CALLBACKS_V1 1 +#define NGTCP2_CALLBACKS_VERSION NGTCP2_CALLBACKS_V1 /** * @struct @@ -3338,8 +3238,9 @@ typedef struct ngtcp2_callbacks { ngtcp2_client_initial client_initial; /** * :member:`recv_client_initial` is a callback function which is - * invoked when a server receives the first packet from client. - * This callback function must be specified for a server application. + * invoked when a server receives the first Initial packet from + * client. This callback function must be specified for a server + * application. */ ngtcp2_recv_client_initial recv_client_initial; /** @@ -3373,23 +3274,23 @@ typedef struct ngtcp2_callbacks { ngtcp2_decrypt decrypt; /** * :member:`hp_mask` is a callback function which is invoked to get - * a mask to encrypt or decrypt packet header. This callback + * a mask to encrypt or decrypt QUIC packet header. This callback * function must be specified. */ ngtcp2_hp_mask hp_mask; /** * :member:`recv_stream_data` is a callback function which is - * invoked when STREAM data, which includes application data, is + * invoked when stream data, which includes application data, is * received. This callback function is optional. */ ngtcp2_recv_stream_data recv_stream_data; /** * :member:`acked_stream_data_offset` is a callback function which - * is invoked when STREAM data, which includes application data, is + * is invoked when stream data, which includes application data, is * acknowledged by a remote endpoint. It tells an application the - * largest offset of acknowledged STREAM data without a gap so that - * application can free memory for the data. This callback function - * is optional. + * largest offset of acknowledged stream data without a gap so that + * application can free memory for the data up to that offset. This + * callback function is optional. */ ngtcp2_acked_stream_data_offset acked_stream_data_offset; /** @@ -3431,8 +3332,8 @@ typedef struct ngtcp2_callbacks { ngtcp2_extend_max_streams extend_max_local_streams_uni; /** * :member:`rand` is a callback function which is invoked when the - * library needs sequence of random data. This callback function - * must be specified. + * library needs random data. This callback function must be + * specified. */ ngtcp2_rand rand; /** @@ -3450,7 +3351,7 @@ typedef struct ngtcp2_callbacks { /** * :member:`update_key` is a callback function which is invoked when * the library tells an application that it must update keying - * materials and install new keys. This callback function must be + * materials, and install new keys. This callback function must be * specified. */ ngtcp2_update_key update_key; @@ -3463,8 +3364,8 @@ typedef struct ngtcp2_callbacks { /** * :member:`select_preferred_addr` is a callback function which is * invoked when the library asks a client to select preferred - * address presented by a server. This callback function is - * optional. + * address presented by a server. If not set, client ignores + * preferred addresses. This callback function is optional. */ ngtcp2_select_preferred_addr select_preferred_addr; /** @@ -3489,24 +3390,24 @@ typedef struct ngtcp2_callbacks { ngtcp2_extend_max_streams extend_max_remote_streams_uni; /** * :member:`extend_max_stream_data` is callback function which is - * invoked when the maximum offset of STREAM data that a local + * invoked when the maximum offset of stream data that a local * endpoint can send is increased. This callback function is * optional. */ ngtcp2_extend_max_stream_data extend_max_stream_data; /** * :member:`dcid_status` is a callback function which is invoked - * when the new destination Connection ID is activated or the - * activated destination Connection ID is now deactivated. This + * when the new Destination Connection ID is activated, or the + * activated Destination Connection ID is now deactivated. This * callback function is optional. */ ngtcp2_connection_id_status dcid_status; /** * :member:`handshake_confirmed` is a callback function which is * invoked when both endpoints agree that handshake has finished. - * This field is ignored by server because handshake_completed - * indicates the handshake confirmation for server. This callback - * function is optional. + * This field is ignored by server because + * :member:`handshake_completed` also indicates the handshake + * confirmation for server. This callback function is optional. */ ngtcp2_handshake_confirmed handshake_confirmed; /** @@ -3535,20 +3436,20 @@ typedef struct ngtcp2_callbacks { ngtcp2_recv_datagram recv_datagram; /** * :member:`ack_datagram` is a callback function which is invoked - * when a packet containing DATAGRAM frame is acknowledged. This - * callback function is optional. + * when a QUIC packet containing DATAGRAM frame is acknowledged by a + * remote endpoint. This callback function is optional. */ ngtcp2_ack_datagram ack_datagram; /** * :member:`lost_datagram` is a callback function which is invoked - * when a packet containing DATAGRAM frame is declared lost. This - * callback function is optional. + * when a QUIC packet containing DATAGRAM frame is declared lost. + * This callback function is optional. */ ngtcp2_lost_datagram lost_datagram; /** * :member:`get_path_challenge_data` is a callback function which is - * invoked when the library needs new PATH_CHALLENGE data. This - * callback must be specified. + * invoked when the library needs new data sent along with + * PATH_CHALLENGE frame. This callback must be specified. */ ngtcp2_get_path_challenge_data get_path_challenge_data; /** @@ -3568,16 +3469,23 @@ typedef struct ngtcp2_callbacks { * :member:`recv_rx_key` is a callback function which is invoked * when a new key for decrypting packets is installed during QUIC * cryptographic handshake. It is not called for - * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_INITIAL`. + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_INITIAL`. */ ngtcp2_recv_key recv_rx_key; /** * :member:`recv_tx_key` is a callback function which is invoked * when a new key for encrypting packets is installed during QUIC * cryptographic handshake. It is not called for - * :enum:`ngtcp2_crypto_level.NGTCP2_CRYPTO_LEVEL_INITIAL`. + * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_INITIAL`. */ ngtcp2_recv_key recv_tx_key; + /** + * :member:`tls_early_data_rejected` is a callback function which is + * invoked when server rejected early data during TLS handshake, or + * client decided not to attempt early data. This callback function + * is only used by client. + */ + ngtcp2_tls_early_data_rejected tls_early_data_rejected; } ngtcp2_callbacks; /** @@ -3591,7 +3499,7 @@ typedef struct ngtcp2_callbacks { * * The primary use case of this function is for server to send * CONNECTION_CLOSE frame in Initial packet to close connection - * without committing the state when validating Retry token fails. + * without committing any state when validating Retry token fails. * * This function returns the number of bytes written if it succeeds, * or one of the following negative error codes: @@ -3613,11 +3521,11 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_connection_close( * @function * * `ngtcp2_pkt_write_retry` writes Retry packet in the buffer pointed - * by |dest| whose length is |destlen|. |dcid| is the destination - * connection ID which appeared in a packet as a source connection ID - * sent by client. |scid| is a server chosen source connection ID. - * |odcid| specifies Original Destination Connection ID which appeared - * in a packet as a destination connection ID sent by client. |token| + * by |dest| whose length is |destlen|. |dcid| is the Connection ID + * which appeared in a packet as a Source Connection ID sent by + * client. |scid| is a server chosen Source Connection ID. |odcid| + * specifies Original Destination Connection ID which appeared in a + * packet as a Destination Connection ID sent by client. |token| * specifies Retry Token, and |tokenlen| specifies its length. |aead| * must be AEAD_AES_128_GCM. |aead_ctx| must be initialized with * :macro:`NGTCP2_RETRY_KEY` as an encryption key. @@ -3644,17 +3552,14 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_retry( * * `ngtcp2_accept` is used by server implementation, and decides * whether packet |pkt| of length |pktlen| from client is acceptable - * for the very initial packet to a connection. + * for the very first packet to a connection. * - * If |dest| is not ``NULL`` and the function returns 0, or - * :macro:`NGTCP2_ERR_RETRY`, the decoded packet header is stored to - * the object pointed by |dest|. + * If |dest| is not ``NULL`` and the function returns 0, the decoded + * packet header is stored in the object pointed by |dest|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * - * :macro:`NGTCP2_ERR_RETRY` - * Retry packet should be sent. * :macro:`NGTCP2_ERR_INVALID_ARGUMENT` * The packet is not acceptable for the very first packet to a new * connection; or the function failed to parse the packet header. @@ -3666,17 +3571,21 @@ NGTCP2_EXTERN int ngtcp2_accept(ngtcp2_pkt_hd *dest, const uint8_t *pkt, * @function * * `ngtcp2_conn_client_new` creates new :type:`ngtcp2_conn`, and - * initializes it as client. |dcid| is randomized destination - * connection ID. |scid| is source connection ID. - * |client_chosen_version| is a QUIC version that a client chooses. - * |path| is the network path where this QUIC connection is being - * established and must not be ``NULL``. |callbacks|, |settings|, and - * |params| must not be ``NULL``, and the function make a copy of each - * of them. |params| is local QUIC transport parameters and sent to a - * remote endpoint during handshake. |user_data| is the arbitrary - * pointer which is passed to the user-defined callback functions. If - * |mem| is ``NULL``, the memory allocator returned by - * `ngtcp2_mem_default()` is used. + * initializes it as client. On success, it stores the pointer to the + * newly allocated object in |*pconn|. |dcid| is a randomized + * Destination Connection ID which must be longer than or equal to + * :macro:`NGTCP2_MIN_INITIAL_DCIDLEN`. |scid| is a Source Connection + * ID chosen by client. |client_chosen_version| is a QUIC version + * that a client chooses. |path| is the network path where this QUIC + * connection is being established, and must not be ``NULL``. + * |callbacks|, |settings|, and |params| must not be ``NULL``, and the + * function makes a copy of each of them. |params| is a local QUIC + * transport parameters, and sent to a remote endpoint during + * handshake. |user_data| is the arbitrary pointer which is passed to + * the user-defined callback functions. If |mem| is ``NULL``, the + * memory allocator returned by `ngtcp2_mem_default()` is used. + * + * Call `ngtcp2_conn_del` to free memory allocated for |*pconn|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -3696,16 +3605,22 @@ NGTCP2_EXTERN int ngtcp2_conn_client_new_versioned( * @function * * `ngtcp2_conn_server_new` creates new :type:`ngtcp2_conn`, and - * initializes it as server. |dcid| is a destination connection ID. - * |scid| is a source connection ID. |path| is the network path where - * this QUIC connection is being established and must not be ``NULL``. - * |client_chosen_version| is a QUIC version that a client chooses. - * |callbacks|, |settings|, and |params| must not be ``NULL``, and the - * function make a copy of each of them. |params| is local QUIC - * transport parameters and sent to a remote endpoint during - * handshake. |user_data| is the arbitrary pointer which is passed to - * the user-defined callback functions. If |mem| is ``NULL``, the - * memory allocator returned by `ngtcp2_mem_default()` is used. + * initializes it as server. On success, it stores the pointer to the + * newly allocated object in |*pconn|. |dcid| is a Destination + * Connection ID, and is usually the Connection ID that appears in + * client Initial packet as Source Connection ID. |scid| is a Source + * Connection ID chosen by server. |path| is the network path where + * this QUIC connection is being established, and must not be + * ``NULL``. |client_chosen_version| is a QUIC version that a client + * chooses. |callbacks|, |settings|, and |params| must not be + * ``NULL``, and the function makes a copy of each of them. |params| + * is a local QUIC transport parameters, and sent to a remote endpoint + * during handshake. |user_data| is the arbitrary pointer which is + * passed to the user-defined callback functions. If |mem| is + * ``NULL``, the memory allocator returned by `ngtcp2_mem_default()` + * is used. + * + * Call `ngtcp2_conn_del` to free memory allocated for |*pconn|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -3741,19 +3656,31 @@ NGTCP2_EXTERN void ngtcp2_conn_del(ngtcp2_conn *conn); * This function must not be called from inside the callback * functions. * - * This function returns 0 if it succeeds, or negative error codes. - * If :macro:`NGTCP2_ERR_RETRY` is returned, application must be a - * server and it must perform address validation by sending Retry - * packet and discard the connection state. If - * :macro:`NGTCP2_ERR_DROP_CONN` is returned, server application must - * drop the connection silently (without sending any CONNECTION_CLOSE - * frame) and discard connection state. If - * :macro:`NGTCP2_ERR_DRAINING` is returned, a connection has entered - * the draining state, and no further packet transmission is allowed. - * If :macro:`NGTCP2_ERR_CRYPTO` is returned, the error happened in - * TLS stack and `ngtcp2_conn_get_tls_alert` returns TLS alert if set. - * - * If any other negative errors are returned, call + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGTCP2_ERR_RETRY` + * Server must perform address validation by sending Retry packet + * (see `ngtcp2_crypto_write_retry` and `ngtcp2_pkt_write_retry`), + * and discard the connection state. Client application does not + * get this error code. + * :macro:`NGTCP2_ERR_DROP_CONN` + * Server application must drop the connection silently (without + * sending any CONNECTION_CLOSE frame), and discard connection + * state. Client application does not get this error code. + * :macro:`NGTCP2_ERR_DRAINING` + * A connection has entered the draining state, and no further + * packet transmission is allowed. + * :macro:`NGTCP2_ERR_CLOSING` + * A connection has entered the closing state, and no further + * packet transmission is allowed. Calling + * `ngtcp2_conn_write_connection_close` makes a connection enter + * this state. + * :macro:`NGTCP2_ERR_CRYPTO` + * An error happened in TLS stack. `ngtcp2_conn_get_tls_alert` + * returns TLS alert if set. + * + * If any other negative error is returned, call * `ngtcp2_conn_write_connection_close` to get terminal packet, and * sending it makes QUIC connection enter the closing state. */ @@ -3767,8 +3694,8 @@ ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, * @function * * `ngtcp2_conn_write_pkt` is equivalent to calling - * `ngtcp2_conn_writev_stream` with -1 as stream_id, no stream data, and - * :macro:`NGTCP2_WRITE_STREAM_FLAG_NONE` as flags. + * `ngtcp2_conn_writev_stream` with -1 as |stream_id|, no stream data, + * and :macro:`NGTCP2_WRITE_STREAM_FLAG_NONE` as flags. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_pkt_versioned( ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, @@ -3777,18 +3704,18 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_pkt_versioned( /** * @function * - * `ngtcp2_conn_handshake_completed` tells |conn| that the TLS stack - * declares TLS handshake completion. This does not mean QUIC + * `ngtcp2_conn_tls_handshake_completed` tells |conn| that the TLS + * stack declares TLS handshake completion. This does not mean QUIC * handshake has completed. The library needs extra conditions to be * met. */ -NGTCP2_EXTERN void ngtcp2_conn_handshake_completed(ngtcp2_conn *conn); +NGTCP2_EXTERN void ngtcp2_conn_tls_handshake_completed(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_get_handshake_completed` returns nonzero if QUIC handshake - * has completed. + * `ngtcp2_conn_get_handshake_completed` returns nonzero if QUIC + * handshake has completed. */ NGTCP2_EXTERN int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn); @@ -3797,11 +3724,11 @@ NGTCP2_EXTERN int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn); * * `ngtcp2_conn_install_initial_key` installs packet protection keying * materials for Initial packets. |rx_aead_ctx| is AEAD cipher - * context object and must be initialized with a decryption key. + * context object, and must be initialized with a decryption key. * |rx_iv| is IV of length |rx_ivlen| for decryption. |rx_hp_ctx| is * a packet header protection cipher context object for decryption. * Similarly, |tx_aead_ctx|, |tx_iv| and |tx_hp_ctx| are for - * encrypting outgoing packets and are the same length with the + * encrypting outgoing packets, and are the same length with the * decryption counterpart . If they have already been set, they are * overwritten. * @@ -3810,14 +3737,16 @@ NGTCP2_EXTERN int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn); * * If this function succeeds, |conn| takes ownership of |rx_aead_ctx|, * |rx_hp_ctx|, |tx_aead_ctx|, and |tx_hp_ctx|. - * :type:`ngtcp2_delete_crypto_aead_ctx` and - * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete - * these objects when they are no longer used. If this function - * fails, the caller is responsible to delete them. - * - * After receiving Retry packet, the DCID most likely changes. In - * that case, client application must generate these keying materials - * again based on new DCID and install them again. + * :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` and + * :member:`ngtcp2_callbacks.delete_crypto_cipher_ctx` will be called + * to delete these objects when they are no longer used. If this + * function fails, the caller is responsible to delete them. + * + * After receiving Retry packet, a Destination Connection ID that + * client sends in Initial packet most likely changes. In that case, + * client application must generate these keying materials again based + * on new Destination Connection ID, and install them again with this + * function. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -3837,11 +3766,11 @@ NGTCP2_EXTERN int ngtcp2_conn_install_initial_key( * `ngtcp2_conn_install_vneg_initial_key` installs packet protection * keying materials for Initial packets on compatible version * negotiation for |version|. |rx_aead_ctx| is AEAD cipher context - * object and must be initialized with a decryption key. |rx_iv| is + * object, and must be initialized with a decryption key. |rx_iv| is * IV of length |rx_ivlen| for decryption. |rx_hp_ctx| is a packet * header protection cipher context object for decryption. Similarly, * |tx_aead_ctx|, |tx_iv| and |tx_hp_ctx| are for encrypting outgoing - * packets and are the same length with the decryption counterpart . + * packets, and are the same length with the decryption counterpart. * If they have already been set, they are overwritten. * * |ivlen| must be the minimum length of AEAD nonce, or 8 bytes if @@ -3849,10 +3778,10 @@ NGTCP2_EXTERN int ngtcp2_conn_install_initial_key( * * If this function succeeds, |conn| takes ownership of |rx_aead_ctx|, * |rx_hp_ctx|, |tx_aead_ctx|, and |tx_hp_ctx|. - * :type:`ngtcp2_delete_crypto_aead_ctx` and - * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete - * these objects when they are no longer used. If this function - * fails, the caller is responsible to delete them. + * :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` and + * :member:`ngtcp2_callbacks.delete_crypto_cipher_ctx` will be called + * to delete these objects when they are no longer used. If this + * function fails, the caller is responsible to delete them. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -3880,10 +3809,10 @@ NGTCP2_EXTERN int ngtcp2_conn_install_vneg_initial_key( * that is larger. * * If this function succeeds, |conn| takes ownership of |aead_ctx|, - * and |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and - * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete - * these objects when they are no longer used. If this function - * fails, the caller is responsible to delete them. + * and |hp_ctx|. :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` + * and :member:`ngtcp2_callbacks.delete_crypto_cipher_ctx` will be + * called to delete these objects when they are no longer used. If + * this function fails, the caller is responsible to delete them. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -3908,10 +3837,10 @@ NGTCP2_EXTERN int ngtcp2_conn_install_rx_handshake_key( * that is larger. * * If this function succeeds, |conn| takes ownership of |aead_ctx| and - * |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and - * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete - * these objects when they are no longer used. If this function - * fails, the caller is responsible to delete them. + * |hp_ctx|. :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` and + * :member:`ngtcp2_callbacks.delete_crypto_cipher_ctx` will be called + * to delete these objects when they are no longer used. If this + * function fails, the caller is responsible to delete them. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -3926,19 +3855,19 @@ NGTCP2_EXTERN int ngtcp2_conn_install_tx_handshake_key( /** * @function * - * `ngtcp2_conn_install_early_key` installs packet protection AEAD + * `ngtcp2_conn_install_0rtt_key` installs packet protection AEAD * cipher context object |aead_ctx|, IV |iv| of length |ivlen|, and * packet header protection cipher context object |hp_ctx| to encrypt - * (for client) or decrypt (for server) 0RTT packets. + * (for client) or decrypt (for server) 0-RTT packets. * * |ivlen| must be the minimum length of AEAD nonce, or 8 bytes if * that is larger. * * If this function succeeds, |conn| takes ownership of |aead_ctx| and - * |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and - * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete - * these objects when they are no longer used. If this function - * fails, the caller is responsible to delete them. + * |hp_ctx|. :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` and + * :member:`ngtcp2_callbacks.delete_crypto_cipher_ctx` will be called + * to delete these objects when they are no longer used. If this + * function fails, the caller is responsible to delete them. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -3946,7 +3875,7 @@ NGTCP2_EXTERN int ngtcp2_conn_install_tx_handshake_key( * :macro:`NGTCP2_ERR_NOMEM` * Out of memory. */ -NGTCP2_EXTERN int ngtcp2_conn_install_early_key( +NGTCP2_EXTERN int ngtcp2_conn_install_0rtt_key( ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx); @@ -3954,7 +3883,7 @@ NGTCP2_EXTERN int ngtcp2_conn_install_early_key( * @function * * `ngtcp2_conn_install_rx_key` installs packet protection keying - * materials for decrypting Short header packets. |secret| of length + * materials for decrypting 1-RTT packets. |secret| of length * |secretlen| is the decryption secret which is used to derive keying * materials passed to this function. |aead_ctx| is AEAD cipher * context object which must be initialized with a decryption key. @@ -3965,10 +3894,10 @@ NGTCP2_EXTERN int ngtcp2_conn_install_early_key( * that is larger. * * If this function succeeds, |conn| takes ownership of |aead_ctx| and - * |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and - * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete - * these objects when they are no longer used. If this function - * fails, the caller is responsible to delete them. + * |hp_ctx|. :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` and + * :member:`ngtcp2_callbacks.delete_crypto_cipher_ctx` will be called + * to delete these objects when they are no longer used. If this + * function fails, the caller is responsible to delete them. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -3985,7 +3914,7 @@ NGTCP2_EXTERN int ngtcp2_conn_install_rx_key( * @function * * `ngtcp2_conn_install_tx_key` installs packet protection keying - * materials for encrypting Short header packets. |secret| of length + * materials for encrypting 1-RTT packets. |secret| of length * |secretlen| is the encryption secret which is used to derive keying * materials passed to this function. |aead_ctx| is AEAD cipher * context object which must be initialized with an encryption key. @@ -3996,10 +3925,10 @@ NGTCP2_EXTERN int ngtcp2_conn_install_rx_key( * that is larger. * * If this function succeeds, |conn| takes ownership of |aead_ctx| and - * |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and - * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete - * these objects when they are no longer used. If this function - * fails, the caller is responsible to delete them. + * |hp_ctx|. :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` and + * :member:`ngtcp2_callbacks.delete_crypto_cipher_ctx` will be called + * to delete these objects when they are no longer used. If this + * function fails, the caller is responsible to delete them. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -4035,10 +3964,12 @@ NGTCP2_EXTERN int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, * is defined as NGTCP2_ERR_* macro, such as * :macro:`NGTCP2_ERR_DECRYPT`). In general, error code should be * propagated via return value, but sometimes ngtcp2 API is called - * inside callback function of TLS stack and it does not allow to + * inside callback function of TLS stack, and it does not allow to * return ngtcp2 error code directly. In this case, implementation * can set the error code (e.g., * :macro:`NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM`) using this function. + * + * See also `ngtcp2_conn_get_tls_error`. */ NGTCP2_EXTERN void ngtcp2_conn_set_tls_error(ngtcp2_conn *conn, int liberr); @@ -4055,7 +3986,9 @@ NGTCP2_EXTERN int ngtcp2_conn_get_tls_error(ngtcp2_conn *conn); * @function * * `ngtcp2_conn_set_tls_alert` sets a TLS alert |alert| generated by a - * local endpoint to |conn|. + * TLS stack of a local endpoint to |conn|. + * + * See also `ngtcp2_conn_get_tls_alert`. */ NGTCP2_EXTERN void ngtcp2_conn_set_tls_alert(ngtcp2_conn *conn, uint8_t alert); @@ -4073,8 +4006,10 @@ NGTCP2_EXTERN uint8_t ngtcp2_conn_get_tls_alert(ngtcp2_conn *conn); * * `ngtcp2_conn_set_keep_alive_timeout` sets keep-alive timeout. If * nonzero value is given, after a connection is idle at least in a - * given amount of time, a keep-alive packet is sent. If 0 is set, - * keep-alive functionality is disabled and this is the default. + * given amount of time, a keep-alive packet is sent. If UINT64_MAX + * is set, keep-alive functionality is disabled, and this is the + * default. Specifying 0 in |timeout| is reserved for a future + * extension, and for now it is treated as if UINT64_MAX is given. */ NGTCP2_EXTERN void ngtcp2_conn_set_keep_alive_timeout(ngtcp2_conn *conn, ngtcp2_duration timeout); @@ -4082,18 +4017,19 @@ NGTCP2_EXTERN void ngtcp2_conn_set_keep_alive_timeout(ngtcp2_conn *conn, /** * @function * - * `ngtcp2_conn_get_expiry` returns the next expiry time. + * `ngtcp2_conn_get_expiry` returns the next expiry time. It returns + * ``UINT64_MAX`` if there is no next expiry. * - * Call `ngtcp2_conn_handle_expiry()` and `ngtcp2_conn_write_pkt` (or - * `ngtcp2_conn_writev_stream`) if expiry time is passed. + * Call `ngtcp2_conn_handle_expiry` and then + * `ngtcp2_conn_writev_stream` (or `ngtcp2_conn_writev_datagram`) when + * the expiry time has passed. */ NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_handle_expiry` handles expired timer. It does nothing - * if timer is not expired. + * `ngtcp2_conn_handle_expiry` handles expired timer. */ NGTCP2_EXTERN int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts); @@ -4108,9 +4044,9 @@ NGTCP2_EXTERN ngtcp2_duration ngtcp2_conn_get_pto(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_decode_remote_transport_params` decodes QUIC transport - * parameters from the buffer pointed by |data| of length |datalen|, - * and sets the result to |conn|. + * `ngtcp2_conn_decode_and_set_remote_transport_params` decodes QUIC + * transport parameters from the buffer pointed by |data| of length + * |datalen|, and sets the result to |conn|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -4126,9 +4062,8 @@ NGTCP2_EXTERN ngtcp2_duration ngtcp2_conn_get_pto(ngtcp2_conn *conn); * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` * User callback failed */ -NGTCP2_EXTERN int -ngtcp2_conn_decode_remote_transport_params(ngtcp2_conn *conn, - const uint8_t *data, size_t datalen); +NGTCP2_EXTERN int ngtcp2_conn_decode_and_set_remote_transport_params( + ngtcp2_conn *conn, const uint8_t *data, size_t datalen); /** * @function @@ -4143,36 +4078,77 @@ ngtcp2_conn_get_remote_transport_params(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_set_early_remote_transport_params` sets |params| as - * transport parameters previously received from a server. The - * parameters are used to send early data. QUIC requires that client - * application should remember transport parameters along with a - * session ticket. - * - * At least following fields should be set: - * - * - initial_max_stream_id_bidi - * - initial_max_stream_id_uni - * - initial_max_stream_data_bidi_local - * - initial_max_stream_data_bidi_remote - * - initial_max_stream_data_uni - * - initial_max_data - * - active_connection_id_limit - * - max_datagram_frame_size (if DATAGRAM extension was negotiated) - * - * The following fields are ignored: - * - * - ack_delay_exponent - * - max_ack_delay - * - initial_scid - * - original_dcid - * - preferred_address and preferred_address_present - * - retry_scid and retry_scid_present - * - stateless_reset_token and stateless_reset_token_present - */ -NGTCP2_EXTERN void ngtcp2_conn_set_early_remote_transport_params_versioned( - ngtcp2_conn *conn, int transport_params_version, - const ngtcp2_transport_params *params); + * `ngtcp2_conn_encode_0rtt_transport_params` encodes the QUIC + * transport parameters that are used for 0-RTT data in the buffer + * pointed by |dest| of length |destlen|. It includes at least the + * following fields: + * + * - :member:`ngtcp2_transport_params.initial_max_streams_bidi` + * - :member:`ngtcp2_transport_params.initial_max_streams_uni` + * - :member:`ngtcp2_transport_params.initial_max_stream_data_bidi_local` + * - :member:`ngtcp2_transport_params.initial_max_stream_data_bidi_remote` + * - :member:`ngtcp2_transport_params.initial_max_stream_data_uni` + * - :member:`ngtcp2_transport_params.initial_max_data` + * - :member:`ngtcp2_transport_params.active_connection_id_limit` + * - :member:`ngtcp2_transport_params.max_datagram_frame_size` + * + * If |conn| is initialized as server, the following additional fields + * are also included: + * + * - :member:`ngtcp2_transport_params.max_idle_timeout` + * - :member:`ngtcp2_transport_params.max_udp_payload_size` + * - :member:`ngtcp2_transport_params.disable_active_migration` + * + * If |conn| is initialized as client, these parameters are + * synthesized from the remote transport parameters received from + * server. Otherwise, it is the local transport parameters that are + * set by the local endpoint. + * + * This function returns the number of bytes written, or one of the + * following negative error codes: + * + * :macro:`NGTCP2_ERR_NOBUF` + * Buffer is too small. + */ +NGTCP2_EXTERN +ngtcp2_ssize ngtcp2_conn_encode_0rtt_transport_params(ngtcp2_conn *conn, + uint8_t *dest, + size_t destlen); + +/** + * @function + * + * `ngtcp2_conn_decode_and_set_0rtt_transport_params` decodes QUIC + * transport parameters from |data| of length |datalen|, which is + * assumed to be the parameters received from the server in the + * previous connection, and sets it to |conn|. These parameters are + * used to send 0-RTT data. QUIC requires that client application + * should remember transport parameters along with a session ticket. + * + * At least following fields should be included: + * + * - :member:`ngtcp2_transport_params.initial_max_streams_bidi` + * - :member:`ngtcp2_transport_params.initial_max_streams_uni` + * - :member:`ngtcp2_transport_params.initial_max_stream_data_bidi_local` + * - :member:`ngtcp2_transport_params.initial_max_stream_data_bidi_remote` + * - :member:`ngtcp2_transport_params.initial_max_stream_data_uni` + * - :member:`ngtcp2_transport_params.initial_max_data` + * - :member:`ngtcp2_transport_params.active_connection_id_limit` + * - :member:`ngtcp2_transport_params.max_datagram_frame_size` (if + * DATAGRAM extension was negotiated) + * + * This function must only be used by client. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGTCP2_ERR_NOMEM` + * Out of memory. + * :macro:`NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM` + * The input is malformed. + */ +NGTCP2_EXTERN int ngtcp2_conn_decode_and_set_0rtt_transport_params( + ngtcp2_conn *conn, const uint8_t *data, size_t datalen); /** * @function @@ -4182,7 +4158,7 @@ NGTCP2_EXTERN void ngtcp2_conn_set_early_remote_transport_params_versioned( * Although the local transport parameters are passed to * `ngtcp2_conn_server_new`, server might want to update them after * ALPN is chosen. In that case, server can update the transport - * parameter with this function. Server must call this function + * parameters with this function. Server must call this function * before calling `ngtcp2_conn_install_tx_handshake_key`. * * This function returns 0 if it succeeds, or one of the following @@ -4208,11 +4184,9 @@ ngtcp2_conn_get_local_transport_params(ngtcp2_conn *conn); * @function * * `ngtcp2_conn_encode_local_transport_params` encodes the local QUIC - * transport parameters in |dest| of length |destlen|. This is - * equivalent to calling `ngtcp2_conn_get_local_transport_params` and - * then `ngtcp2_encode_transport_params`. + * transport parameters in |dest| of length |destlen|. * - * This function returns the number of written, or one of the + * This function returns the number of bytes written, or one of the * following negative error codes: * * :macro:`NGTCP2_ERR_NOBUF` @@ -4226,16 +4200,16 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_encode_local_transport_params( * * `ngtcp2_conn_open_bidi_stream` opens new bidirectional stream. The * |stream_user_data| is the user data specific to the stream. The - * open stream ID is stored in |*pstream_id|. + * stream ID of the opened stream is stored in |*pstream_id|. * * Application can call this function before handshake completes. For - * 0RTT packet, application can call this function after calling - * `ngtcp2_conn_set_early_remote_transport_params`. For 1RTT packet, - * application can call this function after calling - * `ngtcp2_conn_decode_remote_transport_params` and + * 0-RTT packet, application can call this function after calling + * `ngtcp2_conn_decode_and_set_0rtt_transport_params`. For 1-RTT + * packet, application can call this function after calling + * `ngtcp2_conn_decode_and_set_remote_transport_params` and * `ngtcp2_conn_install_tx_key`. If ngtcp2 crypto support library is * used, application can call this function after calling - * `ngtcp2_crypto_derive_and_install_tx_key` for 1RTT packet. + * `ngtcp2_crypto_derive_and_install_tx_key` for 1-RTT packet. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -4243,7 +4217,7 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_encode_local_transport_params( * :macro:`NGTCP2_ERR_NOMEM` * Out of memory * :macro:`NGTCP2_ERR_STREAM_ID_BLOCKED` - * The remote peer does not allow |stream_id| yet. + * The remote endpoint does not allow |stream_id| yet. */ NGTCP2_EXTERN int ngtcp2_conn_open_bidi_stream(ngtcp2_conn *conn, int64_t *pstream_id, @@ -4254,16 +4228,16 @@ NGTCP2_EXTERN int ngtcp2_conn_open_bidi_stream(ngtcp2_conn *conn, * * `ngtcp2_conn_open_uni_stream` opens new unidirectional stream. The * |stream_user_data| is the user data specific to the stream. The - * open stream ID is stored in |*pstream_id|. + * stream ID of the opened stream is stored in |*pstream_id|. * * Application can call this function before handshake completes. For - * 0RTT packet, application can call this function after calling - * `ngtcp2_conn_set_early_remote_transport_params`. For 1RTT packet, - * application can call this function after calling - * `ngtcp2_conn_decode_remote_transport_params` and + * 0-RTT packet, application can call this function after calling + * `ngtcp2_conn_decode_and_set_0rtt_transport_params`. For 1-RTT + * packet, application can call this function after calling + * `ngtcp2_conn_decode_and_set_remote_transport_params` and * `ngtcp2_conn_install_tx_key`. If ngtcp2 crypto support library is * used, application can call this function after calling - * `ngtcp2_crypto_derive_and_install_tx_key` for 1RTT packet. + * `ngtcp2_crypto_derive_and_install_tx_key` for 1-RTT packet. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -4271,7 +4245,7 @@ NGTCP2_EXTERN int ngtcp2_conn_open_bidi_stream(ngtcp2_conn *conn, * :macro:`NGTCP2_ERR_NOMEM` * Out of memory * :macro:`NGTCP2_ERR_STREAM_ID_BLOCKED` - * The remote peer does not allow |stream_id| yet. + * The remote endpoint does not allow |stream_id| yet. */ NGTCP2_EXTERN int ngtcp2_conn_open_uni_stream(ngtcp2_conn *conn, int64_t *pstream_id, @@ -4280,14 +4254,23 @@ NGTCP2_EXTERN int ngtcp2_conn_open_uni_stream(ngtcp2_conn *conn, /** * @function * - * `ngtcp2_conn_shutdown_stream` closes stream denoted by |stream_id| - * abruptly. |app_error_code| is one of application error codes, and - * indicates the reason of shutdown. Successful call of this function - * does not immediately erase the state of the stream. The actual - * deletion is done when the remote endpoint sends acknowledgement. - * Calling this function is equivalent to call + * `ngtcp2_conn_shutdown_stream` closes a stream denoted by + * |stream_id| abruptly. |app_error_code| is one of application error + * codes, and indicates the reason of shutdown. Successful call of + * this function does not immediately erase the state of the stream. + * The actual deletion is done when the remote endpoint sends + * acknowledgement. Calling this function is equivalent to call * `ngtcp2_conn_shutdown_stream_read`, and - * `ngtcp2_conn_shutdown_stream_write` sequentially. + * `ngtcp2_conn_shutdown_stream_write` sequentially with the following + * differences. If |stream_id| refers to a local unidirectional + * stream, this function only shutdowns write side of the stream. If + * |stream_id| refers to a remote unidirectional stream, this function + * only shutdowns read side of the stream. + * + * |flags| is currently unused, and should be set to 0. + * + * This function returns 0 if a stream denoted by |stream_id| is not + * found. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -4295,46 +4278,62 @@ NGTCP2_EXTERN int ngtcp2_conn_open_uni_stream(ngtcp2_conn *conn, * :macro:`NGTCP2_ERR_NOMEM` * Out of memory */ -NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn, +NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id, uint64_t app_error_code); /** * @function * - * `ngtcp2_conn_shutdown_stream_write` closes write-side of stream + * `ngtcp2_conn_shutdown_stream_write` closes write-side of a stream * denoted by |stream_id| abruptly. |app_error_code| is one of * application error codes, and indicates the reason of shutdown. If - * this function succeeds, no application data is sent to the remote - * endpoint. It discards all data which has not been acknowledged - * yet. + * this function succeeds, no further application data is sent to the + * remote endpoint. It discards all data which has not been + * acknowledged yet. + * + * |flags| is currently unused, and should be set to 0. + * + * This function returns 0 if a stream denoted by |stream_id| is not + * found. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * :macro:`NGTCP2_ERR_NOMEM` * Out of memory + * :macro:`NGTCP2_ERR_INVALID_ARGUMENT` + * |stream_id| refers to a remote unidirectional stream. */ NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn, + uint32_t flags, int64_t stream_id, uint64_t app_error_code); /** * @function * - * `ngtcp2_conn_shutdown_stream_read` closes read-side of stream + * `ngtcp2_conn_shutdown_stream_read` closes read-side of a stream * denoted by |stream_id| abruptly. |app_error_code| is one of * application error codes, and indicates the reason of shutdown. If - * this function succeeds, no application data is forwarded to an - * application layer. + * this function succeeds, no further application data is forwarded to + * an application layer. + * + * |flags| is currently unused, and should be set to 0. + * + * This function returns 0 if a stream denoted by |stream_id| is not + * found. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * :macro:`NGTCP2_ERR_NOMEM` * Out of memory + * :macro:`NGTCP2_ERR_INVALID_ARGUMENT` + * |stream_id| refers to a local unidirectional stream. */ NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn, + uint32_t flags, int64_t stream_id, uint64_t app_error_code); @@ -4355,15 +4354,15 @@ NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn, * @macro * * :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE` indicates that more data may - * come and should be coalesced into the same packet if possible. + * come, and should be coalesced into the same packet if possible. */ #define NGTCP2_WRITE_STREAM_FLAG_MORE 0x01u /** * @macro * - * :macro:`NGTCP2_WRITE_STREAM_FLAG_FIN` indicates that the passed - * data is the final part of a stream. + * :macro:`NGTCP2_WRITE_STREAM_FLAG_FIN` indicates that a passed data + * is the final part of a stream. */ #define NGTCP2_WRITE_STREAM_FLAG_FIN 0x02u @@ -4384,20 +4383,21 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * @function * * `ngtcp2_conn_writev_stream` writes a packet containing stream data - * of stream denoted by |stream_id|. The buffer of the packet is + * of a stream denoted by |stream_id|. The buffer of the packet is * pointed by |dest| of length |destlen|. This function performs QUIC * handshake as well. * * |destlen| should be at least - * :member:`ngtcp2_settings.max_udp_payload_size`. + * :member:`ngtcp2_settings.max_tx_udp_payload_size`. * * Specifying -1 to |stream_id| means no new stream data to send. * * If |path| is not ``NULL``, this function stores the network path - * with which the packet should be sent. Each addr field must point - * to the buffer which should be at least ``sizeof(struct - * sockaddr_storage)`` bytes long. The assignment might not be done - * if nothing is written to |dest|. + * with which the packet should be sent. Each addr field + * (:member:`ngtcp2_path.local` and :member:`ngtcp2_path.remote`) must + * point to the buffer which should be at least + * sizeof(:type:`sockaddr_union`) bytes long. The assignment might + * not be done if nothing is written to |dest|. * * If |pi| is not ``NULL``, this function stores packet metadata in it * if it succeeds. The metadata includes ECN markings. When calling @@ -4405,7 +4405,10 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * :macro:`NGTCP2_ERR_WRITE_MORE`, caller must pass the same |pi| to * this function. * - * If the all given data is encoded as STREAM frame in |dest|, and if + * Stream data is specified as vector of data |datav|. |datavcnt| + * specifies the number of :type:`ngtcp2_vec` that |datav| includes. + * + * If all given data is encoded as STREAM frame in |dest|, and if * |flags| & :macro:`NGTCP2_WRITE_STREAM_FLAG_FIN` is nonzero, fin * flag is set to outgoing STREAM frame. Otherwise, fin flag in * STREAM frame is not set. @@ -4422,49 +4425,67 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * The number of data encoded in STREAM frame is stored in |*pdatalen| * if it is not ``NULL``. The caller must keep the portion of data * covered by |*pdatalen| bytes in tact until - * :type:`ngtcp2_acked_stream_data_offset` indicates that they are - * acknowledged by a remote endpoint or the stream is closed. - * - * If |flags| equals to :macro:`NGTCP2_WRITE_STREAM_FLAG_NONE`, this - * function produces a single payload of UDP packet. If the given - * stream data is small (e.g., few bytes), the packet might be - * severely under filled. Too many small packet might increase - * overall packet processing costs. Unless there are retransmissions, - * by default, application can only send 1 STREAM frame in one QUIC - * packet. In order to include more than 1 STREAM frame in one QUIC - * packet, specify :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE` in |flags|. - * This is analogous to ``MSG_MORE`` flag in :manpage:`send(2)`. If - * the :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE` is used, there are 4 + * :member:`ngtcp2_callbacks.acked_stream_data_offset` indicates that + * they are acknowledged by a remote endpoint or the stream is closed. + * + * If the given stream data is small (e.g., few bytes), the packet + * might be severely under filled. Too many small packet might + * increase overall packet processing costs. Unless there are + * retransmissions, by default, application can only send 1 STREAM + * frame in one QUIC packet. In order to include more than 1 STREAM + * frame in one QUIC packet, specify + * :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE` in |flags|. This is + * analogous to ``MSG_MORE`` flag in :manpage:`send(2)`. If the + * :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE` is used, there are 4 * outcomes: * * - The function returns the written length of packet just like * without :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE`. This is because - * packet is nearly full and the library decided to make a complete - * packet. |*pdatalen| might be -1 or >= 0. + * packet is nearly full, and the library decided to make a complete + * packet. |*pdatalen| might be -1 or >= 0. It may return 0 which + * indicates that no packet transmission is possible at the moment + * for some reason. * * - The function returns :macro:`NGTCP2_ERR_WRITE_MORE`. In this - * case, |*pdatalen| >= 0 is asserted. This indicates that - * application can call this function with different stream data (or - * `ngtcp2_conn_writev_datagram` if it has data to send in + * case, |*pdatalen| >= 0 is asserted. It indicates that + * application can still call this function with different stream + * data (or `ngtcp2_conn_writev_datagram` if it has data to send in * unreliable datagram) to pack them into the same packet. * Application has to specify the same |conn|, |path|, |pi|, |dest|, * |destlen|, and |ts| parameters, otherwise the behaviour is * undefined. The application can change |flags|. * - * - The function returns :macro:`NGTCP2_ERR_STREAM_DATA_BLOCKED` which - * indicates that stream is blocked because of flow control. - * - * - The other error might be returned just like without - * :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE`. + * - The function returns one of the following negative error codes: + * :macro:`NGTCP2_ERR_STREAM_DATA_BLOCKED`, + * :macro:`NGTCP2_ERR_STREAM_NOT_FOUND`, or + * :macro:`NGTCP2_ERR_STREAM_SHUT_WR`. In this case, |*pdatalen| == + * -1 is asserted. Application can still write the stream data of + * the other streams by calling this function (or + * `ngtcp2_conn_writev_datagram` if it has data to send in + * unreliable datagram) to pack them into the same packet. + * Application has to specify the same |conn|, |path|, |pi|, |dest|, + * |destlen|, and |ts| parameters, otherwise the behaviour is + * undefined. The application can change |flags|. * - * When application sees :macro:`NGTCP2_ERR_WRITE_MORE`, it must not - * call other ngtcp2 API functions (application can still call - * `ngtcp2_conn_write_connection_close` to handle error from this - * function). Just keep calling `ngtcp2_conn_writev_stream`, - * `ngtcp2_conn_write_pkt`, or `ngtcp2_conn_writev_datagram` until it - * returns a positive number (which indicates a complete packet is - * ready). If there is no stream data to include, call this function - * with |stream_id| as -1 to stop coalescing and write a packet. + * - The other negative error codes might be returned just like + * without :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE`. These errors + * should be treated as a connection error. + * + * When application uses :macro:`NGTCP2_WRITE_STREAM_FLAG_MORE` at + * least once, it must not call other ngtcp2 API functions + * (application can still call `ngtcp2_conn_write_connection_close` to + * handle error from this function. It can also call + * `ngtcp2_conn_shutdown_stream_read`, + * `ngtcp2_conn_shutdown_stream_write`, and + * `ngtcp2_conn_shutdown_stream`), just keep calling this function (or + * `ngtcp2_conn_writev_datagram`) until it returns 0, a positive + * number (which indicates a complete packet is ready), or the error + * codes other than :macro:`NGTCP2_ERR_WRITE_MORE`, + * :macro:`NGTCP2_ERR_STREAM_DATA_BLOCKED`, + * :macro:`NGTCP2_ERR_STREAM_NOT_FOUND`, and + * :macro:`NGTCP2_ERR_STREAM_SHUT_WR`. If there is no stream data to + * include, call this function with |stream_id| as -1 to stop + * coalescing and write a packet. * * This function returns 0 if it cannot write any frame because buffer * is too small, or packet is congestion limited. Application should @@ -4473,11 +4494,9 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * This function must not be called from inside the callback * functions. * - * If pacing is enabled, `ngtcp2_conn_update_pkt_tx_time` must be - * called after this function. Application may call this function - * multiple times before calling `ngtcp2_conn_update_pkt_tx_time`. - * Packet pacing is enabled if BBR congestion controller algorithm is - * used. + * `ngtcp2_conn_update_pkt_tx_time` must be called after this + * function. Application may call this function multiple times before + * calling `ngtcp2_conn_update_pkt_tx_time`. * * This function returns the number of bytes written in |dest| if it * succeeds, or one of the following negative error codes: @@ -4501,12 +4520,9 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * Application can call this function to pack more stream data * into the same packet. See above to know how it works. * - * In general, if the error code which satisfies - * `ngtcp2_err_is_fatal(err) ` != 0 is returned, - * the application should just close the connection by calling - * `ngtcp2_conn_write_connection_close` or just delete the QUIC - * connection using `ngtcp2_conn_del`. It is undefined to call the - * other library functions. + * If any other negative error is returned, call + * `ngtcp2_conn_write_connection_close` to get terminal packet, and + * sending it makes QUIC connection enter the closing state. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, @@ -4531,10 +4547,23 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( * @macro * * :macro:`NGTCP2_WRITE_DATAGRAM_FLAG_MORE` indicates that more data - * may come and should be coalesced into the same packet if possible. + * may come, and should be coalesced into the same packet if possible. */ #define NGTCP2_WRITE_DATAGRAM_FLAG_MORE 0x01u +/** + * @function + * + * `ngtcp2_conn_write_datagram` is just like + * `ngtcp2_conn_writev_datagram`. The only difference is that it + * conveniently accepts a single buffer. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_datagram_versioned( + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, + uint32_t flags, uint64_t dgram_id, const uint8_t *data, size_t datalen, + ngtcp2_tstamp ts); + /** * @function * @@ -4544,25 +4573,28 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( * as well. * * |destlen| should be at least - * :member:`ngtcp2_settings.max_udp_payload_size`. + * :member:`ngtcp2_settings.max_tx_udp_payload_size`. * * For |path| and |pi| parameters, refer to * `ngtcp2_conn_writev_stream`. * + * Stream data is specified as vector of data |datav|. |datavcnt| + * specifies the number of :type:`ngtcp2_vec` that |datav| includes. + * * If the given data is written to the buffer, nonzero value is * assigned to |*paccepted| if it is not NULL. The data in DATAGRAM * frame cannot be fragmented; writing partial data is not possible. * * |dgram_id| is an opaque identifier which should uniquely identify - * the given DATAGRAM. It is passed to :type:`ngtcp2_ack_datagram` - * callback when a packet that contains DATAGRAM frame is - * acknowledged. It is passed to :type:`ngtcp2_lost_datagram` - * callback when a packet that contains DATAGRAM frame is declared - * lost. If an application uses neither of those callbacks, it can - * sets 0 to this parameter. + * the given DATAGRAM data. It is passed to + * :member:`ngtcp2_callbacks.ack_datagram` callback when a packet that + * contains DATAGRAM frame is acknowledged. It is also passed to + * :member:`ngtcp2_callbacks.lost_datagram` callback when a packet + * that contains DATAGRAM frame is declared lost. If an application + * uses neither of those callbacks, it can sets 0 to this parameter. * - * This function might write other frames other than DATAGRAM, just - * like `ngtcp2_conn_writev_stream`. + * This function might write other frames other than DATAGRAM frame, + * just like `ngtcp2_conn_writev_stream`. * * If the function returns 0, it means that no more data cannot be * sent because of congestion control limit; or, data does not fit @@ -4593,10 +4625,11 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( * When application sees :macro:`NGTCP2_ERR_WRITE_MORE`, it must not * call other ngtcp2 API functions (application can still call * `ngtcp2_conn_write_connection_close` to handle error from this - * function). Just keep calling `ngtcp2_conn_writev_datagram`, - * `ngtcp2_conn_writev_stream` or `ngtcp2_conn_write_pkt` until it - * returns a positive number (which indicates a complete packet is - * ready). + * function. It can also call `ngtcp2_conn_shutdown_stream_read`, + * `ngtcp2_conn_shutdown_stream_write`, and + * `ngtcp2_conn_shutdown_stream`). Just keep calling this function + * (or `ngtcp2_conn_writev_stream`) until it returns a positive number + * (which indicates a complete packet is ready). * * This function returns the number of bytes written in |dest| if it * succeeds, or one of the following negative error codes: @@ -4617,12 +4650,9 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( * The provisional DATAGRAM frame size exceeds the maximum * DATAGRAM frame size that a remote endpoint can receive. * - * In general, if the error code which satisfies - * `ngtcp2_err_is_fatal(err) ` != 0 is returned, - * the application should just close the connection by calling - * `ngtcp2_conn_write_connection_close` or just delete the QUIC - * connection using `ngtcp2_conn_del`. It is undefined to call the - * other library functions. + * If any other negative error is returned, call + * `ngtcp2_conn_write_connection_close` to get terminal packet, and + * sending it makes QUIC connection enter the closing state. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_datagram_versioned( ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, @@ -4633,30 +4663,37 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_datagram_versioned( /** * @function * - * `ngtcp2_conn_is_in_closing_period` returns nonzero if |conn| is in - * the closing period. + * `ngtcp2_conn_in_closing_period` returns nonzero if |conn| is in the + * closing period. */ -NGTCP2_EXTERN int ngtcp2_conn_is_in_closing_period(ngtcp2_conn *conn); +NGTCP2_EXTERN int ngtcp2_conn_in_closing_period(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_is_in_draining_period` returns nonzero if |conn| is in + * `ngtcp2_conn_in_draining_period` returns nonzero if |conn| is in * the draining period. */ -NGTCP2_EXTERN int ngtcp2_conn_is_in_draining_period(ngtcp2_conn *conn); +NGTCP2_EXTERN int ngtcp2_conn_in_draining_period(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_extend_max_stream_offset` extends stream's max stream - * data value by |datalen|. + * `ngtcp2_conn_extend_max_stream_offset` extends the maximum stream + * data that a remote endpoint can send by |datalen|. |stream_id| + * specifies the stream ID. This function only extends stream-level + * flow control window. + * + * This function returns 0 if a stream denoted by |stream_id| is not + * found. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * :macro:`NGTCP2_ERR_NOMEM` * Out of memory. + * :macro:`NGTCP2_ERR_INVALID_ARGUMENT` + * |stream_id| refers to a local unidirectional stream. */ NGTCP2_EXTERN int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn, int64_t stream_id, @@ -4666,7 +4703,8 @@ NGTCP2_EXTERN int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn, * @function * * `ngtcp2_conn_extend_max_offset` extends max data offset by - * |datalen|. + * |datalen|. This function only extends connection-level flow + * control window. */ NGTCP2_EXTERN void ngtcp2_conn_extend_max_offset(ngtcp2_conn *conn, uint64_t datalen); @@ -4675,12 +4713,13 @@ NGTCP2_EXTERN void ngtcp2_conn_extend_max_offset(ngtcp2_conn *conn, * @function * * `ngtcp2_conn_extend_max_streams_bidi` extends the number of maximum - * local bidirectional streams that a remote endpoint can open by |n|. + * remote bidirectional streams that a remote endpoint can open by + * |n|. * * The library does not increase maximum stream limit automatically. * The exception is when a stream is closed without - * :type:`ngtcp2_stream_open` callback being called. In this case, - * stream limit is increased automatically. + * :member:`ngtcp2_callbacks.stream_open` callback being called. In + * this case, stream limit is increased automatically. */ NGTCP2_EXTERN void ngtcp2_conn_extend_max_streams_bidi(ngtcp2_conn *conn, size_t n); @@ -4689,13 +4728,13 @@ NGTCP2_EXTERN void ngtcp2_conn_extend_max_streams_bidi(ngtcp2_conn *conn, * @function * * `ngtcp2_conn_extend_max_streams_uni` extends the number of maximum - * local unidirectional streams that a remote endpoint can open by + * remote unidirectional streams that a remote endpoint can open by * |n|. * * The library does not increase maximum stream limit automatically. * The exception is when a stream is closed without - * :type:`ngtcp2_stream_open` callback being called. In this case, - * stream limit is increased automatically. + * :member:`ngtcp2_callbacks.stream_open` callback being called. In + * this case, stream limit is increased automatically. */ NGTCP2_EXTERN void ngtcp2_conn_extend_max_streams_uni(ngtcp2_conn *conn, size_t n); @@ -4703,9 +4742,10 @@ NGTCP2_EXTERN void ngtcp2_conn_extend_max_streams_uni(ngtcp2_conn *conn, /** * @function * - * `ngtcp2_conn_get_dcid` returns the non-NULL pointer to destination - * connection ID. If no destination connection ID is present, the - * return value is not ``NULL``, and its datalen field is 0. + * `ngtcp2_conn_get_dcid` returns the non-NULL pointer to the current + * Destination Connection ID. If no Destination Connection ID is + * present, the return value is not ``NULL``, and its :member:`datalen + * ` field is 0. */ NGTCP2_EXTERN const ngtcp2_cid *ngtcp2_conn_get_dcid(ngtcp2_conn *conn); @@ -4714,7 +4754,9 @@ NGTCP2_EXTERN const ngtcp2_cid *ngtcp2_conn_get_dcid(ngtcp2_conn *conn); * * `ngtcp2_conn_get_client_initial_dcid` returns the non-NULL pointer * to the Destination Connection ID that client sent in its Initial - * packet. + * packet. If the Destination Connection ID is not present, the + * return value is not ``NULL``, and its :member:`datalen + * ` field is 0. */ NGTCP2_EXTERN const ngtcp2_cid * ngtcp2_conn_get_client_initial_dcid(ngtcp2_conn *conn); @@ -4722,31 +4764,17 @@ ngtcp2_conn_get_client_initial_dcid(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_get_num_scid` returns the number of source connection - * IDs which the local endpoint has provided to the peer and have not - * retired. - */ -NGTCP2_EXTERN size_t ngtcp2_conn_get_num_scid(ngtcp2_conn *conn); - -/** - * @function - * - * `ngtcp2_conn_get_scid` writes the all source connection IDs which - * the local endpoint has provided to the peer and have not retired in - * |dest|. The buffer pointed by |dest| must have - * ``sizeof(ngtcp2_cid) * n`` bytes available, where n is the return - * value of `ngtcp2_conn_get_num_scid()`. + * `ngtcp2_conn_get_scid` writes the all Source Connection IDs which a + * local endpoint has provided to a remote endpoint, and are not + * retired in |dest|. If |dest| is NULL, this function does not write + * anything, and returns the number of Source Connection IDs that + * would otherwise be written to the provided buffer. The buffer + * pointed by |dest| must have sizeof(:type:`ngtcp2_cid`) * n bytes + * available, where n is the return value of `ngtcp2_conn_get_scid` + * with |dest| == NULL. */ NGTCP2_EXTERN size_t ngtcp2_conn_get_scid(ngtcp2_conn *conn, ngtcp2_cid *dest); -/** - * @function - * - * `ngtcp2_conn_get_num_active_dcid` returns the number of the active - * destination connection ID. - */ -NGTCP2_EXTERN size_t ngtcp2_conn_get_num_active_dcid(ngtcp2_conn *conn); - /** * @struct * @@ -4763,8 +4791,8 @@ typedef struct ngtcp2_cid_token { */ ngtcp2_cid cid; /** - * :member:`ps` is the path which is associated to this Connection - * ID. + * :member:`ps` is the path which this Connection ID is associated + * with. */ ngtcp2_path_storage ps; /** @@ -4782,10 +4810,15 @@ typedef struct ngtcp2_cid_token { /** * @function * - * `ngtcp2_conn_get_active_dcid` writes the all active destination - * connection IDs and tokens to |dest|. The buffer pointed by |dest| - * must have ``sizeof(ngtcp2_cid_token) * n`` bytes available, where n - * is the return value of `ngtcp2_conn_get_num_active_dcid()`. + * `ngtcp2_conn_get_active_dcid` writes the all active Destination + * Connection IDs and their tokens to |dest|. Before handshake + * completes, this function returns 0. If |dest| is NULL, this + * function does not write anything, and returns the number of + * Destination Connection IDs that would otherwise be written to the + * provided buffer. The buffer pointed by |dest| must have + * sizeof(:type:`ngtcp2_cid_token`) * n bytes available, where n is + * the return value of `ngtcp2_conn_get_active_dcid` with |dest| == + * NULL. */ NGTCP2_EXTERN size_t ngtcp2_conn_get_active_dcid(ngtcp2_conn *conn, ngtcp2_cid_token *dest); @@ -4801,7 +4834,8 @@ NGTCP2_EXTERN uint32_t ngtcp2_conn_get_client_chosen_version(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_get_negotiated_version` returns the negotiated version. + * `ngtcp2_conn_get_negotiated_version` returns the negotiated + * version. * * Until the version is negotiated, this function returns 0. */ @@ -4810,44 +4844,59 @@ NGTCP2_EXTERN uint32_t ngtcp2_conn_get_negotiated_version(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_early_data_rejected` tells |conn| that early data was - * rejected by a server. |conn| discards the following connection - * states: + * `ngtcp2_conn_tls_early_data_rejected` tells |conn| that early data + * was rejected by a server during TLS handshake, or client decided + * not to attempt early data for some reason. |conn| discards the + * following connection states: * - * - Any opended streams. + * - Any opened streams. * - Stream identifier allocations. * - Max data extended by `ngtcp2_conn_extend_max_offset`. * - Max bidi streams extended by `ngtcp2_conn_extend_max_streams_bidi`. * - Max uni streams extended by `ngtcp2_conn_extend_max_streams_uni`. * * Application which wishes to retransmit early data, it has to open - * streams and send stream data again. + * streams, and send stream data again. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` + * User callback failed + */ +NGTCP2_EXTERN int ngtcp2_conn_tls_early_data_rejected(ngtcp2_conn *conn); + +/** + * @function + * + * `ngtcp2_conn_get_tls_early_data_rejected` returns nonzero if + * `ngtcp2_conn_tls_early_data_rejected` has been called. */ -NGTCP2_EXTERN void ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn); +NGTCP2_EXTERN int ngtcp2_conn_get_tls_early_data_rejected(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_get_conn_stat` assigns connection statistics data to - * |*cstat|. + * `ngtcp2_conn_get_conn_info` assigns connection statistics data to + * |*cinfo|. */ -NGTCP2_EXTERN void ngtcp2_conn_get_conn_stat_versioned(ngtcp2_conn *conn, - int conn_stat_version, - ngtcp2_conn_stat *cstat); +NGTCP2_EXTERN void ngtcp2_conn_get_conn_info_versioned(ngtcp2_conn *conn, + int conn_info_version, + ngtcp2_conn_info *cinfo); /** * @function * - * `ngtcp2_conn_submit_crypto_data` submits crypto stream data |data| - * of length |datalen| to the library for transmission. The - * encryption level is given in |crypto_level|. + * `ngtcp2_conn_submit_crypto_data` submits crypto data |data| of + * length |datalen| to the library for transmission. + * |encryption_level| specifies the encryption level of data. * * The library makes a copy of the buffer pointed by |data| of length * |datalen|. Application can discard |data|. */ NGTCP2_EXTERN int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, + ngtcp2_encryption_level encryption_level, const uint8_t *data, const size_t datalen); /** @@ -4874,7 +4923,8 @@ NGTCP2_EXTERN int ngtcp2_conn_submit_new_token(ngtcp2_conn *conn, * @function * * `ngtcp2_conn_set_local_addr` sets local endpoint address |addr| to - * the current path of |conn|. + * the current path of |conn|. This function is provided for testing + * purpose only. */ NGTCP2_EXTERN void ngtcp2_conn_set_local_addr(ngtcp2_conn *conn, const ngtcp2_addr *addr); @@ -4898,34 +4948,34 @@ NGTCP2_EXTERN const ngtcp2_path *ngtcp2_conn_get_path(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_get_max_udp_payload_size` returns the maximum UDP + * `ngtcp2_conn_get_max_tx_udp_payload_size` returns the maximum UDP * payload size that this local endpoint would send. This is the - * value of :member:`ngtcp2_settings.max_udp_payload_size` that is + * value of :member:`ngtcp2_settings.max_tx_udp_payload_size` that is * passed to `ngtcp2_conn_client_new` or `ngtcp2_conn_server_new`. */ -NGTCP2_EXTERN size_t ngtcp2_conn_get_max_udp_payload_size(ngtcp2_conn *conn); +NGTCP2_EXTERN size_t ngtcp2_conn_get_max_tx_udp_payload_size(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_get_path_max_udp_payload_size` returns the maximum UDP - * payload size for the current path. If - * :member:`ngtcp2_settings.no_udp_payload_size_shaping` is set to + * `ngtcp2_conn_get_path_max_tx_udp_payload_size` returns the maximum + * UDP payload size for the current path. If + * :member:`ngtcp2_settings.no_tx_udp_payload_size_shaping` is set to * nonzero, this function is equivalent to - * `ngtcp2_conn_get_max_udp_payload_size`. Otherwise, it returns the - * maximum UDP payload size that is probed for the current path. + * `ngtcp2_conn_get_max_tx_udp_payload_size`. Otherwise, it returns + * the maximum UDP payload size that is probed for the current path. */ NGTCP2_EXTERN size_t -ngtcp2_conn_get_path_max_udp_payload_size(ngtcp2_conn *conn); +ngtcp2_conn_get_path_max_tx_udp_payload_size(ngtcp2_conn *conn); /** * @function * * `ngtcp2_conn_initiate_immediate_migration` starts connection - * migration to the given |path|. - * Only client can initiate migration. This function does - * immediate migration; it does not probe peer reachability from a new - * local address. + * migration to the given |path|. Only client can initiate migration. + * This function does immediate migration; while the path validation + * is nonetheless performed, this function does not wait for it to + * succeed. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -4936,7 +4986,8 @@ ngtcp2_conn_get_path_max_udp_payload_size(ngtcp2_conn *conn); * :macro:`NGTCP2_ERR_CONN_ID_BLOCKED` * No unused connection ID is available. * :macro:`NGTCP2_ERR_INVALID_ARGUMENT` - * |local_addr| equals the current local address. + * :member:`local ` field of |path| equals the + * current local address. * :macro:`NGTCP2_ERR_NOMEM` * Out of memory */ @@ -4949,7 +5000,7 @@ NGTCP2_EXTERN int ngtcp2_conn_initiate_immediate_migration( * `ngtcp2_conn_initiate_migration` starts connection migration to the * given |path|. Only client can initiate migration. Unlike * `ngtcp2_conn_initiate_immediate_migration`, this function starts a - * path validation with a new path and migrate to the new path after + * path validation with a new path, and migrate to the new path after * successful path validation. * * This function returns 0 if it succeeds, or one of the following @@ -4961,7 +5012,8 @@ NGTCP2_EXTERN int ngtcp2_conn_initiate_immediate_migration( * :macro:`NGTCP2_ERR_CONN_ID_BLOCKED` * No unused connection ID is available. * :macro:`NGTCP2_ERR_INVALID_ARGUMENT` - * |local_addr| equals the current local address. + * :member:`local ` field of |path| equals the + * current local address. * :macro:`NGTCP2_ERR_NOMEM` * Out of memory */ @@ -4969,19 +5021,12 @@ NGTCP2_EXTERN int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_tstamp ts); -/** - * @function - * - * `ngtcp2_conn_get_max_local_streams_uni` returns the cumulative - * number of streams which local endpoint can open. - */ -NGTCP2_EXTERN uint64_t ngtcp2_conn_get_max_local_streams_uni(ngtcp2_conn *conn); - /** * @function * * `ngtcp2_conn_get_max_data_left` returns the number of bytes that - * this local endpoint can send in this connection. + * this local endpoint can send in this connection without violating + * connection-level flow control. */ NGTCP2_EXTERN uint64_t ngtcp2_conn_get_max_data_left(ngtcp2_conn *conn); @@ -4990,7 +5035,8 @@ NGTCP2_EXTERN uint64_t ngtcp2_conn_get_max_data_left(ngtcp2_conn *conn); * * `ngtcp2_conn_get_max_stream_data_left` returns the number of bytes * that this local endpoint can send to a stream identified by - * |stream_id|. If no such stream is found, this function returns 0. + * |stream_id| without violating stream-level flow control. If no + * such stream is found, this function returns 0. */ NGTCP2_EXTERN uint64_t ngtcp2_conn_get_max_stream_data_left(ngtcp2_conn *conn, int64_t stream_id); @@ -5046,7 +5092,7 @@ ngtcp2_conn_get_initial_crypto_ctx(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_set_crypto_ctx` sets |ctx| for Handshake/1RTT packet + * `ngtcp2_conn_set_crypto_ctx` sets |ctx| for Handshake/1-RTT packet * encryption. The passed data will be passed to * :type:`ngtcp2_encrypt`, :type:`ngtcp2_decrypt` and * :type:`ngtcp2_hp_mask` callbacks. @@ -5057,114 +5103,113 @@ NGTCP2_EXTERN void ngtcp2_conn_set_crypto_ctx(ngtcp2_conn *conn, /** * @function * - * `ngtcp2_conn_get_tls_native_handle` returns TLS native handle set by - * `ngtcp2_conn_set_tls_native_handle()`. + * `ngtcp2_conn_get_crypto_ctx` returns :type:`ngtcp2_crypto_ctx` + * object for Handshake/1-RTT packet encryption. */ -NGTCP2_EXTERN void *ngtcp2_conn_get_tls_native_handle(ngtcp2_conn *conn); +NGTCP2_EXTERN const ngtcp2_crypto_ctx * +ngtcp2_conn_get_crypto_ctx(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_set_tls_native_handle` sets TLS native handle - * |tls_native_handle| to |conn|. Internally, it is used as an opaque - * pointer. + * `ngtcp2_conn_set_0rtt_crypto_ctx` sets |ctx| for 0-RTT packet + * encryption. The passed data will be passed to + * :type:`ngtcp2_encrypt`, :type:`ngtcp2_decrypt` and + * :type:`ngtcp2_hp_mask` callbacks. */ -NGTCP2_EXTERN void ngtcp2_conn_set_tls_native_handle(ngtcp2_conn *conn, - void *tls_native_handle); +NGTCP2_EXTERN void +ngtcp2_conn_set_0rtt_crypto_ctx(ngtcp2_conn *conn, + const ngtcp2_crypto_ctx *ctx); /** * @function * - * `ngtcp2_conn_set_retry_aead` sets |aead| and |aead_ctx| for Retry - * integrity tag verification. |aead| must be AEAD_AES_128_GCM. - * |aead_ctx| must be initialized with :macro:`NGTCP2_RETRY_KEY` as - * encryption key. This function must be called if |conn| is - * initialized as client. Server does not verify the tag and has no - * need to call this function. - * - * If this function succeeds, |conn| takes ownership of |aead_ctx|. - * :type:`ngtcp2_delete_crypto_aead_ctx` will be called to delete this - * object when it is no longer used. If this function fails, the - * caller is responsible to delete it. + * `ngtcp2_conn_get_0rtt_crypto_ctx` returns :type:`ngtcp2_crypto_ctx` + * object for 0-RTT packet encryption. */ -NGTCP2_EXTERN void -ngtcp2_conn_set_retry_aead(ngtcp2_conn *conn, const ngtcp2_crypto_aead *aead, - const ngtcp2_crypto_aead_ctx *aead_ctx); +NGTCP2_EXTERN const ngtcp2_crypto_ctx * +ngtcp2_conn_get_0rtt_crypto_ctx(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_get_crypto_ctx` returns :type:`ngtcp2_crypto_ctx` - * object for Handshake/1RTT packet encryption. + * `ngtcp2_conn_get_tls_native_handle` returns TLS native handle set + * by `ngtcp2_conn_set_tls_native_handle`. */ -NGTCP2_EXTERN const ngtcp2_crypto_ctx * -ngtcp2_conn_get_crypto_ctx(ngtcp2_conn *conn); +NGTCP2_EXTERN void *ngtcp2_conn_get_tls_native_handle(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_set_early_crypto_ctx` sets |ctx| for 0RTT packet - * encryption. The passed data will be passed to - * :type:`ngtcp2_encrypt`, :type:`ngtcp2_decrypt` and - * :type:`ngtcp2_hp_mask` callbacks. + * `ngtcp2_conn_set_tls_native_handle` sets TLS native handle + * |tls_native_handle| to |conn|. Internally, it is used as an opaque + * pointer. */ -NGTCP2_EXTERN void -ngtcp2_conn_set_early_crypto_ctx(ngtcp2_conn *conn, - const ngtcp2_crypto_ctx *ctx); +NGTCP2_EXTERN void ngtcp2_conn_set_tls_native_handle(ngtcp2_conn *conn, + void *tls_native_handle); /** * @function * - * `ngtcp2_conn_get_early_crypto_ctx` returns - * :type:`ngtcp2_crypto_ctx` object for 0RTT packet encryption. + * `ngtcp2_conn_set_retry_aead` sets |aead| and |aead_ctx| for Retry + * integrity tag verification. |aead| must be AEAD_AES_128_GCM. + * |aead_ctx| must be initialized with :macro:`NGTCP2_RETRY_KEY` as + * encryption key. This function must be called if |conn| is + * initialized as client. Server does not verify the tag, and has no + * need to call this function. + * + * |conn| takes ownership of |aead_ctx|. + * :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` will be called to + * delete this object when it is no longer used. */ -NGTCP2_EXTERN const ngtcp2_crypto_ctx * -ngtcp2_conn_get_early_crypto_ctx(ngtcp2_conn *conn); +NGTCP2_EXTERN void +ngtcp2_conn_set_retry_aead(ngtcp2_conn *conn, const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx); /** * @enum * - * :type:`ngtcp2_connection_close_error_code_type` defines connection - * error code type. + * :type:`ngtcp2_ccerr_type` defines connection error type. */ -typedef enum ngtcp2_connection_close_error_code_type { +typedef enum ngtcp2_ccerr_type { /** - * :enum:`NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT` - * indicates the error code is QUIC transport error code. + * :enum:`NGTCP2_CCERR_TYPE_TRANSPORT` indicates the QUIC transport + * error, and the error code is QUIC transport error code. */ - NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT, + NGTCP2_CCERR_TYPE_TRANSPORT, /** - * :enum:`NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION` - * indicates the error code is application error code. + * :enum:`NGTCP2_CCERR_TYPE_APPLICATION` indicates an application + * error, and the error code is application error code. */ - NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION, + NGTCP2_CCERR_TYPE_APPLICATION, /** - * :enum:`NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_VERSION_NEGOTIATION` - * is a special case of QUIC transport error, and it indicates that - * client receives Version Negotiation packet. + * :enum:`NGTCP2_CCERR_TYPE_VERSION_NEGOTIATION` is a special case + * of QUIC transport error, and it indicates that client receives + * Version Negotiation packet. */ - NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_VERSION_NEGOTIATION, + NGTCP2_CCERR_TYPE_VERSION_NEGOTIATION, /** - * :enum:`NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_IDLE_CLOSE` - * is a special case of QUIC transport error, and it indicates that - * connection is closed because of idle timeout. + * :enum:`NGTCP2_CCERR_TYPE_IDLE_CLOSE` is a special case of QUIC + * transport error, and it indicates that connection is closed + * because of idle timeout. */ - NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_IDLE_CLOSE -} ngtcp2_connection_close_error_code_type; + NGTCP2_CCERR_TYPE_IDLE_CLOSE +} ngtcp2_ccerr_type; /** * @struct * - * :type:`ngtcp2_connection_close_error` contains connection - * error code, its type, and the optional reason phrase. + * :type:`ngtcp2_ccerr` contains connection error code, its type, a + * frame type that caused this error, and the optional reason phrase. */ -typedef struct ngtcp2_connection_close_error { +typedef struct ngtcp2_ccerr { /** - * :member:`type` is the type of :member:`error_code`. + * :member:`type` is the type of this error. */ - ngtcp2_connection_close_error_code_type type; + ngtcp2_ccerr_type type; /** * :member:`error_code` is the error code for connection closure. + * Its interpretation depends on :member:`type`. */ uint64_t error_code; /** @@ -5179,109 +5224,106 @@ typedef struct ngtcp2_connection_close_error { * received from a remote endpoint, it is truncated to at most 1024 * bytes. */ - uint8_t *reason; + const uint8_t *reason; /** * :member:`reasonlen` is the length of data pointed by * :member:`reason`. */ size_t reasonlen; -} ngtcp2_connection_close_error; +} ngtcp2_ccerr; /** * @function * - * `ngtcp2_connection_close_error_default` initializes |ccerr| with - * the default values. It sets the following fields: + * `ngtcp2_ccerr_default` initializes |ccerr| with the default values. + * It sets the following fields: * - * - :member:`type ` = - * :enum:`ngtcp2_connection_close_error_code_type.NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT` - * - :member:`error_code ` = + * - :member:`type ` = + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_TRANSPORT` + * - :member:`error_code ` = * :macro:`NGTCP2_NO_ERROR`. - * - :member:`frame_type ` = - * 0 - * - :member:`reason ` = NULL - * - :member:`reasonlen ` = 0 + * - :member:`frame_type ` = 0 + * - :member:`reason ` = NULL + * - :member:`reasonlen ` = 0 */ -NGTCP2_EXTERN void -ngtcp2_connection_close_error_default(ngtcp2_connection_close_error *ccerr); +NGTCP2_EXTERN void ngtcp2_ccerr_default(ngtcp2_ccerr *ccerr); /** * @function * - * `ngtcp2_connection_close_error_set_transport_error` sets - * :member:`ccerr->type ` to - * :enum:`ngtcp2_connection_close_error_code_type.NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT`, - * and :member:`ccerr->error_code - * ` to |error_code|. - * |reason| is the reason phrase of length |reasonlen|. This function - * does not make a copy of the reason phrase. + * `ngtcp2_ccerr_set_transport_error` sets :member:`ccerr->type + * ` to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_TRANSPORT`, and + * :member:`ccerr->error_code ` to + * |error_code|. |reason| is the reason phrase of length |reasonlen|. + * This function does not make a copy of the reason phrase. */ -NGTCP2_EXTERN void ngtcp2_connection_close_error_set_transport_error( - ngtcp2_connection_close_error *ccerr, uint64_t error_code, - const uint8_t *reason, size_t reasonlen); +NGTCP2_EXTERN void ngtcp2_ccerr_set_transport_error(ngtcp2_ccerr *ccerr, + uint64_t error_code, + const uint8_t *reason, + size_t reasonlen); /** * @function * - * `ngtcp2_connection_close_error_set_transport_error_liberr` sets - * type and error_code based on |liberr|. + * `ngtcp2_ccerr_set_liberr` sets type and error_code based on + * |liberr|. + * + * |reason| is the reason phrase of length |reasonlen|. This function + * does not make a copy of the reason phrase. * * If |liberr| is :macro:`NGTCP2_ERR_RECV_VERSION_NEGOTIATION`, - * :member:`ccerr->type ` is set - * to - * :enum:`ngtcp2_connection_close_error_code_type.NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_VERSION_NEGOTIATION`, - * and :member:`ccerr->error_code - * ` to - * :macro:`NGTCP2_NO_ERROR`. If |liberr| is - * :macro:`NGTCP2_ERR_IDLE_CLOSE`, :member:`ccerr->type - * ` is set to - * :enum:`ngtcp2_connection_close_error_code_type.NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_IDLE_CLOSE`, - * and :member:`ccerr->error_code - * ` to - * :macro:`NGTCP2_NO_ERROR`. Otherwise, :member:`ccerr->type - * ` is set to - * :enum:`ngtcp2_connection_close_error_code_type.NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT`, - * and :member:`ccerr->error_code - * ` is set to an error code - * inferred by |liberr| (see - * `ngtcp2_err_infer_quic_transport_error_code`). |reason| is the - * reason phrase of length |reasonlen|. This function does not make a - * copy of the reason phrase. + * :member:`ccerr->type ` is set to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_VERSION_NEGOTIATION`, + * and :member:`ccerr->error_code ` to + * :macro:`NGTCP2_NO_ERROR`. + * + * If |liberr| is :macro:`NGTCP2_ERR_IDLE_CLOSE`, :member:`ccerr->type + * ` is set to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_IDLE_CLOSE`, and + * :member:`ccerr->error_code ` to + * :macro:`NGTCP2_NO_ERROR`. + * + * Otherwise, :member:`ccerr->type ` is set to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_TRANSPORT`, and + * :member:`ccerr->error_code ` is set to an + * error code inferred by |liberr| (see + * `ngtcp2_err_infer_quic_transport_error_code`). */ -NGTCP2_EXTERN void ngtcp2_connection_close_error_set_transport_error_liberr( - ngtcp2_connection_close_error *ccerr, int liberr, const uint8_t *reason, - size_t reasonlen); +NGTCP2_EXTERN void ngtcp2_ccerr_set_liberr(ngtcp2_ccerr *ccerr, int liberr, + const uint8_t *reason, + size_t reasonlen); /** * @function * - * `ngtcp2_connection_close_error_set_transport_error_tls_alert` sets - * :member:`ccerr->type ` to - * :enum:`ngtcp2_connection_close_error_code_type.NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT`, - * and :member:`ccerr->error_code - * ` to bitwise-OR of - * :macro:`NGTCP2_CRYPTO_ERROR` and |tls_alert|. |reason| is the + * `ngtcp2_ccerr_set_tls_alert` sets :member:`ccerr->type + * ` to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_TRANSPORT`, and + * :member:`ccerr->error_code ` to bitwise-OR + * of :macro:`NGTCP2_CRYPTO_ERROR` and |tls_alert|. |reason| is the * reason phrase of length |reasonlen|. This function does not make a * copy of the reason phrase. */ -NGTCP2_EXTERN void ngtcp2_connection_close_error_set_transport_error_tls_alert( - ngtcp2_connection_close_error *ccerr, uint8_t tls_alert, - const uint8_t *reason, size_t reasonlen); +NGTCP2_EXTERN void ngtcp2_ccerr_set_tls_alert(ngtcp2_ccerr *ccerr, + uint8_t tls_alert, + const uint8_t *reason, + size_t reasonlen); /** * @function * - * `ngtcp2_connection_close_error_set_application_error` sets - * :member:`ccerr->type ` to - * :enum:`ngtcp2_connection_close_error_code_type.NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION`, - * and :member:`ccerr->error_code - * ` to |error_code|. - * |reason| is the reason phrase of length |reasonlen|. This function - * does not make a copy of the reason phrase. + * `ngtcp2_ccerr_set_application_error` sets :member:`ccerr->type + * ` to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_APPLICATION`, and + * :member:`ccerr->error_code ` to + * |error_code|. |reason| is the reason phrase of length |reasonlen|. + * This function does not make a copy of the reason phrase. */ -NGTCP2_EXTERN void ngtcp2_connection_close_error_set_application_error( - ngtcp2_connection_close_error *ccerr, uint64_t error_code, - const uint8_t *reason, size_t reasonlen); +NGTCP2_EXTERN void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr, + uint64_t error_code, + const uint8_t *reason, + size_t reasonlen); /** * @function @@ -5295,20 +5337,25 @@ NGTCP2_EXTERN void ngtcp2_connection_close_error_set_application_error( * * If |path| is not ``NULL``, this function stores the network path * with which the packet should be sent. Each addr field must point - * to the buffer which should be at least ``sizeof(struct - * sockaddr_storage)`` bytes long. The assignment might not be done - * if nothing is written to |dest|. + * to the buffer which should be at least + * sizeof(:type:`ngtcp2_sockaddr_union`) bytes long. The assignment + * might not be done if nothing is written to |dest|. * * If |pi| is not ``NULL``, this function stores packet metadata in it * if it succeeds. The metadata includes ECN markings. * - * If :member:`ccerr->type ` == - * :enum:`ngtcp2_connection_close_error_code_type.NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT`, - * this function sends CONNECTION_CLOSE (type 0x1c) frame. If - * :member:`ccerr->type ` == - * :enum:`ngtcp2_connection_close_error_code_type.NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION`, - * it sends CONNECTION_CLOSE (type 0x1d) frame. Otherwise, it does - * not produce any data, and returns 0. + * If :member:`ccerr->type ` == + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_TRANSPORT`, this + * function sends CONNECTION_CLOSE (type 0x1c) frame. If + * :member:`ccerr->type ` == + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_APPLICATION`, it sends + * CONNECTION_CLOSE (type 0x1d) frame. Otherwise, it does not produce + * any data, and returns 0. + * + * |destlen| could be shorten by some factors (e.g., server side + * amplification limit). This function returns + * :macro:`NGTCP2_ERR_NOBUF` if the resulting buffer is too small even + * if the given buffer has enough space. * * This function must not be called from inside the callback * functions. @@ -5325,7 +5372,8 @@ NGTCP2_EXTERN void ngtcp2_connection_close_error_set_application_error( * :macro:`NGTCP2_ERR_NOBUF` * Buffer is too small * :macro:`NGTCP2_ERR_INVALID_STATE` - * The current state does not allow sending CONNECTION_CLOSE. + * The current state does not allow sending CONNECTION_CLOSE + * frame. * :macro:`NGTCP2_ERR_PKT_NUM_EXHAUSTED` * Packet number is exhausted, and cannot send any more packet. * :macro:`NGTCP2_ERR_CALLBACK_FAILURE` @@ -5334,23 +5382,22 @@ NGTCP2_EXTERN void ngtcp2_connection_close_error_set_application_error( NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_connection_close_versioned( ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, - const ngtcp2_connection_close_error *ccerr, ngtcp2_tstamp ts); + const ngtcp2_ccerr *ccerr, ngtcp2_tstamp ts); /** * @function * - * `ngtcp2_conn_get_connection_close_error` stores the received - * connection close error in |ccerr|. + * `ngtcp2_conn_get_ccerr` returns the received connection close + * error. If no connection error is received, it returns + * :type:`ngtcp2_ccerr` that is initialized by `ngtcp2_ccerr_default`. */ -NGTCP2_EXTERN void -ngtcp2_conn_get_connection_close_error(ngtcp2_conn *conn, - ngtcp2_connection_close_error *ccerr); +NGTCP2_EXTERN const ngtcp2_ccerr *ngtcp2_conn_get_ccerr(ngtcp2_conn *conn); /** * @function * - * `ngtcp2_conn_is_local_stream` returns nonzero if |stream_id| denotes the - * stream which a local endpoint issues. + * `ngtcp2_conn_is_local_stream` returns nonzero if |stream_id| + * denotes a locally initiated stream. */ NGTCP2_EXTERN int ngtcp2_conn_is_local_stream(ngtcp2_conn *conn, int64_t stream_id); @@ -5367,7 +5414,7 @@ NGTCP2_EXTERN int ngtcp2_conn_is_server(ngtcp2_conn *conn); * @function * * `ngtcp2_conn_after_retry` returns nonzero if |conn| as a client has - * received Retry packet from server and successfully validated it. + * received Retry packet from server, and successfully validated it. */ NGTCP2_EXTERN int ngtcp2_conn_after_retry(ngtcp2_conn *conn); @@ -5391,12 +5438,11 @@ NGTCP2_EXTERN int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn, * @function * * `ngtcp2_conn_update_pkt_tx_time` sets the time instant of the next - * packet transmission. This function is noop if packet pacing is - * disabled. If packet pacing is enabled, this function must be - * called after (multiple invocation of) `ngtcp2_conn_writev_stream`. - * If packet aggregation (e.g., packet batching, GSO) is used, call - * this function after all aggregated datagrams are sent, which - * indicates multiple invocation of `ngtcp2_conn_writev_stream`. + * packet transmission to pace packets. This function must be called + * after (multiple invocation of) `ngtcp2_conn_writev_stream`. If + * packet aggregation (e.g., packet batching, GSO) is used, call this + * function after all aggregated datagrams are sent, which indicates + * multiple invocation of `ngtcp2_conn_writev_stream`. */ NGTCP2_EXTERN void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts); @@ -5405,8 +5451,7 @@ NGTCP2_EXTERN void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, * @function * * `ngtcp2_conn_get_send_quantum` returns the maximum number of bytes - * that can be sent in one go without packet spacing. If packet - * pacing is disabled, this function returns SIZE_MAX. + * that can be sent in one go without packet spacing. */ NGTCP2_EXTERN size_t ngtcp2_conn_get_send_quantum(ngtcp2_conn *conn); @@ -5427,8 +5472,8 @@ NGTCP2_EXTERN size_t ngtcp2_conn_get_stream_loss_count(ngtcp2_conn *conn, * * `ngtcp2_strerror` returns the text representation of |liberr|. * |liberr| must be one of ngtcp2 library error codes (which is - * defined as NGTCP2_ERR_* macro, such as - * :macro:`NGTCP2_ERR_DECRYPT`). + * defined as :macro:`NGTCP2_ERR_* ` + * macros). */ NGTCP2_EXTERN const char *ngtcp2_strerror(int liberr); @@ -5437,8 +5482,8 @@ NGTCP2_EXTERN const char *ngtcp2_strerror(int liberr); * * `ngtcp2_err_is_fatal` returns nonzero if |liberr| is a fatal error. * |liberr| must be one of ngtcp2 library error codes (which is - * defined as NGTCP2_ERR_* macro, such as - * :macro:`NGTCP2_ERR_DECRYPT`). + * defined as :macro:`NGTCP2_ERR_* ` + * macros). */ NGTCP2_EXTERN int ngtcp2_err_is_fatal(int liberr); @@ -5448,7 +5493,7 @@ NGTCP2_EXTERN int ngtcp2_err_is_fatal(int liberr); * `ngtcp2_err_infer_quic_transport_error_code` returns a QUIC * transport error code which corresponds to |liberr|. |liberr| must * be one of ngtcp2 library error codes (which is defined as - * NGTCP2_ERR_* macro, such as :macro:`NGTCP2_ERR_DECRYPT`). + * :macro:`NGTCP2_ERR_* ` macros). */ NGTCP2_EXTERN uint64_t ngtcp2_err_infer_quic_transport_error_code(int liberr); @@ -5501,7 +5546,7 @@ NGTCP2_EXTERN void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps); * @function * * `ngtcp2_settings_default` initializes |settings| with the default - * values. First this function fills |settings| with 0 and set the + * values. First this function fills |settings| with 0, and set the * default value to the following fields: * * * :type:`cc_algo ` = @@ -5509,10 +5554,10 @@ NGTCP2_EXTERN void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps); * * :type:`initial_rtt ` = * :macro:`NGTCP2_DEFAULT_INITIAL_RTT` * * :type:`ack_thresh ` = 2 - * * :type:`max_udp_payload_size - * ` = 1452 + * * :type:`max_tx_udp_payload_size + * ` = 1452 * * :type:`handshake_timeout ` = - * :macro:`NGTCP2_DEFAULT_HANDSHAKE_TIMEOUT`. + * ``UINT64_MAX`` */ NGTCP2_EXTERN void ngtcp2_settings_default_versioned(int settings_version, ngtcp2_settings *settings); @@ -5521,7 +5566,7 @@ NGTCP2_EXTERN void ngtcp2_settings_default_versioned(int settings_version, * @function * * `ngtcp2_transport_params_default` initializes |params| with the - * default values. First this function fills |params| with 0 and set + * default values. First this function fills |params| with 0, and set * the default value to the following fields: * * * :type:`max_udp_payload_size @@ -5564,7 +5609,7 @@ NGTCP2_EXTERN const ngtcp2_mem *ngtcp2_mem_default(void); /** * @struct * - * :type:`ngtcp2_info` is what `ngtcp2_version()` returns. It holds + * :type:`ngtcp2_info` is what `ngtcp2_version` returns. It holds * information about the particular ngtcp2 version. */ typedef struct ngtcp2_info { @@ -5576,12 +5621,12 @@ typedef struct ngtcp2_info { int age; /** * :member:`version_num` is the :macro:`NGTCP2_VERSION_NUM` number - * (since age ==1) + * (since :member:`age` ==1) */ int version_num; /** * :member:`version_str` points to the :macro:`NGTCP2_VERSION` - * string (since age ==1) + * string (since :member:`age` ==1) */ const char *version_str; /* -------- the above fields all exist when age == 1 */ @@ -5590,10 +5635,10 @@ typedef struct ngtcp2_info { /** * @function * - * `ngtcp2_version` returns a pointer to a ngtcp2_info struct with - * version information about the run-time library in use. The + * `ngtcp2_version` returns a pointer to a :type:`ngtcp2_info` struct + * with version information about the run-time library in use. The * |least_version| argument can be set to a 24 bit numerical value for - * the least accepted version number and if the condition is not met, + * the least accepted version number, and if the condition is not met, * this function will return a ``NULL``. Pass in 0 to skip the * version checking. */ @@ -5628,12 +5673,12 @@ NGTCP2_EXTERN int ngtcp2_path_eq(const ngtcp2_path *a, const ngtcp2_path *b); /** * @function * - * `ngtcp2_is_supported_version` returns nonzero if the library supports - * QUIC version |version|. + * `ngtcp2_is_supported_version` returns nonzero if the library + * supports QUIC version |version|. */ NGTCP2_EXTERN int ngtcp2_is_supported_version(uint32_t version); -/* +/** * @function * * `ngtcp2_is_reserved_version` returns nonzero if |version| is a @@ -5649,9 +5694,9 @@ NGTCP2_EXTERN int ngtcp2_is_reserved_version(uint32_t version); * |preferred_versions| of |preferred_versionslen| elements specifies * the preference of versions, which is sorted in the order of * preference. All versions included in |preferred_versions| must be - * supported by the library, that is, passing a version to - * `ngtcp2_is_supported_version` must return nonzero. This function - * is intended to be used by client when it receives Version + * supported by the library, that is, passing any version in the array + * to `ngtcp2_is_supported_version` must return nonzero. This + * function is intended to be used by client when it receives Version * Negotiation packet. If no version is selected, this function * returns 0. */ @@ -5703,6 +5748,17 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ (PDATALEN), (FLAGS), (STREAM_ID), (DATAV), (DATAVCNT), (TS)) +/* + * `ngtcp2_conn_write_datagram` is a wrapper around + * `ngtcp2_conn_write_datagram_versioned` to set the correct struct + * version. + */ +#define ngtcp2_conn_write_datagram(CONN, PATH, PI, DEST, DESTLEN, PACCEPTED, \ + FLAGS, DGRAM_ID, DATA, DATALEN, TS) \ + ngtcp2_conn_write_datagram_versioned( \ + (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ + (PACCEPTED), (FLAGS), (DGRAM_ID), (DATA), (DATALEN), (TS)) + /* * `ngtcp2_conn_writev_datagram` is a wrapper around * `ngtcp2_conn_writev_datagram_versioned` to set the correct struct @@ -5726,22 +5782,22 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, (CCERR), (TS)) /* - * `ngtcp2_encode_transport_params` is a wrapper around - * `ngtcp2_encode_transport_params_versioned` to set the correct + * `ngtcp2_transport_params_encode` is a wrapper around + * `ngtcp2_transport_params_encode_versioned` to set the correct * struct version. */ -#define ngtcp2_encode_transport_params(DEST, DESTLEN, EXTTYPE, PARAMS) \ - ngtcp2_encode_transport_params_versioned( \ - (DEST), (DESTLEN), (EXTTYPE), NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS)) +#define ngtcp2_transport_params_encode(DEST, DESTLEN, PARAMS) \ + ngtcp2_transport_params_encode_versioned( \ + (DEST), (DESTLEN), NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS)) /* - * `ngtcp2_decode_transport_params` is a wrapper around - * `ngtcp2_decode_transport_params_versioned` to set the correct + * `ngtcp2_transport_params_decode` is a wrapper around + * `ngtcp2_transport_params_decode_versioned` to set the correct * struct version. */ -#define ngtcp2_decode_transport_params(PARAMS, EXTTYPE, DATA, DATALEN) \ - ngtcp2_decode_transport_params_versioned( \ - NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS), (EXTTYPE), (DATA), (DATALEN)) +#define ngtcp2_transport_params_decode(PARAMS, DATA, DATALEN) \ + ngtcp2_transport_params_decode_versioned(NGTCP2_TRANSPORT_PARAMS_VERSION, \ + (PARAMS), (DATA), (DATALEN)) /* * `ngtcp2_conn_client_new` is a wrapper around @@ -5767,15 +5823,6 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, (CALLBACKS), NGTCP2_SETTINGS_VERSION, (SETTINGS), \ NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS), (MEM), (USER_DATA)) -/* - * `ngtcp2_conn_set_early_remote_transport_params` is a wrapper around - * `ngtcp2_conn_set_early_remote_transport_params_versioned` to set - * the correct struct version. - */ -#define ngtcp2_conn_set_early_remote_transport_params(CONN, PARAMS) \ - ngtcp2_conn_set_early_remote_transport_params_versioned( \ - (CONN), NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS)) - /* * `ngtcp2_conn_set_local_transport_params` is a wrapper around * `ngtcp2_conn_set_local_transport_params_versioned` to set the @@ -5795,12 +5842,12 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, (PARAMS)) /* - * `ngtcp2_conn_get_conn_stat` is a wrapper around - * `ngtcp2_conn_get_conn_stat_versioned` to set the correct struct + * `ngtcp2_conn_get_conn_info` is a wrapper around + * `ngtcp2_conn_get_conn_info_versioned` to set the correct struct * version. */ -#define ngtcp2_conn_get_conn_stat(CONN, CSTAT) \ - ngtcp2_conn_get_conn_stat_versioned((CONN), NGTCP2_CONN_STAT_VERSION, (CSTAT)) +#define ngtcp2_conn_get_conn_info(CONN, CINFO) \ + ngtcp2_conn_get_conn_info_versioned((CONN), NGTCP2_CONN_INFO_VERSION, (CINFO)) /* * `ngtcp2_settings_default` is a wrapper around diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h index 9f7592b84a4585..801c6cb2681386 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h @@ -36,7 +36,7 @@ * * Version number of the ngtcp2 library release. */ -#define NGTCP2_VERSION "0.8.1" +#define NGTCP2_VERSION "1.3.0" /** * @macro @@ -46,6 +46,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGTCP2_VERSION_NUM 0x000801 +#define NGTCP2_VERSION_NUM 0x010300 #endif /* VERSION_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c index 02c45de90d112a..d4778d66accf31 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c @@ -27,6 +27,9 @@ #include #include "ngtcp2_macro.h" +#include "ngtcp2_tstamp.h" + +ngtcp2_objalloc_def(acktr_entry, ngtcp2_acktr_entry, oplent); static void acktr_entry_init(ngtcp2_acktr_entry *ent, int64_t pkt_num, ngtcp2_tstamp tstamp) { @@ -66,7 +69,7 @@ int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, rv = ngtcp2_ringbuf_init(&acktr->acks, 32, sizeof(ngtcp2_acktr_ack_entry), mem); if (rv != 0) { - return rv; + goto fail_acks_init; } ngtcp2_ksl_init(&acktr->ents, greater, sizeof(int64_t), mem); @@ -78,6 +81,10 @@ int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, acktr->rx_npkt = 0; return 0; + +fail_acks_init: + ngtcp2_objalloc_free(&acktr->objalloc); + return rv; } void ngtcp2_acktr_free(ngtcp2_acktr *acktr) { @@ -286,16 +293,16 @@ void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) { return; } - min_ack = largest_ack - (int64_t)fr->first_ack_blklen; + min_ack = largest_ack - (int64_t)fr->first_ack_range; if (min_ack <= ent->pkt_num && ent->pkt_num <= largest_ack) { acktr_on_ack(acktr, rb, j); return; } - for (i = 0; i < fr->num_blks && j < nacks; ++i) { - largest_ack = min_ack - (int64_t)fr->blks[i].gap - 2; - min_ack = largest_ack - (int64_t)fr->blks[i].blklen; + for (i = 0; i < fr->rangecnt && j < nacks; ++i) { + largest_ack = min_ack - (int64_t)fr->ranges[i].gap - 2; + min_ack = largest_ack - (int64_t)fr->ranges[i].len; for (;;) { if (ent->pkt_num > largest_ack) { @@ -326,8 +333,7 @@ void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr) { int ngtcp2_acktr_require_active_ack(ngtcp2_acktr *acktr, ngtcp2_duration max_ack_delay, ngtcp2_tstamp ts) { - return acktr->first_unacked_ts != UINT64_MAX && - acktr->first_unacked_ts + max_ack_delay <= ts; + return ngtcp2_tstamp_elapsed(acktr->first_unacked_ts, max_ack_delay, ts); } void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h index 1b00d64fe62cb6..809fb692adc3c8 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h @@ -65,7 +65,7 @@ typedef struct ngtcp2_acktr_entry { }; } ngtcp2_acktr_entry; -ngtcp2_objalloc_def(acktr_entry, ngtcp2_acktr_entry, oplent); +ngtcp2_objalloc_decl(acktr_entry, ngtcp2_acktr_entry, oplent); /* * ngtcp2_acktr_entry_objalloc_new allocates memory for ent, and @@ -124,7 +124,8 @@ typedef struct ngtcp2_acktr { /* first_unacked_ts is timestamp when ngtcp2_acktr_entry is added first time after the last outgoing ACK frame. */ ngtcp2_tstamp first_unacked_ts; - /* rx_npkt is the number of packets received without sending ACK. */ + /* rx_npkt is the number of ACK eliciting packets received without + sending ACK. */ size_t rx_npkt; } ngtcp2_acktr; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c index daab5dd7ce664b..f389abe76d71c8 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c @@ -27,6 +27,8 @@ #include #include +#include "ngtcp2_unreachable.h" + ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const ngtcp2_sockaddr *addr, ngtcp2_socklen addrlen) { dest->addrlen = addrlen; @@ -66,8 +68,7 @@ static int sockaddr_eq(const ngtcp2_sockaddr *a, const ngtcp2_sockaddr *b) { memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr)) == 0; } default: - assert(0); - abort(); + ngtcp2_unreachable(); } } @@ -109,8 +110,7 @@ uint32_t ngtcp2_addr_compare(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { return flags; } default: - assert(0); - abort(); + ngtcp2_unreachable(); } } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h index f1d7f7bdc70ea9..8e3a9f591d9977 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h @@ -38,8 +38,10 @@ */ void ngtcp2_addr_copy(ngtcp2_addr *dest, const ngtcp2_addr *src); -/* - * ngtcp2_addr_eq returns nonzero if |a| equals |b|. +/** + * @function + * + * `ngtcp2_addr_eq` returns nonzero if |a| equals |b|. */ int ngtcp2_addr_eq(const ngtcp2_addr *a, const ngtcp2_addr *b); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c index 0816d69b816c52..27c4667c03924a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c @@ -9,7 +9,7 @@ * 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 following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. @@ -25,668 +25,1426 @@ #include "ngtcp2_bbr.h" #include +#include #include "ngtcp2_log.h" #include "ngtcp2_macro.h" #include "ngtcp2_mem.h" #include "ngtcp2_rcvry.h" #include "ngtcp2_rst.h" +#include "ngtcp2_conn_stat.h" -static const double pacing_gain_cycle[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1}; +#define NGTCP2_BBR_MAX_BW_FILTERLEN 2 -#define NGTCP2_BBR_GAIN_CYCLELEN \ - (sizeof(pacing_gain_cycle) / sizeof(pacing_gain_cycle[0])) +#define NGTCP2_BBR_EXTRA_ACKED_FILTERLEN 10 + +#define NGTCP2_BBR_STARTUP_PACING_GAIN_H 277 + +#define NGTCP2_BBR_STARTUP_CWND_GAIN_H 200 + +#define NGTCP2_BBR_PROBE_RTT_CWND_GAIN_H 50 + +#define NGTCP2_BBR_BETA_NUMER 7 +#define NGTCP2_BBR_BETA_DENOM 10 + +#define NGTCP2_BBR_LOSS_THRESH_NUMER 2 +#define NGTCP2_BBR_LOSS_THRESH_DENOM 100 + +#define NGTCP2_BBR_HEADROOM_NUMER 15 +#define NGTCP2_BBR_HEADROOM_DENOM 100 + +#define NGTCP2_BBR_PROBE_RTT_INTERVAL (5 * NGTCP2_SECONDS) +#define NGTCP2_BBR_MIN_RTT_FILTERLEN (10 * NGTCP2_SECONDS) -#define NGTCP2_BBR_HIGH_GAIN 2.89 #define NGTCP2_BBR_PROBE_RTT_DURATION (200 * NGTCP2_MILLISECONDS) -#define NGTCP2_RTPROP_FILTERLEN (10 * NGTCP2_SECONDS) -#define NGTCP2_BBR_BTL_BW_FILTERLEN 10 -static void bbr_update_on_ack(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, +#define NGTCP2_BBR_PACING_MARGIN_PERCENT 1 + +static void bbr_on_init(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp initial_ts); + +static void bbr_on_transmit(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts); + +static void bbr_reset_congestion_signals(ngtcp2_cc_bbr *bbr); + +static void bbr_reset_lower_bounds(ngtcp2_cc_bbr *bbr); + +static void bbr_init_round_counting(ngtcp2_cc_bbr *bbr); + +static void bbr_init_full_pipe(ngtcp2_cc_bbr *bbr); + +static void bbr_init_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); + +static void bbr_set_pacing_rate_with_gain(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + uint64_t pacing_gain_h); + +static void bbr_set_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); + +static void bbr_enter_startup(ngtcp2_cc_bbr *bbr); + +static void bbr_check_startup_done(ngtcp2_cc_bbr *bbr, + const ngtcp2_cc_ack *ack); + +static void bbr_update_on_ack(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); -static void bbr_update_model_and_state(ngtcp2_bbr_cc *cc, + +static void bbr_update_model_and_state(ngtcp2_cc_bbr *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); -static void bbr_update_control_parameters(ngtcp2_bbr_cc *cc, + +static void bbr_update_control_parameters(ngtcp2_cc_bbr *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack); -static void bbr_on_transmit(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat); -static void bbr_init_round_counting(ngtcp2_bbr_cc *cc); -static void bbr_update_round(ngtcp2_bbr_cc *cc, const ngtcp2_cc_ack *ack); -static void bbr_update_btl_bw(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); -static void bbr_update_rtprop(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); -static void bbr_init_pacing_rate(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat); -static void bbr_set_pacing_rate_with_gain(ngtcp2_bbr_cc *cc, + +static void bbr_update_on_loss(ngtcp2_cc_bbr *cc, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); + +static void bbr_update_latest_delivery_signals(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static void bbr_advance_latest_delivery_signals(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static void bbr_update_congestion_signals(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - double pacing_gain); -static void bbr_set_pacing_rate(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat); -static void bbr_set_send_quantum(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat); -static void bbr_update_target_cwnd(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat); -static void bbr_modulate_cwnd_for_recovery(ngtcp2_bbr_cc *cc, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); -static void bbr_save_cwnd(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat); -static void bbr_restore_cwnd(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat); -static void bbr_modulate_cwnd_for_probe_rtt(ngtcp2_bbr_cc *cc, - ngtcp2_conn_stat *cstat); -static void bbr_set_cwnd(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); -static void bbr_init(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp initial_ts); -static void bbr_enter_startup(ngtcp2_bbr_cc *cc); -static void bbr_init_full_pipe(ngtcp2_bbr_cc *cc); -static void bbr_check_full_pipe(ngtcp2_bbr_cc *cc); -static void bbr_enter_drain(ngtcp2_bbr_cc *cc); -static void bbr_check_drain(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack); + +static void bbr_adapt_lower_bounds_from_congestion(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static void bbr_init_lower_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); + +static void bbr_loss_lower_bounds(ngtcp2_cc_bbr *bbr); + +static void bbr_bound_bw_for_model(ngtcp2_cc_bbr *bbr); + +static void bbr_update_max_bw(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack); + +static void bbr_update_round(ngtcp2_cc_bbr *bbr, const ngtcp2_cc_ack *ack); + +static void bbr_start_round(ngtcp2_cc_bbr *bbr); + +static int bbr_is_in_probe_bw_state(ngtcp2_cc_bbr *bbr); + +static void bbr_update_ack_aggregation(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts); + +static void bbr_enter_drain(ngtcp2_cc_bbr *bbr); + +static void bbr_check_drain(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -static void bbr_enter_probe_bw(ngtcp2_bbr_cc *cc, ngtcp2_tstamp ts); -static void bbr_check_cycle_phase(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); -static void bbr_advance_cycle_phase(ngtcp2_bbr_cc *cc, ngtcp2_tstamp ts); -static int bbr_is_next_cycle_phase(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, + +static void bbr_enter_probe_bw(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts); + +static void bbr_start_probe_bw_down(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts); + +static void bbr_start_probe_bw_cruise(ngtcp2_cc_bbr *bbr); + +static void bbr_start_probe_bw_refill(ngtcp2_cc_bbr *bbr); + +static void bbr_start_probe_bw_up(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts); + +static void bbr_update_probe_bw_cycle_phase(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts); + +static int bbr_check_time_to_cruise(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts); + +static int bbr_has_elapsed_in_phase(ngtcp2_cc_bbr *bbr, + ngtcp2_duration interval, ngtcp2_tstamp ts); + +static uint64_t bbr_inflight_with_headroom(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static void bbr_raise_inflight_hi_slope(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static void bbr_probe_inflight_hi_upward(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack); + +static void bbr_adapt_upper_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); -static void bbr_handle_restart_from_idle(ngtcp2_bbr_cc *cc, - ngtcp2_conn_stat *cstat); -static void bbr_check_probe_rtt(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, + +static int bbr_check_time_to_probe_bw(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts); + +static void bbr_pick_probe_wait(ngtcp2_cc_bbr *bbr); + +static int bbr_is_reno_coexistence_probe_time(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static uint64_t bbr_target_inflight(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static int bbr_check_inflight_too_high(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts); + +static int is_inflight_too_high(const ngtcp2_rs *rs); + +static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_rs *rs, ngtcp2_tstamp ts); + +static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); + +static uint64_t bbr_inflight_hi_from_lost_packet(ngtcp2_cc_bbr *bbr, + const ngtcp2_rs *rs, + const ngtcp2_cc_pkt *pkt); + +static void bbr_update_min_rtt(ngtcp2_cc_bbr *bbr, const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts); + +static void bbr_check_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -static void bbr_enter_probe_rtt(ngtcp2_bbr_cc *cc); -static void bbr_handle_probe_rtt(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, + +static void bbr_enter_probe_rtt(ngtcp2_cc_bbr *bbr); + +static void bbr_handle_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -static void bbr_exit_probe_rtt(ngtcp2_bbr_cc *cc, ngtcp2_tstamp ts); - -void ngtcp2_bbr_cc_init(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_rst *rst, ngtcp2_tstamp initial_ts, - ngtcp2_rand rand, const ngtcp2_rand_ctx *rand_ctx, - ngtcp2_log *log) { - cc->ccb.log = log; - cc->rst = rst; - cc->rand = rand; - cc->rand_ctx = *rand_ctx; - cc->initial_cwnd = cstat->cwnd; - bbr_init(cc, cstat, initial_ts); -} - -void ngtcp2_bbr_cc_free(ngtcp2_bbr_cc *cc) { (void)cc; } - -int ngtcp2_cc_bbr_cc_init(ngtcp2_cc *cc, ngtcp2_log *log, - ngtcp2_conn_stat *cstat, ngtcp2_rst *rst, - ngtcp2_tstamp initial_ts, ngtcp2_rand rand, - const ngtcp2_rand_ctx *rand_ctx, - const ngtcp2_mem *mem) { - ngtcp2_bbr_cc *bbr_cc; - - bbr_cc = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_bbr_cc)); - if (bbr_cc == NULL) { - return NGTCP2_ERR_NOMEM; - } - - ngtcp2_bbr_cc_init(bbr_cc, cstat, rst, initial_ts, rand, rand_ctx, log); - - cc->ccb = &bbr_cc->ccb; - cc->on_pkt_acked = ngtcp2_cc_bbr_cc_on_pkt_acked; - cc->congestion_event = ngtcp2_cc_bbr_cc_congestion_event; - cc->on_spurious_congestion = ngtcp2_cc_bbr_cc_on_spurious_congestion; - cc->on_persistent_congestion = ngtcp2_cc_bbr_cc_on_persistent_congestion; - cc->on_ack_recv = ngtcp2_cc_bbr_cc_on_ack_recv; - cc->on_pkt_sent = ngtcp2_cc_bbr_cc_on_pkt_sent; - cc->new_rtt_sample = ngtcp2_cc_bbr_cc_new_rtt_sample; - cc->reset = ngtcp2_cc_bbr_cc_reset; - cc->event = ngtcp2_cc_bbr_cc_event; - return 0; -} +static void bbr_check_probe_rtt_done(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); + +static void bbr_mark_connection_app_limited(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static void bbr_exit_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts); + +static void bbr_handle_restart_from_idle(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts); + +static uint64_t bbr_bdp_multiple(ngtcp2_cc_bbr *bbr, uint64_t bw, + uint64_t gain_h); + +static uint64_t bbr_quantization_budget(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + uint64_t inflight); + +static uint64_t bbr_inflight(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + uint64_t bw, uint64_t gain_h); + +static void bbr_update_max_inflight(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static void bbr_update_offload_budget(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static uint64_t min_pipe_cwnd(size_t max_udp_payload_size); + +static void bbr_advance_max_bw_filter(ngtcp2_cc_bbr *bbr); + +static void bbr_modulate_cwnd_for_recovery(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack); + +static void bbr_save_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); + +static void bbr_restore_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); + +static uint64_t bbr_probe_rtt_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); + +static void bbr_bound_cwnd_for_probe_rtt(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static void bbr_set_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack); + +static void bbr_bound_cwnd_for_model(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat); + +static void bbr_set_send_quantum(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); + +static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, + ngtcp2_tstamp sent_time); + +static void bbr_handle_recovery(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); + +static void bbr_on_init(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp initial_ts) { + ngtcp2_window_filter_init(&bbr->max_bw_filter, NGTCP2_BBR_MAX_BW_FILTERLEN); + ngtcp2_window_filter_init(&bbr->extra_acked_filter, + NGTCP2_BBR_EXTRA_ACKED_FILTERLEN); + + bbr->min_rtt = UINT64_MAX; + bbr->min_rtt_stamp = initial_ts; + /* remark: Use UINT64_MAX instead of 0 for consistency. */ + bbr->probe_rtt_done_stamp = UINT64_MAX; + bbr->probe_rtt_round_done = 0; + bbr->prior_cwnd = 0; + bbr->idle_restart = 0; + bbr->extra_acked_interval_start = initial_ts; + bbr->extra_acked_delivered = 0; + + bbr_reset_congestion_signals(bbr); + bbr_reset_lower_bounds(bbr); + bbr_init_round_counting(bbr); + bbr_init_full_pipe(bbr); + bbr_init_pacing_rate(bbr, cstat); + bbr_enter_startup(bbr); + + cstat->send_quantum = cstat->max_tx_udp_payload_size * 10; + + /* Missing in documentation */ + bbr->loss_round_start = 0; + bbr->loss_round_delivered = UINT64_MAX; + + bbr->rounds_since_bw_probe = 0; + + bbr->max_bw = 0; + bbr->bw = 0; + + bbr->cycle_count = 0; + + bbr->extra_acked = 0; + + bbr->bytes_lost_in_round = 0; + bbr->loss_events_in_round = 0; -void ngtcp2_cc_bbr_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem) { - ngtcp2_bbr_cc *bbr_cc = ngtcp2_struct_of(cc->ccb, ngtcp2_bbr_cc, ccb); + bbr->offload_budget = 0; - ngtcp2_bbr_cc_free(bbr_cc); - ngtcp2_mem_free(mem, bbr_cc); + bbr->probe_up_cnt = UINT64_MAX; + bbr->cycle_stamp = UINT64_MAX; + bbr->ack_phase = 0; + bbr->bw_probe_wait = 0; + bbr->bw_probe_samples = 0; + bbr->bw_probe_up_rounds = 0; + bbr->bw_probe_up_acks = 0; + + bbr->inflight_hi = UINT64_MAX; + bbr->bw_hi = UINT64_MAX; + + bbr->probe_rtt_expired = 0; + bbr->probe_rtt_min_delay = UINT64_MAX; + bbr->probe_rtt_min_stamp = initial_ts; + + bbr->in_loss_recovery = 0; + bbr->packet_conservation = 0; + + bbr->max_inflight = 0; + + bbr->congestion_recovery_start_ts = UINT64_MAX; + bbr->congestion_recovery_next_round_delivered = 0; + + bbr->prior_inflight_lo = 0; + bbr->prior_inflight_hi = 0; + bbr->prior_bw_lo = 0; } -void ngtcp2_cc_bbr_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { - (void)ccx; - (void)cstat; - (void)pkt; - (void)ts; +static void bbr_reset_congestion_signals(ngtcp2_cc_bbr *bbr) { + bbr->loss_in_round = 0; + bbr->bw_latest = 0; + bbr->inflight_latest = 0; } -static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, - ngtcp2_tstamp sent_time) { - return cstat->congestion_recovery_start_ts != UINT64_MAX && - sent_time <= cstat->congestion_recovery_start_ts; +static void bbr_reset_lower_bounds(ngtcp2_cc_bbr *bbr) { + bbr->bw_lo = UINT64_MAX; + bbr->inflight_lo = UINT64_MAX; } -void ngtcp2_cc_bbr_cc_congestion_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp sent_ts, - ngtcp2_tstamp ts) { - ngtcp2_bbr_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr_cc, ccb); +static void bbr_init_round_counting(ngtcp2_cc_bbr *bbr) { + bbr->next_round_delivered = 0; + bbr->round_start = 0; + bbr->round_count = 0; +} - if (cc->in_loss_recovery || cc->congestion_recovery_start_ts != UINT64_MAX || - in_congestion_recovery(cstat, sent_ts)) { +static void bbr_init_full_pipe(ngtcp2_cc_bbr *bbr) { + bbr->filled_pipe = 0; + bbr->full_bw = 0; + bbr->full_bw_count = 0; +} + +static void bbr_check_startup_full_bandwidth(ngtcp2_cc_bbr *bbr) { + if (bbr->filled_pipe || !bbr->round_start || bbr->rst->rs.is_app_limited) { return; } - cc->congestion_recovery_start_ts = ts; -} + if (bbr->max_bw * 100 >= bbr->full_bw * 125) { + bbr->full_bw = bbr->max_bw; + bbr->full_bw_count = 0; + } -void ngtcp2_cc_bbr_cc_on_spurious_congestion(ngtcp2_cc *ccx, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - ngtcp2_bbr_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr_cc, ccb); - (void)ts; + ++bbr->full_bw_count; - cc->congestion_recovery_start_ts = UINT64_MAX; - cstat->congestion_recovery_start_ts = UINT64_MAX; + if (bbr->full_bw_count >= 3) { + bbr->filled_pipe = 1; - if (cc->in_loss_recovery) { - cc->in_loss_recovery = 0; - cc->packet_conservation = 0; - bbr_restore_cwnd(cc, cstat); + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, + "bbr filled pipe, full_bw=%" PRIu64, bbr->full_bw); } } -void ngtcp2_cc_bbr_cc_on_persistent_congestion(ngtcp2_cc *ccx, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - ngtcp2_bbr_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr_cc, ccb); - (void)ts; +static void bbr_check_startup_high_loss(ngtcp2_cc_bbr *bbr, + const ngtcp2_cc_ack *ack) { + if (bbr->filled_pipe || !bbr->round_start || bbr->rst->rs.is_app_limited) { + return; + } - cstat->congestion_recovery_start_ts = UINT64_MAX; - cc->congestion_recovery_start_ts = UINT64_MAX; - cc->in_loss_recovery = 0; - cc->packet_conservation = 0; + if (bbr->loss_events_in_round <= 3) { + return; + } - bbr_save_cwnd(cc, cstat); - cstat->cwnd = 2 * cstat->max_udp_payload_size; -} + /* loss_thresh = 2% */ + if (bbr->bytes_lost_in_round * 100 <= ack->prior_bytes_in_flight * 2) { + return; + } -void ngtcp2_cc_bbr_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - ngtcp2_bbr_cc *bbr_cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr_cc, ccb); + bbr->filled_pipe = 1; +} - bbr_update_on_ack(bbr_cc, cstat, ack, ts); +static void bbr_init_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { + cstat->pacing_interval = NGTCP2_MILLISECONDS * 100 / + NGTCP2_BBR_STARTUP_PACING_GAIN_H / bbr->initial_cwnd; } -void ngtcp2_cc_bbr_cc_on_pkt_sent(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt) { - ngtcp2_bbr_cc *bbr_cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr_cc, ccb); - (void)pkt; +static void bbr_set_pacing_rate_with_gain(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + uint64_t pacing_gain_h) { + ngtcp2_duration interval; + + if (bbr->bw == 0) { + return; + } + + interval = NGTCP2_SECONDS * 100 * 100 / pacing_gain_h / bbr->bw / + (100 - NGTCP2_BBR_PACING_MARGIN_PERCENT); - bbr_on_transmit(bbr_cc, cstat); + if (bbr->filled_pipe || interval < cstat->pacing_interval) { + cstat->pacing_interval = interval; + } } -void ngtcp2_cc_bbr_cc_new_rtt_sample(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - (void)ccx; - (void)cstat; - (void)ts; +static void bbr_set_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { + bbr_set_pacing_rate_with_gain(bbr, cstat, bbr->pacing_gain_h); } -void ngtcp2_cc_bbr_cc_reset(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - ngtcp2_bbr_cc *bbr_cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr_cc, ccb); - bbr_init(bbr_cc, cstat, ts); +static void bbr_enter_startup(ngtcp2_cc_bbr *bbr) { + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, "bbr enter Startup"); + + bbr->state = NGTCP2_BBR_STATE_STARTUP; + bbr->pacing_gain_h = NGTCP2_BBR_STARTUP_PACING_GAIN_H; + bbr->cwnd_gain_h = NGTCP2_BBR_STARTUP_CWND_GAIN_H; } -void ngtcp2_cc_bbr_cc_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - ngtcp2_cc_event_type event, ngtcp2_tstamp ts) { - (void)ccx; - (void)cstat; - (void)event; - (void)ts; +static void bbr_check_startup_done(ngtcp2_cc_bbr *bbr, + const ngtcp2_cc_ack *ack) { + bbr_check_startup_full_bandwidth(bbr); + bbr_check_startup_high_loss(bbr, ack); + + if (bbr->state == NGTCP2_BBR_STATE_STARTUP && bbr->filled_pipe) { + bbr_enter_drain(bbr); + } +} + +static void bbr_on_transmit(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + bbr_handle_restart_from_idle(bbr, cstat, ts); } -static void bbr_update_on_ack(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, +static void bbr_update_on_ack(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - bbr_update_model_and_state(cc, cstat, ack, ts); - bbr_update_control_parameters(cc, cstat, ack); + bbr_update_model_and_state(bbr, cstat, ack, ts); + bbr_update_control_parameters(bbr, cstat, ack); } -static void bbr_update_model_and_state(ngtcp2_bbr_cc *cc, +static void bbr_update_model_and_state(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - bbr_update_btl_bw(cc, cstat, ack); - bbr_check_cycle_phase(cc, cstat, ack, ts); - bbr_check_full_pipe(cc); - bbr_check_drain(cc, cstat, ts); - bbr_update_rtprop(cc, cstat, ts); - bbr_check_probe_rtt(cc, cstat, ts); + bbr_update_latest_delivery_signals(bbr, cstat); + bbr_update_congestion_signals(bbr, cstat, ack); + bbr_update_ack_aggregation(bbr, cstat, ack, ts); + bbr_check_startup_done(bbr, ack); + bbr_check_drain(bbr, cstat, ts); + bbr_update_probe_bw_cycle_phase(bbr, cstat, ack, ts); + bbr_update_min_rtt(bbr, ack, ts); + bbr_check_probe_rtt(bbr, cstat, ts); + bbr_advance_latest_delivery_signals(bbr, cstat); + bbr_bound_bw_for_model(bbr); } -static void bbr_update_control_parameters(ngtcp2_bbr_cc *cc, +static void bbr_update_control_parameters(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack) { - bbr_set_pacing_rate(cc, cstat); - bbr_set_send_quantum(cc, cstat); - bbr_set_cwnd(cc, cstat, ack); + bbr_set_pacing_rate(bbr, cstat); + bbr_set_send_quantum(bbr, cstat); + bbr_set_cwnd(bbr, cstat, ack); } -static void bbr_on_transmit(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat) { - bbr_handle_restart_from_idle(cc, cstat); +static void bbr_update_on_loss(ngtcp2_cc_bbr *cc, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { + bbr_handle_lost_packet(cc, cstat, pkt, ts); } -static void bbr_init_round_counting(ngtcp2_bbr_cc *cc) { - cc->next_round_delivered = 0; - cc->round_start = 0; - cc->round_count = 0; -} - -static void bbr_update_round(ngtcp2_bbr_cc *cc, const ngtcp2_cc_ack *ack) { - if (ack->pkt_delivered >= cc->next_round_delivered) { - cc->next_round_delivered = cc->rst->delivered; - ++cc->round_count; - cc->round_start = 1; +static void bbr_update_latest_delivery_signals(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + bbr->loss_round_start = 0; + bbr->bw_latest = ngtcp2_max(bbr->bw_latest, cstat->delivery_rate_sec); + bbr->inflight_latest = + ngtcp2_max(bbr->inflight_latest, bbr->rst->rs.delivered); - return; + if (bbr->rst->rs.prior_delivered >= bbr->loss_round_delivered) { + bbr->loss_round_delivered = bbr->rst->delivered; + bbr->loss_round_start = 1; } +} - cc->round_start = 0; +static void bbr_advance_latest_delivery_signals(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + if (bbr->loss_round_start) { + bbr->bw_latest = cstat->delivery_rate_sec; + bbr->inflight_latest = bbr->rst->rs.delivered; + } } -static void bbr_handle_recovery(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - if (cc->in_loss_recovery) { - if (ack->pkt_delivered >= cc->congestion_recovery_next_round_delivered) { - cc->packet_conservation = 0; - } +static void bbr_update_congestion_signals(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack) { + bbr_update_max_bw(bbr, cstat, ack); + + if (ack->bytes_lost) { + bbr->bytes_lost_in_round += ack->bytes_lost; + ++bbr->loss_events_in_round; - if (!in_congestion_recovery(cstat, ack->largest_acked_sent_ts)) { - cc->in_loss_recovery = 0; - cc->packet_conservation = 0; - bbr_restore_cwnd(cc, cstat); + if (!bbr->loss_in_round) { + bbr->loss_in_round = 1; + bbr->loss_round_delivered = bbr->rst->delivered; } + } + if (!bbr->loss_round_start) { return; } - if (cc->congestion_recovery_start_ts != UINT64_MAX) { - cc->in_loss_recovery = 1; - bbr_save_cwnd(cc, cstat); - cstat->cwnd = cstat->bytes_in_flight + - ngtcp2_max(ack->bytes_delivered, cstat->max_udp_payload_size); + bbr_adapt_lower_bounds_from_congestion(bbr, cstat); - cstat->congestion_recovery_start_ts = cc->congestion_recovery_start_ts; - cc->congestion_recovery_start_ts = UINT64_MAX; - cc->packet_conservation = 1; - cc->congestion_recovery_next_round_delivered = cc->rst->delivered; + bbr->loss_in_round = 0; +} + +static void bbr_adapt_lower_bounds_from_congestion(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + if (bbr_is_in_probe_bw_state(bbr)) { + return; + } + + if (bbr->loss_in_round) { + bbr_init_lower_bounds(bbr, cstat); + bbr_loss_lower_bounds(bbr); } } -static void bbr_update_btl_bw(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - bbr_update_round(cc, ack); - bbr_handle_recovery(cc, cstat, ack); +static void bbr_init_lower_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { + if (bbr->bw_lo == UINT64_MAX) { + bbr->bw_lo = bbr->max_bw; + } - if (cstat->delivery_rate_sec < cc->btl_bw && cc->rst->rs.is_app_limited) { - return; + if (bbr->inflight_lo == UINT64_MAX) { + bbr->inflight_lo = cstat->cwnd; } +} - ngtcp2_window_filter_update(&cc->btl_bw_filter, cstat->delivery_rate_sec, - cc->round_count); +static void bbr_loss_lower_bounds(ngtcp2_cc_bbr *bbr) { + bbr->bw_lo = ngtcp2_max(bbr->bw_latest, bbr->bw_lo * NGTCP2_BBR_BETA_NUMER / + NGTCP2_BBR_BETA_DENOM); + bbr->inflight_lo = ngtcp2_max(bbr->inflight_latest, + bbr->inflight_lo * NGTCP2_BBR_BETA_NUMER / + NGTCP2_BBR_BETA_DENOM); +} - cc->btl_bw = ngtcp2_window_filter_get_best(&cc->btl_bw_filter); +static void bbr_bound_bw_for_model(ngtcp2_cc_bbr *bbr) { + bbr->bw = ngtcp2_min(bbr->max_bw, bbr->bw_lo); + bbr->bw = ngtcp2_min(bbr->bw, bbr->bw_hi); } -static void bbr_update_rtprop(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - cc->rtprop_expired = ts > cc->rtprop_stamp + NGTCP2_RTPROP_FILTERLEN; +static void bbr_update_max_bw(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack) { + bbr_update_round(bbr, ack); - /* Need valid RTT sample */ - if (cstat->latest_rtt && - (cstat->latest_rtt <= cc->rt_prop || cc->rtprop_expired)) { - cc->rt_prop = cstat->latest_rtt; - cc->rtprop_stamp = ts; + if (cstat->delivery_rate_sec >= bbr->max_bw || !bbr->rst->rs.is_app_limited) { + ngtcp2_window_filter_update(&bbr->max_bw_filter, cstat->delivery_rate_sec, + bbr->cycle_count); - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr update RTprop=%" PRIu64, cc->rt_prop); + bbr->max_bw = ngtcp2_window_filter_get_best(&bbr->max_bw_filter); } } -static void bbr_init_pacing_rate(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat) { - double nominal_bandwidth = - (double)cc->initial_cwnd / (double)NGTCP2_MILLISECONDS; +static void bbr_update_round(ngtcp2_cc_bbr *bbr, const ngtcp2_cc_ack *ack) { + if (ack->pkt_delivered >= bbr->next_round_delivered) { + bbr_start_round(bbr); - cstat->pacing_rate = cc->pacing_gain * nominal_bandwidth; -} + ++bbr->round_count; + ++bbr->rounds_since_bw_probe; + bbr->round_start = 1; -static void bbr_set_pacing_rate_with_gain(ngtcp2_bbr_cc *cc, - ngtcp2_conn_stat *cstat, - double pacing_gain) { - double rate = pacing_gain * (double)cc->btl_bw / NGTCP2_SECONDS; + bbr->bytes_lost_in_round = 0; + bbr->loss_events_in_round = 0; + + bbr->rst->is_cwnd_limited = 0; - if (cc->filled_pipe || rate > cstat->pacing_rate) { - cstat->pacing_rate = rate; + return; } + + bbr->round_start = 0; } -static void bbr_set_pacing_rate(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat) { - bbr_set_pacing_rate_with_gain(cc, cstat, cc->pacing_gain); +static void bbr_start_round(ngtcp2_cc_bbr *bbr) { + bbr->next_round_delivered = bbr->rst->delivered; } -static void bbr_set_send_quantum(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat) { - uint64_t send_quantum; - (void)cc; +static int bbr_is_in_probe_bw_state(ngtcp2_cc_bbr *bbr) { + switch (bbr->state) { + case NGTCP2_BBR_STATE_PROBE_BW_DOWN: + case NGTCP2_BBR_STATE_PROBE_BW_CRUISE: + case NGTCP2_BBR_STATE_PROBE_BW_REFILL: + case NGTCP2_BBR_STATE_PROBE_BW_UP: + return 1; + default: + return 0; + } +} - if (cstat->pacing_rate < 1.2 * 1024 * 1024 / 8 / NGTCP2_SECONDS) { - cstat->send_quantum = cstat->max_udp_payload_size; - } else if (cstat->pacing_rate < 24.0 * 1024 * 1024 / 8 / NGTCP2_SECONDS) { - cstat->send_quantum = cstat->max_udp_payload_size * 2; - } else { - send_quantum = - (uint64_t)(cstat->pacing_rate * (double)(cstat->min_rtt == UINT64_MAX - ? NGTCP2_MILLISECONDS - : cstat->min_rtt)); - cstat->send_quantum = (size_t)ngtcp2_min(send_quantum, 64 * 1024); +static void bbr_update_ack_aggregation(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts) { + ngtcp2_duration interval = ts - bbr->extra_acked_interval_start; + uint64_t expected_delivered = bbr->bw * interval / NGTCP2_SECONDS; + uint64_t extra; + + if (bbr->extra_acked_delivered <= expected_delivered) { + bbr->extra_acked_delivered = 0; + bbr->extra_acked_interval_start = ts; + expected_delivered = 0; } - cstat->send_quantum = - ngtcp2_max(cstat->send_quantum, cstat->max_udp_payload_size * 10); + bbr->extra_acked_delivered += ack->bytes_delivered; + extra = bbr->extra_acked_delivered - expected_delivered; + extra = ngtcp2_min(extra, cstat->cwnd); + + ngtcp2_window_filter_update(&bbr->extra_acked_filter, extra, + bbr->round_count); + + bbr->extra_acked = ngtcp2_window_filter_get_best(&bbr->extra_acked_filter); } -static uint64_t bbr_inflight(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - double gain) { - uint64_t quanta = 3 * cstat->send_quantum; - double estimated_bdp; +static void bbr_enter_drain(ngtcp2_cc_bbr *bbr) { + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, "bbr enter Drain"); + + bbr->state = NGTCP2_BBR_STATE_DRAIN; + bbr->pacing_gain_h = 100 * 100 / NGTCP2_BBR_STARTUP_CWND_GAIN_H; + bbr->cwnd_gain_h = NGTCP2_BBR_STARTUP_CWND_GAIN_H; +} - if (cc->rt_prop == UINT64_MAX) { - /* no valid RTT samples yet */ - return cc->initial_cwnd; +static void bbr_check_drain(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + if (bbr->state == NGTCP2_BBR_STATE_DRAIN && + cstat->bytes_in_flight <= bbr_inflight(bbr, cstat, bbr->bw, 100)) { + bbr_enter_probe_bw(bbr, ts); } +} - estimated_bdp = (double)cc->btl_bw * (double)cc->rt_prop / NGTCP2_SECONDS; +static void bbr_enter_probe_bw(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts) { + bbr_start_probe_bw_down(bbr, ts); +} - return (uint64_t)(gain * estimated_bdp) + quanta; +static void bbr_start_probe_bw_down(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts) { + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, "bbr start ProbeBW_DOWN"); + + bbr_reset_congestion_signals(bbr); + + bbr->probe_up_cnt = UINT64_MAX; + + bbr_pick_probe_wait(bbr); + + bbr->cycle_stamp = ts; + bbr->ack_phase = NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_STOPPING; + + bbr_start_round(bbr); + + bbr->state = NGTCP2_BBR_STATE_PROBE_BW_DOWN; + bbr->pacing_gain_h = 90; + bbr->cwnd_gain_h = 200; } -static void bbr_update_target_cwnd(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat) { - cc->target_cwnd = bbr_inflight(cc, cstat, cc->cwnd_gain); +static void bbr_start_probe_bw_cruise(ngtcp2_cc_bbr *bbr) { + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, + "bbr start ProbeBW_CRUISE"); + + bbr->state = NGTCP2_BBR_STATE_PROBE_BW_CRUISE; + bbr->pacing_gain_h = 100; + bbr->cwnd_gain_h = 200; } -static void bbr_modulate_cwnd_for_recovery(ngtcp2_bbr_cc *cc, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - if (ack->bytes_lost > 0) { - if (cstat->cwnd > ack->bytes_lost) { - cstat->cwnd -= ack->bytes_lost; - cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_udp_payload_size); - } else { - cstat->cwnd = cstat->max_udp_payload_size; - } +static void bbr_start_probe_bw_refill(ngtcp2_cc_bbr *bbr) { + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, + "bbr start ProbeBW_REFILL"); + + bbr_reset_lower_bounds(bbr); + + bbr->bw_probe_up_rounds = 0; + bbr->bw_probe_up_acks = 0; + bbr->ack_phase = NGTCP2_BBR_ACK_PHASE_ACKS_REFILLING; + + bbr_start_round(bbr); + + bbr->state = NGTCP2_BBR_STATE_PROBE_BW_REFILL; + bbr->pacing_gain_h = 100; + bbr->cwnd_gain_h = 200; +} + +static void bbr_start_probe_bw_up(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, "bbr start ProbeBW_UP"); + + bbr->ack_phase = NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_STARTING; + + bbr_start_round(bbr); + + bbr->cycle_stamp = ts; + bbr->state = NGTCP2_BBR_STATE_PROBE_BW_UP; + bbr->pacing_gain_h = 125; + bbr->cwnd_gain_h = 225; + + bbr_raise_inflight_hi_slope(bbr, cstat); +} + +static void bbr_update_probe_bw_cycle_phase(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts) { + if (!bbr->filled_pipe) { + return; } - if (cc->packet_conservation) { - cstat->cwnd = - ngtcp2_max(cstat->cwnd, cstat->bytes_in_flight + ack->bytes_delivered); + bbr_adapt_upper_bounds(bbr, cstat, ack, ts); + + if (!bbr_is_in_probe_bw_state(bbr)) { + return; + } + + switch (bbr->state) { + case NGTCP2_BBR_STATE_PROBE_BW_DOWN: + if (bbr_check_time_to_probe_bw(bbr, cstat, ts)) { + return; + } + + if (bbr_check_time_to_cruise(bbr, cstat, ts)) { + bbr_start_probe_bw_cruise(bbr); + } + + break; + case NGTCP2_BBR_STATE_PROBE_BW_CRUISE: + if (bbr_check_time_to_probe_bw(bbr, cstat, ts)) { + return; + } + + break; + case NGTCP2_BBR_STATE_PROBE_BW_REFILL: + if (bbr->round_start) { + bbr->bw_probe_samples = 1; + bbr_start_probe_bw_up(bbr, cstat, ts); + } + + break; + case NGTCP2_BBR_STATE_PROBE_BW_UP: + if (bbr_has_elapsed_in_phase(bbr, bbr->min_rtt, ts) && + cstat->bytes_in_flight > bbr_inflight(bbr, cstat, bbr->max_bw, 125)) { + bbr_start_probe_bw_down(bbr, ts); + } + + break; + default: + break; } } -static void bbr_save_cwnd(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat) { - if (!cc->in_loss_recovery && cc->state != NGTCP2_BBR_STATE_PROBE_RTT) { - cc->prior_cwnd = cstat->cwnd; - return; +static int bbr_check_time_to_cruise(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + (void)ts; + + if (cstat->bytes_in_flight > bbr_inflight_with_headroom(bbr, cstat)) { + return 0; } - cc->prior_cwnd = ngtcp2_max(cc->prior_cwnd, cstat->cwnd); + if (cstat->bytes_in_flight <= bbr_inflight(bbr, cstat, bbr->max_bw, 100)) { + return 1; + } + + return 0; } -static void bbr_restore_cwnd(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat) { - cstat->cwnd = ngtcp2_max(cstat->cwnd, cc->prior_cwnd); +static int bbr_has_elapsed_in_phase(ngtcp2_cc_bbr *bbr, + ngtcp2_duration interval, + ngtcp2_tstamp ts) { + return ts > bbr->cycle_stamp + interval; } -static uint64_t min_pipe_cwnd(size_t max_udp_payload_size) { - return max_udp_payload_size * 4; +static uint64_t bbr_inflight_with_headroom(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + uint64_t headroom; + uint64_t mpcwnd; + if (bbr->inflight_hi == UINT64_MAX) { + return UINT64_MAX; + } + + headroom = ngtcp2_max(cstat->max_tx_udp_payload_size, + bbr->inflight_hi * NGTCP2_BBR_HEADROOM_NUMER / + NGTCP2_BBR_HEADROOM_DENOM); + mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size); + + if (bbr->inflight_hi > headroom) { + return ngtcp2_max(bbr->inflight_hi - headroom, mpcwnd); + } + + return mpcwnd; } -static void bbr_modulate_cwnd_for_probe_rtt(ngtcp2_bbr_cc *cc, - ngtcp2_conn_stat *cstat) { - if (cc->state == NGTCP2_BBR_STATE_PROBE_RTT) { - cstat->cwnd = - ngtcp2_min(cstat->cwnd, min_pipe_cwnd(cstat->max_udp_payload_size)); +static void bbr_raise_inflight_hi_slope(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + uint64_t growth_this_round = cstat->max_tx_udp_payload_size + << bbr->bw_probe_up_rounds; + + bbr->bw_probe_up_rounds = ngtcp2_min(bbr->bw_probe_up_rounds + 1, 30); + bbr->probe_up_cnt = ngtcp2_max(cstat->cwnd / growth_this_round, 1) * + cstat->max_tx_udp_payload_size; +} + +static void bbr_probe_inflight_hi_upward(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack) { + uint64_t delta; + + if (!bbr->rst->is_cwnd_limited || cstat->cwnd < bbr->inflight_hi) { + return; + } + + bbr->bw_probe_up_acks += ack->bytes_delivered; + + if (bbr->bw_probe_up_acks >= bbr->probe_up_cnt) { + delta = bbr->bw_probe_up_acks / bbr->probe_up_cnt; + bbr->bw_probe_up_acks -= delta * bbr->probe_up_cnt; + bbr->inflight_hi += delta * cstat->max_tx_udp_payload_size; + } + + if (bbr->round_start) { + bbr_raise_inflight_hi_slope(bbr, cstat); } } -static void bbr_set_cwnd(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - bbr_update_target_cwnd(cc, cstat); - bbr_modulate_cwnd_for_recovery(cc, cstat, ack); - - if (!cc->packet_conservation) { - if (cc->filled_pipe) { - cstat->cwnd = - ngtcp2_min(cstat->cwnd + ack->bytes_delivered, cc->target_cwnd); - } else if (cstat->cwnd < cc->target_cwnd || - cc->rst->delivered < cc->initial_cwnd) { - cstat->cwnd += ack->bytes_delivered; +static void bbr_adapt_upper_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { + if (bbr->ack_phase == NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_STARTING && + bbr->round_start) { + bbr->ack_phase = NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_FEEDBACK; + } + + if (bbr->ack_phase == NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_STOPPING && + bbr->round_start) { + if (bbr_is_in_probe_bw_state(bbr) && !bbr->rst->rs.is_app_limited) { + bbr_advance_max_bw_filter(bbr); } + } - cstat->cwnd = - ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_udp_payload_size)); + if (!bbr_check_inflight_too_high(bbr, cstat, ts)) { + /* bbr->bw_hi never be updated */ + if (bbr->inflight_hi == UINT64_MAX /* || bbr->bw_hi == UINT64_MAX */) { + return; + } + + if (bbr->rst->rs.tx_in_flight > bbr->inflight_hi) { + bbr->inflight_hi = bbr->rst->rs.tx_in_flight; + } + + if (cstat->delivery_rate_sec > bbr->bw_hi) { + bbr->bw_hi = cstat->delivery_rate_sec; + } + + if (bbr->state == NGTCP2_BBR_STATE_PROBE_BW_UP) { + bbr_probe_inflight_hi_upward(bbr, cstat, ack); + } + } +} + +static int bbr_check_time_to_probe_bw(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + if (bbr_has_elapsed_in_phase(bbr, bbr->bw_probe_wait, ts) || + bbr_is_reno_coexistence_probe_time(bbr, cstat)) { + bbr_start_probe_bw_refill(bbr); + + return 1; } - bbr_modulate_cwnd_for_probe_rtt(cc, cstat); + return 0; } -static void bbr_init(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp initial_ts) { - cc->pacing_gain = NGTCP2_BBR_HIGH_GAIN; - cc->prior_cwnd = 0; - cc->target_cwnd = 0; - cc->btl_bw = 0; - cc->rt_prop = UINT64_MAX; - cc->rtprop_stamp = initial_ts; - cc->cycle_stamp = UINT64_MAX; - cc->probe_rtt_done_stamp = UINT64_MAX; - cc->cycle_index = 0; - cc->rtprop_expired = 0; - cc->idle_restart = 0; - cc->packet_conservation = 0; - cc->probe_rtt_round_done = 0; +static void bbr_pick_probe_wait(ngtcp2_cc_bbr *bbr) { + uint8_t rand; - cc->congestion_recovery_start_ts = UINT64_MAX; - cc->congestion_recovery_next_round_delivered = 0; - cc->in_loss_recovery = 0; + bbr->rand(&rand, 1, &bbr->rand_ctx); - cstat->send_quantum = cstat->max_udp_payload_size * 10; + bbr->rounds_since_bw_probe = (uint64_t)(rand * 2 / 256); - ngtcp2_window_filter_init(&cc->btl_bw_filter, NGTCP2_BBR_BTL_BW_FILTERLEN); + bbr->rand(&rand, 1, &bbr->rand_ctx); - bbr_init_round_counting(cc); - bbr_init_full_pipe(cc); - bbr_init_pacing_rate(cc, cstat); - bbr_enter_startup(cc); + bbr->bw_probe_wait = + 2 * NGTCP2_SECONDS + (ngtcp2_tstamp)(NGTCP2_SECONDS * rand / 255); } -static void bbr_enter_startup(ngtcp2_bbr_cc *cc) { - cc->state = NGTCP2_BBR_STATE_STARTUP; - cc->pacing_gain = NGTCP2_BBR_HIGH_GAIN; - cc->cwnd_gain = NGTCP2_BBR_HIGH_GAIN; +static int bbr_is_reno_coexistence_probe_time(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + uint64_t reno_rounds = + bbr_target_inflight(bbr, cstat) / cstat->max_tx_udp_payload_size; + + return bbr->rounds_since_bw_probe >= ngtcp2_min(reno_rounds, 63); } -static void bbr_init_full_pipe(ngtcp2_bbr_cc *cc) { - cc->filled_pipe = 0; - cc->full_bw = 0; - cc->full_bw_count = 0; +static uint64_t bbr_target_inflight(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + uint64_t bdp = bbr_inflight(bbr, cstat, bbr->bw, 100); + + return ngtcp2_min(bdp, cstat->cwnd); } -static void bbr_check_full_pipe(ngtcp2_bbr_cc *cc) { - if (cc->filled_pipe || !cc->round_start || cc->rst->rs.is_app_limited) { - /* no need to check for a full pipe now. */ - return; +static int bbr_check_inflight_too_high(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + if (is_inflight_too_high(&bbr->rst->rs)) { + if (bbr->bw_probe_samples) { + bbr_handle_inflight_too_high(bbr, cstat, &bbr->rst->rs, ts); + } + + return 1; } - /* cc->btl_bw still growing? */ - if (cc->btl_bw * 100 >= cc->full_bw * 125) { - /* record new baseline level */ - cc->full_bw = cc->btl_bw; - cc->full_bw_count = 0; + return 0; +} + +static int is_inflight_too_high(const ngtcp2_rs *rs) { + return rs->lost * NGTCP2_BBR_LOSS_THRESH_DENOM > + rs->tx_in_flight * NGTCP2_BBR_LOSS_THRESH_NUMER; +} + +static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_rs *rs, + ngtcp2_tstamp ts) { + bbr->bw_probe_samples = 0; + + if (!rs->is_app_limited) { + bbr->inflight_hi = ngtcp2_max( + rs->tx_in_flight, bbr_target_inflight(bbr, cstat) * + NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM); + } + + if (bbr->state == NGTCP2_BBR_STATE_PROBE_BW_UP) { + bbr_start_probe_bw_down(bbr, ts); + } +} + +static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { + ngtcp2_rs rs = {0}; + + if (!bbr->bw_probe_samples) { return; } - /* another round w/o much growth */ - ++cc->full_bw_count; - if (cc->full_bw_count >= 3) { - cc->filled_pipe = 1; - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr filled pipe, btl_bw=%" PRIu64, cc->btl_bw); + + rs.tx_in_flight = pkt->tx_in_flight; + /* bbr->rst->lost is not incremented for pkt yet */ + rs.lost = bbr->rst->lost + pkt->pktlen - pkt->lost; + rs.is_app_limited = pkt->is_app_limited; + + if (is_inflight_too_high(&rs)) { + rs.tx_in_flight = bbr_inflight_hi_from_lost_packet(bbr, &rs, pkt); + + bbr_handle_inflight_too_high(bbr, cstat, &rs, ts); } } -static void bbr_enter_drain(ngtcp2_bbr_cc *cc) { - cc->state = NGTCP2_BBR_STATE_DRAIN; - /* pace slowly */ - cc->pacing_gain = 1.0 / NGTCP2_BBR_HIGH_GAIN; - /* maintain cwnd */ - cc->cwnd_gain = NGTCP2_BBR_HIGH_GAIN; +static uint64_t bbr_inflight_hi_from_lost_packet(ngtcp2_cc_bbr *bbr, + const ngtcp2_rs *rs, + const ngtcp2_cc_pkt *pkt) { + uint64_t inflight_prev, lost_prev, lost_prefix; + (void)bbr; + + assert(rs->tx_in_flight >= pkt->pktlen); + + inflight_prev = rs->tx_in_flight - pkt->pktlen; + + assert(rs->lost >= pkt->pktlen); + + lost_prev = rs->lost - pkt->pktlen; + + if (inflight_prev * NGTCP2_BBR_LOSS_THRESH_NUMER < + lost_prev * NGTCP2_BBR_LOSS_THRESH_DENOM) { + return inflight_prev; + } + + lost_prefix = (inflight_prev * NGTCP2_BBR_LOSS_THRESH_NUMER - + lost_prev * NGTCP2_BBR_LOSS_THRESH_DENOM) / + (NGTCP2_BBR_LOSS_THRESH_DENOM - NGTCP2_BBR_LOSS_THRESH_NUMER); + + return inflight_prev + lost_prefix; } -static void bbr_check_drain(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - if (cc->state == NGTCP2_BBR_STATE_STARTUP && cc->filled_pipe) { - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr exit Startup and enter Drain"); +static void bbr_update_min_rtt(ngtcp2_cc_bbr *bbr, const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts) { + int min_rtt_expired; + + bbr->probe_rtt_expired = + ts > bbr->probe_rtt_min_stamp + NGTCP2_BBR_PROBE_RTT_INTERVAL; - bbr_enter_drain(cc); + if (ack->rtt != UINT64_MAX && + (ack->rtt < bbr->probe_rtt_min_delay || bbr->probe_rtt_expired)) { + bbr->probe_rtt_min_delay = ack->rtt; + bbr->probe_rtt_min_stamp = ts; } - if (cc->state == NGTCP2_BBR_STATE_DRAIN && - cstat->bytes_in_flight <= bbr_inflight(cc, cstat, 1.0)) { - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr exit Drain and enter ProbeBW"); + min_rtt_expired = ts > bbr->min_rtt_stamp + NGTCP2_BBR_MIN_RTT_FILTERLEN; - /* we estimate queue is drained */ - bbr_enter_probe_bw(cc, ts); + if (bbr->probe_rtt_min_delay < bbr->min_rtt || min_rtt_expired) { + bbr->min_rtt = bbr->probe_rtt_min_delay; + bbr->min_rtt_stamp = bbr->probe_rtt_min_stamp; + + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, + "bbr update min_rtt=%" PRIu64, bbr->min_rtt); } } -static void bbr_enter_probe_bw(ngtcp2_bbr_cc *cc, ngtcp2_tstamp ts) { - uint8_t rand; +static void bbr_check_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + if (bbr->state != NGTCP2_BBR_STATE_PROBE_RTT && bbr->probe_rtt_expired && + !bbr->idle_restart) { + bbr_enter_probe_rtt(bbr); + bbr_save_cwnd(bbr, cstat); + + bbr->probe_rtt_done_stamp = UINT64_MAX; + bbr->ack_phase = NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_STOPPING; - cc->state = NGTCP2_BBR_STATE_PROBE_BW; - cc->pacing_gain = 1; - cc->cwnd_gain = 2; + bbr_start_round(bbr); + } + + if (bbr->state == NGTCP2_BBR_STATE_PROBE_RTT) { + bbr_handle_probe_rtt(bbr, cstat, ts); + } - assert(cc->rand); + if (bbr->rst->rs.delivered) { + bbr->idle_restart = 0; + } +} - cc->rand(&rand, 1, &cc->rand_ctx); +static void bbr_enter_probe_rtt(ngtcp2_cc_bbr *bbr) { + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, "bbr enter ProbeRTT"); - cc->cycle_index = NGTCP2_BBR_GAIN_CYCLELEN - 1 - (size_t)(rand * 7 / 256); - bbr_advance_cycle_phase(cc, ts); + bbr->state = NGTCP2_BBR_STATE_PROBE_RTT; + bbr->pacing_gain_h = 100; + bbr->cwnd_gain_h = NGTCP2_BBR_PROBE_RTT_CWND_GAIN_H; } -static void bbr_check_cycle_phase(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - if (cc->state == NGTCP2_BBR_STATE_PROBE_BW && - bbr_is_next_cycle_phase(cc, cstat, ack, ts)) { - bbr_advance_cycle_phase(cc, ts); +static void bbr_handle_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + bbr_mark_connection_app_limited(bbr, cstat); + + if (bbr->probe_rtt_done_stamp == UINT64_MAX && + cstat->bytes_in_flight <= bbr_probe_rtt_cwnd(bbr, cstat)) { + bbr->probe_rtt_done_stamp = ts + NGTCP2_BBR_PROBE_RTT_DURATION; + bbr->probe_rtt_round_done = 0; + + bbr_start_round(bbr); + + return; + } + + if (bbr->probe_rtt_done_stamp != UINT64_MAX) { + if (bbr->round_start) { + bbr->probe_rtt_round_done = 1; + } + + if (bbr->probe_rtt_round_done) { + bbr_check_probe_rtt_done(bbr, cstat, ts); + } } } -static void bbr_advance_cycle_phase(ngtcp2_bbr_cc *cc, ngtcp2_tstamp ts) { - cc->cycle_stamp = ts; - cc->cycle_index = (cc->cycle_index + 1) & (NGTCP2_BBR_GAIN_CYCLELEN - 1); - cc->pacing_gain = pacing_gain_cycle[cc->cycle_index]; +static void bbr_check_probe_rtt_done(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + if (bbr->probe_rtt_done_stamp != UINT64_MAX && + ts > bbr->probe_rtt_done_stamp) { + bbr->probe_rtt_min_stamp = ts; + bbr_restore_cwnd(bbr, cstat); + bbr_exit_probe_rtt(bbr, ts); + } } -static int bbr_is_next_cycle_phase(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - int is_full_length = (ts - cc->cycle_stamp) > cc->rt_prop; +static void bbr_mark_connection_app_limited(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + uint64_t app_limited = bbr->rst->delivered + cstat->bytes_in_flight; - if (cc->pacing_gain > 1) { - return is_full_length && (ack->bytes_lost > 0 || - ack->prior_bytes_in_flight >= - bbr_inflight(cc, cstat, cc->pacing_gain)); + if (app_limited) { + bbr->rst->app_limited = app_limited; + } else { + bbr->rst->app_limited = cstat->max_tx_udp_payload_size; } +} - if (cc->pacing_gain < 1) { - return is_full_length || - ack->prior_bytes_in_flight <= bbr_inflight(cc, cstat, 1); - } +static void bbr_exit_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts) { + bbr_reset_lower_bounds(bbr); - return is_full_length; + if (bbr->filled_pipe) { + bbr_start_probe_bw_down(bbr, ts); + bbr_start_probe_bw_cruise(bbr); + } else { + bbr_enter_startup(bbr); + } } -static void bbr_handle_restart_from_idle(ngtcp2_bbr_cc *cc, - ngtcp2_conn_stat *cstat) { - if (cstat->bytes_in_flight == 0 && cc->rst->app_limited) { - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, "bbr restart from idle"); +static void bbr_handle_restart_from_idle(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + if (cstat->bytes_in_flight == 0 && bbr->rst->app_limited) { + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, "bbr restart from idle"); - cc->idle_restart = 1; + bbr->idle_restart = 1; + bbr->extra_acked_interval_start = ts; - if (cc->state == NGTCP2_BBR_STATE_PROBE_BW) { - bbr_set_pacing_rate_with_gain(cc, cstat, 1); + if (bbr_is_in_probe_bw_state(bbr)) { + bbr_set_pacing_rate_with_gain(bbr, cstat, 100); + } else if (bbr->state == NGTCP2_BBR_STATE_PROBE_RTT) { + bbr_check_probe_rtt_done(bbr, cstat, ts); } } } -static void bbr_check_probe_rtt(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - if (cc->state != NGTCP2_BBR_STATE_PROBE_RTT && cc->rtprop_expired && - !cc->idle_restart) { - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, "bbr enter ProbeRTT"); +static uint64_t bbr_bdp_multiple(ngtcp2_cc_bbr *bbr, uint64_t bw, + uint64_t gain_h) { + uint64_t bdp; - bbr_enter_probe_rtt(cc); - bbr_save_cwnd(cc, cstat); - cc->probe_rtt_done_stamp = UINT64_MAX; + if (bbr->min_rtt == UINT64_MAX) { + return bbr->initial_cwnd; } - if (cc->state == NGTCP2_BBR_STATE_PROBE_RTT) { - bbr_handle_probe_rtt(cc, cstat, ts); + bdp = bw * bbr->min_rtt / NGTCP2_SECONDS; + + return (uint64_t)(bdp * gain_h / 100); +} + +static uint64_t min_pipe_cwnd(size_t max_udp_payload_size) { + return max_udp_payload_size * 4; +} + +static uint64_t bbr_quantization_budget(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + uint64_t inflight) { + bbr_update_offload_budget(bbr, cstat); + + inflight = ngtcp2_max(inflight, bbr->offload_budget); + inflight = + ngtcp2_max(inflight, min_pipe_cwnd(cstat->max_tx_udp_payload_size)); + + if (bbr->state == NGTCP2_BBR_STATE_PROBE_BW_UP) { + inflight += 2 * cstat->max_tx_udp_payload_size; } - cc->idle_restart = 0; + return inflight; } -static void bbr_enter_probe_rtt(ngtcp2_bbr_cc *cc) { - cc->state = NGTCP2_BBR_STATE_PROBE_RTT; - cc->pacing_gain = 1; - cc->cwnd_gain = 1; +static uint64_t bbr_inflight(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + uint64_t bw, uint64_t gain_h) { + uint64_t inflight = bbr_bdp_multiple(bbr, bw, gain_h); + + return bbr_quantization_budget(bbr, cstat, inflight); } -static void bbr_handle_probe_rtt(ngtcp2_bbr_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - uint64_t app_limited = cc->rst->delivered + cstat->bytes_in_flight; +static void bbr_update_max_inflight(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + uint64_t inflight; + + /* Not documented */ + /* bbr_update_aggregation_budget(bbr); */ + + inflight = + bbr_bdp_multiple(bbr, bbr->bw, bbr->cwnd_gain_h) + bbr->extra_acked; + bbr->max_inflight = bbr_quantization_budget(bbr, cstat, inflight); +} - /* Ignore low rate samples during NGTCP2_BBR_STATE_PROBE_RTT. */ - cc->rst->app_limited = app_limited ? app_limited : 1; +static void bbr_update_offload_budget(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + bbr->offload_budget = 3 * cstat->send_quantum; +} - if (cc->probe_rtt_done_stamp == UINT64_MAX && - cstat->bytes_in_flight <= min_pipe_cwnd(cstat->max_udp_payload_size)) { - cc->probe_rtt_done_stamp = ts + NGTCP2_BBR_PROBE_RTT_DURATION; - cc->probe_rtt_round_done = 0; - cc->next_round_delivered = cc->rst->delivered; +static void bbr_advance_max_bw_filter(ngtcp2_cc_bbr *bbr) { + ++bbr->cycle_count; +} +static void bbr_modulate_cwnd_for_recovery(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack) { + if (ack->bytes_lost > 0) { + if (cstat->cwnd > ack->bytes_lost) { + cstat->cwnd -= ack->bytes_lost; + cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_tx_udp_payload_size); + } else { + cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; + } + } + + if (bbr->packet_conservation) { + cstat->cwnd = + ngtcp2_max(cstat->cwnd, cstat->bytes_in_flight + ack->bytes_delivered); + } +} + +static void bbr_save_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { + if (!bbr->in_loss_recovery && bbr->state != NGTCP2_BBR_STATE_PROBE_RTT) { + bbr->prior_cwnd = cstat->cwnd; return; } - if (cc->probe_rtt_done_stamp != UINT64_MAX) { - if (cc->round_start) { - cc->probe_rtt_round_done = 1; + bbr->prior_cwnd = ngtcp2_max(bbr->prior_cwnd, cstat->cwnd); +} + +static void bbr_restore_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { + cstat->cwnd = ngtcp2_max(cstat->cwnd, bbr->prior_cwnd); +} + +static uint64_t bbr_probe_rtt_cwnd(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + uint64_t probe_rtt_cwnd = + bbr_bdp_multiple(bbr, bbr->bw, NGTCP2_BBR_PROBE_RTT_CWND_GAIN_H); + uint64_t mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size); + + return ngtcp2_max(probe_rtt_cwnd, mpcwnd); +} + +static void bbr_bound_cwnd_for_probe_rtt(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + uint64_t probe_rtt_cwnd; + + if (bbr->state == NGTCP2_BBR_STATE_PROBE_RTT) { + probe_rtt_cwnd = bbr_probe_rtt_cwnd(bbr, cstat); + + cstat->cwnd = ngtcp2_min(cstat->cwnd, probe_rtt_cwnd); + } +} + +static void bbr_set_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack) { + uint64_t mpcwnd; + + bbr_update_max_inflight(bbr, cstat); + bbr_modulate_cwnd_for_recovery(bbr, cstat, ack); + + if (!bbr->packet_conservation) { + if (bbr->filled_pipe) { + cstat->cwnd += ack->bytes_delivered; + cstat->cwnd = ngtcp2_min(cstat->cwnd, bbr->max_inflight); + } else if (cstat->cwnd < bbr->max_inflight || + bbr->rst->delivered < bbr->initial_cwnd) { + cstat->cwnd += ack->bytes_delivered; + } + + mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size); + cstat->cwnd = ngtcp2_max(cstat->cwnd, mpcwnd); + } + + bbr_bound_cwnd_for_probe_rtt(bbr, cstat); + bbr_bound_cwnd_for_model(bbr, cstat); +} + +static void bbr_bound_cwnd_for_model(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + uint64_t cap = UINT64_MAX; + uint64_t mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size); + + if (bbr_is_in_probe_bw_state(bbr) && + bbr->state != NGTCP2_BBR_STATE_PROBE_BW_CRUISE) { + cap = bbr->inflight_hi; + } else if (bbr->state == NGTCP2_BBR_STATE_PROBE_RTT || + bbr->state == NGTCP2_BBR_STATE_PROBE_BW_CRUISE) { + cap = bbr_inflight_with_headroom(bbr, cstat); + } + + cap = ngtcp2_min(cap, bbr->inflight_lo); + cap = ngtcp2_max(cap, mpcwnd); + + cstat->cwnd = ngtcp2_min(cstat->cwnd, cap); +} + +static void bbr_set_send_quantum(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { + size_t floor, send_quantum; + (void)bbr; + + if (cstat->pacing_interval > (NGTCP2_SECONDS * 8 * 10 / 12) >> 20) { + floor = cstat->max_tx_udp_payload_size; + } else { + floor = 2 * cstat->max_tx_udp_payload_size; + } + + if (cstat->pacing_interval) { + send_quantum = (size_t)(NGTCP2_MILLISECONDS / cstat->pacing_interval); + send_quantum = ngtcp2_min(send_quantum, 64 * 1024); + } else { + send_quantum = 64 * 1024; + } + + cstat->send_quantum = ngtcp2_max(send_quantum, floor); +} + +static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, + ngtcp2_tstamp sent_time) { + return cstat->congestion_recovery_start_ts != UINT64_MAX && + sent_time <= cstat->congestion_recovery_start_ts; +} + +static void bbr_handle_recovery(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { + if (bbr->in_loss_recovery) { + if (ts - cstat->congestion_recovery_start_ts >= cstat->smoothed_rtt) { + bbr->packet_conservation = 0; } - if (cc->probe_rtt_round_done && ts > cc->probe_rtt_done_stamp) { - cc->rtprop_stamp = ts; - bbr_restore_cwnd(cc, cstat); - bbr_exit_probe_rtt(cc, ts); + if (ack->largest_pkt_sent_ts != UINT64_MAX && + !in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { + bbr->in_loss_recovery = 0; + bbr->packet_conservation = 0; + bbr_restore_cwnd(bbr, cstat); } + + return; + } + + if (bbr->congestion_recovery_start_ts != UINT64_MAX) { + bbr->in_loss_recovery = 1; + bbr_save_cwnd(bbr, cstat); + cstat->cwnd = + cstat->bytes_in_flight + + ngtcp2_max(ack->bytes_delivered, cstat->max_tx_udp_payload_size); + + cstat->congestion_recovery_start_ts = bbr->congestion_recovery_start_ts; + bbr->congestion_recovery_start_ts = UINT64_MAX; + bbr->packet_conservation = 1; + bbr->congestion_recovery_next_round_delivered = bbr->rst->delivered; + bbr->prior_inflight_hi = bbr->inflight_hi; + bbr->prior_inflight_lo = bbr->inflight_lo; + bbr->prior_bw_lo = bbr->bw_lo; } } -static void bbr_exit_probe_rtt(ngtcp2_bbr_cc *cc, ngtcp2_tstamp ts) { - if (cc->filled_pipe) { - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr exit ProbeRTT and enter ProbeBW"); +static void bbr_cc_on_pkt_lost(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { + ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); + + bbr_update_on_loss(bbr, cstat, pkt, ts); +} - bbr_enter_probe_bw(cc, ts); +static void bbr_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp sent_ts, ngtcp2_tstamp ts) { + ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); + if (bbr->in_loss_recovery || + bbr->congestion_recovery_start_ts != UINT64_MAX || + in_congestion_recovery(cstat, sent_ts)) { return; } - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr exit ProbeRTT and enter Startup"); + bbr->congestion_recovery_start_ts = ts; +} + +static void bbr_cc_on_spurious_congestion(ngtcp2_cc *cc, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); + (void)ts; + + bbr->congestion_recovery_start_ts = UINT64_MAX; + cstat->congestion_recovery_start_ts = UINT64_MAX; + + if (bbr->in_loss_recovery) { + bbr->in_loss_recovery = 0; + bbr->packet_conservation = 0; + bbr_restore_cwnd(bbr, cstat); + bbr->full_bw_count = 0; + bbr->loss_in_round = 0; + bbr->inflight_lo = ngtcp2_max(bbr->inflight_lo, bbr->prior_inflight_lo); + bbr->inflight_hi = ngtcp2_max(bbr->inflight_hi, bbr->prior_inflight_hi); + bbr->bw_lo = ngtcp2_max(bbr->bw_lo, bbr->prior_bw_lo); + } +} + +static void bbr_cc_on_persistent_congestion(ngtcp2_cc *cc, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); + (void)ts; + + cstat->congestion_recovery_start_ts = UINT64_MAX; + bbr->congestion_recovery_start_ts = UINT64_MAX; + bbr->in_loss_recovery = 0; + bbr->packet_conservation = 0; + + bbr_save_cwnd(bbr, cstat); + cstat->cwnd = cstat->bytes_in_flight + cstat->max_tx_udp_payload_size; + cstat->cwnd = + ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size)); +} + +static void bbr_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { + ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); + + bbr_handle_recovery(bbr, cstat, ack, ts); + bbr_update_on_ack(bbr, cstat, ack, ts); +} + +static void bbr_cc_on_pkt_sent(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_pkt *pkt) { + ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); + + bbr_on_transmit(bbr, cstat, pkt->sent_ts); +} + +static void bbr_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); + + bbr_on_init(bbr, cstat, ts); +} - bbr_enter_startup(cc); +void ngtcp2_cc_bbr_init(ngtcp2_cc_bbr *bbr, ngtcp2_log *log, + ngtcp2_conn_stat *cstat, ngtcp2_rst *rst, + ngtcp2_tstamp initial_ts, ngtcp2_rand rand, + const ngtcp2_rand_ctx *rand_ctx) { + memset(bbr, 0, sizeof(*bbr)); + + bbr->cc.log = log; + bbr->cc.on_pkt_lost = bbr_cc_on_pkt_lost; + bbr->cc.congestion_event = bbr_cc_congestion_event; + bbr->cc.on_spurious_congestion = bbr_cc_on_spurious_congestion; + bbr->cc.on_persistent_congestion = bbr_cc_on_persistent_congestion; + bbr->cc.on_ack_recv = bbr_cc_on_ack_recv; + bbr->cc.on_pkt_sent = bbr_cc_on_pkt_sent; + bbr->cc.reset = bbr_cc_reset; + + bbr->rst = rst; + bbr->rand = rand; + bbr->rand_ctx = *rand_ctx; + bbr->initial_cwnd = cstat->cwnd; + + bbr_on_init(bbr, cstat, initial_ts); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h index 7311f051e187bc..0017be35010e66 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h @@ -39,118 +39,108 @@ typedef struct ngtcp2_rst ngtcp2_rst; typedef enum ngtcp2_bbr_state { NGTCP2_BBR_STATE_STARTUP, NGTCP2_BBR_STATE_DRAIN, - NGTCP2_BBR_STATE_PROBE_BW, + NGTCP2_BBR_STATE_PROBE_BW_DOWN, + NGTCP2_BBR_STATE_PROBE_BW_CRUISE, + NGTCP2_BBR_STATE_PROBE_BW_REFILL, + NGTCP2_BBR_STATE_PROBE_BW_UP, NGTCP2_BBR_STATE_PROBE_RTT, } ngtcp2_bbr_state; +typedef enum ngtcp2_bbr_ack_phase { + NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_STARTING, + NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_STOPPING, + NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_FEEDBACK, + NGTCP2_BBR_ACK_PHASE_ACKS_REFILLING, +} ngtcp2_bbr_ack_phase; + /* - * ngtcp2_bbr_cc is BBR congestion controller, described in - * https://tools.ietf.org/html/draft-cardwell-iccrg-bbr-congestion-control-00 + * ngtcp2_cc_bbr is BBR v2 congestion controller, described in + * https://datatracker.ietf.org/doc/html/draft-cardwell-iccrg-bbr-congestion-control-01 */ -typedef struct ngtcp2_bbr_cc { - ngtcp2_cc_base ccb; +typedef struct ngtcp2_cc_bbr { + ngtcp2_cc cc; - /* The max filter used to estimate BBR.BtlBw. */ - ngtcp2_window_filter btl_bw_filter; uint64_t initial_cwnd; ngtcp2_rst *rst; ngtcp2_rand rand; ngtcp2_rand_ctx rand_ctx; - /* BBR variables */ + /* max_bw_filter for tracking the maximum recent delivery rate + samples for estimating max_bw. */ + ngtcp2_window_filter max_bw_filter; - /* The dynamic gain factor used to scale BBR.BtlBw to - produce BBR.pacing_rate. */ - double pacing_gain; - /* The dynamic gain factor used to scale the estimated BDP to produce a - congestion window (cwnd). */ - double cwnd_gain; - uint64_t full_bw; - /* packet.delivered value denoting the end of a packet-timed round trip. */ - uint64_t next_round_delivered; - /* Count of packet-timed round trips. */ - uint64_t round_count; - uint64_t prior_cwnd; - /* target_cwnd is the upper bound on the volume of data BBR - allows in flight. */ - uint64_t target_cwnd; - /* BBR's estimated bottleneck bandwidth available to the - transport flow, estimated from the maximum delivery rate sample in a - sliding window. */ - uint64_t btl_bw; - /* BBR's estimated two-way round-trip propagation delay of - the path, estimated from the windowed minimum recent round-trip delay - sample. */ - ngtcp2_duration rt_prop; - /* The wall clock time at which the current BBR.RTProp - sample was obtained. */ - ngtcp2_tstamp rtprop_stamp; - ngtcp2_tstamp cycle_stamp; + ngtcp2_window_filter extra_acked_filter; + + ngtcp2_duration min_rtt; + ngtcp2_tstamp min_rtt_stamp; ngtcp2_tstamp probe_rtt_done_stamp; - /* congestion_recovery_start_ts is the time when congestion recovery - period started.*/ - ngtcp2_tstamp congestion_recovery_start_ts; - uint64_t congestion_recovery_next_round_delivered; - size_t full_bw_count; - size_t cycle_index; - ngtcp2_bbr_state state; - /* A boolean that records whether BBR estimates that it has ever fully - utilized its available bandwidth ("filled the pipe"). */ - int filled_pipe; - /* A boolean that BBR sets to true once per packet-timed round trip, - on ACKs that advance BBR.round_count. */ - int round_start; - int rtprop_expired; - int idle_restart; - int packet_conservation; int probe_rtt_round_done; - /* in_loss_recovery becomes nonzero when BBR enters loss recovery - period. */ - int in_loss_recovery; -} ngtcp2_bbr_cc; - -int ngtcp2_cc_bbr_cc_init(ngtcp2_cc *cc, ngtcp2_log *log, - ngtcp2_conn_stat *cstat, ngtcp2_rst *rst, - ngtcp2_tstamp initial_ts, ngtcp2_rand rand, - const ngtcp2_rand_ctx *rand_ctx, - const ngtcp2_mem *mem); - -void ngtcp2_cc_bbr_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem); - -void ngtcp2_bbr_cc_init(ngtcp2_bbr_cc *bbr_cc, ngtcp2_conn_stat *cstat, - ngtcp2_rst *rst, ngtcp2_tstamp initial_ts, - ngtcp2_rand rand, const ngtcp2_rand_ctx *rand_ctx, - ngtcp2_log *log); - -void ngtcp2_bbr_cc_free(ngtcp2_bbr_cc *cc); - -void ngtcp2_cc_bbr_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); + uint64_t prior_cwnd; + int idle_restart; + ngtcp2_tstamp extra_acked_interval_start; + uint64_t extra_acked_delivered; -void ngtcp2_cc_bbr_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp sent_ts, ngtcp2_tstamp ts); + /* Congestion signals */ + int loss_in_round; + uint64_t bw_latest; + uint64_t inflight_latest; -void ngtcp2_cc_bbr_cc_on_spurious_congestion(ngtcp2_cc *ccx, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); + /* Lower bounds */ + uint64_t bw_lo; + uint64_t inflight_lo; -void ngtcp2_cc_bbr_cc_on_persistent_congestion(ngtcp2_cc *cc, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); + /* Round counting */ + uint64_t next_round_delivered; + int round_start; + uint64_t round_count; -void ngtcp2_cc_bbr_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); + /* Full pipe */ + int filled_pipe; + uint64_t full_bw; + size_t full_bw_count; -void ngtcp2_cc_bbr_cc_on_pkt_sent(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt); + /* Pacing rate */ + uint64_t pacing_gain_h; -void ngtcp2_cc_bbr_cc_new_rtt_sample(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); + ngtcp2_bbr_state state; + uint64_t cwnd_gain_h; + + int loss_round_start; + uint64_t loss_round_delivered; + uint64_t rounds_since_bw_probe; + uint64_t max_bw; + uint64_t bw; + uint64_t cycle_count; + uint64_t extra_acked; + uint64_t bytes_lost_in_round; + size_t loss_events_in_round; + uint64_t offload_budget; + uint64_t probe_up_cnt; + ngtcp2_tstamp cycle_stamp; + ngtcp2_bbr_ack_phase ack_phase; + ngtcp2_duration bw_probe_wait; + int bw_probe_samples; + size_t bw_probe_up_rounds; + uint64_t bw_probe_up_acks; + uint64_t inflight_hi; + uint64_t bw_hi; + int probe_rtt_expired; + ngtcp2_duration probe_rtt_min_delay; + ngtcp2_tstamp probe_rtt_min_stamp; + int in_loss_recovery; + int packet_conservation; + uint64_t max_inflight; + ngtcp2_tstamp congestion_recovery_start_ts; + uint64_t congestion_recovery_next_round_delivered; -void ngtcp2_cc_bbr_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); + uint64_t prior_inflight_lo; + uint64_t prior_inflight_hi; + uint64_t prior_bw_lo; +} ngtcp2_cc_bbr; -void ngtcp2_cc_bbr_cc_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_cc_event_type event, ngtcp2_tstamp ts); +void ngtcp2_cc_bbr_init(ngtcp2_cc_bbr *bbr, ngtcp2_log *log, + ngtcp2_conn_stat *cstat, ngtcp2_rst *rst, + ngtcp2_tstamp initial_ts, ngtcp2_rand rand, + const ngtcp2_rand_ctx *rand_ctx); #endif /* NGTCP2_BBR_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr2.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr2.c deleted file mode 100644 index 585ea11e8e29a5..00000000000000 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr2.c +++ /dev/null @@ -1,1486 +0,0 @@ -/* - * ngtcp2 - * - * Copyright (c) 2021 ngtcp2 contributors - * - * 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 "ngtcp2_bbr2.h" - -#include - -#include "ngtcp2_log.h" -#include "ngtcp2_macro.h" -#include "ngtcp2_mem.h" -#include "ngtcp2_rcvry.h" -#include "ngtcp2_rst.h" - -#define NGTCP2_BBR_MAX_BW_FILTERLEN 2 - -#define NGTCP2_BBR_EXTRA_ACKED_FILTERLEN 10 - -#define NGTCP2_BBR_STARTUP_PACING_GAIN ((double)2.77) - -#define NGTCP2_BBR_STARTUP_CWND_GAIN 2 - -#define NGTCP2_BBR_PROBE_RTT_CWND_GAIN ((double)0.5) - -#define NGTCP2_BBR_BETA_NUMER 7 -#define NGTCP2_BBR_BETA_DENOM 10 - -#define NGTCP2_BBR_LOSS_THRESH_NUMER 2 -#define NGTCP2_BBR_LOSS_THRESH_DENOM 100 - -#define NGTCP2_BBR_HEADROOM_NUMER 15 -#define NGTCP2_BBR_HEADROOM_DENOM 100 - -#define NGTCP2_BBR_PROBE_RTT_INTERVAL (5 * NGTCP2_SECONDS) -#define NGTCP2_BBR_MIN_RTT_FILTERLEN (10 * NGTCP2_SECONDS) - -#define NGTCP2_BBR_PROBE_RTT_DURATION (200 * NGTCP2_MILLISECONDS) - -#define NGTCP2_BBR_PACING_MARGIN_PERCENT 1 - -static void bbr_on_init(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp initial_ts); - -static void bbr_on_transmit(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - -static void bbr_reset_congestion_signals(ngtcp2_bbr2_cc *bbr); - -static void bbr_reset_lower_bounds(ngtcp2_bbr2_cc *bbr); - -static void bbr_init_round_counting(ngtcp2_bbr2_cc *bbr); - -static void bbr_init_full_pipe(ngtcp2_bbr2_cc *bbr); - -static void bbr_init_pacing_rate(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat); - -static void bbr_set_pacing_rate_with_gain(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - double pacing_gain); - -static void bbr_set_pacing_rate(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat); - -static void bbr_enter_startup(ngtcp2_bbr2_cc *bbr); - -static void bbr_check_startup_done(ngtcp2_bbr2_cc *bbr, - const ngtcp2_cc_ack *ack); - -static void bbr_update_on_ack(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); - -static void bbr_update_model_and_state(ngtcp2_bbr2_cc *cc, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, - ngtcp2_tstamp ts); - -static void bbr_update_control_parameters(ngtcp2_bbr2_cc *cc, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); - -static void bbr_update_on_loss(ngtcp2_bbr2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); - -static void bbr_update_latest_delivery_signals(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_advance_latest_delivery_signals(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_update_congestion_signals(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); - -static void bbr_adapt_lower_bounds_from_congestion(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_init_lower_bounds(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat); - -static void bbr_loss_lower_bounds(ngtcp2_bbr2_cc *bbr); - -static void bbr_bound_bw_for_model(ngtcp2_bbr2_cc *bbr); - -static void bbr_update_max_bw(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); - -static void bbr_update_round(ngtcp2_bbr2_cc *bbr, const ngtcp2_cc_ack *ack); - -static void bbr_start_round(ngtcp2_bbr2_cc *bbr); - -static int bbr_is_in_probe_bw_state(ngtcp2_bbr2_cc *bbr); - -static void bbr_update_ack_aggregation(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, - ngtcp2_tstamp ts); - -static void bbr_enter_drain(ngtcp2_bbr2_cc *bbr); - -static void bbr_check_drain(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - -static void bbr_enter_probe_bw(ngtcp2_bbr2_cc *bbr, ngtcp2_tstamp ts); - -static void bbr_start_probe_bw_down(ngtcp2_bbr2_cc *bbr, ngtcp2_tstamp ts); - -static void bbr_start_probe_bw_cruise(ngtcp2_bbr2_cc *bbr); - -static void bbr_start_probe_bw_refill(ngtcp2_bbr2_cc *bbr); - -static void bbr_start_probe_bw_up(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - -static void bbr_update_probe_bw_cycle_phase(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, - ngtcp2_tstamp ts); - -static int bbr_check_time_to_cruise(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); - -static int bbr_has_elapsed_in_phase(ngtcp2_bbr2_cc *bbr, - ngtcp2_duration interval, ngtcp2_tstamp ts); - -static uint64_t bbr_inflight_with_headroom(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_raise_inflight_hi_slope(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_probe_inflight_hi_upward(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); - -static void bbr_adapt_upper_bounds(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); - -static int bbr_check_time_to_probe_bw(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - -static void bbr_pick_probe_wait(ngtcp2_bbr2_cc *bbr); - -static int bbr_is_reno_coexistence_probe_time(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static uint64_t bbr_target_inflight(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static int bbr_check_inflight_too_high(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - -static int is_inflight_too_high(const ngtcp2_rs *rs); - -static void bbr_handle_inflight_too_high(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_rs *rs, ngtcp2_tstamp ts); - -static void bbr_handle_lost_packet(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); - -static uint64_t bbr_inflight_hi_from_lost_packet(ngtcp2_bbr2_cc *bbr, - const ngtcp2_rs *rs, - const ngtcp2_cc_pkt *pkt); - -static void bbr_update_min_rtt(ngtcp2_bbr2_cc *bbr, const ngtcp2_cc_ack *ack, - ngtcp2_tstamp ts); - -static void bbr_check_probe_rtt(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - -static void bbr_enter_probe_rtt(ngtcp2_bbr2_cc *bbr); - -static void bbr_handle_probe_rtt(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - -static void bbr_check_probe_rtt_done(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); - -static void bbr_mark_connection_app_limited(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_exit_probe_rtt(ngtcp2_bbr2_cc *bbr, ngtcp2_tstamp ts); - -static void bbr_handle_restart_from_idle(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - -static uint64_t bbr_bdp_multiple(ngtcp2_bbr2_cc *bbr, uint64_t bw, double gain); - -static uint64_t bbr_quantization_budget(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - uint64_t inflight); - -static uint64_t bbr_inflight(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - uint64_t bw, double gain); - -static void bbr_update_max_inflight(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_update_offload_budget(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static uint64_t min_pipe_cwnd(size_t max_udp_payload_size); - -static void bbr_advance_max_bw_filter(ngtcp2_bbr2_cc *bbr); - -static void bbr_modulate_cwnd_for_recovery(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); - -static void bbr_save_cwnd(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat); - -static void bbr_restore_cwnd(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat); - -static uint64_t bbr_probe_rtt_cwnd(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_bound_cwnd_for_probe_rtt(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_set_cwnd(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); - -static void bbr_bound_cwnd_for_model(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat); - -static void bbr_set_send_quantum(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat); - -static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, - ngtcp2_tstamp sent_time); - -static void bbr_handle_recovery(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); - -static void bbr_on_init(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp initial_ts) { - ngtcp2_window_filter_init(&bbr->max_bw_filter, NGTCP2_BBR_MAX_BW_FILTERLEN); - ngtcp2_window_filter_init(&bbr->extra_acked_filter, - NGTCP2_BBR_EXTRA_ACKED_FILTERLEN); - - bbr->min_rtt = UINT64_MAX; - bbr->min_rtt_stamp = initial_ts; - /* remark: Use UINT64_MAX instead of 0 for consistency. */ - bbr->probe_rtt_done_stamp = UINT64_MAX; - bbr->probe_rtt_round_done = 0; - bbr->prior_cwnd = 0; - bbr->idle_restart = 0; - bbr->extra_acked_interval_start = initial_ts; - bbr->extra_acked_delivered = 0; - - bbr_reset_congestion_signals(bbr); - bbr_reset_lower_bounds(bbr); - bbr_init_round_counting(bbr); - bbr_init_full_pipe(bbr); - bbr_init_pacing_rate(bbr, cstat); - bbr_enter_startup(bbr); - - cstat->send_quantum = cstat->max_udp_payload_size * 10; - - /* Missing in documentation */ - bbr->loss_round_start = 0; - bbr->loss_round_delivered = UINT64_MAX; - - bbr->rounds_since_bw_probe = 0; - - bbr->max_bw = 0; - bbr->bw = 0; - - bbr->cycle_count = 0; - - bbr->extra_acked = 0; - - bbr->bytes_lost_in_round = 0; - bbr->loss_events_in_round = 0; - - bbr->offload_budget = 0; - - bbr->probe_up_cnt = UINT64_MAX; - bbr->cycle_stamp = UINT64_MAX; - bbr->ack_phase = 0; - bbr->bw_probe_wait = 0; - bbr->bw_probe_samples = 0; - bbr->bw_probe_up_rounds = 0; - bbr->bw_probe_up_acks = 0; - - bbr->inflight_hi = UINT64_MAX; - bbr->bw_hi = UINT64_MAX; - - bbr->probe_rtt_expired = 0; - bbr->probe_rtt_min_delay = UINT64_MAX; - bbr->probe_rtt_min_stamp = initial_ts; - - bbr->in_loss_recovery = 0; - bbr->packet_conservation = 0; - - bbr->max_inflight = 0; - - bbr->congestion_recovery_start_ts = UINT64_MAX; - bbr->congestion_recovery_next_round_delivered = 0; - - bbr->prior_inflight_lo = 0; - bbr->prior_inflight_hi = 0; - bbr->prior_bw_lo = 0; -} - -static void bbr_reset_congestion_signals(ngtcp2_bbr2_cc *bbr) { - bbr->loss_in_round = 0; - bbr->bw_latest = 0; - bbr->inflight_latest = 0; -} - -static void bbr_reset_lower_bounds(ngtcp2_bbr2_cc *bbr) { - bbr->bw_lo = UINT64_MAX; - bbr->inflight_lo = UINT64_MAX; -} - -static void bbr_init_round_counting(ngtcp2_bbr2_cc *bbr) { - bbr->next_round_delivered = 0; - bbr->round_start = 0; - bbr->round_count = 0; -} - -static void bbr_init_full_pipe(ngtcp2_bbr2_cc *bbr) { - bbr->filled_pipe = 0; - bbr->full_bw = 0; - bbr->full_bw_count = 0; -} - -static void bbr_check_startup_full_bandwidth(ngtcp2_bbr2_cc *bbr) { - if (bbr->filled_pipe || !bbr->round_start || bbr->rst->rs.is_app_limited) { - return; - } - - if (bbr->max_bw * 100 >= bbr->full_bw * 125) { - bbr->full_bw = bbr->max_bw; - bbr->full_bw_count = 0; - } - - ++bbr->full_bw_count; - - if (bbr->full_bw_count >= 3) { - bbr->filled_pipe = 1; - - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr2 filled pipe, full_bw=%" PRIu64, bbr->full_bw); - } -} - -static void bbr_check_startup_high_loss(ngtcp2_bbr2_cc *bbr, - const ngtcp2_cc_ack *ack) { - if (bbr->filled_pipe || !bbr->round_start || bbr->rst->rs.is_app_limited) { - return; - } - - if (bbr->loss_events_in_round <= 3) { - return; - } - - /* loss_thresh = 2% */ - if (bbr->bytes_lost_in_round * 100 <= ack->prior_bytes_in_flight * 2) { - return; - } - - bbr->filled_pipe = 1; -} - -static void bbr_init_pacing_rate(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat) { - double nominal_bandwidth = (double)bbr->initial_cwnd; - - cstat->pacing_rate = NGTCP2_BBR_STARTUP_PACING_GAIN * nominal_bandwidth / - (double)NGTCP2_MILLISECONDS; -} - -static void bbr_set_pacing_rate_with_gain(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - double pacing_gain) { - double rate = pacing_gain * (double)bbr->bw * - (100 - NGTCP2_BBR_PACING_MARGIN_PERCENT) / 100 / NGTCP2_SECONDS; - - if (bbr->filled_pipe || rate > cstat->pacing_rate) { - cstat->pacing_rate = rate; - } -} - -static void bbr_set_pacing_rate(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat) { - bbr_set_pacing_rate_with_gain(bbr, cstat, bbr->pacing_gain); -} - -static void bbr_enter_startup(ngtcp2_bbr2_cc *bbr) { - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, "bbr2 enter Startup"); - - bbr->state = NGTCP2_BBR2_STATE_STARTUP; - bbr->pacing_gain = NGTCP2_BBR_STARTUP_PACING_GAIN; - bbr->cwnd_gain = NGTCP2_BBR_STARTUP_CWND_GAIN; -} - -static void bbr_check_startup_done(ngtcp2_bbr2_cc *bbr, - const ngtcp2_cc_ack *ack) { - bbr_check_startup_full_bandwidth(bbr); - bbr_check_startup_high_loss(bbr, ack); - - if (bbr->state == NGTCP2_BBR2_STATE_STARTUP && bbr->filled_pipe) { - bbr_enter_drain(bbr); - } -} - -static void bbr_on_transmit(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - bbr_handle_restart_from_idle(bbr, cstat, ts); -} - -static void bbr_update_on_ack(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - bbr_update_model_and_state(bbr, cstat, ack, ts); - bbr_update_control_parameters(bbr, cstat, ack); -} - -static void bbr_update_model_and_state(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, - ngtcp2_tstamp ts) { - bbr_update_latest_delivery_signals(bbr, cstat); - bbr_update_congestion_signals(bbr, cstat, ack); - bbr_update_ack_aggregation(bbr, cstat, ack, ts); - bbr_check_startup_done(bbr, ack); - bbr_check_drain(bbr, cstat, ts); - bbr_update_probe_bw_cycle_phase(bbr, cstat, ack, ts); - bbr_update_min_rtt(bbr, ack, ts); - bbr_check_probe_rtt(bbr, cstat, ts); - bbr_advance_latest_delivery_signals(bbr, cstat); - bbr_bound_bw_for_model(bbr); -} - -static void bbr_update_control_parameters(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - bbr_set_pacing_rate(bbr, cstat); - bbr_set_send_quantum(bbr, cstat); - bbr_set_cwnd(bbr, cstat, ack); -} - -static void bbr_update_on_loss(ngtcp2_bbr2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { - bbr_handle_lost_packet(cc, cstat, pkt, ts); -} - -static void bbr_update_latest_delivery_signals(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - bbr->loss_round_start = 0; - bbr->bw_latest = ngtcp2_max(bbr->bw_latest, cstat->delivery_rate_sec); - bbr->inflight_latest = - ngtcp2_max(bbr->inflight_latest, bbr->rst->rs.delivered); - - if (bbr->rst->rs.prior_delivered >= bbr->loss_round_delivered) { - bbr->loss_round_delivered = bbr->rst->delivered; - bbr->loss_round_start = 1; - } -} - -static void bbr_advance_latest_delivery_signals(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - if (bbr->loss_round_start) { - bbr->bw_latest = cstat->delivery_rate_sec; - bbr->inflight_latest = bbr->rst->rs.delivered; - } -} - -static void bbr_update_congestion_signals(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - bbr_update_max_bw(bbr, cstat, ack); - - if (ack->bytes_lost) { - bbr->bytes_lost_in_round += ack->bytes_lost; - ++bbr->loss_events_in_round; - - if (!bbr->loss_in_round) { - bbr->loss_in_round = 1; - bbr->loss_round_delivered = bbr->rst->delivered; - } - } - - if (!bbr->loss_round_start) { - return; - } - - bbr_adapt_lower_bounds_from_congestion(bbr, cstat); - - bbr->loss_in_round = 0; -} - -static void bbr_adapt_lower_bounds_from_congestion(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - if (!bbr->filled_pipe || bbr_is_in_probe_bw_state(bbr)) { - return; - } - - if (bbr->loss_in_round) { - bbr_init_lower_bounds(bbr, cstat); - bbr_loss_lower_bounds(bbr); - } -} - -static void bbr_init_lower_bounds(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - if (bbr->bw_lo == UINT64_MAX) { - bbr->bw_lo = bbr->max_bw; - } - - if (bbr->inflight_lo == UINT64_MAX) { - bbr->inflight_lo = cstat->cwnd; - } -} - -static void bbr_loss_lower_bounds(ngtcp2_bbr2_cc *bbr) { - bbr->bw_lo = ngtcp2_max(bbr->bw_latest, bbr->bw_lo * NGTCP2_BBR_BETA_NUMER / - NGTCP2_BBR_BETA_DENOM); - bbr->inflight_lo = ngtcp2_max(bbr->inflight_latest, - bbr->inflight_lo * NGTCP2_BBR_BETA_NUMER / - NGTCP2_BBR_BETA_DENOM); -} - -static void bbr_bound_bw_for_model(ngtcp2_bbr2_cc *bbr) { - bbr->bw = ngtcp2_min(bbr->max_bw, bbr->bw_lo); - bbr->bw = ngtcp2_min(bbr->bw, bbr->bw_hi); -} - -static void bbr_update_max_bw(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - bbr_update_round(bbr, ack); - bbr_handle_recovery(bbr, cstat, ack); - - if (cstat->delivery_rate_sec >= bbr->max_bw || !bbr->rst->rs.is_app_limited) { - ngtcp2_window_filter_update(&bbr->max_bw_filter, cstat->delivery_rate_sec, - bbr->cycle_count); - - bbr->max_bw = ngtcp2_window_filter_get_best(&bbr->max_bw_filter); - } -} - -static void bbr_update_round(ngtcp2_bbr2_cc *bbr, const ngtcp2_cc_ack *ack) { - if (ack->pkt_delivered >= bbr->next_round_delivered) { - bbr_start_round(bbr); - - ++bbr->round_count; - ++bbr->rounds_since_bw_probe; - bbr->round_start = 1; - - bbr->bytes_lost_in_round = 0; - bbr->loss_events_in_round = 0; - - bbr->rst->is_cwnd_limited = 0; - - return; - } - - bbr->round_start = 0; -} - -static void bbr_start_round(ngtcp2_bbr2_cc *bbr) { - bbr->next_round_delivered = bbr->rst->delivered; -} - -static int bbr_is_in_probe_bw_state(ngtcp2_bbr2_cc *bbr) { - switch (bbr->state) { - case NGTCP2_BBR2_STATE_PROBE_BW_DOWN: - case NGTCP2_BBR2_STATE_PROBE_BW_CRUISE: - case NGTCP2_BBR2_STATE_PROBE_BW_REFILL: - case NGTCP2_BBR2_STATE_PROBE_BW_UP: - return 1; - default: - return 0; - } -} - -static void bbr_update_ack_aggregation(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, - ngtcp2_tstamp ts) { - ngtcp2_duration interval = ts - bbr->extra_acked_interval_start; - uint64_t expected_delivered = bbr->bw * interval / NGTCP2_SECONDS; - uint64_t extra; - - if (bbr->extra_acked_delivered <= expected_delivered) { - bbr->extra_acked_delivered = 0; - bbr->extra_acked_interval_start = ts; - expected_delivered = 0; - } - - bbr->extra_acked_delivered += ack->bytes_delivered; - extra = bbr->extra_acked_delivered - expected_delivered; - extra = ngtcp2_min(extra, cstat->cwnd); - - ngtcp2_window_filter_update(&bbr->extra_acked_filter, extra, - bbr->round_count); - - bbr->extra_acked = ngtcp2_window_filter_get_best(&bbr->extra_acked_filter); -} - -static void bbr_enter_drain(ngtcp2_bbr2_cc *bbr) { - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, "bbr2 enter Drain"); - - bbr->state = NGTCP2_BBR2_STATE_DRAIN; - bbr->pacing_gain = 1. / NGTCP2_BBR_STARTUP_CWND_GAIN; - bbr->cwnd_gain = NGTCP2_BBR_STARTUP_CWND_GAIN; -} - -static void bbr_check_drain(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - if (bbr->state == NGTCP2_BBR2_STATE_DRAIN && - cstat->bytes_in_flight <= bbr_inflight(bbr, cstat, bbr->bw, 1.0)) { - bbr_enter_probe_bw(bbr, ts); - } -} - -static void bbr_enter_probe_bw(ngtcp2_bbr2_cc *bbr, ngtcp2_tstamp ts) { - bbr_start_probe_bw_down(bbr, ts); -} - -static void bbr_start_probe_bw_down(ngtcp2_bbr2_cc *bbr, ngtcp2_tstamp ts) { - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr2 start ProbeBW_DOWN"); - - bbr_reset_congestion_signals(bbr); - - bbr->probe_up_cnt = UINT64_MAX; - - bbr_pick_probe_wait(bbr); - - bbr->cycle_stamp = ts; - bbr->ack_phase = NGTCP2_BBR2_ACK_PHASE_ACKS_PROBE_STOPPING; - - bbr_start_round(bbr); - - bbr->state = NGTCP2_BBR2_STATE_PROBE_BW_DOWN; - bbr->pacing_gain = 0.9; - bbr->cwnd_gain = 2; -} - -static void bbr_start_probe_bw_cruise(ngtcp2_bbr2_cc *bbr) { - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr2 start ProbeBW_CRUISE"); - - bbr->state = NGTCP2_BBR2_STATE_PROBE_BW_CRUISE; - bbr->pacing_gain = 1.0; - bbr->cwnd_gain = 2; -} - -static void bbr_start_probe_bw_refill(ngtcp2_bbr2_cc *bbr) { - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr2 start ProbeBW_REFILL"); - - bbr_reset_lower_bounds(bbr); - - bbr->bw_probe_up_rounds = 0; - bbr->bw_probe_up_acks = 0; - bbr->ack_phase = NGTCP2_BBR2_ACK_PHASE_ACKS_REFILLING; - - bbr_start_round(bbr); - - bbr->state = NGTCP2_BBR2_STATE_PROBE_BW_REFILL; - bbr->pacing_gain = 1.0; - bbr->cwnd_gain = 2; -} - -static void bbr_start_probe_bw_up(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, "bbr2 start ProbeBW_UP"); - - bbr->ack_phase = NGTCP2_BBR2_ACK_PHASE_ACKS_PROBE_STARTING; - - bbr_start_round(bbr); - - bbr->cycle_stamp = ts; - bbr->state = NGTCP2_BBR2_STATE_PROBE_BW_UP; - bbr->pacing_gain = 1.25; - bbr->cwnd_gain = 2; - - bbr_raise_inflight_hi_slope(bbr, cstat); -} - -static void bbr_update_probe_bw_cycle_phase(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, - ngtcp2_tstamp ts) { - if (!bbr->filled_pipe) { - return; - } - - bbr_adapt_upper_bounds(bbr, cstat, ack, ts); - - if (!bbr_is_in_probe_bw_state(bbr)) { - return; - } - - switch (bbr->state) { - case NGTCP2_BBR2_STATE_PROBE_BW_DOWN: - if (bbr_check_time_to_probe_bw(bbr, cstat, ts)) { - return; - } - - if (bbr_check_time_to_cruise(bbr, cstat, ts)) { - bbr_start_probe_bw_cruise(bbr); - } - - break; - case NGTCP2_BBR2_STATE_PROBE_BW_CRUISE: - if (bbr_check_time_to_probe_bw(bbr, cstat, ts)) { - return; - } - - break; - case NGTCP2_BBR2_STATE_PROBE_BW_REFILL: - if (bbr->round_start) { - bbr->bw_probe_samples = 1; - bbr_start_probe_bw_up(bbr, cstat, ts); - } - - break; - case NGTCP2_BBR2_STATE_PROBE_BW_UP: - if (bbr_has_elapsed_in_phase(bbr, bbr->min_rtt, ts) && - cstat->bytes_in_flight > bbr_inflight(bbr, cstat, bbr->max_bw, 1.25)) { - bbr_start_probe_bw_down(bbr, ts); - } - - break; - default: - break; - } -} - -static int bbr_check_time_to_cruise(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - (void)ts; - - if (cstat->bytes_in_flight > bbr_inflight_with_headroom(bbr, cstat)) { - return 0; - } - - if (cstat->bytes_in_flight <= bbr_inflight(bbr, cstat, bbr->max_bw, 1.0)) { - return 1; - } - - return 0; -} - -static int bbr_has_elapsed_in_phase(ngtcp2_bbr2_cc *bbr, - ngtcp2_duration interval, - ngtcp2_tstamp ts) { - return ts > bbr->cycle_stamp + interval; -} - -static uint64_t bbr_inflight_with_headroom(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - uint64_t headroom; - uint64_t mpcwnd; - if (bbr->inflight_hi == UINT64_MAX) { - return UINT64_MAX; - } - - headroom = ngtcp2_max(cstat->max_udp_payload_size, - bbr->inflight_hi * NGTCP2_BBR_HEADROOM_NUMER / - NGTCP2_BBR_HEADROOM_DENOM); - mpcwnd = min_pipe_cwnd(cstat->max_udp_payload_size); - - if (bbr->inflight_hi > headroom) { - return ngtcp2_max(bbr->inflight_hi - headroom, mpcwnd); - } - - return mpcwnd; -} - -static void bbr_raise_inflight_hi_slope(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - uint64_t growth_this_round = cstat->max_udp_payload_size - << bbr->bw_probe_up_rounds; - - bbr->bw_probe_up_rounds = ngtcp2_min(bbr->bw_probe_up_rounds + 1, 30); - bbr->probe_up_cnt = ngtcp2_max(cstat->cwnd / growth_this_round, 1) * - cstat->max_udp_payload_size; -} - -static void bbr_probe_inflight_hi_upward(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - uint64_t delta; - - if (!bbr->rst->is_cwnd_limited || cstat->cwnd < bbr->inflight_hi) { - return; - } - - bbr->bw_probe_up_acks += ack->bytes_delivered; - - if (bbr->bw_probe_up_acks >= bbr->probe_up_cnt) { - delta = bbr->bw_probe_up_acks / bbr->probe_up_cnt; - bbr->bw_probe_up_acks -= delta * bbr->probe_up_cnt; - bbr->inflight_hi += delta * cstat->max_udp_payload_size; - } - - if (bbr->round_start) { - bbr_raise_inflight_hi_slope(bbr, cstat); - } -} - -static void bbr_adapt_upper_bounds(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - if (bbr->ack_phase == NGTCP2_BBR2_ACK_PHASE_ACKS_PROBE_STARTING && - bbr->round_start) { - bbr->ack_phase = NGTCP2_BBR2_ACK_PHASE_ACKS_PROBE_FEEDBACK; - } - - if (bbr->ack_phase == NGTCP2_BBR2_ACK_PHASE_ACKS_PROBE_STOPPING && - bbr->round_start) { - if (bbr_is_in_probe_bw_state(bbr) && !bbr->rst->rs.is_app_limited) { - bbr_advance_max_bw_filter(bbr); - } - } - - if (!bbr_check_inflight_too_high(bbr, cstat, ts)) { - /* bbr->bw_hi never be updated */ - if (bbr->inflight_hi == UINT64_MAX /* || bbr->bw_hi == UINT64_MAX */) { - return; - } - - if (bbr->rst->rs.tx_in_flight > bbr->inflight_hi) { - bbr->inflight_hi = bbr->rst->rs.tx_in_flight; - } - - if (cstat->delivery_rate_sec > bbr->bw_hi) { - bbr->bw_hi = cstat->delivery_rate_sec; - } - - if (bbr->state == NGTCP2_BBR2_STATE_PROBE_BW_UP) { - bbr_probe_inflight_hi_upward(bbr, cstat, ack); - } - } -} - -static int bbr_check_time_to_probe_bw(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - if (bbr_has_elapsed_in_phase(bbr, bbr->bw_probe_wait, ts) || - bbr_is_reno_coexistence_probe_time(bbr, cstat)) { - bbr_start_probe_bw_refill(bbr); - - return 1; - } - - return 0; -} - -static void bbr_pick_probe_wait(ngtcp2_bbr2_cc *bbr) { - uint8_t rand; - - bbr->rand(&rand, 1, &bbr->rand_ctx); - - bbr->rounds_since_bw_probe = (uint64_t)(rand * 2 / 256); - - bbr->rand(&rand, 1, &bbr->rand_ctx); - - bbr->bw_probe_wait = 2 * NGTCP2_SECONDS + - (ngtcp2_tstamp)((double)rand / 255. * NGTCP2_SECONDS); -} - -static int bbr_is_reno_coexistence_probe_time(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - uint64_t reno_rounds = - bbr_target_inflight(bbr, cstat) / cstat->max_udp_payload_size; - - return bbr->rounds_since_bw_probe >= ngtcp2_min(reno_rounds, 63); -} - -static uint64_t bbr_target_inflight(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - uint64_t bdp = bbr_inflight(bbr, cstat, bbr->bw, 1.0); - - return ngtcp2_min(bdp, cstat->cwnd); -} - -static int bbr_check_inflight_too_high(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - if (is_inflight_too_high(&bbr->rst->rs)) { - if (bbr->bw_probe_samples) { - bbr_handle_inflight_too_high(bbr, cstat, &bbr->rst->rs, ts); - } - - return 1; - } - - return 0; -} - -static int is_inflight_too_high(const ngtcp2_rs *rs) { - return rs->lost * NGTCP2_BBR_LOSS_THRESH_DENOM > - rs->tx_in_flight * NGTCP2_BBR_LOSS_THRESH_NUMER; -} - -static void bbr_handle_inflight_too_high(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_rs *rs, - ngtcp2_tstamp ts) { - bbr->bw_probe_samples = 0; - - if (!rs->is_app_limited) { - bbr->prior_inflight_hi = bbr->inflight_hi; - - bbr->inflight_hi = ngtcp2_max( - rs->tx_in_flight, bbr_target_inflight(bbr, cstat) * - NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM); - } - - if (bbr->state == NGTCP2_BBR2_STATE_PROBE_BW_UP) { - bbr_start_probe_bw_down(bbr, ts); - } -} - -static void bbr_handle_lost_packet(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { - ngtcp2_rs rs = {0}; - - if (!bbr->bw_probe_samples) { - return; - } - - rs.tx_in_flight = pkt->tx_in_flight; - rs.lost = bbr->rst->lost - pkt->lost; - rs.is_app_limited = pkt->is_app_limited; - - if (is_inflight_too_high(&rs)) { - rs.tx_in_flight = bbr_inflight_hi_from_lost_packet(bbr, &rs, pkt); - - bbr_handle_inflight_too_high(bbr, cstat, &rs, ts); - } -} - -static uint64_t bbr_inflight_hi_from_lost_packet(ngtcp2_bbr2_cc *bbr, - const ngtcp2_rs *rs, - const ngtcp2_cc_pkt *pkt) { - uint64_t inflight_prev, lost_prefix; - (void)bbr; - - assert(rs->tx_in_flight >= pkt->pktlen); - - inflight_prev = rs->tx_in_flight - pkt->pktlen; - - assert(rs->lost >= pkt->pktlen); - - /* bbr->rst->lost is not incremented for pkt yet */ - - if (inflight_prev * NGTCP2_BBR_LOSS_THRESH_NUMER < - rs->lost * NGTCP2_BBR_LOSS_THRESH_DENOM) { - return inflight_prev; - } - - lost_prefix = (inflight_prev * NGTCP2_BBR_LOSS_THRESH_NUMER - - rs->lost * NGTCP2_BBR_LOSS_THRESH_DENOM) / - (NGTCP2_BBR_LOSS_THRESH_DENOM - NGTCP2_BBR_LOSS_THRESH_NUMER); - - return inflight_prev + lost_prefix; -} - -static void bbr_update_min_rtt(ngtcp2_bbr2_cc *bbr, const ngtcp2_cc_ack *ack, - ngtcp2_tstamp ts) { - int min_rtt_expired; - - bbr->probe_rtt_expired = - ts > bbr->probe_rtt_min_stamp + NGTCP2_BBR_PROBE_RTT_INTERVAL; - - if (ack->rtt != UINT64_MAX && - (ack->rtt < bbr->probe_rtt_min_delay || bbr->probe_rtt_expired)) { - bbr->probe_rtt_min_delay = ack->rtt; - bbr->probe_rtt_min_stamp = ts; - } - - min_rtt_expired = ts > bbr->min_rtt_stamp + NGTCP2_BBR_MIN_RTT_FILTERLEN; - - if (bbr->probe_rtt_min_delay < bbr->min_rtt || min_rtt_expired) { - bbr->min_rtt = bbr->probe_rtt_min_delay; - bbr->min_rtt_stamp = bbr->probe_rtt_min_stamp; - - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr2 update min_rtt=%" PRIu64, bbr->min_rtt); - } -} - -static void bbr_check_probe_rtt(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - if (bbr->state != NGTCP2_BBR2_STATE_PROBE_RTT && bbr->probe_rtt_expired && - !bbr->idle_restart) { - bbr_enter_probe_rtt(bbr); - bbr_save_cwnd(bbr, cstat); - - bbr->probe_rtt_done_stamp = UINT64_MAX; - bbr->ack_phase = NGTCP2_BBR2_ACK_PHASE_ACKS_PROBE_STOPPING; - - bbr_start_round(bbr); - } - - if (bbr->state == NGTCP2_BBR2_STATE_PROBE_RTT) { - bbr_handle_probe_rtt(bbr, cstat, ts); - } - - if (bbr->rst->rs.delivered) { - bbr->idle_restart = 0; - } -} - -static void bbr_enter_probe_rtt(ngtcp2_bbr2_cc *bbr) { - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, "bbr2 enter ProbeRTT"); - - bbr->state = NGTCP2_BBR2_STATE_PROBE_RTT; - bbr->pacing_gain = 1; - bbr->cwnd_gain = NGTCP2_BBR_PROBE_RTT_CWND_GAIN; -} - -static void bbr_handle_probe_rtt(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - bbr_mark_connection_app_limited(bbr, cstat); - - if (bbr->probe_rtt_done_stamp == UINT64_MAX && - cstat->bytes_in_flight <= bbr_probe_rtt_cwnd(bbr, cstat)) { - bbr->probe_rtt_done_stamp = ts + NGTCP2_BBR_PROBE_RTT_DURATION; - bbr->probe_rtt_round_done = 0; - - bbr_start_round(bbr); - - return; - } - - if (bbr->probe_rtt_done_stamp != UINT64_MAX) { - if (bbr->round_start) { - bbr->probe_rtt_round_done = 1; - } - - if (bbr->probe_rtt_round_done) { - bbr_check_probe_rtt_done(bbr, cstat, ts); - } - } -} - -static void bbr_check_probe_rtt_done(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - if (bbr->probe_rtt_done_stamp != UINT64_MAX && - ts > bbr->probe_rtt_done_stamp) { - bbr->probe_rtt_min_stamp = ts; - bbr_restore_cwnd(bbr, cstat); - bbr_exit_probe_rtt(bbr, ts); - } -} - -static void bbr_mark_connection_app_limited(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - uint64_t app_limited = bbr->rst->delivered + cstat->bytes_in_flight; - - if (app_limited) { - bbr->rst->app_limited = app_limited; - } else { - bbr->rst->app_limited = cstat->max_udp_payload_size; - } -} - -static void bbr_exit_probe_rtt(ngtcp2_bbr2_cc *bbr, ngtcp2_tstamp ts) { - bbr_reset_lower_bounds(bbr); - - if (bbr->filled_pipe) { - bbr_start_probe_bw_down(bbr, ts); - bbr_start_probe_bw_cruise(bbr); - } else { - bbr_enter_startup(bbr); - } -} - -static void bbr_handle_restart_from_idle(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - if (cstat->bytes_in_flight == 0 && bbr->rst->app_limited) { - ngtcp2_log_info(bbr->ccb.log, NGTCP2_LOG_EVENT_RCV, - "bbr2 restart from idle"); - - bbr->idle_restart = 1; - bbr->extra_acked_interval_start = ts; - - if (bbr_is_in_probe_bw_state(bbr)) { - bbr_set_pacing_rate_with_gain(bbr, cstat, 1); - } else if (bbr->state == NGTCP2_BBR2_STATE_PROBE_RTT) { - bbr_check_probe_rtt_done(bbr, cstat, ts); - } - } -} - -static uint64_t bbr_bdp_multiple(ngtcp2_bbr2_cc *bbr, uint64_t bw, - double gain) { - uint64_t bdp; - - if (bbr->min_rtt == UINT64_MAX) { - return bbr->initial_cwnd; - } - - bdp = bw * bbr->min_rtt / NGTCP2_SECONDS; - - return (uint64_t)(gain * (double)bdp); -} - -static uint64_t min_pipe_cwnd(size_t max_udp_payload_size) { - return max_udp_payload_size * 4; -} - -static uint64_t bbr_quantization_budget(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - uint64_t inflight) { - bbr_update_offload_budget(bbr, cstat); - - inflight = ngtcp2_max(inflight, bbr->offload_budget); - inflight = ngtcp2_max(inflight, min_pipe_cwnd(cstat->max_udp_payload_size)); - - if (bbr->state == NGTCP2_BBR2_STATE_PROBE_BW_UP) { - inflight += 2 * cstat->max_udp_payload_size; - } - - return inflight; -} - -static uint64_t bbr_inflight(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - uint64_t bw, double gain) { - uint64_t inflight = bbr_bdp_multiple(bbr, bw, gain); - - return bbr_quantization_budget(bbr, cstat, inflight); -} - -static void bbr_update_max_inflight(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - uint64_t inflight; - - /* Not documented */ - /* bbr_update_aggregation_budget(bbr); */ - - inflight = bbr_bdp_multiple(bbr, bbr->bw, bbr->cwnd_gain) + bbr->extra_acked; - bbr->max_inflight = bbr_quantization_budget(bbr, cstat, inflight); -} - -static void bbr_update_offload_budget(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - bbr->offload_budget = 3 * cstat->send_quantum; -} - -static void bbr_advance_max_bw_filter(ngtcp2_bbr2_cc *bbr) { - ++bbr->cycle_count; -} - -static void bbr_modulate_cwnd_for_recovery(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - if (ack->bytes_lost > 0) { - if (cstat->cwnd > ack->bytes_lost) { - cstat->cwnd -= ack->bytes_lost; - cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_udp_payload_size); - } else { - cstat->cwnd = cstat->max_udp_payload_size; - } - } - - if (bbr->packet_conservation) { - cstat->cwnd = - ngtcp2_max(cstat->cwnd, cstat->bytes_in_flight + ack->bytes_delivered); - } -} - -static void bbr_save_cwnd(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat) { - if (!bbr->in_loss_recovery && bbr->state != NGTCP2_BBR2_STATE_PROBE_RTT) { - bbr->prior_cwnd = cstat->cwnd; - return; - } - - bbr->prior_cwnd = ngtcp2_max(bbr->prior_cwnd, cstat->cwnd); -} - -static void bbr_restore_cwnd(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat) { - cstat->cwnd = ngtcp2_max(cstat->cwnd, bbr->prior_cwnd); -} - -static uint64_t bbr_probe_rtt_cwnd(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - uint64_t probe_rtt_cwnd = - bbr_bdp_multiple(bbr, bbr->bw, NGTCP2_BBR_PROBE_RTT_CWND_GAIN); - uint64_t mpcwnd = min_pipe_cwnd(cstat->max_udp_payload_size); - - return ngtcp2_max(probe_rtt_cwnd, mpcwnd); -} - -static void bbr_bound_cwnd_for_probe_rtt(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - uint64_t probe_rtt_cwnd; - - if (bbr->state == NGTCP2_BBR2_STATE_PROBE_RTT) { - probe_rtt_cwnd = bbr_probe_rtt_cwnd(bbr, cstat); - - cstat->cwnd = ngtcp2_min(cstat->cwnd, probe_rtt_cwnd); - } -} - -static void bbr_set_cwnd(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - uint64_t mpcwnd; - - bbr_update_max_inflight(bbr, cstat); - bbr_modulate_cwnd_for_recovery(bbr, cstat, ack); - - if (!bbr->packet_conservation) { - if (bbr->filled_pipe) { - cstat->cwnd += ack->bytes_delivered; - cstat->cwnd = ngtcp2_min(cstat->cwnd, bbr->max_inflight); - } else if (cstat->cwnd < bbr->max_inflight || - bbr->rst->delivered < bbr->initial_cwnd) { - cstat->cwnd += ack->bytes_delivered; - } - - mpcwnd = min_pipe_cwnd(cstat->max_udp_payload_size); - cstat->cwnd = ngtcp2_max(cstat->cwnd, mpcwnd); - } - - bbr_bound_cwnd_for_probe_rtt(bbr, cstat); - bbr_bound_cwnd_for_model(bbr, cstat); -} - -static void bbr_bound_cwnd_for_model(ngtcp2_bbr2_cc *bbr, - ngtcp2_conn_stat *cstat) { - uint64_t cap = UINT64_MAX; - uint64_t mpcwnd = min_pipe_cwnd(cstat->max_udp_payload_size); - - if (bbr_is_in_probe_bw_state(bbr) && - bbr->state != NGTCP2_BBR2_STATE_PROBE_BW_CRUISE) { - cap = bbr->inflight_hi; - } else if (bbr->state == NGTCP2_BBR2_STATE_PROBE_RTT || - bbr->state == NGTCP2_BBR2_STATE_PROBE_BW_CRUISE) { - cap = bbr_inflight_with_headroom(bbr, cstat); - } - - cap = ngtcp2_min(cap, bbr->inflight_lo); - cap = ngtcp2_max(cap, mpcwnd); - - cstat->cwnd = ngtcp2_min(cstat->cwnd, cap); -} - -static void bbr_set_send_quantum(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat) { - size_t send_quantum = - (size_t)(cstat->pacing_rate * (double)(bbr->min_rtt == UINT64_MAX - ? NGTCP2_MILLISECONDS - : bbr->min_rtt)); - (void)bbr; - - cstat->send_quantum = ngtcp2_min(send_quantum, 64 * 1024); - cstat->send_quantum = - ngtcp2_max(cstat->send_quantum, cstat->max_udp_payload_size * 10); -} - -static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, - ngtcp2_tstamp sent_time) { - return cstat->congestion_recovery_start_ts != UINT64_MAX && - sent_time <= cstat->congestion_recovery_start_ts; -} - -static void bbr_handle_recovery(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - if (bbr->in_loss_recovery) { - if (ack->pkt_delivered >= bbr->congestion_recovery_next_round_delivered) { - bbr->packet_conservation = 0; - } - - if (!in_congestion_recovery(cstat, ack->largest_acked_sent_ts)) { - bbr->in_loss_recovery = 0; - bbr->packet_conservation = 0; - bbr_restore_cwnd(bbr, cstat); - } - - return; - } - - if (bbr->congestion_recovery_start_ts != UINT64_MAX) { - bbr->in_loss_recovery = 1; - bbr_save_cwnd(bbr, cstat); - cstat->cwnd = cstat->bytes_in_flight + - ngtcp2_max(ack->bytes_delivered, cstat->max_udp_payload_size); - - cstat->congestion_recovery_start_ts = bbr->congestion_recovery_start_ts; - bbr->congestion_recovery_start_ts = UINT64_MAX; - bbr->packet_conservation = 1; - bbr->congestion_recovery_next_round_delivered = bbr->rst->delivered; - bbr->prior_inflight_lo = bbr->inflight_lo; - bbr->prior_bw_lo = bbr->bw_lo; - } -} - -static void bbr2_cc_init(ngtcp2_bbr2_cc *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_rst *rst, ngtcp2_tstamp initial_ts, - ngtcp2_rand rand, const ngtcp2_rand_ctx *rand_ctx, - ngtcp2_log *log) { - bbr->ccb.log = log; - bbr->rst = rst; - bbr->rand = rand; - bbr->rand_ctx = *rand_ctx; - bbr->initial_cwnd = cstat->cwnd; - - bbr_on_init(bbr, cstat, initial_ts); -} - -static void bbr2_cc_free(ngtcp2_bbr2_cc *bbr) { (void)bbr; } - -static void bbr2_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { - (void)ccx; - (void)cstat; - (void)pkt; - (void)ts; -} - -static void bbr2_cc_on_pkt_lost(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { - ngtcp2_bbr2_cc *bbr = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr2_cc, ccb); - - bbr_update_on_loss(bbr, cstat, pkt, ts); -} - -static void bbr2_cc_congestion_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp sent_ts, ngtcp2_tstamp ts) { - ngtcp2_bbr2_cc *bbr = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr2_cc, ccb); - - if (!bbr->filled_pipe || bbr->in_loss_recovery || - bbr->congestion_recovery_start_ts != UINT64_MAX || - in_congestion_recovery(cstat, sent_ts)) { - return; - } - - bbr->congestion_recovery_start_ts = ts; -} - -static void bbr2_cc_on_spurious_congestion(ngtcp2_cc *ccx, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - ngtcp2_bbr2_cc *bbr = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr2_cc, ccb); - (void)ts; - - bbr->congestion_recovery_start_ts = UINT64_MAX; - cstat->congestion_recovery_start_ts = UINT64_MAX; - - if (bbr->in_loss_recovery) { - bbr->in_loss_recovery = 0; - bbr->packet_conservation = 0; - bbr_restore_cwnd(bbr, cstat); - bbr->full_bw_count = 0; - bbr->loss_in_round = 0; - bbr->inflight_lo = ngtcp2_max(bbr->inflight_lo, bbr->prior_inflight_lo); - bbr->inflight_hi = ngtcp2_max(bbr->inflight_hi, bbr->prior_inflight_hi); - bbr->bw_lo = ngtcp2_max(bbr->bw_lo, bbr->prior_bw_lo); - } -} - -static void bbr2_cc_on_persistent_congestion(ngtcp2_cc *ccx, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - ngtcp2_bbr2_cc *bbr = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr2_cc, ccb); - (void)ts; - - cstat->congestion_recovery_start_ts = UINT64_MAX; - bbr->congestion_recovery_start_ts = UINT64_MAX; - bbr->in_loss_recovery = 0; - bbr->packet_conservation = 0; - - bbr_save_cwnd(bbr, cstat); - cstat->cwnd = cstat->bytes_in_flight + cstat->max_udp_payload_size; - cstat->cwnd = - ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_udp_payload_size)); -} - -static void bbr2_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - ngtcp2_bbr2_cc *bbr = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr2_cc, ccb); - - bbr_update_on_ack(bbr, cstat, ack, ts); -} - -static void bbr2_cc_on_pkt_sent(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt) { - ngtcp2_bbr2_cc *bbr = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr2_cc, ccb); - - bbr_on_transmit(bbr, cstat, pkt->sent_ts); -} - -static void bbr2_cc_new_rtt_sample(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - (void)ccx; - (void)cstat; - (void)ts; -} - -static void bbr2_cc_reset(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - ngtcp2_bbr2_cc *bbr = ngtcp2_struct_of(ccx->ccb, ngtcp2_bbr2_cc, ccb); - - bbr_on_init(bbr, cstat, ts); -} - -static void bbr2_cc_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, - ngtcp2_cc_event_type event, ngtcp2_tstamp ts) { - (void)ccx; - (void)cstat; - (void)event; - (void)ts; -} - -int ngtcp2_cc_bbr2_cc_init(ngtcp2_cc *cc, ngtcp2_log *log, - ngtcp2_conn_stat *cstat, ngtcp2_rst *rst, - ngtcp2_tstamp initial_ts, ngtcp2_rand rand, - const ngtcp2_rand_ctx *rand_ctx, - const ngtcp2_mem *mem) { - ngtcp2_bbr2_cc *bbr; - - bbr = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_bbr2_cc)); - if (bbr == NULL) { - return NGTCP2_ERR_NOMEM; - } - - bbr2_cc_init(bbr, cstat, rst, initial_ts, rand, rand_ctx, log); - - cc->ccb = &bbr->ccb; - cc->on_pkt_acked = bbr2_cc_on_pkt_acked; - cc->on_pkt_lost = bbr2_cc_on_pkt_lost; - cc->congestion_event = bbr2_cc_congestion_event; - cc->on_spurious_congestion = bbr2_cc_on_spurious_congestion; - cc->on_persistent_congestion = bbr2_cc_on_persistent_congestion; - cc->on_ack_recv = bbr2_cc_on_ack_recv; - cc->on_pkt_sent = bbr2_cc_on_pkt_sent; - cc->new_rtt_sample = bbr2_cc_new_rtt_sample; - cc->reset = bbr2_cc_reset; - cc->event = bbr2_cc_event; - - return 0; -} - -void ngtcp2_cc_bbr2_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem) { - ngtcp2_bbr2_cc *bbr = ngtcp2_struct_of(cc->ccb, ngtcp2_bbr2_cc, ccb); - - bbr2_cc_free(bbr); - ngtcp2_mem_free(mem, bbr); -} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr2.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr2.h deleted file mode 100644 index 50dc05a5f26121..00000000000000 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr2.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * ngtcp2 - * - * Copyright (c) 2021 ngtcp2 contributors - * - * 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. - */ -#ifndef NGTCP2_BBR2_H -#define NGTCP2_BBR2_H - -#ifdef HAVE_CONFIG_H -# include -#endif /* HAVE_CONFIG_H */ - -#include - -#include "ngtcp2_cc.h" -#include "ngtcp2_window_filter.h" - -typedef struct ngtcp2_rst ngtcp2_rst; - -typedef enum ngtcp2_bbr2_state { - NGTCP2_BBR2_STATE_STARTUP, - NGTCP2_BBR2_STATE_DRAIN, - NGTCP2_BBR2_STATE_PROBE_BW_DOWN, - NGTCP2_BBR2_STATE_PROBE_BW_CRUISE, - NGTCP2_BBR2_STATE_PROBE_BW_REFILL, - NGTCP2_BBR2_STATE_PROBE_BW_UP, - NGTCP2_BBR2_STATE_PROBE_RTT, -} ngtcp2_bbr2_state; - -typedef enum ngtcp2_bbr2_ack_phase { - NGTCP2_BBR2_ACK_PHASE_ACKS_PROBE_STARTING, - NGTCP2_BBR2_ACK_PHASE_ACKS_PROBE_STOPPING, - NGTCP2_BBR2_ACK_PHASE_ACKS_PROBE_FEEDBACK, - NGTCP2_BBR2_ACK_PHASE_ACKS_REFILLING, -} ngtcp2_bbr2_ack_phase; - -/* - * ngtcp2_bbr2_cc is BBR v2 congestion controller, described in - * https://datatracker.ietf.org/doc/html/draft-cardwell-iccrg-bbr-congestion-control-01 - */ -typedef struct ngtcp2_bbr2_cc { - ngtcp2_cc_base ccb; - - uint64_t initial_cwnd; - ngtcp2_rst *rst; - ngtcp2_rand rand; - ngtcp2_rand_ctx rand_ctx; - - /* max_bw_filter for tracking the maximum recent delivery rate - samples for estimating max_bw. */ - ngtcp2_window_filter max_bw_filter; - - ngtcp2_window_filter extra_acked_filter; - - ngtcp2_duration min_rtt; - ngtcp2_tstamp min_rtt_stamp; - ngtcp2_tstamp probe_rtt_done_stamp; - int probe_rtt_round_done; - uint64_t prior_cwnd; - int idle_restart; - ngtcp2_tstamp extra_acked_interval_start; - uint64_t extra_acked_delivered; - - /* Congestion signals */ - int loss_in_round; - uint64_t bw_latest; - uint64_t inflight_latest; - - /* Lower bounds */ - uint64_t bw_lo; - uint64_t inflight_lo; - - /* Round counting */ - uint64_t next_round_delivered; - int round_start; - uint64_t round_count; - - /* Full pipe */ - int filled_pipe; - uint64_t full_bw; - size_t full_bw_count; - - /* Pacing rate */ - double pacing_gain; - - ngtcp2_bbr2_state state; - double cwnd_gain; - - int loss_round_start; - uint64_t loss_round_delivered; - uint64_t rounds_since_bw_probe; - uint64_t max_bw; - uint64_t bw; - uint64_t cycle_count; - uint64_t extra_acked; - uint64_t bytes_lost_in_round; - size_t loss_events_in_round; - uint64_t offload_budget; - uint64_t probe_up_cnt; - ngtcp2_tstamp cycle_stamp; - ngtcp2_bbr2_ack_phase ack_phase; - ngtcp2_duration bw_probe_wait; - int bw_probe_samples; - size_t bw_probe_up_rounds; - uint64_t bw_probe_up_acks; - uint64_t inflight_hi; - uint64_t bw_hi; - int probe_rtt_expired; - ngtcp2_duration probe_rtt_min_delay; - ngtcp2_tstamp probe_rtt_min_stamp; - int in_loss_recovery; - int packet_conservation; - uint64_t max_inflight; - ngtcp2_tstamp congestion_recovery_start_ts; - uint64_t congestion_recovery_next_round_delivered; - - uint64_t prior_inflight_lo; - uint64_t prior_inflight_hi; - uint64_t prior_bw_lo; -} ngtcp2_bbr2_cc; - -int ngtcp2_cc_bbr2_cc_init(ngtcp2_cc *cc, ngtcp2_log *log, - ngtcp2_conn_stat *cstat, ngtcp2_rst *rst, - ngtcp2_tstamp initial_ts, ngtcp2_rand rand, - const ngtcp2_rand_ctx *rand_ctx, - const ngtcp2_mem *mem); - -void ngtcp2_cc_bbr2_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem); - -#endif /* NGTCP2_BBR2_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h index 107d413382da20..85b5f4ddf0464a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h @@ -36,7 +36,7 @@ typedef struct ngtcp2_buf { uint8_t *begin; /* end points to the one beyond of the last byte of the buffer */ uint8_t *end; - /* pos pointers to the start of data. Typically, this points to the + /* pos points to the start of data. Typically, this points to the point that next data should be read. Initially, it points to |begin|. */ uint8_t *pos; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c index 1ee7d96b04776e..9ad37fbdb6395a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c @@ -25,15 +25,18 @@ #include "ngtcp2_cc.h" #include - -#if defined(_MSC_VER) -# include -#endif +#include #include "ngtcp2_log.h" #include "ngtcp2_macro.h" #include "ngtcp2_mem.h" #include "ngtcp2_rcvry.h" +#include "ngtcp2_conn_stat.h" +#include "ngtcp2_unreachable.h" + +/* NGTCP2_CC_DELIVERY_RATE_SEC_FILTERLEN is the window length of + delivery rate filter driven by ACK clocking. */ +#define NGTCP2_CC_DELIVERY_RATE_SEC_FILTERLEN 10 uint64_t ngtcp2_cc_compute_initcwnd(size_t max_udp_payload_size) { uint64_t n = 2 * max_udp_payload_size; @@ -56,45 +59,26 @@ ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num, return pkt; } -static void reno_cc_reset(ngtcp2_reno_cc *cc) { - cc->max_delivery_rate_sec = 0; - cc->target_cwnd = 0; - cc->pending_add = 0; -} - -void ngtcp2_reno_cc_init(ngtcp2_reno_cc *cc, ngtcp2_log *log) { - cc->ccb.log = log; - reno_cc_reset(cc); +static void reno_cc_reset(ngtcp2_cc_reno *reno) { + ngtcp2_window_filter_init(&reno->delivery_rate_sec_filter, + NGTCP2_CC_DELIVERY_RATE_SEC_FILTERLEN); + reno->ack_count = 0; + reno->target_cwnd = 0; + reno->pending_add = 0; } -void ngtcp2_reno_cc_free(ngtcp2_reno_cc *cc) { (void)cc; } - -int ngtcp2_cc_reno_cc_init(ngtcp2_cc *cc, ngtcp2_log *log, - const ngtcp2_mem *mem) { - ngtcp2_reno_cc *reno_cc; - - reno_cc = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_reno_cc)); - if (reno_cc == NULL) { - return NGTCP2_ERR_NOMEM; - } - - ngtcp2_reno_cc_init(reno_cc, log); - - cc->ccb = &reno_cc->ccb; - cc->on_pkt_acked = ngtcp2_cc_reno_cc_on_pkt_acked; - cc->congestion_event = ngtcp2_cc_reno_cc_congestion_event; - cc->on_persistent_congestion = ngtcp2_cc_reno_cc_on_persistent_congestion; - cc->on_ack_recv = ngtcp2_cc_reno_cc_on_ack_recv; - cc->reset = ngtcp2_cc_reno_cc_reset; - - return 0; -} +void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log) { + memset(reno, 0, sizeof(*reno)); -void ngtcp2_cc_reno_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem) { - ngtcp2_reno_cc *reno_cc = ngtcp2_struct_of(cc->ccb, ngtcp2_reno_cc, ccb); + reno->cc.log = log; + reno->cc.on_pkt_acked = ngtcp2_cc_reno_cc_on_pkt_acked; + reno->cc.congestion_event = ngtcp2_cc_reno_cc_congestion_event; + reno->cc.on_persistent_congestion = + ngtcp2_cc_reno_cc_on_persistent_congestion; + reno->cc.on_ack_recv = ngtcp2_cc_reno_cc_on_ack_recv; + reno->cc.reset = ngtcp2_cc_reno_cc_reset; - ngtcp2_reno_cc_free(reno_cc); - ngtcp2_mem_free(mem, reno_cc); + reno_cc_reset(reno); } static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, @@ -103,10 +87,10 @@ static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, sent_time <= cstat->congestion_recovery_start_ts; } -void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { - ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb); + ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); uint64_t m; (void)ts; @@ -114,28 +98,28 @@ void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, return; } - if (cc->target_cwnd && cc->target_cwnd < cstat->cwnd) { + if (reno->target_cwnd && reno->target_cwnd < cstat->cwnd) { return; } if (cstat->cwnd < cstat->ssthresh) { cstat->cwnd += pkt->pktlen; - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(reno->cc.log, NGTCP2_LOG_EVENT_CCA, "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64, pkt->pkt_num, cstat->cwnd); return; } - m = cstat->max_udp_payload_size * pkt->pktlen + cc->pending_add; - cc->pending_add = m % cstat->cwnd; + m = cstat->max_tx_udp_payload_size * pkt->pktlen + reno->pending_add; + reno->pending_add = m % cstat->cwnd; cstat->cwnd += m / cstat->cwnd; } -void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, ngtcp2_tstamp ts) { - ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb); + ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); uint64_t min_cwnd; if (in_congestion_recovery(cstat, sent_ts)) { @@ -144,157 +128,130 @@ void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, cstat->congestion_recovery_start_ts = ts; cstat->cwnd >>= NGTCP2_LOSS_REDUCTION_FACTOR_BITS; - min_cwnd = 2 * cstat->max_udp_payload_size; + min_cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->cwnd = ngtcp2_max(cstat->cwnd, min_cwnd); cstat->ssthresh = cstat->cwnd; - cc->pending_add = 0; + reno->pending_add = 0; - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(reno->cc.log, NGTCP2_LOG_EVENT_CCA, "reduce cwnd because of packet loss cwnd=%" PRIu64, cstat->cwnd); } -void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *ccx, +void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - (void)ccx; + (void)cc; (void)ts; - cstat->cwnd = 2 * cstat->max_udp_payload_size; + cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->congestion_recovery_start_ts = UINT64_MAX; } -void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb); + ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); uint64_t target_cwnd, initcwnd; + uint64_t max_delivery_rate_sec; (void)ack; (void)ts; - /* TODO Use sliding window for min rtt measurement */ - /* TODO Use sliding window */ - cc->max_delivery_rate_sec = - ngtcp2_max(cc->max_delivery_rate_sec, cstat->delivery_rate_sec); + ++reno->ack_count; - if (cstat->min_rtt != UINT64_MAX && cc->max_delivery_rate_sec) { - target_cwnd = cc->max_delivery_rate_sec * cstat->min_rtt / NGTCP2_SECONDS; - initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_udp_payload_size); - cc->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100; + ngtcp2_window_filter_update(&reno->delivery_rate_sec_filter, + cstat->delivery_rate_sec, reno->ack_count); - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + max_delivery_rate_sec = + ngtcp2_window_filter_get_best(&reno->delivery_rate_sec_filter); + + if (cstat->min_rtt != UINT64_MAX && max_delivery_rate_sec) { + target_cwnd = max_delivery_rate_sec * cstat->smoothed_rtt / NGTCP2_SECONDS; + initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_tx_udp_payload_size); + reno->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100; + + ngtcp2_log_info(reno->cc.log, NGTCP2_LOG_EVENT_CCA, "target_cwnd=%" PRIu64 " max_delivery_rate_sec=%" PRIu64 - " min_rtt=%" PRIu64, - cc->target_cwnd, cc->max_delivery_rate_sec, cstat->min_rtt); + " smoothed_rtt=%" PRIu64, + reno->target_cwnd, max_delivery_rate_sec, + cstat->smoothed_rtt); } } -void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb); + ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); (void)cstat; (void)ts; - reno_cc_reset(cc); + reno_cc_reset(reno); } -static void cubic_cc_reset(ngtcp2_cubic_cc *cc) { - cc->max_delivery_rate_sec = 0; - cc->target_cwnd = 0; - cc->w_last_max = 0; - cc->w_tcp = 0; - cc->origin_point = 0; - cc->epoch_start = UINT64_MAX; - cc->k = 0; - - cc->prior.cwnd = 0; - cc->prior.ssthresh = 0; - cc->prior.w_last_max = 0; - cc->prior.w_tcp = 0; - cc->prior.origin_point = 0; - cc->prior.epoch_start = UINT64_MAX; - cc->prior.k = 0; - - cc->rtt_sample_count = 0; - cc->current_round_min_rtt = UINT64_MAX; - cc->last_round_min_rtt = UINT64_MAX; - cc->window_end = -1; +static void cubic_cc_reset(ngtcp2_cc_cubic *cubic) { + ngtcp2_window_filter_init(&cubic->delivery_rate_sec_filter, + NGTCP2_CC_DELIVERY_RATE_SEC_FILTERLEN); + cubic->ack_count = 0; + cubic->target_cwnd = 0; + cubic->w_last_max = 0; + cubic->w_tcp = 0; + cubic->origin_point = 0; + cubic->epoch_start = UINT64_MAX; + cubic->k = 0; + + cubic->prior.cwnd = 0; + cubic->prior.ssthresh = 0; + cubic->prior.w_last_max = 0; + cubic->prior.w_tcp = 0; + cubic->prior.origin_point = 0; + cubic->prior.epoch_start = UINT64_MAX; + cubic->prior.k = 0; + + cubic->rtt_sample_count = 0; + cubic->current_round_min_rtt = UINT64_MAX; + cubic->last_round_min_rtt = UINT64_MAX; + cubic->window_end = -1; } -void ngtcp2_cubic_cc_init(ngtcp2_cubic_cc *cc, ngtcp2_log *log) { - cc->ccb.log = log; - cubic_cc_reset(cc); +void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cubic, ngtcp2_log *log) { + memset(cubic, 0, sizeof(*cubic)); + + cubic->cc.log = log; + cubic->cc.on_pkt_acked = ngtcp2_cc_cubic_cc_on_pkt_acked; + cubic->cc.congestion_event = ngtcp2_cc_cubic_cc_congestion_event; + cubic->cc.on_spurious_congestion = ngtcp2_cc_cubic_cc_on_spurious_congestion; + cubic->cc.on_persistent_congestion = + ngtcp2_cc_cubic_cc_on_persistent_congestion; + cubic->cc.on_ack_recv = ngtcp2_cc_cubic_cc_on_ack_recv; + cubic->cc.on_pkt_sent = ngtcp2_cc_cubic_cc_on_pkt_sent; + cubic->cc.new_rtt_sample = ngtcp2_cc_cubic_cc_new_rtt_sample; + cubic->cc.reset = ngtcp2_cc_cubic_cc_reset; + cubic->cc.event = ngtcp2_cc_cubic_cc_event; + + cubic_cc_reset(cubic); } -void ngtcp2_cubic_cc_free(ngtcp2_cubic_cc *cc) { (void)cc; } - -int ngtcp2_cc_cubic_cc_init(ngtcp2_cc *cc, ngtcp2_log *log, - const ngtcp2_mem *mem) { - ngtcp2_cubic_cc *cubic_cc; - - cubic_cc = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_cubic_cc)); - if (cubic_cc == NULL) { - return NGTCP2_ERR_NOMEM; +uint64_t ngtcp2_cbrt(uint64_t n) { + size_t s; + uint64_t y = 0; + uint64_t b; + + for (s = 63; s > 0; s -= 3) { + y <<= 1; + b = 3 * y * (y + 1) + 1; + if ((n >> s) >= b) { + n -= b << s; + y++; + } } - ngtcp2_cubic_cc_init(cubic_cc, log); - - cc->ccb = &cubic_cc->ccb; - cc->on_pkt_acked = ngtcp2_cc_cubic_cc_on_pkt_acked; - cc->congestion_event = ngtcp2_cc_cubic_cc_congestion_event; - cc->on_spurious_congestion = ngtcp2_cc_cubic_cc_on_spurious_congestion; - cc->on_persistent_congestion = ngtcp2_cc_cubic_cc_on_persistent_congestion; - cc->on_ack_recv = ngtcp2_cc_cubic_cc_on_ack_recv; - cc->on_pkt_sent = ngtcp2_cc_cubic_cc_on_pkt_sent; - cc->new_rtt_sample = ngtcp2_cc_cubic_cc_new_rtt_sample; - cc->reset = ngtcp2_cc_cubic_cc_reset; - cc->event = ngtcp2_cc_cubic_cc_event; - - return 0; -} - -void ngtcp2_cc_cubic_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem) { - ngtcp2_cubic_cc *cubic_cc = ngtcp2_struct_of(cc->ccb, ngtcp2_cubic_cc, ccb); - - ngtcp2_cubic_cc_free(cubic_cc); - ngtcp2_mem_free(mem, cubic_cc); -} - -static uint64_t ngtcp2_cbrt(uint64_t n) { - int d; - uint64_t a; - - if (n == 0) { - return 0; + y <<= 1; + b = 3 * y * (y + 1) + 1; + if (n >= b) { + n -= b; + y++; } -#if defined(_MSC_VER) -# if defined(_M_X64) - d = (int)__lzcnt64(n); -# elif defined(_M_ARM64) - { - unsigned long index; - d = sizeof(uint64_t) * CHAR_BIT; - if (_BitScanReverse64(&index, n)) { - d = d - 1 - index; - } - } -# else - if ((n >> 32) != 0) { - d = __lzcnt((unsigned int)(n >> 32)); - } else { - d = 32 + __lzcnt((unsigned int)n); - } -# endif -#else - d = __builtin_clzll(n); -#endif - a = 1ULL << ((64 - d) / 3 + 1); - - for (; a * a * a > n;) { - a = (2 * a + n / a / a) / 3; - } - return a; + return y; } /* HyStart++ constants */ @@ -303,42 +260,41 @@ static uint64_t ngtcp2_cbrt(uint64_t n) { #define NGTCP2_HS_MIN_ETA (4 * NGTCP2_MILLISECONDS) #define NGTCP2_HS_MAX_ETA (16 * NGTCP2_MILLISECONDS) -void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { - ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb); - ngtcp2_duration t, min_rtt, eta; - uint64_t target; + ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); + ngtcp2_duration t, eta; + uint64_t target, cwnd_thres; uint64_t tx, kx, time_delta, delta; uint64_t add, tcp_add; uint64_t m; - if (pkt->pktns_id == NGTCP2_PKTNS_ID_APPLICATION && cc->window_end != -1 && - cc->window_end <= pkt->pkt_num) { - cc->window_end = -1; + if (pkt->pktns_id == NGTCP2_PKTNS_ID_APPLICATION && cubic->window_end != -1 && + cubic->window_end <= pkt->pkt_num) { + cubic->window_end = -1; } if (in_congestion_recovery(cstat, pkt->sent_ts)) { return; } - if (cc->target_cwnd && cc->target_cwnd < cstat->cwnd) { - return; - } - if (cstat->cwnd < cstat->ssthresh) { /* slow-start */ - cstat->cwnd += pkt->pktlen; + if (cubic->target_cwnd == 0 || cubic->target_cwnd > cstat->cwnd) { + cstat->cwnd += pkt->pktlen; + } - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64, pkt->pkt_num, cstat->cwnd); - if (cc->last_round_min_rtt != UINT64_MAX && - cc->current_round_min_rtt != UINT64_MAX && - cstat->cwnd >= NGTCP2_HS_MIN_SSTHRESH * cstat->max_udp_payload_size && - cc->rtt_sample_count >= NGTCP2_HS_N_RTT_SAMPLE) { - eta = cc->last_round_min_rtt / 8; + if (cubic->last_round_min_rtt != UINT64_MAX && + cubic->current_round_min_rtt != UINT64_MAX && + cstat->cwnd >= + NGTCP2_HS_MIN_SSTHRESH * cstat->max_tx_udp_payload_size && + cubic->rtt_sample_count >= NGTCP2_HS_N_RTT_SAMPLE) { + eta = cubic->last_round_min_rtt / 8; if (eta < NGTCP2_HS_MIN_ETA) { eta = NGTCP2_HS_MIN_ETA; @@ -346,11 +302,11 @@ void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, eta = NGTCP2_HS_MAX_ETA; } - if (cc->current_round_min_rtt >= cc->last_round_min_rtt + eta) { - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + if (cubic->current_round_min_rtt >= cubic->last_round_min_rtt + eta) { + ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "HyStart++ exit slow start"); - cc->w_last_max = cstat->cwnd; + cubic->w_last_max = cstat->cwnd; cstat->ssthresh = cstat->cwnd; } } @@ -360,34 +316,32 @@ void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, /* congestion avoidance */ - if (cc->epoch_start == UINT64_MAX) { - cc->epoch_start = ts; - if (cstat->cwnd < cc->w_last_max) { - cc->k = ngtcp2_cbrt((cc->w_last_max - cstat->cwnd) * 10 / 4 / - cstat->max_udp_payload_size); - cc->origin_point = cc->w_last_max; + if (cubic->epoch_start == UINT64_MAX) { + cubic->epoch_start = ts; + if (cstat->cwnd < cubic->w_last_max) { + cubic->k = ngtcp2_cbrt((cubic->w_last_max - cstat->cwnd) * 10 / 4 / + cstat->max_tx_udp_payload_size); + cubic->origin_point = cubic->w_last_max; } else { - cc->k = 0; - cc->origin_point = cstat->cwnd; + cubic->k = 0; + cubic->origin_point = cstat->cwnd; } - cc->w_tcp = cstat->cwnd; + cubic->w_tcp = cstat->cwnd; - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "cubic-ca epoch_start=%" PRIu64 " k=%" PRIu64 " origin_point=%" PRIu64, - cc->epoch_start, cc->k, cc->origin_point); + cubic->epoch_start, cubic->k, cubic->origin_point); - cc->pending_add = 0; - cc->pending_w_add = 0; + cubic->pending_add = 0; + cubic->pending_w_add = 0; } - min_rtt = cstat->min_rtt == UINT64_MAX ? cstat->initial_rtt : cstat->min_rtt; + t = ts - cubic->epoch_start; - t = ts + min_rtt - cc->epoch_start; - - tx = (t << 4) / NGTCP2_SECONDS; - kx = (cc->k << 4); + tx = (t << 10) / NGTCP2_SECONDS; + kx = (cubic->k << 10); if (tx > kx) { time_delta = tx - kx; @@ -395,210 +349,229 @@ void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, time_delta = kx - tx; } - delta = cstat->max_udp_payload_size * - ((((time_delta * time_delta) >> 4) * time_delta) >> 8) * 4 / 10; + delta = cstat->max_tx_udp_payload_size * + ((((time_delta * time_delta) >> 10) * time_delta) >> 10) * 4 / 10; + delta >>= 10; if (tx > kx) { - target = cc->origin_point + delta; + target = cubic->origin_point + delta; + } else { + target = cubic->origin_point - delta; + } + + cwnd_thres = + (target * (((t + cstat->smoothed_rtt) << 10) / NGTCP2_SECONDS)) >> 10; + if (cwnd_thres < cstat->cwnd) { + target = cstat->cwnd; + } else if (2 * cwnd_thres > 3 * cstat->cwnd) { + target = cstat->cwnd * 3 / 2; } else { - target = cc->origin_point - delta; + target = cwnd_thres; } if (target > cstat->cwnd) { - m = cc->pending_add + cstat->max_udp_payload_size * (target - cstat->cwnd); + m = cubic->pending_add + + cstat->max_tx_udp_payload_size * (target - cstat->cwnd); add = m / cstat->cwnd; - cc->pending_add = m % cstat->cwnd; + cubic->pending_add = m % cstat->cwnd; } else { - m = cc->pending_add + cstat->max_udp_payload_size; + m = cubic->pending_add + cstat->max_tx_udp_payload_size; add = m / (100 * cstat->cwnd); - cc->pending_add = m % (100 * cstat->cwnd); + cubic->pending_add = m % (100 * cstat->cwnd); } - m = cc->pending_w_add + cstat->max_udp_payload_size * pkt->pktlen; + m = cubic->pending_w_add + cstat->max_tx_udp_payload_size * pkt->pktlen; - cc->w_tcp += m / cstat->cwnd; - cc->pending_w_add = m % cstat->cwnd; + cubic->w_tcp += m / cstat->cwnd; + cubic->pending_w_add = m % cstat->cwnd; - if (cc->w_tcp > cstat->cwnd) { - tcp_add = - cstat->max_udp_payload_size * (cc->w_tcp - cstat->cwnd) / cstat->cwnd; + if (cubic->w_tcp > cstat->cwnd) { + tcp_add = cstat->max_tx_udp_payload_size * (cubic->w_tcp - cstat->cwnd) / + cstat->cwnd; if (tcp_add > add) { add = tcp_add; } } - cstat->cwnd += add; + if (cubic->target_cwnd == 0 || cubic->target_cwnd > cstat->cwnd) { + cstat->cwnd += add; + } - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "pkn=%" PRId64 " acked, cubic-ca cwnd=%" PRIu64 " t=%" PRIu64 " k=%" PRIi64 " time_delta=%" PRIu64 " delta=%" PRIu64 " target=%" PRIu64 " w_tcp=%" PRIu64, - pkt->pkt_num, cstat->cwnd, t, cc->k, time_delta >> 4, delta, - target, cc->w_tcp); + pkt->pkt_num, cstat->cwnd, t, cubic->k, time_delta >> 4, + delta, target, cubic->w_tcp); } -void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *ccx, - ngtcp2_conn_stat *cstat, +void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, ngtcp2_tstamp ts) { - ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb); + ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); uint64_t min_cwnd; if (in_congestion_recovery(cstat, sent_ts)) { return; } - if (cc->prior.cwnd < cstat->cwnd) { - cc->prior.cwnd = cstat->cwnd; - cc->prior.ssthresh = cstat->ssthresh; - cc->prior.w_last_max = cc->w_last_max; - cc->prior.w_tcp = cc->w_tcp; - cc->prior.origin_point = cc->origin_point; - cc->prior.epoch_start = cc->epoch_start; - cc->prior.k = cc->k; + if (cubic->prior.cwnd < cstat->cwnd) { + cubic->prior.cwnd = cstat->cwnd; + cubic->prior.ssthresh = cstat->ssthresh; + cubic->prior.w_last_max = cubic->w_last_max; + cubic->prior.w_tcp = cubic->w_tcp; + cubic->prior.origin_point = cubic->origin_point; + cubic->prior.epoch_start = cubic->epoch_start; + cubic->prior.k = cubic->k; } cstat->congestion_recovery_start_ts = ts; - cc->epoch_start = UINT64_MAX; - if (cstat->cwnd < cc->w_last_max) { - cc->w_last_max = cstat->cwnd * 17 / 10 / 2; + cubic->epoch_start = UINT64_MAX; + if (cstat->cwnd < cubic->w_last_max) { + cubic->w_last_max = cstat->cwnd * 17 / 10 / 2; } else { - cc->w_last_max = cstat->cwnd; + cubic->w_last_max = cstat->cwnd; } - min_cwnd = 2 * cstat->max_udp_payload_size; + min_cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->ssthresh = cstat->cwnd * 7 / 10; cstat->ssthresh = ngtcp2_max(cstat->ssthresh, min_cwnd); cstat->cwnd = cstat->ssthresh; - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "reduce cwnd because of packet loss cwnd=%" PRIu64, cstat->cwnd); } -void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *ccx, +void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb); + ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); (void)ts; - if (cstat->cwnd >= cc->prior.cwnd) { + if (cstat->cwnd >= cubic->prior.cwnd) { return; } cstat->congestion_recovery_start_ts = UINT64_MAX; - cstat->cwnd = cc->prior.cwnd; - cstat->ssthresh = cc->prior.ssthresh; - cc->w_last_max = cc->prior.w_last_max; - cc->w_tcp = cc->prior.w_tcp; - cc->origin_point = cc->prior.origin_point; - cc->epoch_start = cc->prior.epoch_start; - cc->k = cc->prior.k; - - cc->prior.cwnd = 0; - cc->prior.ssthresh = 0; - cc->prior.w_last_max = 0; - cc->prior.w_tcp = 0; - cc->prior.origin_point = 0; - cc->prior.epoch_start = UINT64_MAX; - cc->prior.k = 0; - - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + cstat->cwnd = cubic->prior.cwnd; + cstat->ssthresh = cubic->prior.ssthresh; + cubic->w_last_max = cubic->prior.w_last_max; + cubic->w_tcp = cubic->prior.w_tcp; + cubic->origin_point = cubic->prior.origin_point; + cubic->epoch_start = cubic->prior.epoch_start; + cubic->k = cubic->prior.k; + + cubic->prior.cwnd = 0; + cubic->prior.ssthresh = 0; + cubic->prior.w_last_max = 0; + cubic->prior.w_tcp = 0; + cubic->prior.origin_point = 0; + cubic->prior.epoch_start = UINT64_MAX; + cubic->prior.k = 0; + + ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "spurious congestion is detected and congestion state is " "restored cwnd=%" PRIu64, cstat->cwnd); } -void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *ccx, +void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - (void)ccx; + (void)cc; (void)ts; - cstat->cwnd = 2 * cstat->max_udp_payload_size; + cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->congestion_recovery_start_ts = UINT64_MAX; } -void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb); + ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); uint64_t target_cwnd, initcwnd; + uint64_t max_delivery_rate_sec; (void)ack; (void)ts; - /* TODO Use sliding window for min rtt measurement */ - /* TODO Use sliding window */ - cc->max_delivery_rate_sec = - ngtcp2_max(cc->max_delivery_rate_sec, cstat->delivery_rate_sec); + ++cubic->ack_count; + + ngtcp2_window_filter_update(&cubic->delivery_rate_sec_filter, + cstat->delivery_rate_sec, cubic->ack_count); + + max_delivery_rate_sec = + ngtcp2_window_filter_get_best(&cubic->delivery_rate_sec_filter); - if (cstat->min_rtt != UINT64_MAX && cc->max_delivery_rate_sec) { - target_cwnd = cc->max_delivery_rate_sec * cstat->min_rtt / NGTCP2_SECONDS; - initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_udp_payload_size); - cc->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100; + if (cstat->min_rtt != UINT64_MAX && max_delivery_rate_sec) { + target_cwnd = max_delivery_rate_sec * cstat->smoothed_rtt / NGTCP2_SECONDS; + initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_tx_udp_payload_size); + cubic->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100; - ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "target_cwnd=%" PRIu64 " max_delivery_rate_sec=%" PRIu64 - " min_rtt=%" PRIu64, - cc->target_cwnd, cc->max_delivery_rate_sec, cstat->min_rtt); + " smoothed_rtt=%" PRIu64, + cubic->target_cwnd, max_delivery_rate_sec, + cstat->smoothed_rtt); } } -void ngtcp2_cc_cubic_cc_on_pkt_sent(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_cubic_cc_on_pkt_sent(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt) { - ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb); + ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); (void)cstat; - if (pkt->pktns_id != NGTCP2_PKTNS_ID_APPLICATION || cc->window_end != -1) { + if (pkt->pktns_id != NGTCP2_PKTNS_ID_APPLICATION || cubic->window_end != -1) { return; } - cc->window_end = pkt->pkt_num; - cc->last_round_min_rtt = cc->current_round_min_rtt; - cc->current_round_min_rtt = UINT64_MAX; - cc->rtt_sample_count = 0; + cubic->window_end = pkt->pkt_num; + cubic->last_round_min_rtt = cubic->current_round_min_rtt; + cubic->current_round_min_rtt = UINT64_MAX; + cubic->rtt_sample_count = 0; } -void ngtcp2_cc_cubic_cc_new_rtt_sample(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_cubic_cc_new_rtt_sample(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb); + ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); (void)ts; - if (cc->window_end == -1) { + if (cubic->window_end == -1) { return; } - cc->current_round_min_rtt = - ngtcp2_min(cc->current_round_min_rtt, cstat->latest_rtt); - ++cc->rtt_sample_count; + cubic->current_round_min_rtt = + ngtcp2_min(cubic->current_round_min_rtt, cstat->latest_rtt); + ++cubic->rtt_sample_count; } -void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb); + ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); (void)cstat; (void)ts; - cubic_cc_reset(cc); + cubic_cc_reset(cubic); } -void ngtcp2_cc_cubic_cc_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, +void ngtcp2_cc_cubic_cc_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_cc_event_type event, ngtcp2_tstamp ts) { - ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb); + ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); ngtcp2_tstamp last_ts; - if (event != NGTCP2_CC_EVENT_TYPE_TX_START || cc->epoch_start == UINT64_MAX) { + if (event != NGTCP2_CC_EVENT_TYPE_TX_START || + cubic->epoch_start == UINT64_MAX) { return; } last_ts = cstat->last_tx_pkt_ts[NGTCP2_PKTNS_ID_APPLICATION]; - if (last_ts == UINT64_MAX || last_ts <= cc->epoch_start) { + if (last_ts == UINT64_MAX || last_ts <= cubic->epoch_start) { return; } assert(ts >= last_ts); - cc->epoch_start += ts - last_ts; + cubic->epoch_start += ts - last_ts; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h index 6d9e0c2459ece4..524bcdb7e4bf86 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h @@ -31,24 +31,14 @@ #include +#include "ngtcp2_pktns_id.h" +#include "ngtcp2_window_filter.h" + #define NGTCP2_LOSS_REDUCTION_FACTOR_BITS 1 #define NGTCP2_PERSISTENT_CONGESTION_THRESHOLD 3 typedef struct ngtcp2_log ngtcp2_log; - -/** - * @struct - * - * :type:`ngtcp2_cc_base` is the base structure of custom congestion - * control algorithm. It must be the first field of custom congestion - * controller. - */ -typedef struct ngtcp2_cc_base { - /** - * :member:`log` is ngtcp2 library internal logger. - */ - ngtcp2_log *log; -} ngtcp2_cc_base; +typedef struct ngtcp2_conn_stat ngtcp2_conn_stat; /** * @struct @@ -117,10 +107,10 @@ typedef struct ngtcp2_cc_ack { */ uint64_t pkt_delivered; /** - * :member:`largest_acked_sent_ts` is the time when the largest - * acknowledged packet was sent. + * :member:`largest_pkt_sent_ts` is the time when the largest + * acknowledged packet was sent. It is UINT64_MAX if it is unknown. */ - ngtcp2_tstamp largest_acked_sent_ts; + ngtcp2_tstamp largest_pkt_sent_ts; /** * :member:`rtt` is the RTT sample. It is UINT64_MAX if no RTT * sample is available. @@ -242,15 +232,14 @@ typedef void (*ngtcp2_cc_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, /** * @struct * - * :type:`ngtcp2_cc` is congestion control algorithm interface to - * allow custom implementation. + * :type:`ngtcp2_cc` is congestion control algorithm interface shared + * by implementations. All callback functions are optional. */ typedef struct ngtcp2_cc { /** - * :member:`ccb` is a pointer to :type:`ngtcp2_cc_base` which - * usually contains a state. + * :member:`log` is ngtcp2 library internal logger. */ - ngtcp2_cc_base *ccb; + ngtcp2_log *log; /** * :member:`on_pkt_acked` is a callback function which is called * when a packet is acknowledged. @@ -313,22 +302,16 @@ ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num, ngtcp2_tstamp sent_ts, uint64_t lost, uint64_t tx_in_flight, int is_app_limited); -/* ngtcp2_reno_cc is the RENO congestion controller. */ -typedef struct ngtcp2_reno_cc { - ngtcp2_cc_base ccb; - uint64_t max_delivery_rate_sec; +/* ngtcp2_cc_reno is the RENO congestion controller. */ +typedef struct ngtcp2_cc_reno { + ngtcp2_cc cc; + ngtcp2_window_filter delivery_rate_sec_filter; + uint64_t ack_count; uint64_t target_cwnd; uint64_t pending_add; -} ngtcp2_reno_cc; - -int ngtcp2_cc_reno_cc_init(ngtcp2_cc *cc, ngtcp2_log *log, - const ngtcp2_mem *mem); - -void ngtcp2_cc_reno_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem); - -void ngtcp2_reno_cc_init(ngtcp2_reno_cc *cc, ngtcp2_log *log); +} ngtcp2_cc_reno; -void ngtcp2_reno_cc_free(ngtcp2_reno_cc *cc); +void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log); void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); @@ -347,10 +330,11 @@ void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -/* ngtcp2_cubic_cc is CUBIC congestion controller. */ -typedef struct ngtcp2_cubic_cc { - ngtcp2_cc_base ccb; - uint64_t max_delivery_rate_sec; +/* ngtcp2_cc_cubic is CUBIC congestion controller. */ +typedef struct ngtcp2_cc_cubic { + ngtcp2_cc cc; + ngtcp2_window_filter delivery_rate_sec_filter; + uint64_t ack_count; uint64_t target_cwnd; uint64_t w_last_max; uint64_t w_tcp; @@ -376,16 +360,9 @@ typedef struct ngtcp2_cubic_cc { int64_t window_end; uint64_t pending_add; uint64_t pending_w_add; -} ngtcp2_cubic_cc; +} ngtcp2_cc_cubic; -int ngtcp2_cc_cubic_cc_init(ngtcp2_cc *cc, ngtcp2_log *log, - const ngtcp2_mem *mem); - -void ngtcp2_cc_cubic_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem); - -void ngtcp2_cubic_cc_init(ngtcp2_cubic_cc *cc, ngtcp2_log *log); - -void ngtcp2_cubic_cc_free(ngtcp2_cubic_cc *cc); +void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cc, ngtcp2_log *log); void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, @@ -418,4 +395,6 @@ void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, void ngtcp2_cc_cubic_cc_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_cc_event_type event, ngtcp2_tstamp ts); +uint64_t ngtcp2_cbrt(uint64_t n); + #endif /* NGTCP2_CC_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c index a3135680ca160f..c8caf47ea76232 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c @@ -35,6 +35,11 @@ #include "ngtcp2_addr.h" #include "ngtcp2_path.h" #include "ngtcp2_rcvry.h" +#include "ngtcp2_unreachable.h" +#include "ngtcp2_net.h" +#include "ngtcp2_conversion.h" +#include "ngtcp2_tstamp.h" +#include "ngtcp2_frame_chain.h" /* NGTCP2_FLOW_WINDOW_RTT_FACTOR is the factor of RTT when flow control window auto-tuning is triggered. */ @@ -46,6 +51,8 @@ packet payload that should be coalesced to a long packet. */ #define NGTCP2_MIN_COALESCED_PAYLOADLEN 128 +ngtcp2_objalloc_def(strm, ngtcp2_strm, oplent); + /* * conn_local_stream returns nonzero if |stream_id| indicates that it * is the stream initiated by local endpoint. @@ -60,12 +67,20 @@ static int conn_local_stream(ngtcp2_conn *conn, int64_t stream_id) { */ static int bidi_stream(int64_t stream_id) { return (stream_id & 0x2) == 0; } +static void conn_update_timestamp(ngtcp2_conn *conn, ngtcp2_tstamp ts) { + assert(conn->log.last_ts <= ts); + assert(conn->qlog.last_ts <= ts); + + conn->log.last_ts = ts; + conn->qlog.last_ts = ts; +} + /* - * conn_is_handshake_completed returns nonzero if QUIC handshake has - * completed. + * conn_is_tls_handshake_completed returns nonzero if TLS handshake + * has completed and 1 RTT keys are available. */ -static int conn_is_handshake_completed(ngtcp2_conn *conn) { - return (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) && +static int conn_is_tls_handshake_completed(ngtcp2_conn *conn) { + return (conn->flags & NGTCP2_CONN_FLAG_TLS_HANDSHAKE_COMPLETED) && conn->pktns.crypto.rx.ckm && conn->pktns.crypto.tx.ckm; } @@ -118,14 +133,14 @@ static int conn_call_recv_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm, } static int conn_call_recv_crypto_data(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, + ngtcp2_encryption_level encryption_level, uint64_t offset, const uint8_t *data, size_t datalen) { int rv; assert(conn->callbacks.recv_crypto_data); - rv = conn->callbacks.recv_crypto_data(conn, crypto_level, offset, data, + rv = conn->callbacks.recv_crypto_data(conn, encryption_level, offset, data, datalen, conn->user_data); switch (rv) { case 0: @@ -267,6 +282,7 @@ static int conn_call_path_validation(ngtcp2_conn *conn, const ngtcp2_pv *pv, ngtcp2_path_validation_result res) { int rv; uint32_t flags = NGTCP2_PATH_VALIDATION_FLAG_NONE; + const ngtcp2_path *old_path = NULL; if (!conn->callbacks.path_validation) { return 0; @@ -276,8 +292,18 @@ static int conn_call_path_validation(ngtcp2_conn *conn, const ngtcp2_pv *pv, flags |= NGTCP2_PATH_VALIDATION_FLAG_PREFERRED_ADDR; } - rv = conn->callbacks.path_validation(conn, flags, &pv->dcid.ps.path, res, - conn->user_data); + if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) { + old_path = &pv->fallback_dcid.ps.path; + } + + if (conn->server && old_path && + (ngtcp2_addr_compare(&pv->dcid.ps.path.remote, &old_path->remote) & + (NGTCP2_ADDR_COMPARE_FLAG_ADDR | NGTCP2_ADDR_COMPARE_FLAG_FAMILY))) { + flags |= NGTCP2_PATH_VALIDATION_FLAG_NEW_TOKEN; + } + + rv = conn->callbacks.path_validation(conn, flags, &pv->dcid.ps.path, old_path, + res, conn->user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -294,10 +320,10 @@ static int conn_call_select_preferred_addr(ngtcp2_conn *conn, } assert(conn->remote.transport_params); - assert(conn->remote.transport_params->preferred_address_present); + assert(conn->remote.transport_params->preferred_addr_present); rv = conn->callbacks.select_preferred_addr( - conn, dest, &conn->remote.transport_params->preferred_address, + conn, dest, &conn->remote.transport_params->preferred_addr, conn->user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; @@ -369,7 +395,7 @@ static int conn_call_dcid_status(ngtcp2_conn *conn, } rv = conn->callbacks.dcid_status( - conn, (int)type, dcid->seq, &dcid->cid, + conn, type, dcid->seq, &dcid->cid, (dcid->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) ? dcid->token : NULL, conn->user_data); if (rv != 0) { @@ -505,15 +531,15 @@ conn_call_recv_stateless_reset(ngtcp2_conn *conn, return 0; } -static int conn_call_recv_new_token(ngtcp2_conn *conn, - const ngtcp2_vec *token) { +static int conn_call_recv_new_token(ngtcp2_conn *conn, const uint8_t *token, + size_t tokenlen) { int rv; if (!conn->callbacks.recv_new_token) { return 0; } - rv = conn->callbacks.recv_new_token(conn, token, conn->user_data); + rv = conn->callbacks.recv_new_token(conn, token, tokenlen, conn->user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -557,8 +583,8 @@ static int conn_call_recv_datagram(ngtcp2_conn *conn, datalen = 0; } - if (!conn_is_handshake_completed(conn)) { - flags |= NGTCP2_DATAGRAM_FLAG_EARLY; + if (!conn_is_tls_handshake_completed(conn)) { + flags |= NGTCP2_DATAGRAM_FLAG_0RTT; } rv = conn->callbacks.recv_datagram(conn, flags, data, datalen, @@ -605,7 +631,8 @@ static int conn_call_version_negotiation(ngtcp2_conn *conn, uint32_t version, return 0; } -static int conn_call_recv_rx_key(ngtcp2_conn *conn, ngtcp2_crypto_level level) { +static int conn_call_recv_rx_key(ngtcp2_conn *conn, + ngtcp2_encryption_level level) { int rv; if (!conn->callbacks.recv_rx_key) { @@ -620,7 +647,8 @@ static int conn_call_recv_rx_key(ngtcp2_conn *conn, ngtcp2_crypto_level level) { return 0; } -static int conn_call_recv_tx_key(ngtcp2_conn *conn, ngtcp2_crypto_level level) { +static int conn_call_recv_tx_key(ngtcp2_conn *conn, + ngtcp2_encryption_level level) { int rv; if (!conn->callbacks.recv_tx_key) { @@ -635,14 +663,10 @@ static int conn_call_recv_tx_key(ngtcp2_conn *conn, ngtcp2_crypto_level level) { return 0; } -static int crypto_offset_less(const ngtcp2_ksl_key *lhs, - const ngtcp2_ksl_key *rhs) { - return *(int64_t *)lhs < *(int64_t *)rhs; -} - static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, - ngtcp2_rst *rst, ngtcp2_cc *cc, ngtcp2_log *log, - ngtcp2_qlog *qlog, ngtcp2_objalloc *rtb_entry_objalloc, + ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num, + ngtcp2_log *log, ngtcp2_qlog *qlog, + ngtcp2_objalloc *rtb_entry_objalloc, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { int rv; @@ -650,7 +674,8 @@ static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, ngtcp2_gaptr_init(&pktns->rx.pngap, mem); - pktns->tx.last_pkt_num = -1; + pktns->tx.last_pkt_num = initial_pkt_num - 1; + pktns->tx.non_ack_pkt_start_ts = UINT64_MAX; pktns->rx.max_pkt_num = -1; pktns->rx.max_ack_eliciting_pkt_num = -1; @@ -660,14 +685,12 @@ static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, } ngtcp2_strm_init(&pktns->crypto.strm, 0, NGTCP2_STRM_FLAG_NONE, 0, 0, NULL, - NULL, mem); + frc_objalloc, mem); - ngtcp2_ksl_init(&pktns->crypto.tx.frq, crypto_offset_less, sizeof(uint64_t), + ngtcp2_rtb_init(&pktns->rtb, pktns_id, &pktns->crypto.strm, rst, cc, + initial_pkt_num, log, qlog, rtb_entry_objalloc, frc_objalloc, mem); - ngtcp2_rtb_init(&pktns->rtb, pktns_id, &pktns->crypto.strm, rst, cc, log, - qlog, rtb_entry_objalloc, frc_objalloc, mem); - return 0; fail_acktr_init: @@ -677,8 +700,9 @@ static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, } static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id, - ngtcp2_rst *rst, ngtcp2_cc *cc, ngtcp2_log *log, - ngtcp2_qlog *qlog, ngtcp2_objalloc *rtb_entry_objalloc, + ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num, + ngtcp2_log *log, ngtcp2_qlog *qlog, + ngtcp2_objalloc *rtb_entry_objalloc, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { int rv; @@ -687,8 +711,8 @@ static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id, return NGTCP2_ERR_NOMEM; } - rv = pktns_init(*ppktns, pktns_id, rst, cc, log, qlog, rtb_entry_objalloc, - frc_objalloc, mem); + rv = pktns_init(*ppktns, pktns_id, rst, cc, initial_pkt_num, log, qlog, + rtb_entry_objalloc, frc_objalloc, mem); if (rv != 0) { ngtcp2_mem_free(mem, *ppktns); } @@ -729,9 +753,6 @@ static void delete_buf_chain(ngtcp2_buf_chain *bufchain, } static void pktns_free(ngtcp2_pktns *pktns, const ngtcp2_mem *mem) { - ngtcp2_frame_chain *frc; - ngtcp2_ksl_it it; - delete_buf_chain(pktns->crypto.tx.data, mem); delete_buffed_pkts(pktns->rx.buffed_pkts, mem); @@ -742,13 +763,6 @@ static void pktns_free(ngtcp2_pktns *pktns, const ngtcp2_mem *mem) { ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, mem); ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, mem); - for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it); - ngtcp2_ksl_it_next(&it)) { - frc = ngtcp2_ksl_it_get(&it); - ngtcp2_frame_chain_objalloc_del(frc, pktns->rtb.frc_objalloc, mem); - } - - ngtcp2_ksl_free(&pktns->crypto.tx.frq); ngtcp2_rtb_free(&pktns->rtb); ngtcp2_strm_free(&pktns->crypto.strm); ngtcp2_acktr_free(&pktns->acktr); @@ -765,26 +779,6 @@ static void pktns_del(ngtcp2_pktns *pktns, const ngtcp2_mem *mem) { ngtcp2_mem_free(mem, pktns); } -static void cc_del(ngtcp2_cc *cc, ngtcp2_cc_algo cc_algo, - const ngtcp2_mem *mem) { - switch (cc_algo) { - case NGTCP2_CC_ALGO_RENO: - ngtcp2_cc_reno_cc_free(cc, mem); - break; - case NGTCP2_CC_ALGO_CUBIC: - ngtcp2_cc_cubic_cc_free(cc, mem); - break; - case NGTCP2_CC_ALGO_BBR: - ngtcp2_cc_bbr_cc_free(cc, mem); - break; - case NGTCP2_CC_ALGO_BBR2: - ngtcp2_cc_bbr2_cc_free(cc, mem); - break; - default: - break; - } -} - static int cid_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { return ngtcp2_cid_less(lhs, rhs); } @@ -810,13 +804,13 @@ static void conn_reset_conn_stat_cc(ngtcp2_conn *conn, cstat->pto_count = 0; cstat->loss_detection_timer = UINT64_MAX; cstat->cwnd = - ngtcp2_cc_compute_initcwnd(conn->local.settings.max_udp_payload_size); + ngtcp2_cc_compute_initcwnd(conn->local.settings.max_tx_udp_payload_size); cstat->ssthresh = UINT64_MAX; cstat->congestion_recovery_start_ts = UINT64_MAX; cstat->bytes_in_flight = 0; cstat->delivery_rate_sec = 0; - cstat->pacing_rate = 0.0; - cstat->send_quantum = SIZE_MAX; + cstat->pacing_interval = 0; + cstat->send_quantum = 64 * 1024; } /* @@ -896,6 +890,25 @@ ngtcp2_duration ngtcp2_conn_compute_pto(ngtcp2_conn *conn, return conn_compute_pto(conn, pktns); } +/* + * conn_compute_pv_timeout_pto returns path validation timeout using + * the given |pto|. + */ +static ngtcp2_duration conn_compute_pv_timeout_pto(ngtcp2_conn *conn, + ngtcp2_duration pto) { + ngtcp2_duration initial_pto = conn_compute_initial_pto(conn, &conn->pktns); + + return 3 * ngtcp2_max(pto, initial_pto); +} + +/* + * conn_compute_pv_timeout returns path validation timeout. + */ +static ngtcp2_duration conn_compute_pv_timeout(ngtcp2_conn *conn) { + return conn_compute_pv_timeout_pto(conn, + conn_compute_pto(conn, &conn->pktns)); +} + static void conn_handle_tx_ecn(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint16_t *prtb_entry_flags, ngtcp2_pktns *pktns, const ngtcp2_pkt_hd *hd, ngtcp2_tstamp ts) { @@ -959,7 +972,7 @@ static void conn_handle_tx_ecn(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, case NGTCP2_ECN_STATE_FAILED: break; default: - assert(0); + ngtcp2_unreachable(); } } @@ -989,14 +1002,14 @@ static void conn_reset_ecn_validation_state(ngtcp2_conn *conn) { pktns->tx.ecn.validation_pkt_lost = 0; } -/* server_default_other_versions is the default other_versions field - sent by server. */ -static uint8_t server_default_other_versions[] = {0, 0, 0, 1}; +/* server_default_available_versions is the default available_versions + field sent by server. */ +static uint8_t server_default_available_versions[] = {0, 0, 0, 1}; /* - * other_versions_new allocates new buffer, and writes |versions| of - * length |versionslen| in network byte order, suitable for sending in - * other_versions field of version_information QUIC transport + * available_versions_new allocates new buffer, and writes |versions| + * of length |versionslen| in network byte order, suitable for sending + * in available_versions field of version_information QUIC transport * parameter. The pointer to the allocated buffer is assigned to * |*pbuf|. * @@ -1006,8 +1019,8 @@ static uint8_t server_default_other_versions[] = {0, 0, 0, 1}; * NGTCP2_ERR_NOMEM * Out of memory. */ -static int other_versions_new(uint8_t **pbuf, const uint32_t *versions, - size_t versionslen, const ngtcp2_mem *mem) { +static int available_versions_new(uint8_t **pbuf, const uint32_t *versions, + size_t versionslen, const ngtcp2_mem *mem) { size_t i; uint8_t *buf = ngtcp2_mem_malloc(mem, sizeof(uint32_t) * versionslen); @@ -1032,16 +1045,13 @@ conn_set_local_transport_params(ngtcp2_conn *conn, *p = *params; - /* grease_quic_bit is always enabled. */ - p->grease_quic_bit = 1; - if (conn->server) { p->version_info.chosen_version = chosen_version; } else { p->version_info.chosen_version = conn->client_chosen_version; } - p->version_info.other_versions = conn->vneg.other_versions; - p->version_info.other_versionslen = conn->vneg.other_versionslen; + p->version_info.available_versions = conn->vneg.available_versions; + p->version_info.available_versionslen = conn->vneg.available_versionslen; p->version_info_present = 1; } @@ -1059,19 +1069,33 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, uint8_t fixed_bit_byte; size_t i; uint32_t *preferred_versions; + ngtcp2_transport_params paramsbuf; (void)callbacks_version; (void)settings_version; - (void)transport_params_version; + + params = ngtcp2_transport_params_convert_to_latest( + ¶msbuf, transport_params_version, params); assert(settings->max_window <= NGTCP2_MAX_VARINT); assert(settings->max_stream_window <= NGTCP2_MAX_VARINT); - assert(settings->max_udp_payload_size); - assert(settings->max_udp_payload_size <= NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE); + assert(settings->max_tx_udp_payload_size); + assert(settings->max_tx_udp_payload_size <= NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE); + assert(settings->initial_pkt_num <= INT32_MAX); + assert(params->active_connection_id_limit >= + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT); assert(params->active_connection_id_limit <= NGTCP2_MAX_DCID_POOL_SIZE); assert(params->initial_max_data <= NGTCP2_MAX_VARINT); assert(params->initial_max_stream_data_bidi_local <= NGTCP2_MAX_VARINT); assert(params->initial_max_stream_data_bidi_remote <= NGTCP2_MAX_VARINT); assert(params->initial_max_stream_data_uni <= NGTCP2_MAX_VARINT); + assert((server && params->original_dcid_present) || + (!server && !params->original_dcid_present)); + assert(!params->initial_scid_present); + assert(server || !params->stateless_reset_token_present); + assert(server || !params->preferred_addr_present); + assert(server || !params->retry_scid_present); + assert(params->max_idle_timeout != UINT64_MAX); + assert(params->max_ack_delay < (1 << 14) * NGTCP2_MILLISECONDS); assert(server || callbacks->client_initial); assert(!server || callbacks->recv_client_initial); assert(callbacks->recv_crypto_data); @@ -1097,6 +1121,8 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, goto fail_conn; } + (*pconn)->server = server; + ngtcp2_objalloc_frame_chain_init(&(*pconn)->frc_objalloc, 64, mem); ngtcp2_objalloc_rtb_entry_init(&(*pconn)->rtb_entry_objalloc, 64, mem); ngtcp2_objalloc_strm_init(&(*pconn)->strm_objalloc, 64, mem); @@ -1125,7 +1151,7 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, ngtcp2_log_init(&(*pconn)->log, scid, settings->log_printf, settings->initial_ts, user_data); - ngtcp2_qlog_init(&(*pconn)->qlog, settings->qlog.write, settings->initial_ts, + ngtcp2_qlog_init(&(*pconn)->qlog, settings->qlog_write, settings->initial_ts, user_data); if ((*pconn)->qlog.write) { buf = ngtcp2_mem_malloc(mem, NGTCP2_QLOG_BUFLEN); @@ -1138,17 +1164,16 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, (*pconn)->local.settings = *settings; - if (settings->token.len) { - buf = ngtcp2_mem_malloc(mem, settings->token.len); + if (settings->tokenlen) { + buf = ngtcp2_mem_malloc(mem, settings->tokenlen); if (buf == NULL) { rv = NGTCP2_ERR_NOMEM; goto fail_token; } - memcpy(buf, settings->token.base, settings->token.len); - (*pconn)->local.settings.token.base = buf; + memcpy(buf, settings->token, settings->tokenlen); + (*pconn)->local.settings.token = buf; } else { - (*pconn)->local.settings.token.base = NULL; - (*pconn)->local.settings.token.len = 0; + (*pconn)->local.settings.token = NULL; } if (!(*pconn)->local.settings.original_version) { @@ -1157,8 +1182,8 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, conn_reset_conn_stat(*pconn, &(*pconn)->cstat); (*pconn)->cstat.initial_rtt = settings->initial_rtt; - (*pconn)->cstat.max_udp_payload_size = - (*pconn)->local.settings.max_udp_payload_size; + (*pconn)->cstat.max_tx_udp_payload_size = + (*pconn)->local.settings.max_tx_udp_payload_size; ngtcp2_rst_init(&(*pconn)->rst); @@ -1166,54 +1191,43 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, switch (settings->cc_algo) { case NGTCP2_CC_ALGO_RENO: - rv = ngtcp2_cc_reno_cc_init(&(*pconn)->cc, &(*pconn)->log, mem); - if (rv != 0) { - goto fail_cc_init; - } + ngtcp2_cc_reno_init(&(*pconn)->reno, &(*pconn)->log); + break; case NGTCP2_CC_ALGO_CUBIC: - rv = ngtcp2_cc_cubic_cc_init(&(*pconn)->cc, &(*pconn)->log, mem); - if (rv != 0) { - goto fail_cc_init; - } + ngtcp2_cc_cubic_init(&(*pconn)->cubic, &(*pconn)->log); + break; case NGTCP2_CC_ALGO_BBR: - rv = ngtcp2_cc_bbr_cc_init(&(*pconn)->cc, &(*pconn)->log, &(*pconn)->cstat, - &(*pconn)->rst, settings->initial_ts, - callbacks->rand, &settings->rand_ctx, mem); - if (rv != 0) { - goto fail_cc_init; - } - break; - case NGTCP2_CC_ALGO_BBR2: - rv = ngtcp2_cc_bbr2_cc_init(&(*pconn)->cc, &(*pconn)->log, &(*pconn)->cstat, - &(*pconn)->rst, settings->initial_ts, - callbacks->rand, &settings->rand_ctx, mem); - if (rv != 0) { - goto fail_cc_init; - } + ngtcp2_cc_bbr_init(&(*pconn)->bbr, &(*pconn)->log, &(*pconn)->cstat, + &(*pconn)->rst, settings->initial_ts, callbacks->rand, + &settings->rand_ctx); + break; default: - assert(0); + ngtcp2_unreachable(); } rv = pktns_new(&(*pconn)->in_pktns, NGTCP2_PKTNS_ID_INITIAL, &(*pconn)->rst, - &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, - &(*pconn)->rtb_entry_objalloc, &(*pconn)->frc_objalloc, mem); + &(*pconn)->cc, settings->initial_pkt_num, &(*pconn)->log, + &(*pconn)->qlog, &(*pconn)->rtb_entry_objalloc, + &(*pconn)->frc_objalloc, mem); if (rv != 0) { goto fail_in_pktns_init; } rv = pktns_new(&(*pconn)->hs_pktns, NGTCP2_PKTNS_ID_HANDSHAKE, &(*pconn)->rst, - &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, - &(*pconn)->rtb_entry_objalloc, &(*pconn)->frc_objalloc, mem); + &(*pconn)->cc, settings->initial_pkt_num, &(*pconn)->log, + &(*pconn)->qlog, &(*pconn)->rtb_entry_objalloc, + &(*pconn)->frc_objalloc, mem); if (rv != 0) { goto fail_hs_pktns_init; } rv = pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APPLICATION, &(*pconn)->rst, - &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, - &(*pconn)->rtb_entry_objalloc, &(*pconn)->frc_objalloc, mem); + &(*pconn)->cc, settings->initial_pkt_num, &(*pconn)->log, + &(*pconn)->qlog, &(*pconn)->rtb_entry_objalloc, + &(*pconn)->frc_objalloc, mem); if (rv != 0) { goto fail_pktns_init; } @@ -1271,56 +1285,63 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, (*pconn)->vneg.preferred_versionslen = settings->preferred_versionslen; } - if (settings->other_versionslen) { + (*pconn)->local.settings.preferred_versions = NULL; + (*pconn)->local.settings.preferred_versionslen = 0; + + if (settings->available_versionslen) { if (!server && !ngtcp2_is_reserved_version(client_chosen_version)) { - for (i = 0; i < settings->other_versionslen; ++i) { - if (settings->other_versions[i] == client_chosen_version) { + for (i = 0; i < settings->available_versionslen; ++i) { + if (settings->available_versions[i] == client_chosen_version) { break; } } - assert(i < settings->other_versionslen); + assert(i < settings->available_versionslen); } - for (i = 0; i < settings->other_versionslen; ++i) { - assert(ngtcp2_is_reserved_version(settings->other_versions[i]) || - ngtcp2_is_supported_version(settings->other_versions[i])); + for (i = 0; i < settings->available_versionslen; ++i) { + assert(ngtcp2_is_reserved_version(settings->available_versions[i]) || + ngtcp2_is_supported_version(settings->available_versions[i])); } - rv = other_versions_new(&buf, settings->other_versions, - settings->other_versionslen, mem); + rv = available_versions_new(&buf, settings->available_versions, + settings->available_versionslen, mem); if (rv != 0) { - goto fail_other_versions; + goto fail_available_versions; } - (*pconn)->vneg.other_versions = buf; - (*pconn)->vneg.other_versionslen = - sizeof(uint32_t) * settings->other_versionslen; + (*pconn)->vneg.available_versions = buf; + (*pconn)->vneg.available_versionslen = + sizeof(uint32_t) * settings->available_versionslen; } else if (server) { if (settings->preferred_versionslen) { - rv = other_versions_new(&buf, settings->preferred_versions, - settings->preferred_versionslen, mem); + rv = available_versions_new(&buf, settings->preferred_versions, + settings->preferred_versionslen, mem); if (rv != 0) { - goto fail_other_versions; + goto fail_available_versions; } - (*pconn)->vneg.other_versions = buf; - (*pconn)->vneg.other_versionslen = + (*pconn)->vneg.available_versions = buf; + (*pconn)->vneg.available_versionslen = sizeof(uint32_t) * settings->preferred_versionslen; } else { - (*pconn)->vneg.other_versions = server_default_other_versions; - (*pconn)->vneg.other_versionslen = sizeof(server_default_other_versions); + (*pconn)->vneg.available_versions = server_default_available_versions; + (*pconn)->vneg.available_versionslen = + sizeof(server_default_available_versions); } } else if (!server && !ngtcp2_is_reserved_version(client_chosen_version)) { - rv = other_versions_new(&buf, &client_chosen_version, 1, mem); + rv = available_versions_new(&buf, &client_chosen_version, 1, mem); if (rv != 0) { - goto fail_other_versions; + goto fail_available_versions; } - (*pconn)->vneg.other_versions = buf; - (*pconn)->vneg.other_versionslen = sizeof(uint32_t); + (*pconn)->vneg.available_versions = buf; + (*pconn)->vneg.available_versionslen = sizeof(uint32_t); } + (*pconn)->local.settings.available_versions = NULL; + (*pconn)->local.settings.available_versionslen = 0; + (*pconn)->client_chosen_version = client_chosen_version; conn_set_local_transport_params(*pconn, params); @@ -1331,8 +1352,8 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, } (*pconn)->keep_alive.last_ts = UINT64_MAX; + (*pconn)->keep_alive.timeout = UINT64_MAX; - (*pconn)->server = server; (*pconn)->oscid = *scid; (*pconn)->callbacks = *callbacks; (*pconn)->mem = mem; @@ -1341,16 +1362,22 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, (*pconn)->crypto.key_update.confirmed_ts = UINT64_MAX; (*pconn)->tx.last_max_data_ts = UINT64_MAX; (*pconn)->tx.pacing.next_ts = UINT64_MAX; + (*pconn)->tx.last_blocked_offset = UINT64_MAX; (*pconn)->early.discard_started_ts = UINT64_MAX; conn_reset_ecn_validation_state(*pconn); - ngtcp2_qlog_start(&(*pconn)->qlog, server ? &settings->qlog.odcid : dcid, - server); + ngtcp2_qlog_start( + &(*pconn)->qlog, + server ? ((*pconn)->local.transport_params.retry_scid_present + ? &(*pconn)->local.transport_params.retry_scid + : &(*pconn)->local.transport_params.original_dcid) + : dcid, + server); return 0; -fail_other_versions: +fail_available_versions: ngtcp2_mem_free(mem, (*pconn)->vneg.preferred_versions); fail_preferred_versions: fail_seqgap_push: @@ -1363,9 +1390,7 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, fail_hs_pktns_init: pktns_del((*pconn)->in_pktns, mem); fail_in_pktns_init: - cc_del(&(*pconn)->cc, settings->cc_algo, mem); -fail_cc_init: - ngtcp2_mem_free(mem, (*pconn)->local.settings.token.base); + ngtcp2_mem_free(mem, (uint8_t *)(*pconn)->local.settings.token); fail_token: ngtcp2_mem_free(mem, (*pconn)->qlog.buf.begin); fail_qlog_buf: @@ -1432,7 +1457,7 @@ int ngtcp2_conn_server_new_versioned( (*pconn)->local.bidi.next_stream_id = 1; (*pconn)->local.uni.next_stream_id = 3; - if ((*pconn)->local.settings.token.len) { + if ((*pconn)->local.settings.tokenlen) { /* Usage of token lifts amplification limit */ (*pconn)->dcid.current.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED; } @@ -1558,13 +1583,13 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { conn_vneg_crypto_free(conn); ngtcp2_mem_free(conn->mem, conn->vneg.preferred_versions); - if (conn->vneg.other_versions != server_default_other_versions) { - ngtcp2_mem_free(conn->mem, conn->vneg.other_versions); + if (conn->vneg.available_versions != server_default_available_versions) { + ngtcp2_mem_free(conn->mem, conn->vneg.available_versions); } ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_buf.base); ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_hp_buf.base); - ngtcp2_mem_free(conn->mem, conn->local.settings.token.base); + ngtcp2_mem_free(conn->mem, (uint8_t *)conn->local.settings.token); ngtcp2_crypto_km_del(conn->crypto.key_update.old_rx_ckm, conn->mem); ngtcp2_crypto_km_del(conn->crypto.key_update.new_rx_ckm, conn->mem); @@ -1575,14 +1600,12 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { pktns_del(conn->hs_pktns, conn->mem); pktns_del(conn->in_pktns, conn->mem); - cc_del(&conn->cc, conn->cc_algo, conn->mem); - ngtcp2_mem_free(conn->mem, conn->qlog.buf.begin); ngtcp2_pmtud_del(conn->pmtud); ngtcp2_pv_del(conn->pv); - ngtcp2_mem_free(conn->mem, conn->rx.ccerr.reason); + ngtcp2_mem_free(conn->mem, (uint8_t *)conn->rx.ccerr.reason); ngtcp2_idtr_free(&conn->remote.uni.idtr); ngtcp2_idtr_free(&conn->remote.bidi.idtr); @@ -1604,8 +1627,8 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { } /* - * conn_ensure_ack_blks makes sure that conn->tx.ack->ack.blks can - * contain at least |n| additional ngtcp2_ack_blk. + * conn_ensure_ack_ranges makes sure that conn->tx.ack->ack.ranges can + * contain at least |n| additional ngtcp2_ack_range. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -1613,9 +1636,9 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { * NGTCP2_ERR_NOMEM * Out of memory. */ -static int conn_ensure_ack_blks(ngtcp2_conn *conn, size_t n) { +static int conn_ensure_ack_ranges(ngtcp2_conn *conn, size_t n) { ngtcp2_frame *fr; - size_t max = conn->tx.max_ack_blks; + size_t max = conn->tx.max_ack_ranges; if (n <= max) { return 0; @@ -1626,13 +1649,13 @@ static int conn_ensure_ack_blks(ngtcp2_conn *conn, size_t n) { assert(max >= n); fr = ngtcp2_mem_realloc(conn->mem, conn->tx.ack, - sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_blk) * max); + sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_range) * max); if (fr == NULL) { return NGTCP2_ERR_NOMEM; } conn->tx.ack = fr; - conn->tx.max_ack_blks = max; + conn->tx.max_ack_ranges = max; return 0; } @@ -1646,40 +1669,20 @@ static ngtcp2_duration conn_compute_ack_delay(ngtcp2_conn *conn) { conn->cstat.smoothed_rtt / 8); } -/* - * conn_create_ack_frame creates ACK frame, and assigns its pointer to - * |*pfr| if there are any received packets to acknowledge. If there - * are no packets to acknowledge, this function returns 0, and |*pfr| - * is untouched. The caller is advised to set |*pfr| to NULL before - * calling this function, and check it after this function returns. - * If |nodelay| is nonzero, delayed ACK timer is ignored. - * - * The memory for ACK frame is dynamically allocated by this function. - * A caller is responsible to free it. - * - * Call ngtcp2_acktr_commit_ack after a created ACK frame is - * successfully serialized into a packet. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. - */ -static int conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, +int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, ngtcp2_pktns *pktns, uint8_t type, ngtcp2_tstamp ts, ngtcp2_duration ack_delay, uint64_t ack_delay_exponent) { /* TODO Measure an actual size of ACK blocks to find the best default value. */ - const size_t initial_max_ack_blks = 8; + const size_t initial_max_ack_ranges = 8; int64_t last_pkt_num; ngtcp2_acktr *acktr = &pktns->acktr; - ngtcp2_ack_blk *blk; + ngtcp2_ack_range *range; ngtcp2_ksl_it it; ngtcp2_acktr_entry *rpkt; ngtcp2_ack *ack; - size_t blk_idx; + size_t range_idx; ngtcp2_tstamp largest_ack_ts; int rv; @@ -1700,11 +1703,11 @@ static int conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, if (conn->tx.ack == NULL) { conn->tx.ack = ngtcp2_mem_malloc( conn->mem, - sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_blk) * initial_max_ack_blks); + sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_range) * initial_max_ack_ranges); if (conn->tx.ack == NULL) { return NGTCP2_ERR_NOMEM; } - conn->tx.max_ack_blks = initial_max_ack_blks; + conn->tx.max_ack_ranges = initial_max_ack_ranges; } ack = &conn->tx.ack->ack; @@ -1717,7 +1720,7 @@ static int conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, } else { ack->type = NGTCP2_FRAME_ACK; } - ack->num_blks = 0; + ack->rangecnt = 0; rpkt = ngtcp2_ksl_it_get(&it); @@ -1725,7 +1728,14 @@ static int conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); largest_ack_ts = rpkt->tstamp; ack->largest_ack = rpkt->pkt_num; - ack->first_ack_blklen = rpkt->len - 1; + ack->first_ack_range = rpkt->len - 1; + + ngtcp2_ksl_it_next(&it); + } else if (rpkt->pkt_num + 1 == pktns->rx.max_pkt_num) { + last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); + largest_ack_ts = pktns->rx.max_pkt_ts; + ack->largest_ack = pktns->rx.max_pkt_num; + ack->first_ack_range = rpkt->len; ngtcp2_ksl_it_next(&it); } else { @@ -1734,7 +1744,7 @@ static int conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, last_pkt_num = pktns->rx.max_pkt_num; largest_ack_ts = pktns->rx.max_pkt_ts; ack->largest_ack = pktns->rx.max_pkt_num; - ack->first_ack_blklen = 0; + ack->first_ack_range = 0; } if (type == NGTCP2_PKT_1RTT) { @@ -1747,21 +1757,21 @@ static int conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, } for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) { - if (ack->num_blks == NGTCP2_MAX_ACK_BLKS) { + if (ack->rangecnt == NGTCP2_MAX_ACK_RANGES) { break; } rpkt = ngtcp2_ksl_it_get(&it); - blk_idx = ack->num_blks++; - rv = conn_ensure_ack_blks(conn, ack->num_blks); + range_idx = ack->rangecnt++; + rv = conn_ensure_ack_ranges(conn, ack->rangecnt); if (rv != 0) { return rv; } ack = &conn->tx.ack->ack; - blk = &ack->blks[blk_idx]; - blk->gap = (uint64_t)(last_pkt_num - rpkt->pkt_num - 2); - blk->blklen = rpkt->len - 1; + range = &ack->ranges[range_idx]; + range->gap = (uint64_t)(last_pkt_num - rpkt->pkt_num - 2); + range->len = rpkt->len - 1; last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); } @@ -1888,7 +1898,7 @@ static size_t pktns_select_pkt_numlen(ngtcp2_pktns *pktns) { */ static uint64_t conn_get_cwnd(ngtcp2_conn *conn) { return conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) - ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_udp_payload_size) + ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_tx_udp_payload_size) : conn->cstat.cwnd; } @@ -1896,12 +1906,12 @@ static uint64_t conn_get_cwnd(ngtcp2_conn *conn) { * conn_cwnd_is_zero returns nonzero if the number of bytes the local * endpoint can sent at this time is zero. */ -static uint64_t conn_cwnd_is_zero(ngtcp2_conn *conn) { +static int conn_cwnd_is_zero(ngtcp2_conn *conn) { uint64_t bytes_in_flight = conn->cstat.bytes_in_flight; uint64_t cwnd = conn_get_cwnd(conn); if (bytes_in_flight >= cwnd) { - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, "cwnd limited bytes_in_flight=%lu cwnd=%lu", bytes_in_flight, cwnd); } @@ -1943,349 +1953,6 @@ static uint64_t conn_retry_early_payloadlen(ngtcp2_conn *conn) { return 0; } -static void conn_cryptofrq_clear(ngtcp2_conn *conn, ngtcp2_pktns *pktns) { - ngtcp2_frame_chain *frc; - ngtcp2_ksl_it it; - - for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it); - ngtcp2_ksl_it_next(&it)) { - frc = ngtcp2_ksl_it_get(&it); - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - } - ngtcp2_ksl_clear(&pktns->crypto.tx.frq); -} - -/* - * conn_cryptofrq_unacked_offset returns the CRYPTO frame offset by - * taking into account acknowledged offset. If there is no data to - * send, this function returns (uint64_t)-1. - */ -static uint64_t conn_cryptofrq_unacked_offset(ngtcp2_conn *conn, - ngtcp2_pktns *pktns) { - ngtcp2_frame_chain *frc; - ngtcp2_crypto *fr; - ngtcp2_range gap; - ngtcp2_rtb *rtb = &pktns->rtb; - ngtcp2_ksl_it it; - uint64_t datalen; - - (void)conn; - - for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it); - ngtcp2_ksl_it_next(&it)) { - frc = ngtcp2_ksl_it_get(&it); - fr = &frc->fr.crypto; - - gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, fr->offset); - - datalen = ngtcp2_vec_len(fr->data, fr->datacnt); - - if (gap.begin <= fr->offset) { - return fr->offset; - } - if (gap.begin < fr->offset + datalen) { - return gap.begin; - } - } - - return (uint64_t)-1; -} - -static int conn_cryptofrq_unacked_pop(ngtcp2_conn *conn, ngtcp2_pktns *pktns, - ngtcp2_frame_chain **pfrc) { - ngtcp2_frame_chain *frc, *nfrc; - ngtcp2_crypto *fr, *nfr; - uint64_t offset, end_offset; - size_t idx, end_idx; - uint64_t base_offset, end_base_offset; - ngtcp2_range gap; - ngtcp2_rtb *rtb = &pktns->rtb; - ngtcp2_vec *v; - int rv; - ngtcp2_ksl_it it; - - *pfrc = NULL; - - for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it);) { - frc = ngtcp2_ksl_it_get(&it); - fr = &frc->fr.crypto; - - ngtcp2_ksl_remove_hint(&pktns->crypto.tx.frq, &it, &it, &fr->offset); - - idx = 0; - offset = fr->offset; - base_offset = 0; - - gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, offset); - if (gap.begin < offset) { - gap.begin = offset; - } - - for (; idx < fr->datacnt && offset < gap.begin; ++idx) { - v = &fr->data[idx]; - if (offset + v->len > gap.begin) { - base_offset = gap.begin - offset; - break; - } - - offset += v->len; - } - - if (idx == fr->datacnt) { - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - continue; - } - - assert(gap.begin == offset + base_offset); - - end_idx = idx; - end_offset = offset; - end_base_offset = 0; - - for (; end_idx < fr->datacnt; ++end_idx) { - v = &fr->data[end_idx]; - if (end_offset + v->len > gap.end) { - end_base_offset = gap.end - end_offset; - break; - } - - end_offset += v->len; - } - - if (fr->offset == offset && base_offset == 0 && fr->datacnt == end_idx) { - *pfrc = frc; - return 0; - } - - if (fr->datacnt == end_idx) { - memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx)); - - assert(fr->data[0].len > base_offset); - - fr->offset = offset + base_offset; - fr->datacnt = end_idx - idx; - fr->data[0].base += base_offset; - fr->data[0].len -= (size_t)base_offset; - - *pfrc = frc; - return 0; - } - - rv = ngtcp2_frame_chain_crypto_datacnt_objalloc_new( - &nfrc, fr->datacnt - end_idx, &conn->frc_objalloc, conn->mem); - if (rv != 0) { - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - - nfr = &nfrc->fr.crypto; - nfr->type = NGTCP2_FRAME_CRYPTO; - memcpy(nfr->data, fr->data + end_idx, - sizeof(nfr->data[0]) * (fr->datacnt - end_idx)); - - assert(nfr->data[0].len > end_base_offset); - - nfr->offset = end_offset + end_base_offset; - nfr->datacnt = fr->datacnt - end_idx; - nfr->data[0].base += end_base_offset; - nfr->data[0].len -= (size_t)end_base_offset; - - rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - ngtcp2_frame_chain_objalloc_del(nfrc, &conn->frc_objalloc, conn->mem); - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - - if (end_base_offset) { - ++end_idx; - } - - memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx)); - - assert(fr->data[0].len > base_offset); - - fr->offset = offset + base_offset; - fr->datacnt = end_idx - idx; - if (end_base_offset) { - assert(fr->data[fr->datacnt - 1].len > end_base_offset); - fr->data[fr->datacnt - 1].len = (size_t)end_base_offset; - } - fr->data[0].base += base_offset; - fr->data[0].len -= (size_t)base_offset; - - *pfrc = frc; - return 0; - } - - return 0; -} -static int conn_cryptofrq_pop(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc, - ngtcp2_pktns *pktns, size_t left) { - ngtcp2_crypto *fr, *nfr; - ngtcp2_frame_chain *frc, *nfrc; - int rv; - size_t nmerged; - uint64_t datalen; - ngtcp2_vec a[NGTCP2_MAX_CRYPTO_DATACNT]; - ngtcp2_vec b[NGTCP2_MAX_CRYPTO_DATACNT]; - size_t acnt, bcnt; - ngtcp2_ksl_it it; - - rv = conn_cryptofrq_unacked_pop(conn, pktns, &frc); - if (rv != 0) { - return rv; - } - if (frc == NULL) { - *pfrc = NULL; - return 0; - } - - fr = &frc->fr.crypto; - datalen = ngtcp2_vec_len(fr->data, fr->datacnt); - - if (datalen > left) { - ngtcp2_vec_copy(a, fr->data, fr->datacnt); - acnt = fr->datacnt; - - bcnt = 0; - ngtcp2_vec_split(a, &acnt, b, &bcnt, left, NGTCP2_MAX_CRYPTO_DATACNT); - - assert(acnt > 0); - assert(bcnt > 0); - - rv = ngtcp2_frame_chain_crypto_datacnt_objalloc_new( - &nfrc, bcnt, &conn->frc_objalloc, conn->mem); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - - nfr = &nfrc->fr.crypto; - nfr->type = NGTCP2_FRAME_CRYPTO; - nfr->offset = fr->offset + left; - nfr->datacnt = bcnt; - ngtcp2_vec_copy(nfr->data, b, bcnt); - - rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - ngtcp2_frame_chain_objalloc_del(nfrc, &conn->frc_objalloc, conn->mem); - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - - rv = ngtcp2_frame_chain_crypto_datacnt_objalloc_new( - &nfrc, acnt, &conn->frc_objalloc, conn->mem); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - - nfr = &nfrc->fr.crypto; - *nfr = *fr; - nfr->datacnt = acnt; - ngtcp2_vec_copy(nfr->data, a, acnt); - - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - - *pfrc = nfrc; - - return 0; - } - - left -= (size_t)datalen; - - ngtcp2_vec_copy(a, fr->data, fr->datacnt); - acnt = fr->datacnt; - - for (; left && ngtcp2_ksl_len(&pktns->crypto.tx.frq);) { - it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); - nfrc = ngtcp2_ksl_it_get(&it); - nfr = &nfrc->fr.crypto; - - if (nfr->offset != fr->offset + datalen) { - assert(fr->offset + datalen < nfr->offset); - break; - } - - rv = conn_cryptofrq_unacked_pop(conn, pktns, &nfrc); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - if (nfrc == NULL) { - break; - } - - nfr = &nfrc->fr.crypto; - - nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &nfr->datacnt, left, - NGTCP2_MAX_CRYPTO_DATACNT); - if (nmerged == 0) { - rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - ngtcp2_frame_chain_objalloc_del(nfrc, &conn->frc_objalloc, conn->mem); - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - break; - } - - datalen += nmerged; - left -= nmerged; - - if (nfr->datacnt == 0) { - ngtcp2_frame_chain_objalloc_del(nfrc, &conn->frc_objalloc, conn->mem); - continue; - } - - nfr->offset += nmerged; - - rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc); - if (rv != 0) { - ngtcp2_frame_chain_objalloc_del(nfrc, &conn->frc_objalloc, conn->mem); - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - - break; - } - - if (acnt == fr->datacnt) { - assert(acnt > 0); - fr->data[acnt - 1] = a[acnt - 1]; - - *pfrc = frc; - return 0; - } - - assert(acnt > fr->datacnt); - - rv = ngtcp2_frame_chain_crypto_datacnt_objalloc_new( - &nfrc, acnt, &conn->frc_objalloc, conn->mem); - if (rv != 0) { - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - - nfr = &nfrc->fr.crypto; - *nfr = *fr; - nfr->datacnt = acnt; - ngtcp2_vec_copy(nfr->data, a, acnt); - - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - - *pfrc = nfrc; - - return 0; -} - /* * conn_verify_dcid verifies that destination connection ID in |hd| is * valid for the connection. If it is successfully verified and the @@ -2341,7 +2008,7 @@ static int conn_verify_dcid(ngtcp2_conn *conn, int *pnew_cid_used, * conn_should_pad_pkt returns nonzero if the packet should be padded. * |type| is the type of packet. |left| is the space left in packet * buffer. |write_datalen| is the number of bytes which will be sent - * in the next, coalesced 0-RTT or 1RTT packet. + * in the next, coalesced 0-RTT packet. */ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, uint64_t write_datalen, int ack_eliciting, @@ -2356,7 +2023,7 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, if (conn->hs_pktns->crypto.tx.ckm && (conn->hs_pktns->rtb.probe_pkt_left || - ngtcp2_ksl_len(&conn->hs_pktns->crypto.tx.frq) || + !ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm) || !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) { /* If we have something to send in Handshake packet, then add PADDING in Handshake packet. */ @@ -2367,20 +2034,19 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, } else { if (conn->hs_pktns->crypto.tx.ckm && (conn->hs_pktns->rtb.probe_pkt_left || - ngtcp2_ksl_len(&conn->hs_pktns->crypto.tx.frq) || + !ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm) || !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) { /* If we have something to send in Handshake packet, then add PADDING in Handshake packet. */ min_payloadlen = NGTCP2_MIN_COALESCED_PAYLOADLEN; - } else if ((!conn->early.ckm && !conn->pktns.crypto.tx.ckm) || - write_datalen == 0) { - return 1; - } else { - /* If we have something to send in 0RTT or 1RTT packet, then - add PADDING in that packet. Take maximum in case that + } else if (conn->early.ckm && write_datalen > 0) { + /* If we have something to send in 0RTT packet, then add + PADDING in that packet. Take maximum in case that write_datalen includes DATAGRAM which cannot be split. */ min_payloadlen = ngtcp2_max(write_datalen, NGTCP2_MIN_COALESCED_PAYLOADLEN); + } else { + return 1; } } } else { @@ -2390,11 +2056,11 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, return 0; } - if (!conn->pktns.crypto.tx.ckm || write_datalen == 0) { + if (!conn->pktns.crypto.tx.ckm) { return 1; } - min_payloadlen = ngtcp2_max(write_datalen, NGTCP2_MIN_COALESCED_PAYLOADLEN); + min_payloadlen = NGTCP2_MIN_COALESCED_PAYLOADLEN; } /* TODO the next packet type should be taken into account */ @@ -2419,7 +2085,8 @@ static void conn_restart_timer_on_read(ngtcp2_conn *conn, ngtcp2_tstamp ts) { * conn_keep_alive_enabled returns nonzero if keep-alive is enabled. */ static int conn_keep_alive_enabled(ngtcp2_conn *conn) { - return conn->keep_alive.last_ts != UINT64_MAX && conn->keep_alive.timeout; + return conn->keep_alive.last_ts != UINT64_MAX && + conn->keep_alive.timeout != UINT64_MAX; } /* @@ -2427,8 +2094,8 @@ static int conn_keep_alive_enabled(ngtcp2_conn *conn) { * expired. */ static int conn_keep_alive_expired(ngtcp2_conn *conn, ngtcp2_tstamp ts) { - return conn_keep_alive_enabled(conn) && - conn->keep_alive.last_ts + conn->keep_alive.timeout <= ts; + return ngtcp2_tstamp_elapsed(conn->keep_alive.last_ts, + conn->keep_alive.timeout, ts); } /* @@ -2436,7 +2103,9 @@ static int conn_keep_alive_expired(ngtcp2_conn *conn, ngtcp2_tstamp ts) { */ static ngtcp2_tstamp conn_keep_alive_expiry(ngtcp2_conn *conn) { if ((conn->flags & NGTCP2_CONN_FLAG_KEEP_ALIVE_CANCELLED) || - !conn_keep_alive_enabled(conn)) { + !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) || + !conn_keep_alive_enabled(conn) || + conn->keep_alive.last_ts >= UINT64_MAX - conn->keep_alive.timeout) { return UINT64_MAX; } @@ -2467,6 +2136,10 @@ static void conn_update_keep_alive_last_ts(ngtcp2_conn *conn, void ngtcp2_conn_set_keep_alive_timeout(ngtcp2_conn *conn, ngtcp2_duration timeout) { + if (timeout == 0) { + timeout = UINT64_MAX; + } + conn->keep_alive.timeout = timeout; } @@ -2527,7 +2200,7 @@ static uint8_t conn_pkt_flags_short(ngtcp2_conn *conn) { * NGTCP2_PKT_HANDSHAKE_PKT. * * |write_datalen| is the minimum length of application data ready to - * send in subsequent 0RTT or 1RTT packet. + * send in subsequent 0RTT packet. * * This function returns the number of bytes written in |dest| if it * succeeds, or one of the following negative error codes: @@ -2590,8 +2263,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, cc.hp_ctx = pktns->crypto.tx.hp_ctx; break; default: - assert(0); - abort(); + ngtcp2_unreachable(); } cc.aead = pktns->crypto.ctx.aead; @@ -2605,8 +2277,9 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, version, 0); if (!conn->server && type == NGTCP2_PKT_INITIAL && - conn->local.settings.token.len) { + conn->local.settings.tokenlen) { hd.token = conn->local.settings.token; + hd.tokenlen = conn->local.settings.tokenlen; } ngtcp2_ppe_init(&ppe, dest, destlen, &cc); @@ -2621,9 +2294,9 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, return 0; } - rv = conn_create_ack_frame(conn, &ackfr, pktns, type, ts, - /* ack_delay = */ 0, - NGTCP2_DEFAULT_ACK_DELAY_EXPONENT); + rv = ngtcp2_conn_create_ack_frame(conn, &ackfr, pktns, type, ts, + /* ack_delay = */ 0, + NGTCP2_DEFAULT_ACK_DELAY_EXPONENT); if (rv != 0) { ngtcp2_frame_chain_list_objalloc_del(frq, &conn->frc_objalloc, conn->mem); return rv; @@ -2645,12 +2318,12 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, if (!conn->server || type != NGTCP2_PKT_INITIAL || destlen >= NGTCP2_MAX_UDP_PAYLOAD_SIZE) { build_pkt: - for (; ngtcp2_ksl_len(&pktns->crypto.tx.frq);) { + for (; !ngtcp2_strm_streamfrq_empty(&pktns->crypto.strm);) { left = ngtcp2_ppe_left(&ppe); - crypto_offset = conn_cryptofrq_unacked_offset(conn, pktns); - if (crypto_offset == (size_t)-1) { - conn_cryptofrq_clear(conn, pktns); + crypto_offset = ngtcp2_strm_streamfrq_unacked_offset(&pktns->crypto.strm); + if (crypto_offset == (uint64_t)-1) { + ngtcp2_strm_streamfrq_clear(&pktns->crypto.strm); break; } @@ -2659,7 +2332,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, break; } - rv = conn_cryptofrq_pop(conn, &nfrc, pktns, left); + rv = ngtcp2_strm_streamfrq_pop(&pktns->crypto.strm, &nfrc, left); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); ngtcp2_frame_chain_list_objalloc_del(frq, &conn->frc_objalloc, @@ -2673,7 +2346,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &nfrc->fr); if (rv != 0) { - assert(0); + ngtcp2_unreachable(); } *pfrc = nfrc; @@ -2729,9 +2402,8 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, if (!pkt_empty) { if (!(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { - /* The intention of smaller limit is get more chance to measure - RTT samples in early phase. */ - if (pktns->tx.num_non_ack_pkt >= 1) { + if (ngtcp2_tstamp_elapsed(pktns->tx.non_ack_pkt_start_ts, + conn->cstat.smoothed_rtt, ts)) { lfr.type = NGTCP2_FRAME_PING; rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &lfr); @@ -2739,18 +2411,18 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, assert(rv == NGTCP2_ERR_NOBUF); } else { rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING; - pktns->tx.num_non_ack_pkt = 0; + pktns->tx.non_ack_pkt_start_ts = UINT64_MAX; } - } else { - ++pktns->tx.num_non_ack_pkt; + } else if (pktns->tx.non_ack_pkt_start_ts == UINT64_MAX) { + pktns->tx.non_ack_pkt_start_ts = ts; } } else { - pktns->tx.num_non_ack_pkt = 0; + pktns->tx.non_ack_pkt_start_ts = UINT64_MAX; } } } - if (pkt_empty) { + if (pkt_empty && !require_padding) { return 0; } @@ -2762,6 +2434,8 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, require_padding)) { lfr.type = NGTCP2_FRAME_PADDING; lfr.padding.len = ngtcp2_ppe_padding(&ppe); + } else if (pkt_empty) { + return 0; } else { lfr.type = NGTCP2_FRAME_PADDING; lfr.padding.len = ngtcp2_ppe_padding_hp_sample(&ppe); @@ -2872,8 +2546,7 @@ static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, ack_delay_exponent = conn->local.transport_params.ack_delay_exponent; break; default: - assert(0); - abort(); + ngtcp2_unreachable(); } if (!pktns->crypto.tx.ckm) { @@ -2881,8 +2554,8 @@ static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } ackfr = NULL; - rv = conn_create_ack_frame(conn, &ackfr, pktns, type, ts, ack_delay, - ack_delay_exponent); + rv = ngtcp2_conn_create_ack_frame(conn, &ackfr, pktns, type, ts, ack_delay, + ack_delay_exponent); if (rv != 0) { return rv; } @@ -2992,11 +2665,11 @@ static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn, ngtcp2_ssize res = 0, nwrite = 0; /* In the most cases, client sends ACK in conn_write_handshake_pkt. - This function is only called when it is CWND limited. It is not - required for client to send ACK for server Initial. This is - because once it gets server Initial, it gets Handshake tx key and - discards Initial key. The only good reason to send ACK is give - server RTT measurement early. */ + This function is only called when it is CWND limited or pacing + limited. It is not required for client to send ACK for server + Initial. This is because once it gets server Initial, it gets + Handshake tx key and discards Initial key. The only good reason + to send ACK is give server RTT measurement early. */ if (conn->server && conn->in_pktns) { nwrite = conn_write_ack_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, ts); @@ -3145,13 +2818,14 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, } if (nwrite == 0) { - if (conn->server && (conn->in_pktns->rtb.probe_pkt_left || - ngtcp2_ksl_len(&conn->in_pktns->crypto.tx.frq))) { + if (conn->server && + (conn->in_pktns->rtb.probe_pkt_left || + !ngtcp2_strm_streamfrq_empty(&conn->in_pktns->crypto.strm))) { if (cstat->loss_detection_timer != UINT64_MAX && conn_server_tx_left(conn, &conn->dcid.current) < NGTCP2_MAX_UDP_PAYLOAD_SIZE) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_RCV, + &conn->log, NGTCP2_LOG_EVENT_LDC, "loss detection timer canceled due to amplification limit"); cstat->loss_detection_timer = UINT64_MAX; } @@ -3252,11 +2926,19 @@ static int conn_should_send_max_data(ngtcp2_conn *conn) { static size_t conn_required_num_new_connection_id(ngtcp2_conn *conn) { uint64_t n; size_t len = ngtcp2_ksl_len(&conn->scid.set); + size_t lim; if (len >= NGTCP2_MAX_SCID_POOL_SIZE) { return 0; } + assert(NGTCP2_MAX_SCID_POOL_SIZE >= conn->scid.num_in_flight); + + lim = NGTCP2_MAX_SCID_POOL_SIZE - conn->scid.num_in_flight; + if (lim == 0) { + return 0; + } + assert(conn->remote.transport_params); assert(conn->remote.transport_params->active_connection_id_limit); @@ -3266,7 +2948,9 @@ static size_t conn_required_num_new_connection_id(ngtcp2_conn *conn) { n = conn->remote.transport_params->active_connection_id_limit + conn->scid.num_retired; - return (size_t)ngtcp2_min(NGTCP2_MAX_SCID_POOL_SIZE, n) - len; + n = ngtcp2_min(NGTCP2_MAX_SCID_POOL_SIZE, n) - len; + + return (size_t)ngtcp2_min(lim, n); } /* @@ -3338,6 +3022,10 @@ static int conn_enqueue_new_connection_id(ngtcp2_conn *conn) { sizeof(token)); nfrc->next = pktns->tx.frq; pktns->tx.frq = nfrc; + + assert(NGTCP2_MAX_SCID_POOL_SIZE > conn->scid.num_in_flight); + + ++conn->scid.num_in_flight; } return 0; @@ -3368,7 +3056,7 @@ static int conn_remove_retired_connection_id(ngtcp2_conn *conn, for (; !ngtcp2_pq_empty(&conn->scid.used);) { scid = ngtcp2_struct_of(ngtcp2_pq_top(&conn->scid.used), ngtcp2_scid, pe); - if (scid->retired_ts == UINT64_MAX || scid->retired_ts + timeout >= ts) { + if (!ngtcp2_tstamp_elapsed(scid->retired_ts, timeout, ts)) { break; } @@ -3435,6 +3123,36 @@ static void conn_handle_unconfirmed_key_update_from_remote(ngtcp2_conn *conn, ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CRY, "key update confirmed"); } +static uint64_t conn_tx_strmq_first_cycle(ngtcp2_conn *conn); + +/* + * strm_should_send_stream_data_blocked returns nonzero if + * STREAM_DATA_BLOCKED frame should be sent to |strm|. + */ +static int strm_should_send_stream_data_blocked(ngtcp2_strm *strm) { + return strm->tx.offset == strm->tx.max_offset && + strm->tx.last_blocked_offset != strm->tx.max_offset; +} + +/* + * conn_should_send_data_blocked returns nonzero if DATA_BLOCKED frame + * should be sent. + */ +static int conn_should_send_data_blocked(ngtcp2_conn *conn) { + return conn->tx.offset == conn->tx.max_offset && + conn->tx.last_blocked_offset != conn->tx.max_offset; +} + +/* + * conn_reset_ppe_pending clears NGTCP2_CONN_FLAG_PPE_PENDING flag and + * nullifies conn->pkt. + */ +static void conn_reset_ppe_pending(ngtcp2_conn *conn) { + conn->flags &= (uint32_t)~NGTCP2_CONN_FLAG_PPE_PENDING; + + memset(&conn->pkt, 0, sizeof(conn->pkt)); +} + /* * conn_write_pkt writes a protected packet in the buffer pointed by * |dest| whose length if |destlen|. |type| specifies the type of @@ -3550,8 +3268,12 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, /* transport parameter is only valid after handshake completion which means we don't know how many connection ID that remote - peer can accept before handshake completion. */ - if (conn->oscid.datalen && conn_is_handshake_completed(conn)) { + peer can accept before handshake completion. Because server + can use remote transport parameters sending stream data in + 0.5 RTT, it is also allowed to use remote transport + parameters here. */ + if (conn->oscid.datalen && + (conn->server || conn_is_tls_handshake_completed(conn))) { rv = conn_enqueue_new_connection_id(conn); if (rv != 0) { return rv; @@ -3574,7 +3296,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, break; default: /* Unreachable */ - assert(0); + ngtcp2_unreachable(); } cc->encrypt = conn->callbacks.encrypt; @@ -3617,6 +3339,32 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, nfrc->fr.max_data.max_data; } + if (stream_blocked && conn_should_send_max_data(conn)) { + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); + if (rv != 0) { + return rv; + } + + nfrc->fr.type = NGTCP2_FRAME_DATA_BLOCKED; + nfrc->fr.data_blocked.offset = conn->tx.max_offset; + nfrc->next = pktns->tx.frq; + pktns->tx.frq = nfrc; + + conn->tx.last_blocked_offset = conn->tx.max_offset; + } + + if (stream_blocked && !ngtcp2_strm_is_tx_queued(vmsg->stream.strm) && + strm_should_send_stream_data_blocked(vmsg->stream.strm)) { + assert(vmsg); + assert(vmsg->type == NGTCP2_VMSG_TYPE_STREAM); + + vmsg->stream.strm->cycle = conn_tx_strmq_first_cycle(conn); + rv = ngtcp2_conn_tx_strmq_push(conn, vmsg->stream.strm); + if (rv != 0) { + return rv; + } + } + ngtcp2_pkt_hd_init(hd, hd_flags, type, &conn->dcid.current.cid, scid, pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), version, 0); @@ -3651,16 +3399,16 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, pkt_empty = 0; rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING; - require_padding = - !conn->server || destlen >= NGTCP2_MAX_UDP_PAYLOAD_SIZE; + require_padding = require_padding || !conn->server || + destlen >= NGTCP2_MAX_UDP_PAYLOAD_SIZE; /* We don't retransmit PATH_RESPONSE. */ } } } - rv = conn_create_ack_frame(conn, &ackfr, pktns, type, ts, - conn_compute_ack_delay(conn), - conn->local.transport_params.ack_delay_exponent); + rv = ngtcp2_conn_create_ack_frame( + conn, &ackfr, pktns, type, ts, conn_compute_ack_delay(conn), + conn->local.transport_params.ack_delay_exponent); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); return rv; @@ -3693,32 +3441,30 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } switch ((*pfrc)->fr.type) { + case NGTCP2_FRAME_RESET_STREAM: + strm = + ngtcp2_conn_find_stream(conn, (*pfrc)->fr.reset_stream.stream_id); + if (strm == NULL || + !ngtcp2_strm_require_retransmit_reset_stream(strm)) { + frc = *pfrc; + *pfrc = (*pfrc)->next; + ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); + continue; + } + break; case NGTCP2_FRAME_STOP_SENDING: strm = ngtcp2_conn_find_stream(conn, (*pfrc)->fr.stop_sending.stream_id); - if (strm == NULL || (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD)) { + if (strm == NULL || + !ngtcp2_strm_require_retransmit_stop_sending(strm)) { frc = *pfrc; *pfrc = (*pfrc)->next; ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); continue; } - - if (!(strm->flags & NGTCP2_STRM_FLAG_STREAM_STOP_SENDING_CALLED)) { - strm->flags |= NGTCP2_STRM_FLAG_STREAM_STOP_SENDING_CALLED; - - rv = conn_call_stream_stop_sending( - conn, (*pfrc)->fr.stop_sending.stream_id, - (*pfrc)->fr.stop_sending.app_error_code, strm->stream_user_data); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - return rv; - } - } - break; case NGTCP2_FRAME_STREAM: - assert(0); - break; + ngtcp2_unreachable(); case NGTCP2_FRAME_MAX_STREAMS_BIDI: if ((*pfrc)->fr.max_streams.max_streams < conn->remote.bidi.max_streams) { @@ -3740,8 +3486,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, case NGTCP2_FRAME_MAX_STREAM_DATA: strm = ngtcp2_conn_find_stream(conn, (*pfrc)->fr.max_stream_data.stream_id); - if (strm == NULL || (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) || - (*pfrc)->fr.max_stream_data.max_stream_data < strm->rx.max_offset) { + if (strm == NULL || !ngtcp2_strm_require_retransmit_max_stream_data( + strm, &(*pfrc)->fr.max_stream_data)) { frc = *pfrc; *pfrc = (*pfrc)->next; ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); @@ -3756,9 +3502,27 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, continue; } break; - case NGTCP2_FRAME_CRYPTO: - assert(0); + case NGTCP2_FRAME_STREAM_DATA_BLOCKED: + strm = ngtcp2_conn_find_stream( + conn, (*pfrc)->fr.stream_data_blocked.stream_id); + if (strm == NULL || !ngtcp2_strm_require_retransmit_stream_data_blocked( + strm, &(*pfrc)->fr.stream_data_blocked)) { + frc = *pfrc; + *pfrc = (*pfrc)->next; + ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); + continue; + } break; + case NGTCP2_FRAME_DATA_BLOCKED: + if ((*pfrc)->fr.data_blocked.offset != conn->tx.max_offset) { + frc = *pfrc; + *pfrc = (*pfrc)->next; + ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); + continue; + } + break; + case NGTCP2_FRAME_CRYPTO: + ngtcp2_unreachable(); } rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &(*pfrc)->fr); @@ -3774,13 +3538,14 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, pfrc = &(*pfrc)->next; } - if (rv != NGTCP2_ERR_NOBUF) { - for (; ngtcp2_ksl_len(&pktns->crypto.tx.frq);) { + if (*pfrc == NULL) { + for (; !ngtcp2_strm_streamfrq_empty(&pktns->crypto.strm);) { left = ngtcp2_ppe_left(ppe); - crypto_offset = conn_cryptofrq_unacked_offset(conn, pktns); - if (crypto_offset == (size_t)-1) { - conn_cryptofrq_clear(conn, pktns); + crypto_offset = + ngtcp2_strm_streamfrq_unacked_offset(&pktns->crypto.strm); + if (crypto_offset == (uint64_t)-1) { + ngtcp2_strm_streamfrq_clear(&pktns->crypto.strm); break; } @@ -3790,7 +3555,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, break; } - rv = conn_cryptofrq_pop(conn, &nfrc, pktns, left); + rv = ngtcp2_strm_streamfrq_pop(&pktns->crypto.strm, &nfrc, left); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); return rv; @@ -3802,7 +3567,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { - assert(0); + ngtcp2_unreachable(); } *pfrc = nfrc; @@ -3815,79 +3580,114 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } } - /* Write MAX_STREAM_ID after RESET_STREAM so that we can extend stream - ID space in one packet. */ - if (rv != NGTCP2_ERR_NOBUF && *pfrc == NULL && - conn->remote.bidi.unsent_max_streams > conn->remote.bidi.max_streams) { - rv = conn_call_extend_max_remote_streams_bidi( - conn, conn->remote.bidi.unsent_max_streams); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - return rv; - } + if (*pfrc == NULL) { + for (; !ngtcp2_pq_empty(&conn->tx.strmq);) { + strm = ngtcp2_conn_tx_strmq_top(conn); - rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - return rv; - } - nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_BIDI; - nfrc->fr.max_streams.max_streams = conn->remote.bidi.unsent_max_streams; - *pfrc = nfrc; + if (strm->flags & NGTCP2_STRM_FLAG_SEND_RESET_STREAM) { + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); + if (rv != 0) { + return rv; + } - conn->remote.bidi.max_streams = conn->remote.bidi.unsent_max_streams; + nfrc->fr.type = NGTCP2_FRAME_RESET_STREAM; + nfrc->fr.reset_stream.stream_id = strm->stream_id; + nfrc->fr.reset_stream.app_error_code = + strm->tx.reset_stream_app_error_code; + nfrc->fr.reset_stream.final_size = strm->tx.offset; + *pfrc = nfrc; - rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &(*pfrc)->fr); - if (rv != 0) { - assert(NGTCP2_ERR_NOBUF == rv); - } else { - pkt_empty = 0; - rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | - NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | - NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE; - pfrc = &(*pfrc)->next; - } - } + strm->flags &= ~NGTCP2_STRM_FLAG_SEND_RESET_STREAM; - if (rv != NGTCP2_ERR_NOBUF && *pfrc == NULL) { - if (conn->remote.uni.unsent_max_streams > conn->remote.uni.max_streams) { - rv = conn_call_extend_max_remote_streams_uni( - conn, conn->remote.uni.unsent_max_streams); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - return rv; + rv = + conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); + if (rv != 0) { + assert(NGTCP2_ERR_NOBUF == rv); + + break; + } + + pkt_empty = 0; + rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE; + pfrc = &(*pfrc)->next; } - rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - return rv; + if (strm->flags & NGTCP2_STRM_FLAG_SEND_STOP_SENDING) { + if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) && + ngtcp2_strm_rx_offset(strm) == strm->rx.last_offset) { + strm->flags &= ~NGTCP2_STRM_FLAG_SEND_STOP_SENDING; + } else { + rv = conn_call_stream_stop_sending( + conn, strm->stream_id, strm->tx.stop_sending_app_error_code, + strm->stream_user_data); + if (rv != 0) { + assert(ngtcp2_err_is_fatal(rv)); + + return rv; + } + + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); + if (rv != 0) { + return rv; + } + + nfrc->fr.type = NGTCP2_FRAME_STOP_SENDING; + nfrc->fr.stop_sending.stream_id = strm->stream_id; + nfrc->fr.stop_sending.app_error_code = + strm->tx.stop_sending_app_error_code; + *pfrc = nfrc; + + strm->flags &= ~NGTCP2_STRM_FLAG_SEND_STOP_SENDING; + + rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, + &nfrc->fr); + if (rv != 0) { + assert(NGTCP2_ERR_NOBUF == rv); + + break; + } + + pkt_empty = 0; + rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE; + pfrc = &(*pfrc)->next; + } } - nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_UNI; - nfrc->fr.max_streams.max_streams = conn->remote.uni.unsent_max_streams; - *pfrc = nfrc; - conn->remote.uni.max_streams = conn->remote.uni.unsent_max_streams; + if (!(strm->flags & NGTCP2_STRM_FLAG_SHUT_WR) && + strm_should_send_stream_data_blocked(strm)) { + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); + if (rv != 0) { + return rv; + } + + nfrc->fr.type = NGTCP2_FRAME_STREAM_DATA_BLOCKED; + nfrc->fr.stream_data_blocked.stream_id = strm->stream_id; + nfrc->fr.stream_data_blocked.offset = strm->tx.max_offset; + *pfrc = nfrc; + + strm->tx.last_blocked_offset = strm->tx.max_offset; + + rv = + conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); + if (rv != 0) { + assert(NGTCP2_ERR_NOBUF == rv); + + break; + } - rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, - &(*pfrc)->fr); - if (rv != 0) { - assert(NGTCP2_ERR_NOBUF == rv); - } else { pkt_empty = 0; rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE; pfrc = &(*pfrc)->next; } - } - } - if (rv != NGTCP2_ERR_NOBUF) { - for (; !ngtcp2_pq_empty(&conn->tx.strmq);) { - strm = ngtcp2_conn_tx_strmq_top(conn); - - if (!(strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) && + if (!(strm->flags & + (NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_STOP_SENDING)) && conn_should_send_max_stream_data(conn, strm)) { rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); if (rv != 0) { @@ -3922,7 +3722,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, nfrc->fr.max_stream_data.stream_id = strm->stream_id; nfrc->fr.max_stream_data.max_stream_data = strm->rx.unsent_max_offset + delta; - ngtcp2_list_insert(nfrc, pfrc); + *pfrc = nfrc; + + strm->rx.max_offset = strm->rx.unsent_max_offset = + nfrc->fr.max_stream_data.max_stream_data; rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); @@ -3936,8 +3739,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE; pfrc = &(*pfrc)->next; - strm->rx.max_offset = strm->rx.unsent_max_offset = - nfrc->fr.max_stream_data.max_stream_data; } if (ngtcp2_strm_streamfrq_empty(strm)) { @@ -3949,8 +3750,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (stream_offset == (uint64_t)-1) { ngtcp2_strm_streamfrq_clear(strm); ngtcp2_conn_tx_strmq_pop(conn); - assert(conn->tx.strmq_nretrans); - --conn->tx.strmq_nretrans; continue; } @@ -3976,7 +3775,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { - assert(0); + ngtcp2_unreachable(); } *pfrc = nfrc; @@ -3989,8 +3788,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (ngtcp2_strm_streamfrq_empty(strm)) { ngtcp2_conn_tx_strmq_pop(conn); - assert(conn->tx.strmq_nretrans); - --conn->tx.strmq_nretrans; continue; } @@ -4004,10 +3801,75 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } } - if (rv != NGTCP2_ERR_NOBUF && !send_stream && !send_datagram && + /* Write MAX_STREAMS after RESET_STREAM so that we can extend + stream ID space in one packet. */ + if (*pfrc == NULL && + conn->remote.bidi.unsent_max_streams > conn->remote.bidi.max_streams) { + rv = conn_call_extend_max_remote_streams_bidi( + conn, conn->remote.bidi.unsent_max_streams); + if (rv != 0) { + assert(ngtcp2_err_is_fatal(rv)); + return rv; + } + + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); + if (rv != 0) { + assert(ngtcp2_err_is_fatal(rv)); + return rv; + } + nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_BIDI; + nfrc->fr.max_streams.max_streams = conn->remote.bidi.unsent_max_streams; + *pfrc = nfrc; + + conn->remote.bidi.max_streams = conn->remote.bidi.unsent_max_streams; + + rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &(*pfrc)->fr); + if (rv != 0) { + assert(NGTCP2_ERR_NOBUF == rv); + } else { + pkt_empty = 0; + rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE; + pfrc = &(*pfrc)->next; + } + } + + if (*pfrc == NULL && + conn->remote.uni.unsent_max_streams > conn->remote.uni.max_streams) { + rv = conn_call_extend_max_remote_streams_uni( + conn, conn->remote.uni.unsent_max_streams); + if (rv != 0) { + assert(ngtcp2_err_is_fatal(rv)); + return rv; + } + + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); + if (rv != 0) { + assert(ngtcp2_err_is_fatal(rv)); + return rv; + } + nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_UNI; + nfrc->fr.max_streams.max_streams = conn->remote.uni.unsent_max_streams; + *pfrc = nfrc; + + conn->remote.uni.max_streams = conn->remote.uni.unsent_max_streams; + + rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &(*pfrc)->fr); + if (rv != 0) { + assert(NGTCP2_ERR_NOBUF == rv); + } else { + pkt_empty = 0; + rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE; + pfrc = &(*pfrc)->next; + } + } + + if (pktns->tx.frq == NULL && !send_stream && !send_datagram && !(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) && - pktns->rtb.num_retransmittable && pktns->tx.frq == NULL && - pktns->rtb.probe_pkt_left) { + pktns->rtb.num_retransmittable && pktns->rtb.probe_pkt_left) { num_reclaimed = ngtcp2_rtb_reclaim_on_pto(&pktns->rtb, conn, pktns, 1); if (num_reclaimed < 0) { return rv; @@ -4016,15 +3878,16 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, goto build_pkt; } - /* We had pktns->rtb.num_retransmittable > 0 but the contents of - those packets have been acknowledged (i.e., retransmission in - another packet). In this case, we don't have to send any - probe packet. */ + /* We had pktns->rtb.num_retransmittable > 0 but we were unable + to reclaim any frame. In this case, we do not have to send + any probe packet. */ if (pktns->rtb.num_pto_eliciting == 0) { pktns->rtb.probe_pkt_left = 0; ngtcp2_conn_set_loss_detection_timer(conn, ts); - /* TODO If packet is empty, we should return now if cwnd is - zero. */ + + if (pkt_empty && conn_cwnd_is_zero(conn) && !require_padding) { + return 0; + } } } } else { @@ -4036,7 +3899,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, left = ngtcp2_ppe_left(ppe); - if (rv != NGTCP2_ERR_NOBUF && send_stream && *pfrc == NULL && + if (*pfrc == NULL && send_stream && (ndatalen = ngtcp2_pkt_stream_max_datalen( vmsg->stream.strm->stream_id, vmsg->stream.strm->tx.offset, ndatalen, left)) != (size_t)-1 && @@ -4068,7 +3931,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { - assert(0); + ngtcp2_unreachable(); } *pfrc = nfrc; @@ -4093,7 +3956,83 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, send_stream = 0; } - if (rv != NGTCP2_ERR_NOBUF && send_datagram && + if (vmsg && vmsg->type == NGTCP2_VMSG_TYPE_STREAM && + ((stream_blocked && *pfrc == NULL) || + (send_stream && + !(vmsg->stream.strm->flags & NGTCP2_STRM_FLAG_SHUT_WR)))) { + if (conn_should_send_data_blocked(conn)) { + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); + if (rv != 0) { + assert(ngtcp2_err_is_fatal(rv)); + + return rv; + } + + nfrc->fr.type = NGTCP2_FRAME_DATA_BLOCKED; + nfrc->fr.data_blocked.offset = conn->tx.offset; + + rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); + if (rv != 0) { + assert(NGTCP2_ERR_NOBUF == rv); + + /* We cannot add nfrc to pktns->tx.frq here. */ + ngtcp2_frame_chain_objalloc_del(nfrc, &conn->frc_objalloc, conn->mem); + } else { + *pfrc = nfrc; + pfrc = &(*pfrc)->next; + + pkt_empty = 0; + rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE; + + conn->tx.last_blocked_offset = conn->tx.max_offset; + } + } + + strm = vmsg->stream.strm; + + if (strm_should_send_stream_data_blocked(strm)) { + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); + if (rv != 0) { + assert(ngtcp2_err_is_fatal(rv)); + + return rv; + } + + nfrc->fr.type = NGTCP2_FRAME_STREAM_DATA_BLOCKED; + nfrc->fr.stream_data_blocked.stream_id = strm->stream_id; + nfrc->fr.stream_data_blocked.offset = strm->tx.max_offset; + + rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); + if (rv != 0) { + assert(NGTCP2_ERR_NOBUF == rv); + + /* We cannot add nfrc to pktns->tx.frq here. */ + ngtcp2_frame_chain_objalloc_del(nfrc, &conn->frc_objalloc, conn->mem); + + if (!ngtcp2_strm_is_tx_queued(strm)) { + strm->cycle = conn_tx_strmq_first_cycle(conn); + rv = ngtcp2_conn_tx_strmq_push(conn, strm); + if (rv != 0) { + return rv; + } + } + } else { + *pfrc = nfrc; + pfrc = &(*pfrc)->next; + + pkt_empty = 0; + rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE; + + strm->tx.last_blocked_offset = strm->tx.max_offset; + } + } + } + + if (*pfrc == NULL && send_datagram && left >= ngtcp2_pkt_datagram_framelen((size_t)datalen)) { if (conn->callbacks.ack_datagram || conn->callbacks.lost_datagram) { rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); @@ -4129,8 +4068,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } pkt_empty = 0; - rtb_entry_flags |= - NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | NGTCP2_RTB_ENTRY_FLAG_DATAGRAM; + rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_DATAGRAM; if (vmsg->datagram.paccepted) { *vmsg->datagram.paccepted = 1; @@ -4140,14 +4080,27 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } if (pkt_empty) { - assert(rv == 0 || NGTCP2_ERR_NOBUF == rv); - if (rv == 0 && stream_blocked && ngtcp2_conn_get_max_data_left(conn)) { + if (*pfrc == NULL && rv == 0 && stream_blocked && + (write_more || !require_padding) && + ngtcp2_conn_get_max_data_left(conn)) { + if (write_more) { + conn->pkt.pfrc = pfrc; + conn->pkt.pkt_empty = pkt_empty; + conn->pkt.rtb_entry_flags = rtb_entry_flags; + conn->pkt.hd_logged = hd_logged; + conn->flags |= NGTCP2_CONN_FLAG_PPE_PENDING; + } + return NGTCP2_ERR_STREAM_DATA_BLOCKED; } - keep_alive_expired = conn_keep_alive_expired(conn, ts); + keep_alive_expired = + type == NGTCP2_PKT_1RTT && conn_keep_alive_expired(conn, ts); + + if (conn->pktns.rtb.probe_pkt_left == 0 && !keep_alive_expired && + !require_padding) { + conn_reset_ppe_pending(conn); - if (conn->pktns.rtb.probe_pkt_left == 0 && !keep_alive_expired) { return 0; } } else if (write_more) { @@ -4165,7 +4118,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (ngtcp2_ppe_left(ppe)) { return NGTCP2_ERR_WRITE_MORE; } - } else if (ngtcp2_conn_get_max_data_left(conn) && stream_blocked) { + break; + } + + if (*pfrc == NULL && ngtcp2_conn_get_max_data_left(conn) && + stream_blocked) { return NGTCP2_ERR_STREAM_DATA_BLOCKED; } break; @@ -4178,12 +4135,13 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, calls ngtcp2_conn_writev_datagram again. */ break; default: - assert(0); + ngtcp2_unreachable(); } } if (!(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { - if (pktns->tx.num_non_ack_pkt >= NGTCP2_MAX_NON_ACK_TX_PKT || + if (ngtcp2_tstamp_elapsed(pktns->tx.non_ack_pkt_start_ts, + cstat->smoothed_rtt, ts) || keep_alive_expired || conn->pktns.rtb.probe_pkt_left) { lfr.type = NGTCP2_FRAME_PING; @@ -4197,13 +4155,13 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (conn->pktns.rtb.probe_pkt_left) { rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_PROBE; } - pktns->tx.num_non_ack_pkt = 0; + pktns->tx.non_ack_pkt_start_ts = UINT64_MAX; } - } else { - ++pktns->tx.num_non_ack_pkt; + } else if (pktns->tx.non_ack_pkt_start_ts == UINT64_MAX) { + pktns->tx.non_ack_pkt_start_ts = ts; } } else { - pktns->tx.num_non_ack_pkt = 0; + pktns->tx.non_ack_pkt_start_ts = UINT64_MAX; } /* TODO Push STREAM frame back to ngtcp2_strm if there is an error @@ -4212,8 +4170,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, /* Making full sized packet will help GSO a bit */ ngtcp2_ppe_left(ppe) < 10) { lfr.padding.len = ngtcp2_ppe_padding(ppe); - } else { + } else if (type == NGTCP2_PKT_1RTT) { lfr.padding.len = ngtcp2_ppe_padding_size(ppe, min_pktlen); + } else { + lfr.padding.len = ngtcp2_ppe_padding_hp_sample(ppe); } if (lfr.padding.len) { @@ -4285,7 +4245,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, conn_handle_tx_ecn(conn, pi, NULL, pktns, hd, ts); } - conn->flags &= (uint32_t)~NGTCP2_CONN_FLAG_PPE_PENDING; + conn_reset_ppe_pending(conn); if (pktns->rtb.probe_pkt_left && (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { @@ -4360,8 +4320,7 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( break; default: /* We don't support 0-RTT packet in this function. */ - assert(0); - abort(); + ngtcp2_unreachable(); } cc.aead = pktns->crypto.ctx.aead; @@ -4448,7 +4407,8 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( if (((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) || padded) && (!path || ngtcp2_path_eq(&conn->dcid.current.ps.path, path))) { - if (pi && !(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE)) { + if (pi && (conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE || + !(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE))) { conn_handle_tx_ecn(conn, pi, &rtb_entry_flags, pktns, &hd, ts); } @@ -4479,8 +4439,7 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( nwrite); } } - } else if (pi && !(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE) && - conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE) { + } else if (pi && conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE) { conn_handle_tx_ecn(conn, pi, NULL, pktns, &hd, ts); } @@ -4488,7 +4447,17 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( conn_update_keep_alive_last_ts(conn, ts); } - conn->tx.pacing.pktlen += (size_t)nwrite; + if (!padded) { + switch (fr->type) { + case NGTCP2_FRAME_ACK: + case NGTCP2_FRAME_ACK_ECN: + break; + default: + conn->tx.pacing.pktlen += (size_t)nwrite; + } + } else { + conn->tx.pacing.pktlen += (size_t)nwrite; + } ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); @@ -4529,11 +4498,11 @@ static int conn_handshake_remnants_left(ngtcp2_conn *conn) { ngtcp2_pktns *in_pktns = conn->in_pktns; ngtcp2_pktns *hs_pktns = conn->hs_pktns; - return !conn_is_handshake_completed(conn) || + return !conn_is_tls_handshake_completed(conn) || (in_pktns && (in_pktns->rtb.num_pto_eliciting || - ngtcp2_ksl_len(&in_pktns->crypto.tx.frq))) || + !ngtcp2_strm_streamfrq_empty(&in_pktns->crypto.strm))) || (hs_pktns && (hs_pktns->rtb.num_pto_eliciting || - ngtcp2_ksl_len(&hs_pktns->crypto.tx.frq))); + !ngtcp2_strm_streamfrq_empty(&hs_pktns->crypto.strm))); } /* @@ -4684,14 +4653,14 @@ static int conn_start_pmtud(ngtcp2_conn *conn) { assert(!conn->local.settings.no_pmtud); assert(!conn->pmtud); - assert(conn_is_handshake_completed(conn)); + assert(conn_is_tls_handshake_completed(conn)); assert(conn->remote.transport_params); assert(conn->remote.transport_params->max_udp_payload_size >= NGTCP2_MAX_UDP_PAYLOAD_SIZE); - hard_max_udp_payload_size = - (size_t)ngtcp2_min(conn->remote.transport_params->max_udp_payload_size, - (uint64_t)conn->local.settings.max_udp_payload_size); + hard_max_udp_payload_size = (size_t)ngtcp2_min( + conn->remote.transport_params->max_udp_payload_size, + (uint64_t)conn->local.settings.max_tx_udp_payload_size); rv = ngtcp2_pmtud_new(&conn->pmtud, conn->dcid.current.max_udp_payload_size, hard_max_udp_payload_size, @@ -4850,9 +4819,9 @@ static size_t conn_shape_udp_payload(ngtcp2_conn *conn, const ngtcp2_dcid *dcid, } payloadlen = - ngtcp2_min(payloadlen, conn->local.settings.max_udp_payload_size); + ngtcp2_min(payloadlen, conn->local.settings.max_tx_udp_payload_size); - if (conn->local.settings.no_udp_payload_size_shaping) { + if (conn->local.settings.no_tx_udp_payload_size_shaping) { return payloadlen; } @@ -4885,10 +4854,6 @@ static int conn_on_path_validation_failed(ngtcp2_conn *conn, ngtcp2_pv *pv, } } - if (pv->flags & NGTCP2_PV_FLAG_MTU_PROBE) { - return NGTCP2_ERR_NO_VIABLE_PATH; - } - if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) { ngtcp2_dcid_copy(&conn->dcid.current, &pv->fallback_dcid); conn_reset_congestion_state(conn, ts); @@ -4918,7 +4883,7 @@ static ngtcp2_ssize conn_write_path_challenge(ngtcp2_conn *conn, ngtcp2_tstamp expiry; ngtcp2_pv *pv = conn->pv; ngtcp2_frame lfr; - ngtcp2_duration timeout; + ngtcp2_duration timeout, initial_pto; uint8_t flags; uint64_t tx_left; int rv; @@ -4953,8 +4918,9 @@ static ngtcp2_ssize conn_write_path_challenge(ngtcp2_conn *conn, lfr.type = NGTCP2_FRAME_PATH_CHALLENGE; + initial_pto = conn_compute_initial_pto(conn, &conn->pktns); timeout = conn_compute_pto(conn, &conn->pktns); - timeout = ngtcp2_max(timeout, 3 * conn->cstat.initial_rtt); + timeout = ngtcp2_max(timeout, initial_pto); expiry = ts + timeout * (1ULL << pv->round); destlen = ngtcp2_min(destlen, NGTCP2_MAX_UDP_PAYLOAD_SIZE); @@ -5216,75 +5182,6 @@ uint64_t ngtcp2_conn_tx_strmq_first_cycle(ngtcp2_conn *conn) { return strm->cycle; } -int ngtcp2_conn_resched_frames(ngtcp2_conn *conn, ngtcp2_pktns *pktns, - ngtcp2_frame_chain **pfrc) { - ngtcp2_frame_chain **first = pfrc; - ngtcp2_frame_chain *frc; - ngtcp2_stream *sfr; - ngtcp2_strm *strm; - int rv; - int streamfrq_empty; - - if (*pfrc == NULL) { - return 0; - } - - for (; *pfrc;) { - switch ((*pfrc)->fr.type) { - case NGTCP2_FRAME_STREAM: - frc = *pfrc; - - *pfrc = frc->next; - frc->next = NULL; - sfr = &frc->fr.stream; - - strm = ngtcp2_conn_find_stream(conn, sfr->stream_id); - if (!strm) { - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - break; - } - streamfrq_empty = ngtcp2_strm_streamfrq_empty(strm); - rv = ngtcp2_strm_streamfrq_push(strm, frc); - if (rv != 0) { - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - if (!ngtcp2_strm_is_tx_queued(strm)) { - strm->cycle = conn_tx_strmq_first_cycle(conn); - rv = ngtcp2_conn_tx_strmq_push(conn, strm); - if (rv != 0) { - return rv; - } - } - if (streamfrq_empty) { - ++conn->tx.strmq_nretrans; - } - break; - case NGTCP2_FRAME_CRYPTO: - frc = *pfrc; - - *pfrc = frc->next; - frc->next = NULL; - - rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, - &frc->fr.crypto.offset, frc); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); - return rv; - } - break; - default: - pfrc = &(*pfrc)->next; - } - } - - *pfrc = pktns->tx.frq; - pktns->tx.frq = *first; - - return 0; -} - /* * conn_on_retry is called when Retry packet is received. The * function decodes the data in the buffer pointed by |pkt| whose @@ -5312,7 +5209,7 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, ngtcp2_rtb *rtb = &conn->pktns.rtb; ngtcp2_rtb *in_rtb; uint8_t cidbuf[sizeof(retry.odcid.data) * 2 + 1]; - ngtcp2_vec *token; + uint8_t *token; if (!in_pktns || conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) { return 0; @@ -5340,7 +5237,7 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, (const char *)ngtcp2_encode_hex(cidbuf, retry.odcid.data, retry.odcid.datalen)); - if (retry.token.len == 0) { + if (retry.tokenlen == 0) { return NGTCP2_ERR_PROTO; } @@ -5376,19 +5273,19 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, return rv; } - token = &conn->local.settings.token; - - ngtcp2_mem_free(conn->mem, token->base); - token->base = NULL; - token->len = 0; + ngtcp2_mem_free(conn->mem, (uint8_t *)conn->local.settings.token); + conn->local.settings.token = NULL; + conn->local.settings.tokenlen = 0; - token->base = ngtcp2_mem_malloc(conn->mem, retry.token.len); - if (token->base == NULL) { + token = ngtcp2_mem_malloc(conn->mem, retry.tokenlen); + if (token == NULL) { return NGTCP2_ERR_NOMEM; } - token->len = retry.token.len; - ngtcp2_cpymem(token->base, retry.token.base, retry.token.len); + ngtcp2_cpymem(token, retry.token, retry.tokenlen); + + conn->local.settings.token = token; + conn->local.settings.tokenlen = retry.tokenlen; reset_conn_stat_recovery(&conn->cstat); conn_reset_congestion_state(conn, ts); @@ -5423,7 +5320,6 @@ int ngtcp2_conn_detect_lost_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns, static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr, ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) { int rv; - ngtcp2_frame_chain *frc = NULL; ngtcp2_ssize num_acked; ngtcp2_conn_stat *cstat = &conn->cstat; @@ -5431,7 +5327,7 @@ static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr, return NGTCP2_ERR_PROTO; } - rv = ngtcp2_pkt_validate_ack(fr); + rv = ngtcp2_pkt_validate_ack(fr, conn->local.settings.initial_pkt_num); if (rv != 0) { return rv; } @@ -5441,9 +5337,7 @@ static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr, num_acked = ngtcp2_rtb_recv_ack(&pktns->rtb, fr, &conn->cstat, conn, pktns, pkt_ts, ts); if (num_acked < 0) { - /* TODO assert this */ assert(ngtcp2_err_is_fatal((int)num_acked)); - ngtcp2_frame_chain_list_objalloc_del(frc, &conn->frc_objalloc, conn->mem); return (int)num_acked; } @@ -5778,10 +5672,10 @@ decrypt_hp(ngtcp2_pkt_hd *hd, uint8_t *dest, const ngtcp2_crypto_cipher *hp, * NGTCP2_ERR_CRYPTO * TLS backend reported error */ -static int conn_emit_pending_crypto_data(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, - ngtcp2_strm *strm, - uint64_t rx_offset) { +static int +conn_emit_pending_crypto_data(ngtcp2_conn *conn, + ngtcp2_encryption_level encryption_level, + ngtcp2_strm *strm, uint64_t rx_offset) { size_t datalen; const uint8_t *data; int rv; @@ -5801,7 +5695,8 @@ static int conn_emit_pending_crypto_data(ngtcp2_conn *conn, offset = rx_offset; rx_offset += datalen; - rv = conn_call_recv_crypto_data(conn, crypto_level, offset, data, datalen); + rv = conn_call_recv_crypto_data(conn, encryption_level, offset, data, + datalen); if (rv != 0) { return rv; } @@ -5816,13 +5711,13 @@ static int conn_emit_pending_crypto_data(ngtcp2_conn *conn, */ static int conn_recv_connection_close(ngtcp2_conn *conn, ngtcp2_connection_close *fr) { - ngtcp2_connection_close_error *ccerr = &conn->rx.ccerr; + ngtcp2_ccerr *ccerr = &conn->rx.ccerr; conn->state = NGTCP2_CS_DRAINING; if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) { - ccerr->type = NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT; + ccerr->type = NGTCP2_CCERR_TYPE_TRANSPORT; } else { - ccerr->type = NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION; + ccerr->type = NGTCP2_CCERR_TYPE_APPLICATION; } ccerr->error_code = fr->error_code; ccerr->frame_type = fr->frame_type; @@ -5834,16 +5729,14 @@ static int conn_recv_connection_close(ngtcp2_conn *conn, } if (ccerr->reason == NULL) { - ccerr->reason = ngtcp2_mem_malloc( - conn->mem, NGTCP2_CONNECTION_CLOSE_ERROR_MAX_REASONLEN); + ccerr->reason = ngtcp2_mem_malloc(conn->mem, NGTCP2_CCERR_MAX_REASONLEN); if (ccerr->reason == NULL) { return NGTCP2_ERR_NOMEM; } } - ccerr->reasonlen = - ngtcp2_min(fr->reasonlen, NGTCP2_CONNECTION_CLOSE_ERROR_MAX_REASONLEN); - ngtcp2_cpymem(ccerr->reason, fr->reason, ccerr->reasonlen); + ccerr->reasonlen = ngtcp2_min(fr->reasonlen, NGTCP2_CCERR_MAX_REASONLEN); + ngtcp2_cpymem((uint8_t *)ccerr->reason, fr->reason, ccerr->reasonlen); return 0; } @@ -5872,7 +5765,9 @@ static void conn_recv_path_challenge(ngtcp2_conn *conn, const ngtcp2_path *path, static void conn_reset_congestion_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { conn_reset_conn_stat_cc(conn, &conn->cstat); - conn->cc.reset(&conn->cc, &conn->cstat, ts); + if (conn->cc.reset) { + conn->cc.reset(&conn->cc, &conn->cstat, ts); + } if (conn->hs_pktns) { ngtcp2_rtb_reset_cc_state(&conn->hs_pktns->rtb, @@ -5887,7 +5782,6 @@ static void conn_reset_congestion_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr, ngtcp2_tstamp ts) { int rv; - ngtcp2_duration pto, timeout; ngtcp2_pv *pv = conn->pv, *npv; uint8_t ent_flags; @@ -5903,54 +5797,52 @@ static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr, } if (!(pv->flags & NGTCP2_PV_FLAG_DONT_CARE)) { - if (!(pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE)) { - if (pv->dcid.seq != conn->dcid.current.seq) { - assert(conn->dcid.current.cid.datalen); + if (pv->dcid.seq != conn->dcid.current.seq) { + assert(!conn->server); + assert(conn->dcid.current.cid.datalen); - rv = conn_retire_dcid(conn, &conn->dcid.current, ts); - if (rv != 0) { - return rv; - } - ngtcp2_dcid_copy(&conn->dcid.current, &pv->dcid); + rv = conn_retire_dcid(conn, &conn->dcid.current, ts); + if (rv != 0) { + return rv; } + ngtcp2_dcid_copy(&conn->dcid.current, &pv->dcid); + conn_reset_congestion_state(conn, ts); conn_reset_ecn_validation_state(conn); } - if (ngtcp2_path_eq(&pv->dcid.ps.path, &conn->dcid.current.ps.path)) { - conn->dcid.current.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED; - } + assert(ngtcp2_path_eq(&pv->dcid.ps.path, &conn->dcid.current.ps.path)); - rv = conn_call_path_validation(conn, pv, - NGTCP2_PATH_VALIDATION_RESULT_SUCCESS); - if (rv != 0) { - return rv; - } + conn->dcid.current.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED; if (!conn->local.settings.no_pmtud) { ngtcp2_conn_stop_pmtud(conn); - if (!(pv->flags & NGTCP2_PV_ENTRY_FLAG_UNDERSIZED)) { + if (!(ent_flags & NGTCP2_PV_ENTRY_FLAG_UNDERSIZED)) { rv = conn_start_pmtud(conn); if (rv != 0) { return rv; } } } + + if (!(ent_flags & NGTCP2_PV_ENTRY_FLAG_UNDERSIZED)) { + rv = conn_call_path_validation(conn, pv, + NGTCP2_PATH_VALIDATION_RESULT_SUCCESS); + if (rv != 0) { + return rv; + } + } } if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) { - pto = conn_compute_pto(conn, &conn->pktns); - timeout = 3 * ngtcp2_max(pto, pv->fallback_pto); - if (ent_flags & NGTCP2_PV_ENTRY_FLAG_UNDERSIZED) { assert(conn->server); /* Validate path again */ - rv = ngtcp2_pv_new(&npv, &pv->dcid, timeout, - NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE | - NGTCP2_PV_FLAG_MTU_PROBE, - &conn->log, conn->mem); + rv = ngtcp2_pv_new(&npv, &pv->dcid, conn_compute_pv_timeout(conn), + NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE, &conn->log, + conn->mem); if (rv != 0) { return rv; } @@ -5959,7 +5851,8 @@ static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr, ngtcp2_dcid_copy(&npv->fallback_dcid, &pv->fallback_dcid); npv->fallback_pto = pv->fallback_pto; } else { - rv = ngtcp2_pv_new(&npv, &pv->fallback_dcid, timeout, + rv = ngtcp2_pv_new(&npv, &pv->fallback_dcid, + conn_compute_pv_timeout_pto(conn, pv->fallback_pto), NGTCP2_PV_FLAG_DONT_CARE, &conn->log, conn->mem); if (rv != 0) { return rv; @@ -5984,26 +5877,6 @@ static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr, return conn_stop_pv(conn, ts); } -/* - * pkt_num_bits returns the number of bits available when packet - * number is encoded in |pkt_numlen| bytes. - */ -static size_t pkt_num_bits(size_t pkt_numlen) { - switch (pkt_numlen) { - case 1: - return 8; - case 2: - return 16; - case 3: - return 24; - case 4: - return 32; - default: - assert(0); - abort(); - } -} - /* * pktns_pkt_num_is_duplicate returns nonzero if |pkt_num| is * duplicated packet number. @@ -6019,17 +5892,7 @@ static int pktns_pkt_num_is_duplicate(ngtcp2_pktns *pktns, int64_t pkt_num) { static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num, int ack_eliciting, ngtcp2_tstamp ts) { int rv; - - if (ack_eliciting && pktns->rx.max_ack_eliciting_pkt_num + 1 != pkt_num) { - ngtcp2_acktr_immediate_ack(&pktns->acktr); - } - if (pktns->rx.max_pkt_num < pkt_num) { - pktns->rx.max_pkt_num = pkt_num; - pktns->rx.max_pkt_ts = ts; - } - if (ack_eliciting && pktns->rx.max_ack_eliciting_pkt_num < pkt_num) { - pktns->rx.max_ack_eliciting_pkt_num = pkt_num; - } + ngtcp2_range r; rv = ngtcp2_gaptr_push(&pktns->rx.pngap, (uint64_t)pkt_num, 1); if (rv != 0) { @@ -6040,6 +5903,30 @@ static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num, ngtcp2_gaptr_drop_first_gap(&pktns->rx.pngap); } + if (ack_eliciting) { + if (pktns->rx.max_ack_eliciting_pkt_num != -1) { + if (pkt_num < pktns->rx.max_ack_eliciting_pkt_num) { + ngtcp2_acktr_immediate_ack(&pktns->acktr); + } else if (pkt_num > pktns->rx.max_ack_eliciting_pkt_num) { + r = ngtcp2_gaptr_get_first_gap_after( + &pktns->rx.pngap, (uint64_t)pktns->rx.max_ack_eliciting_pkt_num); + + if (r.begin < (uint64_t)pkt_num) { + ngtcp2_acktr_immediate_ack(&pktns->acktr); + } + } + } + + if (pktns->rx.max_ack_eliciting_pkt_num < pkt_num) { + pktns->rx.max_ack_eliciting_pkt_num = pkt_num; + } + } + + if (pktns->rx.max_pkt_num < pkt_num) { + pktns->rx.max_pkt_num = pkt_num; + pktns->rx.max_pkt_ts = ts; + } + return 0; } @@ -6047,9 +5934,9 @@ static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num, * verify_token verifies |hd| contains |token| in its token field. It * returns 0 if it succeeds, or NGTCP2_ERR_PROTO. */ -static int verify_token(const ngtcp2_vec *token, const ngtcp2_pkt_hd *hd) { - if (token->len == hd->token.len && - ngtcp2_cmemeq(token->base, hd->token.base, token->len)) { +static int verify_token(const uint8_t *token, size_t tokenlen, + const ngtcp2_pkt_hd *hd) { + if (tokenlen == hd->tokenlen && ngtcp2_cmemeq(token, hd->token, tokenlen)) { return 0; } return NGTCP2_ERR_PROTO; @@ -6071,25 +5958,28 @@ static void pktns_increase_ecn_counts(ngtcp2_pktns *pktns, } /* - * vneg_other_versions_includes returns nonzero if |other_versions| of - * length |other_versionslen| includes |version|. |other_versions| is - * the wire image of other_versions field of version_information - * transport parameter, and each version is encoded in network byte - * order. + * vneg_available_versions_includes returns nonzero if + * |available_versions| of length |available_versionslen| includes + * |version|. |available_versions| is the wire image of + * available_versions field of version_information transport + * parameter, and each version is encoded in network byte order. */ -static int vneg_other_versions_includes(const uint8_t *other_versions, - size_t other_versionslen, - uint32_t version) { +static int vneg_available_versions_includes(const uint8_t *available_versions, + size_t available_versionslen, + uint32_t version) { size_t i; + uint32_t v; - assert(!(other_versionslen & 0x3)); + assert(!(available_versionslen & 0x3)); - if (other_versionslen == 0) { + if (available_versionslen == 0) { return 0; } - for (i = 0; i < other_versionslen; i += sizeof(uint32_t)) { - if (version == ngtcp2_get_uint32(&other_versions[i])) { + for (i = 0; i < available_versionslen; i += sizeof(uint32_t)) { + available_versions = ngtcp2_get_uint32(&v, available_versions); + + if (version == v) { return 1; } } @@ -6097,8 +5987,49 @@ static int vneg_other_versions_includes(const uint8_t *other_versions, return 0; } -static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, - ngtcp2_strm *strm, const ngtcp2_crypto *fr); +/* + * conn_verify_fixed_bit verifies that fixed bit in |hd| is + * acceptable. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_INVALID_ARGUMENT + * Clearing fixed bit is not permitted. + */ +static int conn_verify_fixed_bit(ngtcp2_conn *conn, ngtcp2_pkt_hd *hd) { + if (!(hd->flags & NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR)) { + return 0; + } + + if (conn->server) { + switch (hd->type) { + case NGTCP2_PKT_INITIAL: + case NGTCP2_PKT_0RTT: + case NGTCP2_PKT_HANDSHAKE: + /* RFC 9287 requires that a token from NEW_TOKEN. */ + if (!(conn->flags & NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED) && + (conn->local.settings.token_type != NGTCP2_TOKEN_TYPE_NEW_TOKEN || + !conn->local.settings.tokenlen)) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } + + break; + } + } + + /* TODO we have no information that we enabled grease_quic_bit in + the previous connection. */ + if (!conn->local.transport_params.grease_quic_bit) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } + + return 0; +} + +static int conn_recv_crypto(ngtcp2_conn *conn, + ngtcp2_encryption_level encryption_level, + ngtcp2_strm *strm, const ngtcp2_stream *fr); static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, const ngtcp2_pkt_info *pi, const uint8_t *pkt, @@ -6164,7 +6095,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_decrypt decrypt; ngtcp2_pktns *pktns; ngtcp2_strm *crypto; - ngtcp2_crypto_level crypto_level; + ngtcp2_encryption_level encryption_level; int invalid_reserved_bits = 0; if (pktlen == 0) { @@ -6199,7 +6130,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, return NGTCP2_ERR_DISCARD_PKT; } - if (hd.type == NGTCP2_PKT_VERSION_NEGOTIATION) { + switch (hd.type) { + case NGTCP2_PKT_VERSION_NEGOTIATION: hdpktlen = (size_t)nread; ngtcp2_log_rx_pkt_hd(&conn->log, &hd); @@ -6210,7 +6142,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, /* Receiving Version Negotiation packet after getting Handshake packet from server is invalid. */ - if (conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) { + if (conn->flags & NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED) { return NGTCP2_ERR_DISCARD_PKT; } @@ -6235,7 +6167,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, return NGTCP2_ERR_DISCARD_PKT; } return NGTCP2_ERR_RECV_VERSION_NEGOTIATION; - } else if (hd.type == NGTCP2_PKT_RETRY) { + case NGTCP2_PKT_RETRY: hdpktlen = (size_t)nread; ngtcp2_log_rx_pkt_hd(&conn->log, &hd); @@ -6244,9 +6176,13 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, return NGTCP2_ERR_DISCARD_PKT; } + if (conn_verify_fixed_bit(conn, &hd) != 0) { + return NGTCP2_ERR_DISCARD_PKT; + } + /* Receiving Retry packet after getting Initial packet from server is invalid. */ - if (conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) { + if (conn->flags & NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED) { return NGTCP2_ERR_DISCARD_PKT; } @@ -6285,9 +6221,13 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, return NGTCP2_ERR_DISCARD_PKT; } + if (conn_verify_fixed_bit(conn, &hd) != 0) { + return NGTCP2_ERR_DISCARD_PKT; + } + /* Quoted from spec: if subsequent packets of those types include a different Source Connection ID, they MUST be discarded. */ - if ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) && + if ((conn->flags & NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED) && !ngtcp2_cid_eq(&conn->dcid.current.cid, &hd.scid)) { ngtcp2_log_rx_pkt_hd(&conn->log, &hd); ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, @@ -6305,7 +6245,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, return NGTCP2_ERR_DISCARD_PKT; } - if (conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) { + if (conn->flags & NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED) { if (conn->early.ckm) { ngtcp2_ssize nread2; /* TODO Avoid to parse header twice. */ @@ -6351,15 +6291,16 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, NGTCP2_MAX_UDP_PAYLOAD_SIZE, dgramlen); return NGTCP2_ERR_DISCARD_PKT; } - if (conn->local.settings.token.len) { - rv = verify_token(&conn->local.settings.token, &hd); + if (conn->local.settings.tokenlen) { + rv = verify_token(conn->local.settings.token, + conn->local.settings.tokenlen, &hd); if (rv != 0) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "packet was ignored because token is invalid"); return NGTCP2_ERR_DISCARD_PKT; } } - if ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) == 0) { + if ((conn->flags & NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED) == 0) { /* Set rcid here so that it is available to callback. If this packet is discarded later in this function and no packet is processed in this connection attempt so far, connection @@ -6372,7 +6313,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } } } else { - if (hd.token.len != 0) { + if (hd.tokenlen != 0) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "packet was ignored because token is not empty"); return NGTCP2_ERR_DISCARD_PKT; @@ -6380,9 +6321,9 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, if (hd.version != conn->client_chosen_version && !conn->negotiated_version && conn->vneg.version != hd.version) { - if (!vneg_other_versions_includes(conn->vneg.other_versions, - conn->vneg.other_versionslen, - hd.version)) { + if (!vneg_available_versions_includes(conn->vneg.available_versions, + conn->vneg.available_versionslen, + hd.version)) { return NGTCP2_ERR_DISCARD_PKT; } @@ -6402,7 +6343,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, pktns = conn->in_pktns; crypto = &pktns->crypto.strm; - crypto_level = NGTCP2_CRYPTO_LEVEL_INITIAL; + encryption_level = NGTCP2_ENCRYPTION_LEVEL_INITIAL; if (hd.version == conn->client_chosen_version) { ckm = pktns->crypto.rx.ckm; @@ -6441,16 +6382,13 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, pktns = conn->hs_pktns; crypto = &pktns->crypto.strm; - crypto_level = NGTCP2_CRYPTO_LEVEL_HANDSHAKE; + encryption_level = NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE; ckm = pktns->crypto.rx.ckm; hp_ctx = &pktns->crypto.rx.hp_ctx; break; default: - /* unknown packet type */ - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, - "packet was ignored because of unknown packet type"); - return (ngtcp2_ssize)pktlen; + ngtcp2_unreachable(); } hp_mask = conn->callbacks.hp_mask; @@ -6483,7 +6421,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, payloadlen = hd.len - hd.pkt_numlen; hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, - pkt_num_bits(hd.pkt_numlen)); + hd.pkt_numlen); if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); @@ -6543,8 +6481,9 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, switch (hd.type) { case NGTCP2_PKT_INITIAL: - if (!conn->server || ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) && - !ngtcp2_cid_eq(&conn->rcid, &hd.dcid))) { + if (!conn->server || + ((conn->flags & NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED) && + !ngtcp2_cid_eq(&conn->rcid, &hd.dcid))) { rv = conn_verify_dcid(conn, NULL, &hd); if (rv != 0) { if (ngtcp2_err_is_fatal(rv)) { @@ -6568,7 +6507,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } break; default: - assert(0); + ngtcp2_unreachable(); } if (payloadlen == 0) { @@ -6580,8 +6519,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } if (hd.type == NGTCP2_PKT_INITIAL && - !(conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED)) { - conn->flags |= NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED; + !(conn->flags & NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED)) { + conn->flags |= NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED; if (!conn->server) { conn->dcid.current.cid = hd.scid; } @@ -6623,7 +6562,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, break; case NGTCP2_FRAME_CRYPTO: if (!conn->server && !conn->negotiated_version && - ngtcp2_vec_len(fr->crypto.data, fr->crypto.datacnt)) { + ngtcp2_vec_len(fr->stream.data, fr->stream.datacnt)) { conn->negotiated_version = hd.version; ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, @@ -6631,7 +6570,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, conn->negotiated_version); } - rv = conn_recv_crypto(conn, crypto_level, crypto, &fr->crypto); + rv = conn_recv_crypto(conn, encryption_level, crypto, &fr->stream); if (rv != 0) { return rv; } @@ -6653,9 +6592,9 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_qlog_write_frame(&conn->qlog, fr); } - if (conn->server && hd.type == NGTCP2_PKT_HANDSHAKE) { - /* Successful processing of Handshake packet from client verifies - source address. */ + if (hd.type == NGTCP2_PKT_HANDSHAKE) { + /* Successful processing of Handshake packet from a remote + endpoint validates its source address. */ conn->dcid.current.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED; } @@ -6668,14 +6607,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, pktns_increase_ecn_counts(pktns, pi); - /* TODO Initial and Handshake are always acknowledged without - delay. */ - if (require_ack && - (++pktns->acktr.rx_npkt >= conn->local.settings.ack_thresh || - (pi->ecn & NGTCP2_ECN_MASK) == NGTCP2_ECN_CE)) { - ngtcp2_acktr_immediate_ack(&pktns->acktr); - } - + /* Initial and Handshake are always acknowledged without delay. No + need to call ngtcp2_acktr_immediate_ack(). */ rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack, pkt_ts); if (rv != 0) { @@ -6740,7 +6673,7 @@ static ngtcp2_ssize conn_recv_handshake_cpkt(ngtcp2_conn *conn, if ((pkt[0] & NGTCP2_HEADER_FORM_BIT) && pktlen > 4) { /* Not a Version Negotiation packet */ - version = ngtcp2_get_uint32(&pkt[1]); + ngtcp2_get_uint32(&version, &pkt[1]); if (ngtcp2_pkt_get_type_long(version, pkt[0]) == NGTCP2_PKT_INITIAL) { if (conn->server) { if (is_unrecoverable_error((int)nread)) { @@ -6863,7 +6796,7 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm, int rv; uint64_t offset; uint32_t sdflags; - int handshake_completed = conn_is_handshake_completed(conn); + int handshake_completed = conn_is_tls_handshake_completed(conn); if (!strm->rx.rob) { return 0; @@ -6892,7 +6825,7 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm, sdflags |= NGTCP2_STREAM_DATA_FLAG_FIN; } if (!handshake_completed) { - sdflags |= NGTCP2_STREAM_DATA_FLAG_EARLY; + sdflags |= NGTCP2_STREAM_DATA_FLAG_0RTT; } rv = conn_call_recv_stream_data(conn, strm, sdflags, offset, data, datalen); @@ -6909,8 +6842,9 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm, * |rx_offset_base| is the offset in the entire TLS handshake stream. * fr->offset specifies the offset in each encryption level. * |max_rx_offset| is, if it is nonzero, the maximum offset in the - * entire TLS handshake stream that |fr| can carry. |crypto_level| is - * the encryption level where this data is received. + * entire TLS handshake stream that |fr| can carry. + * |encryption_level| is the encryption level where this data is + * received. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -6926,8 +6860,9 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm, * NGTCP2_ERR_CALLBACK_FAILURE * User-defined callback function failed. */ -static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, - ngtcp2_strm *crypto, const ngtcp2_crypto *fr) { +static int conn_recv_crypto(ngtcp2_conn *conn, + ngtcp2_encryption_level encryption_level, + ngtcp2_strm *crypto, const ngtcp2_stream *fr) { uint64_t fr_end_offset; uint64_t rx_offset; int rv; @@ -6947,8 +6882,9 @@ static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, if (fr_end_offset <= rx_offset) { if (conn->server && !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_EARLY_RETRANSMIT) && - crypto_level == NGTCP2_CRYPTO_LEVEL_INITIAL) { - /* recovery draft: Speeding Up Handshake Completion + encryption_level == NGTCP2_ENCRYPTION_LEVEL_INITIAL) { + /* https://datatracker.ietf.org/doc/html/rfc9002#section-6.2.3: + Speeding Up Handshake Completion When a server receives an Initial packet containing duplicate CRYPTO data, it can assume the client did not receive all of @@ -6979,17 +6915,16 @@ static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, uint64_t offset = rx_offset; rx_offset += datalen; - rv = ngtcp2_strm_update_rx_offset(crypto, rx_offset); - if (rv != 0) { - return rv; - } + ngtcp2_strm_update_rx_offset(crypto, rx_offset); - rv = conn_call_recv_crypto_data(conn, crypto_level, offset, data, datalen); + rv = conn_call_recv_crypto_data(conn, encryption_level, offset, data, + datalen); if (rv != 0) { return rv; } - rv = conn_emit_pending_crypto_data(conn, crypto_level, crypto, rx_offset); + rv = conn_emit_pending_crypto_data(conn, encryption_level, crypto, + rx_offset); if (rv != 0) { return rv; } @@ -7099,21 +7034,22 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { if (strm == NULL) { return NGTCP2_ERR_NOMEM; } - /* TODO Perhaps, call new_stream callback? */ + rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL); if (rv != 0) { ngtcp2_objalloc_strm_release(&conn->strm_objalloc, strm); return rv; } + if (!bidi) { + ngtcp2_strm_shutdown(strm, NGTCP2_STRM_FLAG_SHUT_WR); + strm->flags |= NGTCP2_STRM_FLAG_FIN_ACKED; + } + rv = conn_call_stream_open(conn, strm); if (rv != 0) { return rv; } - - if (!bidi) { - ngtcp2_strm_shutdown(strm, NGTCP2_STRM_FLAG_SHUT_WR); - } } fr_end_offset = fr->offset + datalen; @@ -7144,7 +7080,7 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { return NGTCP2_ERR_FINAL_SIZE; } - if (strm->flags & NGTCP2_STRM_FLAG_RECV_RST) { + if (strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM_RECVED) { return 0; } @@ -7170,7 +7106,7 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { return 0; } - if (strm->flags & NGTCP2_STRM_FLAG_RECV_RST) { + if (strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM_RECVED) { return 0; } } @@ -7185,11 +7121,8 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { data = fr->data[0].base + ncut; datalen -= ncut; - rx_offset += datalen; - rv = ngtcp2_strm_update_rx_offset(strm, rx_offset); - if (rv != 0) { - return rv; - } + rx_offset += datalen; + ngtcp2_strm_update_rx_offset(strm, rx_offset); } else { data = NULL; datalen = 0; @@ -7206,8 +7139,8 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { if (fin) { sdflags |= NGTCP2_STREAM_DATA_FLAG_FIN; } - if (!conn_is_handshake_completed(conn)) { - sdflags |= NGTCP2_STREAM_DATA_FLAG_EARLY; + if (!conn_is_tls_handshake_completed(conn)) { + sdflags |= NGTCP2_STREAM_DATA_FLAG_0RTT; } rv = conn_call_recv_stream_data(conn, strm, sdflags, offset, data, (size_t)datalen); @@ -7220,7 +7153,7 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { return rv; } } - } else if (fr->datacnt) { + } else if (fr->datacnt && !(strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING)) { rv = ngtcp2_strm_recv_reordering(strm, fr->data[0].base, fr->data[0].len, fr->offset); if (rv != 0) { @@ -7242,25 +7175,16 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { */ static int conn_reset_stream(ngtcp2_conn *conn, ngtcp2_strm *strm, uint64_t app_error_code) { - int rv; - ngtcp2_frame_chain *frc; - ngtcp2_pktns *pktns = &conn->pktns; + strm->flags |= NGTCP2_STRM_FLAG_SEND_RESET_STREAM; + strm->tx.reset_stream_app_error_code = app_error_code; - rv = ngtcp2_frame_chain_objalloc_new(&frc, &conn->frc_objalloc); - if (rv != 0) { - return rv; + if (ngtcp2_strm_is_tx_queued(strm)) { + return 0; } - frc->fr.type = NGTCP2_FRAME_RESET_STREAM; - frc->fr.reset_stream.stream_id = strm->stream_id; - frc->fr.reset_stream.app_error_code = app_error_code; - frc->fr.reset_stream.final_size = strm->tx.offset; - - /* TODO This prepends RESET_STREAM to pktns->tx.frq. */ - frc->next = pktns->tx.frq; - pktns->tx.frq = frc; + strm->cycle = conn_tx_strmq_first_cycle(conn); - return 0; + return ngtcp2_conn_tx_strmq_push(conn, strm); } /* @@ -7275,24 +7199,16 @@ static int conn_reset_stream(ngtcp2_conn *conn, ngtcp2_strm *strm, */ static int conn_stop_sending(ngtcp2_conn *conn, ngtcp2_strm *strm, uint64_t app_error_code) { - int rv; - ngtcp2_frame_chain *frc; - ngtcp2_pktns *pktns = &conn->pktns; + strm->flags |= NGTCP2_STRM_FLAG_SEND_STOP_SENDING; + strm->tx.stop_sending_app_error_code = app_error_code; - rv = ngtcp2_frame_chain_objalloc_new(&frc, &conn->frc_objalloc); - if (rv != 0) { - return rv; + if (ngtcp2_strm_is_tx_queued(strm)) { + return 0; } - frc->fr.type = NGTCP2_FRAME_STOP_SENDING; - frc->fr.stop_sending.stream_id = strm->stream_id; - frc->fr.stop_sending.app_error_code = app_error_code; - - /* TODO This prepends STOP_SENDING to pktns->tx.frq. */ - frc->next = pktns->tx.frq; - pktns->tx.frq = frc; + strm->cycle = conn_tx_strmq_first_cycle(conn); - return 0; + return ngtcp2_conn_tx_strmq_push(conn, strm); } /* @@ -7396,27 +7312,20 @@ static int conn_recv_reset_stream(ngtcp2_conn *conn, } /* Stream is reset before we create ngtcp2_strm object. */ - conn->rx.offset += fr->final_size; - ngtcp2_conn_extend_max_offset(conn, fr->final_size); - - rv = conn_call_stream_reset(conn, fr->stream_id, fr->final_size, - fr->app_error_code, NULL); + strm = ngtcp2_objalloc_strm_get(&conn->strm_objalloc); + if (strm == NULL) { + return NGTCP2_ERR_NOMEM; + } + rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL); if (rv != 0) { + ngtcp2_objalloc_strm_release(&conn->strm_objalloc, strm); return rv; } - /* There will be no activity in this stream because we got - RESET_STREAM and don't write stream data any further. This - effectively allows another new stream for peer. */ - if (bidi) { - handle_max_remote_streams_extension(&conn->remote.bidi.unsent_max_streams, - 1); - } else { - handle_max_remote_streams_extension(&conn->remote.uni.unsent_max_streams, - 1); + rv = conn_call_stream_open(conn, strm); + if (rv != 0) { + return rv; } - - return 0; } if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD)) { @@ -7427,7 +7336,7 @@ static int conn_recv_reset_stream(ngtcp2_conn *conn, return NGTCP2_ERR_FINAL_SIZE; } - if (strm->flags & NGTCP2_STRM_FLAG_RECV_RST) { + if (strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM_RECVED) { return 0; } @@ -7458,7 +7367,8 @@ static int conn_recv_reset_stream(ngtcp2_conn *conn, ngtcp2_conn_extend_max_offset(conn, datalen); strm->rx.last_offset = fr->final_size; - strm->flags |= NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_RECV_RST; + strm->flags |= + NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_RESET_STREAM_RECVED; ngtcp2_strm_set_app_error_code(strm, fr->app_error_code); @@ -7524,7 +7434,7 @@ static int conn_recv_stop_sending(ngtcp2_conn *conn, return 0; } - /* Frame is received reset before we create ngtcp2_strm + /* STOP_SENDING frame is received before we create ngtcp2_strm object. */ strm = ngtcp2_objalloc_strm_get(&conn->strm_objalloc); if (strm == NULL) { @@ -7542,24 +7452,26 @@ static int conn_recv_stop_sending(ngtcp2_conn *conn, } } + if (strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING_RECVED) { + return 0; + } + ngtcp2_strm_set_app_error_code(strm, fr->app_error_code); /* No RESET_STREAM is required if we have sent FIN and all data have been acknowledged. */ if (!ngtcp2_strm_is_all_tx_data_fin_acked(strm) && - !(strm->flags & NGTCP2_STRM_FLAG_SENT_RST)) { + !(strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM)) { + strm->flags |= NGTCP2_STRM_FLAG_RESET_STREAM; + rv = conn_reset_stream(conn, strm, fr->app_error_code); if (rv != 0) { return rv; } } - strm->flags |= NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_SENT_RST; - - if (ngtcp2_strm_is_tx_queued(strm) && !ngtcp2_strm_streamfrq_empty(strm)) { - assert(conn->tx.strmq_nretrans); - --conn->tx.strmq_nretrans; - } + strm->flags |= + NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_STOP_SENDING_RECVED; ngtcp2_strm_streamfrq_clear(strm); @@ -8042,11 +7954,11 @@ static int conn_recv_new_token(ngtcp2_conn *conn, const ngtcp2_new_token *fr) { return NGTCP2_ERR_PROTO; } - if (fr->token.len == 0) { + if (fr->tokenlen == 0) { return NGTCP2_ERR_FRAME_ENCODING; } - return conn_call_recv_new_token(conn, &fr->token); + return conn_call_recv_new_token(conn, fr->token, fr->tokenlen); } /* @@ -8087,6 +7999,144 @@ static int conn_recv_streams_blocked_uni(ngtcp2_conn *conn, return 0; } +/* + * conn_recv_stream_data_blocked processes the incoming + * STREAM_DATA_BLOCKED frame |fr|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_STREAM_STATE + * STREAM_DATA_BLOCKED is received for a local stream which is not + * initiated; or it is received for a local unidirectional stream. + * NGTCP2_ERR_STREAM_LIMIT + * STREAM_DATA_BLOCKED has remote stream ID which is strictly + * greater than the allowed limit. + * NGTCP2_ERR_FLOW_CONTROL + * STREAM_DATA_BLOCKED frame violates flow control limit. + * NGTCP2_ERR_FINAL_SIZE + * The offset is strictly larger than it is permitted. + * NGTCP2_ERR_NOMEM + * Out of memory. + * NGTCP2_ERR_CALLBACK_FAILURE + * User-defined callback function failed. + */ +static int conn_recv_stream_data_blocked(ngtcp2_conn *conn, + ngtcp2_stream_data_blocked *fr) { + int rv; + ngtcp2_strm *strm; + ngtcp2_idtr *idtr; + int local_stream = conn_local_stream(conn, fr->stream_id); + int bidi = bidi_stream(fr->stream_id); + uint64_t datalen; + + if (bidi) { + if (local_stream) { + if (conn->local.bidi.next_stream_id <= fr->stream_id) { + return NGTCP2_ERR_STREAM_STATE; + } + } else if (conn->remote.bidi.max_streams < + ngtcp2_ord_stream_id(fr->stream_id)) { + return NGTCP2_ERR_STREAM_LIMIT; + } + + idtr = &conn->remote.bidi.idtr; + } else { + if (local_stream) { + return NGTCP2_ERR_STREAM_STATE; + } + if (conn->remote.uni.max_streams < ngtcp2_ord_stream_id(fr->stream_id)) { + return NGTCP2_ERR_STREAM_LIMIT; + } + + idtr = &conn->remote.uni.idtr; + } + + strm = ngtcp2_conn_find_stream(conn, fr->stream_id); + if (strm == NULL) { + if (local_stream) { + return 0; + } + + rv = ngtcp2_idtr_open(idtr, fr->stream_id); + if (rv != 0) { + if (ngtcp2_err_is_fatal(rv)) { + return rv; + } + assert(rv == NGTCP2_ERR_STREAM_IN_USE); + return 0; + } + + /* Frame is received before we create ngtcp2_strm object. */ + strm = ngtcp2_objalloc_strm_get(&conn->strm_objalloc); + if (strm == NULL) { + return NGTCP2_ERR_NOMEM; + } + rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL); + if (rv != 0) { + ngtcp2_objalloc_strm_release(&conn->strm_objalloc, strm); + return rv; + } + + if (!bidi) { + ngtcp2_strm_shutdown(strm, NGTCP2_STRM_FLAG_SHUT_WR); + strm->flags |= NGTCP2_STRM_FLAG_FIN_ACKED; + } + + rv = conn_call_stream_open(conn, strm); + if (rv != 0) { + return rv; + } + } + + if (strm->rx.max_offset < fr->offset) { + return NGTCP2_ERR_FLOW_CONTROL; + } + + if (fr->offset <= strm->rx.last_offset) { + return 0; + } + + if (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) { + return NGTCP2_ERR_FINAL_SIZE; + } + + datalen = fr->offset - strm->rx.last_offset; + if (datalen) { + if (conn_max_data_violated(conn, datalen)) { + return NGTCP2_ERR_FLOW_CONTROL; + } + + conn->rx.offset += datalen; + + if (strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING) { + ngtcp2_conn_extend_max_offset(conn, datalen); + } + } + + strm->rx.last_offset = fr->offset; + + return 0; +} + +/* + * conn_recv_data_blocked processes the incoming DATA_BLOCKED frame + * |fr|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_FLOW_CONTROL + * It violates connection-level flow control limit. + */ +static int conn_recv_data_blocked(ngtcp2_conn *conn, ngtcp2_data_blocked *fr) { + if (conn->rx.max_offset < fr->offset) { + return NGTCP2_ERR_FLOW_CONTROL; + } + + return 0; +} + /* * conn_select_preferred_addr asks a client application to select a * server address from preferred addresses received from server. If a @@ -8103,7 +8153,6 @@ static int conn_recv_streams_blocked_uni(ngtcp2_conn *conn, static int conn_select_preferred_addr(ngtcp2_conn *conn) { ngtcp2_path_storage ps; int rv; - ngtcp2_duration pto, initial_pto, timeout; ngtcp2_pv *pv; ngtcp2_dcid *dcid; @@ -8129,12 +8178,8 @@ static int conn_select_preferred_addr(ngtcp2_conn *conn) { dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0); ngtcp2_dcid_set_path(dcid, &ps.path); - pto = conn_compute_pto(conn, &conn->pktns); - initial_pto = conn_compute_initial_pto(conn, &conn->pktns); - timeout = 3 * ngtcp2_max(pto, initial_pto); - - rv = ngtcp2_pv_new(&pv, dcid, timeout, NGTCP2_PV_FLAG_PREFERRED_ADDR, - &conn->log, conn->mem); + rv = ngtcp2_pv_new(&pv, dcid, conn_compute_pv_timeout(conn), + NGTCP2_PV_FLAG_PREFERRED_ADDR, &conn->log, conn->mem); if (rv != 0) { /* TODO Call ngtcp2_dcid_free here if it is introduced */ return rv; @@ -8180,7 +8225,7 @@ static int conn_recv_handshake_done(ngtcp2_conn *conn, ngtcp2_tstamp ts) { assert(conn->remote.transport_params); - if (conn->remote.transport_params->preferred_address_present) { + if (conn->remote.transport_params->preferred_addr_present) { rv = conn_select_preferred_addr(conn); if (rv != 0) { return rv; @@ -8225,6 +8270,8 @@ static int conn_key_phase_changed(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd) { !(hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE); } +static int conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts); + /* * conn_prepare_key_update installs new updated keys. */ @@ -8241,12 +8288,12 @@ static int conn_prepare_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if ((conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) && tx_ckm->use_count >= pktns->crypto.ctx.max_encryption && - ngtcp2_conn_initiate_key_update(conn, ts) != 0) { + conn_initiate_key_update(conn, ts) != 0) { return NGTCP2_ERR_AEAD_LIMIT_REACHED; } if ((conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED) || - (confirmed_ts != UINT64_MAX && confirmed_ts + pto > ts)) { + ngtcp2_tstamp_not_elapsed(confirmed_ts, pto, ts)) { return 0; } @@ -8369,7 +8416,7 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, ngtcp2_dcid dcid, *bound_dcid, *last; ngtcp2_pv *pv; int rv; - ngtcp2_duration pto, initial_pto, timeout; + ngtcp2_duration pto; int require_new_cid; int local_addr_eq; uint32_t remote_addr_cmp; @@ -8427,10 +8474,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "non-probing packet was received from new remote address"); - pto = conn_compute_pto(conn, &conn->pktns); - initial_pto = conn_compute_initial_pto(conn, &conn->pktns); - timeout = 3 * ngtcp2_max(pto, initial_pto); - len = ngtcp2_ringbuf_len(&conn->dcid.bound.rb); for (i = 0; i < len; ++i) { @@ -8482,13 +8525,16 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, dcid.bytes_recv = 0; dcid.flags &= (uint8_t)~NGTCP2_DCID_FLAG_PATH_VALIDATED; } + + ngtcp2_dcid_set_path(&dcid, path); } - ngtcp2_dcid_set_path(&dcid, path); dcid.bytes_recv += dgramlen; - rv = ngtcp2_pv_new(&pv, &dcid, timeout, NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE, - &conn->log, conn->mem); + pto = conn_compute_pto(conn, &conn->pktns); + + rv = ngtcp2_pv_new(&pv, &dcid, conn_compute_pv_timeout_pto(conn, pto), + NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE, &conn->log, conn->mem); if (rv != 0) { return rv; } @@ -8507,11 +8553,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, if (!local_addr_eq || (remote_addr_cmp & (NGTCP2_ADDR_COMPARE_FLAG_ADDR | NGTCP2_ADDR_COMPARE_FLAG_FAMILY))) { conn_reset_congestion_state(conn, ts); - } else { - /* For NAT rebinding, keep max_udp_payload_size since client most - likely does not send a padded PATH_CHALLENGE. */ - dcid.max_udp_payload_size = ngtcp2_max( - dcid.max_udp_payload_size, conn->dcid.current.max_udp_payload_size); } ngtcp2_dcid_copy(&conn->dcid.current, &dcid); @@ -8687,12 +8728,8 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, pktns_increase_ecn_counts(pktns, pi); - if (require_ack && - (++pktns->acktr.rx_npkt >= conn->local.settings.ack_thresh || - (pi->ecn & NGTCP2_ECN_MASK) == NGTCP2_ECN_CE)) { - ngtcp2_acktr_immediate_ack(&pktns->acktr); - } - + /* Initial and Handshake are always acknowledged without delay. No + need to call ngtcp2_acktr_immediate_ack(). */ rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd->pkt_num, require_ack, pkt_ts); if (rv != 0) { @@ -8706,6 +8743,61 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, return 0; } +/* + * conn_allow_path_change_under_disable_active_migration returns + * nonzero if a packet from |path| is acceptable under + * disable_active_migration is on. + */ +static int +conn_allow_path_change_under_disable_active_migration(ngtcp2_conn *conn, + const ngtcp2_path *path) { + uint32_t remote_addr_cmp; + const ngtcp2_preferred_addr *paddr; + ngtcp2_addr addr; + + assert(conn->server); + assert(conn->local.transport_params.disable_active_migration); + + /* If local address does not change, it must be passive migration + (NAT rebinding). */ + if (ngtcp2_addr_eq(&conn->dcid.current.ps.path.local, &path->local)) { + remote_addr_cmp = + ngtcp2_addr_compare(&conn->dcid.current.ps.path.remote, &path->remote); + + return (remote_addr_cmp | NGTCP2_ADDR_COMPARE_FLAG_PORT) == + NGTCP2_ADDR_COMPARE_FLAG_PORT; + } + + /* If local address changes, it must be one of the preferred + addresses. */ + + if (!conn->local.transport_params.preferred_addr_present) { + return 0; + } + + paddr = &conn->local.transport_params.preferred_addr; + + if (paddr->ipv4_present) { + ngtcp2_addr_init(&addr, (const ngtcp2_sockaddr *)&paddr->ipv4, + sizeof(paddr->ipv4)); + + if (ngtcp2_addr_eq(&addr, &path->local)) { + return 1; + } + } + + if (paddr->ipv6_present) { + ngtcp2_addr_init(&addr, (const ngtcp2_sockaddr *)&paddr->ipv6, + sizeof(paddr->ipv6)); + + if (ngtcp2_addr_eq(&addr, &path->local)) { + return 1; + } + } + + return 0; +} + /* * conn_recv_pkt processes a packet contained in the buffer pointed by * |pkt| of length |pktlen|. |pkt| may contain multiple QUIC packets. @@ -8769,6 +8861,15 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, int new_cid_used = 0; int path_challenge_recved = 0; + if (conn->server && conn->local.transport_params.disable_active_migration && + !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) && + !conn_allow_path_change_under_disable_active_migration(conn, path)) { + ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, + "packet is discarded because active migration is disabled"); + + return NGTCP2_ERR_DISCARD_PKT; + } + if (pkt[0] & NGTCP2_HEADER_FORM_BIT) { nread = ngtcp2_pkt_decode_hd_long(&hd, pkt, pktlen); if (nread < 0) { @@ -8788,6 +8889,10 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, return NGTCP2_ERR_DISCARD_PKT; } + if (conn_verify_fixed_bit(conn, &hd) != 0) { + return NGTCP2_ERR_DISCARD_PKT; + } + pktlen = (size_t)nread + hd.len; /* Quoted from spec: if subsequent packets of those types include @@ -8854,6 +8959,10 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, return NGTCP2_ERR_DISCARD_PKT; } + if (conn_verify_fixed_bit(conn, &hd) != 0) { + return NGTCP2_ERR_DISCARD_PKT; + } + pktns = &conn->pktns; aead = &pktns->crypto.ctx.aead; hp = &pktns->crypto.ctx.hp; @@ -8884,7 +8993,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, payloadlen = pktlen - hdpktlen; hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, - pkt_num_bits(hd.pkt_numlen)); + hd.pkt_numlen); if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); @@ -9020,7 +9129,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, break; default: /* Unreachable */ - assert(0); + ngtcp2_unreachable(); } } else { rv = conn_verify_dcid(conn, &new_cid_used, &hd); @@ -9118,8 +9227,8 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, non_probing_pkt = 1; break; case NGTCP2_FRAME_CRYPTO: - rv = conn_recv_crypto(conn, NGTCP2_CRYPTO_LEVEL_APPLICATION, - &pktns->crypto.strm, &fr->crypto); + rv = conn_recv_crypto(conn, NGTCP2_ENCRYPTION_LEVEL_1RTT, + &pktns->crypto.strm, &fr->stream); if (rv != 0) { return rv; } @@ -9221,8 +9330,18 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } non_probing_pkt = 1; break; + case NGTCP2_FRAME_STREAM_DATA_BLOCKED: + rv = conn_recv_stream_data_blocked(conn, &fr->stream_data_blocked); + if (rv != 0) { + return rv; + } + non_probing_pkt = 1; + break; case NGTCP2_FRAME_DATA_BLOCKED: - /* TODO Not implemented yet */ + rv = conn_recv_data_blocked(conn, &fr->data_blocked); + if (rv != 0) { + return rv; + } non_probing_pkt = 1; break; case NGTCP2_FRAME_DATAGRAM: @@ -9468,7 +9587,7 @@ static int conn_sync_stream_data_limit(ngtcp2_conn *conn) { static int conn_handshake_completed(ngtcp2_conn *conn) { int rv; - conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED; + conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED; rv = conn_call_handshake_completed(conn); if (rv != 0) { @@ -9637,8 +9756,8 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, } } - if (conn_is_handshake_completed(conn) && - !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED)) { + if (conn_is_tls_handshake_completed(conn) && + !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) { rv = conn_handshake_completed(conn); if (rv != 0) { return rv; @@ -9658,27 +9777,22 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, } /* - * Client ServerHello might not fit into single Initial packet - * (e.g., resuming session with client authentication). If we get - * Client Initial which does not increase offset or it is 0RTT - * packet buffered, perform address validation in order to buffer + * Client Hello might not fit into single Initial packet (e.g., + * resuming session with client authentication). If we get Client + * Initial which does not increase offset or it is 0RTT packet + * buffered, perform address validation in order to buffer * validated data only. */ if (ngtcp2_strm_rx_offset(&conn->in_pktns->crypto.strm) == 0) { if (conn->in_pktns->crypto.strm.rx.rob && ngtcp2_rob_data_buffered(conn->in_pktns->crypto.strm.rx.rob)) { /* Address has been validated with token */ - if (conn->local.settings.token.len) { + if (conn->local.settings.tokenlen) { return nread; } return NGTCP2_ERR_RETRY; } - if (conn->in_pktns->rx.buffed_pkts) { - /* 0RTT is buffered, force retry */ - return NGTCP2_ERR_RETRY; - } - /* If neither CRYPTO frame nor 0RTT packet is processed, just - drop connection. */ + /* If CRYPTO frame is not processed, just drop connection. */ return NGTCP2_ERR_DROP_CONN; } @@ -9711,7 +9825,7 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, conn_discard_initial_state(conn, ts); } - if (!conn_is_handshake_completed(conn)) { + if (!conn_is_tls_handshake_completed(conn)) { /* If server hits amplification limit, it cancels loss detection timer. If server receives a packet from client, the limit is increased and server can send more. If server has @@ -9814,8 +9928,9 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, const ngtcp2_pkt_info zero_pi = {0}; (void)pkt_info_version; - conn->log.last_ts = ts; - conn->qlog.last_ts = ts; + assert(!(conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING)); + + conn_update_timestamp(conn, ts); ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "recv packet len=%zu", pktlen); @@ -9840,7 +9955,6 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, switch (conn->state) { case NGTCP2_CS_CLIENT_INITIAL: case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE: - case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED: nread = conn_read_handshake(conn, path, pi, pkt, pktlen, ts); if (nread < 0) { return (int)nread; @@ -9858,7 +9972,6 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, break; case NGTCP2_CS_SERVER_INITIAL: case NGTCP2_CS_SERVER_WAIT_HANDSHAKE: - case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED: if (!ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "ignore packet from unknown path during handshake"); @@ -9899,8 +10012,7 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, } break; default: - assert(0); - abort(); + ngtcp2_unreachable(); } return conn_recv_cpkt(conn, path, pi, pkt, pktlen, ts); @@ -9979,7 +10091,7 @@ static int conn_validate_early_transport_params_limits(ngtcp2_conn *conn) { /* * conn_write_handshake writes QUIC handshake packets to the buffer * pointed by |dest| of length |destlen|. |write_datalen| specifies - * the expected length of 0RTT or 1RTT packet payload. Specify 0 to + * the expected length of 0RTT packet payload. Specify 0 to * |write_datalen| if there is no such data. * * This function returns the number of bytes written to the buffer, or @@ -10054,7 +10166,7 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (!conn_handshake_probe_left(conn) && conn_cwnd_is_zero(conn)) { destlen = 0; } else { - if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED)) { + if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) { pending_early_datalen = conn_retry_early_payloadlen(conn); if (pending_early_datalen) { write_datalen = pending_early_datalen; @@ -10072,7 +10184,7 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, destlen -= (size_t)nwrite; } - if (!conn_is_handshake_completed(conn)) { + if (!conn_is_tls_handshake_completed(conn)) { if (!(conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED)) { nwrite = conn_retransmit_retry_early(conn, pi, dest, destlen, NGTCP2_WRITE_PKT_FLAG_NONE, ts); @@ -10094,6 +10206,10 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return res; } + if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) { + return res; + } + if (!(conn->flags & NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED)) { return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM; } @@ -10117,10 +10233,10 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, assert(conn->remote.transport_params); - if (conn->remote.transport_params->preferred_address_present) { + if (conn->remote.transport_params->preferred_addr_present) { assert(!ngtcp2_ringbuf_full(&conn->dcid.unused.rb)); - paddr = &conn->remote.transport_params->preferred_address; + paddr = &conn->remote.transport_params->preferred_addr; dcid = ngtcp2_ringbuf_push_back(&conn->dcid.unused.rb); ngtcp2_dcid_init(dcid, 1, &paddr->cid, paddr->stateless_reset_token); @@ -10245,19 +10361,10 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn, switch (vmsg->type) { case NGTCP2_VMSG_TYPE_STREAM: datalen = ngtcp2_vec_len(vmsg->stream.data, vmsg->stream.datacnt); - send_stream = - conn_retry_early_payloadlen(conn) == 0 && - /* 0 length STREAM frame is allowed */ - (datalen == 0 || - (datalen > 0 && - (vmsg->stream.strm->tx.max_offset - vmsg->stream.strm->tx.offset) && - (conn->tx.max_offset - conn->tx.offset))); + send_stream = conn_retry_early_payloadlen(conn) == 0; if (send_stream) { - write_datalen = - conn_enforce_flow_control(conn, vmsg->stream.strm, datalen); - write_datalen = - ngtcp2_min(write_datalen, NGTCP2_MIN_COALESCED_PAYLOADLEN); - write_datalen += NGTCP2_STREAM_OVERHEAD; + write_datalen = ngtcp2_min(datalen + NGTCP2_STREAM_OVERHEAD, + NGTCP2_MIN_COALESCED_PAYLOADLEN); if (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_MORE) { wflags |= NGTCP2_WRITE_PKT_FLAG_MORE; @@ -10302,8 +10409,6 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_get_type_long(version, dest[0]) == NGTCP2_PKT_INITIAL) { wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; conn->pkt.require_padding = 1; - } else { - conn->pkt.require_padding = 0; } } else { assert(!conn->pktns.crypto.rx.ckm); @@ -10325,11 +10430,17 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn, early_spktlen = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_0RTT, wflags, ts); - if (early_spktlen < 0) { switch (early_spktlen) { case NGTCP2_ERR_STREAM_DATA_BLOCKED: - return spktlen; + if (!(wflags & NGTCP2_WRITE_PKT_FLAG_MORE)) { + if (spktlen) { + return spktlen; + } + + break; + } + /* fall through */ case NGTCP2_ERR_WRITE_MORE: conn->pkt.hs_spktlen = spktlen; break; @@ -10340,16 +10451,16 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn, return spktlen + early_spktlen; } -void ngtcp2_conn_handshake_completed(ngtcp2_conn *conn) { - conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED; +void ngtcp2_conn_tls_handshake_completed(ngtcp2_conn *conn) { + conn->flags |= NGTCP2_CONN_FLAG_TLS_HANDSHAKE_COMPLETED; if (conn->server) { conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED; } } int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn) { - return conn_is_handshake_completed(conn) && - (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED); + return conn_is_tls_handshake_completed(conn) && + (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED); } int ngtcp2_conn_sched_ack(ngtcp2_conn *conn, ngtcp2_acktr *acktr, @@ -10391,14 +10502,17 @@ int ngtcp2_accept(ngtcp2_pkt_hd *dest, const uint8_t *pkt, size_t pktlen) { case NGTCP2_PKT_0RTT: /* 0-RTT packet may arrive before Initial packet due to re-ordering. ngtcp2 does not buffer 0RTT packet unless the - very first Initial packet is received or token is received. */ - return NGTCP2_ERR_RETRY; + very first Initial packet is received or token is received. + Previously, we returned NGTCP2_ERR_RETRY here, so that client + can resend 0RTT data. But it incurs 1RTT already and + diminishes the value of 0RTT. Therefore, we just discard the + packet here for now. */ default: return NGTCP2_ERR_INVALID_ARGUMENT; } if (pktlen < NGTCP2_MAX_UDP_PAYLOAD_SIZE || - (p->token.len == 0 && p->dcid.datalen < NGTCP2_MIN_INITIAL_DCIDLEN)) { + (p->tokenlen == 0 && p->dcid.datalen < NGTCP2_MIN_INITIAL_DCIDLEN)) { return NGTCP2_ERR_INVALID_ARGUMENT; } @@ -10526,7 +10640,7 @@ int ngtcp2_conn_install_rx_handshake_key( pktns->crypto.rx.hp_ctx = *hp_ctx; - rv = conn_call_recv_rx_key(conn, NGTCP2_CRYPTO_LEVEL_HANDSHAKE); + rv = conn_call_recv_rx_key(conn, NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE); if (rv != 0) { ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, conn->mem); pktns->crypto.rx.ckm = NULL; @@ -10565,7 +10679,7 @@ int ngtcp2_conn_install_tx_handshake_key( } } - rv = conn_call_recv_tx_key(conn, NGTCP2_CRYPTO_LEVEL_HANDSHAKE); + rv = conn_call_recv_tx_key(conn, NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE); if (rv != 0) { ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem); pktns->crypto.tx.ckm = NULL; @@ -10578,10 +10692,10 @@ int ngtcp2_conn_install_tx_handshake_key( return 0; } -int ngtcp2_conn_install_early_key(ngtcp2_conn *conn, - const ngtcp2_crypto_aead_ctx *aead_ctx, - const uint8_t *iv, size_t ivlen, - const ngtcp2_crypto_cipher_ctx *hp_ctx) { +int ngtcp2_conn_install_0rtt_key(ngtcp2_conn *conn, + const ngtcp2_crypto_aead_ctx *aead_ctx, + const uint8_t *iv, size_t ivlen, + const ngtcp2_crypto_cipher_ctx *hp_ctx) { int rv; assert(ivlen >= 8); @@ -10599,9 +10713,9 @@ int ngtcp2_conn_install_early_key(ngtcp2_conn *conn, conn->flags |= NGTCP2_CONN_FLAG_EARLY_KEY_INSTALLED; if (conn->server) { - rv = conn_call_recv_rx_key(conn, NGTCP2_CRYPTO_LEVEL_EARLY); + rv = conn_call_recv_rx_key(conn, NGTCP2_ENCRYPTION_LEVEL_0RTT); } else { - rv = conn_call_recv_tx_key(conn, NGTCP2_CRYPTO_LEVEL_EARLY); + rv = conn_call_recv_tx_key(conn, NGTCP2_ENCRYPTION_LEVEL_0RTT); } if (rv != 0) { ngtcp2_crypto_km_del(conn->early.ckm, conn->mem); @@ -10650,7 +10764,7 @@ int ngtcp2_conn_install_rx_key(ngtcp2_conn *conn, const uint8_t *secret, } } - rv = conn_call_recv_rx_key(conn, NGTCP2_CRYPTO_LEVEL_APPLICATION); + rv = conn_call_recv_rx_key(conn, NGTCP2_ENCRYPTION_LEVEL_1RTT); if (rv != 0) { ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, conn->mem); pktns->crypto.rx.ckm = NULL; @@ -10696,7 +10810,7 @@ int ngtcp2_conn_install_tx_key(ngtcp2_conn *conn, const uint8_t *secret, conn_discard_early_key(conn); } - rv = conn_call_recv_tx_key(conn, NGTCP2_CRYPTO_LEVEL_APPLICATION); + rv = conn_call_recv_tx_key(conn, NGTCP2_ENCRYPTION_LEVEL_1RTT); if (rv != 0) { ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem); pktns->crypto.tx.ckm = NULL; @@ -10709,7 +10823,7 @@ int ngtcp2_conn_install_tx_key(ngtcp2_conn *conn, const uint8_t *secret, return 0; } -int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { +static int conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { ngtcp2_tstamp confirmed_ts = conn->crypto.key_update.confirmed_ts; ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns); @@ -10719,7 +10833,7 @@ int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { (conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED) || !conn->crypto.key_update.new_tx_ckm || !conn->crypto.key_update.new_rx_ckm || - (confirmed_ts != UINT64_MAX && confirmed_ts + 3 * pto > ts)) { + ngtcp2_tstamp_not_elapsed(confirmed_ts, 3 * pto, ts)) { return NGTCP2_ERR_INVALID_STATE; } @@ -10728,6 +10842,12 @@ int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { return 0; } +int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { + conn_update_timestamp(conn, ts); + + return conn_initiate_key_update(conn, ts); +} + /* * conn_retire_stale_bound_dcid retires stale destination connection * ID in conn->dcid.bound to keep some unused destination connection @@ -10751,7 +10871,7 @@ static int conn_retire_stale_bound_dcid(ngtcp2_conn *conn, assert(dcid->cid.datalen); - if (dcid->bound_ts + timeout > ts) { + if (ngtcp2_tstamp_not_elapsed(dcid->bound_ts, timeout, ts)) { ++i; continue; } @@ -10846,8 +10966,10 @@ ngtcp2_tstamp ngtcp2_conn_ack_delay_expiry(ngtcp2_conn *conn) { } static ngtcp2_tstamp conn_handshake_expiry(ngtcp2_conn *conn) { - if (conn_is_handshake_completed(conn) || - conn->local.settings.handshake_timeout == UINT64_MAX) { + if (conn_is_tls_handshake_completed(conn) || + conn->local.settings.handshake_timeout == UINT64_MAX || + conn->local.settings.initial_ts >= + UINT64_MAX - conn->local.settings.handshake_timeout) { return UINT64_MAX; } @@ -10874,7 +10996,13 @@ ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn) { int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts) { int rv; - ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns); + ngtcp2_duration pto; + + conn_update_timestamp(conn, ts); + + pto = conn_compute_pto(conn, &conn->pktns); + + assert(!(conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING)); if (ngtcp2_conn_get_idle_expiry(conn) <= ts) { return NGTCP2_ERR_IDLE_CLOSE; @@ -10919,17 +11047,13 @@ int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts) { } if (conn->server && conn->early.ckm && - conn->early.discard_started_ts != UINT64_MAX) { - if (conn->early.discard_started_ts + 3 * pto <= ts) { - conn_discard_early_key(conn); - } + ngtcp2_tstamp_elapsed(conn->early.discard_started_ts, 3 * pto, ts)) { + conn_discard_early_key(conn); } - if (!conn_is_handshake_completed(conn) && - conn->local.settings.handshake_timeout != UINT64_MAX && - conn->local.settings.initial_ts + - conn->local.settings.handshake_timeout <= - ts) { + if (!conn_is_tls_handshake_completed(conn) && + ngtcp2_tstamp_elapsed(conn->local.settings.initial_ts, + conn->local.settings.handshake_timeout, ts)) { return NGTCP2_ERR_HANDSHAKE_TIMEOUT; } @@ -10940,8 +11064,7 @@ static void acktr_cancel_expired_ack_delay_timer(ngtcp2_acktr *acktr, ngtcp2_duration max_ack_delay, ngtcp2_tstamp ts) { if (!(acktr->flags & NGTCP2_ACKTR_FLAG_CANCEL_TIMER) && - acktr->first_unacked_ts != UINT64_MAX && - acktr->first_unacked_ts + max_ack_delay <= ts) { + ngtcp2_tstamp_elapsed(acktr->first_unacked_ts, max_ack_delay, ts)) { acktr->flags |= NGTCP2_ACKTR_FLAG_CANCEL_TIMER; } } @@ -11006,32 +11129,35 @@ void ngtcp2_conn_remove_lost_pkt(ngtcp2_conn *conn, ngtcp2_tstamp ts) { * select_preferred_version selects the most preferred version. * |fallback_version| is chosen if no preference is made, or * |preferred_versions| does not include any of |chosen_version| or - * |other_versions|. |chosen_version| is treated as an extra other - * version. + * |available_versions|. |chosen_version| is treated as an extra + * other version. */ static uint32_t select_preferred_version(const uint32_t *preferred_versions, size_t preferred_versionslen, uint32_t chosen_version, - const uint8_t *other_versions, - size_t other_versionslen, + const uint8_t *available_versions, + size_t available_versionslen, uint32_t fallback_version) { size_t i, j; + const uint8_t *p; + uint32_t v; if (!preferred_versionslen || - (!other_versionslen && chosen_version == fallback_version)) { + (!available_versionslen && chosen_version == fallback_version)) { return fallback_version; } for (i = 0; i < preferred_versionslen; ++i) { if (preferred_versions[i] == chosen_version) { return chosen_version; - } - for (j = 0; j < other_versionslen; j += sizeof(uint32_t)) { - if (preferred_versions[i] != ngtcp2_get_uint32(&other_versions[j])) { - continue; - } + } + for (j = 0, p = available_versions; j < available_versionslen; + j += sizeof(uint32_t)) { + p = ngtcp2_get_uint32(&v, p); - return preferred_versions[i]; + if (preferred_versions[i] == v) { + return v; + } } } @@ -11054,6 +11180,10 @@ static uint32_t select_preferred_version(const uint32_t *preferred_versions, static int conn_client_validate_transport_params(ngtcp2_conn *conn, const ngtcp2_transport_params *params) { + if (!params->original_dcid_present) { + return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM; + } + if (!ngtcp2_cid_eq(&conn->rcid, ¶ms->original_dcid)) { return NGTCP2_ERR_TRANSPORT_PARAM; } @@ -11069,8 +11199,7 @@ conn_client_validate_transport_params(ngtcp2_conn *conn, return NGTCP2_ERR_TRANSPORT_PARAM; } - if (params->preferred_address_present && - conn->dcid.current.cid.datalen == 0) { + if (params->preferred_addr_present && conn->dcid.current.cid.datalen == 0) { return NGTCP2_ERR_TRANSPORT_PARAM; } @@ -11079,21 +11208,31 @@ conn_client_validate_transport_params(ngtcp2_conn *conn, return NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE; } - assert(vneg_other_versions_includes(conn->vneg.other_versions, - conn->vneg.other_versionslen, - conn->negotiated_version)); - } else if (conn->client_chosen_version != conn->negotiated_version || - conn->client_chosen_version != - conn->local.settings.original_version) { + assert(vneg_available_versions_includes(conn->vneg.available_versions, + conn->vneg.available_versionslen, + conn->negotiated_version)); + } else if (conn->client_chosen_version != conn->negotiated_version) { return NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE; } /* When client reacted upon Version Negotiation */ if (conn->local.settings.original_version != conn->client_chosen_version) { - assert(params->version_info_present); + if (!params->version_info_present) { + assert(conn->client_chosen_version == conn->negotiated_version); + + /* QUIC v1 is treated specially. If version_info is missing, no + further validation is necessary. See + https://datatracker.ietf.org/doc/html/rfc9368#section-8 + */ + if (conn->client_chosen_version == NGTCP2_PROTO_VER_V1) { + return 0; + } + + return NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE; + } - /* Server choose original version after Version Negotiation. - Draft does not say this particular case, but this smells like + /* Server choose original version after Version Negotiation. RFC + 9368 does not say this particular case, but this smells like misbehaved server because server should accept original_version in the original connection. */ if (conn->local.settings.original_version == @@ -11102,7 +11241,7 @@ conn_client_validate_transport_params(ngtcp2_conn *conn, } /* Check version downgrade on incompatible version negotiation. */ - if (params->version_info.other_versionslen == 0) { + if (params->version_info.available_versionslen == 0) { return NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE; } @@ -11110,8 +11249,8 @@ conn_client_validate_transport_params(ngtcp2_conn *conn, select_preferred_version(conn->vneg.preferred_versions, conn->vneg.preferred_versionslen, params->version_info.chosen_version, - params->version_info.other_versions, - params->version_info.other_versionslen, + params->version_info.available_versions, + params->version_info.available_versionslen, /* fallback_version = */ 0)) { return NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE; } @@ -11128,8 +11267,8 @@ ngtcp2_conn_server_negotiate_version(ngtcp2_conn *conn, return select_preferred_version( conn->vneg.preferred_versions, conn->vneg.preferred_versionslen, - version_info->chosen_version, version_info->other_versions, - version_info->other_versionslen, version_info->chosen_version); + version_info->chosen_version, version_info->available_versions, + version_info->available_versionslen, version_info->chosen_version); } int ngtcp2_conn_set_remote_transport_params( @@ -11145,7 +11284,11 @@ int ngtcp2_conn_set_remote_transport_params( return 0; } - /* Assume that ngtcp2_decode_transport_params sets default value if + if (!params->initial_scid_present) { + return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM; + } + + /* Assume that ngtcp2_transport_params_decode sets default value if active_connection_id_limit is omitted. */ if (params->active_connection_id_limit < NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) { @@ -11164,7 +11307,20 @@ int ngtcp2_conn_set_remote_transport_params( } if (conn->server) { + if (params->original_dcid_present || + params->stateless_reset_token_present || + params->preferred_addr_present || params->retry_scid_present) { + return NGTCP2_ERR_TRANSPORT_PARAM; + } + if (params->version_info_present) { + if (!vneg_available_versions_includes( + params->version_info.available_versions, + params->version_info.available_versionslen, + params->version_info.chosen_version)) { + return NGTCP2_ERR_TRANSPORT_PARAM; + } + if (params->version_info.chosen_version != conn->client_chosen_version) { return NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE; } @@ -11195,11 +11351,7 @@ int ngtcp2_conn_set_remote_transport_params( } } - ngtcp2_log_remote_tp(&conn->log, - conn->server - ? NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO - : NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS, - params); + ngtcp2_log_remote_tp(&conn->log, params); ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, params, conn->server, NGTCP2_QLOG_SIDE_REMOTE); @@ -11231,17 +11383,13 @@ int ngtcp2_conn_set_remote_transport_params( return 0; } -int ngtcp2_conn_decode_remote_transport_params(ngtcp2_conn *conn, - const uint8_t *data, - size_t datalen) { +int ngtcp2_conn_decode_and_set_remote_transport_params(ngtcp2_conn *conn, + const uint8_t *data, + size_t datalen) { ngtcp2_transport_params params; int rv; - rv = ngtcp2_decode_transport_params( - ¶ms, - conn->server ? NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO - : NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS, - data, datalen); + rv = ngtcp2_transport_params_decode(¶ms, data, datalen); if (rv != 0) { return rv; } @@ -11258,20 +11406,72 @@ ngtcp2_conn_get_remote_transport_params(ngtcp2_conn *conn) { return conn->remote.transport_params; } -void ngtcp2_conn_set_early_remote_transport_params_versioned( - ngtcp2_conn *conn, int transport_params_version, - const ngtcp2_transport_params *params) { +ngtcp2_ssize ngtcp2_conn_encode_0rtt_transport_params(ngtcp2_conn *conn, + uint8_t *dest, + size_t destlen) { + ngtcp2_transport_params params, *src; + + if (conn->server) { + src = &conn->local.transport_params; + } else { + assert(conn->remote.transport_params); + + src = conn->remote.transport_params; + } + + ngtcp2_transport_params_default(¶ms); + + params.initial_max_streams_bidi = src->initial_max_streams_bidi; + params.initial_max_streams_uni = src->initial_max_streams_uni; + params.initial_max_stream_data_bidi_local = + src->initial_max_stream_data_bidi_local; + params.initial_max_stream_data_bidi_remote = + src->initial_max_stream_data_bidi_remote; + params.initial_max_stream_data_uni = src->initial_max_stream_data_uni; + params.initial_max_data = src->initial_max_data; + params.active_connection_id_limit = src->active_connection_id_limit; + params.max_datagram_frame_size = src->max_datagram_frame_size; + + if (conn->server) { + params.max_idle_timeout = src->max_idle_timeout; + params.max_udp_payload_size = src->max_udp_payload_size; + params.disable_active_migration = src->disable_active_migration; + } + + return ngtcp2_transport_params_encode(dest, destlen, ¶ms); +} + +int ngtcp2_conn_decode_and_set_0rtt_transport_params(ngtcp2_conn *conn, + const uint8_t *data, + size_t datalen) { + ngtcp2_transport_params params; + int rv; + + rv = ngtcp2_transport_params_decode(¶ms, data, datalen); + if (rv != 0) { + return rv; + } + + return ngtcp2_conn_set_0rtt_remote_transport_params(conn, ¶ms); +} + +int ngtcp2_conn_set_0rtt_remote_transport_params( + ngtcp2_conn *conn, const ngtcp2_transport_params *params) { ngtcp2_transport_params *p; - (void)transport_params_version; assert(!conn->server); assert(!conn->remote.transport_params); /* Assume that all pointer fields in p are NULL */ p = ngtcp2_mem_calloc(conn->mem, 1, sizeof(*p)); + if (p == NULL) { + return NGTCP2_ERR_NOMEM; + } conn->remote.transport_params = p; + ngtcp2_transport_params_default(conn->remote.transport_params); + p->initial_max_streams_bidi = params->initial_max_streams_bidi; p->initial_max_streams_uni = params->initial_max_streams_uni; p->initial_max_stream_data_bidi_local = @@ -11280,18 +11480,17 @@ void ngtcp2_conn_set_early_remote_transport_params_versioned( params->initial_max_stream_data_bidi_remote; p->initial_max_stream_data_uni = params->initial_max_stream_data_uni; p->initial_max_data = params->initial_max_data; + /* we might hit garbage, then set the sane default. */ p->active_connection_id_limit = ngtcp2_max(NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT, params->active_connection_id_limit); - p->max_idle_timeout = params->max_idle_timeout; - if (!params->max_udp_payload_size) { - p->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; - } else { + p->max_datagram_frame_size = params->max_datagram_frame_size; + + /* we might hit garbage, then set the sane default. */ + if (params->max_udp_payload_size) { p->max_udp_payload_size = ngtcp2_max(NGTCP2_MAX_UDP_PAYLOAD_SIZE, params->max_udp_payload_size); } - p->disable_active_migration = params->disable_active_migration; - p->max_datagram_frame_size = params->max_datagram_frame_size; /* These parameters are treated specially. If server accepts early data, it must not set values for these parameters that are @@ -11318,14 +11517,21 @@ void ngtcp2_conn_set_early_remote_transport_params_versioned( ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, p, conn->server, NGTCP2_QLOG_SIDE_REMOTE); + + return 0; } int ngtcp2_conn_set_local_transport_params_versioned( ngtcp2_conn *conn, int transport_params_version, const ngtcp2_transport_params *params) { - (void)transport_params_version; + ngtcp2_transport_params paramsbuf; + + params = ngtcp2_transport_params_convert_to_latest( + ¶msbuf, transport_params_version, params); assert(conn->server); + assert(params->active_connection_id_limit >= + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT); assert(params->active_connection_id_limit <= NGTCP2_MAX_DCID_POOL_SIZE); if (conn->hs_pktns == NULL || conn->hs_pktns->crypto.tx.ckm) { @@ -11345,24 +11551,20 @@ int ngtcp2_conn_commit_local_transport_params(ngtcp2_conn *conn) { assert(1 == ngtcp2_ksl_len(&conn->scid.set)); - if (params->active_connection_id_limit == 0) { - params->active_connection_id_limit = - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; - } - params->initial_scid = conn->oscid; + params->initial_scid_present = 1; if (conn->oscid.datalen == 0) { - params->preferred_address_present = 0; + params->preferred_addr_present = 0; } - if (conn->server && params->preferred_address_present) { + if (conn->server && params->preferred_addr_present) { scident = ngtcp2_mem_malloc(mem, sizeof(*scident)); if (scident == NULL) { return NGTCP2_ERR_NOMEM; } - ngtcp2_scid_init(scident, 1, ¶ms->preferred_address.cid); + ngtcp2_scid_init(scident, 1, ¶ms->preferred_addr.cid); rv = ngtcp2_ksl_insert(&conn->scid.set, NULL, &scident->cid, scident); if (rv != 0) { @@ -11396,11 +11598,8 @@ ngtcp2_conn_get_local_transport_params(ngtcp2_conn *conn) { ngtcp2_ssize ngtcp2_conn_encode_local_transport_params(ngtcp2_conn *conn, uint8_t *dest, size_t destlen) { - return ngtcp2_encode_transport_params( - dest, destlen, - conn->server ? NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS - : NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO, - &conn->local.transport_params); + return ngtcp2_transport_params_encode(dest, destlen, + &conn->local.transport_params); } int ngtcp2_conn_open_bidi_stream(ngtcp2_conn *conn, int64_t *pstream_id, @@ -11485,7 +11684,6 @@ static ngtcp2_ssize conn_write_vmsg_wrapper(ngtcp2_conn *conn, ngtcp2_tstamp ts) { ngtcp2_conn_stat *cstat = &conn->cstat; ngtcp2_ssize nwrite; - int undersized; nwrite = ngtcp2_conn_write_vmsg(conn, path, pkt_info_version, pi, dest, destlen, vmsg, ts); @@ -11497,20 +11695,11 @@ static ngtcp2_ssize conn_write_vmsg_wrapper(ngtcp2_conn *conn, conn->rst.is_cwnd_limited = 1; } - if (vmsg == NULL && cstat->bytes_in_flight < cstat->cwnd && - conn->tx.strmq_nretrans == 0) { - if (conn->local.settings.no_udp_payload_size_shaping) { - undersized = (size_t)nwrite < conn->local.settings.max_udp_payload_size; - } else { - undersized = (size_t)nwrite < conn->dcid.current.max_udp_payload_size; - } + if (nwrite == 0 && cstat->bytes_in_flight < cstat->cwnd) { + conn->rst.app_limited = conn->rst.delivered + cstat->bytes_in_flight; - if (undersized) { - conn->rst.app_limited = conn->rst.delivered + cstat->bytes_in_flight; - - if (conn->rst.app_limited == 0) { - conn->rst.app_limited = cstat->max_udp_payload_size; - } + if (conn->rst.app_limited == 0) { + conn->rst.app_limited = cstat->max_tx_udp_payload_size; } } @@ -11566,6 +11755,21 @@ ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( destlen, pvmsg, ts); } +ngtcp2_ssize ngtcp2_conn_write_datagram_versioned( + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, + uint32_t flags, uint64_t dgram_id, const uint8_t *data, size_t datalen, + ngtcp2_tstamp ts) { + ngtcp2_vec datav; + + datav.len = datalen; + datav.base = (uint8_t *)data; + + return ngtcp2_conn_writev_datagram_versioned(conn, path, pkt_info_version, pi, + dest, destlen, paccepted, flags, + dgram_id, &datav, 1, ts); +} + ngtcp2_ssize ngtcp2_conn_writev_datagram_versioned( ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, @@ -11584,8 +11788,12 @@ ngtcp2_ssize ngtcp2_conn_writev_datagram_versioned( } datalen = ngtcp2_vec_len_varint(datav, datavcnt); - if (datalen == -1 || (uint64_t)datalen > SIZE_MAX) { - return NGTCP2_ERR_INVALID_STATE; + if (datalen == -1 +#if UINT64_MAX > SIZE_MAX + || (uint64_t)datalen > SIZE_MAX +#endif /* UINT64_MAX > SIZE_MAX */ + ) { + return NGTCP2_ERR_INVALID_ARGUMENT; } if (conn->remote.transport_params->max_datagram_frame_size < @@ -11617,15 +11825,12 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_conn_stat *cstat = &conn->cstat; ngtcp2_ssize res = 0; uint64_t server_tx_left; - uint64_t datalen; - uint64_t write_datalen = 0; int64_t prev_in_pkt_num = -1; ngtcp2_ksl_it it; ngtcp2_rtb_entry *rtbent; (void)pkt_info_version; - conn->log.last_ts = ts; - conn->qlog.last_ts = ts; + conn_update_timestamp(conn, ts); if (path) { ngtcp2_path_copy(path, &conn->dcid.current.ps.path); @@ -11638,14 +11843,15 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, pi->ecn = NGTCP2_ECN_NOT_ECT; } - if (!conn_pacing_pkt_tx_allowed(conn, ts)) { - return 0; - } - switch (conn->state) { case NGTCP2_CS_CLIENT_INITIAL: case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE: - case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED: + if (!conn_pacing_pkt_tx_allowed(conn, ts)) { + assert(!ppe_pending); + + return conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts); + } + nwrite = conn_client_write_handshake(conn, pi, dest, destlen, vmsg, ts); /* We might be unable to write a packet because of depletion of congestion window budget, perhaps due to packet loss that @@ -11675,14 +11881,28 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, break; case NGTCP2_CS_SERVER_INITIAL: case NGTCP2_CS_SERVER_WAIT_HANDSHAKE: - case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED: + if (!conn_pacing_pkt_tx_allowed(conn, ts)) { + assert(!ppe_pending); + + if (!(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) { + server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); + if (server_tx_left == 0) { + return 0; + } + + origlen = (size_t)ngtcp2_min((uint64_t)origlen, server_tx_left); + } + + return conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts); + } + if (!ppe_pending) { if (!(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) { server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); if (server_tx_left == 0) { if (cstat->loss_detection_timer != UINT64_MAX) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_RCV, + &conn->log, NGTCP2_LOG_EVENT_LDC, "loss detection timer canceled due to amplification limit"); cstat->loss_detection_timer = UINT64_MAX; } @@ -11693,40 +11913,16 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, destlen = (size_t)ngtcp2_min((uint64_t)destlen, server_tx_left); } - if (vmsg) { - switch (vmsg->type) { - case NGTCP2_VMSG_TYPE_STREAM: - datalen = ngtcp2_vec_len(vmsg->stream.data, vmsg->stream.datacnt); - if (datalen == 0 || (datalen > 0 && - (vmsg->stream.strm->tx.max_offset - - vmsg->stream.strm->tx.offset) && - (conn->tx.max_offset - conn->tx.offset))) { - write_datalen = - conn_enforce_flow_control(conn, vmsg->stream.strm, datalen); - write_datalen = - ngtcp2_min(write_datalen, NGTCP2_MIN_COALESCED_PAYLOADLEN); - write_datalen += NGTCP2_STREAM_OVERHEAD; - } - break; - case NGTCP2_VMSG_TYPE_DATAGRAM: - write_datalen = - ngtcp2_vec_len(vmsg->datagram.data, vmsg->datagram.datacnt) + - NGTCP2_DATAGRAM_OVERHEAD; - break; - default: - assert(0); - } - - if (conn->in_pktns && write_datalen > 0) { - it = ngtcp2_rtb_head(&conn->in_pktns->rtb); - if (!ngtcp2_ksl_it_end(&it)) { - rtbent = ngtcp2_ksl_it_get(&it); - prev_in_pkt_num = rtbent->hd.pkt_num; - } + if (conn->in_pktns) { + it = ngtcp2_rtb_head(&conn->in_pktns->rtb); + if (!ngtcp2_ksl_it_end(&it)) { + rtbent = ngtcp2_ksl_it_get(&it); + prev_in_pkt_num = rtbent->hd.pkt_num; } } - nwrite = conn_write_handshake(conn, pi, dest, destlen, write_datalen, ts); + nwrite = conn_write_handshake(conn, pi, dest, destlen, + /* write_datalen = */ 0, ts); if (nwrite < 0) { return nwrite; } @@ -11735,7 +11931,7 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, dest += nwrite; destlen -= (size_t)nwrite; - if (conn->in_pktns && write_datalen > 0) { + if (conn->in_pktns && nwrite > 0) { it = ngtcp2_rtb_head(&conn->in_pktns->rtb); if (!ngtcp2_ksl_it_end(&it)) { rtbent = ngtcp2_ksl_it_get(&it); @@ -11748,12 +11944,27 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, } } } - if (conn->state != NGTCP2_CS_POST_HANDSHAKE && - conn->pktns.crypto.tx.ckm == NULL) { + if (conn->pktns.crypto.tx.ckm == NULL) { return res; } break; case NGTCP2_CS_POST_HANDSHAKE: + if (!conn_pacing_pkt_tx_allowed(conn, ts)) { + assert(!ppe_pending); + + if (conn->server && + !(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) { + server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); + if (server_tx_left == 0) { + return 0; + } + + origlen = (size_t)ngtcp2_min((uint64_t)origlen, server_tx_left); + } + + return conn_write_ack_pkt(conn, pi, dest, origlen, NGTCP2_PKT_1RTT, ts); + } + break; case NGTCP2_CS_CLOSING: return NGTCP2_ERR_CLOSING; @@ -11788,7 +11999,6 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, if (ppe_pending) { res = conn->pkt.hs_spktlen; - conn->pkt.hs_spktlen = 0; if (conn->pkt.require_padding) { wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } @@ -11827,35 +12037,44 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, } if (conn->pmtud && + (conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED) && (!conn->hs_pktns || - ngtcp2_ksl_len(&conn->hs_pktns->crypto.tx.frq) == 0)) { + ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm))) { nwrite = conn_write_pmtud_probe(conn, pi, dest, origdestlen, ts); if (nwrite) { goto fin; } } } + } - if (conn->server && - !(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) { - server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); - origlen = (size_t)ngtcp2_min((uint64_t)origlen, server_tx_left); - destlen = (size_t)ngtcp2_min((uint64_t)destlen, server_tx_left); + if (conn->server && + !(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) { + server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); + origlen = (size_t)ngtcp2_min((uint64_t)origlen, server_tx_left); + destlen = (size_t)ngtcp2_min((uint64_t)destlen, server_tx_left); - if (server_tx_left == 0 && - conn->cstat.loss_detection_timer != UINT64_MAX) { - ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_RCV, - "loss detection timer canceled due to amplification limit"); - conn->cstat.loss_detection_timer = UINT64_MAX; - } + if (server_tx_left == 0 && + conn->cstat.loss_detection_timer != UINT64_MAX) { + ngtcp2_log_info( + &conn->log, NGTCP2_LOG_EVENT_LDC, + "loss detection timer canceled due to amplification limit"); + conn->cstat.loss_detection_timer = UINT64_MAX; } } } if (res == 0) { if (conn_handshake_remnants_left(conn)) { - if (conn_handshake_probe_left(conn)) { + if (conn_handshake_probe_left(conn) || + /* Allow exceeding CWND if an Handshake packet needs to be + sent in order to avoid dead lock. In some situation, + typically for client, 1 RTT packets may occupy in-flight + bytes (e.g., some large requests and PMTUD), and + Handshake packet loss shrinks CWND, and we may get in the + situation that we are unable to send Handshake packet. */ + (conn->hs_pktns->rtb.num_pto_eliciting == 0 && + !ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm))) { destlen = origlen; } nwrite = conn_write_handshake_pkts(conn, pi, dest, destlen, @@ -11867,6 +12086,11 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, res = nwrite; dest += nwrite; destlen -= (size_t)nwrite; + } else if (destlen == 0) { + res = conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts); + if (res) { + return res; + } } } } @@ -11894,16 +12118,24 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, } fin: - conn->pkt.hs_spktlen = 0; - if (nwrite >= 0) { res += nwrite; return res; } - /* NGTCP2_CONN_FLAG_PPE_PENDING is set in conn_write_pkt above. - ppe_pending cannot be used here. */ - if (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING) { + + switch (nwrite) { + case NGTCP2_ERR_STREAM_DATA_BLOCKED: + if (!(wflags & NGTCP2_WRITE_PKT_FLAG_MORE)) { + if (res) { + return res; + } + + break; + } + /* fall through */ + case NGTCP2_ERR_WRITE_MORE: conn->pkt.hs_spktlen = res; + break; } return nwrite; @@ -11989,9 +12221,6 @@ ngtcp2_ssize ngtcp2_conn_write_connection_close_pkt( ngtcp2_ssize nwrite; uint64_t server_tx_left; - conn->log.last_ts = ts; - conn->qlog.last_ts = ts; - if (conn_check_pkt_num_exhausted(conn)) { return NGTCP2_ERR_PKT_NUM_EXHAUSTED; } @@ -12054,9 +12283,6 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( ngtcp2_frame fr; uint64_t server_tx_left; - conn->log.last_ts = ts; - conn->qlog.last_ts = ts; - if (conn_check_pkt_num_exhausted(conn)) { return NGTCP2_ERR_PKT_NUM_EXHAUSTED; } @@ -12135,11 +12361,9 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( return res; } -static void -connection_close_error_init(ngtcp2_connection_close_error *ccerr, - ngtcp2_connection_close_error_code_type type, - uint64_t error_code, const uint8_t *reason, - size_t reasonlen) { +static void ccerr_init(ngtcp2_ccerr *ccerr, ngtcp2_ccerr_type type, + uint64_t error_code, const uint8_t *reason, + size_t reasonlen) { ccerr->type = type; ccerr->error_code = error_code; ccerr->frame_type = 0; @@ -12147,72 +12371,63 @@ connection_close_error_init(ngtcp2_connection_close_error *ccerr, ccerr->reasonlen = reasonlen; } -void ngtcp2_connection_close_error_default( - ngtcp2_connection_close_error *ccerr) { - connection_close_error_init(ccerr, - NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT, - NGTCP2_NO_ERROR, NULL, 0); +void ngtcp2_ccerr_default(ngtcp2_ccerr *ccerr) { + ccerr_init(ccerr, NGTCP2_CCERR_TYPE_TRANSPORT, NGTCP2_NO_ERROR, NULL, 0); } -void ngtcp2_connection_close_error_set_transport_error( - ngtcp2_connection_close_error *ccerr, uint64_t error_code, - const uint8_t *reason, size_t reasonlen) { - connection_close_error_init(ccerr, - NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT, - error_code, reason, reasonlen); +void ngtcp2_ccerr_set_transport_error(ngtcp2_ccerr *ccerr, uint64_t error_code, + const uint8_t *reason, size_t reasonlen) { + ccerr_init(ccerr, NGTCP2_CCERR_TYPE_TRANSPORT, error_code, reason, reasonlen); } -void ngtcp2_connection_close_error_set_transport_error_liberr( - ngtcp2_connection_close_error *ccerr, int liberr, const uint8_t *reason, - size_t reasonlen) { +void ngtcp2_ccerr_set_liberr(ngtcp2_ccerr *ccerr, int liberr, + const uint8_t *reason, size_t reasonlen) { switch (liberr) { case NGTCP2_ERR_RECV_VERSION_NEGOTIATION: - connection_close_error_init( - ccerr, - NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_VERSION_NEGOTIATION, - NGTCP2_NO_ERROR, reason, reasonlen); + ccerr_init(ccerr, NGTCP2_CCERR_TYPE_VERSION_NEGOTIATION, NGTCP2_NO_ERROR, + reason, reasonlen); return; case NGTCP2_ERR_IDLE_CLOSE: - connection_close_error_init( - ccerr, NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_IDLE_CLOSE, - NGTCP2_NO_ERROR, reason, reasonlen); + ccerr_init(ccerr, NGTCP2_CCERR_TYPE_IDLE_CLOSE, NGTCP2_NO_ERROR, reason, + reasonlen); return; }; - ngtcp2_connection_close_error_set_transport_error( + ngtcp2_ccerr_set_transport_error( ccerr, ngtcp2_err_infer_quic_transport_error_code(liberr), reason, reasonlen); } -void ngtcp2_connection_close_error_set_transport_error_tls_alert( - ngtcp2_connection_close_error *ccerr, uint8_t tls_alert, - const uint8_t *reason, size_t reasonlen) { - ngtcp2_connection_close_error_set_transport_error( - ccerr, NGTCP2_CRYPTO_ERROR | tls_alert, reason, reasonlen); +void ngtcp2_ccerr_set_tls_alert(ngtcp2_ccerr *ccerr, uint8_t tls_alert, + const uint8_t *reason, size_t reasonlen) { + ngtcp2_ccerr_set_transport_error(ccerr, NGTCP2_CRYPTO_ERROR | tls_alert, + reason, reasonlen); } -void ngtcp2_connection_close_error_set_application_error( - ngtcp2_connection_close_error *ccerr, uint64_t error_code, - const uint8_t *reason, size_t reasonlen) { - connection_close_error_init( - ccerr, NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION, error_code, - reason, reasonlen); +void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr, + uint64_t error_code, + const uint8_t *reason, + size_t reasonlen) { + ccerr_init(ccerr, NGTCP2_CCERR_TYPE_APPLICATION, error_code, reason, + reasonlen); } ngtcp2_ssize ngtcp2_conn_write_connection_close_versioned( ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, - const ngtcp2_connection_close_error *ccerr, ngtcp2_tstamp ts) { + const ngtcp2_ccerr *ccerr, ngtcp2_tstamp ts) { (void)pkt_info_version; + conn_update_timestamp(conn, ts); + switch (ccerr->type) { - case NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT: + case NGTCP2_CCERR_TYPE_TRANSPORT: return ngtcp2_conn_write_connection_close_pkt( conn, path, pi, dest, destlen, ccerr->error_code, ccerr->reason, ccerr->reasonlen, ts); - case NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION: + case NGTCP2_CCERR_TYPE_APPLICATION: return ngtcp2_conn_write_application_close_pkt( conn, path, pi, dest, destlen, ccerr->error_code, ccerr->reason, ccerr->reasonlen, ts); @@ -12221,51 +12436,46 @@ ngtcp2_ssize ngtcp2_conn_write_connection_close_versioned( } } -int ngtcp2_conn_is_in_closing_period(ngtcp2_conn *conn) { +int ngtcp2_conn_in_closing_period(ngtcp2_conn *conn) { return conn->state == NGTCP2_CS_CLOSING; } -int ngtcp2_conn_is_in_draining_period(ngtcp2_conn *conn) { +int ngtcp2_conn_in_draining_period(ngtcp2_conn *conn) { return conn->state == NGTCP2_CS_DRAINING; } int ngtcp2_conn_close_stream(ngtcp2_conn *conn, ngtcp2_strm *strm) { int rv; - rv = ngtcp2_map_remove(&conn->strms, (ngtcp2_map_key_type)strm->stream_id); + rv = conn_call_stream_close(conn, strm); if (rv != 0) { - assert(rv != NGTCP2_ERR_INVALID_ARGUMENT); return rv; } - rv = conn_call_stream_close(conn, strm); + rv = ngtcp2_map_remove(&conn->strms, (ngtcp2_map_key_type)strm->stream_id); if (rv != 0) { - goto fin; + assert(rv != NGTCP2_ERR_INVALID_ARGUMENT); + return rv; } if (ngtcp2_strm_is_tx_queued(strm)) { ngtcp2_pq_remove(&conn->tx.strmq, &strm->pe); - if (!ngtcp2_strm_streamfrq_empty(strm)) { - assert(conn->tx.strmq_nretrans); - --conn->tx.strmq_nretrans; - } } -fin: ngtcp2_strm_free(strm); ngtcp2_objalloc_strm_release(&conn->strm_objalloc, strm); - return rv; + return 0; } int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm) { if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RDWR) == NGTCP2_STRM_FLAG_SHUT_RDWR && - ((strm->flags & NGTCP2_STRM_FLAG_RECV_RST) || + ((strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM_RECVED) || ngtcp2_strm_rx_offset(strm) == strm->rx.last_offset) && - (((strm->flags & NGTCP2_STRM_FLAG_SENT_RST) && - (strm->flags & NGTCP2_STRM_FLAG_RST_ACKED)) || + (((strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM) && + (strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM_ACKED)) || ngtcp2_strm_is_all_tx_data_fin_acked(strm))) { return ngtcp2_conn_close_stream(conn, strm); } @@ -12286,14 +12496,14 @@ static int conn_shutdown_stream_write(ngtcp2_conn *conn, ngtcp2_strm *strm, uint64_t app_error_code) { ngtcp2_strm_set_app_error_code(strm, app_error_code); - if ((strm->flags & NGTCP2_STRM_FLAG_SENT_RST) || + if ((strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM) || ngtcp2_strm_is_all_tx_data_fin_acked(strm)) { return 0; } /* Set this flag so that we don't accidentally send DATA to this stream. */ - strm->flags |= NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_SENT_RST; + strm->flags |= NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_RESET_STREAM; ngtcp2_strm_streamfrq_clear(strm); @@ -12312,7 +12522,10 @@ static int conn_shutdown_stream_write(ngtcp2_conn *conn, ngtcp2_strm *strm, */ static int conn_shutdown_stream_read(ngtcp2_conn *conn, ngtcp2_strm *strm, uint64_t app_error_code) { - if (strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING) { + ngtcp2_strm_set_app_error_code(strm, app_error_code); + + if (strm->flags & + (NGTCP2_STRM_FLAG_STOP_SENDING | NGTCP2_STRM_FLAG_RESET_STREAM_RECVED)) { return 0; } if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) && @@ -12322,44 +12535,55 @@ static int conn_shutdown_stream_read(ngtcp2_conn *conn, ngtcp2_strm *strm, /* Extend connection flow control window for the amount of data which are not passed to application. */ - if (!(strm->flags & - (NGTCP2_STRM_FLAG_STOP_SENDING | NGTCP2_STRM_FLAG_RECV_RST))) { + if (!(strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM_RECVED)) { ngtcp2_conn_extend_max_offset(conn, strm->rx.last_offset - ngtcp2_strm_rx_offset(strm)); } strm->flags |= NGTCP2_STRM_FLAG_STOP_SENDING; - ngtcp2_strm_set_app_error_code(strm, app_error_code); + + ngtcp2_strm_discard_reordered_data(strm); return conn_stop_sending(conn, strm, app_error_code); } -int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn, int64_t stream_id, - uint64_t app_error_code) { +int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn, uint32_t flags, + int64_t stream_id, uint64_t app_error_code) { int rv; ngtcp2_strm *strm; + (void)flags; strm = ngtcp2_conn_find_stream(conn, stream_id); if (strm == NULL) { return 0; } - rv = conn_shutdown_stream_read(conn, strm, app_error_code); - if (rv != 0) { - return rv; + if (bidi_stream(stream_id) || !conn_local_stream(conn, stream_id)) { + rv = conn_shutdown_stream_read(conn, strm, app_error_code); + if (rv != 0) { + return rv; + } } - rv = conn_shutdown_stream_write(conn, strm, app_error_code); - if (rv != 0) { - return rv; + if (bidi_stream(stream_id) || conn_local_stream(conn, stream_id)) { + rv = conn_shutdown_stream_write(conn, strm, app_error_code); + if (rv != 0) { + return rv; + } } return 0; } -int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn, int64_t stream_id, +int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn, uint32_t flags, + int64_t stream_id, uint64_t app_error_code) { ngtcp2_strm *strm; + (void)flags; + + if (!bidi_stream(stream_id) && !conn_local_stream(conn, stream_id)) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } strm = ngtcp2_conn_find_stream(conn, stream_id); if (strm == NULL) { @@ -12369,9 +12593,15 @@ int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn, int64_t stream_id, return conn_shutdown_stream_write(conn, strm, app_error_code); } -int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn, int64_t stream_id, +int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn, uint32_t flags, + int64_t stream_id, uint64_t app_error_code) { ngtcp2_strm *strm; + (void)flags; + + if (!bidi_stream(stream_id) && conn_local_stream(conn, stream_id)) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } strm = ngtcp2_conn_find_stream(conn, stream_id); if (strm == NULL) { @@ -12421,6 +12651,10 @@ int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn, int64_t stream_id, uint64_t datalen) { ngtcp2_strm *strm; + if (!bidi_stream(stream_id) && conn_local_stream(conn, stream_id)) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } + strm = ngtcp2_conn_find_stream(conn, stream_id); if (strm == NULL) { return 0; @@ -12469,10 +12703,6 @@ static int delete_strms_pq_each(void *data, void *ptr) { if (ngtcp2_strm_is_tx_queued(s)) { ngtcp2_pq_remove(&conn->tx.strmq, &s->pe); - if (!ngtcp2_strm_streamfrq_empty(s)) { - assert(conn->tx.strmq_nretrans); - --conn->tx.strmq_nretrans; - } } ngtcp2_strm_free(s); @@ -12494,6 +12724,7 @@ static void conn_discard_early_data_state(ngtcp2_conn *conn) { ngtcp2_map_clear(&conn->strms); conn->tx.offset = 0; + conn->tx.last_blocked_offset = UINT64_MAX; conn->rx.unsent_max_offset = conn->rx.max_offset = conn->local.transport_params.initial_max_data; @@ -12519,14 +12750,28 @@ static void conn_discard_early_data_state(ngtcp2_conn *conn) { } } -void ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn) { +int ngtcp2_conn_tls_early_data_rejected(ngtcp2_conn *conn) { if (conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED) { - return; + return 0; } conn->flags |= NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED; conn_discard_early_data_state(conn); + + if (conn->callbacks.tls_early_data_rejected) { + return conn->callbacks.tls_early_data_rejected(conn, conn->user_data); + } + + if (conn->early.ckm) { + conn_discard_early_key(conn); + } + + return 0; +} + +int ngtcp2_conn_get_tls_early_data_rejected(ngtcp2_conn *conn) { + return (conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED) != 0; } int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, @@ -12550,7 +12795,7 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, /* Ignore RTT sample if adjusting ack_delay causes the sample less than min_rtt before handshake confirmation. */ ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_RCV, + &conn->log, NGTCP2_LOG_EVENT_LDC, "ignore rtt sample because ack_delay is too large latest_rtt=%" PRIu64 " min_rtt=%" PRIu64 " ack_delay=%" PRIu64, rtt / NGTCP2_MILLISECONDS, cstat->min_rtt / NGTCP2_MILLISECONDS, @@ -12573,7 +12818,7 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, } ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_RCV, + &conn->log, NGTCP2_LOG_EVENT_LDC, "latest_rtt=%" PRIu64 " min_rtt=%" PRIu64 " smoothed_rtt=%" PRIu64 " rttvar=%" PRIu64 " ack_delay=%" PRIu64, cstat->latest_rtt / NGTCP2_MILLISECONDS, @@ -12584,12 +12829,19 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, return 0; } -void ngtcp2_conn_get_conn_stat_versioned(ngtcp2_conn *conn, - int conn_stat_version, - ngtcp2_conn_stat *cstat) { - (void)conn_stat_version; +void ngtcp2_conn_get_conn_info_versioned(ngtcp2_conn *conn, + int conn_info_version, + ngtcp2_conn_info *cinfo) { + const ngtcp2_conn_stat *cstat = &conn->cstat; + (void)conn_info_version; - *cstat = conn->cstat; + cinfo->latest_rtt = cstat->latest_rtt; + cinfo->min_rtt = cstat->min_rtt; + cinfo->smoothed_rtt = cstat->smoothed_rtt; + cinfo->rttvar = cstat->rttvar; + cinfo->cwnd = cstat->cwnd; + cinfo->ssthresh = cstat->ssthresh; + cinfo->bytes_in_flight = cstat->bytes_in_flight; } static void conn_get_loss_time_and_pktns(ngtcp2_conn *conn, @@ -12597,14 +12849,13 @@ static void conn_get_loss_time_and_pktns(ngtcp2_conn *conn, ngtcp2_pktns **ppktns) { ngtcp2_pktns *const ns[] = {conn->hs_pktns, &conn->pktns}; ngtcp2_conn_stat *cstat = &conn->cstat; - ngtcp2_duration *loss_time = cstat->loss_time; - ngtcp2_tstamp earliest_loss_time = loss_time[NGTCP2_PKTNS_ID_INITIAL]; + ngtcp2_duration *loss_time = cstat->loss_time + 1; + ngtcp2_tstamp earliest_loss_time = cstat->loss_time[NGTCP2_PKTNS_ID_INITIAL]; ngtcp2_pktns *pktns = conn->in_pktns; size_t i; - for (i = 0; i < sizeof(ns) / sizeof(ns[0]); ++i) { - if (ns[i] == NULL || ns[i]->rtb.num_pto_eliciting == 0 || - loss_time[i] >= earliest_loss_time) { + for (i = 0; i < ngtcp2_arraylen(ns); ++i) { + if (ns[i] == NULL || loss_time[i] >= earliest_loss_time) { continue; } @@ -12672,7 +12923,7 @@ void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if (earliest_loss_time != UINT64_MAX) { cstat->loss_detection_timer = earliest_loss_time; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, "loss_detection_timer=%" PRIu64 " nonzero crypto loss time", cstat->loss_detection_timer); return; @@ -12686,7 +12937,7 @@ void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { (conn->flags & (NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED | NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)))) { if (cstat->loss_detection_timer != UINT64_MAX) { - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, "loss detection timer canceled"); cstat->loss_detection_timer = UINT64_MAX; cstat->pto_count = 0; @@ -12699,7 +12950,7 @@ void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { timeout = cstat->loss_detection_timer > ts ? cstat->loss_detection_timer - ts : 0; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, "loss_detection_timer=%" PRIu64 " timeout=%" PRIu64, cstat->loss_detection_timer, timeout / NGTCP2_MILLISECONDS); } @@ -12712,9 +12963,6 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { ngtcp2_tstamp earliest_loss_time; ngtcp2_pktns *loss_pktns = NULL; - conn->log.last_ts = ts; - conn->qlog.last_ts = ts; - switch (conn->state) { case NGTCP2_CS_CLOSING: case NGTCP2_CS_DRAINING: @@ -12731,7 +12979,7 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { conn_get_loss_time_and_pktns(conn, &earliest_loss_time, &loss_pktns); - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, "loss detection timer fired"); if (earliest_loss_time != UINT64_MAX) { @@ -12745,7 +12993,7 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { return 0; } - if (!conn->server && !conn_is_handshake_completed(conn)) { + if (!conn->server && !conn_is_tls_handshake_completed(conn)) { if (hs_pktns->crypto.tx.ckm) { hs_pktns->rtb.probe_pkt_left = 1; } else { @@ -12762,7 +13010,7 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { hs_pktns->rtb.probe_pkt_left = 1; } } else if (hs_pktns && hs_pktns->rtb.num_pto_eliciting) { - hs_pktns->rtb.probe_pkt_left = 1; + hs_pktns->rtb.probe_pkt_left = 2; } else { conn->pktns.rtb.probe_pkt_left = 2; } @@ -12770,7 +13018,7 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { ++cstat->pto_count; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, "pto_count=%zu", + ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, "pto_count=%zu", cstat->pto_count); ngtcp2_conn_set_loss_detection_timer(conn, ts); @@ -12807,27 +13055,27 @@ static int conn_buffer_crypto_data(ngtcp2_conn *conn, const uint8_t **pdata, } int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn, - ngtcp2_crypto_level crypto_level, + ngtcp2_encryption_level encryption_level, const uint8_t *data, const size_t datalen) { ngtcp2_pktns *pktns; ngtcp2_frame_chain *frc; - ngtcp2_crypto *fr; + ngtcp2_stream *fr; int rv; if (datalen == 0) { return 0; } - switch (crypto_level) { - case NGTCP2_CRYPTO_LEVEL_INITIAL: + switch (encryption_level) { + case NGTCP2_ENCRYPTION_LEVEL_INITIAL: assert(conn->in_pktns); pktns = conn->in_pktns; break; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: assert(conn->hs_pktns); pktns = conn->hs_pktns; break; - case NGTCP2_CRYPTO_LEVEL_APPLICATION: + case NGTCP2_ENCRYPTION_LEVEL_1RTT: pktns = &conn->pktns; break; default: @@ -12844,15 +13092,18 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn, return rv; } - fr = &frc->fr.crypto; + fr = &frc->fr.stream; fr->type = NGTCP2_FRAME_CRYPTO; + fr->flags = 0; + fr->fin = 0; + fr->stream_id = 0; fr->offset = pktns->crypto.tx.offset; fr->datacnt = 1; fr->data[0].len = datalen; fr->data[0].base = (uint8_t *)data; - rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &fr->offset, frc); + rv = ngtcp2_strm_streamfrq_push(&pktns->crypto.strm, frc); if (rv != 0) { ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); return rv; @@ -12868,14 +13119,13 @@ int ngtcp2_conn_submit_new_token(ngtcp2_conn *conn, const uint8_t *token, size_t tokenlen) { int rv; ngtcp2_frame_chain *nfrc; - ngtcp2_vec tokenv = {(uint8_t *)token, tokenlen}; assert(conn->server); assert(token); assert(tokenlen); rv = ngtcp2_frame_chain_new_token_objalloc_new( - &nfrc, &tokenv, &conn->frc_objalloc, conn->mem); + &nfrc, token, tokenlen, &conn->frc_objalloc, conn->mem); if (rv != 0) { return rv; } @@ -12902,16 +13152,11 @@ int ngtcp2_conn_tx_strmq_push(ngtcp2_conn *conn, ngtcp2_strm *strm) { return ngtcp2_pq_push(&conn->tx.strmq, &strm->pe); } -static int conn_has_uncommited_preferred_address_cid(ngtcp2_conn *conn) { +static int conn_has_uncommitted_preferred_addr_cid(ngtcp2_conn *conn) { return conn->server && !(conn->flags & NGTCP2_CONN_FLAG_LOCAL_TRANSPORT_PARAMS_COMMITTED) && conn->oscid.datalen && - conn->local.transport_params.preferred_address_present; -} - -size_t ngtcp2_conn_get_num_scid(ngtcp2_conn *conn) { - return ngtcp2_ksl_len(&conn->scid.set) + - (size_t)conn_has_uncommited_preferred_address_cid(conn); + conn->local.transport_params.preferred_addr_present; } size_t ngtcp2_conn_get_scid(ngtcp2_conn *conn, ngtcp2_cid *dest) { @@ -12919,27 +13164,28 @@ size_t ngtcp2_conn_get_scid(ngtcp2_conn *conn, ngtcp2_cid *dest) { ngtcp2_ksl_it it; ngtcp2_scid *scid; + if (dest == NULL) { + return ngtcp2_ksl_len(&conn->scid.set) + + (size_t)conn_has_uncommitted_preferred_addr_cid(conn); + } + for (it = ngtcp2_ksl_begin(&conn->scid.set); !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) { scid = ngtcp2_ksl_it_get(&it); *dest++ = scid->cid; } - if (conn_has_uncommited_preferred_address_cid(conn)) { - *dest++ = conn->local.transport_params.preferred_address.cid; + if (conn_has_uncommitted_preferred_addr_cid(conn)) { + *dest++ = conn->local.transport_params.preferred_addr.cid; } return (size_t)(dest - origdest); } -size_t ngtcp2_conn_get_num_active_dcid(ngtcp2_conn *conn) { +static size_t conn_get_num_active_dcid(ngtcp2_conn *conn) { size_t n = 1; /* for conn->dcid.current */ ngtcp2_pv *pv = conn->pv; - if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED)) { - return 0; - } - if (pv) { if (pv->dcid.seq != conn->dcid.current.seq) { ++n; @@ -12973,10 +13219,14 @@ size_t ngtcp2_conn_get_active_dcid(ngtcp2_conn *conn, ngtcp2_cid_token *dest) { ngtcp2_dcid *dcid; size_t len, i; - if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED)) { + if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) { return 0; } + if (dest == NULL) { + return conn_get_num_active_dcid(conn); + } + copy_dcid_to_cid_token(dest, &conn->dcid.current); ++dest; @@ -13019,13 +13269,13 @@ const ngtcp2_path *ngtcp2_conn_get_path(ngtcp2_conn *conn) { return &conn->dcid.current.ps.path; } -size_t ngtcp2_conn_get_max_udp_payload_size(ngtcp2_conn *conn) { - return conn->local.settings.max_udp_payload_size; +size_t ngtcp2_conn_get_max_tx_udp_payload_size(ngtcp2_conn *conn) { + return conn->local.settings.max_tx_udp_payload_size; } -size_t ngtcp2_conn_get_path_max_udp_payload_size(ngtcp2_conn *conn) { - if (conn->local.settings.no_udp_payload_size_shaping) { - return ngtcp2_conn_get_max_udp_payload_size(conn); +size_t ngtcp2_conn_get_path_max_tx_udp_payload_size(ngtcp2_conn *conn) { + if (conn->local.settings.no_tx_udp_payload_size_shaping) { + return ngtcp2_conn_get_max_tx_udp_payload_size(conn); } return conn->dcid.current.max_udp_payload_size; @@ -13056,11 +13306,11 @@ int ngtcp2_conn_initiate_immediate_migration(ngtcp2_conn *conn, ngtcp2_tstamp ts) { int rv; ngtcp2_dcid *dcid; + ngtcp2_pv *pv; assert(!conn->server); - conn->log.last_ts = ts; - conn->qlog.last_ts = ts; + conn_update_timestamp(conn, ts); rv = conn_initiate_migration_precheck(conn, &path->local); if (rv != 0) { @@ -13087,35 +13337,33 @@ int ngtcp2_conn_initiate_immediate_migration(ngtcp2_conn *conn, ngtcp2_dcid_copy(&conn->dcid.current, dcid); ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb); - rv = conn_call_activate_dcid(conn, &conn->dcid.current); - if (rv != 0) { - return rv; - } - conn_reset_congestion_state(conn, ts); conn_reset_ecn_validation_state(conn); - if (!conn->local.settings.no_pmtud) { - rv = conn_start_pmtud(conn); - if (rv != 0) { - return rv; - } + /* TODO It might be better to add a new flag which indicates that a + connection should be closed if this path validation failed. The + current design allows an application to continue, by migrating + into yet another path. */ + rv = ngtcp2_pv_new(&pv, dcid, conn_compute_pv_timeout(conn), + NGTCP2_PV_FLAG_NONE, &conn->log, conn->mem); + if (rv != 0) { + return rv; } - return 0; + conn->pv = pv; + + return conn_call_activate_dcid(conn, &conn->dcid.current); } int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_tstamp ts) { int rv; ngtcp2_dcid *dcid; - ngtcp2_duration pto, initial_pto, timeout; ngtcp2_pv *pv; assert(!conn->server); - conn->log.last_ts = ts; - conn->qlog.last_ts = ts; + conn_update_timestamp(conn, ts); rv = conn_initiate_migration_precheck(conn, &path->local); if (rv != 0) { @@ -13132,12 +13380,8 @@ int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn, const ngtcp2_path *path, dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0); ngtcp2_dcid_set_path(dcid, path); - pto = conn_compute_pto(conn, &conn->pktns); - initial_pto = conn_compute_initial_pto(conn, &conn->pktns); - timeout = 3 * ngtcp2_max(pto, initial_pto); - - rv = ngtcp2_pv_new(&pv, dcid, timeout, NGTCP2_PV_FLAG_NONE, &conn->log, - conn->mem); + rv = ngtcp2_pv_new(&pv, dcid, conn_compute_pv_timeout(conn), + NGTCP2_PV_FLAG_NONE, &conn->log, conn->mem); if (rv != 0) { return rv; } @@ -13148,10 +13392,6 @@ int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn, const ngtcp2_path *path, return conn_call_activate_dcid(conn, &pv->dcid); } -uint64_t ngtcp2_conn_get_max_local_streams_uni(ngtcp2_conn *conn) { - return conn->local.uni.max_streams; -} - uint64_t ngtcp2_conn_get_max_data_left(ngtcp2_conn *conn) { return conn->tx.max_offset - conn->tx.offset; } @@ -13200,7 +13440,7 @@ ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) { /* TODO Remote max_idle_timeout becomes effective after handshake completion. */ - if (!conn_is_handshake_completed(conn) || + if (!conn_is_tls_handshake_completed(conn) || conn->remote.transport_params->max_idle_timeout == 0 || (conn->local.transport_params.max_idle_timeout && conn->local.transport_params.max_idle_timeout < @@ -13214,16 +13454,23 @@ ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) { return UINT64_MAX; } - trpto = 3 * conn_compute_pto(conn, conn_is_handshake_completed(conn) + trpto = 3 * conn_compute_pto(conn, conn_is_tls_handshake_completed(conn) ? &conn->pktns : conn->hs_pktns); - return conn->idle_ts + ngtcp2_max(idle_timeout, trpto); + idle_timeout = ngtcp2_max(idle_timeout, trpto); + + if (conn->idle_ts >= UINT64_MAX - idle_timeout) { + return UINT64_MAX; + } + + return conn->idle_ts + idle_timeout; } ngtcp2_duration ngtcp2_conn_get_pto(ngtcp2_conn *conn) { - return conn_compute_pto( - conn, conn_is_handshake_completed(conn) ? &conn->pktns : conn->hs_pktns); + return conn_compute_pto(conn, conn_is_tls_handshake_completed(conn) + ? &conn->pktns + : conn->hs_pktns); } void ngtcp2_conn_set_initial_crypto_ctx(ngtcp2_conn *conn, @@ -13257,12 +13504,12 @@ const ngtcp2_crypto_ctx *ngtcp2_conn_get_crypto_ctx(ngtcp2_conn *conn) { return &conn->pktns.crypto.ctx; } -void ngtcp2_conn_set_early_crypto_ctx(ngtcp2_conn *conn, - const ngtcp2_crypto_ctx *ctx) { +void ngtcp2_conn_set_0rtt_crypto_ctx(ngtcp2_conn *conn, + const ngtcp2_crypto_ctx *ctx) { conn->early.ctx = *ctx; } -const ngtcp2_crypto_ctx *ngtcp2_conn_get_early_crypto_ctx(ngtcp2_conn *conn) { +const ngtcp2_crypto_ctx *ngtcp2_conn_get_0rtt_crypto_ctx(ngtcp2_conn *conn) { return &conn->early.ctx; } @@ -13275,9 +13522,8 @@ void ngtcp2_conn_set_tls_native_handle(ngtcp2_conn *conn, conn->crypto.tls_native_handle = tls_native_handle; } -void ngtcp2_conn_get_connection_close_error( - ngtcp2_conn *conn, ngtcp2_connection_close_error *ccerr) { - *ccerr = conn->rx.ccerr; +const ngtcp2_ccerr *ngtcp2_conn_get_ccerr(ngtcp2_conn *conn) { + return &conn->rx.ccerr; } void ngtcp2_conn_set_tls_error(ngtcp2_conn *conn, int liberr) { @@ -13320,13 +13566,29 @@ int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn, int64_t stream_id, } void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts) { - if (!(conn->cstat.pacing_rate > 0) || conn->tx.pacing.pktlen == 0) { + ngtcp2_duration pacing_interval; + ngtcp2_duration wait; + + conn_update_timestamp(conn, ts); + + if (conn->tx.pacing.pktlen == 0) { return; } - conn->tx.pacing.next_ts = - ts + (ngtcp2_duration)((double)conn->tx.pacing.pktlen / - conn->cstat.pacing_rate); + if (conn->cstat.pacing_interval) { + pacing_interval = conn->cstat.pacing_interval; + } else { + /* 1.25 is the under-utilization avoidance factor described in + https://datatracker.ietf.org/doc/html/rfc9002#section-7.7 */ + pacing_interval = (conn->cstat.first_rtt_sample_ts == UINT64_MAX + ? NGTCP2_MILLISECONDS + : conn->cstat.smoothed_rtt) * + 100 / 125 / conn->cstat.cwnd; + } + + wait = (ngtcp2_duration)(conn->tx.pacing.pktlen * pacing_interval); + + conn->tx.pacing.next_ts = ts + wait; conn->tx.pacing.pktlen = 0; } @@ -13338,15 +13600,14 @@ int ngtcp2_conn_track_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { size_t i; if (conn->dcid.retire_unacked.len >= - sizeof(conn->dcid.retire_unacked.seqs) / - sizeof(conn->dcid.retire_unacked.seqs[0])) { + ngtcp2_arraylen(conn->dcid.retire_unacked.seqs)) { return NGTCP2_ERR_CONNECTION_ID_LIMIT; } /* Make sure that we do not have a duplicate */ for (i = 0; i < conn->dcid.retire_unacked.len; ++i) { if (conn->dcid.retire_unacked.seqs[i] == seq) { - assert(0); + ngtcp2_unreachable(); } } @@ -13399,20 +13660,35 @@ void ngtcp2_settings_default_versioned(int settings_version, settings->cc_algo = NGTCP2_CC_ALGO_CUBIC; settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT; settings->ack_thresh = 2; - settings->max_udp_payload_size = 1500 - 48; - settings->handshake_timeout = NGTCP2_DEFAULT_HANDSHAKE_TIMEOUT; + settings->max_tx_udp_payload_size = 1500 - 48; + settings->handshake_timeout = UINT64_MAX; } void ngtcp2_transport_params_default_versioned( int transport_params_version, ngtcp2_transport_params *params) { - (void)transport_params_version; - - memset(params, 0, sizeof(*params)); - params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; - params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; - params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; - params->active_connection_id_limit = - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; + size_t len; + + switch (transport_params_version) { + case NGTCP2_TRANSPORT_PARAMS_VERSION: + len = sizeof(*params); + + break; + default: + ngtcp2_unreachable(); + } + + memset(params, 0, len); + + switch (transport_params_version) { + case NGTCP2_TRANSPORT_PARAMS_VERSION: + params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; + params->active_connection_id_limit = + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; + params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; + params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; + + break; + } } /* The functions prefixed with ngtcp2_pkt_ are usually put inside diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h index b1c6564175d482..4ed67876bc3749 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h @@ -43,7 +43,6 @@ #include "ngtcp2_pq.h" #include "ngtcp2_cc.h" #include "ngtcp2_bbr.h" -#include "ngtcp2_bbr2.h" #include "ngtcp2_pv.h" #include "ngtcp2_pmtud.h" #include "ngtcp2_cid.h" @@ -51,16 +50,15 @@ #include "ngtcp2_ppe.h" #include "ngtcp2_qlog.h" #include "ngtcp2_rst.h" +#include "ngtcp2_conn_stat.h" typedef enum { /* Client specific handshake states */ NGTCP2_CS_CLIENT_INITIAL, NGTCP2_CS_CLIENT_WAIT_HANDSHAKE, - NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED, /* Server specific handshake states */ NGTCP2_CS_SERVER_INITIAL, NGTCP2_CS_SERVER_WAIT_HANDSHAKE, - NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED, /* Shared by both client and server */ NGTCP2_CS_POST_HANDSHAKE, NGTCP2_CS_CLOSING, @@ -111,18 +109,14 @@ typedef enum { to put the sane limit.*/ #define NGTCP2_MAX_SCID_POOL_SIZE 8 -/* NGTCP2_MAX_NON_ACK_TX_PKT is the maximum number of continuous non - ACK-eliciting packets. */ -#define NGTCP2_MAX_NON_ACK_TX_PKT 3 - /* NGTCP2_ECN_MAX_NUM_VALIDATION_PKTS is the maximum number of ECN marked packets sent in NGTCP2_ECN_STATE_TESTING period. */ #define NGTCP2_ECN_MAX_NUM_VALIDATION_PKTS 10 -/* NGTCP2_CONNECTION_CLOSE_ERROR_MAX_REASONLEN is the maximum length - of reason phrase to remember. If the received reason phrase is - longer than this value, it is truncated. */ -#define NGTCP2_CONNECTION_CLOSE_ERROR_MAX_REASONLEN 1024 +/* NGTCP2_CCERR_MAX_REASONLEN is the maximum length of reason phrase + to remember. If the received reason phrase is longer than this + value, it is truncated. */ +#define NGTCP2_CCERR_MAX_REASONLEN 1024 /* NGTCP2_WRITE_PKT_FLAG_NONE indicates that no flag is set. */ #define NGTCP2_WRITE_PKT_FLAG_NONE 0x00u @@ -142,8 +136,8 @@ typedef union ngtcp2_max_frame { ngtcp2_frame fr; struct { ngtcp2_ack ack; - /* ack includes 1 ngtcp2_ack_blk. */ - ngtcp2_ack_blk blks[NGTCP2_MAX_ACK_BLKS - 1]; + /* ack includes 1 ngtcp2_ack_range. */ + ngtcp2_ack_range ranges[NGTCP2_MAX_ACK_RANGES - 1]; } ackfr; } ngtcp2_max_frame; @@ -158,17 +152,17 @@ void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent, /* NGTCP2_CONN_FLAG_NONE indicates that no flag is set. */ #define NGTCP2_CONN_FLAG_NONE 0x00u -/* NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED is set when TLS stack declares - that TLS handshake has completed. The condition of this +/* NGTCP2_CONN_FLAG_TLS_HANDSHAKE_COMPLETED is set when TLS stack + declares that TLS handshake has completed. The condition of this declaration varies between TLS implementations and this flag does not indicate the completion of QUIC handshake. Some implementations declare TLS handshake completion as server when they write off Server Finished and before deriving application rx secret. */ -#define NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED 0x01u -/* NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED is set if connection ID is - negotiated. This is only used for client. */ -#define NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED 0x02u +#define NGTCP2_CONN_FLAG_TLS_HANDSHAKE_COMPLETED 0x01u +/* NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED is set when the first + Initial packet has successfully been processed. */ +#define NGTCP2_CONN_FLAG_INITIAL_PKT_PROCESSED 0x02u /* NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED is set if transport parameters are received. */ #define NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED 0x04u @@ -187,9 +181,9 @@ void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent, /* NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED is set when an endpoint confirmed completion of handshake. */ #define NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED 0x80u -/* NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED is set when the - library transitions its state to "post handshake". */ -#define NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED 0x0100u +/* NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED is set when the library + transitions its state to "post handshake". */ +#define NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED 0x0100u /* NGTCP2_CONN_FLAG_HANDSHAKE_EARLY_RETRANSMIT is set when the early handshake retransmission has done when server receives overlapping Initial crypto data. */ @@ -221,23 +215,15 @@ void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent, endpoint has initiated key update. */ #define NGTCP2_CONN_FLAG_KEY_UPDATE_INITIATOR 0x10000u -typedef struct ngtcp2_crypto_data { - ngtcp2_buf buf; - /* pkt_type is the type of packet to send data in buf. If it is 0, - it must be sent in Short packet. Otherwise, it is sent the long - packet type denoted by pkt_type. */ - uint8_t pkt_type; -} ngtcp2_crypto_data; - typedef struct ngtcp2_pktns { struct { /* last_pkt_num is the packet number which the local endpoint sent last time.*/ int64_t last_pkt_num; ngtcp2_frame_chain *frq; - /* num_non_ack_pkt is the number of continuous non ACK-eliciting - packets. */ - size_t num_non_ack_pkt; + /* non_ack_pkt_start_ts is the timestamp since the local endpoint + starts sending continuous non ACK-eliciting packets. */ + ngtcp2_tstamp non_ack_pkt_start_ts; struct { /* ect0 is the number of QUIC packets, not UDP datagram, which @@ -307,8 +293,6 @@ typedef struct ngtcp2_pktns { struct { struct { - /* frq contains crypto data sorted by their offset. */ - ngtcp2_ksl frq; /* offset is the offset of crypto stream in this packet number space. */ uint64_t offset; @@ -344,6 +328,19 @@ typedef enum ngtcp2_ecn_state { NGTCP2_ECN_STATE_CAPABLE, } ngtcp2_ecn_state; +/* ngtcp2_early_transport_params is the values remembered by client + from the previous session. */ +typedef struct ngtcp2_early_transport_params { + uint64_t initial_max_streams_bidi; + uint64_t initial_max_streams_uni; + uint64_t initial_max_stream_data_bidi_local; + uint64_t initial_max_stream_data_bidi_remote; + uint64_t initial_max_stream_data_uni; + uint64_t initial_max_data; + uint64_t active_connection_id_limit; + uint64_t max_datagram_frame_size; +} ngtcp2_early_transport_params; + ngtcp2_static_ringbuf_def(dcid_bound, NGTCP2_MAX_BOUND_DCID_POOL_SIZE, sizeof(ngtcp2_dcid)); ngtcp2_static_ringbuf_def(dcid_unused, NGTCP2_MAX_DCID_POOL_SIZE, @@ -353,7 +350,7 @@ ngtcp2_static_ringbuf_def(dcid_retired, NGTCP2_MAX_DCID_RETIRED_SIZE, ngtcp2_static_ringbuf_def(path_challenge, 4, sizeof(ngtcp2_path_challenge_entry)); -ngtcp2_objalloc_def(strm, ngtcp2_strm, oplent); +ngtcp2_objalloc_decl(strm, ngtcp2_strm, oplent); struct ngtcp2_conn { ngtcp2_objalloc frc_objalloc; @@ -421,25 +418,28 @@ struct ngtcp2_conn { /* num_retired is the number of retired Connection ID still included in set. */ size_t num_retired; + /* num_in_flight is the number of NEW_CONNECTION_ID frames that + are in-flight and not acknowledged yet. */ + size_t num_in_flight; } scid; struct { /* strmq contains ngtcp2_strm which has frames to send. */ ngtcp2_pq strmq; - /* strmq_nretrans is the number of entries in strmq which has - stream data to resent. */ - size_t strmq_nretrans; /* ack is ACK frame. The underlying buffer is reused. */ ngtcp2_frame *ack; - /* max_ack_blks is the number of additional ngtcp2_ack_blk which - ack can contain. */ - size_t max_ack_blks; + /* max_ack_ranges is the number of additional ngtcp2_ack_range + which ack can contain. */ + size_t max_ack_ranges; /* offset is the offset the local endpoint has sent to the remote endpoint. */ uint64_t offset; /* max_offset is the maximum offset that local endpoint can send. */ uint64_t max_offset; + /* last_blocked_offset is the largest offset where the + transmission of stream data is blocked. */ + uint64_t last_blocked_offset; /* last_max_data_ts is the timestamp when last MAX_DATA frame is sent. */ ngtcp2_tstamp last_max_data_ts; @@ -482,7 +482,7 @@ struct ngtcp2_conn { /* path_challenge stores received PATH_CHALLENGE data. */ ngtcp2_static_ringbuf_path_challenge path_challenge; /* ccerr is the received connection close error. */ - ngtcp2_connection_close_error ccerr; + ngtcp2_ccerr ccerr; } rx; struct { @@ -497,16 +497,7 @@ struct ngtcp2_conn { ngtcp2_conn_set_early_remote_transport_params(). Server does not use this field. Server must not set values for these parameters that are smaller than the remembered values. */ - struct { - uint64_t initial_max_streams_bidi; - uint64_t initial_max_streams_uni; - uint64_t initial_max_stream_data_bidi_local; - uint64_t initial_max_stream_data_bidi_remote; - uint64_t initial_max_stream_data_uni; - uint64_t initial_max_data; - uint64_t active_connection_id_limit; - uint64_t max_datagram_frame_size; - } transport_params; + ngtcp2_early_transport_params transport_params; } early; struct { @@ -658,14 +649,14 @@ struct ngtcp2_conn { array pointed by preferred_versions. This field is only used by server. */ size_t preferred_versionslen; - /* other_versions is the versions that the local endpoint sends in - version_information transport parameter. This is the wire - image of other_versions field of version_information transport - parameter. */ - uint8_t *other_versions; - /* other_versionslen is the length of data pointed by - other_versions field. */ - size_t other_versionslen; + /* available_versions is the versions that the local endpoint + sends in version_information transport parameter. This is the + wire image of available_versions field of version_information + transport parameter. */ + uint8_t *available_versions; + /* available_versionslen is the length of data pointed by + available_versions field. */ + size_t available_versionslen; } vneg; ngtcp2_map strms; @@ -676,7 +667,12 @@ struct ngtcp2_conn { ngtcp2_qlog qlog; ngtcp2_rst rst; ngtcp2_cc_algo cc_algo; - ngtcp2_cc cc; + union { + ngtcp2_cc cc; + ngtcp2_cc_reno reno; + ngtcp2_cc_cubic cubic; + ngtcp2_cc_bbr bbr; + }; const ngtcp2_mem *mem; /* idle_ts is the time instant when idle timer started. */ ngtcp2_tstamp idle_ts; @@ -913,19 +909,6 @@ ngtcp2_tstamp ngtcp2_conn_lost_pkt_expiry(ngtcp2_conn *conn); */ void ngtcp2_conn_remove_lost_pkt(ngtcp2_conn *conn, ngtcp2_tstamp ts); -/* - * ngtcp2_conn_resched_frames reschedules frames linked from |*pfrc| - * for retransmission. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. - */ -int ngtcp2_conn_resched_frames(ngtcp2_conn *conn, ngtcp2_pktns *pktns, - ngtcp2_frame_chain **pfrc); - uint64_t ngtcp2_conn_tx_strmq_first_cycle(ngtcp2_conn *conn); /** @@ -1112,4 +1095,65 @@ void ngtcp2_conn_stop_pmtud(ngtcp2_conn *conn); int ngtcp2_conn_set_remote_transport_params( ngtcp2_conn *conn, const ngtcp2_transport_params *params); +/** + * @function + * + * `ngtcp2_conn_set_0rtt_remote_transport_params` sets |params| as + * transport parameters previously received from a server. The + * parameters are used to send early data. QUIC requires that client + * application should remember transport parameters along with a + * session ticket. + * + * At least following fields should be set: + * + * - initial_max_stream_id_bidi + * - initial_max_stream_id_uni + * - initial_max_stream_data_bidi_local + * - initial_max_stream_data_bidi_remote + * - initial_max_stream_data_uni + * - initial_max_data + * - active_connection_id_limit + * - max_datagram_frame_size (if DATAGRAM extension was negotiated) + * + * The following fields are ignored: + * + * - ack_delay_exponent + * - max_ack_delay + * - initial_scid + * - original_dcid + * - preferred_address and preferred_address_present + * - retry_scid and retry_scid_present + * - stateless_reset_token and stateless_reset_token_present + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGTCP2_ERR_NOMEM` + * Out of memory. + */ +int ngtcp2_conn_set_0rtt_remote_transport_params( + ngtcp2_conn *conn, const ngtcp2_transport_params *params); + +/* + * ngtcp2_conn_create_ack_frame creates ACK frame, and assigns its + * pointer to |*pfr| if there are any received packets to acknowledge. + * If there are no packets to acknowledge, this function returns 0, + * and |*pfr| is untouched. The caller is advised to set |*pfr| to + * NULL before calling this function, and check it after this function + * returns. + * + * Call ngtcp2_acktr_commit_ack after a created ACK frame is + * successfully serialized into a packet. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_NOMEM + * Out of memory. + */ +int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, + ngtcp2_pktns *pktns, uint8_t type, + ngtcp2_tstamp ts, ngtcp2_duration ack_delay, + uint64_t ack_delay_exponent); + #endif /* NGTCP2_CONN_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h new file mode 100644 index 00000000000000..1a93867aab3cae --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h @@ -0,0 +1,132 @@ +/* + * ngtcp2 + * + * Copyright (c) 2023 ngtcp2 contributors + * + * 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. + */ +#ifndef NGTCP2_CONN_STAT_H +#define NGTCP2_CONN_STAT_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +/** + * @struct + * + * :type:`ngtcp2_conn_stat` holds various connection statistics, and + * computed data for recovery and congestion controller. + */ +typedef struct ngtcp2_conn_stat { + /** + * :member:`latest_rtt` is the latest RTT sample which is not + * adjusted by acknowledgement delay. + */ + ngtcp2_duration latest_rtt; + /** + * :member:`min_rtt` is the minimum RTT seen so far. It is not + * adjusted by acknowledgement delay. + */ + ngtcp2_duration min_rtt; + /** + * :member:`smoothed_rtt` is the smoothed RTT. + */ + ngtcp2_duration smoothed_rtt; + /** + * :member:`rttvar` is a mean deviation of observed RTT. + */ + ngtcp2_duration rttvar; + /** + * :member:`initial_rtt` is the initial RTT which is used when no + * RTT sample is available. + */ + ngtcp2_duration initial_rtt; + /** + * :member:`first_rtt_sample_ts` is the timestamp when the first RTT + * sample is obtained. + */ + ngtcp2_tstamp first_rtt_sample_ts; + /** + * :member:`pto_count` is the count of successive PTO timer + * expiration. + */ + size_t pto_count; + /** + * :member:`loss_detection_timer` is the deadline of the current + * loss detection timer. + */ + ngtcp2_tstamp loss_detection_timer; + /** + * :member:`last_tx_pkt_ts` corresponds to + * time_of_last_ack_eliciting_packet in :rfc:`9002`. + */ + ngtcp2_tstamp last_tx_pkt_ts[NGTCP2_PKTNS_ID_MAX]; + /** + * :member:`loss_time` corresponds to loss_time in :rfc:`9002`. + */ + ngtcp2_tstamp loss_time[NGTCP2_PKTNS_ID_MAX]; + /** + * :member:`cwnd` is the size of congestion window. + */ + uint64_t cwnd; + /** + * :member:`ssthresh` is slow start threshold. + */ + uint64_t ssthresh; + /** + * :member:`congestion_recovery_start_ts` is the timestamp when + * congestion recovery started. + */ + ngtcp2_tstamp congestion_recovery_start_ts; + /** + * :member:`bytes_in_flight` is the number in bytes of all sent + * packets which have not been acknowledged. + */ + uint64_t bytes_in_flight; + /** + * :member:`max_tx_udp_payload_size` is the maximum size of UDP + * datagram payload that this endpoint transmits. It is used by + * congestion controller to compute congestion window. + */ + size_t max_tx_udp_payload_size; + /** + * :member:`delivery_rate_sec` is the current sending rate measured + * in byte per second. + */ + uint64_t delivery_rate_sec; + /** + * :member:`pacing_interval` is the inverse of pacing rate, which is + * the current packet sending rate computed by a congestion + * controller. 0 if a congestion controller does not set pacing + * interval. Even if this value is set to 0, the library paces + * packets. + */ + ngtcp2_duration pacing_interval; + /** + * :member:`send_quantum` is the maximum size of a data aggregate + * scheduled and transmitted together. + */ + size_t send_quantum; +} ngtcp2_conn_stat; + +#endif /* NGTCP2_CONN_STAT_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c index dcf72e4d0ec980..336721772b4e4c 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c @@ -30,40 +30,51 @@ #include "ngtcp2_str.h" #include "ngtcp2_pkt.h" #include "ngtcp2_net.h" +#include "ngtcp2_unreachable.h" -uint64_t ngtcp2_get_uint64(const uint8_t *p) { +const uint8_t *ngtcp2_get_uint64(uint64_t *dest, const uint8_t *p) { uint64_t n; - memcpy(&n, p, 8); - return ngtcp2_ntohl64(n); + memcpy(&n, p, sizeof(n)); + *dest = ngtcp2_ntohl64(n); + return p + sizeof(n); } -uint64_t ngtcp2_get_uint48(const uint8_t *p) { +const uint8_t *ngtcp2_get_uint48(uint64_t *dest, const uint8_t *p) { uint64_t n = 0; memcpy(((uint8_t *)&n) + 2, p, 6); - return ngtcp2_ntohl64(n); + *dest = ngtcp2_ntohl64(n); + return p + 6; } -uint32_t ngtcp2_get_uint32(const uint8_t *p) { +const uint8_t *ngtcp2_get_uint32(uint32_t *dest, const uint8_t *p) { uint32_t n; - memcpy(&n, p, 4); - return ngtcp2_ntohl(n); + memcpy(&n, p, sizeof(n)); + *dest = ngtcp2_ntohl(n); + return p + sizeof(n); } -uint32_t ngtcp2_get_uint24(const uint8_t *p) { +const uint8_t *ngtcp2_get_uint24(uint32_t *dest, const uint8_t *p) { uint32_t n = 0; memcpy(((uint8_t *)&n) + 1, p, 3); - return ngtcp2_ntohl(n); + *dest = ngtcp2_ntohl(n); + return p + 3; } -uint16_t ngtcp2_get_uint16(const uint8_t *p) { +const uint8_t *ngtcp2_get_uint16(uint16_t *dest, const uint8_t *p) { uint16_t n; - memcpy(&n, p, 2); - return ngtcp2_ntohs(n); + memcpy(&n, p, sizeof(n)); + *dest = ngtcp2_ntohs(n); + return p + sizeof(n); } -uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p) { +const uint8_t *ngtcp2_get_uint16be(uint16_t *dest, const uint8_t *p) { + memcpy(dest, p, sizeof(*dest)); + return p + sizeof(*dest); +} + +static uint64_t get_uvarint(size_t *plen, const uint8_t *p) { union { - char b[8]; + uint8_t n8; uint16_t n16; uint32_t n32; uint64_t n64; @@ -76,36 +87,55 @@ uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p) { return *p; case 2: memcpy(&n, p, 2); - n.b[0] &= 0x3f; + n.n8 &= 0x3f; return ngtcp2_ntohs(n.n16); case 4: memcpy(&n, p, 4); - n.b[0] &= 0x3f; + n.n8 &= 0x3f; return ngtcp2_ntohl(n.n32); case 8: memcpy(&n, p, 8); - n.b[0] &= 0x3f; + n.n8 &= 0x3f; return ngtcp2_ntohl64(n.n64); default: - assert(0); + ngtcp2_unreachable(); } +} + +const uint8_t *ngtcp2_get_uvarint(uint64_t *dest, const uint8_t *p) { + size_t len; - return 0; + *dest = get_uvarint(&len, p); + + return p + len; +} + +const uint8_t *ngtcp2_get_varint(int64_t *dest, const uint8_t *p) { + size_t len; + + *dest = (int64_t)get_uvarint(&len, p); + + return p + len; } int64_t ngtcp2_get_pkt_num(const uint8_t *p, size_t pkt_numlen) { + uint32_t l; + uint16_t s; + switch (pkt_numlen) { case 1: return *p; case 2: - return (int64_t)ngtcp2_get_uint16(p); + ngtcp2_get_uint16(&s, p); + return (int64_t)s; case 3: - return (int64_t)ngtcp2_get_uint24(p); + ngtcp2_get_uint24(&l, p); + return (int64_t)l; case 4: - return (int64_t)ngtcp2_get_uint32(p); + ngtcp2_get_uint32(&l, p); + return (int64_t)l; default: - assert(0); - abort(); + ngtcp2_unreachable(); } } @@ -134,7 +164,11 @@ uint8_t *ngtcp2_put_uint16be(uint8_t *p, uint16_t n) { return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n)); } -uint8_t *ngtcp2_put_varint(uint8_t *p, uint64_t n) { +uint8_t *ngtcp2_put_uint16(uint8_t *p, uint16_t n) { + return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n)); +} + +uint8_t *ngtcp2_put_uvarint(uint8_t *p, uint64_t n) { uint8_t *rv; if (n < 64) { *p++ = (uint8_t)n; @@ -156,7 +190,7 @@ uint8_t *ngtcp2_put_varint(uint8_t *p, uint64_t n) { return rv; } -uint8_t *ngtcp2_put_varint30(uint8_t *p, uint32_t n) { +uint8_t *ngtcp2_put_uvarint30(uint8_t *p, uint32_t n) { uint8_t *rv; assert(n < 1073741824); @@ -182,16 +216,15 @@ uint8_t *ngtcp2_put_pkt_num(uint8_t *p, int64_t pkt_num, size_t len) { ngtcp2_put_uint32be(p, (uint32_t)pkt_num); return p + 4; default: - assert(0); - abort(); + ngtcp2_unreachable(); } } -size_t ngtcp2_get_varint_len(const uint8_t *p) { +size_t ngtcp2_get_uvarintlen(const uint8_t *p) { return (size_t)(1u << (*p >> 6)); } -size_t ngtcp2_put_varint_len(uint64_t n) { +size_t ngtcp2_put_uvarintlen(uint64_t n) { if (n < 64) { return 1; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.h index 99746fdb4cefb7..ef089a971a37f1 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.h @@ -33,45 +33,61 @@ /* * ngtcp2_get_uint64 reads 8 bytes from |p| as 64 bits unsigned - * integer encoded as network byte order, and returns it in host byte - * order. + * integer encoded as network byte order, and stores it in the buffer + * pointed by |dest| in host byte order. It returns |p| + 8. */ -uint64_t ngtcp2_get_uint64(const uint8_t *p); +const uint8_t *ngtcp2_get_uint64(uint64_t *dest, const uint8_t *p); /* * ngtcp2_get_uint48 reads 6 bytes from |p| as 48 bits unsigned - * integer encoded as network byte order, and returns it in host byte - * order. + * integer encoded as network byte order, and stores it in the buffer + * pointed by |dest| in host byte order. It returns |p| + 6. */ -uint64_t ngtcp2_get_uint48(const uint8_t *p); +const uint8_t *ngtcp2_get_uint48(uint64_t *dest, const uint8_t *p); /* * ngtcp2_get_uint32 reads 4 bytes from |p| as 32 bits unsigned - * integer encoded as network byte order, and returns it in host byte - * order. + * integer encoded as network byte order, and stores it in the buffer + * pointed by |dest| in host byte order. It returns |p| + 4. */ -uint32_t ngtcp2_get_uint32(const uint8_t *p); +const uint8_t *ngtcp2_get_uint32(uint32_t *dest, const uint8_t *p); /* * ngtcp2_get_uint24 reads 3 bytes from |p| as 24 bits unsigned - * integer encoded as network byte order, and returns it in host byte - * order. + * integer encoded as network byte order, and stores it in the buffer + * pointed by |dest| in host byte order. It returns |p| + 3. */ -uint32_t ngtcp2_get_uint24(const uint8_t *p); +const uint8_t *ngtcp2_get_uint24(uint32_t *dest, const uint8_t *p); /* * ngtcp2_get_uint16 reads 2 bytes from |p| as 16 bits unsigned - * integer encoded as network byte order, and returns it in host byte - * order. + * integer encoded as network byte order, and stores it in the buffer + * pointed by |dest| in host byte order. It returns |p| + 2. */ -uint16_t ngtcp2_get_uint16(const uint8_t *p); +const uint8_t *ngtcp2_get_uint16(uint16_t *dest, const uint8_t *p); /* - * ngtcp2_get_varint reads variable-length integer from |p|, and - * returns it in host byte order. The number of bytes read is stored - * in |*plen|. + * ngtcp2_get_uint16be reads 2 bytes from |p| as 16 bits unsigned + * integer encoded as network byte order, and stores it in the buffer + * pointed by |dest| as is. It returns |p| + 2. */ -uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p); +const uint8_t *ngtcp2_get_uint16be(uint16_t *dest, const uint8_t *p); + +/* + * ngtcp2_get_uvarint reads variable-length unsigned integer from |p|, + * and stores it in the buffer pointed by |dest| in host byte order. + * It returns |p| plus the number of bytes read from |p|. + */ +const uint8_t *ngtcp2_get_uvarint(uint64_t *dest, const uint8_t *p); + +/* + * ngtcp2_get_varint reads variable-length unsigned integer from |p|, + * and casts it to the signed integer, and stores it in the buffer + * pointed by |dest| in host byte order. No information should be + * lost in this cast, because the variable-length integer is 62 + * bits. It returns |p| plus the number of bytes read from |p|. + */ +const uint8_t *ngtcp2_get_varint(int64_t *dest, const uint8_t *p); /* * ngtcp2_get_pkt_num reads encoded packet number from |p|. The @@ -115,18 +131,24 @@ uint8_t *ngtcp2_put_uint24be(uint8_t *p, uint32_t n); uint8_t *ngtcp2_put_uint16be(uint8_t *p, uint16_t n); /* - * ngtcp2_put_varint writes |n| in |p| using variable-length integer + * ngtcp2_put_uint16 writes |n| as is in |p|. It returns the one + * beyond of the last written position. + */ +uint8_t *ngtcp2_put_uint16(uint8_t *p, uint16_t n); + +/* + * ngtcp2_put_uvarint writes |n| in |p| using variable-length integer * encoding. It returns the one beyond of the last written position. */ -uint8_t *ngtcp2_put_varint(uint8_t *p, uint64_t n); +uint8_t *ngtcp2_put_uvarint(uint8_t *p, uint64_t n); /* - * ngtcp2_put_varint30 writes |n| in |p| using variable-length integer - * encoding. |n| must be strictly less than 1073741824. The function - * always encodes |n| in 4 bytes. It returns the one beyond of the - * last written position. + * ngtcp2_put_uvarint30 writes |n| in |p| using variable-length + * integer encoding. |n| must be strictly less than 1073741824. The + * function always encodes |n| in 4 bytes. It returns the one beyond + * of the last written position. */ -uint8_t *ngtcp2_put_varint30(uint8_t *p, uint32_t n); +uint8_t *ngtcp2_put_uvarint30(uint8_t *p, uint32_t n); /* * ngtcp2_put_pkt_num encodes |pkt_num| using |len| bytes. It @@ -135,16 +157,16 @@ uint8_t *ngtcp2_put_varint30(uint8_t *p, uint32_t n); uint8_t *ngtcp2_put_pkt_num(uint8_t *p, int64_t pkt_num, size_t len); /* - * ngtcp2_get_varint_len returns the required number of bytes to read + * ngtcp2_get_uvarintlen returns the required number of bytes to read * variable-length integer starting at |p|. */ -size_t ngtcp2_get_varint_len(const uint8_t *p); +size_t ngtcp2_get_uvarintlen(const uint8_t *p); /* - * ngtcp2_put_varint_len returns the required number of bytes to + * ngtcp2_put_uvarintlen returns the required number of bytes to * encode |n|. */ -size_t ngtcp2_put_varint_len(uint64_t n); +size_t ngtcp2_put_uvarintlen(uint64_t n); /* * ngtcp2_nth_server_bidi_id returns |n|-th server bidirectional diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.c new file mode 100644 index 00000000000000..eb85687a068449 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.c @@ -0,0 +1,66 @@ +/* + * ngtcp2 + * + * Copyright (c) 2023 ngtcp2 contributors + * + * 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 "ngtcp2_conversion.h" + +#include +#include + +static void transport_params_copy(int transport_params_version, + ngtcp2_transport_params *dest, + const ngtcp2_transport_params *src) { + assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); + + switch (transport_params_version) { + case NGTCP2_TRANSPORT_PARAMS_V1: + memcpy(dest, src, + offsetof(ngtcp2_transport_params, version_info_present) + + sizeof(src->version_info_present)); + + break; + } +} + +const ngtcp2_transport_params * +ngtcp2_transport_params_convert_to_latest(ngtcp2_transport_params *dest, + int transport_params_version, + const ngtcp2_transport_params *src) { + if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { + return src; + } + + ngtcp2_transport_params_default(dest); + + transport_params_copy(transport_params_version, dest, src); + + return dest; +} + +void ngtcp2_transport_params_convert_to_old( + int transport_params_version, ngtcp2_transport_params *dest, + const ngtcp2_transport_params *src) { + assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); + + transport_params_copy(transport_params_version, dest, src); +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.h new file mode 100644 index 00000000000000..3457a8f2053aba --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.h @@ -0,0 +1,71 @@ +/* + * ngtcp2 + * + * Copyright (c) 2023 ngtcp2 contributors + * + * 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. + */ +#ifndef NGTCP2_CONVERSION_H +#define NGTCP2_CONVERSION_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +/* + * ngtcp2_transport_params_convert_to_latest converts |src| of version + * |transport_params_version| to the latest version + * NGTCP2_TRANSPORT_PARAMS_VERSION. + * + * |dest| must point to the latest version. |src| may be the older + * version, and if so, it may have fewer fields. Accessing those + * fields causes undefined behavior. + * + * If |transport_params_version| == NGTCP2_TRANSPORT_PARAMS_VERSION, + * no conversion is made, and |src| is returned. Otherwise, first + * |dest| is initialized via ngtcp2_transport_params_default, and then + * all valid fields in |src| are copied into |dest|. Finally, |dest| + * is returned. + */ +const ngtcp2_transport_params * +ngtcp2_transport_params_convert_to_latest(ngtcp2_transport_params *dest, + int transport_params_version, + const ngtcp2_transport_params *src); + +/* + * ngtcp2_transport_params_convert_to_old converts |src| of the latest + * version to |dest| of version |transport_params_version|. + * + * |transport_params_version| must not be the latest version + * NGTCP2_TRANSPORT_PARAMS_VERSION. + * + * |dest| points to the older version, and it may have fewer fields. + * Accessing those fields causes undefined behavior. + * + * This function copies all valid fields in version + * |transport_params_version| from |src| to |dest|. + */ +void ngtcp2_transport_params_convert_to_old(int transport_params_version, + ngtcp2_transport_params *dest, + const ngtcp2_transport_params *src); + +#endif /* NGTCP2_CONVERSION_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c index f7592f885b4cb2..0a3ecf6a2440cb 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c @@ -31,6 +31,7 @@ #include "ngtcp2_conv.h" #include "ngtcp2_conn.h" #include "ngtcp2_net.h" +#include "ngtcp2_conversion.h" int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret, size_t secretlen, @@ -107,8 +108,8 @@ void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen, * which has variable integer in its parameter. */ static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) { - size_t valuelen = ngtcp2_put_varint_len(param); - return ngtcp2_put_varint_len(id) + ngtcp2_put_varint_len(valuelen) + valuelen; + size_t valuelen = ngtcp2_put_uvarintlen(param); + return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(valuelen) + valuelen; } /* @@ -117,9 +118,28 @@ static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) { */ static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id, uint64_t value) { - p = ngtcp2_put_varint(p, id); - p = ngtcp2_put_varint(p, ngtcp2_put_varint_len(value)); - return ngtcp2_put_varint(p, value); + p = ngtcp2_put_uvarint(p, id); + p = ngtcp2_put_uvarint(p, ngtcp2_put_uvarintlen(value)); + return ngtcp2_put_uvarint(p, value); +} + +/* + * zero_paramlen returns the length of a single transport parameter + * which has zero length value in its parameter. + */ +static size_t zero_paramlen(ngtcp2_transport_param_id id) { + return ngtcp2_put_uvarintlen(id) + 1; +} + +/* + * write_zero_param writes parameter |id| that has zero length value. + * It returns p + the number of bytes written. + */ +static uint8_t *write_zero_param(uint8_t *p, ngtcp2_transport_param_id id) { + p = ngtcp2_put_uvarint(p, id); + *p++ = 0; + + return p; } /* @@ -128,7 +148,7 @@ static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id, */ static size_t cid_paramlen(ngtcp2_transport_param_id id, const ngtcp2_cid *cid) { - return ngtcp2_put_varint_len(id) + ngtcp2_put_varint_len(cid->datalen) + + return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(cid->datalen) + cid->datalen; } @@ -141,8 +161,8 @@ static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id, assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN); assert(cid->datalen <= NGTCP2_MAX_CIDLEN); - p = ngtcp2_put_varint(p, id); - p = ngtcp2_put_varint(p, cid->datalen); + p = ngtcp2_put_uvarint(p, id); + p = ngtcp2_put_uvarint(p, cid->datalen); if (cid->datalen) { p = ngtcp2_cpymem(p, cid->data, cid->datalen); } @@ -151,52 +171,52 @@ static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id, static const uint8_t empty_address[16]; -ngtcp2_ssize ngtcp2_encode_transport_params_versioned( - uint8_t *dest, size_t destlen, ngtcp2_transport_params_type exttype, - int transport_params_version, const ngtcp2_transport_params *params) { +ngtcp2_ssize ngtcp2_transport_params_encode_versioned( + uint8_t *dest, size_t destlen, int transport_params_version, + const ngtcp2_transport_params *params) { uint8_t *p; size_t len = 0; /* For some reason, gcc 7.3.0 requires this initialization. */ size_t preferred_addrlen = 0; size_t version_infolen = 0; - (void)transport_params_version; + const ngtcp2_sockaddr_in *sa_in; + const ngtcp2_sockaddr_in6 *sa_in6; + ngtcp2_transport_params paramsbuf; - switch (exttype) { - case NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO: - break; - case NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS: + params = ngtcp2_transport_params_convert_to_latest( + ¶msbuf, transport_params_version, params); + + if (params->original_dcid_present) { len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, ¶ms->original_dcid); + } - if (params->stateless_reset_token_present) { - len += - ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) + - ngtcp2_put_varint_len(NGTCP2_STATELESS_RESET_TOKENLEN) + - NGTCP2_STATELESS_RESET_TOKENLEN; - } - if (params->preferred_address_present) { - assert(params->preferred_address.cid.datalen >= NGTCP2_MIN_CIDLEN); - assert(params->preferred_address.cid.datalen <= NGTCP2_MAX_CIDLEN); - preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ + - 16 /* ipv6Address */ + 2 /* ipv6Port */ - + 1 + - params->preferred_address.cid.datalen /* CID */ + - NGTCP2_STATELESS_RESET_TOKENLEN; - len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) + - ngtcp2_put_varint_len(preferred_addrlen) + preferred_addrlen; - } - if (params->retry_scid_present) { - len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, - ¶ms->retry_scid); - } - break; - default: - return NGTCP2_ERR_INVALID_ARGUMENT; + if (params->stateless_reset_token_present) { + len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) + + ngtcp2_put_uvarintlen(NGTCP2_STATELESS_RESET_TOKENLEN) + + NGTCP2_STATELESS_RESET_TOKENLEN; } - len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, - ¶ms->initial_scid); + if (params->preferred_addr_present) { + assert(params->preferred_addr.cid.datalen >= NGTCP2_MIN_CIDLEN); + assert(params->preferred_addr.cid.datalen <= NGTCP2_MAX_CIDLEN); + preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ + + 16 /* ipv6Address */ + 2 /* ipv6Port */ + + 1 + params->preferred_addr.cid.datalen /* CID */ + + NGTCP2_STATELESS_RESET_TOKENLEN; + len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) + + ngtcp2_put_uvarintlen(preferred_addrlen) + preferred_addrlen; + } + if (params->retry_scid_present) { + len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, + ¶ms->retry_scid); + } + + if (params->initial_scid_present) { + len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, + ¶ms->initial_scid); + } if (params->initial_max_stream_data_bidi_local) { len += varint_paramlen( @@ -234,9 +254,7 @@ ngtcp2_ssize ngtcp2_encode_transport_params_versioned( params->ack_delay_exponent); } if (params->disable_active_migration) { - len += - ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION) + - ngtcp2_put_varint_len(0); + len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); } if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, @@ -257,14 +275,13 @@ ngtcp2_ssize ngtcp2_encode_transport_params_versioned( params->max_datagram_frame_size); } if (params->grease_quic_bit) { - len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT) + - ngtcp2_put_varint_len(0); + len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); } if (params->version_info_present) { - version_infolen = sizeof(uint32_t) + params->version_info.other_versionslen; - len += ngtcp2_put_varint_len( - NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION_DRAFT) + - ngtcp2_put_varint_len(version_infolen) + version_infolen; + version_infolen = + sizeof(uint32_t) + params->version_info.available_versionslen; + len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION) + + ngtcp2_put_uvarintlen(version_infolen) + version_infolen; } if (dest == NULL && destlen == 0) { @@ -277,58 +294,59 @@ ngtcp2_ssize ngtcp2_encode_transport_params_versioned( p = dest; - if (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) { + if (params->original_dcid_present) { p = write_cid_param( p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, ¶ms->original_dcid); + } + + if (params->stateless_reset_token_present) { + p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN); + p = ngtcp2_put_uvarint(p, sizeof(params->stateless_reset_token)); + p = ngtcp2_cpymem(p, params->stateless_reset_token, + sizeof(params->stateless_reset_token)); + } + + if (params->preferred_addr_present) { + p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS); + p = ngtcp2_put_uvarint(p, preferred_addrlen); - if (params->stateless_reset_token_present) { - p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN); - p = ngtcp2_put_varint(p, sizeof(params->stateless_reset_token)); - p = ngtcp2_cpymem(p, params->stateless_reset_token, - sizeof(params->stateless_reset_token)); + if (params->preferred_addr.ipv4_present) { + sa_in = ¶ms->preferred_addr.ipv4; + p = ngtcp2_cpymem(p, &sa_in->sin_addr, sizeof(sa_in->sin_addr)); + p = ngtcp2_put_uint16(p, sa_in->sin_port); + } else { + p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in->sin_addr)); + p = ngtcp2_put_uint16(p, 0); } - if (params->preferred_address_present) { - p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS); - p = ngtcp2_put_varint(p, preferred_addrlen); - - if (params->preferred_address.ipv4_present) { - p = ngtcp2_cpymem(p, params->preferred_address.ipv4_addr, - sizeof(params->preferred_address.ipv4_addr)); - p = ngtcp2_put_uint16be(p, params->preferred_address.ipv4_port); - } else { - p = ngtcp2_cpymem(p, empty_address, - sizeof(params->preferred_address.ipv4_addr)); - p = ngtcp2_put_uint16be(p, 0); - } - - if (params->preferred_address.ipv6_present) { - p = ngtcp2_cpymem(p, params->preferred_address.ipv6_addr, - sizeof(params->preferred_address.ipv6_addr)); - p = ngtcp2_put_uint16be(p, params->preferred_address.ipv6_port); - } else { - p = ngtcp2_cpymem(p, empty_address, - sizeof(params->preferred_address.ipv6_addr)); - p = ngtcp2_put_uint16be(p, 0); - } - - *p++ = (uint8_t)params->preferred_address.cid.datalen; - if (params->preferred_address.cid.datalen) { - p = ngtcp2_cpymem(p, params->preferred_address.cid.data, - params->preferred_address.cid.datalen); - } - p = ngtcp2_cpymem( - p, params->preferred_address.stateless_reset_token, - sizeof(params->preferred_address.stateless_reset_token)); + + if (params->preferred_addr.ipv6_present) { + sa_in6 = ¶ms->preferred_addr.ipv6; + p = ngtcp2_cpymem(p, &sa_in6->sin6_addr, sizeof(sa_in6->sin6_addr)); + p = ngtcp2_put_uint16(p, sa_in6->sin6_port); + } else { + p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in6->sin6_addr)); + p = ngtcp2_put_uint16(p, 0); } - if (params->retry_scid_present) { - p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, - ¶ms->retry_scid); + + *p++ = (uint8_t)params->preferred_addr.cid.datalen; + if (params->preferred_addr.cid.datalen) { + p = ngtcp2_cpymem(p, params->preferred_addr.cid.data, + params->preferred_addr.cid.datalen); } + p = ngtcp2_cpymem(p, params->preferred_addr.stateless_reset_token, + sizeof(params->preferred_addr.stateless_reset_token)); } - p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, - ¶ms->initial_scid); + if (params->retry_scid_present) { + p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, + ¶ms->retry_scid); + } + + if (params->initial_scid_present) { + p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, + ¶ms->initial_scid); + } if (params->initial_max_stream_data_bidi_local) { p = write_varint_param( @@ -375,8 +393,7 @@ ngtcp2_ssize ngtcp2_encode_transport_params_versioned( } if (params->disable_active_migration) { - p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); - p = ngtcp2_put_varint(p, 0); + p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); } if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { @@ -402,17 +419,16 @@ ngtcp2_ssize ngtcp2_encode_transport_params_versioned( } if (params->grease_quic_bit) { - p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); - p = ngtcp2_put_varint(p, 0); + p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); } if (params->version_info_present) { - p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION_DRAFT); - p = ngtcp2_put_varint(p, version_infolen); + p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION); + p = ngtcp2_put_uvarint(p, version_infolen); p = ngtcp2_put_uint32be(p, params->version_info.chosen_version); - if (params->version_info.other_versionslen) { - p = ngtcp2_cpymem(p, params->version_info.other_versions, - params->version_info.other_versionslen); + if (params->version_info.available_versionslen) { + p = ngtcp2_cpymem(p, params->version_info.available_versions, + params->version_info.available_versionslen); } } @@ -423,49 +439,46 @@ ngtcp2_ssize ngtcp2_encode_transport_params_versioned( /* * decode_varint decodes a single varint from the buffer pointed by - * |p| of length |end - p|. If it decodes an integer successfully, it - * stores the integer in |*pdest| and returns 0. Otherwise it returns - * -1. + * |*pp| of length |end - *pp|. If it decodes an integer + * successfully, it stores the integer in |*pdest|, increment |*pp| by + * the number of bytes read from |*pp|, and returns 0. Otherwise it + * returns -1. */ -static ngtcp2_ssize decode_varint(uint64_t *pdest, const uint8_t *p, - const uint8_t *end) { +static int decode_varint(uint64_t *pdest, const uint8_t **pp, + const uint8_t *end) { + const uint8_t *p = *pp; size_t len; if (p == end) { return -1; } - len = ngtcp2_get_varint_len(p); + len = ngtcp2_get_uvarintlen(p); if ((uint64_t)(end - p) < len) { return -1; } - *pdest = ngtcp2_get_varint(&len, p); + *pp = ngtcp2_get_uvarint(pdest, p); - return (ngtcp2_ssize)len; + return 0; } /* * decode_varint_param decodes length prefixed value from the buffer - * pointed by |p| of length |end - p|. The length and value are + * pointed by |*pp| of length |end - *pp|. The length and value are * encoded in varint form. If it decodes a value successfully, it - * stores the value in |*pdest| and returns 0. Otherwise it returns - * -1. + * stores the value in |*pdest|, increment |*pp| by the number of + * bytes read from |*pp|, and returns 0. Otherwise it returns -1. */ -static ngtcp2_ssize decode_varint_param(uint64_t *pdest, const uint8_t *p, - const uint8_t *end) { - const uint8_t *begin = p; - ngtcp2_ssize nread; +static int decode_varint_param(uint64_t *pdest, const uint8_t **pp, + const uint8_t *end) { + const uint8_t *p = *pp; uint64_t valuelen; - size_t n; - nread = decode_varint(&valuelen, p, end); - if (nread < 0) { + if (decode_varint(&valuelen, &p, end) != 0) { return -1; } - p += nread; - if (p == end) { return -1; } @@ -474,36 +487,51 @@ static ngtcp2_ssize decode_varint_param(uint64_t *pdest, const uint8_t *p, return -1; } - if (ngtcp2_get_varint_len(p) != valuelen) { + if (ngtcp2_get_uvarintlen(p) != valuelen) { return -1; } - *pdest = ngtcp2_get_varint(&n, p); + *pp = ngtcp2_get_uvarint(pdest, p); - p += valuelen; + return 0; +} + +/* + * decode_zero_param decodes zero length value from the buffer pointed + * by |*pp| of length |end - *pp|. The length is encoded in varint + * form. If it decodes zero length value successfully, it increments + * |*pp| by 1, and returns 0. Otherwise it returns -1. + */ +static int decode_zero_param(const uint8_t **pp, const uint8_t *end) { + if (*pp == end || **pp != 0) { + return -1; + } + + ++*pp; - return (ngtcp2_ssize)(p - begin); + return 0; } /* * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer - * pointed by |p| of length |end - p|. The length is encoded in + * pointed by |*pp| of length |end - *pp|. The length is encoded in * varint form. If it decodes a value successfully, it stores the - * value in |*pdest| and returns the number of bytes read. Otherwise - * it returns -1. + * value in |*pdest|, increment |*pp| by the number of read from + * |*pp|, and returns the number of bytes read. Otherwise it returns + * the one of the negative error code: + * + * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM + * Could not decode Connection ID. */ -static ngtcp2_ssize decode_cid_param(ngtcp2_cid *pdest, const uint8_t *p, - const uint8_t *end) { - const uint8_t *begin = p; +static int decode_cid_param(ngtcp2_cid *pdest, const uint8_t **pp, + const uint8_t *end) { + const uint8_t *p = *pp; uint64_t valuelen; - ngtcp2_ssize nread = decode_varint(&valuelen, p, end); - if (nread < 0) { + if (decode_varint(&valuelen, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; - if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) || valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; @@ -513,28 +541,35 @@ static ngtcp2_ssize decode_cid_param(ngtcp2_cid *pdest, const uint8_t *p, p += valuelen; - return (ngtcp2_ssize)(p - begin); + *pp = p; + + return 0; } -int ngtcp2_decode_transport_params_versioned( - int transport_params_version, ngtcp2_transport_params *params, - ngtcp2_transport_params_type exttype, const uint8_t *data, size_t datalen) { - const uint8_t *p, *end; +int ngtcp2_transport_params_decode_versioned(int transport_params_version, + ngtcp2_transport_params *dest, + const uint8_t *data, + size_t datalen) { + const uint8_t *p, *end, *lend; size_t len; uint64_t param_type; uint64_t valuelen; - ngtcp2_ssize nread; - int initial_scid_present = 0; - int original_dcid_present = 0; - size_t i; - (void)transport_params_version; + int rv; + ngtcp2_sockaddr_in *sa_in; + ngtcp2_sockaddr_in6 *sa_in6; + uint32_t version; + ngtcp2_transport_params *params, paramsbuf; - if (datalen == 0) { - return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM; + if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { + params = dest; + } else { + params = ¶msbuf; } /* Set default values */ memset(params, 0, sizeof(*params)); + params->original_dcid_present = 0; + params->initial_scid_present = 0; params->initial_max_streams_bidi = 0; params->initial_max_streams_uni = 0; params->initial_max_stream_data_bidi_local = 0; @@ -543,7 +578,7 @@ int ngtcp2_decode_transport_params_versioned( params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; params->stateless_reset_token_present = 0; - params->preferred_address_present = 0; + params->preferred_addr_present = 0; params->disable_active_migration = 0; params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; params->max_idle_timeout = 0; @@ -560,87 +595,66 @@ int ngtcp2_decode_transport_params_versioned( end = data + datalen; for (; (size_t)(end - p) >= 2;) { - nread = decode_varint(¶m_type, p, end); - if (nread < 0) { + if (decode_varint(¶m_type, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; switch (param_type) { case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL: - nread = decode_varint_param(¶ms->initial_max_stream_data_bidi_local, - p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->initial_max_stream_data_bidi_local, &p, + end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; break; case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE: - nread = decode_varint_param(¶ms->initial_max_stream_data_bidi_remote, - p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->initial_max_stream_data_bidi_remote, &p, + end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; break; case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI: - nread = decode_varint_param(¶ms->initial_max_stream_data_uni, p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->initial_max_stream_data_uni, &p, end) != + 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; break; case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA: - nread = decode_varint_param(¶ms->initial_max_data, p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->initial_max_data, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; break; case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI: - nread = decode_varint_param(¶ms->initial_max_streams_bidi, p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->initial_max_streams_bidi, &p, end) != + 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; break; case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI: - nread = decode_varint_param(¶ms->initial_max_streams_uni, p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->initial_max_streams_uni, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; break; case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT: - nread = decode_varint_param(¶ms->max_idle_timeout, p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->max_idle_timeout, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } params->max_idle_timeout *= NGTCP2_MILLISECONDS; - p += nread; break; case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE: - nread = decode_varint_param(¶ms->max_udp_payload_size, p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->max_udp_payload_size, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; break; case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN: - if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - nread = decode_varint(&valuelen, p, end); - if (nread < 0) { + if (decode_varint(&valuelen, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; if ((size_t)valuelen != sizeof(params->stateless_reset_token)) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } @@ -648,28 +662,23 @@ int ngtcp2_decode_transport_params_versioned( return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - memcpy(params->stateless_reset_token, p, - sizeof(params->stateless_reset_token)); + p = ngtcp2_get_bytes(params->stateless_reset_token, p, + sizeof(params->stateless_reset_token)); params->stateless_reset_token_present = 1; - p += sizeof(params->stateless_reset_token); break; case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT: - nread = decode_varint_param(¶ms->ack_delay_exponent, p, end); - if (nread < 0 || params->ack_delay_exponent > 20) { + if (decode_varint_param(¶ms->ack_delay_exponent, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; - break; - case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS: - if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) { + if (params->ack_delay_exponent > 20) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - nread = decode_varint(&valuelen, p, end); - if (nread < 0) { + break; + case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS: + if (decode_varint(&valuelen, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; if ((size_t)(end - p) < valuelen) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } @@ -680,143 +689,122 @@ int ngtcp2_decode_transport_params_versioned( return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - memcpy(params->preferred_address.ipv4_addr, p, - sizeof(params->preferred_address.ipv4_addr)); - p += sizeof(params->preferred_address.ipv4_addr); - params->preferred_address.ipv4_port = ngtcp2_get_uint16(p); - p += sizeof(uint16_t); + sa_in = ¶ms->preferred_addr.ipv4; + + p = ngtcp2_get_bytes(&sa_in->sin_addr, p, sizeof(sa_in->sin_addr)); + p = ngtcp2_get_uint16be(&sa_in->sin_port, p); - if (params->preferred_address.ipv4_port || - memcmp(empty_address, params->preferred_address.ipv4_addr, - sizeof(params->preferred_address.ipv4_addr)) != 0) { - params->preferred_address.ipv4_present = 1; + if (sa_in->sin_port || memcmp(empty_address, &sa_in->sin_addr, + sizeof(sa_in->sin_addr)) != 0) { + sa_in->sin_family = NGTCP2_AF_INET; + params->preferred_addr.ipv4_present = 1; } - memcpy(params->preferred_address.ipv6_addr, p, - sizeof(params->preferred_address.ipv6_addr)); - p += sizeof(params->preferred_address.ipv6_addr); - params->preferred_address.ipv6_port = ngtcp2_get_uint16(p); - p += sizeof(uint16_t); + sa_in6 = ¶ms->preferred_addr.ipv6; - if (params->preferred_address.ipv6_port || - memcmp(empty_address, params->preferred_address.ipv6_addr, - sizeof(params->preferred_address.ipv6_addr)) != 0) { - params->preferred_address.ipv6_present = 1; + p = ngtcp2_get_bytes(&sa_in6->sin6_addr, p, sizeof(sa_in6->sin6_addr)); + p = ngtcp2_get_uint16be(&sa_in6->sin6_port, p); + + if (sa_in6->sin6_port || memcmp(empty_address, &sa_in6->sin6_addr, + sizeof(sa_in6->sin6_addr)) != 0) { + sa_in6->sin6_family = NGTCP2_AF_INET6; + params->preferred_addr.ipv6_present = 1; } /* cid */ - params->preferred_address.cid.datalen = *p++; - len += params->preferred_address.cid.datalen; + params->preferred_addr.cid.datalen = *p++; + len += params->preferred_addr.cid.datalen; if (valuelen != len || - params->preferred_address.cid.datalen > NGTCP2_MAX_CIDLEN || - params->preferred_address.cid.datalen < NGTCP2_MIN_CIDLEN) { + params->preferred_addr.cid.datalen > NGTCP2_MAX_CIDLEN || + params->preferred_addr.cid.datalen < NGTCP2_MIN_CIDLEN) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - if (params->preferred_address.cid.datalen) { - memcpy(params->preferred_address.cid.data, p, - params->preferred_address.cid.datalen); - p += params->preferred_address.cid.datalen; + if (params->preferred_addr.cid.datalen) { + p = ngtcp2_get_bytes(params->preferred_addr.cid.data, p, + params->preferred_addr.cid.datalen); } /* stateless reset token */ - memcpy(params->preferred_address.stateless_reset_token, p, - sizeof(params->preferred_address.stateless_reset_token)); - p += sizeof(params->preferred_address.stateless_reset_token); - params->preferred_address_present = 1; + p = ngtcp2_get_bytes( + params->preferred_addr.stateless_reset_token, p, + sizeof(params->preferred_addr.stateless_reset_token)); + params->preferred_addr_present = 1; break; case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION: - nread = decode_varint(&valuelen, p, end); - if (nread < 0 || valuelen != 0) { + if (decode_zero_param(&p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; params->disable_active_migration = 1; break; case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID: - if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + rv = decode_cid_param(¶ms->original_dcid, &p, end); + if (rv != 0) { + return rv; } - nread = decode_cid_param(¶ms->original_dcid, p, end); - if (nread < 0) { - return (int)nread; - } - original_dcid_present = 1; - p += nread; + params->original_dcid_present = 1; break; case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID: - if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - nread = decode_cid_param(¶ms->retry_scid, p, end); - if (nread < 0) { - return (int)nread; + rv = decode_cid_param(¶ms->retry_scid, &p, end); + if (rv != 0) { + return rv; } params->retry_scid_present = 1; - p += nread; break; case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID: - nread = decode_cid_param(¶ms->initial_scid, p, end); - if (nread < 0) { - return (int)nread; + rv = decode_cid_param(¶ms->initial_scid, &p, end); + if (rv != 0) { + return rv; } - initial_scid_present = 1; - p += nread; + params->initial_scid_present = 1; break; case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY: - nread = decode_varint_param(¶ms->max_ack_delay, p, end); - if (nread < 0 || params->max_ack_delay >= 16384) { + if (decode_varint_param(¶ms->max_ack_delay, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->max_ack_delay >= 16384) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } params->max_ack_delay *= NGTCP2_MILLISECONDS; - p += nread; break; case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT: - nread = decode_varint_param(¶ms->active_connection_id_limit, p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->active_connection_id_limit, &p, end) != + 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; break; case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE: - nread = decode_varint_param(¶ms->max_datagram_frame_size, p, end); - if (nread < 0) { + if (decode_varint_param(¶ms->max_datagram_frame_size, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; break; case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT: - nread = decode_varint(&valuelen, p, end); - if (nread < 0 || valuelen != 0) { + if (decode_zero_param(&p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; params->grease_quic_bit = 1; break; - case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION_DRAFT: - nread = decode_varint(&valuelen, p, end); - if (nread < 0) { + case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION: + if (decode_varint(&valuelen, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; if ((size_t)(end - p) < valuelen) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } if (valuelen < sizeof(uint32_t) || (valuelen & 0x3)) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - params->version_info.chosen_version = ngtcp2_get_uint32(p); + p = ngtcp2_get_uint32(¶ms->version_info.chosen_version, p); if (params->version_info.chosen_version == 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += sizeof(uint32_t); if (valuelen > sizeof(uint32_t)) { - params->version_info.other_versions = (uint8_t *)p; - params->version_info.other_versionslen = + params->version_info.available_versions = (uint8_t *)p; + params->version_info.available_versionslen = (size_t)valuelen - sizeof(uint32_t); - for (i = sizeof(uint32_t); i < valuelen; - i += sizeof(uint32_t), p += sizeof(uint32_t)) { - if (ngtcp2_get_uint32(p) == 0) { + for (lend = p + (valuelen - sizeof(uint32_t)); p != lend;) { + p = ngtcp2_get_uint32(&version, p); + if (version == 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } } @@ -825,11 +813,9 @@ int ngtcp2_decode_transport_params_versioned( break; default: /* Ignore unknown parameter */ - nread = decode_varint(&valuelen, p, end); - if (nread < 0) { + if (decode_varint(&valuelen, &p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - p += nread; if ((size_t)(end - p) < valuelen) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } @@ -842,10 +828,9 @@ int ngtcp2_decode_transport_params_versioned( return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } - if (!initial_scid_present || - (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS && - !original_dcid_present)) { - return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM; + if (transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION) { + ngtcp2_transport_params_convert_to_old(transport_params_version, dest, + params); } return 0; @@ -859,7 +844,7 @@ static int transport_params_copy_new(ngtcp2_transport_params **pdest, uint8_t *p; if (src->version_info_present) { - len += src->version_info.other_versionslen; + len += src->version_info.available_versionslen; } dest = ngtcp2_mem_malloc(mem, len); @@ -869,11 +854,11 @@ static int transport_params_copy_new(ngtcp2_transport_params **pdest, *dest = *src; - if (src->version_info_present && src->version_info.other_versionslen) { + if (src->version_info_present && src->version_info.available_versionslen) { p = (uint8_t *)dest + sizeof(*dest); - memcpy(p, src->version_info.other_versions, - src->version_info.other_versionslen); - dest->version_info.other_versions = p; + memcpy(p, src->version_info.available_versions, + src->version_info.available_versionslen); + dest->version_info.available_versions = p; } *pdest = dest; @@ -881,14 +866,13 @@ static int transport_params_copy_new(ngtcp2_transport_params **pdest, return 0; } -int ngtcp2_decode_transport_params_new(ngtcp2_transport_params **pparams, - ngtcp2_transport_params_type exttype, +int ngtcp2_transport_params_decode_new(ngtcp2_transport_params **pparams, const uint8_t *data, size_t datalen, const ngtcp2_mem *mem) { int rv; ngtcp2_transport_params params; - rv = ngtcp2_decode_transport_params(¶ms, exttype, data, datalen); + rv = ngtcp2_transport_params_decode(¶ms, data, datalen); if (rv < 0) { return rv; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.h index 9a9d95f5b9fe82..b78429bb38f582 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.h @@ -43,30 +43,30 @@ /* ngtcp2_transport_param_id is the registry of QUIC transport parameter ID. */ -typedef enum ngtcp2_transport_param_id { - NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID = 0x0000, - NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT = 0x0001, - NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN = 0x0002, - NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE = 0x0003, - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA = 0x0004, - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL = 0x0005, - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE = 0x0006, - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI = 0x0007, - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI = 0x0008, - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI = 0x0009, - NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT = 0x000a, - NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY = 0x000b, - NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION = 0x000c, - NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS = 0x000d, - NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT = 0x000e, - NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID = 0x000f, - NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID = 0x0010, - /* https://datatracker.ietf.org/doc/html/rfc9221 */ - NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE = 0x0020, - NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT = 0x2ab2, - /* https://quicwg.org/quic-v2/draft-ietf-quic-v2.html */ - NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION_DRAFT = 0xff73db, -} ngtcp2_transport_param_id; +typedef uint64_t ngtcp2_transport_param_id; + +#define NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID 0x00 +#define NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT 0x01 +#define NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN 0x02 +#define NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE 0x03 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA 0x04 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL 0x05 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE 0x06 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI 0x07 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI 0x08 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI 0x09 +#define NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT 0x0a +#define NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY 0x0b +#define NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION 0x0c +#define NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS 0x0d +#define NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT 0x0e +#define NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID 0x0f +#define NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID 0x10 +/* https://datatracker.ietf.org/doc/html/rfc9221 */ +#define NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE 0x20 +#define NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT 0x2ab2 +/* https://datatracker.ietf.org/doc/html/rfc9368 */ +#define NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION 0x11 /* NGTCP2_CRYPTO_KM_FLAG_NONE indicates that no flag is set. */ #define NGTCP2_CRYPTO_KM_FLAG_NONE 0x00u diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_err.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_err.c index 8f676da3ef0a13..5e4794cd72e7d4 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_err.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_err.c @@ -137,6 +137,9 @@ uint64_t ngtcp2_err_infer_quic_transport_error_code(int liberr) { case NGTCP2_ERR_INVALID_ARGUMENT: case NGTCP2_ERR_NOMEM: case NGTCP2_ERR_CALLBACK_FAILURE: + case NGTCP2_ERR_HANDSHAKE_TIMEOUT: + case NGTCP2_ERR_PKT_NUM_EXHAUSTED: + case NGTCP2_ERR_INTERNAL: return NGTCP2_INTERNAL_ERROR; case NGTCP2_ERR_STREAM_STATE: return NGTCP2_STREAM_STATE_ERROR; @@ -147,7 +150,7 @@ uint64_t ngtcp2_err_infer_quic_transport_error_code(int liberr) { case NGTCP2_ERR_NO_VIABLE_PATH: return NGTCP2_NO_VIABLE_PATH; case NGTCP2_ERR_VERSION_NEGOTIATION_FAILURE: - return NGTCP2_VERSION_NEGOTIATION_ERROR_DRAFT; + return NGTCP2_VERSION_NEGOTIATION_ERROR; default: return NGTCP2_PROTOCOL_VIOLATION; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c new file mode 100644 index 00000000000000..41c2a6a755cc8a --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c @@ -0,0 +1,220 @@ +/* + * ngtcp2 + * + * Copyright (c) 2023 ngtcp2 contributors + * + * 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 "ngtcp2_frame_chain.h" + +#include +#include + +ngtcp2_objalloc_def(frame_chain, ngtcp2_frame_chain, oplent); + +int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem) { + *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain)); + if (*pfrc == NULL) { + return NGTCP2_ERR_NOMEM; + } + + ngtcp2_frame_chain_init(*pfrc); + + return 0; +} + +int ngtcp2_frame_chain_objalloc_new(ngtcp2_frame_chain **pfrc, + ngtcp2_objalloc *objalloc) { + *pfrc = ngtcp2_objalloc_frame_chain_get(objalloc); + if (*pfrc == NULL) { + return NGTCP2_ERR_NOMEM; + } + + ngtcp2_frame_chain_init(*pfrc); + + return 0; +} + +int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen, + const ngtcp2_mem *mem) { + *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain) + extralen); + if (*pfrc == NULL) { + return NGTCP2_ERR_NOMEM; + } + + ngtcp2_frame_chain_init(*pfrc); + + return 0; +} + +int ngtcp2_frame_chain_stream_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, + size_t datacnt, + ngtcp2_objalloc *objalloc, + const ngtcp2_mem *mem) { + size_t need, avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream); + + if (datacnt > 1) { + need = sizeof(ngtcp2_vec) * (datacnt - 1); + + if (need > avail) { + return ngtcp2_frame_chain_extralen_new(pfrc, need - avail, mem); + } + } + + return ngtcp2_frame_chain_objalloc_new(pfrc, objalloc); +} + +int ngtcp2_frame_chain_new_token_objalloc_new(ngtcp2_frame_chain **pfrc, + const uint8_t *token, + size_t tokenlen, + ngtcp2_objalloc *objalloc, + const ngtcp2_mem *mem) { + size_t avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token); + int rv; + uint8_t *p; + ngtcp2_frame *fr; + + if (tokenlen > avail) { + rv = ngtcp2_frame_chain_extralen_new(pfrc, tokenlen - avail, mem); + } else { + rv = ngtcp2_frame_chain_objalloc_new(pfrc, objalloc); + } + if (rv != 0) { + return rv; + } + + fr = &(*pfrc)->fr; + fr->type = NGTCP2_FRAME_NEW_TOKEN; + + p = (uint8_t *)fr + sizeof(ngtcp2_new_token); + memcpy(p, token, tokenlen); + + fr->new_token.token = p; + fr->new_token.tokenlen = tokenlen; + + return 0; +} + +void ngtcp2_frame_chain_del(ngtcp2_frame_chain *frc, const ngtcp2_mem *mem) { + ngtcp2_frame_chain_binder *binder; + + if (frc == NULL) { + return; + } + + binder = frc->binder; + if (binder && --binder->refcount == 0) { + ngtcp2_mem_free(mem, binder); + } + + ngtcp2_mem_free(mem, frc); +} + +void ngtcp2_frame_chain_objalloc_del(ngtcp2_frame_chain *frc, + ngtcp2_objalloc *objalloc, + const ngtcp2_mem *mem) { + ngtcp2_frame_chain_binder *binder; + + if (frc == NULL) { + return; + } + + switch (frc->fr.type) { + case NGTCP2_FRAME_CRYPTO: + case NGTCP2_FRAME_STREAM: + if (frc->fr.stream.datacnt && + sizeof(ngtcp2_vec) * (frc->fr.stream.datacnt - 1) > + sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream)) { + ngtcp2_frame_chain_del(frc, mem); + + return; + } + + break; + case NGTCP2_FRAME_NEW_TOKEN: + if (frc->fr.new_token.tokenlen > + sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token)) { + ngtcp2_frame_chain_del(frc, mem); + + return; + } + + break; + } + + binder = frc->binder; + if (binder && --binder->refcount == 0) { + ngtcp2_mem_free(mem, binder); + } + + frc->binder = NULL; + + ngtcp2_objalloc_frame_chain_release(objalloc, frc); +} + +void ngtcp2_frame_chain_init(ngtcp2_frame_chain *frc) { + frc->next = NULL; + frc->binder = NULL; +} + +void ngtcp2_frame_chain_list_objalloc_del(ngtcp2_frame_chain *frc, + ngtcp2_objalloc *objalloc, + const ngtcp2_mem *mem) { + ngtcp2_frame_chain *next; + + for (; frc; frc = next) { + next = frc->next; + + ngtcp2_frame_chain_objalloc_del(frc, objalloc, mem); + } +} + +int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder, + const ngtcp2_mem *mem) { + *pbinder = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_frame_chain_binder)); + if (*pbinder == NULL) { + return NGTCP2_ERR_NOMEM; + } + + return 0; +} + +int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b, + const ngtcp2_mem *mem) { + ngtcp2_frame_chain_binder *binder; + int rv; + + assert(b->binder == NULL); + + if (a->binder == NULL) { + rv = ngtcp2_frame_chain_binder_new(&binder, mem); + if (rv != 0) { + return rv; + } + + a->binder = binder; + ++a->binder->refcount; + } + + b->binder = a->binder; + ++b->binder->refcount; + + return 0; +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h new file mode 100644 index 00000000000000..656fa5b799450e --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h @@ -0,0 +1,171 @@ +/* + * ngtcp2 + * + * Copyright (c) 2023 ngtcp2 contributors + * + * 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. + */ +#ifndef NGTCP2_FRAME_CHAIN_H +#define NGTCP2_FRAME_CHAIN_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +#include "ngtcp2_pkt.h" +#include "ngtcp2_objalloc.h" + +/* NGTCP2_FRAME_CHAIN_BINDER_FLAG_NONE indicates that no flag is + set. */ +#define NGTCP2_FRAME_CHAIN_BINDER_FLAG_NONE 0x00u +/* NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK indicates that an information + which a frame carries has been acknowledged. */ +#define NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK 0x01u + +/* + * ngtcp2_frame_chain_binder binds 2 or more of ngtcp2_frame_chain to + * share the acknowledgement state. In general, all + * ngtcp2_frame_chains bound to the same binder must have the same + * information. + */ +typedef struct ngtcp2_frame_chain_binder { + size_t refcount; + /* flags is bitwise OR of zero or more of + NGTCP2_FRAME_CHAIN_BINDER_FLAG_*. */ + uint32_t flags; +} ngtcp2_frame_chain_binder; + +int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder, + const ngtcp2_mem *mem); + +typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; + +/* + * ngtcp2_frame_chain chains frames in a single packet. + */ +struct ngtcp2_frame_chain { + union { + struct { + ngtcp2_frame_chain *next; + ngtcp2_frame_chain_binder *binder; + ngtcp2_frame fr; + }; + + ngtcp2_opl_entry oplent; + }; +}; + +ngtcp2_objalloc_decl(frame_chain, ngtcp2_frame_chain, oplent); + +/* + * ngtcp2_bind_frame_chains binds two frame chains |a| and |b| using + * new or existing ngtcp2_frame_chain_binder. |a| might have non-NULL + * a->binder. |b| must not have non-NULL b->binder. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_NOMEM + * Out of memory + */ +int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b, + const ngtcp2_mem *mem); + +/* NGTCP2_MAX_STREAM_DATACNT is the maximum number of ngtcp2_vec that + a ngtcp2_stream can include. */ +#define NGTCP2_MAX_STREAM_DATACNT 256 + +/* + * ngtcp2_frame_chain_new allocates ngtcp2_frame_chain object and + * assigns its pointer to |*pfrc|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_NOMEM + * Out of memory. + */ +int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem); + +/* + * ngtcp2_frame_chain_objalloc_new behaves like + * ngtcp2_frame_chain_new, but it uses |objalloc| to allocate the object. + */ +int ngtcp2_frame_chain_objalloc_new(ngtcp2_frame_chain **pfrc, + ngtcp2_objalloc *objalloc); + +/* + * ngtcp2_frame_chain_extralen_new works like ngtcp2_frame_chain_new, + * but it allocates extra memory |extralen| in order to extend + * ngtcp2_frame. + */ +int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen, + const ngtcp2_mem *mem); + +/* + * ngtcp2_frame_chain_stream_datacnt_objalloc_new works like + * ngtcp2_frame_chain_new, but it allocates enough data to store + * additional |datacnt| - 1 ngtcp2_vec object after ngtcp2_stream + * object. If no additional space is required, + * ngtcp2_frame_chain_objalloc_new is called internally. + */ +int ngtcp2_frame_chain_stream_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, + size_t datacnt, + ngtcp2_objalloc *objalloc, + const ngtcp2_mem *mem); + +int ngtcp2_frame_chain_new_token_objalloc_new(ngtcp2_frame_chain **pfrc, + const uint8_t *token, + size_t tokenlen, + ngtcp2_objalloc *objalloc, + const ngtcp2_mem *mem); + +/* + * ngtcp2_frame_chain_del deallocates |frc|. It also deallocates the + * memory pointed by |frc|. + */ +void ngtcp2_frame_chain_del(ngtcp2_frame_chain *frc, const ngtcp2_mem *mem); + +/* + * ngtcp2_frame_chain_objalloc_del adds |frc| to |objalloc| for reuse. + * It might just delete |frc| depending on the frame type and the size + * of |frc|. + */ +void ngtcp2_frame_chain_objalloc_del(ngtcp2_frame_chain *frc, + ngtcp2_objalloc *objalloc, + const ngtcp2_mem *mem); + +/* + * ngtcp2_frame_chain_init initializes |frc|. + */ +void ngtcp2_frame_chain_init(ngtcp2_frame_chain *frc); + +/* + * ngtcp2_frame_chain_list_objalloc_del adds all ngtcp2_frame_chain + * linked from |frc| to |objalloc| for reuse. Depending on the frame type + * and its size, ngtcp2_frame_chain might be deleted instead. + */ +void ngtcp2_frame_chain_list_objalloc_del(ngtcp2_frame_chain *frc, + ngtcp2_objalloc *objalloc, + const ngtcp2_mem *mem); + +#endif /* NGTCP2_FRAME_CHAIN_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c index 0bd424cb0bc1f1..0ccc048b5b16b1 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c @@ -35,6 +35,8 @@ static ngtcp2_ksl_blk null_blk = {{{NULL, NULL, 0, 0, {0}}}}; +ngtcp2_objalloc_def(ksl_blk, ngtcp2_ksl_blk, oplent); + static size_t ksl_nodelen(size_t keylen) { return (sizeof(ngtcp2_ksl_node) + keylen - sizeof(uint64_t) + 0xfu) & ~(uintptr_t)0xfu; @@ -714,6 +716,24 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key, } } +size_t ngtcp2_ksl_len(ngtcp2_ksl *ksl) { return ksl->n; } + +void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) { + if (!ksl->head) { + return; + } + +#ifdef NOMEMPOOL + ksl_free_blk(ksl, ksl->head); +#endif /* NOMEMPOOL */ + + ksl->front = ksl->back = ksl->head = NULL; + ksl->n = 0; + + ngtcp2_objalloc_clear(&ksl->blkalloc); +} + +#ifndef WIN32 static void ksl_print(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) { size_t i; ngtcp2_ksl_node *node; @@ -734,23 +754,6 @@ static void ksl_print(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) { } } -size_t ngtcp2_ksl_len(ngtcp2_ksl *ksl) { return ksl->n; } - -void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) { - if (!ksl->head) { - return; - } - -#ifdef NOMEMPOOL - ksl_free_blk(ksl, ksl->head); -#endif /* NOMEMPOOL */ - - ksl->front = ksl->back = ksl->head = NULL; - ksl->n = 0; - - ngtcp2_objalloc_clear(&ksl->blkalloc); -} - void ngtcp2_ksl_print(ngtcp2_ksl *ksl) { if (!ksl->head) { return; @@ -758,6 +761,7 @@ void ngtcp2_ksl_print(ngtcp2_ksl *ksl) { ksl_print(ksl, ksl->head, 0); } +#endif /* !WIN32 */ ngtcp2_ksl_it ngtcp2_ksl_begin(const ngtcp2_ksl *ksl) { ngtcp2_ksl_it it; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h index 312a151d4aa9ec..7e08f15cdae6e8 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h @@ -106,7 +106,7 @@ struct ngtcp2_ksl_blk { }; }; -ngtcp2_objalloc_def(ksl_blk, ngtcp2_ksl_blk, oplent); +ngtcp2_objalloc_decl(ksl_blk, ngtcp2_ksl_blk, oplent); /* * ngtcp2_ksl_compar is a function type which returns nonzero if key @@ -263,12 +263,14 @@ void ngtcp2_ksl_clear(ngtcp2_ksl *ksl); #define ngtcp2_ksl_nth_node(KSL, BLK, N) \ ((ngtcp2_ksl_node *)(void *)((BLK)->nodes + (KSL)->nodelen * (N))) +#ifndef WIN32 /* * ngtcp2_ksl_print prints its internal state in stderr. It assumes * that the key is of type int64_t. This function should be used for * the debugging purpose only. */ void ngtcp2_ksl_print(ngtcp2_ksl *ksl); +#endif /* !WIN32 */ /* * ngtcp2_ksl_it_init initializes |it|. diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c index ee37ff3517b2bc..93922a29c319f4 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c @@ -35,6 +35,8 @@ #include "ngtcp2_vec.h" #include "ngtcp2_macro.h" #include "ngtcp2_conv.h" +#include "ngtcp2_unreachable.h" +#include "ngtcp2_net.h" void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid, ngtcp2_printf log_printf, ngtcp2_tstamp ts, @@ -45,6 +47,7 @@ void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid, log->scid[0] = '\0'; } log->log_printf = log_printf; + log->events = 0xff; log->ts = log->last_ts = ts; log->user_data = user_data; } @@ -65,8 +68,7 @@ void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid, * Source Connection ID in hex string. * * : - * Event. pkt=packet, frm=frame, rcv=recovery, cry=crypto, - * con=connection(catch all) + * Event. See ngtcp2_log_event. * * # Frame event * @@ -138,7 +140,7 @@ static const char *strerrorcode(uint64_t error_code) { return "CRYPTO_BUFFER_EXCEEDED"; case NGTCP2_KEY_UPDATE_ERROR: return "KEY_UPDATE_ERROR"; - case NGTCP2_VERSION_NEGOTIATION_ERROR_DRAFT: + case NGTCP2_VERSION_NEGOTIATION_ERROR: return "VERSION_NEGOTIATION_ERROR"; default: if (0x100u <= error_code && error_code <= 0x1ffu) { @@ -202,12 +204,14 @@ static const char *strevent(ngtcp2_log_event ev) { return "pkt"; case NGTCP2_LOG_EVENT_FRM: return "frm"; - case NGTCP2_LOG_EVENT_RCV: - return "rcv"; + case NGTCP2_LOG_EVENT_LDC: + return "ldc"; case NGTCP2_LOG_EVENT_CRY: return "cry"; case NGTCP2_LOG_EVENT_PTV: return "ptv"; + case NGTCP2_LOG_EVENT_CCA: + return "cca"; case NGTCP2_LOG_EVENT_NONE: default: return "non"; @@ -220,8 +224,8 @@ static void log_fr_stream(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_stream *fr, const char *dir) { log->log_printf( log->user_data, - (NGTCP2_LOG_PKT " STREAM(0x%02x) id=0x%" PRIx64 " fin=%d offset=%" PRIu64 - " len=%" PRIu64 " uni=%d"), + (NGTCP2_LOG_PKT " STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 + " fin=%d offset=%" PRIu64 " len=%" PRIu64 " uni=%d"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type | fr->flags, fr->stream_id, fr->fin, fr->offset, ngtcp2_vec_len(fr->data, fr->datacnt), (fr->stream_id & 0x2) != 0); @@ -233,36 +237,37 @@ static void log_fr_ack(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, size_t i; log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " ACK(0x%02x) largest_ack=%" PRId64 + (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") largest_ack=%" PRId64 " ack_delay=%" PRIu64 "(%" PRIu64 - ") ack_block_count=%zu"), + ") ack_range_count=%zu"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->largest_ack, fr->ack_delay_unscaled / NGTCP2_MILLISECONDS, fr->ack_delay, - fr->num_blks); + fr->rangecnt); largest_ack = fr->largest_ack; - min_ack = fr->largest_ack - (int64_t)fr->first_ack_blklen; + min_ack = fr->largest_ack - (int64_t)fr->first_ack_range; log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " ACK(0x%02x) block=[%" PRId64 "..%" PRId64 - "] block_count=%" PRIu64), + (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") range=[%" PRId64 + "..%" PRId64 "] len=%" PRIu64), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, largest_ack, min_ack, - fr->first_ack_blklen); + fr->first_ack_range); - for (i = 0; i < fr->num_blks; ++i) { - const ngtcp2_ack_blk *blk = &fr->blks[i]; - largest_ack = min_ack - (int64_t)blk->gap - 2; - min_ack = largest_ack - (int64_t)blk->blklen; + for (i = 0; i < fr->rangecnt; ++i) { + const ngtcp2_ack_range *range = &fr->ranges[i]; + largest_ack = min_ack - (int64_t)range->gap - 2; + min_ack = largest_ack - (int64_t)range->len; log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " ACK(0x%02x) block=[%" PRId64 "..%" PRId64 - "] gap=%" PRIu64 " block_count=%" PRIu64), + (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") range=[%" PRId64 + "..%" PRId64 "] gap=%" PRIu64 + " len=%" PRIu64), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, largest_ack, - min_ack, blk->gap, blk->blklen); + min_ack, range->gap, range->len); } if (fr->type == NGTCP2_FRAME_ACK_ECN) { log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " ACK(0x%02x) ect0=%" PRIu64 + (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") ect0=%" PRIu64 " ect1=%" PRIu64 " ce=%" PRIu64), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->ecn.ect0, fr->ecn.ect1, fr->ecn.ce); @@ -271,7 +276,8 @@ static void log_fr_ack(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, static void log_fr_padding(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_padding *fr, const char *dir) { - log->log_printf(log->user_data, (NGTCP2_LOG_PKT " PADDING(0x%02x) len=%zu"), + log->log_printf(log->user_data, + (NGTCP2_LOG_PKT " PADDING(0x%02" PRIx64 ") len=%zu"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->len); } @@ -280,7 +286,7 @@ static void log_fr_reset_stream(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const char *dir) { log->log_printf( log->user_data, - (NGTCP2_LOG_PKT " RESET_STREAM(0x%02x) id=0x%" PRIx64 + (NGTCP2_LOG_PKT " RESET_STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 " app_error_code=%s(0x%" PRIx64 ") final_size=%" PRIu64), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, strapperrorcode(fr->app_error_code), fr->app_error_code, fr->final_size); @@ -293,9 +299,10 @@ static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, size_t reasonlen = ngtcp2_min(sizeof(reason) - 1, fr->reasonlen); log->log_printf(log->user_data, - (NGTCP2_LOG_PKT - " CONNECTION_CLOSE(0x%02x) error_code=%s(0x%" PRIx64 ") " - "frame_type=%" PRIx64 " reason_len=%zu reason=[%s]"), + (NGTCP2_LOG_PKT " CONNECTION_CLOSE(0x%02" PRIx64 + ") error_code=%s(0x%" PRIx64 ") " + "frame_type=%" PRIx64 + " reason_len=%zu reason=[%s]"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->type == NGTCP2_FRAME_CONNECTION_CLOSE ? strerrorcode(fr->error_code) @@ -306,16 +313,18 @@ static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, static void log_fr_max_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_max_data *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " MAX_DATA(0x%02x) max_data=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_data); + log->log_printf( + log->user_data, + (NGTCP2_LOG_PKT " MAX_DATA(0x%02" PRIx64 ") max_data=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_data); } static void log_fr_max_stream_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_max_stream_data *fr, const char *dir) { log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " MAX_STREAM_DATA(0x%02x) id=0x%" PRIx64 + (NGTCP2_LOG_PKT " MAX_STREAM_DATA(0x%02" PRIx64 + ") id=0x%" PRIx64 " max_stream_data=%" PRIu64), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, fr->max_stream_data); @@ -323,31 +332,33 @@ static void log_fr_max_stream_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, static void log_fr_max_streams(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_max_streams *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " MAX_STREAMS(0x%02x) max_streams=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams); + log->log_printf( + log->user_data, + (NGTCP2_LOG_PKT " MAX_STREAMS(0x%02" PRIx64 ") max_streams=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams); } static void log_fr_ping(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_ping *fr, const char *dir) { - log->log_printf(log->user_data, (NGTCP2_LOG_PKT " PING(0x%02x)"), + log->log_printf(log->user_data, (NGTCP2_LOG_PKT " PING(0x%02" PRIx64 ")"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type); } static void log_fr_data_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_data_blocked *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " DATA_BLOCKED(0x%02x) offset=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset); + log->log_printf( + log->user_data, + (NGTCP2_LOG_PKT " DATA_BLOCKED(0x%02" PRIx64 ") offset=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset); } static void log_fr_stream_data_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_stream_data_blocked *fr, const char *dir) { log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " STREAM_DATA_BLOCKED(0x%02x) id=0x%" PRIx64 - " offset=%" PRIu64), + (NGTCP2_LOG_PKT " STREAM_DATA_BLOCKED(0x%02" PRIx64 + ") id=0x%" PRIx64 " offset=%" PRIu64), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, fr->offset); } @@ -357,7 +368,7 @@ static void log_fr_streams_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const char *dir) { log->log_printf( log->user_data, - (NGTCP2_LOG_PKT " STREAMS_BLOCKED(0x%02x) max_streams=%" PRIu64), + (NGTCP2_LOG_PKT " STREAMS_BLOCKED(0x%02" PRIx64 ") max_streams=%" PRIu64), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams); } @@ -369,7 +380,7 @@ static void log_fr_new_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, log->log_printf( log->user_data, - (NGTCP2_LOG_PKT " NEW_CONNECTION_ID(0x%02x) seq=%" PRIu64 + (NGTCP2_LOG_PKT " NEW_CONNECTION_ID(0x%02" PRIx64 ") seq=%" PRIu64 " cid=0x%s retire_prior_to=%" PRIu64 " stateless_reset_token=0x%s"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq, @@ -383,7 +394,7 @@ static void log_fr_stop_sending(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_stop_sending *fr, const char *dir) { log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " STOP_SENDING(0x%02x) id=0x%" PRIx64 + (NGTCP2_LOG_PKT " STOP_SENDING(0x%02" PRIx64 ") id=0x%" PRIx64 " app_error_code=%s(0x%" PRIx64 ")"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, strapperrorcode(fr->app_error_code), fr->app_error_code); @@ -395,7 +406,8 @@ static void log_fr_path_challenge(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, uint8_t buf[sizeof(fr->data) * 2 + 1]; log->log_printf( - log->user_data, (NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02x) data=0x%s"), + log->user_data, + (NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02" PRIx64 ") data=0x%s"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); } @@ -406,18 +418,19 @@ static void log_fr_path_response(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, uint8_t buf[sizeof(fr->data) * 2 + 1]; log->log_printf( - log->user_data, (NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02x) data=0x%s"), + log->user_data, + (NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02" PRIx64 ") data=0x%s"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); } static void log_fr_crypto(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, - const ngtcp2_crypto *fr, const char *dir) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " CRYPTO(0x%02x) offset=%" PRIu64 " len=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset, - ngtcp2_vec_len(fr->data, fr->datacnt)); + const ngtcp2_stream *fr, const char *dir) { + log->log_printf(log->user_data, + (NGTCP2_LOG_PKT " CRYPTO(0x%02" PRIx64 ") offset=%" PRIu64 + " len=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset, + ngtcp2_vec_len(fr->data, fr->datacnt)); } static void log_fr_new_token(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -427,38 +440,41 @@ static void log_fr_new_token(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, uint8_t buf[128 + 1 + 1]; uint8_t *p; - if (fr->token.len > 64) { - p = ngtcp2_encode_hex(buf, fr->token.base, 64); + if (fr->tokenlen > 64) { + p = ngtcp2_encode_hex(buf, fr->token, 64); p[128] = '*'; p[129] = '\0'; } else { - p = ngtcp2_encode_hex(buf, fr->token.base, fr->token.len); + p = ngtcp2_encode_hex(buf, fr->token, fr->tokenlen); } log->log_printf( - log->user_data, (NGTCP2_LOG_PKT " NEW_TOKEN(0x%02x) token=0x%s len=%zu"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)p, fr->token.len); + log->user_data, + (NGTCP2_LOG_PKT " NEW_TOKEN(0x%02" PRIx64 ") token=0x%s len=%zu"), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)p, fr->tokenlen); } static void log_fr_retire_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_retire_connection_id *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " RETIRE_CONNECTION_ID(0x%02x) seq=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq); + log->log_printf( + log->user_data, + (NGTCP2_LOG_PKT " RETIRE_CONNECTION_ID(0x%02" PRIx64 ") seq=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq); } static void log_fr_handshake_done(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_handshake_done *fr, const char *dir) { - log->log_printf(log->user_data, (NGTCP2_LOG_PKT " HANDSHAKE_DONE(0x%02x)"), + log->log_printf(log->user_data, + (NGTCP2_LOG_PKT " HANDSHAKE_DONE(0x%02" PRIx64 ")"), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type); } static void log_fr_datagram(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_datagram *fr, const char *dir) { log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " DATAGRAM(0x%02x) len=%" PRIu64), + (NGTCP2_LOG_PKT " DATAGRAM(0x%02" PRIx64 ") len=%" PRIu64), NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, ngtcp2_vec_len(fr->data, fr->datacnt)); } @@ -519,7 +535,7 @@ static void log_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, log_fr_path_response(log, hd, &fr->path_response, dir); break; case NGTCP2_FRAME_CRYPTO: - log_fr_crypto(log, hd, &fr->crypto, dir); + log_fr_crypto(log, hd, &fr->stream, dir); break; case NGTCP2_FRAME_NEW_TOKEN: log_fr_new_token(log, hd, &fr->new_token, dir); @@ -535,13 +551,13 @@ static void log_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, log_fr_datagram(log, hd, &fr->datagram, dir); break; default: - assert(0); + ngtcp2_unreachable(); } } void ngtcp2_log_rx_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_frame *fr) { - if (!log->log_printf) { + if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_FRM)) { return; } @@ -550,7 +566,7 @@ void ngtcp2_log_rx_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, void ngtcp2_log_tx_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_frame *fr) { - if (!log->log_printf) { + if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_FRM)) { return; } @@ -561,7 +577,7 @@ void ngtcp2_log_rx_vn(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const uint32_t *sv, size_t nsv) { size_t i; - if (!log->log_printf) { + if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_PKT)) { return; } @@ -576,7 +592,7 @@ void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) { ngtcp2_pkt_hd shd; ngtcp2_pkt_hd *hd = &shd; - if (!log->log_printf) { + if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_PKT)) { return; } @@ -592,82 +608,94 @@ void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) { sr->randlen); } -void ngtcp2_log_remote_tp(ngtcp2_log *log, uint8_t exttype, +void ngtcp2_log_remote_tp(ngtcp2_log *log, const ngtcp2_transport_params *params) { uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1]; uint8_t addr[16 * 2 + 7 + 1]; uint8_t cid[NGTCP2_MAX_CIDLEN * 2 + 1]; size_t i; + const ngtcp2_sockaddr_in *sa_in; + const ngtcp2_sockaddr_in6 *sa_in6; + const uint8_t *p; + uint32_t version; - if (!log->log_printf) { + if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_CRY)) { return; } - if (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) { - if (params->stateless_reset_token_present) { - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " stateless_reset_token=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex( - token, params->stateless_reset_token, - sizeof(params->stateless_reset_token))); - } + if (params->stateless_reset_token_present) { + log->log_printf( + log->user_data, (NGTCP2_LOG_TP " stateless_reset_token=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex(token, params->stateless_reset_token, + sizeof(params->stateless_reset_token))); + } + + if (params->preferred_addr_present) { + if (params->preferred_addr.ipv4_present) { + sa_in = ¶ms->preferred_addr.ipv4; - if (params->preferred_address_present) { log->log_printf(log->user_data, (NGTCP2_LOG_TP " preferred_address.ipv4_addr=%s"), NGTCP2_LOG_TP_HD_FIELDS, (const char *)ngtcp2_encode_ipv4( - addr, params->preferred_address.ipv4_addr)); - log->log_printf( - log->user_data, (NGTCP2_LOG_TP " preferred_address.ipv4_port=%u"), - NGTCP2_LOG_TP_HD_FIELDS, params->preferred_address.ipv4_port); + addr, (const uint8_t *)&sa_in->sin_addr)); + log->log_printf(log->user_data, + (NGTCP2_LOG_TP " preferred_address.ipv4_port=%u"), + NGTCP2_LOG_TP_HD_FIELDS, ngtcp2_ntohs(sa_in->sin_port)); + } + + if (params->preferred_addr.ipv6_present) { + sa_in6 = ¶ms->preferred_addr.ipv6; log->log_printf(log->user_data, (NGTCP2_LOG_TP " preferred_address.ipv6_addr=%s"), NGTCP2_LOG_TP_HD_FIELDS, (const char *)ngtcp2_encode_ipv6( - addr, params->preferred_address.ipv6_addr)); - log->log_printf( - log->user_data, (NGTCP2_LOG_TP " preferred_address.ipv6_port=%u"), - NGTCP2_LOG_TP_HD_FIELDS, params->preferred_address.ipv6_port); - + addr, (const uint8_t *)&sa_in6->sin6_addr)); log->log_printf(log->user_data, - (NGTCP2_LOG_TP " preferred_address.cid=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex( - cid, params->preferred_address.cid.data, - params->preferred_address.cid.datalen)); - log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " preferred_address.stateless_reset_token=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex( - token, params->preferred_address.stateless_reset_token, - sizeof(params->preferred_address.stateless_reset_token))); + (NGTCP2_LOG_TP " preferred_address.ipv6_port=%u"), + NGTCP2_LOG_TP_HD_FIELDS, ngtcp2_ntohs(sa_in6->sin6_port)); } + log->log_printf( + log->user_data, (NGTCP2_LOG_TP " preferred_address.cid=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex(cid, params->preferred_addr.cid.data, + params->preferred_addr.cid.datalen)); + log->log_printf( + log->user_data, + (NGTCP2_LOG_TP " preferred_address.stateless_reset_token=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex( + token, params->preferred_addr.stateless_reset_token, + sizeof(params->preferred_addr.stateless_reset_token))); + } + + if (params->original_dcid_present) { log->log_printf( log->user_data, (NGTCP2_LOG_TP " original_destination_connection_id=0x%s"), NGTCP2_LOG_TP_HD_FIELDS, (const char *)ngtcp2_encode_hex(cid, params->original_dcid.data, params->original_dcid.datalen)); + } - if (params->retry_scid_present) { - log->log_printf( - log->user_data, (NGTCP2_LOG_TP " retry_source_connection_id=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->retry_scid.data, - params->retry_scid.datalen)); - } + if (params->retry_scid_present) { + log->log_printf( + log->user_data, (NGTCP2_LOG_TP " retry_source_connection_id=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex(cid, params->retry_scid.data, + params->retry_scid.datalen)); } - log->log_printf( - log->user_data, (NGTCP2_LOG_TP " initial_source_connection_id=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->initial_scid.data, - params->initial_scid.datalen)); + if (params->initial_scid_present) { + log->log_printf( + log->user_data, (NGTCP2_LOG_TP " initial_source_connection_id=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex(cid, params->initial_scid.data, + params->initial_scid.datalen)); + } log->log_printf( log->user_data, @@ -718,26 +746,28 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, uint8_t exttype, (NGTCP2_LOG_TP " version_information.chosen_version=0x%08x"), NGTCP2_LOG_TP_HD_FIELDS, params->version_info.chosen_version); - assert(!(params->version_info.other_versionslen & 0x3)); + assert(!(params->version_info.available_versionslen & 0x3)); - for (i = 0; i < params->version_info.other_versionslen; + for (i = 0, p = params->version_info.available_versions; + i < params->version_info.available_versionslen; i += sizeof(uint32_t)) { + p = ngtcp2_get_uint32(&version, p); + log->log_printf( log->user_data, - (NGTCP2_LOG_TP " version_information.other_versions[%zu]=0x%08x"), - NGTCP2_LOG_TP_HD_FIELDS, i >> 2, - ngtcp2_get_uint32(¶ms->version_info.other_versions[i])); + (NGTCP2_LOG_TP " version_information.available_versions[%zu]=0x%08x"), + NGTCP2_LOG_TP_HD_FIELDS, i >> 2, version); } } } void ngtcp2_log_pkt_lost(ngtcp2_log *log, int64_t pkt_num, uint8_t type, uint8_t flags, ngtcp2_tstamp sent_ts) { - if (!log->log_printf) { + if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_LDC)) { return; } - ngtcp2_log_info(log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(log, NGTCP2_LOG_EVENT_LDC, "pkn=%" PRId64 " lost type=%s sent_ts=%" PRIu64, pkt_num, strpkttype_type_flags(type, flags), sent_ts); } @@ -747,7 +777,7 @@ static void log_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, uint8_t dcid[sizeof(hd->dcid.data) * 2 + 1]; uint8_t scid[sizeof(hd->scid.data) * 2 + 1]; - if (!log->log_printf) { + if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_PKT)) { return; } @@ -782,7 +812,7 @@ void ngtcp2_log_info(ngtcp2_log *log, ngtcp2_log_event ev, const char *fmt, int n; char buf[NGTCP2_LOG_BUFLEN]; - if (!log->log_printf) { + if (!log->log_printf || !(log->events & ev)) { return; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h index 029ef1b757ab09..1280ce04d6385a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h @@ -37,6 +37,9 @@ typedef struct ngtcp2_log { /* log_printf is a sink to write log. NULL means no logging output. */ ngtcp2_printf log_printf; + /* events is an event filter. Only events set in this field are + emitted. */ + uint8_t events; /* ts is the time point used to write time delta in the log. */ ngtcp2_tstamp ts; /* last_ts is the most recent time point that this object is @@ -63,27 +66,33 @@ typedef enum ngtcp2_log_event { /** * :enum:`NGTCP2_LOG_EVENT_CON` is a connection (catch-all) event */ - NGTCP2_LOG_EVENT_CON, + NGTCP2_LOG_EVENT_CON = 0x1, /** * :enum:`NGTCP2_LOG_EVENT_PKT` is a packet event. */ - NGTCP2_LOG_EVENT_PKT, + NGTCP2_LOG_EVENT_PKT = 0x2, /** * :enum:`NGTCP2_LOG_EVENT_FRM` is a QUIC frame event. */ - NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_EVENT_FRM = 0x4, /** - * :enum:`NGTCP2_LOG_EVENT_RCV` is a congestion and recovery event. + * :enum:`NGTCP2_LOG_EVENT_LDC` is a loss detection and congestion + * control event. */ - NGTCP2_LOG_EVENT_RCV, + NGTCP2_LOG_EVENT_LDC = 0x8, /** * :enum:`NGTCP2_LOG_EVENT_CRY` is a crypto event. */ - NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_EVENT_CRY = 0x10, /** * :enum:`NGTCP2_LOG_EVENT_PTV` is a path validation event. */ - NGTCP2_LOG_EVENT_PTV, + NGTCP2_LOG_EVENT_PTV = 0x20, + /** + * :enum:`NGTCP2_LOG_EVENT_CCA` is a congestion controller algorithm + * event. + */ + NGTCP2_LOG_EVENT_CCA = 0x40, } ngtcp2_log_event; void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid, @@ -100,7 +109,7 @@ void ngtcp2_log_rx_vn(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr); -void ngtcp2_log_remote_tp(ngtcp2_log *log, uint8_t exttype, +void ngtcp2_log_remote_tp(ngtcp2_log *log, const ngtcp2_transport_params *params); void ngtcp2_log_pkt_lost(ngtcp2_log *log, int64_t pkt_num, uint8_t type, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_macro.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_macro.h index e2603aae15dd04..28d3461bef9238 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_macro.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_macro.h @@ -50,4 +50,9 @@ *(PD) = (T); \ } while (0) +/* + * ngtcp2_arraylen returns the number of elements in array |A|. + */ +#define ngtcp2_arraylen(A) (sizeof(A) / sizeof(A[0])) + #endif /* NGTCP2_MACRO_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c index 12bc6e84bd4f0c..33e9fcc018b5db 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c @@ -126,6 +126,7 @@ static void map_bucket_set_data(ngtcp2_map_bucket *bkt, uint32_t hash, bkt->data = data; } +#ifndef WIN32 void ngtcp2_map_print_distance(ngtcp2_map *map) { uint32_t i; size_t idx; @@ -145,6 +146,7 @@ void ngtcp2_map_print_distance(ngtcp2_map *map) { distance(map->tablelen, map->tablelenbits, bkt, idx)); } } +#endif /* !WIN32 */ static int insert(ngtcp2_map_bucket *table, uint32_t tablelen, uint32_t tablelenbits, uint32_t hash, ngtcp2_map_key_type key, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h index a64344a9a301a3..d05b1657489e45 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h @@ -131,6 +131,8 @@ size_t ngtcp2_map_size(ngtcp2_map *map); int ngtcp2_map_each(ngtcp2_map *map, int (*func)(void *data, void *ptr), void *ptr); +#ifndef WIN32 void ngtcp2_map_print_distance(ngtcp2_map *map); +#endif /* !WIN32 */ #endif /* NGTCP2_MAP_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_net.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_net.h index b1f28096174605..4a2c4041d4d170 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_net.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_net.h @@ -52,16 +52,11 @@ # include #endif /* HAVE_SYS_ENDIAN_H */ -#include +#if defined(__APPLE__) +# include +#endif // __APPLE__ -#if defined(HAVE_BSWAP_64) || \ - (defined(HAVE_DECL_BSWAP_64) && HAVE_DECL_BSWAP_64 > 0) -# define ngtcp2_bswap64 bswap_64 -#else /* !HAVE_BSWAP_64 */ -# define ngtcp2_bswap64(N) \ - ((uint64_t)(ngtcp2_ntohl((uint32_t)(N))) << 32 | \ - ngtcp2_ntohl((uint32_t)((N) >> 32))) -#endif /* !HAVE_BSWAP_64 */ +#include #if defined(HAVE_BE64TOH) || \ (defined(HAVE_DECL_BE64TOH) && HAVE_DECL_BE64TOH > 0) @@ -72,6 +67,18 @@ # define ngtcp2_ntohl64(N) (N) # define ngtcp2_htonl64(N) (N) # else /* !WORDS_BIGENDIAN */ +# if defined(HAVE_BSWAP_64) || \ + (defined(HAVE_DECL_BSWAP_64) && HAVE_DECL_BSWAP_64 > 0) +# define ngtcp2_bswap64 bswap_64 +# elif defined(WIN32) +# define ngtcp2_bswap64 _byteswap_uint64 +# elif defined(__APPLE__) +# define ngtcp2_bswap64 OSSwapInt64 +# else /* !HAVE_BSWAP_64 && !WIN32 && !__APPLE__ */ +# define ngtcp2_bswap64(N) \ + ((uint64_t)(ngtcp2_ntohl((uint32_t)(N))) << 32 | \ + ngtcp2_ntohl((uint32_t)((N) >> 32))) +# endif /* !HAVE_BSWAP_64 && !WIN32 && !__APPLE__ */ # define ngtcp2_ntohl64(N) ngtcp2_bswap64(N) # define ngtcp2_htonl64(N) ngtcp2_bswap64(N) # endif /* !WORDS_BIGENDIAN */ @@ -80,7 +87,7 @@ #if defined(WIN32) /* Windows requires ws2_32 library for ntonl family functions. We define inline functions for those function so that we don't have - dependeny on that lib. */ + dependency on that lib. */ # ifdef _MSC_VER # define STIN static __inline @@ -109,9 +116,9 @@ STIN uint16_t ngtcp2_htons(uint16_t hostshort) { STIN uint32_t ngtcp2_ntohl(uint32_t netlong) { uint32_t res; unsigned char *p = (unsigned char *)&netlong; - res = *p++ << 24; - res += *p++ << 16; - res += *p++ << 8; + res = (uint32_t)(*p++ << 24); + res += (uint32_t)(*p++ << 16); + res += (uint32_t)(*p++ << 8); res += *p; return res; } @@ -119,7 +126,7 @@ STIN uint32_t ngtcp2_ntohl(uint32_t netlong) { STIN uint16_t ngtcp2_ntohs(uint16_t netshort) { uint16_t res; unsigned char *p = (unsigned char *)&netshort; - res = *p++ << 8; + res = (uint16_t)(*p++ << 8); res += *p; return res; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_objalloc.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_objalloc.h index f1bbd3a5c9405c..ea73e788317681 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_objalloc.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_objalloc.h @@ -65,15 +65,25 @@ void ngtcp2_objalloc_free(ngtcp2_objalloc *objalloc); void ngtcp2_objalloc_clear(ngtcp2_objalloc *objalloc); #ifndef NOMEMPOOL -# define ngtcp2_objalloc_def(NAME, TYPE, OPLENTFIELD) \ +# define ngtcp2_objalloc_decl(NAME, TYPE, OPLENTFIELD) \ inline static void ngtcp2_objalloc_##NAME##_init( \ ngtcp2_objalloc *objalloc, size_t nmemb, const ngtcp2_mem *mem) { \ ngtcp2_objalloc_init( \ objalloc, ((sizeof(TYPE) + 0xfu) & ~(uintptr_t)0xfu) * nmemb, mem); \ } \ \ - inline static TYPE *ngtcp2_objalloc_##NAME##_get( \ - ngtcp2_objalloc *objalloc) { \ + TYPE *ngtcp2_objalloc_##NAME##_get(ngtcp2_objalloc *objalloc); \ + \ + TYPE *ngtcp2_objalloc_##NAME##_len_get(ngtcp2_objalloc *objalloc, \ + size_t len); \ + \ + inline static void ngtcp2_objalloc_##NAME##_release( \ + ngtcp2_objalloc *objalloc, TYPE *obj) { \ + ngtcp2_opl_push(&objalloc->opl, &obj->OPLENTFIELD); \ + } + +# define ngtcp2_objalloc_def(NAME, TYPE, OPLENTFIELD) \ + TYPE *ngtcp2_objalloc_##NAME##_get(ngtcp2_objalloc *objalloc) { \ ngtcp2_opl_entry *oplent = ngtcp2_opl_pop(&objalloc->opl); \ TYPE *obj; \ int rv; \ @@ -91,8 +101,8 @@ void ngtcp2_objalloc_clear(ngtcp2_objalloc *objalloc); return ngtcp2_struct_of(oplent, TYPE, OPLENTFIELD); \ } \ \ - inline static TYPE *ngtcp2_objalloc_##NAME##_len_get( \ - ngtcp2_objalloc *objalloc, size_t len) { \ + TYPE *ngtcp2_objalloc_##NAME##_len_get(ngtcp2_objalloc *objalloc, \ + size_t len) { \ ngtcp2_opl_entry *oplent = ngtcp2_opl_pop(&objalloc->opl); \ TYPE *obj; \ int rv; \ @@ -107,14 +117,9 @@ void ngtcp2_objalloc_clear(ngtcp2_objalloc *objalloc); } \ \ return ngtcp2_struct_of(oplent, TYPE, OPLENTFIELD); \ - } \ - \ - inline static void ngtcp2_objalloc_##NAME##_release( \ - ngtcp2_objalloc *objalloc, TYPE *obj) { \ - ngtcp2_opl_push(&objalloc->opl, &obj->OPLENTFIELD); \ } #else /* NOMEMPOOL */ -# define ngtcp2_objalloc_def(NAME, TYPE, OPLENTFIELD) \ +# define ngtcp2_objalloc_decl(NAME, TYPE, OPLENTFIELD) \ inline static void ngtcp2_objalloc_##NAME##_init( \ ngtcp2_objalloc *objalloc, size_t nmemb, const ngtcp2_mem *mem) { \ ngtcp2_objalloc_init( \ @@ -135,6 +140,8 @@ void ngtcp2_objalloc_clear(ngtcp2_objalloc *objalloc); ngtcp2_objalloc *objalloc, TYPE *obj) { \ ngtcp2_mem_free(objalloc->balloc.mem, obj); \ } + +# define ngtcp2_objalloc_def(NAME, TYPE, OPLENTFIELD) #endif /* NOMEMPOOL */ #endif /* NGTCP2_OBJALLOC_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c index 62fef7d6005ed6..1687ff254d94c7 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c @@ -33,6 +33,7 @@ #include "ngtcp2_cid.h" #include "ngtcp2_mem.h" #include "ngtcp2_vec.h" +#include "ngtcp2_unreachable.h" int ngtcp2_pkt_chain_new(ngtcp2_pkt_chain **ppc, const ngtcp2_path *path, const ngtcp2_pkt_info *pi, const uint8_t *pkt, @@ -91,7 +92,7 @@ int ngtcp2_pkt_decode_version_cid(ngtcp2_version_cid *dest, const uint8_t *data, return NGTCP2_ERR_INVALID_ARGUMENT; } - version = ngtcp2_get_uint32(&data[1]); + ngtcp2_get_uint32(&version, &data[1]); supported_version = ngtcp2_is_supported_version(version); @@ -155,15 +156,13 @@ void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type, ngtcp2_cid_zero(&hd->scid); } hd->pkt_num = pkt_num; - hd->token.base = NULL; - hd->token.len = 0; + hd->token = NULL; + hd->tokenlen = 0; hd->pkt_numlen = pkt_numlen; hd->version = version; hd->len = len; } -static int has_mask(uint8_t b, uint8_t mask) { return (b & mask) == mask; } - ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, size_t pktlen) { uint8_t type; @@ -186,7 +185,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, return NGTCP2_ERR_INVALID_ARGUMENT; } - version = ngtcp2_get_uint32(&pkt[1]); + ngtcp2_get_uint32(&version, &pkt[1]); if (version == 0) { type = NGTCP2_PKT_VERSION_NEGOTIATION; @@ -218,7 +217,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, break; default: /* Unreachable */ - assert(0); + ngtcp2_unreachable(); } } @@ -254,22 +253,20 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, if (type == NGTCP2_PKT_INITIAL) { /* Token Length */ - ntokenlen = ngtcp2_get_varint_len(p); + ntokenlen = ngtcp2_get_uvarintlen(p); len += ntokenlen - 1; if (pktlen < len) { return NGTCP2_ERR_INVALID_ARGUMENT; } - vi = ngtcp2_get_varint(&ntokenlen, p); + p = ngtcp2_get_uvarint(&vi, p); if (pktlen - len < vi) { return NGTCP2_ERR_INVALID_ARGUMENT; } tokenlen = (size_t)vi; len += tokenlen; - p += ntokenlen; - if (tokenlen) { token = p; } @@ -288,7 +285,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, } /* Length */ - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (pktlen < len) { @@ -308,8 +305,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, ngtcp2_cid_init(&dest->scid, p, scil); p += scil; - dest->token.base = (uint8_t *)token; - dest->token.len = tokenlen; + dest->token = token; + dest->tokenlen = tokenlen; p += ntokenlen + tokenlen; switch (type) { @@ -324,12 +321,11 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, break; } - vi = ngtcp2_get_varint(&n, p); + p = ngtcp2_get_uvarint(&vi, p); if (vi > SIZE_MAX) { return NGTCP2_ERR_INVALID_ARGUMENT; } dest->len = (size_t)vi; - p += n; } assert((size_t)(p - pkt) == len); @@ -373,8 +369,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_short(ngtcp2_pkt_hd *dest, const uint8_t *pkt, dest->len = 0; dest->pkt_num = 0; dest->pkt_numlen = 0; - dest->token.base = NULL; - dest->token.len = 0; + dest->token = NULL; + dest->tokenlen = 0; assert((size_t)(p - pkt) == len); @@ -393,7 +389,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen, } if (hd->type == NGTCP2_PKT_INITIAL) { - len += ngtcp2_put_varint_len(hd->token.len) + hd->token.len; + len += ngtcp2_put_uvarintlen(hd->tokenlen) + hd->tokenlen; } if (outlen < len) { @@ -422,14 +418,14 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen, } if (hd->type == NGTCP2_PKT_INITIAL) { - p = ngtcp2_put_varint(p, hd->token.len); - if (hd->token.len) { - p = ngtcp2_cpymem(p, hd->token.base, hd->token.len); + p = ngtcp2_put_uvarint(p, hd->tokenlen); + if (hd->tokenlen) { + p = ngtcp2_cpymem(p, hd->token, hd->tokenlen); } } if (hd->type != NGTCP2_PKT_RETRY) { - p = ngtcp2_put_varint30(p, (uint32_t)hd->len); + p = ngtcp2_put_uvarint30(p, (uint32_t)hd->len); p = ngtcp2_put_pkt_num(p, hd->pkt_num, hd->pkt_numlen); } @@ -475,15 +471,14 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, uint8_t type; if (payloadlen == 0) { - return 0; + return NGTCP2_ERR_FRAME_ENCODING; } type = payload[0]; switch (type) { case NGTCP2_FRAME_PADDING: - return (ngtcp2_ssize)ngtcp2_pkt_decode_padding_frame(&dest->padding, - payload, payloadlen); + return ngtcp2_pkt_decode_padding_frame(&dest->padding, payload, payloadlen); case NGTCP2_FRAME_RESET_STREAM: return ngtcp2_pkt_decode_reset_stream_frame(&dest->reset_stream, payload, payloadlen); @@ -529,7 +524,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, return ngtcp2_pkt_decode_path_response_frame(&dest->path_response, payload, payloadlen); case NGTCP2_FRAME_CRYPTO: - return ngtcp2_pkt_decode_crypto_frame(&dest->crypto, payload, payloadlen); + return ngtcp2_pkt_decode_crypto_frame(&dest->stream, payload, payloadlen); case NGTCP2_FRAME_NEW_TOKEN: return ngtcp2_pkt_decode_new_token_frame(&dest->new_token, payload, payloadlen); @@ -544,9 +539,15 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, return ngtcp2_pkt_decode_datagram_frame(&dest->datagram, payload, payloadlen); default: - if (has_mask(type, NGTCP2_FRAME_STREAM)) { + if ((type & ~(NGTCP2_FRAME_STREAM - 1)) == NGTCP2_FRAME_STREAM) { return ngtcp2_pkt_decode_stream_frame(&dest->stream, payload, payloadlen); } + + /* For frame types > 0xff, use ngtcp2_get_uvarintlen and + ngtcp2_get_uvarint to get a frame type, and then switch over + it. Verify that payloadlen >= ngtcp2_get_uvarintlen(payload) + before calling ngtcp2_get_uvarint(payload). */ + return NGTCP2_ERR_FRAME_ENCODING; } } @@ -557,7 +558,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest, uint8_t type; size_t len = 1 + 1; const uint8_t *p; - size_t datalen; + size_t datalen = 0; size_t ndatalen = 0; size_t n; uint64_t vi; @@ -570,7 +571,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -585,7 +586,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest, return NGTCP2_ERR_FRAME_ENCODING; } - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -601,14 +602,14 @@ ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest, return NGTCP2_ERR_FRAME_ENCODING; } - ndatalen = ngtcp2_get_varint_len(p); + ndatalen = ngtcp2_get_uvarintlen(p); len += ndatalen - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } - vi = ngtcp2_get_varint(&ndatalen, p); + /* p = */ ngtcp2_get_uvarint(&vi, p); if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -623,12 +624,10 @@ ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest, dest->type = NGTCP2_FRAME_STREAM; dest->flags = (uint8_t)(type & ~NGTCP2_FRAME_STREAM); dest->fin = (type & NGTCP2_STREAM_FIN_BIT) != 0; - dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_varint(&dest->stream_id, p); if (type & NGTCP2_STREAM_OFF_BIT) { - dest->offset = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_uvarint(&dest->offset, p); } else { dest->offset = 0; } @@ -656,12 +655,12 @@ ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest, ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, const uint8_t *payload, size_t payloadlen) { - size_t num_blks, max_num_blks; - size_t nnum_blks; + size_t rangecnt, max_rangecnt; + size_t nrangecnt; size_t len = 1 + 1 + 1 + 1 + 1; const uint8_t *p; size_t i, j; - ngtcp2_ack_blk *blk; + ngtcp2_ack_range *range; size_t n; uint8_t type; uint64_t vi; @@ -675,7 +674,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, p = payload + 1; /* Largest Acknowledged */ - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -685,7 +684,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, p += n; /* ACK Delay */ - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -694,26 +693,24 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, p += n; - /* ACK Block Count */ - nnum_blks = ngtcp2_get_varint_len(p); - len += nnum_blks - 1; + /* ACK Range Count */ + nrangecnt = ngtcp2_get_uvarintlen(p); + len += nrangecnt - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } - vi = ngtcp2_get_varint(&nnum_blks, p); + p = ngtcp2_get_uvarint(&vi, p); if (vi > SIZE_MAX / (1 + 1) || payloadlen - len < vi * (1 + 1)) { return NGTCP2_ERR_FRAME_ENCODING; } - num_blks = (size_t)vi; - len += num_blks * (1 + 1); - - p += nnum_blks; + rangecnt = (size_t)vi; + len += rangecnt * (1 + 1); - /* First ACK Block */ - n = ngtcp2_get_varint_len(p); + /* First ACK Range */ + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -722,10 +719,10 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, p += n; - for (i = 0; i < num_blks; ++i) { - /* Gap, and Additional ACK Block */ + for (i = 0; i < rangecnt; ++i) { + /* Gap, and Additional ACK Range */ for (j = 0; j < 2; ++j) { - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -743,7 +740,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, } for (i = 0; i < 3; ++i) { - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -754,44 +751,34 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, } } - /* TODO We might not decode all blocks. It could be very large. */ - max_num_blks = ngtcp2_min(NGTCP2_MAX_ACK_BLKS, num_blks); + /* TODO We might not decode all ranges. It could be very large. */ + max_rangecnt = ngtcp2_min(NGTCP2_MAX_ACK_RANGES, rangecnt); p = payload + 1; dest->type = type; - dest->largest_ack = (int64_t)ngtcp2_get_varint(&n, p); - p += n; - dest->ack_delay = ngtcp2_get_varint(&n, p); + p = ngtcp2_get_varint(&dest->largest_ack, p); + p = ngtcp2_get_uvarint(&dest->ack_delay, p); /* This value will be assigned in the upper layer. */ dest->ack_delay_unscaled = 0; - p += n; - dest->num_blks = max_num_blks; - p += nnum_blks; - dest->first_ack_blklen = ngtcp2_get_varint(&n, p); - p += n; + dest->rangecnt = max_rangecnt; + p += nrangecnt; + p = ngtcp2_get_uvarint(&dest->first_ack_range, p); - for (i = 0; i < max_num_blks; ++i) { - blk = &dest->blks[i]; - blk->gap = ngtcp2_get_varint(&n, p); - p += n; - blk->blklen = ngtcp2_get_varint(&n, p); - p += n; + for (i = 0; i < max_rangecnt; ++i) { + range = &dest->ranges[i]; + p = ngtcp2_get_uvarint(&range->gap, p); + p = ngtcp2_get_uvarint(&range->len, p); } - for (i = max_num_blks; i < num_blks; ++i) { - p += ngtcp2_get_varint_len(p); - p += ngtcp2_get_varint_len(p); + for (i = max_rangecnt; i < rangecnt; ++i) { + p += ngtcp2_get_uvarintlen(p); + p += ngtcp2_get_uvarintlen(p); } if (type == NGTCP2_FRAME_ACK_ECN) { - dest->ecn.ect0 = ngtcp2_get_varint(&n, p); - p += n; - - dest->ecn.ect1 = ngtcp2_get_varint(&n, p); - p += n; - - dest->ecn.ce = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_uvarint(&dest->ecn.ect0, p); + p = ngtcp2_get_uvarint(&dest->ecn.ect1, p); + p = ngtcp2_get_uvarint(&dest->ecn.ce, p); } assert((size_t)(p - payload) == len); @@ -799,9 +786,9 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, return (ngtcp2_ssize)len; } -size_t ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest, - const uint8_t *payload, - size_t payloadlen) { +ngtcp2_ssize ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest, + const uint8_t *payload, + size_t payloadlen) { const uint8_t *p, *ep; assert(payloadlen > 0); @@ -815,7 +802,7 @@ size_t ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest, dest->type = NGTCP2_FRAME_PADDING; dest->len = (size_t)(p - payload); - return dest->len; + return (ngtcp2_ssize)dest->len; } ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest, @@ -831,19 +818,19 @@ ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } p += n; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } p += n; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; @@ -852,12 +839,9 @@ ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest, p = payload + 1; dest->type = NGTCP2_FRAME_RESET_STREAM; - dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p); - p += n; - dest->app_error_code = ngtcp2_get_varint(&n, p); - p += n; - dest->final_size = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_varint(&dest->stream_id, p); + p = ngtcp2_get_uvarint(&dest->app_error_code, p); + p = ngtcp2_get_uvarint(&dest->final_size, p); assert((size_t)(p - payload) == len); @@ -882,7 +866,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; @@ -893,7 +877,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( if (type == NGTCP2_FRAME_CONNECTION_CLOSE) { ++len; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; @@ -902,13 +886,13 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( p += n; } - nreasonlen = ngtcp2_get_varint_len(p); + nreasonlen = ngtcp2_get_uvarintlen(p); len += nreasonlen - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } - vi = ngtcp2_get_varint(&nreasonlen, p); + p = ngtcp2_get_uvarint(&vi, p); if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -918,11 +902,9 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( p = payload + 1; dest->type = type; - dest->error_code = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_uvarint(&dest->error_code, p); if (type == NGTCP2_FRAME_CONNECTION_CLOSE) { - dest->frame_type = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_uvarint(&dest->frame_type, p); } else { dest->frame_type = 0; } @@ -953,7 +935,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -961,8 +943,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data *dest, } dest->type = NGTCP2_FRAME_MAX_DATA; - dest->max_data = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_uvarint(&dest->max_data, p); assert((size_t)(p - payload) == len); @@ -981,7 +962,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_stream_data_frame( p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -990,7 +971,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_stream_data_frame( p += n; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -1000,10 +981,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_stream_data_frame( p = payload + 1; dest->type = NGTCP2_FRAME_MAX_STREAM_DATA; - dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p); - p += n; - dest->max_stream_data = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_varint(&dest->stream_id, p); + p = ngtcp2_get_uvarint(&dest->max_stream_data, p); assert((size_t)(p - payload) == len); @@ -1023,7 +1002,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_streams_frame(ngtcp2_max_streams *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -1031,8 +1010,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_streams_frame(ngtcp2_max_streams *dest, } dest->type = payload[0]; - dest->max_streams = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_uvarint(&dest->max_streams, p); assert((size_t)(p - payload) == len); @@ -1062,7 +1040,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -1070,8 +1048,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked *dest, } dest->type = NGTCP2_FRAME_DATA_BLOCKED; - dest->offset = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_uvarint(&dest->offset, p); assert((size_t)(p - payload) == len); @@ -1092,7 +1069,7 @@ ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -1101,7 +1078,7 @@ ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest, p += n; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -1111,10 +1088,8 @@ ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest, p = payload + 1; dest->type = NGTCP2_FRAME_STREAM_DATA_BLOCKED; - dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p); - p += n; - dest->offset = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_varint(&dest->stream_id, p); + p = ngtcp2_get_uvarint(&dest->offset, p); assert((size_t)(p - payload) == len); @@ -1133,7 +1108,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame( p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -1141,8 +1116,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame( } dest->type = payload[0]; - dest->max_streams = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_uvarint(&dest->max_streams, p); assert((size_t)(p - payload) == len); @@ -1162,7 +1136,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame( p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; @@ -1170,7 +1144,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame( p += n; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; @@ -1191,14 +1165,13 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame( p = payload + 1; dest->type = NGTCP2_FRAME_NEW_CONNECTION_ID; - dest->seq = ngtcp2_get_varint(&n, p); - p += n; - dest->retire_prior_to = ngtcp2_get_varint(&n, p); - p += n + 1; + p = ngtcp2_get_uvarint(&dest->seq, p); + p = ngtcp2_get_uvarint(&dest->retire_prior_to, p); + ++p; ngtcp2_cid_init(&dest->cid, p, cil); p += cil; - memcpy(dest->stateless_reset_token, p, NGTCP2_STATELESS_RESET_TOKENLEN); - p += NGTCP2_STATELESS_RESET_TOKENLEN; + p = ngtcp2_get_bytes(dest->stateless_reset_token, p, + NGTCP2_STATELESS_RESET_TOKENLEN); assert((size_t)(p - payload) == len); @@ -1218,14 +1191,14 @@ ngtcp2_ssize ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } p += n; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -1235,10 +1208,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending *dest, p = payload + 1; dest->type = NGTCP2_FRAME_STOP_SENDING; - dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p); - p += n; - dest->app_error_code = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_varint(&dest->stream_id, p); + p = ngtcp2_get_uvarint(&dest->app_error_code, p); assert((size_t)(p - payload) == len); @@ -1287,7 +1258,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_path_response_frame(ngtcp2_path_response *dest, return (ngtcp2_ssize)len; } -ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest, +ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_stream *dest, const uint8_t *payload, size_t payloadlen) { size_t len = 1 + 1 + 1; @@ -1303,7 +1274,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -1312,14 +1283,14 @@ ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest, p += n; - ndatalen = ngtcp2_get_varint_len(p); + ndatalen = ngtcp2_get_uvarintlen(p); len += ndatalen - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } - vi = ngtcp2_get_varint(&ndatalen, p); + p = ngtcp2_get_uvarint(&vi, p); if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -1330,8 +1301,10 @@ ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest, p = payload + 1; dest->type = NGTCP2_FRAME_CRYPTO; - dest->offset = ngtcp2_get_varint(&n, p); - p += n; + dest->flags = 0; + dest->fin = 0; + dest->stream_id = 0; + p = ngtcp2_get_uvarint(&dest->offset, p); dest->data[0].len = datalen; p += ndatalen; if (dest->data[0].len) { @@ -1363,14 +1336,14 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } - vi = ngtcp2_get_varint(&n, p); + p = ngtcp2_get_uvarint(&vi, p); if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -1378,10 +1351,9 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest, len += datalen; dest->type = NGTCP2_FRAME_NEW_TOKEN; - dest->token.len = datalen; - p += n; - dest->token.base = (uint8_t *)p; - p += dest->token.len; + dest->tokenlen = datalen; + dest->token = (uint8_t *)p; + p += dest->tokenlen; assert((size_t)(p - payload) == len); @@ -1402,7 +1374,7 @@ ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id *dest, p = payload + 1; - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { @@ -1410,8 +1382,7 @@ ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id *dest, } dest->type = NGTCP2_FRAME_RETIRE_CONNECTION_ID; - dest->seq = ngtcp2_get_varint(&n, p); - p += n; + p = ngtcp2_get_uvarint(&dest->seq, p); assert((size_t)(p - payload) == len); @@ -1457,14 +1428,14 @@ ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest, return NGTCP2_ERR_FRAME_ENCODING; } - n = ngtcp2_get_varint_len(p); + n = ngtcp2_get_uvarintlen(p); len += n - 1; if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } - vi = ngtcp2_get_varint(&n, p); + p = ngtcp2_get_uvarint(&vi, p); if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -1473,8 +1444,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest, len += datalen; break; default: - assert(0); - abort(); + ngtcp2_unreachable(); } dest->type = type; @@ -1482,19 +1452,11 @@ ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest, if (datalen == 0) { dest->datacnt = 0; dest->data = NULL; - - if (type == NGTCP2_FRAME_DATAGRAM_LEN) { - p += n; - } } else { dest->datacnt = 1; dest->data = dest->rdata; dest->rdata[0].len = datalen; - if (type == NGTCP2_FRAME_DATAGRAM_LEN) { - p += n; - } - dest->rdata[0].base = (uint8_t *)p; p += datalen; } @@ -1551,7 +1513,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen, return ngtcp2_pkt_encode_path_response_frame(out, outlen, &fr->path_response); case NGTCP2_FRAME_CRYPTO: - return ngtcp2_pkt_encode_crypto_frame(out, outlen, &fr->crypto); + return ngtcp2_pkt_encode_crypto_frame(out, outlen, &fr->stream); case NGTCP2_FRAME_NEW_TOKEN: return ngtcp2_pkt_encode_new_token_frame(out, outlen, &fr->new_token); case NGTCP2_FRAME_RETIRE_CONNECTION_ID: @@ -1582,16 +1544,16 @@ ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen, if (fr->offset) { flags |= NGTCP2_STREAM_OFF_BIT; - len += ngtcp2_put_varint_len(fr->offset); + len += ngtcp2_put_uvarintlen(fr->offset); } - len += ngtcp2_put_varint_len((uint64_t)fr->stream_id); + len += ngtcp2_put_uvarintlen((uint64_t)fr->stream_id); for (i = 0; i < fr->datacnt; ++i) { datalen += fr->data[i].len; } - len += ngtcp2_put_varint_len(datalen); + len += ngtcp2_put_uvarintlen(datalen); len += datalen; if (outlen < len) { @@ -1604,13 +1566,13 @@ ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen, fr->flags = flags; - p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id); + p = ngtcp2_put_uvarint(p, (uint64_t)fr->stream_id); if (fr->offset) { - p = ngtcp2_put_varint(p, fr->offset); + p = ngtcp2_put_uvarint(p, fr->offset); } - p = ngtcp2_put_varint(p, datalen); + p = ngtcp2_put_uvarint(p, datalen); for (i = 0; i < fr->datacnt; ++i) { assert(fr->data[i].len); @@ -1625,24 +1587,24 @@ ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_ack_frame(uint8_t *out, size_t outlen, ngtcp2_ack *fr) { - size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->largest_ack) + - ngtcp2_put_varint_len(fr->ack_delay) + - ngtcp2_put_varint_len(fr->num_blks) + - ngtcp2_put_varint_len(fr->first_ack_blklen); + size_t len = 1 + ngtcp2_put_uvarintlen((uint64_t)fr->largest_ack) + + ngtcp2_put_uvarintlen(fr->ack_delay) + + ngtcp2_put_uvarintlen(fr->rangecnt) + + ngtcp2_put_uvarintlen(fr->first_ack_range); uint8_t *p; size_t i; - const ngtcp2_ack_blk *blk; + const ngtcp2_ack_range *range; - for (i = 0; i < fr->num_blks; ++i) { - blk = &fr->blks[i]; - len += ngtcp2_put_varint_len(blk->gap); - len += ngtcp2_put_varint_len(blk->blklen); + for (i = 0; i < fr->rangecnt; ++i) { + range = &fr->ranges[i]; + len += ngtcp2_put_uvarintlen(range->gap); + len += ngtcp2_put_uvarintlen(range->len); } if (fr->type == NGTCP2_FRAME_ACK_ECN) { - len += ngtcp2_put_varint_len(fr->ecn.ect0) + - ngtcp2_put_varint_len(fr->ecn.ect1) + - ngtcp2_put_varint_len(fr->ecn.ce); + len += ngtcp2_put_uvarintlen(fr->ecn.ect0) + + ngtcp2_put_uvarintlen(fr->ecn.ect1) + + ngtcp2_put_uvarintlen(fr->ecn.ce); } if (outlen < len) { @@ -1651,22 +1613,22 @@ ngtcp2_ssize ngtcp2_pkt_encode_ack_frame(uint8_t *out, size_t outlen, p = out; - *p++ = fr->type; - p = ngtcp2_put_varint(p, (uint64_t)fr->largest_ack); - p = ngtcp2_put_varint(p, fr->ack_delay); - p = ngtcp2_put_varint(p, fr->num_blks); - p = ngtcp2_put_varint(p, fr->first_ack_blklen); + *p++ = (uint8_t)fr->type; + p = ngtcp2_put_uvarint(p, (uint64_t)fr->largest_ack); + p = ngtcp2_put_uvarint(p, fr->ack_delay); + p = ngtcp2_put_uvarint(p, fr->rangecnt); + p = ngtcp2_put_uvarint(p, fr->first_ack_range); - for (i = 0; i < fr->num_blks; ++i) { - blk = &fr->blks[i]; - p = ngtcp2_put_varint(p, blk->gap); - p = ngtcp2_put_varint(p, blk->blklen); + for (i = 0; i < fr->rangecnt; ++i) { + range = &fr->ranges[i]; + p = ngtcp2_put_uvarint(p, range->gap); + p = ngtcp2_put_uvarint(p, range->len); } if (fr->type == NGTCP2_FRAME_ACK_ECN) { - p = ngtcp2_put_varint(p, fr->ecn.ect0); - p = ngtcp2_put_varint(p, fr->ecn.ect1); - p = ngtcp2_put_varint(p, fr->ecn.ce); + p = ngtcp2_put_uvarint(p, fr->ecn.ect0); + p = ngtcp2_put_uvarint(p, fr->ecn.ect1); + p = ngtcp2_put_uvarint(p, fr->ecn.ce); } assert((size_t)(p - out) == len); @@ -1688,9 +1650,9 @@ ngtcp2_ssize ngtcp2_pkt_encode_padding_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen, const ngtcp2_reset_stream *fr) { - size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) + - ngtcp2_put_varint_len(fr->app_error_code) + - ngtcp2_put_varint_len(fr->final_size); + size_t len = 1 + ngtcp2_put_uvarintlen((uint64_t)fr->stream_id) + + ngtcp2_put_uvarintlen(fr->app_error_code) + + ngtcp2_put_uvarintlen(fr->final_size); uint8_t *p; if (outlen < len) { @@ -1700,9 +1662,9 @@ ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen, p = out; *p++ = NGTCP2_FRAME_RESET_STREAM; - p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id); - p = ngtcp2_put_varint(p, fr->app_error_code); - p = ngtcp2_put_varint(p, fr->final_size); + p = ngtcp2_put_uvarint(p, (uint64_t)fr->stream_id); + p = ngtcp2_put_uvarint(p, fr->app_error_code); + p = ngtcp2_put_uvarint(p, fr->final_size); assert((size_t)(p - out) == len); @@ -1712,11 +1674,11 @@ ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen, const ngtcp2_connection_close *fr) { - size_t len = 1 + ngtcp2_put_varint_len(fr->error_code) + + size_t len = 1 + ngtcp2_put_uvarintlen(fr->error_code) + (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE - ? ngtcp2_put_varint_len(fr->frame_type) + ? ngtcp2_put_uvarintlen(fr->frame_type) : 0) + - ngtcp2_put_varint_len(fr->reasonlen) + fr->reasonlen; + ngtcp2_put_uvarintlen(fr->reasonlen) + fr->reasonlen; uint8_t *p; if (outlen < len) { @@ -1725,12 +1687,12 @@ ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen, p = out; - *p++ = fr->type; - p = ngtcp2_put_varint(p, fr->error_code); + *p++ = (uint8_t)fr->type; + p = ngtcp2_put_uvarint(p, fr->error_code); if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) { - p = ngtcp2_put_varint(p, fr->frame_type); + p = ngtcp2_put_uvarint(p, fr->frame_type); } - p = ngtcp2_put_varint(p, fr->reasonlen); + p = ngtcp2_put_uvarint(p, fr->reasonlen); if (fr->reasonlen) { p = ngtcp2_cpymem(p, fr->reason, fr->reasonlen); } @@ -1742,7 +1704,7 @@ ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_max_data_frame(uint8_t *out, size_t outlen, const ngtcp2_max_data *fr) { - size_t len = 1 + ngtcp2_put_varint_len(fr->max_data); + size_t len = 1 + ngtcp2_put_uvarintlen(fr->max_data); uint8_t *p; if (outlen < len) { @@ -1752,7 +1714,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_max_data_frame(uint8_t *out, size_t outlen, p = out; *p++ = NGTCP2_FRAME_MAX_DATA; - p = ngtcp2_put_varint(p, fr->max_data); + p = ngtcp2_put_uvarint(p, fr->max_data); assert((size_t)(p - out) == len); @@ -1762,8 +1724,8 @@ ngtcp2_ssize ngtcp2_pkt_encode_max_data_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_max_stream_data_frame(uint8_t *out, size_t outlen, const ngtcp2_max_stream_data *fr) { - size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) + - ngtcp2_put_varint_len(fr->max_stream_data); + size_t len = 1 + ngtcp2_put_uvarintlen((uint64_t)fr->stream_id) + + ngtcp2_put_uvarintlen(fr->max_stream_data); uint8_t *p; if (outlen < len) { @@ -1773,8 +1735,8 @@ ngtcp2_pkt_encode_max_stream_data_frame(uint8_t *out, size_t outlen, p = out; *p++ = NGTCP2_FRAME_MAX_STREAM_DATA; - p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id); - p = ngtcp2_put_varint(p, fr->max_stream_data); + p = ngtcp2_put_uvarint(p, (uint64_t)fr->stream_id); + p = ngtcp2_put_uvarint(p, fr->max_stream_data); assert((size_t)(p - out) == len); @@ -1783,7 +1745,7 @@ ngtcp2_pkt_encode_max_stream_data_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_max_streams_frame(uint8_t *out, size_t outlen, const ngtcp2_max_streams *fr) { - size_t len = 1 + ngtcp2_put_varint_len(fr->max_streams); + size_t len = 1 + ngtcp2_put_uvarintlen(fr->max_streams); uint8_t *p; if (outlen < len) { @@ -1792,8 +1754,8 @@ ngtcp2_ssize ngtcp2_pkt_encode_max_streams_frame(uint8_t *out, size_t outlen, p = out; - *p++ = fr->type; - p = ngtcp2_put_varint(p, fr->max_streams); + *p++ = (uint8_t)fr->type; + p = ngtcp2_put_uvarint(p, fr->max_streams); assert((size_t)(p - out) == len); @@ -1816,7 +1778,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_ping_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_data_blocked_frame(uint8_t *out, size_t outlen, const ngtcp2_data_blocked *fr) { - size_t len = 1 + ngtcp2_put_varint_len(fr->offset); + size_t len = 1 + ngtcp2_put_uvarintlen(fr->offset); uint8_t *p; if (outlen < len) { @@ -1826,7 +1788,7 @@ ngtcp2_pkt_encode_data_blocked_frame(uint8_t *out, size_t outlen, p = out; *p++ = NGTCP2_FRAME_DATA_BLOCKED; - p = ngtcp2_put_varint(p, fr->offset); + p = ngtcp2_put_uvarint(p, fr->offset); assert((size_t)(p - out) == len); @@ -1835,8 +1797,8 @@ ngtcp2_pkt_encode_data_blocked_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_stream_data_blocked_frame( uint8_t *out, size_t outlen, const ngtcp2_stream_data_blocked *fr) { - size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) + - ngtcp2_put_varint_len(fr->offset); + size_t len = 1 + ngtcp2_put_uvarintlen((uint64_t)fr->stream_id) + + ngtcp2_put_uvarintlen(fr->offset); uint8_t *p; if (outlen < len) { @@ -1846,8 +1808,8 @@ ngtcp2_ssize ngtcp2_pkt_encode_stream_data_blocked_frame( p = out; *p++ = NGTCP2_FRAME_STREAM_DATA_BLOCKED; - p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id); - p = ngtcp2_put_varint(p, fr->offset); + p = ngtcp2_put_uvarint(p, (uint64_t)fr->stream_id); + p = ngtcp2_put_uvarint(p, fr->offset); assert((size_t)(p - out) == len); @@ -1857,7 +1819,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_stream_data_blocked_frame( ngtcp2_ssize ngtcp2_pkt_encode_streams_blocked_frame(uint8_t *out, size_t outlen, const ngtcp2_streams_blocked *fr) { - size_t len = 1 + ngtcp2_put_varint_len(fr->max_streams); + size_t len = 1 + ngtcp2_put_uvarintlen(fr->max_streams); uint8_t *p; if (outlen < len) { @@ -1866,8 +1828,8 @@ ngtcp2_pkt_encode_streams_blocked_frame(uint8_t *out, size_t outlen, p = out; - *p++ = fr->type; - p = ngtcp2_put_varint(p, fr->max_streams); + *p++ = (uint8_t)fr->type; + p = ngtcp2_put_uvarint(p, fr->max_streams); assert((size_t)(p - out) == len); @@ -1877,8 +1839,8 @@ ngtcp2_pkt_encode_streams_blocked_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_new_connection_id_frame(uint8_t *out, size_t outlen, const ngtcp2_new_connection_id *fr) { - size_t len = 1 + ngtcp2_put_varint_len(fr->seq) + - ngtcp2_put_varint_len(fr->retire_prior_to) + 1 + + size_t len = 1 + ngtcp2_put_uvarintlen(fr->seq) + + ngtcp2_put_uvarintlen(fr->retire_prior_to) + 1 + fr->cid.datalen + NGTCP2_STATELESS_RESET_TOKENLEN; uint8_t *p; @@ -1889,8 +1851,8 @@ ngtcp2_pkt_encode_new_connection_id_frame(uint8_t *out, size_t outlen, p = out; *p++ = NGTCP2_FRAME_NEW_CONNECTION_ID; - p = ngtcp2_put_varint(p, fr->seq); - p = ngtcp2_put_varint(p, fr->retire_prior_to); + p = ngtcp2_put_uvarint(p, fr->seq); + p = ngtcp2_put_uvarint(p, fr->retire_prior_to); *p++ = (uint8_t)fr->cid.datalen; p = ngtcp2_cpymem(p, fr->cid.data, fr->cid.datalen); p = ngtcp2_cpymem(p, fr->stateless_reset_token, @@ -1904,8 +1866,8 @@ ngtcp2_pkt_encode_new_connection_id_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_stop_sending_frame(uint8_t *out, size_t outlen, const ngtcp2_stop_sending *fr) { - size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) + - ngtcp2_put_varint_len(fr->app_error_code); + size_t len = 1 + ngtcp2_put_uvarintlen((uint64_t)fr->stream_id) + + ngtcp2_put_uvarintlen(fr->app_error_code); uint8_t *p; if (outlen < len) { @@ -1915,8 +1877,8 @@ ngtcp2_pkt_encode_stop_sending_frame(uint8_t *out, size_t outlen, p = out; *p++ = NGTCP2_FRAME_STOP_SENDING; - p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id); - p = ngtcp2_put_varint(p, fr->app_error_code); + p = ngtcp2_put_uvarint(p, (uint64_t)fr->stream_id); + p = ngtcp2_put_uvarint(p, fr->app_error_code); assert((size_t)(p - out) == len); @@ -1964,19 +1926,19 @@ ngtcp2_pkt_encode_path_response_frame(uint8_t *out, size_t outlen, } ngtcp2_ssize ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen, - const ngtcp2_crypto *fr) { + const ngtcp2_stream *fr) { size_t len = 1; uint8_t *p; size_t i; size_t datalen = 0; - len += ngtcp2_put_varint_len(fr->offset); + len += ngtcp2_put_uvarintlen(fr->offset); for (i = 0; i < fr->datacnt; ++i) { datalen += fr->data[i].len; } - len += ngtcp2_put_varint_len(datalen); + len += ngtcp2_put_uvarintlen(datalen); len += datalen; if (outlen < len) { @@ -1987,8 +1949,8 @@ ngtcp2_ssize ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen, *p++ = NGTCP2_FRAME_CRYPTO; - p = ngtcp2_put_varint(p, fr->offset); - p = ngtcp2_put_varint(p, datalen); + p = ngtcp2_put_uvarint(p, fr->offset); + p = ngtcp2_put_uvarint(p, datalen); for (i = 0; i < fr->datacnt; ++i) { assert(fr->data[i].base); @@ -2002,10 +1964,10 @@ ngtcp2_ssize ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen, const ngtcp2_new_token *fr) { - size_t len = 1 + ngtcp2_put_varint_len(fr->token.len) + fr->token.len; + size_t len = 1 + ngtcp2_put_uvarintlen(fr->tokenlen) + fr->tokenlen; uint8_t *p; - assert(fr->token.len); + assert(fr->tokenlen); if (outlen < len) { return NGTCP2_ERR_NOBUF; @@ -2015,8 +1977,8 @@ ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen, *p++ = NGTCP2_FRAME_NEW_TOKEN; - p = ngtcp2_put_varint(p, fr->token.len); - p = ngtcp2_cpymem(p, fr->token.base, fr->token.len); + p = ngtcp2_put_uvarint(p, fr->tokenlen); + p = ngtcp2_cpymem(p, fr->token, fr->tokenlen); assert((size_t)(p - out) == len); @@ -2025,7 +1987,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_retire_connection_id_frame( uint8_t *out, size_t outlen, const ngtcp2_retire_connection_id *fr) { - size_t len = 1 + ngtcp2_put_varint_len(fr->seq); + size_t len = 1 + ngtcp2_put_uvarintlen(fr->seq); uint8_t *p; if (outlen < len) { @@ -2036,7 +1998,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_retire_connection_id_frame( *p++ = NGTCP2_FRAME_RETIRE_CONNECTION_ID; - p = ngtcp2_put_varint(p, fr->seq); + p = ngtcp2_put_uvarint(p, fr->seq); assert((size_t)(p - out) == len); @@ -2062,7 +2024,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_datagram_frame(uint8_t *out, size_t outlen, uint64_t datalen = ngtcp2_vec_len(fr->data, fr->datacnt); uint64_t len = 1 + - (fr->type == NGTCP2_FRAME_DATAGRAM ? 0 : ngtcp2_put_varint_len(datalen)) + + (fr->type == NGTCP2_FRAME_DATAGRAM ? 0 : ngtcp2_put_uvarintlen(datalen)) + datalen; uint8_t *p; size_t i; @@ -2076,9 +2038,9 @@ ngtcp2_ssize ngtcp2_pkt_encode_datagram_frame(uint8_t *out, size_t outlen, p = out; - *p++ = fr->type; + *p++ = (uint8_t)fr->type; if (fr->type == NGTCP2_FRAME_DATAGRAM_LEN) { - p = ngtcp2_put_varint(p, datalen); + p = ngtcp2_put_uvarint(p, datalen); } for (i = 0; i < fr->datacnt; ++i) { @@ -2109,7 +2071,7 @@ ngtcp2_ssize ngtcp2_pkt_write_version_negotiation( p = dest; - *p++ = 0x80 | unused_random; + *p++ = 0xc0 | unused_random; p = ngtcp2_put_uint32be(p, 0); *p++ = (uint8_t)dcidlen; if (dcidlen) { @@ -2136,8 +2098,8 @@ size_t ngtcp2_pkt_decode_version_negotiation(uint32_t *dest, assert((payloadlen % sizeof(uint32_t)) == 0); - for (; payload != end; payload += sizeof(uint32_t)) { - *dest++ = ngtcp2_get_uint32(payload); + for (; payload != end;) { + payload = ngtcp2_get_uint32(dest++, payload); } return payloadlen / sizeof(uint32_t); @@ -2169,17 +2131,17 @@ int ngtcp2_pkt_decode_retry(ngtcp2_pkt_retry *dest, const uint8_t *payload, return NGTCP2_ERR_INVALID_ARGUMENT; } - dest->token.base = (uint8_t *)payload; - dest->token.len = (size_t)(payloadlen - NGTCP2_RETRY_TAGLEN); - ngtcp2_cpymem(dest->tag, payload + dest->token.len, NGTCP2_RETRY_TAGLEN); + dest->token = (uint8_t *)payload; + dest->tokenlen = (size_t)(payloadlen - NGTCP2_RETRY_TAGLEN); + ngtcp2_cpymem(dest->tag, payload + dest->tokenlen, NGTCP2_RETRY_TAGLEN); return 0; } int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num, - size_t n) { + size_t pkt_numlen) { int64_t expected = max_pkt_num + 1; - int64_t win = (int64_t)1 << n; + int64_t win = (int64_t)1 << (pkt_numlen * 8); int64_t hwin = win / 2; int64_t mask = win - 1; int64_t cand = (expected & ~mask) | pkt_num; @@ -2194,28 +2156,36 @@ int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num, return cand; } -int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr) { +int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr, int64_t min_pkt_num) { int64_t largest_ack = fr->largest_ack; size_t i; - if (largest_ack < (int64_t)fr->first_ack_blklen) { + if (largest_ack < (int64_t)fr->first_ack_range) { return NGTCP2_ERR_ACK_FRAME; } - largest_ack -= (int64_t)fr->first_ack_blklen; + largest_ack -= (int64_t)fr->first_ack_range; + + if (largest_ack < min_pkt_num) { + return NGTCP2_ERR_PROTO; + } - for (i = 0; i < fr->num_blks; ++i) { - if (largest_ack < (int64_t)fr->blks[i].gap + 2) { + for (i = 0; i < fr->rangecnt; ++i) { + if (largest_ack < (int64_t)fr->ranges[i].gap + 2) { return NGTCP2_ERR_ACK_FRAME; } - largest_ack -= (int64_t)fr->blks[i].gap + 2; + largest_ack -= (int64_t)fr->ranges[i].gap + 2; - if (largest_ack < (int64_t)fr->blks[i].blklen) { + if (largest_ack < (int64_t)fr->ranges[i].len) { return NGTCP2_ERR_ACK_FRAME; } - largest_ack -= (int64_t)fr->blks[i].blklen; + largest_ack -= (int64_t)fr->ranges[i].len; + + if (largest_ack < min_pkt_num) { + return NGTCP2_ERR_PROTO; + } } return 0; @@ -2285,16 +2255,14 @@ ngtcp2_ssize ngtcp2_pkt_write_retry( switch (version) { case NGTCP2_PROTO_VER_V1: + default: nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V1; noncelen = sizeof(NGTCP2_RETRY_NONCE_V1) - 1; break; - case NGTCP2_PROTO_VER_V2_DRAFT: - nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V2_DRAFT; - noncelen = sizeof(NGTCP2_RETRY_NONCE_V2_DRAFT) - 1; + case NGTCP2_PROTO_VER_V2: + nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V2; + noncelen = sizeof(NGTCP2_RETRY_NONCE_V2) - 1; break; - default: - nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_DRAFT; - noncelen = sizeof(NGTCP2_RETRY_NONCE_DRAFT) - 1; } /* OpenSSL does not like NULL plaintext. */ @@ -2377,16 +2345,14 @@ int ngtcp2_pkt_verify_retry_tag(uint32_t version, const ngtcp2_pkt_retry *retry, switch (version) { case NGTCP2_PROTO_VER_V1: + default: nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V1; noncelen = sizeof(NGTCP2_RETRY_NONCE_V1) - 1; break; - case NGTCP2_PROTO_VER_V2_DRAFT: - nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V2_DRAFT; - noncelen = sizeof(NGTCP2_RETRY_NONCE_V2_DRAFT) - 1; + case NGTCP2_PROTO_VER_V2: + nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V2; + noncelen = sizeof(NGTCP2_RETRY_NONCE_V2) - 1; break; - default: - nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_DRAFT; - noncelen = sizeof(NGTCP2_RETRY_NONCE_DRAFT) - 1; } /* OpenSSL does not like NULL plaintext. */ @@ -2405,8 +2371,8 @@ int ngtcp2_pkt_verify_retry_tag(uint32_t version, const ngtcp2_pkt_retry *retry, size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset, uint64_t len, size_t left) { - size_t n = 1 /* type */ + ngtcp2_put_varint_len((uint64_t)stream_id) + - (offset ? ngtcp2_put_varint_len(offset) : 0); + size_t n = 1 /* type */ + ngtcp2_put_uvarintlen((uint64_t)stream_id) + + (offset ? ngtcp2_put_uvarintlen(offset) : 0); if (left <= n) { return (size_t)-1; @@ -2436,7 +2402,7 @@ size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset, } size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) { - size_t n = 1 /* type */ + ngtcp2_put_varint_len(offset); + size_t n = 1 /* type */ + ngtcp2_put_uvarintlen(offset); /* CRYPTO frame must contain nonzero length data. Return -1 if there is no space to write crypto data. */ @@ -2468,17 +2434,16 @@ size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) { } size_t ngtcp2_pkt_datagram_framelen(size_t len) { - return 1 /* type */ + ngtcp2_put_varint_len(len) + len; + return 1 /* type */ + ngtcp2_put_uvarintlen(len) + len; } int ngtcp2_is_supported_version(uint32_t version) { switch (version) { case NGTCP2_PROTO_VER_V1: - case NGTCP2_PROTO_VER_V2_DRAFT: + case NGTCP2_PROTO_VER_V2: return 1; default: - return NGTCP2_PROTO_VER_DRAFT_MIN <= version && - version <= NGTCP2_PROTO_VER_DRAFT_MAX; + return 0; } } @@ -2491,15 +2456,15 @@ uint8_t ngtcp2_pkt_get_type_long(uint32_t version, uint8_t c) { uint8_t pkt_type = (uint8_t)((c & NGTCP2_LONG_TYPE_MASK) >> 4); switch (version) { - case NGTCP2_PROTO_VER_V2_DRAFT: + case NGTCP2_PROTO_VER_V2: switch (pkt_type) { - case NGTCP2_PKT_TYPE_INITIAL_V2_DRAFT: + case NGTCP2_PKT_TYPE_INITIAL_V2: return NGTCP2_PKT_INITIAL; - case NGTCP2_PKT_TYPE_0RTT_V2_DRAFT: + case NGTCP2_PKT_TYPE_0RTT_V2: return NGTCP2_PKT_0RTT; - case NGTCP2_PKT_TYPE_HANDSHAKE_V2_DRAFT: + case NGTCP2_PKT_TYPE_HANDSHAKE_V2: return NGTCP2_PKT_HANDSHAKE; - case NGTCP2_PKT_TYPE_RETRY_V2_DRAFT: + case NGTCP2_PKT_TYPE_RETRY_V2: return NGTCP2_PKT_RETRY; default: return 0; @@ -2509,8 +2474,6 @@ uint8_t ngtcp2_pkt_get_type_long(uint32_t version, uint8_t c) { return 0; } - /* QUIC v1 and draft versions share the same numeric packet - types. */ switch (pkt_type) { case NGTCP2_PKT_TYPE_INITIAL_V1: return NGTCP2_PKT_INITIAL; @@ -2528,27 +2491,24 @@ uint8_t ngtcp2_pkt_get_type_long(uint32_t version, uint8_t c) { uint8_t ngtcp2_pkt_versioned_type(uint32_t version, uint32_t pkt_type) { switch (version) { - case NGTCP2_PROTO_VER_V2_DRAFT: + case NGTCP2_PROTO_VER_V2: switch (pkt_type) { case NGTCP2_PKT_INITIAL: - return NGTCP2_PKT_TYPE_INITIAL_V2_DRAFT; + return NGTCP2_PKT_TYPE_INITIAL_V2; case NGTCP2_PKT_0RTT: - return NGTCP2_PKT_TYPE_0RTT_V2_DRAFT; + return NGTCP2_PKT_TYPE_0RTT_V2; case NGTCP2_PKT_HANDSHAKE: - return NGTCP2_PKT_TYPE_HANDSHAKE_V2_DRAFT; + return NGTCP2_PKT_TYPE_HANDSHAKE_V2; case NGTCP2_PKT_RETRY: - return NGTCP2_PKT_TYPE_RETRY_V2_DRAFT; + return NGTCP2_PKT_TYPE_RETRY_V2; default: - assert(0); - abort(); + ngtcp2_unreachable(); } default: /* Assume that unsupported versions share the numeric long packet types with QUIC v1 in order to send a packet to elicit Version Negotiation packet. */ - /* QUIC v1 and draft versions share the same numeric packet - types. */ switch (pkt_type) { case NGTCP2_PKT_INITIAL: return NGTCP2_PKT_TYPE_INITIAL_V1; @@ -2559,8 +2519,7 @@ uint8_t ngtcp2_pkt_versioned_type(uint32_t version, uint32_t pkt_type) { case NGTCP2_PKT_RETRY: return NGTCP2_PKT_TYPE_RETRY_V1; default: - assert(0); - abort(); + ngtcp2_unreachable(); } } } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h index 2f7838a08a5625..feec4d32c97bdd 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h @@ -88,9 +88,9 @@ client stream ID. */ #define NGTCP2_MAX_CLIENT_STREAM_ID_UNI ((int64_t)0x3ffffffffffffffell) -/* NGTCP2_MAX_NUM_ACK_BLK is the maximum number of Additional ACK - blocks which this library can create, or decode. */ -#define NGTCP2_MAX_ACK_BLKS 32 +/* NGTCP2_MAX_NUM_ACK_RANGES is the maximum number of Additional ACK + ranges which this library can create, or decode. */ +#define NGTCP2_MAX_ACK_RANGES 32 /* NGTCP2_MAX_PKT_NUM is the maximum packet number. */ #define NGTCP2_MAX_PKT_NUM ((int64_t)((1ll << 62) - 1)) @@ -124,62 +124,67 @@ v1. */ #define NGTCP2_PKT_TYPE_RETRY_V1 0x3 -/* NGTCP2_PKT_TYPE_INITIAL_V2_DRAFT is Initial long header packet type - for QUIC v2 draft. */ -#define NGTCP2_PKT_TYPE_INITIAL_V2_DRAFT 0x1 -/* NGTCP2_PKT_TYPE_0RTT_V2_DRAFT is 0RTT long header packet type for - QUIC v2 draft. */ -#define NGTCP2_PKT_TYPE_0RTT_V2_DRAFT 0x2 -/* NGTCP2_PKT_TYPE_HANDSHAKE_V2_DRAFT is Handshake long header packet - type for QUIC v2 draft. */ -#define NGTCP2_PKT_TYPE_HANDSHAKE_V2_DRAFT 0x3 -/* NGTCP2_PKT_TYPE_RETRY_V2_DRAFT is Retry long header packet type for - QUIC v2 draft. */ -#define NGTCP2_PKT_TYPE_RETRY_V2_DRAFT 0x0 +/* NGTCP2_PKT_TYPE_INITIAL_V2 is Initial long header packet type for + QUIC v2. */ +#define NGTCP2_PKT_TYPE_INITIAL_V2 0x1 +/* NGTCP2_PKT_TYPE_0RTT_V2 is 0RTT long header packet type for QUIC + v2. */ +#define NGTCP2_PKT_TYPE_0RTT_V2 0x2 +/* NGTCP2_PKT_TYPE_HANDSHAKE_V2 is Handshake long header packet type + for QUIC v2. */ +#define NGTCP2_PKT_TYPE_HANDSHAKE_V2 0x3 +/* NGTCP2_PKT_TYPE_RETRY_V2 is Retry long header packet type for QUIC + v2. */ +#define NGTCP2_PKT_TYPE_RETRY_V2 0x0 typedef struct ngtcp2_pkt_retry { ngtcp2_cid odcid; - ngtcp2_vec token; + uint8_t *token; + size_t tokenlen; uint8_t tag[NGTCP2_RETRY_TAGLEN]; } ngtcp2_pkt_retry; -typedef enum { - NGTCP2_FRAME_PADDING = 0x00, - NGTCP2_FRAME_PING = 0x01, - NGTCP2_FRAME_ACK = 0x02, - NGTCP2_FRAME_ACK_ECN = 0x03, - NGTCP2_FRAME_RESET_STREAM = 0x04, - NGTCP2_FRAME_STOP_SENDING = 0x05, - NGTCP2_FRAME_CRYPTO = 0x06, - NGTCP2_FRAME_NEW_TOKEN = 0x07, - NGTCP2_FRAME_STREAM = 0x08, - NGTCP2_FRAME_MAX_DATA = 0x10, - NGTCP2_FRAME_MAX_STREAM_DATA = 0x11, - NGTCP2_FRAME_MAX_STREAMS_BIDI = 0x12, - NGTCP2_FRAME_MAX_STREAMS_UNI = 0x13, - NGTCP2_FRAME_DATA_BLOCKED = 0x14, - NGTCP2_FRAME_STREAM_DATA_BLOCKED = 0x15, - NGTCP2_FRAME_STREAMS_BLOCKED_BIDI = 0x16, - NGTCP2_FRAME_STREAMS_BLOCKED_UNI = 0x17, - NGTCP2_FRAME_NEW_CONNECTION_ID = 0x18, - NGTCP2_FRAME_RETIRE_CONNECTION_ID = 0x19, - NGTCP2_FRAME_PATH_CHALLENGE = 0x1a, - NGTCP2_FRAME_PATH_RESPONSE = 0x1b, - NGTCP2_FRAME_CONNECTION_CLOSE = 0x1c, - NGTCP2_FRAME_CONNECTION_CLOSE_APP = 0x1d, - NGTCP2_FRAME_HANDSHAKE_DONE = 0x1e, - NGTCP2_FRAME_DATAGRAM = 0x30, - NGTCP2_FRAME_DATAGRAM_LEN = 0x31, -} ngtcp2_frame_type; - +#define NGTCP2_FRAME_PADDING 0x00 +#define NGTCP2_FRAME_PING 0x01 +#define NGTCP2_FRAME_ACK 0x02 +#define NGTCP2_FRAME_ACK_ECN 0x03 +#define NGTCP2_FRAME_RESET_STREAM 0x04 +#define NGTCP2_FRAME_STOP_SENDING 0x05 +#define NGTCP2_FRAME_CRYPTO 0x06 +#define NGTCP2_FRAME_NEW_TOKEN 0x07 +#define NGTCP2_FRAME_STREAM 0x08 +#define NGTCP2_FRAME_MAX_DATA 0x10 +#define NGTCP2_FRAME_MAX_STREAM_DATA 0x11 +#define NGTCP2_FRAME_MAX_STREAMS_BIDI 0x12 +#define NGTCP2_FRAME_MAX_STREAMS_UNI 0x13 +#define NGTCP2_FRAME_DATA_BLOCKED 0x14 +#define NGTCP2_FRAME_STREAM_DATA_BLOCKED 0x15 +#define NGTCP2_FRAME_STREAMS_BLOCKED_BIDI 0x16 +#define NGTCP2_FRAME_STREAMS_BLOCKED_UNI 0x17 +#define NGTCP2_FRAME_NEW_CONNECTION_ID 0x18 +#define NGTCP2_FRAME_RETIRE_CONNECTION_ID 0x19 +#define NGTCP2_FRAME_PATH_CHALLENGE 0x1a +#define NGTCP2_FRAME_PATH_RESPONSE 0x1b +#define NGTCP2_FRAME_CONNECTION_CLOSE 0x1c +#define NGTCP2_FRAME_CONNECTION_CLOSE_APP 0x1d +#define NGTCP2_FRAME_HANDSHAKE_DONE 0x1e +#define NGTCP2_FRAME_DATAGRAM 0x30 +#define NGTCP2_FRAME_DATAGRAM_LEN 0x31 + +/* ngtcp2_stream represents STREAM and CRYPTO frames. */ typedef struct ngtcp2_stream { - uint8_t type; + uint64_t type; /** * flags of decoded STREAM frame. This gets ignored when encoding - * STREAM frame. + * STREAM frame. CRYPTO frame does not include this field, and must + * set it to 0. */ uint8_t flags; + /* CRYPTO frame does not include this field, and must set it to + 0. */ uint8_t fin; + /* CRYPTO frame does not include this field, and must set it to + 0. */ int64_t stream_id; uint64_t offset; /* datacnt is the number of elements that data contains. Although @@ -190,13 +195,13 @@ typedef struct ngtcp2_stream { ngtcp2_vec data[1]; } ngtcp2_stream; -typedef struct ngtcp2_ack_blk { +typedef struct ngtcp2_ack_range { uint64_t gap; - uint64_t blklen; -} ngtcp2_ack_blk; + uint64_t len; +} ngtcp2_ack_range; typedef struct ngtcp2_ack { - uint8_t type; + uint64_t type; int64_t largest_ack; uint64_t ack_delay; /** @@ -209,13 +214,13 @@ typedef struct ngtcp2_ack { uint64_t ect1; uint64_t ce; } ecn; - uint64_t first_ack_blklen; - size_t num_blks; - ngtcp2_ack_blk blks[1]; + uint64_t first_ack_range; + size_t rangecnt; + ngtcp2_ack_range ranges[1]; } ngtcp2_ack; typedef struct ngtcp2_padding { - uint8_t type; + uint64_t type; /** * The length of contiguous PADDING frames. */ @@ -223,14 +228,14 @@ typedef struct ngtcp2_padding { } ngtcp2_padding; typedef struct ngtcp2_reset_stream { - uint8_t type; + uint64_t type; int64_t stream_id; uint64_t app_error_code; uint64_t final_size; } ngtcp2_reset_stream; typedef struct ngtcp2_connection_close { - uint8_t type; + uint64_t type; uint64_t error_code; uint64_t frame_type; size_t reasonlen; @@ -238,7 +243,7 @@ typedef struct ngtcp2_connection_close { } ngtcp2_connection_close; typedef struct ngtcp2_max_data { - uint8_t type; + uint64_t type; /** * max_data is Maximum Data. */ @@ -246,38 +251,38 @@ typedef struct ngtcp2_max_data { } ngtcp2_max_data; typedef struct ngtcp2_max_stream_data { - uint8_t type; + uint64_t type; int64_t stream_id; uint64_t max_stream_data; } ngtcp2_max_stream_data; typedef struct ngtcp2_max_streams { - uint8_t type; + uint64_t type; uint64_t max_streams; } ngtcp2_max_streams; typedef struct ngtcp2_ping { - uint8_t type; + uint64_t type; } ngtcp2_ping; typedef struct ngtcp2_data_blocked { - uint8_t type; + uint64_t type; uint64_t offset; } ngtcp2_data_blocked; typedef struct ngtcp2_stream_data_blocked { - uint8_t type; + uint64_t type; int64_t stream_id; uint64_t offset; } ngtcp2_stream_data_blocked; typedef struct ngtcp2_streams_blocked { - uint8_t type; + uint64_t type; uint64_t max_streams; } ngtcp2_streams_blocked; typedef struct ngtcp2_new_connection_id { - uint8_t type; + uint64_t type; uint64_t seq; uint64_t retire_prior_to; ngtcp2_cid cid; @@ -285,48 +290,38 @@ typedef struct ngtcp2_new_connection_id { } ngtcp2_new_connection_id; typedef struct ngtcp2_stop_sending { - uint8_t type; + uint64_t type; int64_t stream_id; uint64_t app_error_code; } ngtcp2_stop_sending; typedef struct ngtcp2_path_challenge { - uint8_t type; + uint64_t type; uint8_t data[NGTCP2_PATH_CHALLENGE_DATALEN]; } ngtcp2_path_challenge; typedef struct ngtcp2_path_response { - uint8_t type; + uint64_t type; uint8_t data[NGTCP2_PATH_CHALLENGE_DATALEN]; } ngtcp2_path_response; -typedef struct ngtcp2_crypto { - uint8_t type; - uint64_t offset; - /* datacnt is the number of elements that data contains. Although - the length of data is 1 in this definition, the library may - allocate extra bytes to hold more elements. */ - size_t datacnt; - /* data is the array of ngtcp2_vec which references data. */ - ngtcp2_vec data[1]; -} ngtcp2_crypto; - typedef struct ngtcp2_new_token { - uint8_t type; - ngtcp2_vec token; + uint64_t type; + uint8_t *token; + size_t tokenlen; } ngtcp2_new_token; typedef struct ngtcp2_retire_connection_id { - uint8_t type; + uint64_t type; uint64_t seq; } ngtcp2_retire_connection_id; typedef struct ngtcp2_handshake_done { - uint8_t type; + uint64_t type; } ngtcp2_handshake_done; typedef struct ngtcp2_datagram { - uint8_t type; + uint64_t type; /* dgram_id is an opaque identifier chosen by an application. */ uint64_t dgram_id; /* datacnt is the number of elements that data contains. */ @@ -341,7 +336,7 @@ typedef struct ngtcp2_datagram { } ngtcp2_datagram; typedef union ngtcp2_frame { - uint8_t type; + uint64_t type; ngtcp2_stream stream; ngtcp2_ack ack; ngtcp2_padding padding; @@ -358,7 +353,6 @@ typedef union ngtcp2_frame { ngtcp2_stop_sending stop_sending; ngtcp2_path_challenge path_challenge; ngtcp2_path_response path_response; - ngtcp2_crypto crypto; ngtcp2_new_token new_token; ngtcp2_retire_connection_id retire_connection_id; ngtcp2_handshake_done handshake_done; @@ -454,7 +448,8 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_short(uint8_t *out, size_t outlen, * frame if it succeeds, or one of the following negative error codes: * * :enum:`NGTCP2_ERR_FRAME_ENCODING` - * Frame is badly formatted; or frame type is unknown. + * Frame is badly formatted; or frame type is unknown; or + * |payloadlen| is 0. */ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, size_t payloadlen); @@ -554,9 +549,9 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, * This function returns the exact number of bytes read to decode * PADDING frames. */ -size_t ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest, - const uint8_t *payload, - size_t payloadlen); +ngtcp2_ssize ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest, + const uint8_t *payload, + size_t payloadlen); /* * ngtcp2_pkt_decode_reset_stream_frame decodes RESET_STREAM frame @@ -639,11 +634,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_streams_frame(ngtcp2_max_streams *dest, * length |payloadlen|. The result is stored in the object pointed by * |dest|. PING frame must start at payload[0]. This function * finishes when it decodes one PING frame, and returns the exact - * number of bytes read to decode a frame if it succeeds, or one of - * the following negative error codes: - * - * NGTCP2_ERR_FRAME_ENCODING - * Payload is too short to include PING frame. + * number of bytes read to decode a frame. */ ngtcp2_ssize ngtcp2_pkt_decode_ping_frame(ngtcp2_ping *dest, const uint8_t *payload, @@ -773,7 +764,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_path_response_frame(ngtcp2_path_response *dest, * NGTCP2_ERR_FRAME_ENCODING * Payload is too short to include CRYPTO frame. */ -ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest, +ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_stream *dest, const uint8_t *payload, size_t payloadlen); @@ -814,11 +805,7 @@ ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id *dest, * object pointed by |dest|. HANDSHAKE_DONE frame must start at * payload[0]. This function finishes when it decodes one * HANDSHAKE_DONE frame, and returns the exact number of bytes read to - * decode a frame if it succeeds, or one of the following negative - * error codes: - * - * NGTCP2_ERR_FRAME_ENCODING - * Payload is too short to include HANDSHAKE_DONE frame. + * decode a frame. */ ngtcp2_ssize ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done *dest, const uint8_t *payload, @@ -1076,7 +1063,7 @@ ngtcp2_pkt_encode_path_response_frame(uint8_t *out, size_t outlen, * Buffer does not have enough capacity to write a frame. */ ngtcp2_ssize ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen, - const ngtcp2_crypto *fr); + const ngtcp2_stream *fr); /* * ngtcp2_pkt_encode_new_token_frame encodes NEW_TOKEN frame |fr| into @@ -1133,23 +1120,28 @@ ngtcp2_ssize ngtcp2_pkt_encode_datagram_frame(uint8_t *out, size_t outlen, /* * ngtcp2_pkt_adjust_pkt_num find the full 64 bits packet number for - * |pkt_num|, which is expected to be least significant |n| bits. The + * |pkt_num|, which is encoded in |pkt_numlen| bytes. The * |max_pkt_num| is the highest successfully authenticated packet * number. */ int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num, - size_t n); + size_t pkt_numlen); /* * ngtcp2_pkt_validate_ack checks that ack is malformed or not. + * |min_pkt_num| is the minimum packet number that an endpoint sends. + * It is an error to receive acknowledgements for a packet less than + * |min_pkt_num|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * NGTCP2_ERR_ACK_FRAME * ACK frame is malformed + * NGTCP2_ERR_PROTO + * |fr| contains a packet number less than |min_pkt_num|. */ -int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr); +int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr, int64_t min_pkt_num); /* * ngtcp2_pkt_stream_max_datalen returns the maximum number of bytes diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pktns_id.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pktns_id.h new file mode 100644 index 00000000000000..66b0ee9e6c13cf --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pktns_id.h @@ -0,0 +1,62 @@ +/* + * ngtcp2 + * + * Copyright (c) 2023 ngtcp2 contributors + * + * 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. + */ +#ifndef NGTCP2_PKTNS_ID_H +#define NGTCP2_PKTNS_ID_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +/** + * @enum + * + * :type:`ngtcp2_pktns_id` defines packet number space identifier. + */ +typedef enum ngtcp2_pktns_id { + /** + * :enum:`NGTCP2_PKTNS_ID_INITIAL` is the Initial packet number + * space. + */ + NGTCP2_PKTNS_ID_INITIAL, + /** + * :enum:`NGTCP2_PKTNS_ID_HANDSHAKE` is the Handshake packet number + * space. + */ + NGTCP2_PKTNS_ID_HANDSHAKE, + /** + * :enum:`NGTCP2_PKTNS_ID_APPLICATION` is the Application data + * packet number space. + */ + NGTCP2_PKTNS_ID_APPLICATION, + /** + * :enum:`NGTCP2_PKTNS_ID_MAX` is defined to get the number of + * packet number spaces. + */ + NGTCP2_PKTNS_ID_MAX +} ngtcp2_pktns_id; + +#endif /* NGTCP2_PKTNS_ID_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.c index 26318bb1c8e38c..771ef5e026d12d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.c @@ -41,7 +41,7 @@ static size_t mtu_probes[] = { 1492 - 48, /* PPPoE */ }; -static size_t mtu_probeslen = sizeof(mtu_probes) / sizeof(mtu_probes[0]); +#define NGTCP2_MTU_PROBESLEN ngtcp2_arraylen(mtu_probes) int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size, size_t hard_max_udp_payload_size, int64_t tx_pkt_num, @@ -61,7 +61,7 @@ int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size, pmtud->hard_max_udp_payload_size = hard_max_udp_payload_size; pmtud->min_fail_udp_payload_size = SIZE_MAX; - for (; pmtud->mtu_idx < mtu_probeslen; ++pmtud->mtu_idx) { + for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) { if (mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { continue; } @@ -84,7 +84,7 @@ void ngtcp2_pmtud_del(ngtcp2_pmtud *pmtud) { } size_t ngtcp2_pmtud_probelen(ngtcp2_pmtud *pmtud) { - assert(pmtud->mtu_idx < mtu_probeslen); + assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN); return mtu_probes[pmtud->mtu_idx]; } @@ -107,13 +107,13 @@ int ngtcp2_pmtud_require_probe(ngtcp2_pmtud *pmtud) { } static void pmtud_next_probe(ngtcp2_pmtud *pmtud) { - assert(pmtud->mtu_idx < mtu_probeslen); + assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN); ++pmtud->mtu_idx; pmtud->num_pkts_sent = 0; pmtud->expiry = UINT64_MAX; - for (; pmtud->mtu_idx < mtu_probeslen; ++pmtud->mtu_idx) { + for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) { if (mtu_probes[pmtud->mtu_idx] <= pmtud->max_udp_payload_size || mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { continue; @@ -129,7 +129,7 @@ void ngtcp2_pmtud_probe_success(ngtcp2_pmtud *pmtud, size_t payloadlen) { pmtud->max_udp_payload_size = ngtcp2_max(pmtud->max_udp_payload_size, payloadlen); - assert(pmtud->mtu_idx < mtu_probeslen); + assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN); if (mtu_probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { return; @@ -156,5 +156,5 @@ void ngtcp2_pmtud_handle_expiry(ngtcp2_pmtud *pmtud, ngtcp2_tstamp ts) { } int ngtcp2_pmtud_finished(ngtcp2_pmtud *pmtud) { - return pmtud->mtu_idx >= mtu_probeslen; + return pmtud->mtu_idx >= NGTCP2_MTU_PROBESLEN; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.c index 5376246bd4caa9..f7c122b1ab406b 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.c @@ -39,7 +39,6 @@ void ngtcp2_ppe_init(ngtcp2_ppe *ppe, uint8_t *out, size_t outlen, ppe->pkt_num_offset = 0; ppe->pkt_numlen = 0; ppe->pkt_num = 0; - ppe->sample_offset = 0; ppe->cc = cc; } @@ -55,7 +54,7 @@ int ngtcp2_ppe_encode_hd(ngtcp2_ppe *ppe, const ngtcp2_pkt_hd *hd) { if (hd->flags & NGTCP2_PKT_FLAG_LONG_FORM) { ppe->len_offset = 1 + 4 + 1 + hd->dcid.datalen + 1 + hd->scid.datalen; if (hd->type == NGTCP2_PKT_INITIAL) { - ppe->len_offset += ngtcp2_put_varint_len(hd->token.len) + hd->token.len; + ppe->len_offset += ngtcp2_put_uvarintlen(hd->tokenlen) + hd->tokenlen; } ppe->pkt_num_offset = ppe->len_offset + NGTCP2_PKT_LENGTHLEN; rv = ngtcp2_pkt_encode_hd_long( @@ -69,8 +68,6 @@ int ngtcp2_ppe_encode_hd(ngtcp2_ppe *ppe, const ngtcp2_pkt_hd *hd) { return (int)rv; } - ppe->sample_offset = ppe->pkt_num_offset + 4; - buf->last += rv; ppe->pkt_numlen = hd->pkt_numlen; @@ -101,6 +98,14 @@ int ngtcp2_ppe_encode_frame(ngtcp2_ppe *ppe, ngtcp2_frame *fr) { return 0; } +/* + * ppe_sample_offset returns the offset to sample for packet number + * encryption. + */ +static size_t ppe_sample_offset(ngtcp2_ppe *ppe) { + return ppe->pkt_num_offset + 4; +} + ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt) { ngtcp2_buf *buf = &ppe->buf; ngtcp2_crypto_cc *cc = ppe->cc; @@ -115,7 +120,7 @@ ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt) { assert(cc->hp_mask); if (ppe->len_offset) { - ngtcp2_put_varint30( + ngtcp2_put_uvarint30( buf->begin + ppe->len_offset, (uint16_t)(payloadlen + ppe->pkt_numlen + cc->aead.max_overhead)); } @@ -132,9 +137,10 @@ ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt) { buf->last = payload + payloadlen + cc->aead.max_overhead; /* TODO Check that we have enough space to get sample */ - assert(ppe->sample_offset + NGTCP2_HP_SAMPLELEN <= ngtcp2_buf_len(buf)); + assert(ppe_sample_offset(ppe) + NGTCP2_HP_SAMPLELEN <= ngtcp2_buf_len(buf)); - rv = cc->hp_mask(mask, &cc->hp, &cc->hp_ctx, buf->begin + ppe->sample_offset); + rv = cc->hp_mask(mask, &cc->hp, &cc->hp_ctx, + buf->begin + ppe_sample_offset(ppe)); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -197,7 +203,7 @@ size_t ngtcp2_ppe_padding_hp_sample(ngtcp2_ppe *ppe) { assert(cc->aead.max_overhead); max_samplelen = - ngtcp2_buf_len(buf) + cc->aead.max_overhead - ppe->sample_offset; + ngtcp2_buf_len(buf) + cc->aead.max_overhead - ppe_sample_offset(ppe); if (max_samplelen < NGTCP2_HP_SAMPLELEN) { len = NGTCP2_HP_SAMPLELEN - max_samplelen; assert(ngtcp2_ppe_left(ppe) >= len); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.h index bf220df37c14f2..2a069ef33451ab 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.h @@ -50,9 +50,6 @@ typedef struct ngtcp2_ppe { /* pkt_numlen is the number of bytes used to encode a packet number */ size_t pkt_numlen; - /* sample_offset is the offset to sample for packet number - encryption. */ - size_t sample_offset; /* pkt_num is the packet number written in buf. */ int64_t pkt_num; /* nonce is the buffer to store nonce. It should be equal or longer diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h index 720c309f5adb5e..484c8f21f75de2 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h @@ -110,7 +110,7 @@ size_t ngtcp2_pq_size(ngtcp2_pq *pq); typedef int (*ngtcp2_pq_item_cb)(ngtcp2_pq_entry *item, void *arg); /* - * Applys |fun| to each item in |pq|. The |arg| is passed as arg + * Applies |fun| to each item in |pq|. The |arg| is passed as arg * parameter to callback function. This function must not change the * ordering key. If the return value from callback is nonzero, this * function returns 1 immediately without iterating remaining items. diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h index 293cbcaaf6e881..c9da15248a3e2b 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h @@ -76,10 +76,6 @@ void ngtcp2_pv_entry_init(ngtcp2_pv_entry *pvent, const uint8_t *data, fallback DCID. If path validation succeeds, fallback DCID is retired if it does not equal to the current DCID. */ #define NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE 0x04u -/* NGTCP2_PV_FLAG_MTU_PROBE indicates that a validation must probe - least MTU that QUIC requires, which is 1200 bytes. If it fails, a - path is not viable. */ -#define NGTCP2_PV_FLAG_MTU_PROBE 0x08u /* NGTCP2_PV_FLAG_PREFERRED_ADDR indicates that client is migrating to server's preferred address. This flag is only used by client. */ #define NGTCP2_PV_FLAG_PREFERRED_ADDR 0x10u diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c index 69eaeb7367438d..27675347794b2a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c @@ -30,6 +30,8 @@ #include "ngtcp2_vec.h" #include "ngtcp2_conv.h" #include "ngtcp2_net.h" +#include "ngtcp2_unreachable.h" +#include "ngtcp2_conn_stat.h" void ngtcp2_qlog_init(ngtcp2_qlog *qlog, ngtcp2_qlog_write write, ngtcp2_tstamp ts, void *user_data) { @@ -284,9 +286,9 @@ static uint8_t *write_pkt_hd(uint8_t *p, const ngtcp2_pkt_hd *hd) { p = write_pair(p, "packet_type", qlog_pkt_type(hd)); *p++ = ','; p = write_pair_number(p, "packet_number", (uint64_t)hd->pkt_num); - if (hd->type == NGTCP2_PKT_INITIAL && hd->token.len) { + if (hd->type == NGTCP2_PKT_INITIAL && hd->tokenlen) { p = write_verbatim(p, ",\"token\":{"); - p = write_pair_hex(p, "data", hd->token.base, hd->token.len); + p = write_pair_hex(p, "data", hd->token, hd->tokenlen); *p++ = '}'; } /* TODO Write DCIL and DCID */ @@ -316,7 +318,7 @@ static uint8_t *write_ping_frame(uint8_t *p, const ngtcp2_ping *fr) { static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) { int64_t largest_ack, min_ack; size_t i; - const ngtcp2_ack_blk *blk; + const ngtcp2_ack_range *range; /* * {"frame_type":"ack","ack_delay":0000000000000000000,"acked_ranges":[]} @@ -336,7 +338,7 @@ static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) { p = write_verbatim(p, ",\"acked_ranges\":["); largest_ack = fr->largest_ack; - min_ack = fr->largest_ack - (int64_t)fr->first_ack_blklen; + min_ack = fr->largest_ack - (int64_t)fr->first_ack_range; *p++ = '['; p = write_number(p, (uint64_t)min_ack); @@ -346,10 +348,10 @@ static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) { } *p++ = ']'; - for (i = 0; i < fr->num_blks; ++i) { - blk = &fr->blks[i]; - largest_ack = min_ack - (int64_t)blk->gap - 2; - min_ack = largest_ack - (int64_t)blk->blklen; + for (i = 0; i < fr->rangecnt; ++i) { + range = &fr->ranges[i]; + largest_ack = min_ack - (int64_t)range->gap - 2; + min_ack = largest_ack - (int64_t)range->len; *p++ = ','; *p++ = '['; p = write_number(p, (uint64_t)min_ack); @@ -410,7 +412,7 @@ static uint8_t *write_stop_sending_frame(uint8_t *p, return p; } -static uint8_t *write_crypto_frame(uint8_t *p, const ngtcp2_crypto *fr) { +static uint8_t *write_crypto_frame(uint8_t *p, const ngtcp2_stream *fr) { /* * {"frame_type":"crypto","offset":0000000000000000000,"length":0000000000000000000} */ @@ -432,9 +434,9 @@ static uint8_t *write_new_token_frame(uint8_t *p, const ngtcp2_new_token *fr) { #define NGTCP2_QLOG_NEW_TOKEN_FRAME_OVERHEAD 75 p = write_verbatim(p, "{\"frame_type\":\"new_token\","); - p = write_pair_number(p, "length", fr->token.len); + p = write_pair_number(p, "length", fr->tokenlen); p = write_verbatim(p, ",\"token\":{"); - p = write_pair_hex(p, "data", fr->token.base, fr->token.len); + p = write_pair_hex(p, "data", fr->token, fr->tokenlen); *p++ = '}'; *p++ = '}'; @@ -513,45 +515,53 @@ static uint8_t *write_max_streams_frame(uint8_t *p, static uint8_t *write_data_blocked_frame(uint8_t *p, const ngtcp2_data_blocked *fr) { - (void)fr; - /* - * {"frame_type":"data_blocked"} + * {"frame_type":"data_blocked","limit":0000000000000000000} */ -#define NGTCP2_QLOG_DATA_BLOCKED_FRAME_OVERHEAD 29 +#define NGTCP2_QLOG_DATA_BLOCKED_FRAME_OVERHEAD 57 - /* TODO log limit */ + p = write_verbatim(p, "{\"frame_type\":\"data_blocked\","); + p = write_pair_number(p, "limit", fr->offset); + *p++ = '}'; - return write_verbatim(p, "{\"frame_type\":\"data_blocked\"}"); + return p; } static uint8_t * write_stream_data_blocked_frame(uint8_t *p, const ngtcp2_stream_data_blocked *fr) { - (void)fr; - /* - * {"frame_type":"stream_data_blocked"} + * {"frame_type":"stream_data_blocked","stream_id":0000000000000000000,"limit":0000000000000000000} */ -#define NGTCP2_QLOG_STREAM_DATA_BLOCKED_FRAME_OVERHEAD 36 +#define NGTCP2_QLOG_STREAM_DATA_BLOCKED_FRAME_OVERHEAD 96 - /* TODO log limit */ + p = write_verbatim(p, "{\"frame_type\":\"stream_data_blocked\","); + p = write_pair_number(p, "stream_id", (uint64_t)fr->stream_id); + *p++ = ','; + p = write_pair_number(p, "limit", fr->offset); + *p++ = '}'; - return write_verbatim(p, "{\"frame_type\":\"stream_data_blocked\"}"); + return p; } static uint8_t *write_streams_blocked_frame(uint8_t *p, const ngtcp2_streams_blocked *fr) { - (void)fr; - /* - * {"frame_type":"streams_blocked"} + * {"frame_type":"streams_blocked","stream_type":"unidirectional","limit":0000000000000000000} */ -#define NGTCP2_QLOG_STREAMS_BLOCKED_FRAME_OVERHEAD 32 +#define NGTCP2_QLOG_STREAMS_BLOCKED_FRAME_OVERHEAD 91 - /* TODO Log stream_type and limit */ + p = write_verbatim(p, "{\"frame_type\":\"streams_blocked\",\"stream_type\":"); + if (fr->type == NGTCP2_FRAME_STREAMS_BLOCKED_BIDI) { + p = write_string(p, "bidirectional"); + } else { + p = write_string(p, "unidirectional"); + } + *p++ = ','; + p = write_pair_number(p, "limit", fr->max_streams); + *p++ = '}'; - return write_verbatim(p, "{\"frame_type\":\"streams_blocked\"}"); + return p; } static uint8_t * @@ -715,7 +725,7 @@ static void qlog_pkt_write_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd, (1 + 50 + NGTCP2_QLOG_PKT_HD_OVERHEAD) if (ngtcp2_buf_left(&qlog->buf) < - NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD + hd->token.len * 2) { + NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD + hd->tokenlen * 2) { return; } @@ -765,7 +775,7 @@ void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) { (size_t)(fr->type == NGTCP2_FRAME_ACK_ECN ? NGTCP2_QLOG_ACK_FRAME_ECN_OVERHEAD : 0) + - NGTCP2_QLOG_ACK_FRAME_RANGE_OVERHEAD * (1 + fr->ack.num_blks) + 1) { + NGTCP2_QLOG_ACK_FRAME_RANGE_OVERHEAD * (1 + fr->ack.rangecnt) + 1) { return; } p = write_ack_frame(p, &fr->ack); @@ -788,11 +798,11 @@ void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) { if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_CRYPTO_FRAME_OVERHEAD + 1) { return; } - p = write_crypto_frame(p, &fr->crypto); + p = write_crypto_frame(p, &fr->stream); break; case NGTCP2_FRAME_NEW_TOKEN: - if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_NEW_TOKEN_FRAME_OVERHEAD + - fr->new_token.token.len * 2 + 1) { + if (ngtcp2_buf_left(&qlog->buf) < + NGTCP2_QLOG_NEW_TOKEN_FRAME_OVERHEAD + fr->new_token.tokenlen * 2 + 1) { return; } p = write_new_token_frame(p, &fr->new_token); @@ -897,7 +907,7 @@ void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) { p = write_datagram_frame(p, &fr->datagram); break; default: - assert(0); + ngtcp2_unreachable(); } *p++ = ','; @@ -929,6 +939,8 @@ void ngtcp2_qlog_parameters_set_transport_params( uint8_t buf[1024]; uint8_t *p = buf; const ngtcp2_preferred_addr *paddr; + const ngtcp2_sockaddr_in *sa_in; + const ngtcp2_sockaddr_in6 *sa_in6; if (!qlog->write) { return; @@ -996,20 +1008,33 @@ void ngtcp2_qlog_parameters_set_transport_params( *p++ = ','; p = write_pair_number(p, "initial_max_streams_uni", params->initial_max_streams_uni); - if (params->preferred_address_present) { + if (params->preferred_addr_present) { *p++ = ','; - paddr = ¶ms->preferred_address; + paddr = ¶ms->preferred_addr; p = write_string(p, "preferred_address"); *p++ = ':'; *p++ = '{'; - p = write_pair_hex(p, "ip_v4", paddr->ipv4_addr, sizeof(paddr->ipv4_addr)); - *p++ = ','; - p = write_pair_number(p, "port_v4", paddr->ipv4_port); - *p++ = ','; - p = write_pair_hex(p, "ip_v6", paddr->ipv6_addr, sizeof(paddr->ipv6_addr)); - *p++ = ','; - p = write_pair_number(p, "port_v6", paddr->ipv6_port); - *p++ = ','; + + if (paddr->ipv4_present) { + sa_in = &paddr->ipv4; + + p = write_pair_hex(p, "ip_v4", (const uint8_t *)&sa_in->sin_addr, + sizeof(sa_in->sin_addr)); + *p++ = ','; + p = write_pair_number(p, "port_v4", ngtcp2_ntohs(sa_in->sin_port)); + *p++ = ','; + } + + if (paddr->ipv6_present) { + sa_in6 = &paddr->ipv6; + + p = write_pair_hex(p, "ip_v6", (const uint8_t *)&sa_in6->sin6_addr, + sizeof(sa_in6->sin6_addr)); + *p++ = ','; + p = write_pair_number(p, "port_v6", ngtcp2_ntohs(sa_in6->sin6_port)); + *p++ = ','; + } + p = write_pair_cid(p, "connection_id", &paddr->cid); p = write_verbatim(p, ",\"stateless_reset_token\":{"); p = write_pair_hex(p, "data", paddr->stateless_reset_token, @@ -1113,16 +1138,15 @@ void ngtcp2_qlog_retry_pkt_received(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd, ",\"name\":\"transport:packet_received\",\"data\":{\"header\":"); if (ngtcp2_buf_left(&buf) < - NGTCP2_QLOG_PKT_HD_OVERHEAD + hd->token.len * 2 + + NGTCP2_QLOG_PKT_HD_OVERHEAD + hd->tokenlen * 2 + sizeof(",\"retry_token\":{\"data\":\"\"}}}\n") - 1 + - retry->token.len * 2) { + retry->tokenlen * 2) { return; } buf.last = write_pkt_hd(buf.last, hd); buf.last = write_verbatim(buf.last, ",\"retry_token\":{"); - buf.last = - write_pair_hex(buf.last, "data", retry->token.base, retry->token.len); + buf.last = write_pair_hex(buf.last, "data", retry->token, retry->tokenlen); buf.last = write_verbatim(buf.last, "}}}\n"); qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf.pos, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c index 74e488bce76f24..c381c231276d34 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c @@ -31,8 +31,9 @@ #include "ngtcp2_macro.h" -#if defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || defined(_M_ARM64)) -unsigned int __popcnt(unsigned int x) { +#if defined(_MSC_VER) && !defined(__clang__) && \ + (defined(_M_ARM) || defined(_M_ARM64)) +static unsigned int __popcnt(unsigned int x) { unsigned int c = 0; for (; x; ++c) { x &= x - 1; @@ -63,7 +64,7 @@ void ngtcp2_ringbuf_buf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size, rb->buf = buf; rb->mem = mem; - rb->nmemb = nmemb; + rb->mask = nmemb - 1; rb->size = size; rb->first = 0; rb->len = 0; @@ -78,17 +79,19 @@ void ngtcp2_ringbuf_free(ngtcp2_ringbuf *rb) { } void *ngtcp2_ringbuf_push_front(ngtcp2_ringbuf *rb) { - rb->first = (rb->first - 1) & (rb->nmemb - 1); - rb->len = ngtcp2_min(rb->nmemb, rb->len + 1); + rb->first = (rb->first - 1) & rb->mask; + if (rb->len < rb->mask + 1) { + ++rb->len; + } return (void *)&rb->buf[rb->first * rb->size]; } void *ngtcp2_ringbuf_push_back(ngtcp2_ringbuf *rb) { - size_t offset = (rb->first + rb->len) & (rb->nmemb - 1); + size_t offset = (rb->first + rb->len) & rb->mask; - if (rb->len == rb->nmemb) { - rb->first = (rb->first + 1) & (rb->nmemb - 1); + if (rb->len == rb->mask + 1) { + rb->first = (rb->first + 1) & rb->mask; } else { ++rb->len; } @@ -97,7 +100,7 @@ void *ngtcp2_ringbuf_push_back(ngtcp2_ringbuf *rb) { } void ngtcp2_ringbuf_pop_front(ngtcp2_ringbuf *rb) { - rb->first = (rb->first + 1) & (rb->nmemb - 1); + rb->first = (rb->first + 1) & rb->mask; --rb->len; } @@ -107,14 +110,14 @@ void ngtcp2_ringbuf_pop_back(ngtcp2_ringbuf *rb) { } void ngtcp2_ringbuf_resize(ngtcp2_ringbuf *rb, size_t len) { - assert(len <= rb->nmemb); + assert(len <= rb->mask + 1); rb->len = len; } void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset) { assert(offset < rb->len); - offset = (rb->first + offset) & (rb->nmemb - 1); + offset = (rb->first + offset) & rb->mask; return &rb->buf[offset * rb->size]; } -int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb) { return rb->len == rb->nmemb; } +int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb) { return rb->len == rb->mask + 1; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h index 16635c941032c7..b28a882c4bae84 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h @@ -37,9 +37,9 @@ typedef struct ngtcp2_ringbuf { /* buf points to the underlying buffer. */ uint8_t *buf; const ngtcp2_mem *mem; - /* nmemb is the number of elements that can be stored in this ring - buffer. */ - size_t nmemb; + /* mask is the bit mask to cover all bits for the maximum number of + elements. The maximum number of elements is mask + 1. */ + size_t mask; /* size is the size of each element. */ size_t size; /* first is the offset to the first element. */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c index 9c3d75dc33ae0c..5cac383f7bb166 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c @@ -218,7 +218,7 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, return 0; } -int ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) { +void ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) { ngtcp2_rob_gap *g; ngtcp2_rob_data *d; ngtcp2_ksl_it it; @@ -245,13 +245,11 @@ int ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) { for (; !ngtcp2_ksl_it_end(&it);) { d = ngtcp2_ksl_it_get(&it); if (offset < d->range.begin + rob->chunk) { - return 0; + return; } ngtcp2_ksl_remove_hint(&rob->dataksl, &it, &it, &d->range); ngtcp2_rob_data_del(d, rob->mem); } - - return 0; } size_t ngtcp2_rob_data_at(ngtcp2_rob *rob, const uint8_t **pdest, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.h index c7688df4542956..6518d56c539185 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.h @@ -152,14 +152,8 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, /* * ngtcp2_rob_remove_prefix removes gap up to |offset|, exclusive. It * also removes data buffer if it is completely included in |offset|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory */ -int ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset); +void ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset); /* * ngtcp2_rob_data_at stores the pointer to the buffer of stream diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c index 7b50f98d41ec7b..b8587e3e9dbac8 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c @@ -29,6 +29,7 @@ #include "ngtcp2_rtb.h" #include "ngtcp2_cc.h" #include "ngtcp2_macro.h" +#include "ngtcp2_conn_stat.h" void ngtcp2_rs_init(ngtcp2_rs *rs) { rs->interval = UINT64_MAX; @@ -69,8 +70,8 @@ void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, ent->rst.lost = rst->lost; } -int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, - uint64_t pkt_delivered) { +void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, + uint64_t pkt_delivered) { ngtcp2_rs *rs = &rst->rs; uint64_t rate; @@ -84,7 +85,7 @@ int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, } if (rs->prior_ts == 0) { - return 0; + return; } rs->interval = ngtcp2_max(rs->send_elapsed, rs->ack_elapsed); @@ -94,11 +95,11 @@ int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, if (rs->interval < cstat->min_rtt) { rs->interval = UINT64_MAX; - return 0; + return; } if (!rs->interval) { - return 0; + return; } rate = rs->delivered * NGTCP2_SECONDS / rs->interval; @@ -107,8 +108,6 @@ int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, ngtcp2_window_filter_update(&rst->wf, rate, rst->round_count); cstat->delivery_rate_sec = ngtcp2_window_filter_get_best(&rst->wf); } - - return 0; } void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h index 488c65575a5589..c9e1e161b7766f 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h @@ -34,6 +34,7 @@ #include "ngtcp2_window_filter.h" typedef struct ngtcp2_rtb_entry ngtcp2_rtb_entry; +typedef struct ngtcp2_conn_stat ngtcp2_conn_stat; /** * @struct @@ -76,8 +77,8 @@ void ngtcp2_rst_init(ngtcp2_rst *rst); void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, const ngtcp2_conn_stat *cstat); -int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, - uint64_t pkt_delivered); +void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, + uint64_t pkt_delivered); void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent, ngtcp2_tstamp ts); void ngtcp2_rst_update_app_limited(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c index 644071400a6eb7..5ebdce7d0e2715 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c @@ -34,220 +34,11 @@ #include "ngtcp2_cc.h" #include "ngtcp2_rcvry.h" #include "ngtcp2_rst.h" +#include "ngtcp2_unreachable.h" +#include "ngtcp2_tstamp.h" +#include "ngtcp2_frame_chain.h" -int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem) { - *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain)); - if (*pfrc == NULL) { - return NGTCP2_ERR_NOMEM; - } - - ngtcp2_frame_chain_init(*pfrc); - - return 0; -} - -int ngtcp2_frame_chain_objalloc_new(ngtcp2_frame_chain **pfrc, - ngtcp2_objalloc *objalloc) { - *pfrc = ngtcp2_objalloc_frame_chain_get(objalloc); - if (*pfrc == NULL) { - return NGTCP2_ERR_NOMEM; - } - - ngtcp2_frame_chain_init(*pfrc); - - return 0; -} - -int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen, - const ngtcp2_mem *mem) { - *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain) + extralen); - if (*pfrc == NULL) { - return NGTCP2_ERR_NOMEM; - } - - ngtcp2_frame_chain_init(*pfrc); - - return 0; -} - -int ngtcp2_frame_chain_stream_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, - size_t datacnt, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem) { - size_t need, avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream); - - if (datacnt > 1) { - need = sizeof(ngtcp2_vec) * (datacnt - 1); - - if (need > avail) { - return ngtcp2_frame_chain_extralen_new(pfrc, need - avail, mem); - } - } - - return ngtcp2_frame_chain_objalloc_new(pfrc, objalloc); -} - -int ngtcp2_frame_chain_crypto_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, - size_t datacnt, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem) { - size_t need, avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_crypto); - - if (datacnt > 1) { - need = sizeof(ngtcp2_vec) * (datacnt - 1); - - if (need > avail) { - return ngtcp2_frame_chain_extralen_new(pfrc, need - avail, mem); - } - } - - return ngtcp2_frame_chain_objalloc_new(pfrc, objalloc); -} - -int ngtcp2_frame_chain_new_token_objalloc_new(ngtcp2_frame_chain **pfrc, - const ngtcp2_vec *token, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem) { - size_t avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token); - int rv; - uint8_t *p; - ngtcp2_frame *fr; - - if (token->len > avail) { - rv = ngtcp2_frame_chain_extralen_new(pfrc, token->len - avail, mem); - } else { - rv = ngtcp2_frame_chain_objalloc_new(pfrc, objalloc); - } - if (rv != 0) { - return rv; - } - - fr = &(*pfrc)->fr; - fr->type = NGTCP2_FRAME_NEW_TOKEN; - - p = (uint8_t *)fr + sizeof(ngtcp2_new_token); - memcpy(p, token->base, token->len); - - ngtcp2_vec_init(&fr->new_token.token, p, token->len); - - return 0; -} - -void ngtcp2_frame_chain_del(ngtcp2_frame_chain *frc, const ngtcp2_mem *mem) { - ngtcp2_frame_chain_binder *binder; - - if (frc == NULL) { - return; - } - - binder = frc->binder; - if (binder && --binder->refcount == 0) { - ngtcp2_mem_free(mem, binder); - } - - ngtcp2_mem_free(mem, frc); -} - -void ngtcp2_frame_chain_objalloc_del(ngtcp2_frame_chain *frc, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem) { - ngtcp2_frame_chain_binder *binder; - - if (frc == NULL) { - return; - } - - switch (frc->fr.type) { - case NGTCP2_FRAME_STREAM: - if (frc->fr.stream.datacnt && - sizeof(ngtcp2_vec) * (frc->fr.stream.datacnt - 1) > - sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream)) { - ngtcp2_frame_chain_del(frc, mem); - - return; - } - - break; - case NGTCP2_FRAME_CRYPTO: - if (frc->fr.crypto.datacnt && - sizeof(ngtcp2_vec) * (frc->fr.crypto.datacnt - 1) > - sizeof(ngtcp2_frame) - sizeof(ngtcp2_crypto)) { - ngtcp2_frame_chain_del(frc, mem); - - return; - } - - break; - case NGTCP2_FRAME_NEW_TOKEN: - if (frc->fr.new_token.token.len > - sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token)) { - ngtcp2_frame_chain_del(frc, mem); - - return; - } - - break; - } - - binder = frc->binder; - if (binder && --binder->refcount == 0) { - ngtcp2_mem_free(mem, binder); - } - - frc->binder = NULL; - - ngtcp2_objalloc_frame_chain_release(objalloc, frc); -} - -void ngtcp2_frame_chain_init(ngtcp2_frame_chain *frc) { - frc->next = NULL; - frc->binder = NULL; -} - -void ngtcp2_frame_chain_list_objalloc_del(ngtcp2_frame_chain *frc, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem) { - ngtcp2_frame_chain *next; - - for (; frc; frc = next) { - next = frc->next; - - ngtcp2_frame_chain_objalloc_del(frc, objalloc, mem); - } -} - -int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder, - const ngtcp2_mem *mem) { - *pbinder = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_frame_chain_binder)); - if (*pbinder == NULL) { - return NGTCP2_ERR_NOMEM; - } - - return 0; -} - -int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b, - const ngtcp2_mem *mem) { - ngtcp2_frame_chain_binder *binder; - int rv; - - assert(b->binder == NULL); - - if (a->binder == NULL) { - rv = ngtcp2_frame_chain_binder_new(&binder, mem); - if (rv != 0) { - return rv; - } - - a->binder = binder; - ++a->binder->refcount; - } - - b->binder = a->binder; - ++b->binder->refcount; - - return 0; -} +ngtcp2_objalloc_def(rtb_entry, ngtcp2_rtb_entry, oplent); static void rtb_entry_init(ngtcp2_rtb_entry *ent, const ngtcp2_pkt_hd *hd, ngtcp2_frame_chain *frc, ngtcp2_tstamp ts, @@ -297,7 +88,7 @@ static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id, ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc, - ngtcp2_log *log, ngtcp2_qlog *qlog, + int64_t cc_pkt_num, ngtcp2_log *log, ngtcp2_qlog *qlog, ngtcp2_objalloc *rtb_entry_objalloc, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { rtb->rtb_entry_objalloc = rtb_entry_objalloc; @@ -315,7 +106,7 @@ void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id, rtb->num_pto_eliciting = 0; rtb->probe_pkt_left = 0; rtb->pktns_id = pktns_id; - rtb->cc_pkt_num = 0; + rtb->cc_pkt_num = cc_pkt_num; rtb->cc_bytes_in_flight = 0; rtb->persistent_congestion_start_ts = UINT64_MAX; rtb->num_lost_pkts = 0; @@ -432,7 +223,6 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, ngtcp2_range gap, range; size_t num_reclaimed = 0; int rv; - int streamfrq_empty; assert(ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE); @@ -447,7 +237,7 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, switch (frc->fr.type) { case NGTCP2_FRAME_STREAM: strm = ngtcp2_conn_find_stream(conn, fr->stream.stream_id); - if (strm == NULL) { + if (strm == NULL || (strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM)) { continue; } @@ -487,7 +277,6 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, ngtcp2_vec_copy(nfrc->fr.stream.data, fr->stream.data, fr->stream.datacnt); - streamfrq_empty = ngtcp2_strm_streamfrq_empty(strm); rv = ngtcp2_strm_streamfrq_push(strm, nfrc); if (rv != 0) { ngtcp2_frame_chain_objalloc_del(nfrc, rtb->frc_objalloc, rtb->mem); @@ -500,9 +289,6 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, return rv; } } - if (streamfrq_empty) { - ++conn->tx.strmq_nretrans; - } ++num_reclaimed; @@ -510,28 +296,27 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, case NGTCP2_FRAME_CRYPTO: /* Don't resend CRYPTO frame if the whole region it contains has been acknowledged */ - gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, fr->crypto.offset); + gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, fr->stream.offset); - range.begin = fr->crypto.offset; - range.end = fr->crypto.offset + - ngtcp2_vec_len(fr->crypto.data, fr->crypto.datacnt); + range.begin = fr->stream.offset; + range.end = fr->stream.offset + + ngtcp2_vec_len(fr->stream.data, fr->stream.datacnt); range = ngtcp2_range_intersect(&range, &gap); if (ngtcp2_range_len(&range) == 0) { continue; } - rv = ngtcp2_frame_chain_crypto_datacnt_objalloc_new( - &nfrc, fr->crypto.datacnt, rtb->frc_objalloc, rtb->mem); + rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( + &nfrc, fr->stream.datacnt, rtb->frc_objalloc, rtb->mem); if (rv != 0) { return rv; } nfrc->fr = *fr; - ngtcp2_vec_copy(nfrc->fr.crypto.data, fr->crypto.data, - fr->crypto.datacnt); + ngtcp2_vec_copy(nfrc->fr.stream.data, fr->stream.data, + fr->stream.datacnt); - rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, - &nfrc->fr.crypto.offset, nfrc); + rv = ngtcp2_strm_streamfrq_push(&pktns->crypto.strm, nfrc); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); ngtcp2_frame_chain_objalloc_del(nfrc, rtb->frc_objalloc, rtb->mem); @@ -543,7 +328,8 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, continue; case NGTCP2_FRAME_NEW_TOKEN: rv = ngtcp2_frame_chain_new_token_objalloc_new( - &nfrc, &fr->new_token.token, rtb->frc_objalloc, rtb->mem); + &nfrc, fr->new_token.token, fr->new_token.tokenlen, rtb->frc_objalloc, + rtb->mem); if (rv != 0) { return rv; } @@ -553,26 +339,60 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, return rv; } - break; + ++num_reclaimed; + + nfrc->next = *pfrc; + *pfrc = nfrc; + pfrc = &nfrc->next; + + continue; case NGTCP2_FRAME_DATAGRAM: case NGTCP2_FRAME_DATAGRAM_LEN: continue; - default: - rv = ngtcp2_frame_chain_objalloc_new(&nfrc, rtb->frc_objalloc); - if (rv != 0) { - return rv; + case NGTCP2_FRAME_RESET_STREAM: + strm = ngtcp2_conn_find_stream(conn, fr->reset_stream.stream_id); + if (strm == NULL || !ngtcp2_strm_require_retransmit_reset_stream(strm)) { + continue; } - nfrc->fr = *fr; + break; + case NGTCP2_FRAME_STOP_SENDING: + strm = ngtcp2_conn_find_stream(conn, fr->stop_sending.stream_id); + if (strm == NULL || !ngtcp2_strm_require_retransmit_stop_sending(strm)) { + continue; + } - rv = ngtcp2_bind_frame_chains(frc, nfrc, rtb->mem); - if (rv != 0) { - return rv; + break; + case NGTCP2_FRAME_MAX_STREAM_DATA: + strm = ngtcp2_conn_find_stream(conn, fr->max_stream_data.stream_id); + if (strm == NULL || !ngtcp2_strm_require_retransmit_max_stream_data( + strm, &fr->max_stream_data)) { + continue; + } + + break; + case NGTCP2_FRAME_STREAM_DATA_BLOCKED: + strm = ngtcp2_conn_find_stream(conn, fr->stream_data_blocked.stream_id); + if (strm == NULL || !ngtcp2_strm_require_retransmit_stream_data_blocked( + strm, &fr->stream_data_blocked)) { + continue; } break; } + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, rtb->frc_objalloc); + if (rv != 0) { + return rv; + } + + nfrc->fr = *fr; + + rv = ngtcp2_bind_frame_chains(frc, nfrc, rtb->mem); + if (rv != 0) { + return rv; + } + ++num_reclaimed; nfrc->next = *pfrc; @@ -638,7 +458,7 @@ static int rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it, } if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, "pkn=%" PRId64 " has already been reclaimed on PTO", ent->hd.pkt_num); assert(!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED)); @@ -770,6 +590,10 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, for (frc = ent->frc; frc; frc = frc->next) { if (frc->binder) { + if (frc->binder->flags & NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK) { + continue; + } + frc->binder->flags |= NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK; } @@ -817,8 +641,8 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, case NGTCP2_FRAME_CRYPTO: prev_stream_offset = ngtcp2_strm_get_acked_offset(crypto); rv = ngtcp2_strm_ack_data( - crypto, frc->fr.crypto.offset, - ngtcp2_vec_len(frc->fr.crypto.data, frc->fr.crypto.datacnt)); + crypto, frc->fr.stream.offset, + ngtcp2_vec_len(frc->fr.stream.data, frc->fr.stream.datacnt)); if (rv != 0) { return rv; } @@ -840,7 +664,7 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, pktns = &conn->pktns; break; default: - assert(0); + ngtcp2_unreachable(); } conn_ack_crypto_data(conn, pktns, datalen); @@ -851,7 +675,7 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, if (strm == NULL) { break; } - strm->flags |= NGTCP2_STRM_FLAG_RST_ACKED; + strm->flags |= NGTCP2_STRM_FLAG_RESET_STREAM_ACKED; rv = ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm); if (rv != 0) { return rv; @@ -861,6 +685,12 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, ngtcp2_conn_untrack_retired_dcid_seq(conn, frc->fr.retire_connection_id.seq); break; + case NGTCP2_FRAME_NEW_CONNECTION_ID: + assert(conn->scid.num_in_flight); + + --conn->scid.num_in_flight; + + break; case NGTCP2_FRAME_DATAGRAM: case NGTCP2_FRAME_DATAGRAM_LEN: if (!conn->callbacks.ack_datagram) { @@ -885,12 +715,14 @@ static void rtb_on_pkt_acked(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, ngtcp2_rst_update_rate_sample(rtb->rst, ent, ts); - cc->on_pkt_acked(cc, cstat, - ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen, - rtb->pktns_id, ent->ts, ent->rst.lost, - ent->rst.tx_in_flight, - ent->rst.is_app_limited), - ts); + if (cc->on_pkt_acked) { + cc->on_pkt_acked(cc, cstat, + ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen, + rtb->pktns_id, ent->ts, ent->rst.lost, + ent->rst.tx_in_flight, + ent->rst.is_app_limited), + ts); + } if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_PROBE) && (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { @@ -901,7 +733,7 @@ static void rtb_on_pkt_acked(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_ack *fr, size_t ecn_acked, - ngtcp2_tstamp largest_acked_sent_ts, + ngtcp2_tstamp largest_pkt_sent_ts, ngtcp2_tstamp ts) { if (conn->tx.ecn.state == NGTCP2_ECN_STATE_FAILED) { return; @@ -928,9 +760,9 @@ static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, } if (fr->type == NGTCP2_FRAME_ACK_ECN) { - if (largest_acked_sent_ts != UINT64_MAX && + if (cc->congestion_event && largest_pkt_sent_ts != UINT64_MAX && fr->ecn.ce > pktns->rx.ecn.ack.ce) { - cc->congestion_event(cc, cstat, largest_acked_sent_ts, ts); + cc->congestion_event(cc, cstat, largest_pkt_sent_ts, ts); } pktns->rx.ecn.ack.ect0 = fr->ecn.ect0; @@ -954,7 +786,6 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, ngtcp2_ksl_it it; ngtcp2_ssize num_acked = 0; ngtcp2_tstamp largest_pkt_sent_ts = UINT64_MAX; - ngtcp2_tstamp largest_acked_sent_ts = UINT64_MAX; int64_t pkt_num; ngtcp2_cc *cc = rtb->cc; ngtcp2_rtb_entry *acked_ent = NULL; @@ -987,12 +818,12 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, if (ngtcp2_ksl_it_end(&it)) { if (conn && verify_ecn) { conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, - largest_acked_sent_ts, ts); + largest_pkt_sent_ts, ts); } return 0; } - min_ack = largest_ack - (int64_t)fr->first_ack_blklen; + min_ack = largest_ack - (int64_t)fr->first_ack_range; for (; !ngtcp2_ksl_it_end(&it);) { pkt_num = *(int64_t *)ngtcp2_ksl_it_key(&it); @@ -1017,9 +848,9 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, ++num_acked; } - for (i = 0; i < fr->num_blks;) { - largest_ack = min_ack - (int64_t)fr->blks[i].gap - 2; - min_ack = largest_ack - (int64_t)fr->blks[i].blklen; + for (i = 0; i < fr->rangecnt;) { + largest_ack = min_ack - (int64_t)fr->ranges[i].gap - 2; + min_ack = largest_ack - (int64_t)fr->ranges[i].len; it = ngtcp2_ksl_lower_bound(&rtb->ents, &largest_ack); if (ngtcp2_ksl_it_end(&it)) { @@ -1060,11 +891,6 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, ++ecn_acked; } - assert(largest_acked_sent_ts == UINT64_MAX || - largest_acked_sent_ts <= ent->ts); - - largest_acked_sent_ts = ent->ts; - rv = rtb_process_acked_pkt(rtb, ent, conn); if (rv != 0) { goto fail; @@ -1085,7 +911,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, if (verify_ecn) { conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, - largest_acked_sent_ts, ts); + largest_pkt_sent_ts, ts); } } else { /* For unit tests */ @@ -1113,8 +939,10 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, rtb->rst->lost += cc_ack.bytes_lost; - cc_ack.largest_acked_sent_ts = largest_acked_sent_ts; - cc->on_ack_recv(cc, cstat, &cc_ack, ts); + cc_ack.largest_pkt_sent_ts = largest_pkt_sent_ts; + if (cc->on_ack_recv) { + cc->on_ack_recv(cc, cstat, &cc_ack, ts); + } return num_acked; @@ -1133,7 +961,7 @@ static int rtb_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat, size_t pkt_thres, ngtcp2_tstamp ts) { ngtcp2_tstamp loss_time; - if (ent->ts + loss_delay <= ts || + if (ngtcp2_tstamp_elapsed(ent->ts, loss_delay, ts) || rtb->largest_acked_tx_pkt_num >= ent->hd.pkt_num + (int64_t)pkt_thres) { return 1; } @@ -1189,7 +1017,7 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, ngtcp2_cc *cc = rtb->cc; int rv; uint64_t pkt_thres = - rtb->cc_bytes_in_flight / cstat->max_udp_payload_size / 2; + rtb->cc_bytes_in_flight / cstat->max_tx_udp_payload_size / 2; size_t ecn_pkt_lost = 0; ngtcp2_tstamp start_ts; ngtcp2_duration pto = ngtcp2_conn_compute_pto(conn, pktns); @@ -1212,7 +1040,9 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, if (rtb_pkt_lost(rtb, cstat, ent, loss_delay, (size_t)pkt_thres, ts)) { /* All entries from ent are considered to be lost. */ latest_ts = oldest_ts = ent->ts; - last_lost_pkt_num = ent->hd.pkt_num; + /* +1 to pick this packet for persistent congestion in the + following loop. */ + last_lost_pkt_num = ent->hd.pkt_num + 1; max_ack_delay = conn->remote.transport_params ? conn->remote.transport_params->max_ack_delay : 0; @@ -1288,7 +1118,9 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, break; } - cc->congestion_event(cc, cstat, latest_ts, ts); + if (cc->congestion_event) { + cc->congestion_event(cc, cstat, latest_ts, ts); + } loss_window = latest_ts - oldest_ts; /* Persistent congestion situation is only evaluated for app @@ -1300,7 +1132,7 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, */ if (rtb->pktns_id == NGTCP2_PKTNS_ID_APPLICATION && loss_window > 0) { if (loss_window >= congestion_period) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, "persistent congestion loss_window=%" PRIu64 " congestion_period=%" PRIu64, loss_window, congestion_period); @@ -1312,7 +1144,9 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, cstat->rttvar = conn->local.settings.initial_rtt / 2; cstat->first_rtt_sample_ts = UINT64_MAX; - cc->on_persistent_congestion(cc, cstat, ts); + if (cc->on_persistent_congestion) { + cc->on_persistent_congestion(cc, cstat, ts); + } } } @@ -1349,7 +1183,7 @@ void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n) { assert(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED); - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, "removing stale lost pkn=%" PRId64, ent->hd.pkt_num); --rtb->num_lost_pkts; @@ -1389,7 +1223,7 @@ void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_duration pto, return; } - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, "removing stale lost pkn=%" PRId64, ent->hd.pkt_num); --rtb->num_lost_pkts; @@ -1435,7 +1269,6 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_stream *sfr; ngtcp2_strm *strm; int rv; - int streamfrq_empty; ngtcp2_log_pkt_lost(rtb->log, ent->hd.pkt_num, ent->hd.type, ent->hd.flags, ent->ts); @@ -1445,7 +1278,7 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, } if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PROBE) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, "pkn=%" PRId64 " is a probe packet, no retransmission is necessary", ent->hd.pkt_num); @@ -1453,7 +1286,7 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, } if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, "pkn=%" PRId64 " is a PMTUD probe packet, no retransmission is necessary", ent->hd.pkt_num); @@ -1467,7 +1300,7 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, --rtb->num_lost_pmtud_pkts; } - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, "pkn=%" PRId64 " was declared lost and has already been retransmitted", ent->hd.pkt_num); @@ -1475,7 +1308,7 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, } if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV, + ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, "pkn=%" PRId64 " has already been reclaimed on PTO", ent->hd.pkt_num); return 0; @@ -1505,7 +1338,6 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_frame_chain_objalloc_del(frc, rtb->frc_objalloc, rtb->mem); break; } - streamfrq_empty = ngtcp2_strm_streamfrq_empty(strm); rv = ngtcp2_strm_streamfrq_push(strm, frc); if (rv != 0) { ngtcp2_frame_chain_objalloc_del(frc, rtb->frc_objalloc, rtb->mem); @@ -1518,9 +1350,6 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, return rv; } } - if (streamfrq_empty) { - ++conn->tx.strmq_nretrans; - } break; case NGTCP2_FRAME_CRYPTO: frc = *pfrc; @@ -1528,8 +1357,7 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, *pfrc = frc->next; frc->next = NULL; - rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, - &frc->fr.crypto.offset, frc); + rv = ngtcp2_strm_streamfrq_push(&pktns->crypto.strm, frc); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); ngtcp2_frame_chain_objalloc_del(frc, rtb->frc_objalloc, rtb->mem); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h index a97805dbaf3bc3..a1ff208b19eac7 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h @@ -35,6 +35,7 @@ #include "ngtcp2_ksl.h" #include "ngtcp2_pq.h" #include "ngtcp2_objalloc.h" +#include "ngtcp2_pktns_id.h" typedef struct ngtcp2_conn ngtcp2_conn; typedef struct ngtcp2_pktns ngtcp2_pktns; @@ -43,156 +44,9 @@ typedef struct ngtcp2_qlog ngtcp2_qlog; typedef struct ngtcp2_strm ngtcp2_strm; typedef struct ngtcp2_rst ngtcp2_rst; typedef struct ngtcp2_cc ngtcp2_cc; - -/* NGTCP2_FRAME_CHAIN_BINDER_FLAG_NONE indicates that no flag is - set. */ -#define NGTCP2_FRAME_CHAIN_BINDER_FLAG_NONE 0x00u -/* NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK indicates that an information - which a frame carries has been acknowledged. */ -#define NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK 0x01u - -/* - * ngtcp2_frame_chain_binder binds 2 or more of ngtcp2_frame_chain to - * share the acknowledgement state. In general, all - * ngtcp2_frame_chains bound to the same binder must have the same - * information. - */ -typedef struct ngtcp2_frame_chain_binder { - size_t refcount; - /* flags is bitwise OR of zero or more of - NGTCP2_FRAME_CHAIN_BINDER_FLAG_*. */ - uint32_t flags; -} ngtcp2_frame_chain_binder; - -int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder, - const ngtcp2_mem *mem); - +typedef struct ngtcp2_conn_stat ngtcp2_conn_stat; typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; -/* - * ngtcp2_frame_chain chains frames in a single packet. - */ -struct ngtcp2_frame_chain { - union { - struct { - ngtcp2_frame_chain *next; - ngtcp2_frame_chain_binder *binder; - ngtcp2_frame fr; - }; - - ngtcp2_opl_entry oplent; - }; -}; - -ngtcp2_objalloc_def(frame_chain, ngtcp2_frame_chain, oplent); - -/* - * ngtcp2_bind_frame_chains binds two frame chains |a| and |b| using - * new or existing ngtcp2_frame_chain_binder. |a| might have non-NULL - * a->binder. |b| must not have non-NULL b->binder. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory - */ -int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b, - const ngtcp2_mem *mem); - -/* NGTCP2_MAX_STREAM_DATACNT is the maximum number of ngtcp2_vec that - a ngtcp2_stream can include. */ -#define NGTCP2_MAX_STREAM_DATACNT 256 - -/* NGTCP2_MAX_CRYPTO_DATACNT is the maximum number of ngtcp2_vec that - a ngtcp2_crypto can include. */ -#define NGTCP2_MAX_CRYPTO_DATACNT 8 - -/* - * ngtcp2_frame_chain_new allocates ngtcp2_frame_chain object and - * assigns its pointer to |*pfrc|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. - */ -int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem); - -/* - * ngtcp2_frame_chain_objalloc_new behaves like - * ngtcp2_frame_chain_new, but it uses |objalloc| to allocate the object. - */ -int ngtcp2_frame_chain_objalloc_new(ngtcp2_frame_chain **pfrc, - ngtcp2_objalloc *objalloc); - -/* - * ngtcp2_frame_chain_extralen_new works like ngtcp2_frame_chain_new, - * but it allocates extra memory |extralen| in order to extend - * ngtcp2_frame. - */ -int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen, - const ngtcp2_mem *mem); - -/* - * ngtcp2_frame_chain_stream_datacnt_objalloc_new works like - * ngtcp2_frame_chain_new, but it allocates enough data to store - * additional |datacnt| - 1 ngtcp2_vec object after ngtcp2_stream - * object. If no additional space is required, - * ngtcp2_frame_chain_objalloc_new is called internally. - */ -int ngtcp2_frame_chain_stream_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, - size_t datacnt, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem); - -/* - * ngtcp2_frame_chain_crypto_datacnt_objalloc_new works like - * ngtcp2_frame_chain_new, but it allocates enough data to store - * additional |datacnt| - 1 ngtcp2_vec object after ngtcp2_crypto - * object. If no additional space is required, - * ngtcp2_frame_chain_objalloc_new is called internally. - */ -int ngtcp2_frame_chain_crypto_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, - size_t datacnt, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem); - -int ngtcp2_frame_chain_new_token_objalloc_new(ngtcp2_frame_chain **pfrc, - const ngtcp2_vec *token, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem); - -/* - * ngtcp2_frame_chain_del deallocates |frc|. It also deallocates the - * memory pointed by |frc|. - */ -void ngtcp2_frame_chain_del(ngtcp2_frame_chain *frc, const ngtcp2_mem *mem); - -/* - * ngtcp2_frame_chain_objalloc_del adds |frc| to |objalloc| for reuse. - * It might just delete |frc| depending on the frame type and the size - * of |frc|. - */ -void ngtcp2_frame_chain_objalloc_del(ngtcp2_frame_chain *frc, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem); - -/* - * ngtcp2_frame_chain_init initializes |frc|. - */ -void ngtcp2_frame_chain_init(ngtcp2_frame_chain *frc); - -/* - * ngtcp2_frame_chain_list_objalloc_del adds all ngtcp2_frame_chain - * linked from |frc| to |objalloc| for reuse. Depending on the frame type - * and its size, ngtcp2_frame_chain might be deleted instead. - */ -void ngtcp2_frame_chain_list_objalloc_del(ngtcp2_frame_chain *frc, - ngtcp2_objalloc *objalloc, - const ngtcp2_mem *mem); - /* NGTCP2_RTB_ENTRY_FLAG_NONE indicates that no flag is set. */ #define NGTCP2_RTB_ENTRY_FLAG_NONE 0x00u /* NGTCP2_RTB_ENTRY_FLAG_PROBE indicates that the entry includes a @@ -268,7 +122,7 @@ struct ngtcp2_rtb_entry { }; }; -ngtcp2_objalloc_def(rtb_entry, ngtcp2_rtb_entry, oplent); +ngtcp2_objalloc_decl(rtb_entry, ngtcp2_rtb_entry, oplent); /* * ngtcp2_rtb_entry_new allocates ngtcp2_rtb_entry object, and assigns @@ -347,7 +201,7 @@ typedef struct ngtcp2_rtb { */ void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id, ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc, - ngtcp2_log *log, ngtcp2_qlog *qlog, + int64_t cc_pkt_num, ngtcp2_log *log, ngtcp2_qlog *qlog, ngtcp2_objalloc *rtb_entry_objalloc, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.c index c1ce64a2e57ac4..a61636d188fae5 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.c @@ -38,6 +38,11 @@ uint8_t *ngtcp2_setmem(uint8_t *dest, uint8_t b, size_t n) { return dest + n; } +const void *ngtcp2_get_bytes(void *dest, const void *src, size_t n) { + memcpy(dest, src, n); + return (uint8_t *)src + n; +} + #define LOWER_XDIGITS "0123456789abcdef" uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h index 04735d6dec5c63..deb75e356d70d4 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h @@ -38,6 +38,13 @@ void *ngtcp2_cpymem(void *dest, const void *src, size_t n); * the buffer pointed by |dest|. It returns dest + n; */ uint8_t *ngtcp2_setmem(uint8_t *dest, uint8_t b, size_t n); + +/* + * ngtcp2_get_bytes copies |n| bytes from |src| to |dest|, and returns + * |src| + |n|. + */ +const void *ngtcp2_get_bytes(void *dest, const void *src, size_t n); + /* * ngtcp2_encode_hex encodes |data| of length |len| in hex string. It * writes additional NULL bytes at the end of the buffer. The buffer diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c index 6f20e866ad51c0..c00e86fa8c1afa 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c @@ -30,6 +30,7 @@ #include "ngtcp2_rtb.h" #include "ngtcp2_pkt.h" #include "ngtcp2_vec.h" +#include "ngtcp2_frame_chain.h" static int offset_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { return *(int64_t *)lhs < *(int64_t *)rhs; @@ -46,9 +47,12 @@ void ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags, strm->tx.streamfrq = NULL; strm->tx.offset = 0; strm->tx.max_offset = max_tx_offset; + strm->tx.last_blocked_offset = UINT64_MAX; strm->tx.last_max_stream_data_ts = UINT64_MAX; strm->tx.loss_count = 0; strm->tx.last_lost_pkt_num = -1; + strm->tx.stop_sending_app_error_code = 0; + strm->tx.reset_stream_app_error_code = 0; strm->rx.rob = NULL; strm->rx.cont_offset = 0; strm->rx.last_offset = 0; @@ -120,7 +124,7 @@ uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm) { /* strm_rob_heavily_fragmented returns nonzero if the number of gaps in |rob| exceeds the limit. */ static int strm_rob_heavily_fragmented(ngtcp2_rob *rob) { - return ngtcp2_ksl_len(&rob->gapksl) >= 1000; + return ngtcp2_ksl_len(&rob->gapksl) >= 5000; } int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data, @@ -134,10 +138,7 @@ int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data, } if (strm->rx.cont_offset) { - rv = ngtcp2_rob_remove_prefix(strm->rx.rob, strm->rx.cont_offset); - if (rv != 0) { - return rv; - } + ngtcp2_rob_remove_prefix(strm->rx.rob, strm->rx.cont_offset); } } @@ -148,13 +149,25 @@ int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data, return ngtcp2_rob_push(strm->rx.rob, offset, data, datalen); } -int ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset) { +void ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset) { if (strm->rx.rob == NULL) { strm->rx.cont_offset = offset; - return 0; + return; } - return ngtcp2_rob_remove_prefix(strm->rx.rob, offset); + ngtcp2_rob_remove_prefix(strm->rx.rob, offset); +} + +void ngtcp2_strm_discard_reordered_data(ngtcp2_strm *strm) { + if (strm->rx.rob == NULL) { + return; + } + + strm->rx.cont_offset = ngtcp2_strm_rx_offset(strm); + + ngtcp2_rob_free(strm->rx.rob); + ngtcp2_mem_free(strm->mem, strm->rx.rob); + strm->rx.rob = NULL; } void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags) { @@ -177,7 +190,8 @@ static int strm_streamfrq_init(ngtcp2_strm *strm) { int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc) { int rv; - assert(frc->fr.type == NGTCP2_FRAME_STREAM); + assert(frc->fr.type == NGTCP2_FRAME_STREAM || + frc->fr.type == NGTCP2_FRAME_CRYPTO); assert(frc->next == NULL); if (strm->tx.streamfrq == NULL) { @@ -308,7 +322,7 @@ static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm, assert(nfr->data[0].len > end_base_offset); - nfr->type = NGTCP2_FRAME_STREAM; + nfr->type = fr->type; nfr->flags = 0; nfr->fin = fr->fin; nfr->stream_id = fr->stream_id; @@ -379,18 +393,16 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, fr = &frc->fr.stream; datalen = ngtcp2_vec_len(fr->data, fr->datacnt); - if (left == 0) { - /* datalen could be zero if 0 length STREAM has been sent */ - if (datalen || ngtcp2_ksl_len(strm->tx.streamfrq) > 1) { - rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &fr->offset, frc); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); - return rv; - } - *pfrc = NULL; - return 0; + /* datalen could be zero if 0 length STREAM has been sent */ + if (left == 0 && datalen) { + rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &fr->offset, frc); + if (rv != 0) { + assert(ngtcp2_err_is_fatal(rv)); + ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); + return rv; } + *pfrc = NULL; + return 0; } if (datalen > left) { @@ -412,7 +424,7 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, } nfr = &nfrc->fr.stream; - nfr->type = NGTCP2_FRAME_STREAM; + nfr->type = fr->type; nfr->flags = 0; nfr->fin = fr->fin; nfr->stream_id = fr->stream_id; @@ -696,3 +708,25 @@ void ngtcp2_strm_set_app_error_code(ngtcp2_strm *strm, strm->flags |= NGTCP2_STRM_FLAG_APP_ERROR_CODE_SET; strm->app_error_code = app_error_code; } + +int ngtcp2_strm_require_retransmit_reset_stream(ngtcp2_strm *strm) { + return !ngtcp2_strm_is_all_tx_data_fin_acked(strm); +} + +int ngtcp2_strm_require_retransmit_stop_sending(ngtcp2_strm *strm) { + return !(strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) || + ngtcp2_strm_rx_offset(strm) != strm->rx.last_offset; +} + +int ngtcp2_strm_require_retransmit_max_stream_data(ngtcp2_strm *strm, + ngtcp2_max_stream_data *fr) { + return fr->max_stream_data == strm->rx.max_offset && + !(strm->flags & + (NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_STOP_SENDING)); +} + +int ngtcp2_strm_require_retransmit_stream_data_blocked( + ngtcp2_strm *strm, ngtcp2_stream_data_blocked *fr) { + return fr->offset == strm->tx.max_offset && + !(strm->flags & NGTCP2_STRM_FLAG_SHUT_WR); +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h index 8e3cfe83543509..385302a5eafa9f 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h @@ -36,6 +36,7 @@ #include "ngtcp2_gaptr.h" #include "ngtcp2_ksl.h" #include "ngtcp2_pq.h" +#include "ngtcp2_pkt.h" typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; @@ -49,20 +50,20 @@ typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; #define NGTCP2_STRM_FLAG_SHUT_WR 0x02u #define NGTCP2_STRM_FLAG_SHUT_RDWR \ (NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_SHUT_WR) -/* NGTCP2_STRM_FLAG_SENT_RST indicates that RST_STREAM is sent from - the local endpoint. In this case, NGTCP2_STRM_FLAG_SHUT_WR is also - set. */ -#define NGTCP2_STRM_FLAG_SENT_RST 0x04u -/* NGTCP2_STRM_FLAG_SENT_RST indicates that RST_STREAM is received - from the remote endpoint. In this case, NGTCP2_STRM_FLAG_SHUT_RD - is also set. */ -#define NGTCP2_STRM_FLAG_RECV_RST 0x08u +/* NGTCP2_STRM_FLAG_RESET_STREAM indicates that RESET_STREAM is sent + from the local endpoint. In this case, NGTCP2_STRM_FLAG_SHUT_WR is + also set. */ +#define NGTCP2_STRM_FLAG_RESET_STREAM 0x04u +/* NGTCP2_STRM_FLAG_RESET_STREAM_RECVED indicates that RESET_STREAM is + received from the remote endpoint. In this case, + NGTCP2_STRM_FLAG_SHUT_RD is also set. */ +#define NGTCP2_STRM_FLAG_RESET_STREAM_RECVED 0x08u /* NGTCP2_STRM_FLAG_STOP_SENDING indicates that STOP_SENDING is sent from the local endpoint. */ #define NGTCP2_STRM_FLAG_STOP_SENDING 0x10u -/* NGTCP2_STRM_FLAG_RST_ACKED indicates that the outgoing RST_STREAM - is acknowledged by peer. */ -#define NGTCP2_STRM_FLAG_RST_ACKED 0x20u +/* NGTCP2_STRM_FLAG_RESET_STREAM_ACKED indicates that the outgoing + RESET_STREAM is acknowledged by peer. */ +#define NGTCP2_STRM_FLAG_RESET_STREAM_ACKED 0x20u /* NGTCP2_STRM_FLAG_FIN_ACKED indicates that a STREAM with FIN bit set is acknowledged by a remote endpoint. */ #define NGTCP2_STRM_FLAG_FIN_ACKED 0x40u @@ -75,9 +76,16 @@ typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; In this case, without this flag, we are unable to distinguish assigned value from unassigned one. */ #define NGTCP2_STRM_FLAG_APP_ERROR_CODE_SET 0x100u -/* NGTCP2_STRM_FLAG_STREAM_STOP_SENDING_CALLED is set when - stream_stop_sending callback is called. */ -#define NGTCP2_STRM_FLAG_STREAM_STOP_SENDING_CALLED 0x200u +/* NGTCP2_STRM_FLAG_SEND_STOP_SENDING is set when STOP_SENDING frame + should be sent. */ +#define NGTCP2_STRM_FLAG_SEND_STOP_SENDING 0x200u +/* NGTCP2_STRM_FLAG_SEND_RESET_STREAM is set when RESET_STREAM frame + should be sent. */ +#define NGTCP2_STRM_FLAG_SEND_RESET_STREAM 0x400u +/* NGTCP2_STRM_FLAG_STOP_SENDING_RECVED indicates that STOP_SENDING is + received from the remote endpoint. In this case, + NGTCP2_STRM_FLAG_SHUT_WR is also set. */ +#define NGTCP2_STRM_FLAG_STOP_SENDING_RECVED 0x800u typedef struct ngtcp2_strm ngtcp2_strm; @@ -96,10 +104,10 @@ struct ngtcp2_strm { remote endpoint acknowledges data in out-of-order. After that, acked_offset is used instead. */ uint64_t cont_acked_offset; - /* streamfrq contains STREAM frame for retransmission. The flow - control credits have been paid when they are transmitted first - time. There are no restriction regarding flow control for - retransmission. */ + /* streamfrq contains STREAM or CRYPTO frame for + retransmission. The flow control credits have been paid + when they are transmitted first time. There are no + restriction regarding flow control for retransmission. */ ngtcp2_ksl *streamfrq; /* offset is the next offset of outgoing data. In other words, it is the number of bytes sent in this stream without @@ -108,6 +116,9 @@ struct ngtcp2_strm { /* max_tx_offset is the maximum offset that local endpoint can send for this stream. */ uint64_t max_offset; + /* last_blocked_offset is the largest offset where the + transmission of stream data is blocked. */ + uint64_t last_blocked_offset; /* last_max_stream_data_ts is the timestamp when last MAX_STREAM_DATA frame is sent. */ ngtcp2_tstamp last_max_stream_data_ts; @@ -123,6 +134,12 @@ struct ngtcp2_strm { is counted to loss_count. It is used to avoid to count multiple STREAM frames in one lost packet. */ int64_t last_lost_pkt_num; + /* stop_sending_app_error_code is the application specific + error code that is sent along with STOP_SENDING. */ + uint64_t stop_sending_app_error_code; + /* reset_stream_app_error_code is the application specific + error code that is sent along with RESET_STREAM. */ + uint64_t reset_stream_app_error_code; } tx; struct { @@ -200,11 +217,14 @@ int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data, /* * ngtcp2_strm_update_rx_offset tells that data up to offset bytes are * received in order. - * - * NGTCP2_ERR_NOMEM - * Out of memory */ -int ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset); +void ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset); + +/* + * ngtcp2_strm_discard_reordered_data discards all buffered reordered + * data. + */ +void ngtcp2_strm_discard_reordered_data(ngtcp2_strm *strm); /* * ngtcp2_strm_shutdown shutdowns |strm|. |flags| should be @@ -307,4 +327,30 @@ int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len); */ void ngtcp2_strm_set_app_error_code(ngtcp2_strm *strm, uint64_t app_error_code); +/* + * ngtcp2_strm_require_retransmit_reset_stream returns nonzero if + * RESET_STREAM frame should be retransmitted. + */ +int ngtcp2_strm_require_retransmit_reset_stream(ngtcp2_strm *strm); + +/* + * ngtcp2_strm_require_retransmit_stop_sending returns nonzero if + * STOP_SENDING frame should be retransmitted. + */ +int ngtcp2_strm_require_retransmit_stop_sending(ngtcp2_strm *strm); + +/* + * ngtcp2_strm_require_retransmit_max_stream_data returns nonzero if + * MAX_STREAM_DATA frame should be retransmitted. + */ +int ngtcp2_strm_require_retransmit_max_stream_data(ngtcp2_strm *strm, + ngtcp2_max_stream_data *fr); + +/* + * ngtcp2_strm_require_retransmit_stream_data_blocked returns nonzero + * if STREAM_DATA_BLOCKED frame frame should be retransmitted. + */ +int ngtcp2_strm_require_retransmit_stream_data_blocked( + ngtcp2_strm *strm, ngtcp2_stream_data_blocked *fr); + #endif /* NGTCP2_STRM_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_tstamp.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_tstamp.h new file mode 100644 index 00000000000000..9a210a320dc1ca --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_tstamp.h @@ -0,0 +1,68 @@ +/* + * ngtcp2 + * + * Copyright (c) 2023 ngtcp2 contributors + * + * 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. + */ +#ifndef NGTCP2_TSTAMP_H +#define NGTCP2_TSTAMP_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +/* + * ngtcp2_tstamp_elapsed returns nonzero if at least |d| has passed + * since |base|. |ts| expresses a current time, and must not be + * UINT64_MAX. + * + * If |base| is UINT64_MAX, this function returns 0 because UINT64_MAX + * is an invalid timestamp. Otherwise, if |base| + |d| >= UINT64_MAX, + * this function returns 0. + * + * !ngtcp2_tstamp_elapsed() == ngtcp2_tstamp_not_elapsed() does not + * hold when |base| is UINT64_MAX. If you need nonzero if |base| is + * UINT64_MAX, use !ngtcp2_tstamp_elapsed. Otherwise, use + * ngtcp2_tstamp_not_elapsed. + */ +static inline int ngtcp2_tstamp_elapsed(ngtcp2_tstamp base, ngtcp2_duration d, + ngtcp2_tstamp ts) { + return base != UINT64_MAX && base < UINT64_MAX - d && base + d <= ts; +} + +/* + * ngtcp2_tstamp_not_elapsed returns nonzero if |d| has not passed + * since |base|. |ts| expresses a current time, and must not be + * UINT64_MAX. + * + * If |base| is UINT64_MAX, this function returns 0 because UINT64_MAX + * is an invalid timestamp. Otherwise, if |base| + |d| >= UINT64_MAX, + * this function returns nonzero. + */ +static inline int ngtcp2_tstamp_not_elapsed(ngtcp2_tstamp base, + ngtcp2_duration d, + ngtcp2_tstamp ts) { + return base != UINT64_MAX && (base >= UINT64_MAX - d || base + d > ts); +} + +#endif /* NGTCP2_TSTAMP_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.c new file mode 100644 index 00000000000000..7c7d9ae78e914d --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.c @@ -0,0 +1,71 @@ +/* + * ngtcp2 + * + * Copyright (c) 2022 ngtcp2 contributors + * + * 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 "ngtcp2_unreachable.h" + +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#ifdef WIN32 +# include +#endif /* WIN32 */ + +void ngtcp2_unreachable_fail(const char *file, int line, const char *func) { + char *buf; + size_t buflen; + int rv; + +#define NGTCP2_UNREACHABLE_TEMPLATE "%s:%d %s: Unreachable.\n" + + rv = snprintf(NULL, 0, NGTCP2_UNREACHABLE_TEMPLATE, file, line, func); + if (rv < 0) { + abort(); + } + + /* here we explicitly use system malloc */ + buflen = (size_t)rv + 1; + buf = malloc(buflen); + if (buf == NULL) { + abort(); + } + + rv = snprintf(buf, buflen, NGTCP2_UNREACHABLE_TEMPLATE, file, line, func); + if (rv < 0) { + abort(); + } + +#ifndef WIN32 + while (write(STDERR_FILENO, buf, (size_t)rv) == -1 && errno == EINTR) + ; +#else /* WIN32 */ + _write(_fileno(stderr), buf, (unsigned int)rv); +#endif /* WIN32 */ + + free(buf); + + abort(); +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.h new file mode 100644 index 00000000000000..a5276fd505463f --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.h @@ -0,0 +1,52 @@ +/* + * ngtcp2 + * + * Copyright (c) 2022 ngtcp2 contributors + * + * 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. + */ +#ifndef NGTCP2_UNREACHABLE_H +#define NGTCP2_UNREACHABLE_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +#ifdef __FILE_NAME__ +# define NGTCP2_FILE_NAME __FILE_NAME__ +#else /* !__FILE_NAME__ */ +# define NGTCP2_FILE_NAME "(file)" +#endif /* !__FILE_NAME__ */ + +#define ngtcp2_unreachable() \ + ngtcp2_unreachable_fail(NGTCP2_FILE_NAME, __LINE__, __func__) + +#ifdef _MSC_VER +__declspec(noreturn) +#endif /* _MSC_VER */ + void ngtcp2_unreachable_fail(const char *file, int line, const char *func) +#ifndef _MSC_VER + __attribute__((noreturn)) +#endif /* !_MSC_VER */ + ; + +#endif /* NGTCP2_UNREACHABLE_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c index 257332e27a2abe..dbc7b668042695 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c @@ -145,7 +145,7 @@ ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *src, size_t *psrccnt, ngtcp2_vec *dst, size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, size_t *psrccnt, size_t left, size_t maxcnt) { size_t orig_left = left; - size_t i; + size_t i = 0; ngtcp2_vec *a, *b; assert(maxcnt); @@ -158,12 +158,7 @@ size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, a = &dst[0]; b = &src[0]; - if (left >= b->len) { - *a = *b; - ++*pdstcnt; - left -= b->len; - i = 1; - } else { + if (left < b->len) { a->len = left; a->base = b->base; @@ -172,41 +167,43 @@ size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, return left; } - } else { - i = 0; + + *a = *b; + ++*pdstcnt; + left -= b->len; + i = 1; } for (; left && i < *psrccnt; ++i) { a = &dst[*pdstcnt - 1]; b = &src[i]; - if (left >= b->len) { + if (left < b->len) { if (a->base + a->len == b->base) { - a->len += b->len; + a->len += left; } else if (*pdstcnt == maxcnt) { break; } else { - dst[(*pdstcnt)++] = *b; + dst[*pdstcnt].len = left; + dst[*pdstcnt].base = b->base; + ++*pdstcnt; } - left -= b->len; - continue; + + b->len -= left; + b->base += left; + left = 0; + + break; } if (a->base + a->len == b->base) { - a->len += left; + a->len += b->len; } else if (*pdstcnt == maxcnt) { break; } else { - dst[*pdstcnt].len = left; - dst[*pdstcnt].base = b->base; - ++*pdstcnt; + dst[(*pdstcnt)++] = *b; } - - b->len -= left; - b->base += left; - left = 0; - - break; + left -= b->len; } memmove(src, src + i, sizeof(ngtcp2_vec) * (*psrccnt - i)); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_window_filter.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_window_filter.c index 71c816e4d3d815..39f3d408a741ba 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_window_filter.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_window_filter.c @@ -39,12 +39,16 @@ void ngtcp2_window_filter_init(ngtcp2_window_filter *wf, uint64_t window_length) { wf->window_length = window_length; - memset(wf->estimates, 0, sizeof(wf->estimates)); + memset(wf->estimates, 0xff, sizeof(wf->estimates)); } void ngtcp2_window_filter_update(ngtcp2_window_filter *wf, uint64_t new_sample, uint64_t new_time) { - if (wf->estimates[0].sample == 0 || new_sample > wf->estimates[0].sample || + /* Reset all estimates if they have not yet been initialized, if new + sample is a new best, or if the newest recorded estimate is too + old. */ + if (wf->estimates[0].sample == UINT64_MAX || + new_sample > wf->estimates[0].sample || new_time - wf->estimates[2].time > wf->window_length) { ngtcp2_window_filter_reset(wf, new_sample, new_time); return; @@ -59,12 +63,19 @@ void ngtcp2_window_filter_update(ngtcp2_window_filter *wf, uint64_t new_sample, wf->estimates[2].time = new_time; } + /* Expire and update estimates as necessary. */ if (new_time - wf->estimates[0].time > wf->window_length) { + /* The best estimate hasn't been updated for an entire window, so + promote second and third best estimates. */ wf->estimates[0] = wf->estimates[1]; wf->estimates[1] = wf->estimates[2]; wf->estimates[2].sample = new_sample; wf->estimates[2].time = new_time; + /* Need to iterate one more time. Check if the new best estimate + is outside the window as well, since it may also have been + recorded a long time ago. Don't need to iterate once more + since we cover that case at the beginning of the method. */ if (new_time - wf->estimates[0].time > wf->window_length) { wf->estimates[0] = wf->estimates[1]; wf->estimates[1] = wf->estimates[2]; @@ -74,6 +85,9 @@ void ngtcp2_window_filter_update(ngtcp2_window_filter *wf, uint64_t new_sample, if (wf->estimates[1].sample == wf->estimates[0].sample && new_time - wf->estimates[1].time > wf->window_length >> 2) { + /* A quarter of the window has passed without a better sample, so + the second-best estimate is taken from the second quarter of + the window. */ wf->estimates[2].sample = new_sample; wf->estimates[2].time = new_time; wf->estimates[1] = wf->estimates[2]; @@ -82,6 +96,9 @@ void ngtcp2_window_filter_update(ngtcp2_window_filter *wf, uint64_t new_sample, if (wf->estimates[2].sample == wf->estimates[1].sample && new_time - wf->estimates[2].time > wf->window_length >> 1) { + /* We've passed a half of the window without a better estimate, so + take a third-best estimate from the second half of the + window. */ wf->estimates[2].sample = new_sample; wf->estimates[2].time = new_time; } diff --git a/deps/npm/bin/npm b/deps/npm/bin/npm index 7f210b936e1fad..027dc9d128d22c 100755 --- a/deps/npm/bin/npm +++ b/deps/npm/bin/npm @@ -41,8 +41,9 @@ if [ $? -ne 0 ]; then fi no_node_dir fi +NPM_PREFIX_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-prefix.js" NPM_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-cli.js" -NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` +NPM_PREFIX=`"$NODE_EXE" "$NPM_PREFIX_JS"` if [ $? -ne 0 ]; then no_node_dir fi diff --git a/deps/npm/bin/npm-prefix.js b/deps/npm/bin/npm-prefix.js new file mode 100755 index 00000000000000..3ff43de0dd84de --- /dev/null +++ b/deps/npm/bin/npm-prefix.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node +// This is a single-use bin to help windows discover the proper prefix for npm +// without having to load all of npm first +// It does not accept argv params + +const path = require('path') +const Config = require('@npmcli/config') +const { definitions, flatten, shorthands } = require('@npmcli/config/lib/definitions') +const config = new Config({ + npmPath: path.dirname(__dirname), + // argv is explicitly not looked at since prefix is not something that can be changed via argv + argv: [], + definitions, + flatten, + shorthands, + excludeNpmCwd: false, +}) + +async function main () { + try { + await config.load() + // eslint-disable-next-line no-console + console.log(config.globalPrefix) + } catch (err) { + // eslint-disable-next-line no-console + console.error(err) + process.exit(1) + } +} +main() diff --git a/deps/npm/bin/npm.cmd b/deps/npm/bin/npm.cmd index f111c59d1efb6e..1a02e83ac365a9 100755 --- a/deps/npm/bin/npm.cmd +++ b/deps/npm/bin/npm.cmd @@ -8,8 +8,9 @@ IF NOT EXIST "%NODE_EXE%" ( SET "NODE_EXE=node" ) +SET "NPM_PREFIX_JS=%~dp0\node_modules\npm\bin\npm-prefix.js" SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js" -FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO ( +FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_PREFIX_JS%"') DO ( SET "NPM_PREFIX_NPM_CLI_JS=%%F\node_modules\npm\bin\npm-cli.js" ) IF EXIST "%NPM_PREFIX_NPM_CLI_JS%" ( diff --git a/deps/npm/bin/npm.ps1 b/deps/npm/bin/npm.ps1 index f2f236adc23db2..04a1fd478ef9dd 100644 --- a/deps/npm/bin/npm.ps1 +++ b/deps/npm/bin/npm.ps1 @@ -1,35 +1,32 @@ #!/usr/bin/env pwsh -$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent -$exe="" -if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { - # Fix case when both the Windows and Linux builds of Node - # are installed in the same directory - $exe=".exe" +$NODE_EXE="$PSScriptRoot/node.exe" +if (-not (Test-Path $NODE_EXE)) { + $NODE_EXE="$PSScriptRoot/node" } -$ret=0 - -$nodeexe = "node$exe" -$nodebin = $(Get-Command $nodeexe -ErrorAction SilentlyContinue -ErrorVariable F).Source -if ($nodebin -eq $null) { - Write-Host "$nodeexe not found." - exit 1 +if (-not (Test-Path $NODE_EXE)) { + $NODE_EXE="node" } -$nodedir = $(New-Object -ComObject Scripting.FileSystemObject).GetFile("$nodebin").ParentFolder.Path -$npmclijs="$nodedir/node_modules/npm/bin/npm-cli.js" -$npmprefix=(& $nodeexe $npmclijs prefix -g) +$NPM_PREFIX_JS="$PSScriptRoot/node_modules/npm/bin/npm-prefix.js" +$NPM_CLI_JS="$PSScriptRoot/node_modules/npm/bin/npm-cli.js" +$NPM_PREFIX=(& $NODE_EXE $NPM_PREFIX_JS) + if ($LASTEXITCODE -ne 0) { Write-Host "Could not determine Node.js install directory" exit 1 } -$npmprefixclijs="$npmprefix/node_modules/npm/bin/npm-cli.js" + +$NPM_PREFIX_NPM_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npm-cli.js" +if (Test-Path $NPM_PREFIX_NPM_CLI_JS) { + $NPM_CLI_JS=$NPM_PREFIX_NPM_CLI_JS +} # Support pipeline input if ($MyInvocation.ExpectingInput) { - $input | & $nodeexe $npmprefixclijs $args + $input | & $NODE_EXE $NPM_CLI_JS $args } else { - & $nodeexe $npmprefixclijs $args + & $NODE_EXE $NPM_CLI_JS $args } -$ret=$LASTEXITCODE -exit $ret + +exit $LASTEXITCODE diff --git a/deps/npm/bin/npx b/deps/npm/bin/npx index 719ff8ecdc19b9..b8619ee9c5e37a 100755 --- a/deps/npm/bin/npx +++ b/deps/npm/bin/npx @@ -41,9 +41,9 @@ if [ $? -ne 0 ]; then fi no_node_dir fi -NPM_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-cli.js" +NPM_PREFIX_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-prefix.js" NPX_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npx-cli.js" -NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` +NPM_PREFIX=`"$NODE_EXE" "$NPM_PREFIX_JS"` if [ $? -ne 0 ]; then no_node_dir fi diff --git a/deps/npm/bin/npx-cli.js b/deps/npm/bin/npx-cli.js index 17d96fb26267c7..e2e1b87906abe0 100755 --- a/deps/npm/bin/npx-cli.js +++ b/deps/npm/bin/npx-cli.js @@ -26,7 +26,7 @@ const removed = new Set([ const { definitions, shorthands } = require('@npmcli/config/lib/definitions') const npmSwitches = Object.entries(definitions) - .filter(([key, { type }]) => type === Boolean || + .filter(([, { type }]) => type === Boolean || (Array.isArray(type) && type.includes(Boolean))) .map(([key]) => key) diff --git a/deps/npm/bin/npx.cmd b/deps/npm/bin/npx.cmd index b79518ec505409..0f02d2dc498544 100755 --- a/deps/npm/bin/npx.cmd +++ b/deps/npm/bin/npx.cmd @@ -8,9 +8,9 @@ IF NOT EXIST "%NODE_EXE%" ( SET "NODE_EXE=node" ) -SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js" +SET "NPM_PREFIX_JS=%~dp0\node_modules\npm\bin\npm-prefix.js" SET "NPX_CLI_JS=%~dp0\node_modules\npm\bin\npx-cli.js" -FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO ( +FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_PREFIX_JS%"') DO ( SET "NPM_PREFIX_NPX_CLI_JS=%%F\node_modules\npm\bin\npx-cli.js" ) IF EXIST "%NPM_PREFIX_NPX_CLI_JS%" ( diff --git a/deps/npm/bin/npx.ps1 b/deps/npm/bin/npx.ps1 index 437e2a7b74c3af..28dae51b22ca93 100644 --- a/deps/npm/bin/npx.ps1 +++ b/deps/npm/bin/npx.ps1 @@ -1,35 +1,32 @@ #!/usr/bin/env pwsh -$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent -$exe="" -if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { - # Fix case when both the Windows and Linux builds of Node - # are installed in the same directory - $exe=".exe" +$NODE_EXE="$PSScriptRoot/node.exe" +if (-not (Test-Path $NODE_EXE)) { + $NODE_EXE="$PSScriptRoot/node" } -$ret=0 - -$nodeexe = "node$exe" -$nodebin = $(Get-Command $nodeexe -ErrorAction SilentlyContinue -ErrorVariable F).Source -if ($nodebin -eq $null) { - Write-Host "$nodeexe not found." - exit 1 +if (-not (Test-Path $NODE_EXE)) { + $NODE_EXE="node" } -$nodedir = $(New-Object -ComObject Scripting.FileSystemObject).GetFile("$nodebin").ParentFolder.Path -$npmclijs="$nodedir/node_modules/npm/bin/npm-cli.js" -$npmprefix=(& $nodeexe $npmclijs prefix -g) +$NPM_PREFIX_JS="$PSScriptRoot/node_modules/npm/bin/npm-prefix.js" +$NPX_CLI_JS="$PSScriptRoot/node_modules/npm/bin/npx-cli.js" +$NPM_PREFIX=(& $NODE_EXE $NPM_PREFIX_JS) + if ($LASTEXITCODE -ne 0) { Write-Host "Could not determine Node.js install directory" exit 1 } -$npmprefixclijs="$npmprefix/node_modules/npm/bin/npx-cli.js" + +$NPM_PREFIX_NPX_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npx-cli.js" +if (Test-Path $NPM_PREFIX_NPX_CLI_JS) { + $NPX_CLI_JS=$NPM_PREFIX_NPX_CLI_JS +} # Support pipeline input if ($MyInvocation.ExpectingInput) { - $input | & $nodeexe $npmprefixclijs $args + $input | & $NODE_EXE $NPX_CLI_JS $args } else { - & $nodeexe $npmprefixclijs $args + & $NODE_EXE $NPX_CLI_JS $args } -$ret=$LASTEXITCODE -exit $ret + +exit $LASTEXITCODE diff --git a/deps/npm/docs/content/commands/npm-access.md b/deps/npm/docs/content/commands/npm-access.md index 9e9f385fe386de..e08030deba076d 100644 --- a/deps/npm/docs/content/commands/npm-access.md +++ b/deps/npm/docs/content/commands/npm-access.md @@ -7,7 +7,7 @@ description: Set access level on published packages ### Synopsis ```bash -npm access list packages [|| [] +npm access list packages [||] [] npm access list collaborators [ []] npm access get status [] npm access set status=public|private [] diff --git a/deps/npm/docs/content/commands/npm-audit.md b/deps/npm/docs/content/commands/npm-audit.md index 7d83fd582f3fd3..a7e0db7474315a 100644 --- a/deps/npm/docs/content/commands/npm-audit.md +++ b/deps/npm/docs/content/commands/npm-audit.md @@ -49,6 +49,13 @@ Registry signatures can be verified using the following `audit` command: $ npm audit signatures ``` +The `audit signatures` command will also verify the provenance attestations of +downloaded packages. Because provenance attestations are such a new feature, +security features may be added to (or changed in) the attestation format over +time. To ensure that you're always able to verify attestation signatures check +that you're running the latest version of the npm CLI. Please note this often +means updating npm beyond the version that ships with Node.js. + The npm CLI supports registry signatures and signing keys provided by any registry if the following conventions are followed: 1. Signatures are provided in the package's `packument` in each published version within the `dist` object: @@ -83,13 +90,13 @@ The `sig` is generated using the following template: `${package.name}@${package. Keys response: -- `expires`: null or a simplified extended [ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601"): `YYYY-MM-DDTHH:mm:ss.sssZ` +- `expires`: null or a simplified extended [ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601): `YYYY-MM-DDTHH:mm:ss.sssZ` - `keydid`: sha256 fingerprint of the public key - `keytype`: only `ecdsa-sha2-nistp256` is currently supported by the npm CLI - `scheme`: only `ecdsa-sha2-nistp256` is currently supported by the npm CLI - `key`: base64 encoded public key -See this [example key's response from the public npm registry](https://registry.npmjs.org/-/npm/v1/keys"). +See this [example key's response from the public npm registry](https://registry.npmjs.org/-/npm/v1/keys). ### Audit Endpoints diff --git a/deps/npm/docs/content/commands/npm-doctor.md b/deps/npm/docs/content/commands/npm-doctor.md index b36ec3883be03a..a96036a773b2a1 100644 --- a/deps/npm/docs/content/commands/npm-doctor.md +++ b/deps/npm/docs/content/commands/npm-doctor.md @@ -7,7 +7,7 @@ description: Check the health of your npm environment ### Synopsis ```bash -npm doctor [ping] [registry] [versions] [environment] [permissions] [cache] +npm doctor [connection] [registry] [versions] [environment] [permissions] [cache] ``` Note: This command is unaware of workspaces. @@ -38,20 +38,21 @@ there are any recommended changes, it will display them. By default npm runs all of these checks. You can limit what checks are ran by specifying them as extra arguments. -#### `npm ping` +#### `Connecting to the registry` By default, npm installs from the primary npm registry, -`registry.npmjs.org`. `npm doctor` hits a special ping endpoint within the -registry. This can also be checked with `npm ping`. If this check fails, -you may be using a proxy that needs to be configured, or may need to talk -to your IT staff to get access over HTTPS to `registry.npmjs.org`. +`registry.npmjs.org`. `npm doctor` hits a special connection testing +endpoint within the registry. This can also be checked with `npm ping`. +If this check fails, you may be using a proxy that needs to be +configured, or may need to talk to your IT staff to get access over +HTTPS to `registry.npmjs.org`. This check is done against whichever registry you've configured (you can see what that is by running `npm config get registry`), and if you're using a private registry that doesn't support the `/whoami` endpoint supported by the primary registry, this check may fail. -#### `npm -v` +#### `Checking npm version` While Node.js may come bundled with a particular version of npm, it's the policy of the CLI team that we recommend all users run `npm@latest` if they @@ -61,7 +62,7 @@ support releases typically only receive critical security and regression fixes. The team believes that the latest tested version of npm is almost always likely to be the most functional and defect-free version of npm. -#### `node -v` +#### `Checking node version` For most users, in most circumstances, the best version of Node will be the latest long-term support (LTS) release. Those of you who want access to new @@ -70,7 +71,7 @@ be running a newer version, and some may be required to run an older version of Node because of enterprise change control policies. That's OK! But in general, the npm team recommends that most users run Node.js LTS. -#### `npm config get registry` +#### `Checking configured npm registry` You may be installing from private package registries for your project or company. That's great! Others may be following tutorials or StackOverflow @@ -79,7 +80,7 @@ Sometimes, this may entail changing the registry you're pointing at. This part of `npm doctor` just lets you, and maybe whoever's helping you with support, know that you're not using the default registry. -#### `which git` +#### `Checking for git executable in PATH` While it's documented in the README, it may not be obvious that npm needs Git installed to do many of the things that it does. Also, in some cases diff --git a/deps/npm/docs/content/commands/npm-ls.md b/deps/npm/docs/content/commands/npm-ls.md index d21af25d6c783b..89a4bd3604ce40 100644 --- a/deps/npm/docs/content/commands/npm-ls.md +++ b/deps/npm/docs/content/commands/npm-ls.md @@ -27,7 +27,7 @@ packages will *also* show the paths to the specified packages. For example, running `npm ls promzard` in npm's source tree will show: ```bash -npm@10.5.0 /path/to/npm +npm@10.7.0 /path/to/npm └─┬ init-package-json@0.0.4 └── promzard@0.1.5 ``` diff --git a/deps/npm/docs/content/commands/npm-profile.md b/deps/npm/docs/content/commands/npm-profile.md index d048532c98d452..2468d6c87faf60 100644 --- a/deps/npm/docs/content/commands/npm-profile.md +++ b/deps/npm/docs/content/commands/npm-profile.md @@ -24,28 +24,17 @@ support this interface. * `npm profile get []`: Display all of the properties of your profile, or one or more specific properties. It looks like: -```bash -+-----------------+---------------------------+ -| name | example | -+-----------------+---------------------------+ -| email | me@example.com (verified) | -+-----------------+---------------------------+ -| two factor auth | auth-and-writes | -+-----------------+---------------------------+ -| fullname | Example User | -+-----------------+---------------------------+ -| homepage | | -+-----------------+---------------------------+ -| freenode | | -+-----------------+---------------------------+ -| twitter | | -+-----------------+---------------------------+ -| github | | -+-----------------+---------------------------+ -| created | 2015-02-26T01:38:35.892Z | -+-----------------+---------------------------+ -| updated | 2017-10-02T21:29:45.922Z | -+-----------------+---------------------------+ +``` +name: example +email: e@example.com (verified) +two-factor auth: auth-and-writes +fullname: Example User +homepage: +freenode: +twitter: +github: +created: 2015-02-26T01:38:35.892Z +updated: 2017-10-02T21:29:45.922Z ``` * `npm profile set `: Set the value of a profile diff --git a/deps/npm/docs/content/commands/npm-search.md b/deps/npm/docs/content/commands/npm-search.md index df5cc51b417ea2..4e4bbf58aec39e 100644 --- a/deps/npm/docs/content/commands/npm-search.md +++ b/deps/npm/docs/content/commands/npm-search.md @@ -7,7 +7,7 @@ description: Search for packages ### Synopsis ```bash -npm search [search terms ...] +npm search [ ...] aliases: find, s, se ``` @@ -39,15 +39,6 @@ expression characters in most shells.) ### Configuration -#### `long` - -* Default: false -* Type: Boolean - -Show extended information in `ls`, `search`, and `help-search`. - - - #### `json` * Default: false @@ -91,6 +82,16 @@ Show the description in `npm search` +#### `searchlimit` + +* Default: 20 +* Type: Number + +Number of items to limit search results to. Will not apply at all to legacy +searches. + + + #### `searchopts` * Default: "" diff --git a/deps/npm/docs/content/commands/npm-token.md b/deps/npm/docs/content/commands/npm-token.md index a17193d5fe8d05..771da7d9857534 100644 --- a/deps/npm/docs/content/commands/npm-token.md +++ b/deps/npm/docs/content/commands/npm-token.md @@ -22,24 +22,14 @@ This lets you list, create and revoke authentication tokens. Shows a table of all active authentication tokens. You can request this as JSON with `--json` or tab-separated values with `--parseable`. -```bash -+--------+---------+------------+----------+----------------+ -| id | token | created | read-only | CIDR whitelist | -+--------+---------+------------+----------+----------------+ -| 7f3134 | 1fa9ba… | 2017-10-02 | yes | | -+--------+---------+------------+----------+----------------+ -| c03241 | af7aef… | 2017-10-02 | no | 192.168.0.1/24 | -+--------+---------+------------+----------+----------------+ -| e0cf92 | 3a436a… | 2017-10-02 | no | | -+--------+---------+------------+----------+----------------+ -| 63eb9d | 74ef35… | 2017-09-28 | no | | -+--------+---------+------------+----------+----------------+ -| 2daaa8 | cbad5f… | 2017-09-26 | no | | -+--------+---------+------------+----------+----------------+ -| 68c2fe | 127e51… | 2017-09-23 | no | | -+--------+---------+------------+----------+----------------+ -| 6334e1 | 1dadd1… | 2017-09-23 | no | | -+--------+---------+------------+----------+----------------+ +``` +Read only token npm_1f… with id 7f3134 created 2017-10-21 + +Publish token npm_af… with id c03241 created 2017-10-02 +with IP Whitelist: 192.168.0.1/24 + +Publish token npm_… with id e0cf92 created 2017-10-02 + ``` * `npm token create [--read-only] [--cidr=]`: @@ -55,16 +45,8 @@ This lets you list, create and revoke authentication tokens. website](https://docs.npmjs.com/creating-and-viewing-access-tokens) for more information on generating automation tokens. -```bash -+----------------+--------------------------------------+ -| token | a73c9572-f1b9-8983-983d-ba3ac3cc913d | -+----------------+--------------------------------------+ -| cidr_whitelist | | -+----------------+--------------------------------------+ -| readonly | false | -+----------------+--------------------------------------+ -| created | 2017-10-02T07:52:24.838Z | -+----------------+--------------------------------------+ +``` +Created publish token a73c9572-f1b9-8983-983d-ba3ac3cc913d ``` * `npm token revoke `: diff --git a/deps/npm/docs/content/commands/npm.md b/deps/npm/docs/content/commands/npm.md index 3b14832d96da56..eb9a779cfdee9d 100644 --- a/deps/npm/docs/content/commands/npm.md +++ b/deps/npm/docs/content/commands/npm.md @@ -14,7 +14,7 @@ Note: This command is unaware of workspaces. ### Version -10.5.0 +10.7.0 ### Description diff --git a/deps/npm/docs/content/configuring-npm/package-json.md b/deps/npm/docs/content/configuring-npm/package-json.md index c857fc8cb8ce5c..43037477491e35 100644 --- a/deps/npm/docs/content/configuring-npm/package-json.md +++ b/deps/npm/docs/content/configuring-npm/package-json.md @@ -40,7 +40,7 @@ Some tips: * Don't use the same name as a core Node module. * Don't put "js" or "node" in the name. It's assumed that it's js, since you're writing a package.json file, and you can specify the engine using - the "engines" field. (See below.) + the "[engines](#engines)" field. (See below.) * The name will probably be passed as an argument to require(), so it should be something short, but also reasonably descriptive. * You may want to check the npm registry to see if there's something by @@ -75,7 +75,7 @@ your package as it's listed in `npm search`. ### homepage -The url to the project homepage. +The URL to the project homepage. Example: @@ -85,7 +85,7 @@ Example: ### bugs -The url to your project's issue tracker and / or the email address to which +The URL to your project's issue tracker and / or the email address to which issues should be reported. These are helpful for people who encounter issues with your package. @@ -101,10 +101,10 @@ It should look like this: ``` You can specify either one or both values. If you want to provide only a -url, you can specify the value for "bugs" as a simple string instead of an +URL, you can specify the value for "bugs" as a simple string instead of an object. -If a url is provided, it will be used by the `npm bugs` command. +If a URL is provided, it will be used by the `npm bugs` command. ### license @@ -511,9 +511,9 @@ Do it like this: } ``` -The URL should be a publicly available (perhaps read-only) url that can be +The URL should be a publicly available (perhaps read-only) URL that can be handed directly to a VCS program without any modification. It should not -be a url to an html project page that you put in your browser. It's for +be a URL to an html project page that you put in your browser. It's for computers. For GitHub, GitHub gist, Bitbucket, or GitLab repositories you can use the @@ -636,7 +636,7 @@ install time. #### Git URLs as Dependencies -Git urls are of the form: +Git URLs are of the form: ```bash ://[[:]@][:][:][/][# | #semver:] @@ -683,7 +683,7 @@ will be rebuilt for every installation. #### GitHub URLs -As of version 1.1.65, you can refer to GitHub urls as just "foo": +As of version 1.1.65, you can refer to GitHub URLs as just "foo": "user/foo-project". Just as with git URLs, a `commit-ish` suffix can be included. For example: @@ -889,7 +889,7 @@ none. If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the `optionalDependencies` object. This is a map of package name to version or -url, just like the `dependencies` object. The difference is that build +URL, just like the `dependencies` object. The difference is that build failures do not cause installation to fail. Running `npm install --omit=optional` will prevent these dependencies from being installed. @@ -928,6 +928,13 @@ Overrides provide a way to replace a package in your dependency tree with another version, or another package entirely. These changes can be scoped as specific or as vague as desired. +Overrides are only considered in the root `package.json` file for a project. +Overrides in installed dependencies (including +[workspaces](/using-npm/workspaces)) are not considered in dependency tree +resolution. Published packages may dictate their resolutions by pinning +dependencies or using an +[`npm-shrinkwrap.json`](/configuring-npm/npm-shrinkwrap-json) file. + To make sure the package `foo` is always installed as version `1.0.0` no matter what version your dependencies rely on: diff --git a/deps/npm/docs/content/configuring-npm/package-lock-json.md b/deps/npm/docs/content/configuring-npm/package-lock-json.md index d540dd0e7228b8..f3b012175fa0ec 100644 --- a/deps/npm/docs/content/configuring-npm/package-lock-json.md +++ b/deps/npm/docs/content/configuring-npm/package-lock-json.md @@ -31,6 +31,8 @@ various purposes: picture of the package tree, reducing the need to read `package.json` files, and allowing for significant performance improvements. +When `npm` creates or updates `package-lock.json`, it will infer line endings and indentation from `package.json` so that the formatting of both files matches. + ### `package-lock.json` vs `npm-shrinkwrap.json` Both of these files have the same format, and perform similar functions in diff --git a/deps/npm/docs/lib/index.js b/deps/npm/docs/lib/index.js index 5d4ae7af3457bb..5f8501ead27b83 100644 --- a/deps/npm/docs/lib/index.js +++ b/deps/npm/docs/lib/index.js @@ -119,7 +119,7 @@ const replaceConfig = (src, { path }) => { } const allConfig = Object.entries(definitions).sort(sort) - .map(([_, def]) => def.describe()) + .map(([, def]) => def.describe()) .join('\n\n') return src.replace(replacer, allConfig) diff --git a/deps/npm/docs/output/commands/npm-access.html b/deps/npm/docs/output/commands/npm-access.html index aa89c3e0068fcf..3263227f8afd5f 100644 --- a/deps/npm/docs/output/commands/npm-access.html +++ b/deps/npm/docs/output/commands/npm-access.html @@ -146,7 +146,7 @@

Table of contents

Synopsis

-
npm access list packages [<user>|<scope>|<scope:team> [<package>]
+
npm access list packages [<user>|<scope>|<scope:team>] [<package>]
 npm access list collaborators [<package> [<user>]]
 npm access get status [<package>]
 npm access set status=public|private [<package>]
diff --git a/deps/npm/docs/output/commands/npm-audit.html b/deps/npm/docs/output/commands/npm-audit.html
index 7ba3101ded64a8..5e8e9d66bb2e59 100644
--- a/deps/npm/docs/output/commands/npm-audit.html
+++ b/deps/npm/docs/output/commands/npm-audit.html
@@ -174,6 +174,12 @@ 

Audit Signatures

Registry signatures can be verified using the following audit command:

$ npm audit signatures
 
+

The audit signatures command will also verify the provenance attestations of +downloaded packages. Because provenance attestations are such a new feature, +security features may be added to (or changed in) the attestation format over +time. To ensure that you're always able to verify attestation signatures check +that you're running the latest version of the npm CLI. Please note this often +means updating npm beyond the version that ships with Node.js.

The npm CLI supports registry signatures and signing keys provided by any registry if the following conventions are followed:

  1. Signatures are provided in the package's packument in each published version within the dist object:
  2. @@ -203,13 +209,13 @@

    Audit Signatures

Keys response:

    -
  • expires: null or a simplified extended ISO 8601 format: YYYY-MM-DDTHH:mm:ss.sssZ
  • +
  • expires: null or a simplified extended ISO 8601 format: YYYY-MM-DDTHH:mm:ss.sssZ
  • keydid: sha256 fingerprint of the public key
  • keytype: only ecdsa-sha2-nistp256 is currently supported by the npm CLI
  • scheme: only ecdsa-sha2-nistp256 is currently supported by the npm CLI
  • key: base64 encoded public key
-

See this example key's response from the public npm registry.

+

See this example key's response from the public npm registry.

Audit Endpoints

There are two audit endpoints that npm may use to fetch vulnerability information: the Bulk Advisory endpoint and the Quick Audit endpoint.

diff --git a/deps/npm/docs/output/commands/npm-doctor.html b/deps/npm/docs/output/commands/npm-doctor.html index d63f33389af97e..fc4f7643fad896 100644 --- a/deps/npm/docs/output/commands/npm-doctor.html +++ b/deps/npm/docs/output/commands/npm-doctor.html @@ -142,11 +142,11 @@

npm-doctor

Table of contents

- +

Synopsis

-
npm doctor [ping] [registry] [versions] [environment] [permissions] [cache]
+
npm doctor [connection] [registry] [versions] [environment] [permissions] [cache]
 

Note: This command is unaware of workspaces.

Description

@@ -171,17 +171,18 @@

Description

there are any recommended changes, it will display them. By default npm runs all of these checks. You can limit what checks are ran by specifying them as extra arguments.

-

npm ping

+

Connecting to the registry

By default, npm installs from the primary npm registry, -registry.npmjs.org. npm doctor hits a special ping endpoint within the -registry. This can also be checked with npm ping. If this check fails, -you may be using a proxy that needs to be configured, or may need to talk -to your IT staff to get access over HTTPS to registry.npmjs.org.

+registry.npmjs.org. npm doctor hits a special connection testing +endpoint within the registry. This can also be checked with npm ping. +If this check fails, you may be using a proxy that needs to be +configured, or may need to talk to your IT staff to get access over +HTTPS to registry.npmjs.org.

This check is done against whichever registry you've configured (you can see what that is by running npm config get registry), and if you're using a private registry that doesn't support the /whoami endpoint supported by the primary registry, this check may fail.

-

npm -v

+

Checking npm version

While Node.js may come bundled with a particular version of npm, it's the policy of the CLI team that we recommend all users run npm@latest if they can. As the CLI is maintained by a small team of contributors, there are @@ -189,21 +190,21 @@

npm -v

support releases typically only receive critical security and regression fixes. The team believes that the latest tested version of npm is almost always likely to be the most functional and defect-free version of npm.

-

node -v

+

Checking node version

For most users, in most circumstances, the best version of Node will be the latest long-term support (LTS) release. Those of you who want access to new ECMAscript features or bleeding-edge changes to Node's standard library may be running a newer version, and some may be required to run an older version of Node because of enterprise change control policies. That's OK! But in general, the npm team recommends that most users run Node.js LTS.

-

npm config get registry

+

Checking configured npm registry

You may be installing from private package registries for your project or company. That's great! Others may be following tutorials or StackOverflow questions in an effort to troubleshoot problems you may be having. Sometimes, this may entail changing the registry you're pointing at. This part of npm doctor just lets you, and maybe whoever's helping you with support, know that you're not using the default registry.

-

which git

+

Checking for git executable in PATH

While it's documented in the README, it may not be obvious that npm needs Git installed to do many of the things that it does. Also, in some cases – especially on Windows – you may have Git set up in such a way that it's diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html index d6e376a0bf2f8a..be2287797a8f30 100644 --- a/deps/npm/docs/output/commands/npm-ls.html +++ b/deps/npm/docs/output/commands/npm-ls.html @@ -160,7 +160,7 @@

Description

the results to only the paths to the packages named. Note that nested packages will also show the paths to the specified packages. For example, running npm ls promzard in npm's source tree will show:

-
npm@10.5.0 /path/to/npm
+
npm@10.7.0 /path/to/npm
 └─┬ init-package-json@0.0.4
   └── promzard@0.1.5
 
diff --git a/deps/npm/docs/output/commands/npm-profile.html b/deps/npm/docs/output/commands/npm-profile.html index a6283aeb1884f8..e0c913a6b46b22 100644 --- a/deps/npm/docs/output/commands/npm-profile.html +++ b/deps/npm/docs/output/commands/npm-profile.html @@ -160,27 +160,16 @@

Description

  • npm profile get [<property>]: Display all of the properties of your profile, or one or more specific properties. It looks like:
  • -
    +-----------------+---------------------------+
    -| name            | example                   |
    -+-----------------+---------------------------+
    -| email           | me@example.com (verified) |
    -+-----------------+---------------------------+
    -| two factor auth | auth-and-writes           |
    -+-----------------+---------------------------+
    -| fullname        | Example User              |
    -+-----------------+---------------------------+
    -| homepage        |                           |
    -+-----------------+---------------------------+
    -| freenode        |                           |
    -+-----------------+---------------------------+
    -| twitter         |                           |
    -+-----------------+---------------------------+
    -| github          |                           |
    -+-----------------+---------------------------+
    -| created         | 2015-02-26T01:38:35.892Z  |
    -+-----------------+---------------------------+
    -| updated         | 2017-10-02T21:29:45.922Z  |
    -+-----------------+---------------------------+
    +
    name: example
    +email: e@example.com (verified)
    +two-factor auth: auth-and-writes
    +fullname: Example User
    +homepage:
    +freenode:
    +twitter:
    +github:
    +created: 2015-02-26T01:38:35.892Z
    +updated: 2017-10-02T21:29:45.922Z
     
    • diff --git a/deps/npm/docs/output/commands/npm-search.html b/deps/npm/docs/output/commands/npm-search.html index 16fe0a50e97a11..3d7821531f730a 100644 --- a/deps/npm/docs/output/commands/npm-search.html +++ b/deps/npm/docs/output/commands/npm-search.html @@ -142,11 +142,11 @@

      npm-search

      Table of contents

      - +

      Synopsis

      -
      npm search [search terms ...]
      +
      npm search <search term> [<search term> ...]
       
       aliases: find, s, se
       
      @@ -170,12 +170,6 @@

      Description

      ignore a trailing / . (Note you must escape or quote many regular expression characters in most shells.)

      Configuration

      -

      long

      -
        -
      • Default: false
      • -
      • Type: Boolean
      • -
      -

      Show extended information in ls, search, and help-search.

      json

      • Default: false
      • @@ -207,6 +201,13 @@

        description

      • Type: Boolean

      Show the description in npm search

      +

      searchlimit

      +
        +
      • Default: 20
      • +
      • Type: Number
      • +
      +

      Number of items to limit search results to. Will not apply at all to legacy +searches.

      searchopts

      • Default: ""
      • diff --git a/deps/npm/docs/output/commands/npm-token.html b/deps/npm/docs/output/commands/npm-token.html index 44f94ec71ff14e..33b66d08e69def 100644 --- a/deps/npm/docs/output/commands/npm-token.html +++ b/deps/npm/docs/output/commands/npm-token.html @@ -158,23 +158,13 @@

        Description

        Shows a table of all active authentication tokens. You can request this as JSON with --json or tab-separated values with --parseable.
      -
      +--------+---------+------------+----------+----------------+
      -| id     | token   | created    | read-only | CIDR whitelist |
      -+--------+---------+------------+----------+----------------+
      -| 7f3134 | 1fa9ba… | 2017-10-02 | yes      |                |
      -+--------+---------+------------+----------+----------------+
      -| c03241 | af7aef… | 2017-10-02 | no       | 192.168.0.1/24 |
      -+--------+---------+------------+----------+----------------+
      -| e0cf92 | 3a436a… | 2017-10-02 | no       |                |
      -+--------+---------+------------+----------+----------------+
      -| 63eb9d | 74ef35… | 2017-09-28 | no       |                |
      -+--------+---------+------------+----------+----------------+
      -| 2daaa8 | cbad5f… | 2017-09-26 | no       |                |
      -+--------+---------+------------+----------+----------------+
      -| 68c2fe | 127e51… | 2017-09-23 | no       |                |
      -+--------+---------+------------+----------+----------------+
      -| 6334e1 | 1dadd1… | 2017-09-23 | no       |                |
      -+--------+---------+------------+----------+----------------+
      +
      Read only token npm_1f… with id 7f3134 created 2017-10-21
      +
      +Publish token npm_af…  with id c03241 created 2017-10-02
      +with IP Whitelist: 192.168.0.1/24
      +
      +Publish token npm_… with id e0cf92 created 2017-10-02
      +
       
      • @@ -191,15 +181,7 @@

        Description

        for more information on generating automation tokens.

      -
      +----------------+--------------------------------------+
      -| token          | a73c9572-f1b9-8983-983d-ba3ac3cc913d |
      -+----------------+--------------------------------------+
      -| cidr_whitelist |                                      |
      -+----------------+--------------------------------------+
      -| readonly       | false                                |
      -+----------------+--------------------------------------+
      -| created        | 2017-10-02T07:52:24.838Z             |
      -+----------------+--------------------------------------+
      +
      Created publish token a73c9572-f1b9-8983-983d-ba3ac3cc913d
       
      • npm token revoke <token|id>: diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html index 976024c99e441a..1a279cf259db33 100644 --- a/deps/npm/docs/output/commands/npm.html +++ b/deps/npm/docs/output/commands/npm.html @@ -150,7 +150,7 @@

        Table of contents

      Note: This command is unaware of workspaces.

      Version

      -

      10.5.0

      +

      10.7.0

      Description

      npm is the package manager for the Node JavaScript platform. It puts modules in place so that node can find them, and manages dependency diff --git a/deps/npm/docs/output/configuring-npm/package-json.html b/deps/npm/docs/output/configuring-npm/package-json.html index 6c85ea97e813a4..3a0e58663c6ac7 100644 --- a/deps/npm/docs/output/configuring-npm/package-json.html +++ b/deps/npm/docs/output/configuring-npm/package-json.html @@ -175,7 +175,7 @@

      name

    • Don't use the same name as a core Node module.
    • Don't put "js" or "node" in the name. It's assumed that it's js, since you're writing a package.json file, and you can specify the engine using -the "engines" field. (See below.)
    • +the "engines" field. (See below.)
    • The name will probably be passed as an argument to require(), so it should be something short, but also reasonably descriptive.
    • You may want to check the npm registry to see if there's something by @@ -201,12 +201,12 @@

      keywords

      Put keywords in it. It's an array of strings. This helps people discover your package as it's listed in npm search.

      homepage

      -

      The url to the project homepage.

      +

      The URL to the project homepage.

      Example:

      "homepage": "https://github.com/owner/project#readme"
       

      bugs

      -

      The url to your project's issue tracker and / or the email address to which +

      The URL to your project's issue tracker and / or the email address to which issues should be reported. These are helpful for people who encounter issues with your package.

      It should look like this:

      @@ -218,9 +218,9 @@

      bugs

      }

    You can specify either one or both values. If you want to provide only a -url, you can specify the value for "bugs" as a simple string instead of an +URL, you can specify the value for "bugs" as a simple string instead of an object.

    -

    If a url is provided, it will be used by the npm bugs command.

    +

    If a URL is provided, it will be used by the npm bugs command.

    license

    You should specify a license for your package so that people know how they are permitted to use it, and any restrictions you're placing on it.

    @@ -531,9 +531,9 @@

    repository

    } }
    -

    The URL should be a publicly available (perhaps read-only) url that can be +

    The URL should be a publicly available (perhaps read-only) URL that can be handed directly to a VCS program without any modification. It should not -be a url to an html project page that you put in your browser. It's for +be a URL to an html project page that you put in your browser. It's for computers.

    For GitHub, GitHub gist, Bitbucket, or GitLab repositories you can use the same shortcut syntax you use for npm install:

    @@ -630,7 +630,7 @@

    URLs as Dependencies

    This tarball will be downloaded and installed locally to your package at install time.

    Git URLs as Dependencies

    -

    Git urls are of the form:

    +

    Git URLs are of the form:

    <protocol>://[<user>[:<password>]@]<hostname>[:<port>][:][/]<path>[#<commit-ish> | #semver:<semver>]
     

    <protocol> is one of git, git+ssh, git+http, git+https, or @@ -666,7 +666,7 @@

    Git URLs as Dependencies

    make sure that none of the above scripts are defined, or your dependency will be rebuilt for every installation.

    GitHub URLs

    -

    As of version 1.1.65, you can refer to GitHub urls as just "foo": +

    As of version 1.1.65, you can refer to GitHub URLs as just "foo": "user/foo-project". Just as with git URLs, a commit-ish suffix can be included. For example:

    {
    @@ -820,7 +820,7 @@ 

    optionalDependencies

    If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the optionalDependencies object. This is a map of package name to version or -url, just like the dependencies object. The difference is that build +URL, just like the dependencies object. The difference is that build failures do not cause installation to fail. Running npm install --omit=optional will prevent these dependencies from being installed.

    It is still your program's responsibility to handle the lack of the dependency. For example, something like this:

    @@ -850,6 +850,12 @@

    overrides

    Overrides provide a way to replace a package in your dependency tree with another version, or another package entirely. These changes can be scoped as specific or as vague as desired.

    +

    Overrides are only considered in the root package.json file for a project. +Overrides in installed dependencies (including +workspaces) are not considered in dependency tree +resolution. Published packages may dictate their resolutions by pinning +dependencies or using an +npm-shrinkwrap.json file.

    To make sure the package foo is always installed as version 1.0.0 no matter what version your dependencies rely on:

    {
    diff --git a/deps/npm/docs/output/configuring-npm/package-lock-json.html b/deps/npm/docs/output/configuring-npm/package-lock-json.html
    index 11e4ab79900e5a..ca61021db3a36a 100644
    --- a/deps/npm/docs/output/configuring-npm/package-lock-json.html
    +++ b/deps/npm/docs/output/configuring-npm/package-lock-json.html
    @@ -176,6 +176,7 @@ 

    Table of contents

    files, and allowing for significant performance improvements.

    +

    When npm creates or updates package-lock.json, it will infer line endings and indentation from package.json so that the formatting of both files matches.

    package-lock.json vs npm-shrinkwrap.json

    Both of these files have the same format, and perform similar functions in the root of a project.

    diff --git a/deps/npm/lib/arborist-cmd.js b/deps/npm/lib/arborist-cmd.js index 42699ece364ad1..9d247d02fa181d 100644 --- a/deps/npm/lib/arborist-cmd.js +++ b/deps/npm/lib/arborist-cmd.js @@ -1,10 +1,9 @@ -const log = require('./utils/log-shim.js') +const { log } = require('proc-log') +const BaseCommand = require('./base-cmd.js') // This is the base for all commands whose execWorkspaces just gets // a list of workspace names and passes it on to new Arborist() to // be able to run a filtered Arborist.reify() at some point. - -const BaseCommand = require('./base-command.js') class ArboristCmd extends BaseCommand { get isArboristCmd () { return true diff --git a/deps/npm/lib/base-command.js b/deps/npm/lib/base-cmd.js similarity index 93% rename from deps/npm/lib/base-command.js rename to deps/npm/lib/base-cmd.js index e4a7bbbec724a6..9c30ef8a4b44e0 100644 --- a/deps/npm/lib/base-command.js +++ b/deps/npm/lib/base-cmd.js @@ -1,11 +1,4 @@ -// Base class for npm commands - -const { relative } = require('path') - -const { definitions } = require('@npmcli/config/lib/definitions') -const getWorkspaces = require('./workspaces/get-workspaces.js') -const { aliases: cmdAliases } = require('./utils/cmd-list') -const log = require('./utils/log-shim.js') +const { log, output } = require('proc-log') class BaseCommand { static workspaces = false @@ -19,6 +12,8 @@ class BaseCommand { // this is a static so that we can read from it without instantiating a command // which would require loading the config static get describeUsage () { + const { definitions } = require('@npmcli/config/lib/definitions') + const { aliases: cmdAliases } = require('./utils/cmd-list') const seenExclusive = new Set() const wrapWidth = 80 const { description, usage = [''], name, params } = this @@ -120,7 +115,7 @@ class BaseCommand { const { config } = this.npm if (config.get('usage')) { - return this.npm.output(this.usage) + return output.standard(this.usage) } const hasWsConfig = config.get('workspaces') || config.get('workspace').length @@ -162,6 +157,8 @@ class BaseCommand { } async setWorkspaces () { + const { relative } = require('node:path') + const includeWorkspaceRoot = this.isArboristCmd ? false : this.npm.config.get('include-workspace-root') @@ -170,6 +167,7 @@ class BaseCommand { const relativeFrom = prefixInsideCwd ? this.npm.localPrefix : process.cwd() const filters = this.npm.config.get('workspace') + const getWorkspaces = require('./utils/get-workspaces.js') const ws = await getWorkspaces(filters, { path: this.npm.localPrefix, includeWorkspaceRoot, @@ -181,4 +179,5 @@ class BaseCommand { this.workspacePaths = [...ws.values()] } } + module.exports = BaseCommand diff --git a/deps/npm/lib/cli.js b/deps/npm/lib/cli.js index c85ecb65a7005a..e11729fe3205b9 100644 --- a/deps/npm/lib/cli.js +++ b/deps/npm/lib/cli.js @@ -1,4 +1,4 @@ -const validateEngines = require('./es6/validate-engines.js') -const cliEntry = require('path').resolve(__dirname, 'cli-entry.js') +const validateEngines = require('./cli/validate-engines.js') +const cliEntry = require('node:path').resolve(__dirname, 'cli/entry.js') module.exports = (process) => validateEngines(process, () => require(cliEntry)) diff --git a/deps/npm/lib/cli-entry.js b/deps/npm/lib/cli/entry.js similarity index 56% rename from deps/npm/lib/cli-entry.js rename to deps/npm/lib/cli/entry.js index aad06e06903856..5d676c3f0a8a10 100644 --- a/deps/npm/lib/cli-entry.js +++ b/deps/npm/lib/cli/entry.js @@ -11,14 +11,17 @@ module.exports = async (process, validateEngines) => { process.argv.splice(1, 1, 'npm', '-g') } + // Patch the global fs module here at the app level + require('graceful-fs').gracefulify(require('fs')) + const satisfies = require('semver/functions/satisfies') - const exitHandler = require('./utils/exit-handler.js') - const Npm = require('./npm.js') + const exitHandler = require('./exit-handler.js') + const Npm = require('../npm.js') const npm = new Npm() exitHandler.setNpm(npm) // only log node and npm paths in argv initially since argv can contain sensitive info. a cleaned version will be logged later - const log = require('./utils/log-shim.js') + const { log, output } = require('proc-log') log.verbose('cli', process.argv.slice(0, 2).join(' ')) log.info('using', 'npm@%s', npm.version) log.info('using', 'node@%s', process.version) @@ -33,39 +36,49 @@ module.exports = async (process, validateEngines) => { log.warn('cli', validateEngines.unsupportedMessage) } - let cmd // Now actually fire up npm and run the command. // This is how to use npm programmatically: try { - await npm.load() + const { exec, command, args } = await npm.load() - // npm -v - if (npm.config.get('version', 'cli')) { - npm.output(npm.version) + if (!exec) { return exitHandler() } - // npm --versions - if (npm.config.get('versions', 'cli')) { - npm.argv = ['version'] - npm.config.set('usage', false, 'cli') - } - - cmd = npm.argv.shift() - if (!cmd) { - npm.output(npm.usage) + if (!command) { + output.standard(npm.usage) process.exitCode = 1 return exitHandler() } - await npm.exec(cmd) + // Options are prefixed by a hyphen-minus (-, \u2d). + // Other dash-type chars look similar but are invalid. + const nonDashArgs = npm.argv.filter(a => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(a)) + if (nonDashArgs.length) { + log.error( + 'arg', + 'Argument starts with non-ascii dash, this is probably invalid:', + require('@npmcli/redact').redactLog(nonDashArgs.join(', ')) + ) + } + + const execPromise = npm.exec(command, args) + + // this is async but we dont await it, since its ok if it doesnt + // finish before the command finishes running. it uses command and argv + // so it must be initiated here, after the command name is set + const updateNotifier = require('./update-notifier.js') + // eslint-disable-next-line promise/catch-or-return + updateNotifier(npm).then((msg) => (npm.updateNotification = msg)) + + await execPromise return exitHandler() } catch (err) { if (err.code === 'EUNKNOWNCOMMAND') { - const didYouMean = require('./utils/did-you-mean.js') - const suggestions = await didYouMean(npm.localPrefix, cmd) - npm.output(`Unknown command: "${cmd}"${suggestions}\n`) - npm.output('To see a list of supported npm commands, run:\n npm help') + const didYouMean = require('../utils/did-you-mean.js') + const suggestions = await didYouMean(npm.localPrefix, err.command) + output.standard(`Unknown command: "${err.command}"${suggestions}\n`) + output.standard('To see a list of supported npm commands, run:\n npm help') process.exitCode = 1 return exitHandler() } diff --git a/deps/npm/lib/utils/exit-handler.js b/deps/npm/lib/cli/exit-handler.js similarity index 64% rename from deps/npm/lib/utils/exit-handler.js rename to deps/npm/lib/cli/exit-handler.js index 25cecd170a584c..5866c46b57c5f0 100644 --- a/deps/npm/lib/utils/exit-handler.js +++ b/deps/npm/lib/cli/exit-handler.js @@ -1,30 +1,14 @@ -const os = require('os') -const fs = require('fs') - -const log = require('./log-shim.js') -const errorMessage = require('./error-message.js') -const replaceInfo = require('./replace-info.js') +const { log, output, META } = require('proc-log') +const errorMessage = require('../utils/error-message.js') +const { redactLog: replaceInfo } = require('@npmcli/redact') let npm = null // set by the cli let exitHandlerCalled = false let showLogFileError = false process.on('exit', code => { - log.disableProgress() - - // process.emit is synchronous, so the timeEnd handler will run before the - // unfinished timer check below - process.emit('timeEnd', 'npm') - const hasLoadedNpm = npm?.config.loaded - // Unfinished timers can be read before config load - if (npm) { - for (const [name, timer] of npm.unfinishedTimers) { - log.verbose('unfinished npm timer', name, timer) - } - } - if (!code) { log.info('ok') } else { @@ -34,66 +18,16 @@ process.on('exit', code => { if (!exitHandlerCalled) { process.exitCode = code || 1 log.error('', 'Exit handler never called!') - // eslint-disable-next-line no-console - console.error('') log.error('', 'This is an error with npm itself. Please report this error at:') log.error('', ' ') + // eslint-disable-next-line no-console + console.error('') showLogFileError = true } // npm must be loaded to know where the log file was written if (hasLoadedNpm) { - // write the timing file now, this might do nothing based on the configs set. - // we need to call it here in case it errors so we dont tell the user - // about a timing file that doesn't exist - npm.writeTimingFile() - - const logsDir = npm.logsDir - const logFiles = npm.logFiles - - const timingDir = npm.timingDir - const timingFile = npm.timingFile - - const timing = npm.config.get('timing') - const logsMax = npm.config.get('logs-max') - - // Determine whether to show log file message and why it is - // being shown since in timing mode we always show the log file message - const logMethod = showLogFileError ? 'error' : timing ? 'info' : null - - if (logMethod) { - if (!npm.silent) { - // just a line break if not in silent mode - // eslint-disable-next-line no-console - console.error('') - } - - const message = [] - - if (timingFile) { - message.push(`Timing info written to: ${timingFile}`) - } else if (timing) { - message.push( - `The timing file was not written due to an error writing to the directory: ${timingDir}` - ) - } - - if (logFiles.length) { - message.push(`A complete log of this run can be found in: ${logFiles}`) - } else if (logsMax <= 0) { - // user specified no log file - message.push(`Log files were not written due to the config logs-max=${logsMax}`) - } else { - // could be an error writing to the directory - message.push( - `Log files were not written due to an error writing to the directory: ${logsDir}`, - 'You can rerun the command with `--loglevel=verbose` to see the logs in your terminal' - ) - } - - log[logMethod]('', message.join('\n')) - } - + npm.finish({ showLogFileError }) // This removes any listeners npm setup, mostly for tests to avoid max listener warnings npm.unload() } @@ -106,12 +40,11 @@ process.on('exit', code => { const exitHandler = err => { exitHandlerCalled = true - log.disableProgress() - const hasLoadedNpm = npm?.config.loaded if (!npm) { err = err || new Error('Exit prior to setting npm in exit handler') + // Don't use proc-log here since npm was never set // eslint-disable-next-line no-console console.error(err.stack || err.message) return process.exit(1) @@ -119,16 +52,14 @@ const exitHandler = err => { if (!hasLoadedNpm) { err = err || new Error('Exit prior to config file resolving.') + // Don't use proc-log here since npm was never loaded // eslint-disable-next-line no-console console.error(err.stack || err.message) } // only show the notification if it finished. if (typeof npm.updateNotification === 'string') { - const { level } = log - log.level = 'notice' - log.notice('', npm.updateNotification) - log.level = level + log.notice('', npm.updateNotification, { [META]: true, force: true }) } let exitCode = process.exitCode || 0 @@ -154,6 +85,8 @@ const exitHandler = err => { log.error('weird error', err) noLogMessage = true } else { + const os = require('node:os') + const fs = require('node:fs') if (!err.code) { const matchErrorCode = err.message.match(/^(?:Error: )?(E[A-Z]+)/) err.code = matchErrorCode && matchErrorCode[1] @@ -205,7 +138,7 @@ const exitHandler = err => { } if (hasLoadedNpm) { - npm.flushOutput(jsonError) + output.flush({ [META]: true, jsonError }) } log.verbose('exit', exitCode || 0) diff --git a/deps/npm/lib/utils/update-notifier.js b/deps/npm/lib/cli/update-notifier.js similarity index 80% rename from deps/npm/lib/utils/update-notifier.js rename to deps/npm/lib/cli/update-notifier.js index 7c9611e4773f97..41fece36a558eb 100644 --- a/deps/npm/lib/utils/update-notifier.js +++ b/deps/npm/lib/cli/update-notifier.js @@ -3,7 +3,9 @@ // Check daily for betas, and weekly otherwise. const ciInfo = require('ci-info') -const semver = require('semver') +const gt = require('semver/functions/gt') +const gte = require('semver/functions/gte') +const parse = require('semver/functions/parse') const { stat, writeFile } = require('fs/promises') const { resolve } = require('path') @@ -38,39 +40,33 @@ const updateCheck = async (npm, spec, version, current) => { // and should get the updates from that release train. // Note that this isn't another http request over the network, because // the packument will be cached by pacote from previous request. - if (semver.gt(version, latest) && spec === 'latest') { + if (gt(version, latest) && spec === 'latest') { return updateNotifier(npm, `^${version}`) } // if we already have something >= the desired spec, then we're done - if (semver.gte(version, latest)) { + if (gte(version, latest)) { return null } - const useColor = npm.logColor const chalk = npm.logChalk // ok! notify the user about this update they should get. // The message is saved for printing at process exit so it will not get // lost in any other messages being printed as part of the command. - const update = semver.parse(mani.version) + const update = parse(mani.version) const type = update.major !== current.major ? 'major' : update.minor !== current.minor ? 'minor' : update.patch !== current.patch ? 'patch' : 'prerelease' - const typec = type === 'major' ? chalk.red(type) - : type === 'minor' ? chalk.yellow(type) - : chalk.green(type) - const oldc = chalk.red(current) - const latestc = chalk.green(latest) - const changelog = `https://github.com/npm/cli/releases/tag/v${latest}` - const changelogc = !useColor ? `<${changelog}>` : chalk.cyan(changelog) + const typec = type === 'major' ? 'red' + : type === 'minor' ? 'yellow' + : 'cyan' const cmd = `npm install -g npm@${latest}` - const cmdc = !useColor ? `\`${cmd}\`` : chalk.green(cmd) - const message = `\nNew ${typec} version of npm available! ` + - `${oldc} -> ${latestc}\n` + - `Changelog: ${changelogc}\n` + - `Run ${cmdc} to update!\n` + const message = `\nNew ${chalk[typec](type)} version of npm available! ` + + `${chalk[typec](current)} -> ${chalk.blue(latest)}\n` + + `Changelog: ${chalk.blue(`https://github.com/npm/cli/releases/tag/v${latest}`)}\n` + + `To update run: ${chalk.underline(cmd)}\n` return message } @@ -79,7 +75,7 @@ const updateNotifier = async (npm, spec = 'latest') => { // if we're on a prerelease train, then updates are coming fast // check for a new one daily. otherwise, weekly. const { version } = npm - const current = semver.parse(version) + const current = parse(version) // if we're on a beta train, always get the next beta if (current.prerelease.length) { diff --git a/deps/npm/lib/es6/validate-engines.js b/deps/npm/lib/cli/validate-engines.js similarity index 100% rename from deps/npm/lib/es6/validate-engines.js rename to deps/npm/lib/cli/validate-engines.js diff --git a/deps/npm/lib/commands/access.js b/deps/npm/lib/commands/access.js index 99c1264a84eda3..d35699e839109c 100644 --- a/deps/npm/lib/commands/access.js +++ b/deps/npm/lib/commands/access.js @@ -1,11 +1,11 @@ const libnpmaccess = require('libnpmaccess') const npa = require('npm-package-arg') +const { output } = require('proc-log') const pkgJson = require('@npmcli/package-json') const localeCompare = require('@isaacs/string-locale-compare')('en') - const otplease = require('../utils/otplease.js') const getIdentity = require('../utils/get-identity.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const commands = [ 'get', @@ -36,7 +36,7 @@ class Access extends BaseCommand { ] static usage = [ - 'list packages [|| []', + 'list packages [||] []', 'list collaborators [ []]', 'get status []', 'set status=public|private []', @@ -197,7 +197,7 @@ class Access extends BaseCommand { } #output (items, limiter) { - const output = {} + const outputs = {} const lookup = { __proto__: null, read: 'read-only', @@ -205,14 +205,14 @@ class Access extends BaseCommand { } for (const item in items) { const val = items[item] - output[item] = lookup[val] || val + outputs[item] = lookup[val] || val } if (this.npm.config.get('json')) { - this.npm.output(JSON.stringify(output, null, 2)) + output.standard(JSON.stringify(outputs, null, 2)) } else { - for (const item of Object.keys(output).sort(localeCompare)) { + for (const item of Object.keys(outputs).sort(localeCompare)) { if (!limiter || limiter === item) { - this.npm.output(`${item}: ${output[item]}`) + output.standard(`${item}: ${outputs[item]}`) } } } diff --git a/deps/npm/lib/commands/adduser.js b/deps/npm/lib/commands/adduser.js index cd4cba60511cb6..cf64e7a7e74389 100644 --- a/deps/npm/lib/commands/adduser.js +++ b/deps/npm/lib/commands/adduser.js @@ -1,8 +1,7 @@ -const log = require('../utils/log-shim.js') -const replaceInfo = require('../utils/replace-info.js') +const { log, output } = require('proc-log') +const { redactLog: replaceInfo } = require('@npmcli/redact') const auth = require('../utils/auth.js') - -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class AddUser extends BaseCommand { static description = 'Add a registry user account' @@ -13,7 +12,7 @@ class AddUser extends BaseCommand { 'auth-type', ] - async exec (args) { + async exec () { const scope = this.npm.config.get('scope') let registry = this.npm.config.get('registry') @@ -27,7 +26,6 @@ class AddUser extends BaseCommand { const creds = this.npm.config.getCredentialsByURI(registry) - log.disableProgress() log.notice('', `Log in on ${replaceInfo(registry)}`) const { message, newCreds } = await auth.adduser(this.npm, { @@ -45,7 +43,8 @@ class AddUser extends BaseCommand { await this.npm.config.save('user') - this.npm.output(message) + output.standard(message) } } + module.exports = AddUser diff --git a/deps/npm/lib/commands/audit.js b/deps/npm/lib/commands/audit.js index 8c10a36cfee3cf..aed1be7a82906b 100644 --- a/deps/npm/lib/commands/audit.js +++ b/deps/npm/lib/commands/audit.js @@ -1,399 +1,9 @@ const npmAuditReport = require('npm-audit-report') -const fetch = require('npm-registry-fetch') -const localeCompare = require('@isaacs/string-locale-compare')('en') -const npa = require('npm-package-arg') -const pacote = require('pacote') -const pMap = require('p-map') -const tufClient = require('@sigstore/tuf') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') const auditError = require('../utils/audit-error.js') -const log = require('../utils/log-shim.js') +const { log, output } = require('proc-log') const reifyFinish = require('../utils/reify-finish.js') - -const sortAlphabetically = (a, b) => localeCompare(a.name, b.name) - -class VerifySignatures { - constructor (tree, filterSet, npm, opts) { - this.tree = tree - this.filterSet = filterSet - this.npm = npm - this.opts = opts - this.keys = new Map() - this.invalid = [] - this.missing = [] - this.checkedPackages = new Set() - this.auditedWithKeysCount = 0 - this.verifiedSignatureCount = 0 - this.verifiedAttestationCount = 0 - this.exitCode = 0 - } - - async run () { - const start = process.hrtime.bigint() - - // Find all deps in tree - const { edges, registries } = this.getEdgesOut(this.tree.inventory.values(), this.filterSet) - if (edges.size === 0) { - throw new Error('found no installed dependencies to audit') - } - - const tuf = await tufClient.initTUF({ - cachePath: this.opts.tufCache, - retry: this.opts.retry, - timeout: this.opts.timeout, - }) - await Promise.all([...registries].map(registry => this.setKeys({ registry, tuf }))) - - const progress = log.newItem('verifying registry signatures', edges.size) - const mapper = async (edge) => { - progress.completeWork(1) - await this.getVerifiedInfo(edge) - } - await pMap(edges, mapper, { concurrency: 20, stopOnError: true }) - - // Didn't find any dependencies that could be verified, e.g. only local - // deps, missing version, not on a registry etc. - if (!this.auditedWithKeysCount) { - throw new Error('found no dependencies to audit that were installed from ' + - 'a supported registry') - } - - const invalid = this.invalid.sort(sortAlphabetically) - const missing = this.missing.sort(sortAlphabetically) - - const hasNoInvalidOrMissing = invalid.length === 0 && missing.length === 0 - - if (!hasNoInvalidOrMissing) { - process.exitCode = 1 - } - - if (this.npm.config.get('json')) { - this.npm.output(JSON.stringify({ - invalid, - missing, - }, null, 2)) - return - } - const end = process.hrtime.bigint() - const elapsed = end - start - - const auditedPlural = this.auditedWithKeysCount > 1 ? 's' : '' - const timing = `audited ${this.auditedWithKeysCount} package${auditedPlural} in ` + - `${Math.floor(Number(elapsed) / 1e9)}s` - this.npm.output(timing) - this.npm.output('') - - const verifiedBold = this.npm.chalk.bold('verified') - if (this.verifiedSignatureCount) { - if (this.verifiedSignatureCount === 1) { - /* eslint-disable-next-line max-len */ - this.npm.output(`${this.verifiedSignatureCount} package has a ${verifiedBold} registry signature`) - } else { - /* eslint-disable-next-line max-len */ - this.npm.output(`${this.verifiedSignatureCount} packages have ${verifiedBold} registry signatures`) - } - this.npm.output('') - } - - if (this.verifiedAttestationCount) { - if (this.verifiedAttestationCount === 1) { - /* eslint-disable-next-line max-len */ - this.npm.output(`${this.verifiedAttestationCount} package has a ${verifiedBold} attestation`) - } else { - /* eslint-disable-next-line max-len */ - this.npm.output(`${this.verifiedAttestationCount} packages have ${verifiedBold} attestations`) - } - this.npm.output('') - } - - if (missing.length) { - const missingClr = this.npm.chalk.bold(this.npm.chalk.red('missing')) - if (missing.length === 1) { - /* eslint-disable-next-line max-len */ - this.npm.output(`1 package has a ${missingClr} registry signature but the registry is providing signing keys:`) - } else { - /* eslint-disable-next-line max-len */ - this.npm.output(`${missing.length} packages have ${missingClr} registry signatures but the registry is providing signing keys:`) - } - this.npm.output('') - missing.map(m => - this.npm.output(`${this.npm.chalk.red(`${m.name}@${m.version}`)} (${m.registry})`) - ) - } - - if (invalid.length) { - if (missing.length) { - this.npm.output('') - } - const invalidClr = this.npm.chalk.bold(this.npm.chalk.red('invalid')) - // We can have either invalid signatures or invalid provenance - const invalidSignatures = this.invalid.filter(i => i.code === 'EINTEGRITYSIGNATURE') - if (invalidSignatures.length) { - if (invalidSignatures.length === 1) { - this.npm.output(`1 package has an ${invalidClr} registry signature:`) - } else { - /* eslint-disable-next-line max-len */ - this.npm.output(`${invalidSignatures.length} packages have ${invalidClr} registry signatures:`) - } - this.npm.output('') - invalidSignatures.map(i => - this.npm.output(`${this.npm.chalk.red(`${i.name}@${i.version}`)} (${i.registry})`) - ) - this.npm.output('') - } - - const invalidAttestations = this.invalid.filter(i => i.code === 'EATTESTATIONVERIFY') - if (invalidAttestations.length) { - if (invalidAttestations.length === 1) { - this.npm.output(`1 package has an ${invalidClr} attestation:`) - } else { - /* eslint-disable-next-line max-len */ - this.npm.output(`${invalidAttestations.length} packages have ${invalidClr} attestations:`) - } - this.npm.output('') - invalidAttestations.map(i => - this.npm.output(`${this.npm.chalk.red(`${i.name}@${i.version}`)} (${i.registry})`) - ) - this.npm.output('') - } - - if (invalid.length === 1) { - /* eslint-disable-next-line max-len */ - this.npm.output(`Someone might have tampered with this package since it was published on the registry!`) - } else { - /* eslint-disable-next-line max-len */ - this.npm.output(`Someone might have tampered with these packages since they were published on the registry!`) - } - this.npm.output('') - } - } - - getEdgesOut (nodes, filterSet) { - const edges = new Set() - const registries = new Set() - for (const node of nodes) { - for (const edge of node.edgesOut.values()) { - const filteredOut = - edge.from - && filterSet - && filterSet.size > 0 - && !filterSet.has(edge.from.target) - - if (!filteredOut) { - const spec = this.getEdgeSpec(edge) - if (spec) { - // Prefetch and cache public keys from used registries - registries.add(this.getSpecRegistry(spec)) - } - edges.add(edge) - } - } - } - return { edges, registries } - } - - async setKeys ({ registry, tuf }) { - const { host, pathname } = new URL(registry) - // Strip any trailing slashes from pathname - const regKey = `${host}${pathname.replace(/\/$/, '')}/keys.json` - let keys = await tuf.getTarget(regKey) - .then((target) => JSON.parse(target)) - .then(({ keys: ks }) => ks.map((key) => ({ - ...key, - keyid: key.keyId, - pemkey: `-----BEGIN PUBLIC KEY-----\n${key.publicKey.rawBytes}\n-----END PUBLIC KEY-----`, - expires: key.publicKey.validFor.end || null, - }))).catch(err => { - if (err.code === 'TUF_FIND_TARGET_ERROR') { - return null - } else { - throw err - } - }) - - // If keys not found in Sigstore TUF repo, fallback to registry keys API - if (!keys) { - keys = await fetch.json('/-/npm/v1/keys', { - ...this.npm.flatOptions, - registry, - }).then(({ keys: ks }) => ks.map((key) => ({ - ...key, - pemkey: `-----BEGIN PUBLIC KEY-----\n${key.key}\n-----END PUBLIC KEY-----`, - }))).catch(err => { - if (err.code === 'E404' || err.code === 'E400') { - return null - } else { - throw err - } - }) - } - - if (keys) { - this.keys.set(registry, keys) - } - } - - getEdgeType (edge) { - return edge.optional ? 'optionalDependencies' - : edge.peer ? 'peerDependencies' - : edge.dev ? 'devDependencies' - : 'dependencies' - } - - getEdgeSpec (edge) { - let name = edge.name - try { - name = npa(edge.spec).subSpec.name - } catch { - // leave it as edge.name - } - try { - return npa(`${name}@${edge.spec}`) - } catch { - // Skip packages with invalid spec - } - } - - buildRegistryConfig (registry) { - const keys = this.keys.get(registry) || [] - const parsedRegistry = new URL(registry) - const regKey = `//${parsedRegistry.host}${parsedRegistry.pathname}` - return { - [`${regKey}:_keys`]: keys, - } - } - - getSpecRegistry (spec) { - return fetch.pickRegistry(spec, this.npm.flatOptions) - } - - getValidPackageInfo (edge) { - const type = this.getEdgeType(edge) - // Skip potentially optional packages that are not on disk, as these could - // be omitted during install - if (edge.error === 'MISSING' && type !== 'dependencies') { - return - } - - const spec = this.getEdgeSpec(edge) - // Skip invalid version requirements - if (!spec) { - return - } - const node = edge.to || edge - const { version } = node.package || {} - - if (node.isWorkspace || // Skip local workspaces packages - !version || // Skip packages that don't have a installed version, e.g. optonal dependencies - !spec.registry) { // Skip if not from registry, e.g. git package - return - } - - for (const omitType of this.npm.config.get('omit')) { - if (node[omitType]) { - return - } - } - - return { - name: spec.name, - version, - type, - location: node.location, - registry: this.getSpecRegistry(spec), - } - } - - async verifySignatures (name, version, registry) { - const { - _integrity: integrity, - _signatures, - _attestations, - _resolved: resolved, - } = await pacote.manifest(`${name}@${version}`, { - verifySignatures: true, - verifyAttestations: true, - ...this.buildRegistryConfig(registry), - ...this.npm.flatOptions, - }) - const signatures = _signatures || [] - const result = { - integrity, - signatures, - attestations: _attestations, - resolved, - } - return result - } - - async getVerifiedInfo (edge) { - const info = this.getValidPackageInfo(edge) - if (!info) { - return - } - const { name, version, location, registry, type } = info - if (this.checkedPackages.has(location)) { - // we already did or are doing this one - return - } - this.checkedPackages.add(location) - - // We only "audit" or verify the signature, or the presence of it, on - // packages whose registry returns signing keys - const keys = this.keys.get(registry) || [] - if (keys.length) { - this.auditedWithKeysCount += 1 - } - - try { - const { integrity, signatures, attestations, resolved } = await this.verifySignatures( - name, version, registry - ) - - // Currently we only care about missing signatures on registries that provide a public key - // We could make this configurable in the future with a strict/paranoid mode - if (signatures.length) { - this.verifiedSignatureCount += 1 - } else if (keys.length) { - this.missing.push({ - integrity, - location, - name, - registry, - resolved, - version, - }) - } - - // Track verified attestations separately to registry signatures, as all - // packages on registries with signing keys are expected to have registry - // signatures, but not all packages have provenance and publish attestations. - if (attestations) { - this.verifiedAttestationCount += 1 - } - } catch (e) { - if (e.code === 'EINTEGRITYSIGNATURE' || e.code === 'EATTESTATIONVERIFY') { - this.invalid.push({ - code: e.code, - message: e.message, - integrity: e.integrity, - keyid: e.keyid, - location, - name, - registry, - resolved: e.resolved, - signature: e.signature, - predicateType: e.predicateType, - type, - version, - }) - } else { - throw e - } - } - } -} +const VerifySignatures = require('../utils/verify-signatures.js') class Audit extends ArboristWorkspaceCmd { static description = 'Run a security audit' @@ -467,7 +77,7 @@ class Audit extends ArboristWorkspaceCmd { chalk: this.npm.chalk, }) process.exitCode = process.exitCode || result.exitCode - this.npm.output(result.report) + output.standard(result.report) } } diff --git a/deps/npm/lib/commands/cache.js b/deps/npm/lib/commands/cache.js index 50bb35e3544dfe..108c261ffe57d5 100644 --- a/deps/npm/lib/commands/cache.js +++ b/deps/npm/lib/commands/cache.js @@ -3,11 +3,11 @@ const pacote = require('pacote') const fs = require('fs/promises') const { join } = require('path') const semver = require('semver') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const npa = require('npm-package-arg') const jsonParse = require('json-parse-even-better-errors') const localeCompare = require('@isaacs/string-locale-compare')('en') -const log = require('../utils/log-shim') +const { log, output } = require('proc-log') const searchCachePackage = async (path, parsed, cacheKeys) => { /* eslint-disable-next-line max-len */ @@ -135,7 +135,7 @@ class Cache extends BaseCommand { log.warn(`Not Found: ${key}`) break } - this.npm.output(`Deleted: ${key}`) + output.standard(`Deleted: ${key}`) await cacache.rm.entry(cachePath, key) // XXX this could leave other entries without content! await cacache.rm.content(cachePath, entry.integrity) @@ -170,20 +170,20 @@ class Cache extends BaseCommand { ? `~${cache.slice(process.env.HOME.length)}` : cache const stats = await cacache.verify(cache) - this.npm.output(`Cache verified and compressed (${prefix})`) - this.npm.output(`Content verified: ${stats.verifiedContent} (${stats.keptSize} bytes)`) + output.standard(`Cache verified and compressed (${prefix})`) + output.standard(`Content verified: ${stats.verifiedContent} (${stats.keptSize} bytes)`) if (stats.badContentCount) { - this.npm.output(`Corrupted content removed: ${stats.badContentCount}`) + output.standard(`Corrupted content removed: ${stats.badContentCount}`) } if (stats.reclaimedCount) { /* eslint-disable-next-line max-len */ - this.npm.output(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`) + output.standard(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`) } if (stats.missingContent) { - this.npm.output(`Missing content: ${stats.missingContent}`) + output.standard(`Missing content: ${stats.missingContent}`) } - this.npm.output(`Index entries: ${stats.totalEntries}`) - this.npm.output(`Finished in ${stats.runTime.total / 1000}s`) + output.standard(`Index entries: ${stats.totalEntries}`) + output.standard(`Finished in ${stats.runTime.total / 1000}s`) } // npm cache ls [--package ...] @@ -203,10 +203,10 @@ class Cache extends BaseCommand { results.add(key) } } - [...results].sort(localeCompare).forEach(key => this.npm.output(key)) + [...results].sort(localeCompare).forEach(key => output.standard(key)) return } - cacheKeys.sort(localeCompare).forEach(key => this.npm.output(key)) + cacheKeys.sort(localeCompare).forEach(key => output.standard(key)) } } diff --git a/deps/npm/lib/commands/ci.js b/deps/npm/lib/commands/ci.js index 706b77ac361cf2..7e79d7208c9c4b 100644 --- a/deps/npm/lib/commands/ci.js +++ b/deps/npm/lib/commands/ci.js @@ -1,9 +1,8 @@ const reifyFinish = require('../utils/reify-finish.js') const runScript = require('@npmcli/run-script') const fs = require('fs/promises') -const log = require('../utils/log-shim.js') +const { log, time } = require('proc-log') const validateLockfile = require('../utils/validate-lockfile.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') class CI extends ArboristWorkspaceCmd { @@ -75,14 +74,18 @@ class CI extends ArboristWorkspaceCmd { ) } - // Only remove node_modules after we've successfully loaded the virtual - // tree and validated the lockfile - await this.npm.time('npm-ci:rm', async () => { - const path = `${where}/node_modules` - // get the list of entries so we can skip the glob for performance - const entries = await fs.readdir(path, null).catch(er => []) - return Promise.all(entries.map(f => fs.rm(`${path}/${f}`, { force: true, recursive: true }))) - }) + const dryRun = this.npm.config.get('dry-run') + if (!dryRun) { + // Only remove node_modules after we've successfully loaded the virtual + // tree and validated the lockfile + await time.start('npm-ci:rm', async () => { + const path = `${where}/node_modules` + // get the list of entries so we can skip the glob for performance + const entries = await fs.readdir(path, null).catch(() => []) + return Promise.all(entries.map(f => fs.rm(`${path}/${f}`, + { force: true, recursive: true }))) + }) + } await arb.reify(opts) @@ -105,7 +108,6 @@ class CI extends ArboristWorkspaceCmd { args: [], scriptShell, stdio: 'inherit', - banner: !this.npm.silent, event, }) } diff --git a/deps/npm/lib/commands/completion.js b/deps/npm/lib/commands/completion.js index 59113c50560bca..9b147d2f5bdac6 100644 --- a/deps/npm/lib/commands/completion.js +++ b/deps/npm/lib/commands/completion.js @@ -27,22 +27,22 @@ // Matches are wrapped with ' to escape them, if necessary, and then printed // one per line for the shell completion method to consume in IFS=$'\n' mode // as an array. -// const fs = require('fs/promises') const nopt = require('nopt') const { resolve } = require('path') - +const { output } = require('proc-log') const Npm = require('../npm.js') const { definitions, shorthands } = require('@npmcli/config/lib/definitions') const { commands, aliases, deref } = require('../utils/cmd-list.js') -const configNames = Object.keys(definitions) -const shorthandNames = Object.keys(shorthands) -const allConfs = configNames.concat(shorthandNames) const { isWindowsShell } = require('../utils/is-windows.js') +const BaseCommand = require('../base-cmd.js') + const fileExists = (file) => fs.stat(file).then(s => s.isFile()).catch(() => false) -const BaseCommand = require('../base-command.js') +const configNames = Object.keys(definitions) +const shorthandNames = Object.keys(shorthands) +const allConfs = configNames.concat(shorthandNames) class Completion extends BaseCommand { static description = 'Tab Completion for npm' @@ -185,7 +185,7 @@ class Completion extends BaseCommand { } if (compls.length > 0) { - this.npm.output(compls.join('\n')) + output.standard(compls.join('\n')) } } } @@ -248,7 +248,7 @@ const configCompl = opts => { // expand with the valid values of various config values. // not yet implemented. -const configValueCompl = opts => [] +const configValueCompl = () => [] // check if the thing is a flag or not. const isFlag = word => { @@ -265,7 +265,7 @@ const isFlag = word => { // complete against the npm commands // if they all resolve to the same thing, just return the thing it already is -const cmdCompl = (opts, npm) => { +const cmdCompl = (opts) => { const allCommands = commands.concat(Object.keys(aliases)) const matches = allCommands.filter(c => c.startsWith(opts.partialWord)) if (!matches.length) { diff --git a/deps/npm/lib/commands/config.js b/deps/npm/lib/commands/config.js index 8e8358fc50b7be..7fb8476276937b 100644 --- a/deps/npm/lib/commands/config.js +++ b/deps/npm/lib/commands/config.js @@ -1,12 +1,12 @@ -const { mkdir, readFile, writeFile } = require('fs/promises') -const { dirname, resolve } = require('path') -const { spawn } = require('child_process') -const { EOL } = require('os') -const ini = require('ini') +const { mkdir, readFile, writeFile } = require('node:fs/promises') +const { dirname, resolve } = require('node:path') +const { spawn } = require('node:child_process') +const { EOL } = require('node:os') const localeCompare = require('@isaacs/string-locale-compare')('en') const pkgJson = require('@npmcli/package-json') const { defaults, definitions } = require('@npmcli/config/lib/definitions') -const log = require('../utils/log-shim.js') +const { log, output } = require('proc-log') +const BaseCommand = require('../base-cmd.js') // These are the configs that we can nerf-dart. Not all of them currently even // *have* config definitions so we have to explicitly validate them here @@ -47,7 +47,6 @@ const publicVar = k => { return true } -const BaseCommand = require('../base-command.js') class Config extends BaseCommand { static description = 'Manage the npm configuration files' static name = 'config' @@ -111,35 +110,30 @@ class Config extends BaseCommand { } async exec ([action, ...args]) { - log.disableProgress() - try { - switch (action) { - case 'set': - await this.set(args) - break - case 'get': - await this.get(args) - break - case 'delete': - case 'rm': - case 'del': - await this.del(args) - break - case 'list': - case 'ls': - await (this.npm.flatOptions.json ? this.listJson() : this.list()) - break - case 'edit': - await this.edit() - break - case 'fix': - await this.fix() - break - default: - throw this.usageError() - } - } finally { - log.enableProgress() + switch (action) { + case 'set': + await this.set(args) + break + case 'get': + await this.get(args) + break + case 'delete': + case 'rm': + case 'del': + await this.del(args) + break + case 'list': + case 'ls': + await (this.npm.flatOptions.json ? this.listJson() : this.list()) + break + case 'edit': + await this.edit() + break + case 'fix': + await this.fix() + break + default: + throw this.usageError() } } @@ -190,7 +184,7 @@ class Config extends BaseCommand { const pref = keys.length > 1 ? `${key}=` : '' out.push(pref + this.npm.config.get(key)) } - this.npm.output(out.join('\n')) + output.standard(out.join('\n')) } async del (keys) { @@ -206,6 +200,7 @@ class Config extends BaseCommand { } async edit () { + const ini = require('ini') const e = this.npm.flatOptions.editor const where = this.npm.flatOptions.location const file = this.npm.config.data.get(where).source @@ -287,7 +282,7 @@ ${defData} this.npm.config.repair(problems) const locations = [] - this.npm.output('The following configuration problems have been repaired:\n') + output.standard('The following configuration problems have been repaired:\n') const summary = problems.map(({ action, from, to, key, where }) => { // coverage disabled for else branch because it is intentionally omitted // istanbul ignore else @@ -300,7 +295,7 @@ ${defData} return `- \`${key}\` deleted from ${where} config` } }).join('\n') - this.npm.output(summary) + output.standard(summary) return await Promise.all(locations.map((location) => this.npm.config.save(location))) } @@ -359,7 +354,7 @@ ${defData} } } - this.npm.output(msg.join('\n').trim()) + output.standard(msg.join('\n').trim()) } async listJson () { @@ -371,7 +366,7 @@ ${defData} publicConf[key] = this.npm.config.get(key) } - this.npm.output(JSON.stringify(publicConf, null, 2)) + output.standard(JSON.stringify(publicConf, null, 2)) } } diff --git a/deps/npm/lib/commands/dedupe.js b/deps/npm/lib/commands/dedupe.js index 0d0e26621b2275..e07bcd31e894b9 100644 --- a/deps/npm/lib/commands/dedupe.js +++ b/deps/npm/lib/commands/dedupe.js @@ -1,8 +1,7 @@ -// dedupe duplicated packages, or find them in the tree const reifyFinish = require('../utils/reify-finish.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') +// dedupe duplicated packages, or find them in the tree class Dedupe extends ArboristWorkspaceCmd { static description = 'Reduce duplication in the package tree' static name = 'dedupe' @@ -22,7 +21,7 @@ class Dedupe extends ArboristWorkspaceCmd { ...super.params, ] - async exec (args) { + async exec () { if (this.npm.global) { const er = new Error('`npm dedupe` does not work in global mode.') er.code = 'EDEDUPEGLOBAL' diff --git a/deps/npm/lib/commands/deprecate.js b/deps/npm/lib/commands/deprecate.js index bdce313923cff8..58856538fe23f2 100644 --- a/deps/npm/lib/commands/deprecate.js +++ b/deps/npm/lib/commands/deprecate.js @@ -4,7 +4,7 @@ const npa = require('npm-package-arg') const semver = require('semver') const getIdentity = require('../utils/get-identity.js') const libaccess = require('libnpmaccess') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Deprecate extends BaseCommand { static description = 'Deprecate a version of a package' diff --git a/deps/npm/lib/commands/diff.js b/deps/npm/lib/commands/diff.js index 64d81d525d79d2..ca8b1237b40c5a 100644 --- a/deps/npm/lib/commands/diff.js +++ b/deps/npm/lib/commands/diff.js @@ -4,9 +4,9 @@ const libnpmdiff = require('libnpmdiff') const npa = require('npm-package-arg') const pacote = require('pacote') const pickManifest = require('npm-pick-manifest') -const log = require('../utils/log-shim') +const { log, output } = require('proc-log') const pkgJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Diff extends BaseCommand { static description = 'The registry diff command' @@ -64,7 +64,7 @@ class Diff extends BaseCommand { diffFiles: args, where: this.top, }) - return this.npm.output(res) + return output.standard(res) } async execWorkspaces (args) { @@ -78,7 +78,7 @@ class Diff extends BaseCommand { // get the package name from the packument at `path` // throws if no packument is present OR if it does not have `name` attribute - async packageName (path) { + async packageName () { let name try { const { content: pkg } = await pkgJson.normalize(this.prefix) @@ -103,7 +103,7 @@ class Diff extends BaseCommand { // no arguments, defaults to comparing cwd // to its latest published registry version if (!a) { - const pkgName = await this.packageName(this.prefix) + const pkgName = await this.packageName() return [ `${pkgName}@${this.npm.config.get('tag')}`, `file:${this.prefix.replace(/#/g, '%23')}`, diff --git a/deps/npm/lib/commands/dist-tag.js b/deps/npm/lib/commands/dist-tag.js index ff49bc8e307cb6..e13f9ecf59c7fe 100644 --- a/deps/npm/lib/commands/dist-tag.js +++ b/deps/npm/lib/commands/dist-tag.js @@ -1,10 +1,10 @@ const npa = require('npm-package-arg') const regFetch = require('npm-registry-fetch') const semver = require('semver') -const log = require('../utils/log-shim') +const { log, output } = require('proc-log') const otplease = require('../utils/otplease.js') const pkgJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class DistTag extends BaseCommand { static description = 'Modify package distribution tags' @@ -120,7 +120,7 @@ class DistTag extends BaseCommand { spec, } await otplease(this.npm, reqOpts, o => regFetch(url, o)) - this.npm.output(`+${t}: ${spec.name}@${version}`) + output.standard(`+${t}: ${spec.name}@${version}`) } async remove (spec, tag, opts) { @@ -146,7 +146,7 @@ class DistTag extends BaseCommand { spec, } await otplease(this.npm, reqOpts, o => regFetch(url, o)) - this.npm.output(`-${tag}: ${spec.name}@${version}`) + output.standard(`-${tag}: ${spec.name}@${version}`) } async list (spec, opts) { @@ -167,7 +167,7 @@ class DistTag extends BaseCommand { const tags = await this.fetchTags(spec, opts) const msg = Object.keys(tags).map(k => `${k}: ${tags[k]}`).sort().join('\n') - this.npm.output(msg) + output.standard(msg) return tags } catch (err) { log.error('dist-tag ls', "Couldn't get dist-tag data for", spec) @@ -180,7 +180,7 @@ class DistTag extends BaseCommand { for (const name of this.workspaceNames) { try { - this.npm.output(`${name}:`) + output.standard(`${name}:`) await this.list(npa(name), this.npm.flatOptions) } catch (err) { // set the exitCode directly, but ignore the error @@ -205,4 +205,5 @@ class DistTag extends BaseCommand { return data } } + module.exports = DistTag diff --git a/deps/npm/lib/commands/docs.js b/deps/npm/lib/commands/docs.js index 5d20215b56a07f..2259b49f79617f 100644 --- a/deps/npm/lib/commands/docs.js +++ b/deps/npm/lib/commands/docs.js @@ -1,4 +1,5 @@ const PackageUrlCmd = require('../package-url-cmd.js') + class Docs extends PackageUrlCmd { static description = 'Open documentation for a package in a web browser' static name = 'docs' @@ -16,4 +17,5 @@ class Docs extends PackageUrlCmd { return `https://www.npmjs.com/package/${mani.name}` } } + module.exports = Docs diff --git a/deps/npm/lib/commands/doctor.js b/deps/npm/lib/commands/doctor.js index 2a528d46ddb8dc..c29dd7e0ecb174 100644 --- a/deps/npm/lib/commands/doctor.js +++ b/deps/npm/lib/commands/doctor.js @@ -1,19 +1,14 @@ const cacache = require('cacache') -const fs = require('fs') +const { access, lstat, readdir, constants: { R_OK, W_OK, X_OK } } = require('fs/promises') const fetch = require('make-fetch-happen') -const Table = require('cli-table3') const which = require('which') const pacote = require('pacote') const { resolve } = require('path') const semver = require('semver') -const { promisify } = require('util') -const log = require('../utils/log-shim.js') +const { log, output } = require('proc-log') const ping = require('../utils/ping.js') const { defaults } = require('@npmcli/config/lib/definitions') -const lstat = promisify(fs.lstat) -const readdir = promisify(fs.readdir) -const access = promisify(fs.access) -const { R_OK, W_OK, X_OK } = fs.constants +const BaseCommand = require('../base-cmd.js') const maskLabel = mask => { const label = [] @@ -34,57 +29,59 @@ const maskLabel = mask => { const subcommands = [ { - groups: ['ping', 'registry'], - title: 'npm ping', + // Ping is left in as a legacy command but is listed as "connection" to + // make more sense to more people + groups: ['connection', 'ping', 'registry'], + title: 'Connecting to the registry', cmd: 'checkPing', }, { groups: ['versions'], - title: 'npm -v', + title: 'Checking npm version', cmd: 'getLatestNpmVersion', }, { groups: ['versions'], - title: 'node -v', + title: 'Checking node version', cmd: 'getLatestNodejsVersion', }, { groups: ['registry'], - title: 'npm config get registry', + title: 'Checking configured npm registry', cmd: 'checkNpmRegistry', }, { groups: ['environment'], - title: 'git executable in PATH', + title: 'Checking for git executable in PATH', cmd: 'getGitPath', }, { groups: ['environment'], - title: 'global bin folder in PATH', + title: 'Checking for global bin folder in PATH', cmd: 'getBinPath', }, { groups: ['permissions', 'cache'], - title: 'Perms check on cached files', + title: 'Checking permissions on cached files (this may take awhile)', cmd: 'checkCachePermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on local node_modules', + title: 'Checking permissions on local node_modules (this may take awhile)', cmd: 'checkLocalModulesPermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on global node_modules', + title: 'Checking permissions on global node_modules (this may take awhile)', cmd: 'checkGlobalModulesPermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on local bin folder', + title: 'Checking permissions on local bin folder', cmd: 'checkLocalBinPermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on global bin folder', + title: 'Checking permissions on global bin folder', cmd: 'checkGlobalBinPermission', windows: false, }, { groups: ['cache'], - title: 'Verify cache contents', + title: 'Verifying cache contents (this may take awhile)', cmd: 'verifyCachedFiles', windows: false, }, @@ -97,50 +94,35 @@ const subcommands = [ // - verify all local packages have bins linked // What is the fix for these? ] -const BaseCommand = require('../base-command.js') + class Doctor extends BaseCommand { static description = 'Check the health of your npm environment' static name = 'doctor' static params = ['registry'] static ignoreImplicitWorkspace = false static usage = [`[${subcommands.flatMap(s => s.groups) - .filter((value, index, self) => self.indexOf(value) === index) + .filter((value, index, self) => self.indexOf(value) === index && value !== 'ping') .join('] [')}]`] static subcommands = subcommands - // minimum width of check column, enough for the word `Check` - #checkWidth = 5 - async exec (args) { - log.info('Running checkup') + log.info('doctor', 'Running checkup') let allOk = true const actions = this.actions(args) - this.#checkWidth = actions.reduce((length, item) => - Math.max(item.title.length, length), this.#checkWidth) - if (!this.npm.silent) { - this.output(['Check', 'Value', 'Recommendation/Notes'].map(h => this.npm.chalk.underline(h))) - } - // Do the actual work + const chalk = this.npm.chalk for (const { title, cmd } of actions) { - const item = [title] + this.output(title) + // TODO when we have an in progress indicator that could go here + let result try { - item.push(true, await this[cmd]()) + result = await this[cmd]() + this.output(`${chalk.green('Ok')}${result ? `\n${result}` : ''}\n`) } catch (err) { - item.push(false, err) - } - if (!item[1]) { allOk = false - item[0] = this.npm.chalk.red(item[0]) - item[1] = this.npm.chalk.red('not ok') - item[2] = this.npm.chalk.magenta(String(item[2])) - } else { - item[1] = this.npm.chalk.green('ok') - } - if (!this.npm.silent) { - this.output(item) + this.output(`${chalk.red('Not ok')}\n${chalk.cyan(err)}\n`) } } @@ -155,8 +137,7 @@ class Doctor extends BaseCommand { } async checkPing () { - const tracker = log.newItem('checkPing', 1) - tracker.info('checkPing', 'Pinging registry') + log.info('doctor', 'Pinging registry') try { await ping({ ...this.npm.flatOptions, retry: false }) return '' @@ -166,23 +147,16 @@ class Doctor extends BaseCommand { } else { throw er.message } - } finally { - tracker.finish() } } async getLatestNpmVersion () { - const tracker = log.newItem('getLatestNpmVersion', 1) - tracker.info('getLatestNpmVersion', 'Getting npm package information') - try { - const latest = (await pacote.manifest('npm@latest', this.npm.flatOptions)).version - if (semver.gte(this.npm.version, latest)) { - return `current: v${this.npm.version}, latest: v${latest}` - } else { - throw `Use npm v${latest}` - } - } finally { - tracker.finish() + log.info('doctor', 'Getting npm package information') + const latest = (await pacote.manifest('npm@latest', this.npm.flatOptions)).version + if (semver.gte(this.npm.version, latest)) { + return `current: v${this.npm.version}, latest: v${latest}` + } else { + throw `Use npm v${latest}` } } @@ -191,36 +165,30 @@ class Doctor extends BaseCommand { const current = process.version const currentRange = `^${current}` const url = 'https://nodejs.org/dist/index.json' - const tracker = log.newItem('getLatestNodejsVersion', 1) - tracker.info('getLatestNodejsVersion', 'Getting Node.js release information') - try { - const res = await fetch(url, { method: 'GET', ...this.npm.flatOptions }) - const data = await res.json() - let maxCurrent = '0.0.0' - let maxLTS = '0.0.0' - for (const { lts, version } of data) { - if (lts && semver.gt(version, maxLTS)) { - maxLTS = version - } - - if (semver.satisfies(version, currentRange) && semver.gt(version, maxCurrent)) { - maxCurrent = version - } + log.info('doctor', 'Getting Node.js release information') + const res = await fetch(url, { method: 'GET', ...this.npm.flatOptions }) + const data = await res.json() + let maxCurrent = '0.0.0' + let maxLTS = '0.0.0' + for (const { lts, version } of data) { + if (lts && semver.gt(version, maxLTS)) { + maxLTS = version } - const recommended = semver.gt(maxCurrent, maxLTS) ? maxCurrent : maxLTS - if (semver.gte(process.version, recommended)) { - return `current: ${current}, recommended: ${recommended}` - } else { - throw `Use node ${recommended} (current: ${current})` + + if (semver.satisfies(version, currentRange) && semver.gt(version, maxCurrent)) { + maxCurrent = version } - } finally { - tracker.finish() + } + const recommended = semver.gt(maxCurrent, maxLTS) ? maxCurrent : maxLTS + if (semver.gte(process.version, recommended)) { + return `current: ${current}, recommended: ${recommended}` + } else { + throw `Use node ${recommended} (current: ${current})` } } - async getBinPath (dir) { - const tracker = log.newItem('getBinPath', 1) - tracker.info('getBinPath', 'Finding npm global bin in your PATH') + async getBinPath () { + log.info('doctor', 'getBinPath', 'Finding npm global bin in your PATH') if (!process.env.PATH.includes(this.npm.globalBin)) { throw new Error(`Add ${this.npm.globalBin} to your $PATH`) } @@ -250,30 +218,25 @@ class Doctor extends BaseCommand { async checkFilesPermission (root, shouldOwn, mask, missingOk) { let ok = true - const tracker = log.newItem(root, 1) - try { const uid = process.getuid() const gid = process.getgid() const files = new Set([root]) for (const f of files) { - tracker.silly('checkFilesPermission', f.slice(root.length + 1)) const st = await lstat(f).catch(er => { // if it can't be missing, or if it can and the error wasn't that it was missing if (!missingOk || er.code !== 'ENOENT') { ok = false - tracker.warn('checkFilesPermission', 'error getting info for ' + f) + log.warn('doctor', 'checkFilesPermission', 'error getting info for ' + f) } }) - tracker.completeWork(1) - if (!st) { continue } if (shouldOwn && (uid !== st.uid || gid !== st.gid)) { - tracker.warn('checkFilesPermission', 'should be owner of ' + f) + log.warn('doctor', 'checkFilesPermission', 'should be owner of ' + f) ok = false } @@ -286,14 +249,14 @@ class Doctor extends BaseCommand { } catch (er) { ok = false const msg = `Missing permissions on ${f} (expect: ${maskLabel(mask)})` - tracker.error('checkFilesPermission', msg) + log.error('doctor', 'checkFilesPermission', msg) continue } if (st.isDirectory()) { - const entries = await readdir(f).catch(er => { + const entries = await readdir(f).catch(() => { ok = false - tracker.warn('checkFilesPermission', 'error reading directory ' + f) + log.warn('doctor', 'checkFilesPermission', 'error reading directory ' + f) return [] }) for (const entry of entries) { @@ -302,7 +265,6 @@ class Doctor extends BaseCommand { } } } finally { - tracker.finish() if (!ok) { throw ( `Check the permissions of files in ${root}` + @@ -315,50 +277,43 @@ class Doctor extends BaseCommand { } async getGitPath () { - const tracker = log.newItem('getGitPath', 1) - tracker.info('getGitPath', 'Finding git in your PATH') - try { - return await which('git').catch(er => { - tracker.warn(er) - throw new Error("Install git and ensure it's in your PATH.") - }) - } finally { - tracker.finish() - } + log.info('doctor', 'Finding git in your PATH') + return await which('git').catch(er => { + log.warn('doctor', 'getGitPath', er) + throw new Error("Install git and ensure it's in your PATH.") + }) } async verifyCachedFiles () { - const tracker = log.newItem('verifyCachedFiles', 1) - tracker.info('verifyCachedFiles', 'Verifying the npm cache') - try { - const stats = await cacache.verify(this.npm.flatOptions.cache) - const { badContentCount, reclaimedCount, missingContent, reclaimedSize } = stats - if (badContentCount || reclaimedCount || missingContent) { - if (badContentCount) { - tracker.warn('verifyCachedFiles', `Corrupted content removed: ${badContentCount}`) - } + log.info('doctor', 'verifyCachedFiles', 'Verifying the npm cache') - if (reclaimedCount) { - tracker.warn( - 'verifyCachedFiles', - `Content garbage-collected: ${reclaimedCount} (${reclaimedSize} bytes)` - ) - } + const stats = await cacache.verify(this.npm.flatOptions.cache) + const { badContentCount, reclaimedCount, missingContent, reclaimedSize } = stats + if (badContentCount || reclaimedCount || missingContent) { + if (badContentCount) { + log.warn('doctor', 'verifyCachedFiles', `Corrupted content removed: ${badContentCount}`) + } - if (missingContent) { - tracker.warn('verifyCachedFiles', `Missing content: ${missingContent}`) - } + if (reclaimedCount) { + log.warn( + 'doctor', + 'verifyCachedFiles', + `Content garbage-collected: ${reclaimedCount} (${reclaimedSize} bytes)` + ) + } - tracker.warn('verifyCachedFiles', 'Cache issues have been fixed') + if (missingContent) { + log.warn('doctor', 'verifyCachedFiles', `Missing content: ${missingContent}`) } - tracker.info( - 'verifyCachedFiles', - `Verification complete. Stats: ${JSON.stringify(stats, null, 2)}` - ) - return `verified ${stats.verifiedContent} tarballs` - } finally { - tracker.finish() + + log.warn('doctor', 'verifyCachedFiles', 'Cache issues have been fixed') } + log.info( + 'doctor', + 'verifyCachedFiles', + `Verification complete. Stats: ${JSON.stringify(stats, null, 2)}` + ) + return `verified ${stats.verifiedContent} tarballs` } async checkNpmRegistry () { @@ -369,38 +324,11 @@ class Doctor extends BaseCommand { } } - output (row) { - const t = new Table({ - chars: { - top: '', - 'top-mid': '', - 'top-left': '', - 'top-right': '', - bottom: '', - 'bottom-mid': '', - 'bottom-left': '', - 'bottom-right': '', - left: '', - 'left-mid': '', - mid: '', - 'mid-mid': '', - right: '', - 'right-mid': '', - middle: ' ', - }, - style: { - 'padding-left': 0, - 'padding-right': 0, - // setting border here is not necessary visually since we've already - // zeroed out all the chars above, but without it cli-table3 will wrap - // some of the separator spaces with ansi codes which show up in - // snapshots. - border: 0, - }, - colWidths: [this.#checkWidth, 6], - }) - t.push(row) - this.npm.output(t.toString()) + output (...args) { + // TODO display layer should do this + if (!this.npm.silent) { + output.standard(...args) + } } actions (params) { diff --git a/deps/npm/lib/commands/edit.js b/deps/npm/lib/commands/edit.js index fbc7840a39876f..4110a1db55e825 100644 --- a/deps/npm/lib/commands/edit.js +++ b/deps/npm/lib/commands/edit.js @@ -1,34 +1,31 @@ -// npm edit -// open the package folder in the $EDITOR - const { resolve } = require('path') -const fs = require('graceful-fs') +const { lstat } = require('fs/promises') const cp = require('child_process') -const completion = require('../utils/completion/installed-shallow.js') -const BaseCommand = require('../base-command.js') +const completion = require('../utils/installed-shallow.js') +const BaseCommand = require('../base-cmd.js') -const splitPackageNames = (path) => { - return path.split('/') - // combine scoped parts - .reduce((parts, part) => { - if (parts.length === 0) { - return [part] - } +const splitPackageNames = (path) => path.split('/') +// combine scoped parts + .reduce((parts, part) => { + if (parts.length === 0) { + return [part] + } - const lastPart = parts[parts.length - 1] - // check if previous part is the first part of a scoped package - if (lastPart[0] === '@' && !lastPart.includes('/')) { - parts[parts.length - 1] += '/' + part - } else { - parts.push(part) - } + const lastPart = parts[parts.length - 1] + // check if previous part is the first part of a scoped package + if (lastPart[0] === '@' && !lastPart.includes('/')) { + parts[parts.length - 1] += '/' + part + } else { + parts.push(part) + } - return parts - }, []) - .join('/node_modules/') - .replace(/(\/node_modules)+/, '/node_modules') -} + return parts + }, []) + .join('/node_modules/') + .replace(/(\/node_modules)+/, '/node_modules') +// npm edit +// open the package folder in the $EDITOR class Edit extends BaseCommand { static description = 'Edit an installed package' static name = 'edit' @@ -50,27 +47,18 @@ class Edit extends BaseCommand { const path = splitPackageNames(args[0]) const dir = resolve(this.npm.dir, path) - // graceful-fs does not promisify + await lstat(dir) await new Promise((res, rej) => { - fs.lstat(dir, (err) => { - if (err) { - return rej(err) + const [bin, ...spawnArgs] = this.npm.config.get('editor').split(/\s+/) + const editor = cp.spawn(bin, [...spawnArgs, dir], { stdio: 'inherit' }) + editor.on('exit', async (code) => { + if (code) { + return rej(new Error(`editor process exited with code: ${code}`)) } - const [bin, ...spawnArgs] = this.npm.config.get('editor').split(/\s+/) - const editor = cp.spawn(bin, [...spawnArgs, dir], { stdio: 'inherit' }) - editor.on('exit', async (code) => { - if (code) { - return rej(new Error(`editor process exited with code: ${code}`)) - } - try { - await this.npm.exec('rebuild', [dir]) - } catch (execErr) { - rej(execErr) - } - res() - }) + await this.npm.exec('rebuild', [dir]).then(res).catch(rej) }) }) } } + module.exports = Edit diff --git a/deps/npm/lib/commands/exec.js b/deps/npm/lib/commands/exec.js index d532eca107c6c1..9bb4b15e0c5a3c 100644 --- a/deps/npm/lib/commands/exec.js +++ b/deps/npm/lib/commands/exec.js @@ -1,6 +1,6 @@ const { resolve } = require('path') const libexec = require('libnpmexec') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Exec extends BaseCommand { static description = 'Run a command from a local or remote npm package' @@ -65,7 +65,6 @@ class Exec extends BaseCommand { globalDir, chalk, } = this.npm - const output = this.npm.output.bind(this.npm) const scriptShell = this.npm.config.get('script-shell') || undefined const packages = this.npm.config.get('package') const yes = this.npm.config.get('yes') @@ -93,7 +92,6 @@ class Exec extends BaseCommand { globalPath, localBin, locationMsg, - output, packages, path, runPath, diff --git a/deps/npm/lib/commands/explain.js b/deps/npm/lib/commands/explain.js index 403274db68dfaf..2e7d07df729a8c 100644 --- a/deps/npm/lib/commands/explain.js +++ b/deps/npm/lib/commands/explain.js @@ -3,6 +3,7 @@ const npa = require('npm-package-arg') const semver = require('semver') const { relative, resolve } = require('path') const validName = require('validate-npm-package-name') +const { output } = require('proc-log') const ArboristWorkspaceCmd = require('../arborist-cmd.js') class Explain extends ArboristWorkspaceCmd { @@ -19,7 +20,7 @@ class Explain extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } @@ -75,9 +76,9 @@ class Explain extends ArboristWorkspaceCmd { } if (this.npm.flatOptions.json) { - this.npm.output(JSON.stringify(expls, null, 2)) + output.standard(JSON.stringify(expls, null, 2)) } else { - this.npm.output(expls.map(expl => { + output.standard(expls.map(expl => { return explainNode(expl, Infinity, this.npm.chalk) }).join('\n\n')) } @@ -125,4 +126,5 @@ class Explain extends ArboristWorkspaceCmd { }) } } + module.exports = Explain diff --git a/deps/npm/lib/commands/explore.js b/deps/npm/lib/commands/explore.js index 7a03ea4eabd7f6..d9dd9a9931f569 100644 --- a/deps/npm/lib/commands/explore.js +++ b/deps/npm/lib/commands/explore.js @@ -1,13 +1,12 @@ -// npm explore [@] -// open a subshell to the package folder. - const pkgJson = require('@npmcli/package-json') const runScript = require('@npmcli/run-script') const { join, relative } = require('path') -const log = require('../utils/log-shim.js') -const completion = require('../utils/completion/installed-shallow.js') -const BaseCommand = require('../base-command.js') +const { log, output } = require('proc-log') +const completion = require('../utils/installed-shallow.js') +const BaseCommand = require('../base-cmd.js') +// npm explore [@] +// open a subshell to the package folder. class Explore extends BaseCommand { static description = 'Browse an installed package' static name = 'explore' @@ -50,30 +49,26 @@ class Explore extends BaseCommand { } if (!args.length) { - this.npm.output(`\nExploring ${path}\nType 'exit' or ^D when finished\n`) + output.standard(`\nExploring ${path}\nType 'exit' or ^D when finished\n`) } - log.disableProgress() - try { - return await runScript({ - ...this.npm.flatOptions, - pkg, - banner: false, - path, - event: '_explore', - stdio: 'inherit', - }).catch(er => { - process.exitCode = typeof er.code === 'number' && er.code !== 0 ? er.code - : 1 + + return runScript({ + ...this.npm.flatOptions, + pkg, + path, + event: '_explore', + stdio: 'inherit', + }).catch(er => { + process.exitCode = typeof er.code === 'number' && er.code !== 0 ? er.code + : 1 // if it's not an exit error, or non-interactive, throw it - const isProcExit = er.message === 'command failed' && + const isProcExit = er.message === 'command failed' && (typeof er.code === 'number' || /^SIG/.test(er.signal || '')) - if (args.length || !isProcExit) { - throw er - } - }) - } finally { - log.enableProgress() - } + if (args.length || !isProcExit) { + throw er + } + }) } } + module.exports = Explore diff --git a/deps/npm/lib/commands/find-dupes.js b/deps/npm/lib/commands/find-dupes.js index 2e06e8b6bd93f4..735ac7c4a7ed09 100644 --- a/deps/npm/lib/commands/find-dupes.js +++ b/deps/npm/lib/commands/find-dupes.js @@ -1,6 +1,6 @@ -// dedupe duplicated packages, or find them in the tree const ArboristWorkspaceCmd = require('../arborist-cmd.js') +// dedupe duplicated packages, or find them in the tree class FindDupes extends ArboristWorkspaceCmd { static description = 'Find duplication in the package tree' static name = 'find-dupes' @@ -19,9 +19,10 @@ class FindDupes extends ArboristWorkspaceCmd { ...super.params, ] - async exec (args) { + async exec () { this.npm.config.set('dry-run', true) return this.npm.exec('dedupe', []) } } + module.exports = FindDupes diff --git a/deps/npm/lib/commands/fund.js b/deps/npm/lib/commands/fund.js index 2804d36cd56034..8bcd184e709683 100644 --- a/deps/npm/lib/commands/fund.js +++ b/deps/npm/lib/commands/fund.js @@ -1,6 +1,7 @@ const archy = require('archy') const pacote = require('pacote') const semver = require('semver') +const { output } = require('proc-log') const npa = require('npm-package-arg') const { depth } = require('treeverse') const { readTree: getFundingInfo, normalizeFunding, isValidFunding } = require('libnpmfund') @@ -37,7 +38,7 @@ class Fund extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } @@ -85,9 +86,9 @@ class Fund extends ArboristWorkspaceCmd { }) if (this.npm.config.get('json')) { - this.npm.output(this.printJSON(fundingInfo)) + output.standard(this.printJSON(fundingInfo)) } else { - this.npm.output(this.printHuman(fundingInfo)) + output.standard(this.printHuman(fundingInfo)) } } @@ -110,26 +111,25 @@ class Fund extends ArboristWorkspaceCmd { const [fundingSource] = [].concat(normalizeFunding(funding)).filter(isValidFunding) const { url } = fundingSource || {} const pkgRef = getPrintableName({ name, version }) - let item = { - label: pkgRef, - } - if (url) { - item.label = tree({ - label: this.npm.chalk.bgBlack.white(url), + if (!url) { + return { label: pkgRef } + } + let item + if (seenUrls.has(url)) { + item = seenUrls.get(url) + item.label += `${this.npm.chalk.dim(',')} ${pkgRef}` + return null + } + item = { + label: tree({ + label: this.npm.chalk.blue(url), nodes: [pkgRef], - }).trim() - - // stacks all packages together under the same item - if (seenUrls.has(url)) { - item = seenUrls.get(url) - item.label += `, ${pkgRef}` - return null - } else { - seenUrls.set(url, item) - } + }).trim(), } + // stacks all packages together under the same item + seenUrls.set(url, item) return item }, @@ -153,7 +153,7 @@ class Fund extends ArboristWorkspaceCmd { }) const res = tree(result) - return this.npm.chalk.reset(res) + return res } async openFundingUrl ({ path, tree, spec, fundingSourceNumber }) { @@ -212,7 +212,7 @@ class Fund extends ArboristWorkspaceCmd { if (fundingSourceNumber) { ambiguousUrlMsg.unshift(`--which=${fundingSourceNumber} is not a valid index`) } - this.npm.output(ambiguousUrlMsg.join('\n')) + output.standard(ambiguousUrlMsg.join('\n')) } urlMessage (source) { @@ -222,4 +222,5 @@ class Fund extends ArboristWorkspaceCmd { return [url, message] } } + module.exports = Fund diff --git a/deps/npm/lib/commands/get.js b/deps/npm/lib/commands/get.js index 4bf5d2caf82645..4191f2c973e7d3 100644 --- a/deps/npm/lib/commands/get.js +++ b/deps/npm/lib/commands/get.js @@ -1,5 +1,5 @@ const Npm = require('../npm.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Get extends BaseCommand { static description = 'Get a value from the npm configuration' @@ -19,4 +19,5 @@ class Get extends BaseCommand { return this.npm.exec('config', ['get'].concat(args)) } } + module.exports = Get diff --git a/deps/npm/lib/commands/help-search.js b/deps/npm/lib/commands/help-search.js index 273807c7469af0..72dd03ac7406ec 100644 --- a/deps/npm/lib/commands/help-search.js +++ b/deps/npm/lib/commands/help-search.js @@ -1,7 +1,8 @@ -const { readFile } = require('fs/promises') -const path = require('path') +const { readFile } = require('node:fs/promises') +const path = require('node:path') const { glob } = require('glob') -const BaseCommand = require('../base-command.js') +const { output } = require('proc-log') +const BaseCommand = require('../base-cmd.js') const globify = pattern => pattern.split('\\').join('/') @@ -21,12 +22,12 @@ class HelpSearch extends BaseCommand { // preserve glob@8 behavior files = files.sort((a, b) => a.localeCompare(b, 'en')) const data = await this.readFiles(files) - const results = await this.searchFiles(args, data, files) + const results = await this.searchFiles(args, data) const formatted = this.formatResults(args, results) if (!formatted.trim()) { - this.npm.output(`No matches in help for: ${args.join(' ')}\n`) + output.standard(`No matches in help for: ${args.join(' ')}\n`) } else { - this.npm.output(formatted) + output.standard(formatted) } } @@ -39,7 +40,7 @@ class HelpSearch extends BaseCommand { return res } - async searchFiles (args, data, files) { + async searchFiles (args, data) { const results = [] for (const [file, content] of Object.entries(data)) { const lowerCase = content.toLowerCase() @@ -140,7 +141,7 @@ class HelpSearch extends BaseCommand { formatResults (args, results) { const cols = Math.min(process.stdout.columns || Infinity, 80) + 1 - const output = results.map(res => { + const formattedOutput = results.map(res => { const out = [res.cmd] const r = Object.keys(res.hits) .map(k => `${k}:${res.hits[k]}`) @@ -169,8 +170,7 @@ class HelpSearch extends BaseCommand { for (const f of finder) { hilitLine.push(line.slice(p, p + f.length)) const word = line.slice(p + f.length, p + f.length + arg.length) - const hilit = this.npm.chalk.bgBlack.red(word) - hilitLine.push(hilit) + hilitLine.push(this.npm.chalk.blue(word)) p += f.length + arg.length } } @@ -183,12 +183,13 @@ class HelpSearch extends BaseCommand { const finalOut = results.length && !this.npm.config.get('long') ? 'Top hits for ' + (args.map(JSON.stringify).join(' ')) + '\n' + '—'.repeat(cols - 1) + '\n' + - output + '\n' + + formattedOutput + '\n' + '—'.repeat(cols - 1) + '\n' + '(run with -l or --long to see more context)' - : output + : formattedOutput return finalOut.trim() } } + module.exports = HelpSearch diff --git a/deps/npm/lib/commands/help.js b/deps/npm/lib/commands/help.js index 39c580f9a68715..fb3fe664e017df 100644 --- a/deps/npm/lib/commands/help.js +++ b/deps/npm/lib/commands/help.js @@ -2,11 +2,12 @@ const spawn = require('@npmcli/promise-spawn') const path = require('path') const openUrl = require('../utils/open-url.js') const { glob } = require('glob') +const { output } = require('proc-log') const localeCompare = require('@isaacs/string-locale-compare')('en') const { deref } = require('../utils/cmd-list.js') +const BaseCommand = require('../base-cmd.js') const globify = pattern => pattern.split('\\').join('/') -const BaseCommand = require('../base-command.js') // Strips out the number from foo.7 or foo.7. or foo.7.tgz // We don't currently compress our man pages but if we ever did this would @@ -50,7 +51,7 @@ class Help extends BaseCommand { const manSearch = /^\d+$/.test(args[0]) ? `man${args.shift()}` : 'man*' if (!args.length) { - return this.npm.output(this.npm.usage) + return output.standard(this.npm.usage) } // npm help foo bar baz: search topics @@ -110,4 +111,5 @@ class Help extends BaseCommand { return 'file:///' + path.resolve(this.npm.npmRoot, `docs/output/${sect}/${f}.html`) } } + module.exports = Help diff --git a/deps/npm/lib/commands/hook.js b/deps/npm/lib/commands/hook.js index b0f52a801f5717..3b91ff539081a9 100644 --- a/deps/npm/lib/commands/hook.js +++ b/deps/npm/lib/commands/hook.js @@ -1,9 +1,9 @@ const hookApi = require('libnpmhook') const otplease = require('../utils/otplease.js') const relativeDate = require('tiny-relative-date') -const Table = require('cli-table3') +const { output } = require('proc-log') +const BaseCommand = require('../base-cmd.js') -const BaseCommand = require('../base-command.js') class Hook extends BaseCommand { static description = 'Manage registry hooks' static name = 'hook' @@ -40,86 +40,70 @@ class Hook extends BaseCommand { async add (pkg, uri, secret, opts) { const hook = await hookApi.add(pkg, uri, secret, opts) if (opts.json) { - this.npm.output(JSON.stringify(hook, null, 2)) + output.standard(JSON.stringify(hook, null, 2)) } else if (opts.parseable) { - this.npm.output(Object.keys(hook).join('\t')) - this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) + output.standard(Object.keys(hook).join('\t')) + output.standard(Object.keys(hook).map(k => hook[k]).join('\t')) } else if (!this.npm.silent) { - this.npm.output(`+ ${this.hookName(hook)} ${opts.unicode ? ' ➜ ' : ' -> '} ${hook.endpoint}`) + output.standard(`+ ${this.hookName(hook)} ${opts.unicode ? ' ➜ ' : ' -> '} ${hook.endpoint}`) } } async ls (pkg, opts) { const hooks = await hookApi.ls({ ...opts, package: pkg }) + if (opts.json) { - this.npm.output(JSON.stringify(hooks, null, 2)) + output.standard(JSON.stringify(hooks, null, 2)) } else if (opts.parseable) { - this.npm.output(Object.keys(hooks[0]).join('\t')) + output.standard(Object.keys(hooks[0]).join('\t')) hooks.forEach(hook => { - this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) + output.standard(Object.keys(hook).map(k => hook[k]).join('\t')) }) } else if (!hooks.length) { - this.npm.output("You don't have any hooks configured yet.") + output.standard("You don't have any hooks configured yet.") } else if (!this.npm.silent) { - if (hooks.length === 1) { - this.npm.output('You have one hook configured.') - } else { - this.npm.output(`You have ${hooks.length} hooks configured.`) - } + output.standard(`You have ${hooks.length} hook${hooks.length !== 1 ? 's' : ''} configured.`) - const table = new Table({ head: ['id', 'target', 'endpoint'] }) - hooks.forEach((hook) => { - table.push([ - { rowSpan: 2, content: hook.id }, - this.hookName(hook), - hook.endpoint, - ]) + for (const hook of hooks) { + output.standard(`Hook ${hook.id}: ${this.hookName(hook)}`) + output.standard(`Endpoint: ${hook.endpoint}`) if (hook.last_delivery) { - table.push([ - { - colSpan: 1, - content: `triggered ${relativeDate(hook.last_delivery)}`, - }, - hook.response_code, - ]) + /* eslint-disable-next-line max-len */ + output.standard(`Triggered ${relativeDate(hook.last_delivery)}, response code was "${hook.response_code}"\n`) } else { - table.push([{ colSpan: 2, content: 'never triggered' }]) + output.standard('Never triggered\n') } - }) - this.npm.output(table.toString()) + } } } async rm (id, opts) { const hook = await hookApi.rm(id, opts) if (opts.json) { - this.npm.output(JSON.stringify(hook, null, 2)) + output.standard(JSON.stringify(hook, null, 2)) } else if (opts.parseable) { - this.npm.output(Object.keys(hook).join('\t')) - this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) + output.standard(Object.keys(hook).join('\t')) + output.standard(Object.keys(hook).map(k => hook[k]).join('\t')) } else if (!this.npm.silent) { - this.npm.output(`- ${this.hookName(hook)} ${opts.unicode ? ' ✘ ' : ' X '} ${hook.endpoint}`) + output.standard(`- ${this.hookName(hook)} ${opts.unicode ? ' ✘ ' : ' X '} ${hook.endpoint}`) } } async update (id, uri, secret, opts) { const hook = await hookApi.update(id, uri, secret, opts) if (opts.json) { - this.npm.output(JSON.stringify(hook, null, 2)) + output.standard(JSON.stringify(hook, null, 2)) } else if (opts.parseable) { - this.npm.output(Object.keys(hook).join('\t')) - this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) + output.standard(Object.keys(hook).join('\t')) + output.standard(Object.keys(hook).map(k => hook[k]).join('\t')) } else if (!this.npm.silent) { - this.npm.output(`+ ${this.hookName(hook)} ${opts.unicode ? ' ➜ ' : ' -> '} ${hook.endpoint}`) + output.standard(`+ ${this.hookName(hook)} ${opts.unicode ? ' ➜ ' : ' -> '} ${hook.endpoint}`) } } hookName (hook) { - let target = hook.name - if (hook.type === 'owner') { - target = '~' + target - } - return target + return `${hook.type === 'owner' ? '~' : ''}${hook.name}` } } + module.exports = Hook diff --git a/deps/npm/lib/commands/init.js b/deps/npm/lib/commands/init.js index 030c97356edb83..205352e86e6edc 100644 --- a/deps/npm/lib/commands/init.js +++ b/deps/npm/lib/commands/init.js @@ -1,4 +1,4 @@ -const fs = require('fs') +const { statSync } = require('fs') const { relative, resolve } = require('path') const { mkdir } = require('fs/promises') const initJson = require('init-package-json') @@ -6,13 +6,12 @@ const npa = require('npm-package-arg') const libexec = require('libnpmexec') const mapWorkspaces = require('@npmcli/map-workspaces') const PackageJson = require('@npmcli/package-json') -const log = require('../utils/log-shim.js') -const updateWorkspaces = require('../workspaces/update-workspaces.js') +const { log, output, input } = require('proc-log') +const updateWorkspaces = require('../utils/update-workspaces.js') +const BaseCommand = require('../base-cmd.js') const posixPath = p => p.split('\\').join('/') -const BaseCommand = require('../base-command.js') - class Init extends BaseCommand { static description = 'Create a package.json file' static params = [ @@ -60,7 +59,7 @@ class Init extends BaseCommand { // to create a workspace package.json file or its folders const { content: pkg } = await PackageJson.normalize(this.npm.localPrefix).catch(err => { if (err.code === 'ENOENT') { - log.warn('Missing package.json. Try with `--include-workspace-root`.') + log.warn('init', 'Missing package.json. Try with `--include-workspace-root`.') } throw err }) @@ -130,7 +129,6 @@ class Init extends BaseCommand { globalBin, chalk, } = this.npm - const output = this.npm.output.bind(this.npm) const runPath = path const scriptShell = this.npm.config.get('script-shell') || undefined const yes = this.npm.config.get('yes') @@ -150,12 +148,9 @@ class Init extends BaseCommand { } async template (path = process.cwd()) { - log.pause() - log.disableProgress() - const initFile = this.npm.config.get('init-module') if (!this.npm.config.get('yes') && !this.npm.config.get('force')) { - this.npm.output([ + output.standard([ 'This utility will walk you through creating a package.json file.', 'It only covers the most common items, and tries to guess sensible defaults.', '', @@ -170,7 +165,7 @@ class Init extends BaseCommand { } try { - const data = await initJson(path, initFile, this.npm.config) + const data = await input.read(() => initJson(path, initFile, this.npm.config)) log.silly('package data', data) return data } catch (er) { @@ -179,9 +174,6 @@ class Init extends BaseCommand { } else { throw er } - } finally { - log.resume() - log.enableProgress() } } @@ -200,7 +192,7 @@ class Init extends BaseCommand { // mapWorkspaces, so we're just going to avoid touching the // top-level package.json try { - fs.statSync(resolve(workspacePath, 'package.json')) + statSync(resolve(workspacePath, 'package.json')) } catch (err) { return } diff --git a/deps/npm/lib/commands/install-ci-test.js b/deps/npm/lib/commands/install-ci-test.js index f7a357ba6e1246..4b9dd269f8c748 100644 --- a/deps/npm/lib/commands/install-ci-test.js +++ b/deps/npm/lib/commands/install-ci-test.js @@ -1,8 +1,7 @@ -// npm install-ci-test -// Runs `npm ci` and then runs `npm test` - const CI = require('./ci.js') +// npm install-ci-test +// Runs `npm ci` and then runs `npm test` class InstallCITest extends CI { static description = 'Install a project with a clean slate and run tests' static name = 'install-ci-test' @@ -12,4 +11,5 @@ class InstallCITest extends CI { return this.npm.exec('test', []) } } + module.exports = InstallCITest diff --git a/deps/npm/lib/commands/install-test.js b/deps/npm/lib/commands/install-test.js index 11f22e535403cc..e21ca7c929c55e 100644 --- a/deps/npm/lib/commands/install-test.js +++ b/deps/npm/lib/commands/install-test.js @@ -1,8 +1,7 @@ -// npm install-test -// Runs `npm install` and then runs `npm test` - const Install = require('./install.js') +// npm install-test +// Runs `npm install` and then runs `npm test` class InstallTest extends Install { static description = 'Install package(s) and run tests' static name = 'install-test' @@ -12,4 +11,5 @@ class InstallTest extends Install { return this.npm.exec('test', []) } } + module.exports = InstallTest diff --git a/deps/npm/lib/commands/install.js b/deps/npm/lib/commands/install.js index d04a35fbec2a76..24e5f6819b3141 100644 --- a/deps/npm/lib/commands/install.js +++ b/deps/npm/lib/commands/install.js @@ -1,15 +1,12 @@ -/* eslint-disable camelcase */ -const fs = require('fs') -const util = require('util') -const readdir = util.promisify(fs.readdir) -const reifyFinish = require('../utils/reify-finish.js') -const log = require('../utils/log-shim.js') -const { resolve, join } = require('path') +const { readdir } = require('node:fs/promises') +const { resolve, join } = require('node:path') +const { log } = require('proc-log') const runScript = require('@npmcli/run-script') const pacote = require('pacote') const checks = require('npm-install-checks') - +const reifyFinish = require('../utils/reify-finish.js') const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Install extends ArboristWorkspaceCmd { static description = 'Install a package' static name = 'install' @@ -168,7 +165,6 @@ class Install extends ArboristWorkspaceCmd { args: [], scriptShell, stdio: 'inherit', - banner: !this.npm.silent, event, }) } @@ -176,4 +172,5 @@ class Install extends ArboristWorkspaceCmd { await reifyFinish(this.npm, arb) } } + module.exports = Install diff --git a/deps/npm/lib/commands/link.js b/deps/npm/lib/commands/link.js index cdc248569849c3..bde761c4226dcd 100644 --- a/deps/npm/lib/commands/link.js +++ b/deps/npm/lib/commands/link.js @@ -1,15 +1,11 @@ -const fs = require('fs') -const util = require('util') -const readdir = util.promisify(fs.readdir) +const { readdir } = require('fs/promises') const { resolve } = require('path') - const npa = require('npm-package-arg') const pkgJson = require('@npmcli/package-json') const semver = require('semver') - const reifyFinish = require('../utils/reify-finish.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Link extends ArboristWorkspaceCmd { static description = 'Symlink a package folder' static name = 'link' @@ -189,4 +185,5 @@ class Link extends ArboristWorkspaceCmd { return missing } } + module.exports = Link diff --git a/deps/npm/lib/commands/login.js b/deps/npm/lib/commands/login.js index dc4ed8a67acd97..630abf9ac8e045 100644 --- a/deps/npm/lib/commands/login.js +++ b/deps/npm/lib/commands/login.js @@ -1,8 +1,7 @@ -const log = require('../utils/log-shim.js') -const replaceInfo = require('../utils/replace-info.js') +const { log, output } = require('proc-log') +const { redactLog: replaceInfo } = require('@npmcli/redact') const auth = require('../utils/auth.js') - -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Login extends BaseCommand { static description = 'Login to a registry user account' @@ -13,7 +12,7 @@ class Login extends BaseCommand { 'auth-type', ] - async exec (args) { + async exec () { const scope = this.npm.config.get('scope') let registry = this.npm.config.get('registry') @@ -27,7 +26,6 @@ class Login extends BaseCommand { const creds = this.npm.config.getCredentialsByURI(registry) - log.disableProgress() log.notice('', `Log in on ${replaceInfo(registry)}`) const { message, newCreds } = await auth.login(this.npm, { @@ -45,7 +43,8 @@ class Login extends BaseCommand { await this.npm.config.save('user') - this.npm.output(message) + output.standard(message) } } + module.exports = Login diff --git a/deps/npm/lib/commands/logout.js b/deps/npm/lib/commands/logout.js index 665580930639cf..dc5a0dfda0e98e 100644 --- a/deps/npm/lib/commands/logout.js +++ b/deps/npm/lib/commands/logout.js @@ -1,7 +1,7 @@ const npmFetch = require('npm-registry-fetch') const { getAuth } = npmFetch -const log = require('../utils/log-shim') -const BaseCommand = require('../base-command.js') +const { log } = require('proc-log') +const BaseCommand = require('../base-cmd.js') class Logout extends BaseCommand { static description = 'Log out of the registry' @@ -11,7 +11,7 @@ class Logout extends BaseCommand { 'scope', ] - async exec (args) { + async exec () { const registry = this.npm.config.get('registry') const scope = this.npm.config.get('scope') const regRef = scope ? `${scope}:registry` : 'registry' @@ -46,4 +46,5 @@ class Logout extends BaseCommand { await this.npm.config.save(level) } } + module.exports = Logout diff --git a/deps/npm/lib/commands/ls.js b/deps/npm/lib/commands/ls.js index 3f9775cf125040..51e99f429816a9 100644 --- a/deps/npm/lib/commands/ls.js +++ b/deps/npm/lib/commands/ls.js @@ -1,10 +1,12 @@ const { resolve, relative, sep } = require('path') -const relativePrefix = `.${sep}` -const { EOL } = require('os') - const archy = require('archy') const { breadth } = require('treeverse') const npa = require('npm-package-arg') +const { output } = require('proc-log') +const ArboristWorkspaceCmd = require('../arborist-cmd.js') +const localeCompare = require('@isaacs/string-locale-compare')('en') + +const relativePrefix = `.${sep}` const _depth = Symbol('depth') const _dedupe = Symbol('dedupe') @@ -17,8 +19,6 @@ const _parent = Symbol('parent') const _problems = Symbol('problems') const _required = Symbol('required') const _type = Symbol('type') -const ArboristWorkspaceCmd = require('../arborist-cmd.js') -const localeCompare = require('@isaacs/string-locale-compare')('en') class LS extends ArboristWorkspaceCmd { static description = 'List installed packages' @@ -42,7 +42,7 @@ class LS extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } @@ -177,7 +177,7 @@ class LS extends ArboristWorkspaceCmd { const [rootError] = tree.errors.filter(e => e.code === 'EJSONPARSE' && e.path === resolve(path, 'package.json')) - this.npm.outputBuffer( + output.buffer( json ? jsonOutput({ path, problems, result, rootError, seenItems }) : parseable ? parseableOutput({ seenNodes, global, long }) : humanOutput({ chalk, result, seenItems, unicode }) @@ -200,7 +200,7 @@ class LS extends ArboristWorkspaceCmd { if (shouldThrow) { throw Object.assign( - new Error([...problems].join(EOL)), + new Error([...problems].join('\n')), { code: 'ELSPROBLEMS' } ) } @@ -219,6 +219,7 @@ class LS extends ArboristWorkspaceCmd { return tree } } + module.exports = LS const isGitNode = (node) => { @@ -280,7 +281,7 @@ const augmentItemWithIncludeMetadata = (node, item) => { const getHumanOutputItem = (node, { args, chalk, global, long }) => { const { pkgid, path } = node - const workspacePkgId = chalk.green(pkgid) + const workspacePkgId = chalk.blueBright(pkgid) let printable = node.isWorkspace ? workspacePkgId : pkgid // special formatting for top-level package name @@ -289,14 +290,16 @@ const getHumanOutputItem = (node, { args, chalk, global, long }) => { if (hasNoPackageJson || global) { printable = path } else { - printable += `${long ? EOL : ' '}${path}` + printable += `${long ? '\n' : ' '}${path}` } } + // TODO there is a LOT of overlap with lib/utils/explain-dep.js here + const highlightDepName = args.length && node[_filteredBy] const missingColor = isOptional(node) - ? chalk.yellow.bgBlack - : chalk.red.bgBlack + ? chalk.yellow + : chalk.red const missingMsg = `UNMET ${isOptional(node) ? 'OPTIONAL ' : ''}DEPENDENCY` const targetLocation = node.root ? relative(node.root.realpath, node.realpath) @@ -310,30 +313,30 @@ const getHumanOutputItem = (node, { args, chalk, global, long }) => { ? missingColor(missingMsg) + ' ' : '' ) + - `${highlightDepName ? chalk.yellow.bgBlack(printable) : printable}` + + `${highlightDepName ? chalk.yellow(printable) : printable}` + ( node[_dedupe] - ? ' ' + chalk.gray('deduped') + ? ' ' + chalk.dim('deduped') : '' ) + ( invalid - ? ' ' + chalk.red.bgBlack(invalid) + ? ' ' + chalk.red(invalid) : '' ) + ( isExtraneous(node, { global }) - ? ' ' + chalk.green.bgBlack('extraneous') + ? ' ' + chalk.red('extraneous') : '' ) + ( node.overridden - ? ' ' + chalk.gray('overridden') + ? ' ' + chalk.dim('overridden') : '' ) + (isGitNode(node) ? ` (${node.resolved})` : '') + (node.isLink ? ` -> ${relativePrefix}${targetLocation}` : '') + - (long ? `${EOL}${node.package.description || ''}` : '') + (long ? `\n${node.package.description || ''}` : '') return augmentItemWithIncludeMetadata(node, { label, nodes: [] }) } @@ -566,7 +569,7 @@ const parseableOutput = ({ global, long, seenNodes }) => { out += node[_invalid] ? ':INVALID' : '' out += node.overridden ? ':OVERRIDDEN' : '' } - out += EOL + out += '\n' } } return out.trim() diff --git a/deps/npm/lib/commands/org.js b/deps/npm/lib/commands/org.js index 1f32d41ff73068..af67547a643db2 100644 --- a/deps/npm/lib/commands/org.js +++ b/deps/npm/lib/commands/org.js @@ -1,7 +1,7 @@ const liborg = require('libnpmorg') const otplease = require('../utils/otplease.js') -const Table = require('cli-table3') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') +const { output } = require('proc-log') class Org extends BaseCommand { static description = 'Manage orgs' @@ -68,14 +68,14 @@ class Org extends BaseCommand { const memDeets = await liborg.set(org, user, role, opts) if (opts.json) { - this.npm.output(JSON.stringify(memDeets, null, 2)) + output.standard(JSON.stringify(memDeets, null, 2)) } else if (opts.parseable) { - this.npm.output(['org', 'orgsize', 'user', 'role'].join('\t')) - this.npm.output( + output.standard(['org', 'orgsize', 'user', 'role'].join('\t')) + output.standard( [memDeets.org.name, memDeets.org.size, memDeets.user, memDeets.role].join('\t') ) } else if (!this.npm.silent) { - this.npm.output( + output.standard( `Added ${memDeets.user} as ${memDeets.role} to ${memDeets.org.name}. You now have ${ memDeets.org.size } member${memDeets.org.size === 1 ? '' : 's'} in this org.` @@ -100,7 +100,7 @@ class Org extends BaseCommand { org = org.replace(/^[~@]?/, '') const userCount = Object.keys(roster).length if (opts.json) { - this.npm.output( + output.standard( JSON.stringify({ user, org, @@ -109,10 +109,10 @@ class Org extends BaseCommand { }) ) } else if (opts.parseable) { - this.npm.output(['user', 'org', 'userCount', 'deleted'].join('\t')) - this.npm.output([user, org, userCount, true].join('\t')) + output.standard(['user', 'org', 'userCount', 'deleted'].join('\t')) + output.standard([user, org, userCount, true].join('\t')) } else if (!this.npm.silent) { - this.npm.output( + output.standard( `Successfully removed ${user} from ${org}. You now have ${userCount} member${ userCount === 1 ? '' : 's' } in this org.` @@ -135,21 +135,19 @@ class Org extends BaseCommand { roster = newRoster } if (opts.json) { - this.npm.output(JSON.stringify(roster, null, 2)) + output.standard(JSON.stringify(roster, null, 2)) } else if (opts.parseable) { - this.npm.output(['user', 'role'].join('\t')) + output.standard(['user', 'role'].join('\t')) Object.keys(roster).forEach(u => { - this.npm.output([u, roster[u]].join('\t')) + output.standard([u, roster[u]].join('\t')) }) } else if (!this.npm.silent) { - const table = new Table({ head: ['user', 'role'] }) - Object.keys(roster) - .sort() - .forEach(u => { - table.push([u, roster[u]]) - }) - this.npm.output(table.toString()) + const chalk = this.npm.chalk + for (const u of Object.keys(roster).sort()) { + output.standard(`${u} - ${chalk.cyan(roster[u])}`) + } } } } + module.exports = Org diff --git a/deps/npm/lib/commands/outdated.js b/deps/npm/lib/commands/outdated.js index 4216f1cdb1437f..2249808110bbbf 100644 --- a/deps/npm/lib/commands/outdated.js +++ b/deps/npm/lib/commands/outdated.js @@ -1,12 +1,11 @@ -const os = require('node:os') const { resolve } = require('node:path') const { stripVTControlCharacters } = require('node:util') const pacote = require('pacote') const table = require('text-table') const npa = require('npm-package-arg') const pickManifest = require('npm-pick-manifest') +const { output } = require('proc-log') const localeCompare = require('@isaacs/string-locale-compare')('en') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') class Outdated extends ArboristWorkspaceCmd { @@ -84,9 +83,9 @@ class Outdated extends ArboristWorkspaceCmd { // display results if (this.npm.config.get('json')) { - this.npm.output(this.makeJSON(outdated)) + output.standard(this.makeJSON(outdated)) } else if (this.npm.config.get('parseable')) { - this.npm.output(this.makeParseable(outdated)) + output.standard(this.makeParseable(outdated)) } else { const outList = outdated.map(x => this.makePretty(x)) const outHead = ['Package', @@ -102,13 +101,13 @@ class Outdated extends ArboristWorkspaceCmd { } const outTable = [outHead].concat(outList) - outTable[0] = outTable[0].map(heading => this.npm.chalk.underline(heading)) + outTable[0] = outTable[0].map(heading => this.npm.chalk.bold.underline(heading)) const tableOpts = { align: ['l', 'r', 'r', 'r', 'l'], stringLength: s => stripVTControlCharacters(s).length, } - this.npm.output(table(outTable, tableOpts)) + output.standard(table(outTable, tableOpts)) } } @@ -161,7 +160,7 @@ class Outdated extends ArboristWorkspaceCmd { this.edges.add(edge) } - getWorkspacesEdges (node) { + getWorkspacesEdges () { if (this.npm.global) { return } @@ -278,7 +277,7 @@ class Outdated extends ArboristWorkspaceCmd { : node.name return humanOutput - ? this.npm.chalk.green(workspaceName) + ? this.npm.chalk.blue(workspaceName) : workspaceName } @@ -295,17 +294,20 @@ class Outdated extends ArboristWorkspaceCmd { dependent, } = dep - const columns = [name, current, wanted, latest, location, dependent] + const columns = [ + this.npm.chalk[current === wanted ? 'yellow' : 'red'](name), + current, + this.npm.chalk.cyan(wanted), + this.npm.chalk.blue(latest), + location, + dependent, + ] if (this.npm.config.get('long')) { columns[6] = type - columns[7] = homepage + columns[7] = this.npm.chalk.blue(homepage) } - columns[0] = this.npm.chalk[current === wanted ? 'yellow' : 'red'](columns[0]) // current - columns[2] = this.npm.chalk.green(columns[2]) // wanted - columns[3] = this.npm.chalk.magenta(columns[3]) // latest - return columns } @@ -335,7 +337,7 @@ class Outdated extends ArboristWorkspaceCmd { } return out.join(':') - }).join(os.EOL) + }).join('\n') } makeJSON (list) { @@ -366,4 +368,5 @@ class Outdated extends ArboristWorkspaceCmd { return JSON.stringify(out, null, 2) } } + module.exports = Outdated diff --git a/deps/npm/lib/commands/owner.js b/deps/npm/lib/commands/owner.js index 5b54dd41f3d607..188065583198d0 100644 --- a/deps/npm/lib/commands/owner.js +++ b/deps/npm/lib/commands/owner.js @@ -1,10 +1,11 @@ const npa = require('npm-package-arg') const npmFetch = require('npm-registry-fetch') const pacote = require('pacote') -const log = require('../utils/log-shim') +const { log, output } = require('proc-log') const otplease = require('../utils/otplease.js') const pkgJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') +const { redact } = require('@npmcli/redact') const readJson = async (path) => { try { @@ -114,12 +115,12 @@ class Owner extends BaseCommand { const packumentOpts = { ...this.npm.flatOptions, fullMetadata: true, preferOnline: true } const { maintainers } = await pacote.packument(spec, packumentOpts) if (!maintainers || !maintainers.length) { - this.npm.output('no admin found') + output.standard('no admin found') } else { - this.npm.output(maintainers.map(m => `${m.name} <${m.email}>`).join('\n')) + output.standard(maintainers.map(m => `${m.name} <${m.email}>`).join('\n')) } } catch (err) { - log.error('owner ls', "Couldn't get owner data", npmFetch.cleanUrl(pkg)) + log.error('owner ls', "Couldn't get owner data", redact(pkg)) throw err } } @@ -215,9 +216,9 @@ class Owner extends BaseCommand { }) }) if (addOrRm === 'add') { - this.npm.output(`+ ${user} (${spec.name})`) + output.standard(`+ ${user} (${spec.name})`) } else { - this.npm.output(`- ${user} (${spec.name})`) + output.standard(`- ${user} (${spec.name})`) } return res } catch (err) { diff --git a/deps/npm/lib/commands/pack.js b/deps/npm/lib/commands/pack.js index 6d5f00df55e3fc..f64a21dcc0d9de 100644 --- a/deps/npm/lib/commands/pack.js +++ b/deps/npm/lib/commands/pack.js @@ -1,9 +1,9 @@ const pacote = require('pacote') const libpack = require('libnpmpack') const npa = require('npm-package-arg') -const log = require('../utils/log-shim') +const { log, output } = require('proc-log') const { getContents, logTar } = require('../utils/tar.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Pack extends BaseCommand { static description = 'Create a tarball from a package' @@ -58,13 +58,13 @@ class Pack extends BaseCommand { } if (json) { - this.npm.output(JSON.stringify(tarballs, null, 2)) + output.standard(JSON.stringify(tarballs, null, 2)) return } for (const tar of tarballs) { logTar(tar, { unicode }) - this.npm.output(tar.filename.replace(/^@/, '').replace(/\//, '-')) + output.standard(tar.filename.replace(/^@/, '').replace(/\//, '-')) } } @@ -83,4 +83,5 @@ class Pack extends BaseCommand { return this.exec([...this.workspacePaths, ...args.filter(a => a !== '.')]) } } + module.exports = Pack diff --git a/deps/npm/lib/commands/ping.js b/deps/npm/lib/commands/ping.js index c79e6a96cee405..0d057862baa8fe 100644 --- a/deps/npm/lib/commands/ping.js +++ b/deps/npm/lib/commands/ping.js @@ -1,29 +1,30 @@ -const { cleanUrl } = require('npm-registry-fetch') -const log = require('../utils/log-shim') +const { redact } = require('@npmcli/redact') +const { log, output } = require('proc-log') const pingUtil = require('../utils/ping.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Ping extends BaseCommand { static description = 'Ping npm registry' static params = ['registry'] static name = 'ping' - async exec (args) { - const cleanRegistry = cleanUrl(this.npm.config.get('registry')) + async exec () { + const cleanRegistry = redact(this.npm.config.get('registry')) log.notice('PING', cleanRegistry) const start = Date.now() const details = await pingUtil({ ...this.npm.flatOptions }) const time = Date.now() - start log.notice('PONG', `${time}ms`) if (this.npm.config.get('json')) { - this.npm.output(JSON.stringify({ + output.standard(JSON.stringify({ registry: cleanRegistry, time, details, }, null, 2)) } else if (Object.keys(details).length) { - log.notice('PONG', `${JSON.stringify(details, null, 2)}`) + log.notice('PONG', JSON.stringify(details, null, 2)) } } } + module.exports = Ping diff --git a/deps/npm/lib/commands/pkg.js b/deps/npm/lib/commands/pkg.js index 49a66823cca996..62553b15103e3b 100644 --- a/deps/npm/lib/commands/pkg.js +++ b/deps/npm/lib/commands/pkg.js @@ -1,5 +1,6 @@ +const { output } = require('proc-log') const PackageJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const Queryable = require('../utils/queryable.js') class Pkg extends BaseCommand { @@ -62,7 +63,7 @@ class Pkg extends BaseCommand { } // when running in workspaces names, make sure to key by workspace // name the results of each value retrieved in each ws - this.npm.output(JSON.stringify(result, null, 2)) + output.standard(JSON.stringify(result, null, 2)) } async get (args) { @@ -85,7 +86,7 @@ class Pkg extends BaseCommand { // only outputs if not running with workspaces config // execWorkspaces will handle the output otherwise if (!this.workspaces) { - this.npm.output(JSON.stringify(result, null, 2)) + output.standard(JSON.stringify(result, null, 2)) } return result diff --git a/deps/npm/lib/commands/prefix.js b/deps/npm/lib/commands/prefix.js index 264b819fc7692a..da8702cf91caaf 100644 --- a/deps/npm/lib/commands/prefix.js +++ b/deps/npm/lib/commands/prefix.js @@ -1,4 +1,5 @@ -const BaseCommand = require('../base-command.js') +const { output } = require('proc-log') +const BaseCommand = require('../base-cmd.js') class Prefix extends BaseCommand { static description = 'Display prefix' @@ -6,8 +7,9 @@ class Prefix extends BaseCommand { static params = ['global'] static usage = ['[-g]'] - async exec (args) { - return this.npm.output(this.npm.prefix) + async exec () { + return output.standard(this.npm.prefix) } } + module.exports = Prefix diff --git a/deps/npm/lib/commands/profile.js b/deps/npm/lib/commands/profile.js index a7d4ac2f29fbe7..8eae6278549f56 100644 --- a/deps/npm/lib/commands/profile.js +++ b/deps/npm/lib/commands/profile.js @@ -1,13 +1,11 @@ -const inspect = require('util').inspect +const { inspect } = require('util') const { URL } = require('url') -const log = require('../utils/log-shim.js') +const { log, output } = require('proc-log') const npmProfile = require('npm-profile') const qrcodeTerminal = require('qrcode-terminal') -const Table = require('cli-table3') - const otplease = require('../utils/otplease.js') -const pulseTillDone = require('../utils/pulse-till-done.js') const readUserInfo = require('../utils/read-user-info.js') +const BaseCommand = require('../base-cmd.js') const qrcode = url => new Promise((resolve) => qrcodeTerminal.generate(url, resolve)) @@ -35,7 +33,6 @@ const writableProfileKeys = [ 'github', ] -const BaseCommand = require('../base-command.js') class Profile extends BaseCommand { static description = 'Change settings on your registry profile' static name = 'profile' @@ -80,8 +77,6 @@ class Profile extends BaseCommand { throw this.usageError() } - log.gauge.show('profile') - const [subcmd, ...opts] = args switch (subcmd) { @@ -106,16 +101,14 @@ class Profile extends BaseCommand { async get (args) { const tfa = 'two-factor auth' - const info = await pulseTillDone.withPromise( - npmProfile.get({ ...this.npm.flatOptions }) - ) + const info = await npmProfile.get({ ...this.npm.flatOptions }) if (!info.cidr_whitelist) { delete info.cidr_whitelist } if (this.npm.config.get('json')) { - this.npm.output(JSON.stringify(info, null, 2)) + output.standard(JSON.stringify(info, null, 2)) return } @@ -147,23 +140,20 @@ class Profile extends BaseCommand { .filter((arg) => arg.trim() !== '') .map((arg) => cleaned[arg]) .join('\t') - this.npm.output(values) + output.standard(values) } else { if (this.npm.config.get('parseable')) { for (const key of Object.keys(info)) { if (key === 'tfa') { - this.npm.output(`${key}\t${cleaned[tfa]}`) + output.standard(`${key}\t${cleaned[tfa]}`) } else { - this.npm.output(`${key}\t${info[key]}`) + output.standard(`${key}\t${info[key]}`) } } } else { - const table = new Table() - for (const key of Object.keys(cleaned)) { - table.push({ [this.npm.chalk.bold(key)]: cleaned[key] }) + for (const [key, value] of Object.entries(cleaned)) { + output.standard(`${key}: ${value}`) } - - this.npm.output(table.toString()) } } } @@ -209,7 +199,7 @@ class Profile extends BaseCommand { } // FIXME: Work around to not clear everything other than what we're setting - const user = await pulseTillDone.withPromise(npmProfile.get(conf)) + const user = await npmProfile.get(conf) const newUser = {} for (const key of writableProfileKeys) { @@ -221,13 +211,13 @@ class Profile extends BaseCommand { const result = await otplease(this.npm, conf, c => npmProfile.set(newUser, c)) if (this.npm.config.get('json')) { - this.npm.output(JSON.stringify({ [prop]: result[prop] }, null, 2)) + output.standard(JSON.stringify({ [prop]: result[prop] }, null, 2)) } else if (this.npm.config.get('parseable')) { - this.npm.output(prop + '\t' + result[prop]) + output.standard(prop + '\t' + result[prop]) } else if (result[prop] != null) { - this.npm.output('Set', prop, 'to', result[prop]) + output.standard('Set', prop, 'to', result[prop]) } else { - this.npm.output('Set', prop) + output.standard('Set', prop) } } @@ -307,16 +297,12 @@ class Profile extends BaseCommand { info.tfa.password = password log.info('profile', 'Determine if tfa is pending') - const userInfo = await pulseTillDone.withPromise( - npmProfile.get({ ...this.npm.flatOptions }) - ) + const userInfo = await npmProfile.get({ ...this.npm.flatOptions }) const conf = { ...this.npm.flatOptions } if (userInfo && userInfo.tfa && userInfo.tfa.pending) { log.info('profile', 'Resetting two-factor authentication') - await pulseTillDone.withPromise( - npmProfile.set({ tfa: { password, mode: 'disable' } }, conf) - ) + await npmProfile.set({ tfa: { password, mode: 'disable' } }, conf) } else if (userInfo && userInfo.tfa) { if (!conf.otp) { conf.otp = await readUserInfo.otp( @@ -326,12 +312,10 @@ class Profile extends BaseCommand { } log.info('profile', 'Setting two-factor authentication to ' + mode) - const challenge = await pulseTillDone.withPromise( - npmProfile.set(info, conf) - ) + const challenge = await npmProfile.set(info, conf) if (challenge.tfa === null) { - this.npm.output('Two factor authentication mode changed to: ' + mode) + output.standard('Two factor authentication mode changed to: ' + mode) return } @@ -348,7 +332,7 @@ class Profile extends BaseCommand { const secret = otpauth.searchParams.get('secret') const code = await qrcode(challenge.tfa) - this.npm.output( + output.standard( 'Scan into your authenticator app:\n' + code + '\n Or enter code:', secret ) @@ -359,26 +343,26 @@ class Profile extends BaseCommand { const result = await npmProfile.set({ tfa: [interactiveOTP] }, conf) - this.npm.output( + output.standard( '2FA successfully enabled. Below are your recovery codes, ' + 'please print these out.' ) - this.npm.output( + output.standard( 'You will need these to recover access to your account ' + 'if you lose your authentication device.' ) for (const tfaCode of result.tfa) { - this.npm.output('\t' + tfaCode) + output.standard('\t' + tfaCode) } } - async disable2fa (args) { + async disable2fa () { const conf = { ...this.npm.flatOptions } - const info = await pulseTillDone.withPromise(npmProfile.get(conf)) + const info = await npmProfile.get(conf) if (!info.tfa || info.tfa.pending) { - this.npm.output('Two factor authentication not enabled.') + output.standard('Two factor authentication not enabled.') return } @@ -391,17 +375,16 @@ class Profile extends BaseCommand { log.info('profile', 'disabling tfa') - await pulseTillDone.withPromise(npmProfile.set({ - tfa: { password: password, mode: 'disable' }, - }, conf)) + await npmProfile.set({ tfa: { password: password, mode: 'disable' } }, conf) if (this.npm.config.get('json')) { - this.npm.output(JSON.stringify({ tfa: false }, null, 2)) + output.standard(JSON.stringify({ tfa: false }, null, 2)) } else if (this.npm.config.get('parseable')) { - this.npm.output('tfa\tfalse') + output.standard('tfa\tfalse') } else { - this.npm.output('Two factor authentication disabled.') + output.standard('Two factor authentication disabled.') } } } + module.exports = Profile diff --git a/deps/npm/lib/commands/prune.js b/deps/npm/lib/commands/prune.js index 189fc29cb8bc35..1bcf8a9576316c 100644 --- a/deps/npm/lib/commands/prune.js +++ b/deps/npm/lib/commands/prune.js @@ -1,7 +1,7 @@ -// prune extraneous packages const reifyFinish = require('../utils/reify-finish.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + +// prune extraneous packages class Prune extends ArboristWorkspaceCmd { static description = 'Remove extraneous packages' static name = 'prune' @@ -30,4 +30,5 @@ class Prune extends ArboristWorkspaceCmd { await reifyFinish(this.npm, arb) } } + module.exports = Prune diff --git a/deps/npm/lib/commands/publish.js b/deps/npm/lib/commands/publish.js index 63abc50b4745f4..6bb2dcc6614bb2 100644 --- a/deps/npm/lib/commands/publish.js +++ b/deps/npm/lib/commands/publish.js @@ -1,4 +1,4 @@ -const log = require('../utils/log-shim.js') +const { log, output } = require('proc-log') const semver = require('semver') const pack = require('libnpmpack') const libpub = require('libnpmpublish').publish @@ -6,19 +6,17 @@ const runScript = require('@npmcli/run-script') const pacote = require('pacote') const npa = require('npm-package-arg') const npmFetch = require('npm-registry-fetch') -const replaceInfo = require('../utils/replace-info.js') - +const { redactLog: replaceInfo } = require('@npmcli/redact') const otplease = require('../utils/otplease.js') const { getContents, logTar } = require('../utils/tar.js') - // for historical reasons, publishConfig in package.json can contain ANY config // keys that npm supports in .npmrc files and elsewhere. We *may* want to // revisit this at some point, and have a minimal set that's a SemVer-major // change that ought to get a RFC written on it. const { flatten } = require('@npmcli/config/lib/definitions') const pkgJson = require('@npmcli/package-json') +const BaseCommand = require('../base-cmd.js') -const BaseCommand = require('../base-command.js') class Publish extends BaseCommand { static description = 'Publish a package' static name = 'publish' @@ -59,7 +57,6 @@ class Publish extends BaseCommand { } const opts = { ...this.npm.flatOptions, progress: false } - log.disableProgress() // you can publish name@version, ./foo.tgz, etc. // even though the default is the 'file:.' cwd. @@ -73,7 +70,6 @@ class Publish extends BaseCommand { path: spec.fetchSpec, stdio: 'inherit', pkg: manifest, - banner: !silent, }) } @@ -132,7 +128,6 @@ class Publish extends BaseCommand { path: spec.fetchSpec, stdio: 'inherit', pkg: manifest, - banner: !silent, }) await runScript({ @@ -140,22 +135,21 @@ class Publish extends BaseCommand { path: spec.fetchSpec, stdio: 'inherit', pkg: manifest, - banner: !silent, }) } if (!this.suppressOutput) { if (!silent && json) { - this.npm.output(JSON.stringify(pkgContents, null, 2)) + output.standard(JSON.stringify(pkgContents, null, 2)) } else if (!silent) { - this.npm.output(`+ ${pkgContents.id}`) + output.standard(`+ ${pkgContents.id}`) } } return pkgContents } - async execWorkspaces (args) { + async execWorkspaces () { // Suppresses JSON output in publish() so we can handle it here this.suppressOutput = true @@ -173,7 +167,7 @@ class Publish extends BaseCommand { log.warn( 'publish', `Skipping workspace ${ - this.npm.chalk.green(name) + this.npm.chalk.cyan(name) }, marked as ${ this.npm.chalk.bold('private') }` @@ -185,14 +179,14 @@ class Publish extends BaseCommand { // This needs to be in-line w/ the rest of the output that non-JSON // publish generates if (!silent && !json) { - this.npm.output(`+ ${pkgContents.id}`) + output.standard(`+ ${pkgContents.id}`) } else { results[name] = pkgContents } } if (!silent && json) { - this.npm.output(JSON.stringify(results, null, 2)) + output.standard(JSON.stringify(results, null, 2)) } } @@ -220,9 +214,15 @@ class Publish extends BaseCommand { }) } if (manifest.publishConfig) { - flatten(manifest.publishConfig, opts) + const cliFlags = this.npm.config.data.get('cli').raw + // Filter out properties set in CLI flags to prioritize them over + // corresponding `publishConfig` settings + const filteredPublishConfig = Object.fromEntries( + Object.entries(manifest.publishConfig).filter(([key]) => !(key in cliFlags))) + flatten(filteredPublishConfig, opts) } return manifest } } + module.exports = Publish diff --git a/deps/npm/lib/commands/query.js b/deps/npm/lib/commands/query.js index 17a55a446b0869..fe84469b88fe0a 100644 --- a/deps/npm/lib/commands/query.js +++ b/deps/npm/lib/commands/query.js @@ -1,8 +1,6 @@ -'use strict' - -const { resolve } = require('path') -const BaseCommand = require('../base-command.js') -const log = require('../utils/log-shim.js') +const { resolve } = require('node:path') +const BaseCommand = require('../base-cmd.js') +const { log, output } = require('proc-log') class QuerySelectorItem { constructor (node) { @@ -83,7 +81,7 @@ class Query extends BaseCommand { this.buildResponse(items) this.checkExpected(this.#response.length) - this.npm.output(this.parsedResponse) + output.standard(this.parsedResponse) } async execWorkspaces (args) { @@ -107,16 +105,18 @@ class Query extends BaseCommand { this.buildResponse(items) } this.checkExpected(this.#response.length) - this.npm.output(this.parsedResponse) + output.standard(this.parsedResponse) } // builds a normalized inventory buildResponse (items) { for (const node of items) { - if (!this.#seen.has(node.target.location)) { + if (!node.target.location || !this.#seen.has(node.target.location)) { const item = new QuerySelectorItem(node) this.#response.push(item) - this.#seen.add(item.location) + if (node.target.location) { + this.#seen.add(item.location) + } } } } diff --git a/deps/npm/lib/commands/rebuild.js b/deps/npm/lib/commands/rebuild.js index 8af96f725555cb..3894f0aa290cc7 100644 --- a/deps/npm/lib/commands/rebuild.js +++ b/deps/npm/lib/commands/rebuild.js @@ -1,8 +1,9 @@ const { resolve } = require('path') +const { output } = require('proc-log') const npa = require('npm-package-arg') const semver = require('semver') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Rebuild extends ArboristWorkspaceCmd { static description = 'Rebuild a package' static name = 'rebuild' @@ -19,7 +20,7 @@ class Rebuild extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } @@ -56,7 +57,7 @@ class Rebuild extends ArboristWorkspaceCmd { await arb.rebuild() } - this.npm.output('rebuilt dependencies successfully') + output.standard('rebuilt dependencies successfully') } isNode (specs, node) { @@ -79,4 +80,5 @@ class Rebuild extends ArboristWorkspaceCmd { }) } } + module.exports = Rebuild diff --git a/deps/npm/lib/commands/repo.js b/deps/npm/lib/commands/repo.js index b89b74c0bf1baa..8e2fef24771d9d 100644 --- a/deps/npm/lib/commands/repo.js +++ b/deps/npm/lib/commands/repo.js @@ -1,6 +1,6 @@ const { URL } = require('url') - const PackageUrlCmd = require('../package-url-cmd.js') + class Repo extends PackageUrlCmd { static description = 'Open package repository page in the browser' static name = 'repo' @@ -30,6 +30,7 @@ class Repo extends PackageUrlCmd { return url } } + module.exports = Repo const unknownHostedUrl = url => { diff --git a/deps/npm/lib/commands/root.js b/deps/npm/lib/commands/root.js index 7749c602456b77..180f4c4ed0720a 100644 --- a/deps/npm/lib/commands/root.js +++ b/deps/npm/lib/commands/root.js @@ -1,11 +1,14 @@ -const BaseCommand = require('../base-command.js') +const { output } = require('proc-log') +const BaseCommand = require('../base-cmd.js') + class Root extends BaseCommand { static description = 'Display npm root' static name = 'root' static params = ['global'] async exec () { - this.npm.output(this.npm.dir) + output.standard(this.npm.dir) } } + module.exports = Root diff --git a/deps/npm/lib/commands/run-script.js b/deps/npm/lib/commands/run-script.js index 75f00a46b84e9f..dd00c98fc8b6ec 100644 --- a/deps/npm/lib/commands/run-script.js +++ b/deps/npm/lib/commands/run-script.js @@ -1,22 +1,7 @@ -const runScript = require('@npmcli/run-script') -const { isServerPackage } = runScript +const { log, output } = require('proc-log') const pkgJson = require('@npmcli/package-json') -const log = require('../utils/log-shim.js') -const didYouMean = require('../utils/did-you-mean.js') -const { isWindowsShell } = require('../utils/is-windows.js') - -const cmdList = [ - 'publish', - 'install', - 'uninstall', - 'test', - 'stop', - 'start', - 'restart', - 'version', -].reduce((l, p) => l.concat(['pre' + p, p, 'post' + p]), []) - -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') + class RunScript extends BaseCommand { static description = 'Run arbitrary package scripts' static params = [ @@ -39,7 +24,7 @@ class RunScript extends BaseCommand { const argv = opts.conf.argv.remain if (argv.length === 2) { const { content: { scripts = {} } } = await pkgJson.normalize(npm.localPrefix) - .catch(er => ({ content: {} })) + .catch(() => ({ content: {} })) if (opts.isFish) { return Object.keys(scripts).map(s => `${s}\t${scripts[s].slice(0, 30)}`) } @@ -64,9 +49,7 @@ class RunScript extends BaseCommand { } async run ([event, ...args], { path = this.npm.localPrefix, pkg } = {}) { - // this || undefined is because runScript will be unhappy with the default - // null value - const scriptShell = this.npm.config.get('script-shell') || undefined + const runScript = require('@npmcli/run-script') if (!pkg) { const { content } = await pkgJson.normalize(path) @@ -77,6 +60,7 @@ class RunScript extends BaseCommand { if (event === 'restart' && !scripts.restart) { scripts.restart = 'npm stop --if-present && npm start' } else if (event === 'env' && !scripts.env) { + const { isWindowsShell } = require('../utils/is-windows.js') scripts.env = isWindowsShell ? 'SET' : 'env' } @@ -84,12 +68,13 @@ class RunScript extends BaseCommand { if ( !Object.prototype.hasOwnProperty.call(scripts, event) && - !(event === 'start' && (await isServerPackage(path))) + !(event === 'start' && (await runScript.isServerPackage(path))) ) { if (this.npm.config.get('if-present')) { return } + const didYouMean = require('../utils/did-you-mean.js') const suggestions = await didYouMean(path, event) throw new Error( `Missing script: "${event}"${suggestions}\n\nTo see a list of scripts, run:\n npm run` @@ -108,18 +93,14 @@ class RunScript extends BaseCommand { } } - const opts = { - path, - args, - scriptShell, - stdio: 'inherit', - pkg, - banner: !this.npm.silent, - } - for (const [ev, evArgs] of events) { await runScript({ - ...opts, + path, + // this || undefined is because runScript will be unhappy with the + // default null value + scriptShell: this.npm.config.get('script-shell') || undefined, + stdio: 'inherit', + pkg, event: ev, args: evArgs, }) @@ -141,18 +122,29 @@ class RunScript extends BaseCommand { } if (this.npm.config.get('json')) { - this.npm.output(JSON.stringify(scripts, null, 2)) + output.standard(JSON.stringify(scripts, null, 2)) return allScripts } if (this.npm.config.get('parseable')) { for (const [script, cmd] of Object.entries(scripts)) { - this.npm.output(`${script}:${cmd}`) + output.standard(`${script}:${cmd}`) } return allScripts } + // TODO this is missing things like prepare, prepublishOnly, and dependencies + const cmdList = [ + 'preinstall', 'install', 'postinstall', + 'prepublish', 'publish', 'postpublish', + 'prerestart', 'restart', 'postrestart', + 'prestart', 'start', 'poststart', + 'prestop', 'stop', 'poststop', + 'pretest', 'test', 'posttest', + 'preuninstall', 'uninstall', 'postuninstall', + 'preversion', 'version', 'postversion', + ] const indent = '\n ' const prefix = ' ' const cmds = [] @@ -164,7 +156,7 @@ class RunScript extends BaseCommand { const colorize = this.npm.chalk if (cmds.length) { - this.npm.output( + output.standard( `${colorize.reset(colorize.bold('Lifecycle scripts'))} included in ${colorize.green( pkgid )}:` @@ -172,28 +164,28 @@ class RunScript extends BaseCommand { } for (const script of cmds) { - this.npm.output(prefix + script + indent + colorize.dim(scripts[script])) + output.standard(prefix + script + indent + colorize.dim(scripts[script])) } if (!cmds.length && runScripts.length) { - this.npm.output( + output.standard( `${colorize.bold('Scripts')} available in ${colorize.green(pkgid)} via \`${colorize.blue( 'npm run-script' )}\`:` ) } else if (runScripts.length) { - this.npm.output(`\navailable via \`${colorize.blue('npm run-script')}\`:`) + output.standard(`\navailable via \`${colorize.blue('npm run-script')}\`:`) } for (const script of runScripts) { - this.npm.output(prefix + script + indent + colorize.dim(scripts[script])) + output.standard(prefix + script + indent + colorize.dim(scripts[script])) } - this.npm.output('') + output.standard('') return allScripts } - async runWorkspaces (args, filters) { + async runWorkspaces (args) { const res = [] await this.setWorkspaces() @@ -213,7 +205,7 @@ class RunScript extends BaseCommand { } } - async listWorkspaces (args, filters) { + async listWorkspaces (args) { await this.setWorkspaces() if (this.npm.silent) { @@ -226,7 +218,7 @@ class RunScript extends BaseCommand { const { content: { scripts, name } } = await pkgJson.normalize(workspacePath) res[name] = { ...scripts } } - this.npm.output(JSON.stringify(res, null, 2)) + output.standard(JSON.stringify(res, null, 2)) return } @@ -234,7 +226,7 @@ class RunScript extends BaseCommand { for (const workspacePath of this.workspacePaths) { const { content: { scripts, name } } = await pkgJson.normalize(workspacePath) for (const [script, cmd] of Object.entries(scripts || {})) { - this.npm.output(`${name}:${script}:${cmd}`) + output.standard(`${name}:${script}:${cmd}`) } } return diff --git a/deps/npm/lib/commands/sbom.js b/deps/npm/lib/commands/sbom.js index 311dfbc852406d..ff7377581dfa51 100644 --- a/deps/npm/lib/commands/sbom.js +++ b/deps/npm/lib/commands/sbom.js @@ -1,9 +1,6 @@ -'use strict' - -const { EOL } = require('os') const localeCompare = require('@isaacs/string-locale-compare')('en') -const BaseCommand = require('../base-command.js') -const log = require('../utils/log-shim.js') +const BaseCommand = require('../base-cmd.js') +const { log, output } = require('proc-log') const { cyclonedxOutput } = require('../utils/sbom-cyclonedx.js') const { spdxOutput } = require('../utils/sbom-spdx.js') @@ -77,7 +74,7 @@ class SBOM extends BaseCommand { if (errors.size > 0) { throw Object.assign( - new Error([...errors].join(EOL)), + new Error([...errors].join('\n')), { code: 'ESBOMPROBLEMS' } ) } @@ -87,7 +84,7 @@ class SBOM extends BaseCommand { items .sort((a, b) => localeCompare(a.location, b.location)) ) - this.npm.output(this.#parsedResponse) + output.standard(this.#parsedResponse) } async execWorkspaces (args) { diff --git a/deps/npm/lib/commands/search.js b/deps/npm/lib/commands/search.js index f4a4ce32491424..8b6c01e3930d81 100644 --- a/deps/npm/lib/commands/search.js +++ b/deps/npm/lib/commands/search.js @@ -1,47 +1,18 @@ -const { Minipass } = require('minipass') const Pipeline = require('minipass-pipeline') const libSearch = require('libnpmsearch') -const log = require('../utils/log-shim.js') - +const { log, output } = require('proc-log') const formatSearchStream = require('../utils/format-search-stream.js') +const BaseCommand = require('../base-cmd.js') -function filter (data, include, exclude) { - const words = [data.name] - .concat(data.maintainers.map(m => `=${m.username}`)) - .concat(data.keywords || []) - .map(f => f && f.trim && f.trim()) - .filter(f => f) - .join(' ') - .toLowerCase() - - if (exclude.find(e => match(words, e))) { - return false - } - - return true -} - -function match (words, pattern) { - if (pattern.startsWith('/')) { - if (pattern.endsWith('/')) { - pattern = pattern.slice(0, -1) - } - pattern = new RegExp(pattern.slice(1)) - return words.match(pattern) - } - return words.indexOf(pattern) !== -1 -} - -const BaseCommand = require('../base-command.js') class Search extends BaseCommand { static description = 'Search for packages' static name = 'search' static params = [ - 'long', 'json', 'color', 'parseable', 'description', + 'searchlimit', 'searchopts', 'searchexclude', 'registry', @@ -50,13 +21,13 @@ class Search extends BaseCommand { 'offline', ] - static usage = ['[search terms ...]'] + static usage = [' [ ...]'] async exec (args) { const opts = { ...this.npm.flatOptions, ...this.npm.flatOptions.search, - include: args.map(s => s.toLowerCase()).filter(s => s), + include: args.map(s => s.toLowerCase()).filter(Boolean), exclude: this.npm.flatOptions.search.exclude.split(/\s+/), } @@ -67,30 +38,16 @@ class Search extends BaseCommand { // Used later to figure out whether we had any packages go out let anyOutput = false - class FilterStream extends Minipass { - constructor () { - super({ objectMode: true }) - } - - write (pkg) { - if (filter(pkg, opts.include, opts.exclude)) { - super.write(pkg) - } - } - } - - const filterStream = new FilterStream() - // Grab a configured output stream that will spit out packages in the desired format. - const outputStream = await formatSearchStream({ + const outputStream = formatSearchStream({ args, // --searchinclude options are not highlighted ...opts, + npm: this.npm, }) log.silly('search', 'searching packages') const p = new Pipeline( libSearch.stream(opts.include, opts), - filterStream, outputStream ) @@ -98,16 +55,16 @@ class Search extends BaseCommand { if (!anyOutput) { anyOutput = true } - this.npm.output(chunk.toString('utf8')) + output.standard(chunk.toString('utf8')) }) await p.promise() if (!anyOutput && !this.npm.config.get('json') && !this.npm.config.get('parseable')) { - this.npm.output('No matches found for ' + (args.map(JSON.stringify).join(' '))) + output.standard('No matches found for ' + (args.map(JSON.stringify).join(' '))) } log.silly('search', 'search completed') - log.clearProgress() } } + module.exports = Search diff --git a/deps/npm/lib/commands/set.js b/deps/npm/lib/commands/set.js index f315d183845c5e..2e61762ba9dcd4 100644 --- a/deps/npm/lib/commands/set.js +++ b/deps/npm/lib/commands/set.js @@ -1,5 +1,5 @@ const Npm = require('../npm.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Set extends BaseCommand { static description = 'Set a value in the npm configuration' @@ -22,4 +22,5 @@ class Set extends BaseCommand { return this.npm.exec('config', ['set'].concat(args)) } } + module.exports = Set diff --git a/deps/npm/lib/commands/shrinkwrap.js b/deps/npm/lib/commands/shrinkwrap.js index c6d817d4801423..d7866bdb91dceb 100644 --- a/deps/npm/lib/commands/shrinkwrap.js +++ b/deps/npm/lib/commands/shrinkwrap.js @@ -1,7 +1,8 @@ const { resolve, basename } = require('path') -const { unlink } = require('fs').promises -const log = require('../utils/log-shim') -const BaseCommand = require('../base-command.js') +const { unlink } = require('fs/promises') +const { log } = require('proc-log') +const BaseCommand = require('../base-cmd.js') + class Shrinkwrap extends BaseCommand { static description = 'Lock down dependency versions for publication' static name = 'shrinkwrap' @@ -68,4 +69,5 @@ class Shrinkwrap extends BaseCommand { } } } + module.exports = Shrinkwrap diff --git a/deps/npm/lib/commands/star.js b/deps/npm/lib/commands/star.js index 20039bf8938116..1b76955810c726 100644 --- a/deps/npm/lib/commands/star.js +++ b/deps/npm/lib/commands/star.js @@ -1,9 +1,9 @@ const fetch = require('npm-registry-fetch') const npa = require('npm-package-arg') -const log = require('../utils/log-shim') +const { log, output } = require('proc-log') const getIdentity = require('../utils/get-identity') +const BaseCommand = require('../base-cmd.js') -const BaseCommand = require('../base-command.js') class Star extends BaseCommand { static description = 'Mark your favorite packages' static name = 'star' @@ -62,10 +62,11 @@ class Star extends BaseCommand { body, }) - this.npm.output(show + ' ' + pkg.name) + output.standard(show + ' ' + pkg.name) log.verbose('star', data) return data } } } + module.exports = Star diff --git a/deps/npm/lib/commands/stars.js b/deps/npm/lib/commands/stars.js index 4214134eb5871a..1059569979dafe 100644 --- a/deps/npm/lib/commands/stars.js +++ b/deps/npm/lib/commands/stars.js @@ -1,8 +1,8 @@ const fetch = require('npm-registry-fetch') -const log = require('../utils/log-shim') +const { log, output } = require('proc-log') const getIdentity = require('../utils/get-identity.js') +const BaseCommand = require('../base-cmd.js') -const BaseCommand = require('../base-command.js') class Stars extends BaseCommand { static description = 'View packages marked as favorites' static name = 'stars' @@ -25,7 +25,7 @@ class Stars extends BaseCommand { } for (const row of rows) { - this.npm.output(row.value) + output.standard(row.value) } } catch (err) { if (err.code === 'ENEEDAUTH') { @@ -35,4 +35,5 @@ class Stars extends BaseCommand { } } } + module.exports = Stars diff --git a/deps/npm/lib/commands/team.js b/deps/npm/lib/commands/team.js index 3c6cf305a6e5f9..22af61863851ab 100644 --- a/deps/npm/lib/commands/team.js +++ b/deps/npm/lib/commands/team.js @@ -1,9 +1,9 @@ const columns = require('cli-columns') const libteam = require('libnpmteam') - +const { output } = require('proc-log') const otplease = require('../utils/otplease.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Team extends BaseCommand { static description = 'Manage organization teams and team memberships' static name = 'team' @@ -68,87 +68,88 @@ class Team extends BaseCommand { async create (entity, opts) { await libteam.create(entity, opts) if (opts.json) { - this.npm.output(JSON.stringify({ + output.standard(JSON.stringify({ created: true, team: entity, })) } else if (opts.parseable) { - this.npm.output(`${entity}\tcreated`) + output.standard(`${entity}\tcreated`) } else if (!this.npm.silent) { - this.npm.output(`+@${entity}`) + output.standard(`+@${entity}`) } } async destroy (entity, opts) { await libteam.destroy(entity, opts) if (opts.json) { - this.npm.output(JSON.stringify({ + output.standard(JSON.stringify({ deleted: true, team: entity, })) } else if (opts.parseable) { - this.npm.output(`${entity}\tdeleted`) + output.standard(`${entity}\tdeleted`) } else if (!this.npm.silent) { - this.npm.output(`-@${entity}`) + output.standard(`-@${entity}`) } } async add (entity, user, opts) { await libteam.add(user, entity, opts) if (opts.json) { - this.npm.output(JSON.stringify({ + output.standard(JSON.stringify({ added: true, team: entity, user, })) } else if (opts.parseable) { - this.npm.output(`${user}\t${entity}\tadded`) + output.standard(`${user}\t${entity}\tadded`) } else if (!this.npm.silent) { - this.npm.output(`${user} added to @${entity}`) + output.standard(`${user} added to @${entity}`) } } async rm (entity, user, opts) { await libteam.rm(user, entity, opts) if (opts.json) { - this.npm.output(JSON.stringify({ + output.standard(JSON.stringify({ removed: true, team: entity, user, })) } else if (opts.parseable) { - this.npm.output(`${user}\t${entity}\tremoved`) + output.standard(`${user}\t${entity}\tremoved`) } else if (!this.npm.silent) { - this.npm.output(`${user} removed from @${entity}`) + output.standard(`${user} removed from @${entity}`) } } async listUsers (entity, opts) { const users = (await libteam.lsUsers(entity, opts)).sort() if (opts.json) { - this.npm.output(JSON.stringify(users, null, 2)) + output.standard(JSON.stringify(users, null, 2)) } else if (opts.parseable) { - this.npm.output(users.join('\n')) + output.standard(users.join('\n')) } else if (!this.npm.silent) { const plural = users.length === 1 ? '' : 's' const more = users.length === 0 ? '' : ':\n' - this.npm.output(`\n@${entity} has ${users.length} user${plural}${more}`) - this.npm.output(columns(users, { padding: 1 })) + output.standard(`\n@${entity} has ${users.length} user${plural}${more}`) + output.standard(columns(users, { padding: 1 })) } } async listTeams (entity, opts) { const teams = (await libteam.lsTeams(entity, opts)).sort() if (opts.json) { - this.npm.output(JSON.stringify(teams, null, 2)) + output.standard(JSON.stringify(teams, null, 2)) } else if (opts.parseable) { - this.npm.output(teams.join('\n')) + output.standard(teams.join('\n')) } else if (!this.npm.silent) { const plural = teams.length === 1 ? '' : 's' const more = teams.length === 0 ? '' : ':\n' - this.npm.output(`\n@${entity} has ${teams.length} team${plural}${more}`) - this.npm.output(columns(teams.map(t => `@${t}`), { padding: 1 })) + output.standard(`\n@${entity} has ${teams.length} team${plural}${more}`) + output.standard(columns(teams.map(t => `@${t}`), { padding: 1 })) } } } + module.exports = Team diff --git a/deps/npm/lib/commands/token.js b/deps/npm/lib/commands/token.js index dc1df6e0fcb25b..24ca21a8e29ce9 100644 --- a/deps/npm/lib/commands/token.js +++ b/deps/npm/lib/commands/token.js @@ -1,12 +1,9 @@ -const Table = require('cli-table3') -const log = require('../utils/log-shim.js') +const { log, output } = require('proc-log') const profile = require('npm-profile') - const otplease = require('../utils/otplease.js') -const pulseTillDone = require('../utils/pulse-till-done.js') const readUserInfo = require('../utils/read-user-info.js') +const BaseCommand = require('../base-cmd.js') -const BaseCommand = require('../base-command.js') class Token extends BaseCommand { static description = 'Manage your authentication tokens' static name = 'token' @@ -28,7 +25,6 @@ class Token extends BaseCommand { } async exec (args) { - log.gauge.show('token') if (args.length === 0) { return this.list() } @@ -36,10 +32,10 @@ class Token extends BaseCommand { case 'list': case 'ls': return this.list() + case 'rm': case 'delete': case 'revoke': case 'remove': - case 'rm': return this.rm(args.slice(1)) case 'create': return this.create(args.slice(1)) @@ -49,16 +45,18 @@ class Token extends BaseCommand { } async list () { - const conf = this.config() + const json = this.npm.config.get('json') + const parseable = this.npm.config.get('parseable') log.info('token', 'getting list') - const tokens = await pulseTillDone.withPromise(profile.listTokens(conf)) - if (conf.json) { - this.npm.output(JSON.stringify(tokens, null, 2)) + const tokens = await profile.listTokens(this.npm.flatOptions) + if (json) { + output.standard(JSON.stringify(tokens, null, 2)) return - } else if (conf.parseable) { - this.npm.output(['key', 'token', 'created', 'readonly', 'CIDR whitelist'].join('\t')) + } + if (parseable) { + output.standard(['key', 'token', 'created', 'readonly', 'CIDR whitelist'].join('\t')) tokens.forEach(token => { - this.npm.output( + output.standard( [ token.key, token.token, @@ -71,21 +69,17 @@ class Token extends BaseCommand { return } this.generateTokenIds(tokens, 6) - const idWidth = tokens.reduce((acc, token) => Math.max(acc, token.id.length), 0) - const table = new Table({ - head: ['id', 'token', 'created', 'readonly', 'CIDR whitelist'], - colWidths: [Math.max(idWidth, 2) + 2, 9, 12, 10], - }) - tokens.forEach(token => { - table.push([ - token.id, - token.token + '…', - String(token.created).slice(0, 10), - token.readonly ? 'yes' : 'no', - token.cidr_whitelist ? token.cidr_whitelist.join(', ') : '', - ]) - }) - this.npm.output(table.toString()) + const chalk = this.npm.chalk + for (const token of tokens) { + const level = token.readonly ? 'Read only token' : 'Publish token' + const created = String(token.created).slice(0, 10) + /* eslint-disable-next-line max-len */ + output.standard(`${chalk.blue(level)} ${token.token}… with id ${chalk.cyan(token.id)} created ${created}`) + if (token.cidr_whitelist) { + output.standard(`with IP whitelist: ${chalk.green(token.cidr_whitelist.join(','))}`) + } + output.standard() + } } async rm (args) { @@ -93,11 +87,12 @@ class Token extends BaseCommand { throw this.usageError('`` argument is required.') } - const conf = this.config() + const json = this.npm.config.get('json') + const parseable = this.npm.config.get('parseable') const toRemove = [] - const progress = log.newItem('removing tokens', toRemove.length) - progress.info('token', 'getting existing list') - const tokens = await pulseTillDone.withPromise(profile.listTokens(conf)) + const opts = { ...this.npm.flatOptions } + log.info('token', `removing ${toRemove.length} tokens`) + const tokens = await profile.listTokens(opts) args.forEach(id => { const matches = tokens.filter(token => token.key.indexOf(id) === 0) if (matches.length === 1) { @@ -118,72 +113,47 @@ class Token extends BaseCommand { }) await Promise.all( toRemove.map(key => { - return otplease(this.npm, conf, c => profile.removeToken(key, c)) + return otplease(this.npm, opts, c => profile.removeToken(key, c)) }) ) - if (conf.json) { - this.npm.output(JSON.stringify(toRemove)) - } else if (conf.parseable) { - this.npm.output(toRemove.join('\t')) + if (json) { + output.standard(JSON.stringify(toRemove)) + } else if (parseable) { + output.standard(toRemove.join('\t')) } else { - this.npm.output('Removed ' + toRemove.length + ' token' + (toRemove.length !== 1 ? 's' : '')) + output.standard('Removed ' + toRemove.length + ' token' + (toRemove.length !== 1 ? 's' : '')) } } - async create (args) { - const conf = this.config() - const cidr = conf.cidr - const readonly = conf.readOnly + async create () { + const json = this.npm.config.get('json') + const parseable = this.npm.config.get('parseable') + const cidr = this.npm.config.get('cidr') + const readonly = this.npm.config.get('read-only') - const password = await readUserInfo.password() const validCIDR = await this.validateCIDRList(cidr) + const password = await readUserInfo.password() log.info('token', 'creating') - const result = await pulseTillDone.withPromise( - otplease(this.npm, conf, c => profile.createToken(password, readonly, validCIDR, c)) + const result = await otplease( + this.npm, + { ...this.npm.flatOptions }, + c => profile.createToken(password, readonly, validCIDR, c) ) delete result.key delete result.updated - if (conf.json) { - this.npm.output(JSON.stringify(result)) - } else if (conf.parseable) { - Object.keys(result).forEach(k => this.npm.output(k + '\t' + result[k])) + if (json) { + output.standard(JSON.stringify(result)) + } else if (parseable) { + Object.keys(result).forEach(k => output.standard(k + '\t' + result[k])) } else { - const table = new Table() - for (const k of Object.keys(result)) { - table.push({ [this.npm.chalk.bold(k)]: String(result[k]) }) - } - this.npm.output(table.toString()) - } - } - - config () { - const conf = { ...this.npm.flatOptions } - const creds = this.npm.config.getCredentialsByURI(conf.registry) - if (creds.token) { - conf.auth = { token: creds.token } - } else if (creds.username) { - conf.auth = { - basic: { - username: creds.username, - password: creds.password, - }, + const chalk = this.npm.chalk + // Identical to list + const level = result.readonly ? 'read only' : 'publish' + output.standard(`Created ${chalk.blue(level)} token ${result.token}`) + if (result.cidr_whitelist?.length) { + output.standard(`with IP whitelist: ${chalk.green(result.cidr_whitelist.join(','))}`) } - } else if (creds.auth) { - const auth = Buffer.from(creds.auth, 'base64').toString().split(':', 2) - conf.auth = { - basic: { - username: auth[0], - password: auth[1], - }, - } - } else { - conf.auth = {} } - - if (conf.otp) { - conf.auth.otp = conf.otp - } - return conf } invalidCIDRError (msg) { @@ -191,7 +161,6 @@ class Token extends BaseCommand { } generateTokenIds (tokens, minLength) { - const byId = {} for (const token of tokens) { token.id = token.key for (let ii = minLength; ii < token.key.length; ++ii) { @@ -203,9 +172,7 @@ class Token extends BaseCommand { break } } - byId[token.id] = token } - return byId } async validateCIDRList (cidrs) { @@ -215,15 +182,16 @@ class Token extends BaseCommand { for (const cidr of list) { if (isCidrV6(cidr)) { throw this.invalidCIDRError( - 'CIDR whitelist can only contain IPv4 addresses, ' + cidr + ' is IPv6' + `CIDR whitelist can only contain IPv4 addresses${cidr} is IPv6` ) } if (!isCidrV4(cidr)) { - throw this.invalidCIDRError('CIDR whitelist contains invalid CIDR entry: ' + cidr) + throw this.invalidCIDRError(`CIDR whitelist contains invalid CIDR entry: ${cidr}`) } } return list } } + module.exports = Token diff --git a/deps/npm/lib/commands/uninstall.js b/deps/npm/lib/commands/uninstall.js index 07775efb9cf2f1..7496c02deb28f4 100644 --- a/deps/npm/lib/commands/uninstall.js +++ b/deps/npm/lib/commands/uninstall.js @@ -1,10 +1,9 @@ const { resolve } = require('path') const pkgJson = require('@npmcli/package-json') - const reifyFinish = require('../utils/reify-finish.js') -const completion = require('../utils/completion/installed-shallow.js') - +const completion = require('../utils/installed-shallow.js') const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Uninstall extends ArboristWorkspaceCmd { static description = 'Remove a package' static name = 'uninstall' @@ -53,4 +52,5 @@ class Uninstall extends ArboristWorkspaceCmd { await reifyFinish(this.npm, arb) } } + module.exports = Uninstall diff --git a/deps/npm/lib/commands/unpublish.js b/deps/npm/lib/commands/unpublish.js index a9c20900534c3a..47a5db82062442 100644 --- a/deps/npm/lib/commands/unpublish.js +++ b/deps/npm/lib/commands/unpublish.js @@ -2,18 +2,17 @@ const libaccess = require('libnpmaccess') const libunpub = require('libnpmpublish').unpublish const npa = require('npm-package-arg') const pacote = require('pacote') +const { output, log } = require('proc-log') const pkgJson = require('@npmcli/package-json') - const { flatten } = require('@npmcli/config/lib/definitions') const getIdentity = require('../utils/get-identity.js') -const log = require('../utils/log-shim') const otplease = require('../utils/otplease.js') +const BaseCommand = require('../base-cmd.js') const LAST_REMAINING_VERSION_ERROR = 'Refusing to delete the last version of the package. ' + 'It will block from republishing a new version for 24 hours.\n' + 'Run with --force to do this.' -const BaseCommand = require('../base-command.js') class Unpublish extends BaseCommand { static description = 'Remove a package from the registry' static name = 'unpublish' @@ -141,7 +140,12 @@ class Unpublish extends BaseCommand { // If localPrefix has a package.json with a name that matches the package // being unpublished, load up the publishConfig if (manifest?.name === spec.name && manifest.publishConfig) { - flatten(manifest.publishConfig, opts) + const cliFlags = this.npm.config.data.get('cli').raw + // Filter out properties set in CLI flags to prioritize them over + // corresponding `publishConfig` settings + const filteredPublishConfig = Object.fromEntries( + Object.entries(manifest.publishConfig).filter(([key]) => !(key in cliFlags))) + flatten(filteredPublishConfig, opts) } const versions = await Unpublish.getKeysOfVersions(spec.name, opts) @@ -156,7 +160,7 @@ class Unpublish extends BaseCommand { await otplease(this.npm, opts, o => libunpub(spec, o)) } if (!silent) { - this.npm.output(`- ${spec.name}${pkgVersion}`) + output.standard(`- ${spec.name}${pkgVersion}`) } } @@ -168,4 +172,5 @@ class Unpublish extends BaseCommand { } } } + module.exports = Unpublish diff --git a/deps/npm/lib/commands/unstar.js b/deps/npm/lib/commands/unstar.js index cbcb73636c6384..c72966866669a9 100644 --- a/deps/npm/lib/commands/unstar.js +++ b/deps/npm/lib/commands/unstar.js @@ -4,4 +4,5 @@ class Unstar extends Star { static description = 'Remove an item from your favorite packages' static name = 'unstar' } + module.exports = Unstar diff --git a/deps/npm/lib/commands/update.js b/deps/npm/lib/commands/update.js index 43d031c7ada3f3..ddc3e4a47f38a1 100644 --- a/deps/npm/lib/commands/update.js +++ b/deps/npm/lib/commands/update.js @@ -1,10 +1,8 @@ const path = require('path') - -const log = require('../utils/log-shim.js') - +const { log } = require('proc-log') const reifyFinish = require('../utils/reify-finish.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Update extends ArboristWorkspaceCmd { static description = 'Update packages' static name = 'update' @@ -33,7 +31,7 @@ class Update extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } @@ -66,4 +64,5 @@ class Update extends ArboristWorkspaceCmd { await reifyFinish(this.npm, arb) } } + module.exports = Update diff --git a/deps/npm/lib/commands/version.js b/deps/npm/lib/commands/version.js index 029a6fdd3101e4..549ba9b9f9c771 100644 --- a/deps/npm/lib/commands/version.js +++ b/deps/npm/lib/commands/version.js @@ -1,10 +1,7 @@ -const libnpmversion = require('libnpmversion') -const { resolve } = require('path') -const { promisify } = require('util') -const readFile = promisify(require('fs').readFile) - -const updateWorkspaces = require('../workspaces/update-workspaces.js') -const BaseCommand = require('../base-command.js') +const { resolve } = require('node:path') +const { readFile } = require('node:fs/promises') +const { output } = require('proc-log') +const BaseCommand = require('../base-cmd.js') class Version extends BaseCommand { static description = 'Bump a package version' @@ -73,29 +70,43 @@ class Version extends BaseCommand { } async change (args) { + const libnpmversion = require('libnpmversion') const prefix = this.npm.config.get('tag-version-prefix') const version = await libnpmversion(args[0], { ...this.npm.flatOptions, path: this.npm.prefix, }) - return this.npm.output(`${prefix}${version}`) + return output.standard(`${prefix}${version}`) } async changeWorkspaces (args) { + const updateWorkspaces = require('../utils/update-workspaces.js') + const libnpmversion = require('libnpmversion') const prefix = this.npm.config.get('tag-version-prefix') + const { + config, + flatOptions, + localPrefix, + } = this.npm await this.setWorkspaces() const updatedWorkspaces = [] for (const [name, path] of this.workspaces) { - this.npm.output(name) + output.standard(name) const version = await libnpmversion(args[0], { - ...this.npm.flatOptions, + ...flatOptions, 'git-tag-version': false, path, }) updatedWorkspaces.push(name) - this.npm.output(`${prefix}${version}`) + output.standard(`${prefix}${version}`) } - return this.update(updatedWorkspaces) + return updateWorkspaces({ + config, + flatOptions, + localPrefix, + npm: this.npm, + workspaces: updatedWorkspaces, + }) } async list (results = {}) { @@ -115,9 +126,9 @@ class Version extends BaseCommand { } if (this.npm.config.get('json')) { - this.npm.output(JSON.stringify(results, null, 2)) + output.standard(JSON.stringify(results, null, 2)) } else { - this.npm.output(results) + output.standard(results) } } @@ -135,22 +146,6 @@ class Version extends BaseCommand { } return this.list(results) } - - async update (workspaces) { - const { - config, - flatOptions, - localPrefix, - } = this.npm - - await updateWorkspaces({ - config, - flatOptions, - localPrefix, - npm: this.npm, - workspaces, - }) - } } module.exports = Version diff --git a/deps/npm/lib/commands/view.js b/deps/npm/lib/commands/view.js index b19604f8c2ed35..c0d5bf552eee02 100644 --- a/deps/npm/lib/commands/view.js +++ b/deps/npm/lib/commands/view.js @@ -1,20 +1,19 @@ const columns = require('cli-columns') -const fs = require('fs') +const { readFile } = require('fs/promises') const jsonParse = require('json-parse-even-better-errors') -const log = require('../utils/log-shim.js') +const { log, output } = require('proc-log') const npa = require('npm-package-arg') const { resolve } = require('path') const formatBytes = require('../utils/format-bytes.js') const relativeDate = require('tiny-relative-date') const semver = require('semver') -const { inspect, promisify } = require('util') +const { inspect } = require('util') const { packument } = require('pacote') +const Queryable = require('../utils/queryable.js') +const BaseCommand = require('../base-cmd.js') -const readFile = promisify(fs.readFile) const readJson = async file => jsonParse(await readFile(file, 'utf8')) -const Queryable = require('../utils/queryable.js') -const BaseCommand = require('../base-command.js') class View extends BaseCommand { static description = 'View registry info' static name = 'view' @@ -115,13 +114,10 @@ class View extends BaseCommand { reducedData = cleanBlanks(reducedData) log.silly('view', reducedData) } - // disable the progress bar entirely, as we can't meaningfully update it - // if we may have partial lines printed. - log.disableProgress() const msg = await this.jsonData(reducedData, pckmnt._id) if (msg !== '') { - this.npm.output(msg) + output.standard(msg) } } } @@ -160,10 +156,10 @@ class View extends BaseCommand { if (wholePackument) { data.map((v) => this.prettyView(pckmnt, v[Object.keys(v)[0]][''])) } else { - this.npm.output(`${name}:`) + output.standard(`${name}:`) const msg = await this.jsonData(reducedData, pckmnt._id) if (msg !== '') { - this.npm.output(msg) + output.standard(msg) } } } else { @@ -174,7 +170,7 @@ class View extends BaseCommand { } } if (Object.keys(results).length > 0) { - this.npm.output(JSON.stringify(results, null, 2)) + output.standard(JSON.stringify(results, null, 2)) } } @@ -321,131 +317,96 @@ class View extends BaseCommand { // More modern, pretty printing of default view const unicode = this.npm.config.get('unicode') const chalk = this.npm.chalk - const tags = [] - - Object.keys(packu['dist-tags']).forEach((t) => { - const version = packu['dist-tags'][t] - tags.push(`${chalk.bold.green(t)}: ${version}`) - }) - const unpackedSize = manifest.dist.unpackedSize && - formatBytes(manifest.dist.unpackedSize, true) + const deps = Object.keys(manifest.dependencies || {}).map((dep) => + `${chalk.blue(dep)}: ${manifest.dependencies[dep]}` + ) + const site = manifest.homepage?.url || manifest.homepage + const bins = Object.keys(manifest.bin || {}) const licenseField = manifest.license || 'Proprietary' - const info = { - name: chalk.green(manifest.name), - version: chalk.green(manifest.version), - bins: Object.keys(manifest.bin || {}), - versions: chalk.yellow(packu.versions.length + ''), - description: manifest.description, - deprecated: manifest.deprecated, - keywords: packu.keywords || [], - license: typeof licenseField === 'string' - ? licenseField - : (licenseField.type || 'Proprietary'), - deps: Object.keys(manifest.dependencies || {}).map((dep) => { - return `${chalk.yellow(dep)}: ${manifest.dependencies[dep]}` - }), - publisher: manifest._npmUser && unparsePerson({ - name: chalk.yellow(manifest._npmUser.name), - email: chalk.cyan(manifest._npmUser.email), - }), - modified: !packu.time ? undefined - : chalk.yellow(relativeDate(packu.time[manifest.version])), - maintainers: (packu.maintainers || []).map((u) => unparsePerson({ - name: chalk.yellow(u.name), - email: chalk.cyan(u.email), - })), - repo: ( - manifest.bugs && (manifest.bugs.url || manifest.bugs) - ) || ( - manifest.repository && (manifest.repository.url || manifest.repository) - ), - site: ( - manifest.homepage && (manifest.homepage.url || manifest.homepage) - ), - tags, - tarball: chalk.cyan(manifest.dist.tarball), - shasum: chalk.yellow(manifest.dist.shasum), - integrity: - manifest.dist.integrity && chalk.yellow(manifest.dist.integrity), - fileCount: - manifest.dist.fileCount && chalk.yellow(manifest.dist.fileCount), - unpackedSize: unpackedSize && chalk.yellow(unpackedSize), - } - if (info.license.toLowerCase().trim() === 'proprietary') { - info.license = chalk.bold.red(info.license) - } else { - info.license = chalk.green(info.license) + const license = typeof licenseField === 'string' + ? licenseField + : (licenseField.type || 'Proprietary') + + output.standard('') + output.standard([ + chalk.underline.cyan(`${manifest.name}@${manifest.version}`), + license.toLowerCase().trim() === 'proprietary' + ? chalk.red(license) + : chalk.green(license), + `deps: ${deps.length ? chalk.cyan(deps.length) : chalk.cyan('none')}`, + `versions: ${chalk.cyan(packu.versions.length + '')}`, + ].join(' | ')) + + manifest.description && output.standard(manifest.description) + if (site) { + output.standard(chalk.blue(site)) } - this.npm.output('') - this.npm.output( - chalk.underline.bold(`${info.name}@${info.version}`) + - ' | ' + info.license + - ' | deps: ' + (info.deps.length ? chalk.cyan(info.deps.length) : chalk.green('none')) + - ' | versions: ' + info.versions + manifest.deprecated && output.standard( + `\n${chalk.redBright('DEPRECATED')}${unicode ? ' ⚠️ ' : '!!'} - ${manifest.deprecated}` ) - info.description && this.npm.output(info.description) - if (info.repo || info.site) { - info.site && this.npm.output(chalk.cyan(info.site)) - } - const warningSign = unicode ? ' ⚠️ ' : '!!' - info.deprecated && this.npm.output( - `\n${chalk.bold.red('DEPRECATED')}${ - warningSign - } - ${info.deprecated}` - ) + if (packu.keywords?.length) { + output.standard(`\nkeywords: ${ + packu.keywords.map(k => chalk.cyan(k)).join(', ') + }`) + } - if (info.keywords.length) { - this.npm.output('') - this.npm.output(`keywords: ${chalk.yellow(info.keywords.join(', '))}`) + if (bins.length) { + output.standard(`\nbin: ${chalk.cyan(bins.join(', '))}`) } - if (info.bins.length) { - this.npm.output('') - this.npm.output(`bin: ${chalk.yellow(info.bins.join(', '))}`) + output.standard('\ndist') + output.standard(`.tarball: ${chalk.blue(manifest.dist.tarball)}`) + output.standard(`.shasum: ${chalk.green(manifest.dist.shasum)}`) + if (manifest.dist.integrity) { + output.standard(`.integrity: ${chalk.green(manifest.dist.integrity)}`) + } + if (manifest.dist.unpackedSize) { + output.standard(`.unpackedSize: ${chalk.blue(formatBytes(manifest.dist.unpackedSize, true))}`) } - this.npm.output('') - this.npm.output('dist') - this.npm.output(`.tarball: ${info.tarball}`) - this.npm.output(`.shasum: ${info.shasum}`) - info.integrity && this.npm.output(`.integrity: ${info.integrity}`) - info.unpackedSize && this.npm.output(`.unpackedSize: ${info.unpackedSize}`) - - const maxDeps = 24 - if (info.deps.length) { - this.npm.output('') - this.npm.output('dependencies:') - this.npm.output(columns(info.deps.slice(0, maxDeps), { padding: 1 })) - if (info.deps.length > maxDeps) { - this.npm.output(`(...and ${info.deps.length - maxDeps} more.)`) + if (deps.length) { + const maxDeps = 24 + output.standard('\ndependencies:') + output.standard(columns(deps.slice(0, maxDeps), { padding: 1 })) + if (deps.length > maxDeps) { + output.standard(chalk.dim(`(...and ${deps.length - maxDeps} more.)`)) } } - if (info.maintainers && info.maintainers.length) { - this.npm.output('') - this.npm.output('maintainers:') - info.maintainers.forEach((u) => this.npm.output(`- ${u}`)) + if (packu.maintainers?.length) { + output.standard('\nmaintainers:') + packu.maintainers.forEach(u => + output.standard(`- ${unparsePerson({ + name: chalk.blue(u.name), + email: chalk.dim(u.email) })}`) + ) } - this.npm.output('') - this.npm.output('dist-tags:') - this.npm.output(columns(info.tags)) + output.standard('\ndist-tags:') + output.standard(columns(Object.keys(packu['dist-tags']).map(t => + `${chalk.blue(t)}: ${packu['dist-tags'][t]}` + ))) - if (info.publisher || info.modified) { + const publisher = manifest._npmUser && unparsePerson({ + name: chalk.blue(manifest._npmUser.name), + email: chalk.dim(manifest._npmUser.email), + }) + if (publisher || packu.time) { let publishInfo = 'published' - if (info.modified) { - publishInfo += ` ${info.modified}` + if (packu.time) { + publishInfo += ` ${chalk.cyan(relativeDate(packu.time[manifest.version]))}` } - if (info.publisher) { - publishInfo += ` by ${info.publisher}` + if (publisher) { + publishInfo += ` by ${publisher}` } - this.npm.output('') - this.npm.output(publishInfo) + output.standard('') + output.standard(publishInfo) } } } + module.exports = View function cleanBlanks (obj) { diff --git a/deps/npm/lib/commands/whoami.js b/deps/npm/lib/commands/whoami.js index 154cc870391ba1..507adb276c7313 100644 --- a/deps/npm/lib/commands/whoami.js +++ b/deps/npm/lib/commands/whoami.js @@ -1,16 +1,18 @@ +const { output } = require('proc-log') const getIdentity = require('../utils/get-identity.js') +const BaseCommand = require('../base-cmd.js') -const BaseCommand = require('../base-command.js') class Whoami extends BaseCommand { static description = 'Display npm username' static name = 'whoami' static params = ['registry'] - async exec (args) { + async exec () { const username = await getIdentity(this.npm, { ...this.npm.flatOptions }) - this.npm.output( + output.standard( this.npm.config.get('json') ? JSON.stringify(username) : username ) } } + module.exports = Whoami diff --git a/deps/npm/lib/lifecycle-cmd.js b/deps/npm/lib/lifecycle-cmd.js index 848771a38355e5..a509a9380f668c 100644 --- a/deps/npm/lib/lifecycle-cmd.js +++ b/deps/npm/lib/lifecycle-cmd.js @@ -1,7 +1,7 @@ +const BaseCommand = require('./base-cmd.js') + // The implementation of commands that are just "run a script" // restart, start, stop, test - -const BaseCommand = require('./base-command.js') class LifecycleCmd extends BaseCommand { static usage = ['[-- ]'] static isShellout = true @@ -16,4 +16,5 @@ class LifecycleCmd extends BaseCommand { return this.npm.exec('run-script', [this.constructor.name, ...args]) } } + module.exports = LifecycleCmd diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js index 0a023f4ac8a302..df2297b215da7b 100644 --- a/deps/npm/lib/npm.js +++ b/deps/npm/lib/npm.js @@ -1,19 +1,14 @@ -const { resolve, dirname, join } = require('path') +const { resolve, dirname, join } = require('node:path') const Config = require('@npmcli/config') const which = require('which') -const fs = require('fs/promises') - -// Patch the global fs module here at the app level -require('graceful-fs').gracefulify(require('fs')) - +const fs = require('node:fs/promises') const { definitions, flatten, shorthands } = require('@npmcli/config/lib/definitions') const usage = require('./utils/npm-usage.js') const LogFile = require('./utils/log-file.js') const Timers = require('./utils/timers.js') const Display = require('./utils/display.js') -const log = require('./utils/log-shim') -const replaceInfo = require('./utils/replace-info.js') -const updateNotifier = require('./utils/update-notifier.js') +const { log, time, output } = require('proc-log') +const { redactLog: replaceInfo } = require('@npmcli/redact') const pkg = require('../package.json') const { deref } = require('./utils/cmd-list.js') @@ -27,38 +22,25 @@ class Npm { if (!command) { throw Object.assign(new Error(`Unknown command ${c}`), { code: 'EUNKNOWNCOMMAND', + command: c, }) } return require(`./commands/${command}.js`) } + unrefPromises = [] updateNotification = null - loadErr = null argv = [] #command = null #runId = new Date().toISOString().replace(/[.:]/g, '_') - #loadPromise = null #title = 'npm' #argvClean = [] #npmRoot = null - #warnedNonDashArg = false - - #chalk = null - #logChalk = null - #noColorChalk = null - #outputBuffer = [] + #display = null #logFile = new LogFile() - #display = new Display() - #timers = new Timers({ - start: 'npm', - listener: (name, ms) => { - const args = ['timing', name, `Completed in ${ms}ms`] - this.#logFile.log(...args) - this.#display.log(...args) - }, - }) + #timers = new Timers() // all these options are only used by tests in order to make testing more // closely resemble real world usage. for now, npm has no programmatic API so @@ -72,7 +54,14 @@ class Npm { // allows tests created by tap inside this repo to not set the local // prefix to `npmRoot` since that is the first dir it would encounter when // doing implicit detection - constructor ({ npmRoot = dirname(__dirname), argv = [], excludeNpmCwd = false } = {}) { + constructor ({ + stdout = process.stdout, + stderr = process.stderr, + npmRoot = dirname(__dirname), + argv = [], + excludeNpmCwd = false, + } = {}) { + this.#display = new Display({ stdout, stderr }) this.#npmRoot = npmRoot this.config = new Config({ npmPath: this.#npmRoot, @@ -88,7 +77,8 @@ class Npm { return this.constructor.version } - setCmd (cmd) { + // Call an npm command + async exec (cmd, args = this.argv) { const Command = Npm.cmd(cmd) const command = new Command(this) @@ -99,51 +89,11 @@ class Npm { process.env.npm_command = this.command } - return command - } - - // Call an npm command - // TODO: tests are currently the only time the second - // parameter of args is used. When called via `lib/cli.js` the config is - // loaded and this.argv is set to the remaining command line args. We should - // consider testing the CLI the same way it is used and not allow args to be - // passed in directly. - async exec (cmd, args = this.argv) { - const command = this.setCmd(cmd) - - const timeEnd = this.time(`command:${cmd}`) - - // this is async but we dont await it, since its ok if it doesnt - // finish before the command finishes running. it uses command and argv - // so it must be initiated here, after the command name is set - // eslint-disable-next-line promise/catch-or-return - updateNotifier(this).then((msg) => (this.updateNotification = msg)) - - // Options are prefixed by a hyphen-minus (-, \u2d). - // Other dash-type chars look similar but are invalid. - if (!this.#warnedNonDashArg) { - const nonDashArgs = args.filter(a => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(a)) - if (nonDashArgs.length) { - this.#warnedNonDashArg = true - log.error( - 'arg', - 'Argument starts with non-ascii dash, this is probably invalid:', - nonDashArgs.join(', ') - ) - } - } - - return command.cmdExec(args).finally(timeEnd) + return time.start(`command:${cmd}`, () => command.cmdExec(args)) } async load () { - if (!this.#loadPromise) { - this.#loadPromise = this.time('npm:load', () => this.#load().catch((er) => { - this.loadErr = er - throw er - })) - } - return this.#loadPromise + return time.start('npm:load', () => this.#load()) } get loaded () { @@ -159,30 +109,44 @@ class Npm { this.#logFile.off() } - time (name, fn) { - return this.#timers.time(name, fn) - } - - writeTimingFile () { - this.#timers.writeFile({ + finish ({ showLogFileError } = {}) { + this.#timers.finish({ id: this.#runId, command: this.#argvClean, logfiles: this.logFiles, version: this.version, }) + + if (showLogFileError) { + if (!this.silent) { + // just a line break if not in silent mode + output.error('') + } + + if (this.logFiles.length) { + return log.error('', `A complete log of this run can be found in: ${this.logFiles}`) + } + + const logsMax = this.config.get('logs-max') + if (logsMax <= 0) { + // user specified no log file + log.error('', `Log files were not written due to the config logs-max=${logsMax}`) + } else { + // could be an error writing to the directory + log.error('', + `Log files were not written due to an error writing to the directory: ${this.#logsDir}` + + '\nYou can rerun the command with `--loglevel=verbose` to see the logs in your terminal' + ) + } + } } get title () { return this.#title } - set title (t) { - process.title = t - this.#title = t - } - async #load () { - await this.time('npm:load:whichnode', async () => { + await time.start('npm:load:whichnode', async () => { // TODO should we throw here? const node = await which(process.argv[0]).catch(() => {}) if (node && node.toUpperCase() !== process.execPath.toUpperCase()) { @@ -192,46 +156,72 @@ class Npm { } }) - await this.time('npm:load:configload', () => this.config.load()) - - // get createSupportsColor from chalk directly if this lands - // https://github.com/chalk/chalk/pull/600 - const [{ Chalk }, { createSupportsColor }] = await Promise.all([ - import('chalk'), - import('supports-color'), - ]) - this.#noColorChalk = new Chalk({ level: 0 }) - // we get the chalk level based on a null stream meaning chalk will only use - // what it knows about the environment to get color support since we already - // determined in our definitions that we want to show colors. - const level = Math.max(createSupportsColor(null).level, 1) - this.#chalk = this.color ? new Chalk({ level }) : this.#noColorChalk - this.#logChalk = this.logColor ? new Chalk({ level }) : this.#noColorChalk + await time.start('npm:load:configload', () => this.config.load()) + + // npm --versions + if (this.config.get('versions', 'cli')) { + this.argv = ['version'] + this.config.set('usage', false, 'cli') + } else { + this.argv = [...this.config.parsedArgv.remain] + } + + // Remove first argv since that is our command as typed + // Note that this might not be the actual name of the command + // due to aliases, etc. But we use the raw form of it later + // in user output so it must be preserved as is. + const commandArg = this.argv.shift() + + // This is the actual name of the command that will be run or + // undefined if deref could not find a match + const command = deref(commandArg) + + await this.#display.load({ + command, + loglevel: this.config.get('loglevel'), + stdoutColor: this.color, + stderrColor: this.logColor, + timing: this.config.get('timing'), + unicode: this.config.get('unicode'), + progress: this.flatOptions.progress, + json: this.config.get('json'), + heading: this.config.get('heading'), + }) + process.env.COLOR = this.color ? '1' : '0' + + // npm -v + // return from here early so we dont create any caches/logfiles/timers etc + if (this.config.get('version', 'cli')) { + output.standard(this.version) + return { exec: false } + } // mkdir this separately since the logs dir can be set to // a different location. if this fails, then we don't have // a cache dir, but we don't want to fail immediately since // the command might not need a cache dir (like `npm --version`) - await this.time('npm:load:mkdirpcache', () => + await time.start('npm:load:mkdirpcache', () => fs.mkdir(this.cache, { recursive: true }) .catch((e) => log.verbose('cache', `could not create cache: ${e}`))) // it's ok if this fails. user might have specified an invalid dir // which we will tell them about at the end if (this.config.get('logs-max') > 0) { - await this.time('npm:load:mkdirplogs', () => - fs.mkdir(this.logsDir, { recursive: true }) + await time.start('npm:load:mkdirplogs', () => + fs.mkdir(this.#logsDir, { recursive: true }) .catch((e) => log.verbose('logfile', `could not create logs-dir: ${e}`))) } // note: this MUST be shorter than the actual argv length, because it // uses the same memory, so node will truncate it if it's too long. - this.time('npm:load:setTitle', () => { + // We time this because setting process.title is slow sometimes but we + // have to do it for security reasons. But still helpful to know how slow it is. + time.start('npm:load:setTitle', () => { const { parsedArgv: { cooked, remain } } = this.config - this.argv = remain // Secrets are mostly in configs, so title is set using only the positional args - // to keep those from being leaked. - this.title = ['npm'].concat(replaceInfo(remain)).join(' ').trim() + // to keep those from being leaked. We still do a best effort replaceInfo. + this.#title = ['npm'].concat(replaceInfo(remain)).join(' ').trim() + process.title = this.#title // The cooked argv is also logged separately for debugging purposes. It is // cleaned as a best effort by replacing known secrets like basic auth // password and strings that look like npm tokens. XXX: for this to be @@ -242,45 +232,32 @@ class Npm { log.verbose('argv', this.#argvClean.map(JSON.stringify).join(' ')) }) - this.time('npm:load:display', () => { - this.#display.load({ - // Use logColor since that is based on stderr - color: this.logColor, - chalk: this.logChalk, - progress: this.flatOptions.progress, - silent: this.silent, - timing: this.config.get('timing'), - loglevel: this.config.get('loglevel'), - unicode: this.config.get('unicode'), - heading: this.config.get('heading'), - }) - process.env.COLOR = this.color ? '1' : '0' - }) - - this.time('npm:load:logFile', () => { - this.#logFile.load({ - path: this.logPath, - logsMax: this.config.get('logs-max'), - }) - log.verbose('logfile', this.#logFile.files[0] || 'no logfile created') + // logFile.load returns a promise that resolves when old logs are done being cleaned. + // We save this promise to an array so that we can await it in tests to ensure more + // deterministic logging behavior. The process will also hang open if this were to + // take a long time to resolve, but that is why process.exit is called explicitly + // in the exit-handler. + this.unrefPromises.push(this.#logFile.load({ + path: this.logPath, + logsMax: this.config.get('logs-max'), + timing: this.config.get('timing'), + })) + + this.#timers.load({ + path: this.logPath, + timing: this.config.get('timing'), }) - this.time('npm:load:timers', () => - this.#timers.load({ - path: this.config.get('timing') ? this.logPath : null, - }) - ) - - this.time('npm:load:configScope', () => { - const configScope = this.config.get('scope') - if (configScope && !/^@/.test(configScope)) { - this.config.set('scope', `@${configScope}`, this.config.find('scope')) - } - }) + const configScope = this.config.get('scope') + if (configScope && !/^@/.test(configScope)) { + this.config.set('scope', `@${configScope}`, this.config.find('scope')) + } if (this.config.get('force')) { log.warn('using --force', 'Recommended protections disabled.') } + + return { exec: true, command: commandArg, args: this.argv } } get isShellout () { @@ -313,15 +290,15 @@ class Npm { } get noColorChalk () { - return this.#noColorChalk + return this.#display.chalk.noColor } get chalk () { - return this.#chalk + return this.#display.chalk.stdout } get logChalk () { - return this.#logChalk + return this.#display.chalk.stderr } get global () { @@ -336,14 +313,6 @@ class Npm { return 2 } - get unfinishedTimers () { - return this.#timers.unfinished - } - - get finishedTimers () { - return this.#timers.finished - } - get started () { return this.#timers.started } @@ -352,16 +321,12 @@ class Npm { return this.#logFile.files } - get logsDir () { + get #logsDir () { return this.config.get('logs-dir') || join(this.cache, '_logs') } get logPath () { - return resolve(this.logsDir, `${this.#runId}-`) - } - - get timingFile () { - return this.#timers.file + return resolve(this.#logsDir, `${this.#runId}-`) } get npmRoot () { @@ -372,26 +337,14 @@ class Npm { return this.config.get('cache') } - set cache (r) { - this.config.set('cache', r) - } - get globalPrefix () { return this.config.globalPrefix } - set globalPrefix (r) { - this.config.globalPrefix = r - } - get localPrefix () { return this.config.localPrefix } - set localPrefix (r) { - this.config.localPrefix = r - } - get localPackage () { return this.config.localPackage } @@ -427,59 +380,9 @@ class Npm { return this.global ? this.globalPrefix : this.localPrefix } - set prefix (r) { - const k = this.global ? 'globalPrefix' : 'localPrefix' - this[k] = r - } - get usage () { return usage(this) } - - // output to stdout in a progress bar compatible way - output (...msg) { - log.clearProgress() - // eslint-disable-next-line no-console - console.log(...msg.map(Display.clean)) - log.showProgress() - } - - outputBuffer (item) { - this.#outputBuffer.push(item) - } - - flushOutput (jsonError) { - if (!jsonError && !this.#outputBuffer.length) { - return - } - - if (this.config.get('json')) { - const jsonOutput = this.#outputBuffer.reduce((acc, item) => { - if (typeof item === 'string') { - // try to parse it as json in case its a string - try { - item = JSON.parse(item) - } catch { - return acc - } - } - return { ...acc, ...item } - }, {}) - this.output(JSON.stringify({ ...jsonOutput, ...jsonError }, null, 2)) - } else { - for (const item of this.#outputBuffer) { - this.output(item) - } - } - - this.#outputBuffer.length = 0 - } - - outputError (...msg) { - log.clearProgress() - // eslint-disable-next-line no-console - console.error(...msg.map(Display.clean)) - log.showProgress() - } } + module.exports = Npm diff --git a/deps/npm/lib/package-url-cmd.js b/deps/npm/lib/package-url-cmd.js index 250b46eeeddbe5..bcefd17af4492a 100644 --- a/deps/npm/lib/package-url-cmd.js +++ b/deps/npm/lib/package-url-cmd.js @@ -1,12 +1,9 @@ -// Base command for opening urls from a package manifest (bugs, docs, repo) - const pacote = require('pacote') -const hostedGitInfo = require('hosted-git-info') - const openUrl = require('./utils/open-url.js') -const log = require('./utils/log-shim') +const { log } = require('proc-log') +const BaseCommand = require('./base-cmd.js') -const BaseCommand = require('./base-command.js') +// Base command for opening urls from a package manifest (bugs, docs, repo) class PackageUrlCommand extends BaseCommand { static params = [ 'browser', @@ -52,6 +49,7 @@ class PackageUrlCommand extends BaseCommand { // repository (if a string) or repository.url (if an object) returns null // if it's not a valid repo, or not a known hosted repo hostedFromMani (mani) { + const hostedGitInfo = require('hosted-git-info') const r = mani.repository const rurl = !r ? null : typeof r === 'string' ? r @@ -62,4 +60,5 @@ class PackageUrlCommand extends BaseCommand { return (rurl && hostedGitInfo.fromUrl(rurl.replace(/^git\+/, ''))) || null } } + module.exports = PackageUrlCommand diff --git a/deps/npm/lib/utils/audit-error.js b/deps/npm/lib/utils/audit-error.js index aaf35566fc0304..10aec7592b03ce 100644 --- a/deps/npm/lib/utils/audit-error.js +++ b/deps/npm/lib/utils/audit-error.js @@ -1,5 +1,5 @@ -const log = require('./log-shim') -const replaceInfo = require('./replace-info.js') +const { log, output } = require('proc-log') +const { redactLog: replaceInfo } = require('@npmcli/redact') // print an error or just nothing if the audit report has an error // this is called by the audit command, and by the reify-output util @@ -22,7 +22,7 @@ const auditError = (npm, report) => { const { body: errBody } = error const body = Buffer.isBuffer(errBody) ? errBody.toString() : errBody if (npm.flatOptions.json) { - npm.output(JSON.stringify({ + output.standard(JSON.stringify({ message: error.message, method: error.method, uri: replaceInfo(error.uri), @@ -31,7 +31,7 @@ const auditError = (npm, report) => { body, }, null, 2)) } else { - npm.output(body) + output.standard(body) } throw 'audit endpoint returned an error' diff --git a/deps/npm/lib/utils/auth.js b/deps/npm/lib/utils/auth.js index 729ce32c2a7a8f..04ca455ceb5261 100644 --- a/deps/npm/lib/utils/auth.js +++ b/deps/npm/lib/utils/auth.js @@ -1,5 +1,5 @@ const profile = require('npm-profile') -const log = require('../utils/log-shim') +const { log } = require('proc-log') const openUrlPrompt = require('../utils/open-url-prompt.js') const read = require('../utils/read-user-info.js') const otplease = require('../utils/otplease.js') @@ -36,7 +36,7 @@ const adduser = async (npm, { creds, ...opts }) => { // password, it's effectively a login, and if that account has otp you'll // be prompted for it. res = await otplease(npm, opts, (reqOpts) => - profile.adduserCouch(username, email, password, opts) + profile.adduserCouch(username, email, password, reqOpts) ) } diff --git a/deps/npm/lib/utils/did-you-mean.js b/deps/npm/lib/utils/did-you-mean.js index ff3c812b46c3c7..54c8ff2e35aa69 100644 --- a/deps/npm/lib/utils/did-you-mean.js +++ b/deps/npm/lib/utils/did-you-mean.js @@ -8,7 +8,7 @@ const didYouMean = async (path, scmd) => { let best = [] for (const str of close) { const cmd = Npm.cmd(str) - best.push(` npm ${str} # ${cmd.description}`) + best.push(` npm ${str} # ${cmd.description}`) } // We would already be suggesting this in `npm x` so omit them here const runScripts = ['stop', 'start', 'test', 'restart'] @@ -17,13 +17,13 @@ const didYouMean = async (path, scmd) => { best = best.concat( Object.keys(scripts || {}) .filter(cmd => distance(scmd, cmd) < scmd.length * 0.4 && !runScripts.includes(cmd)) - .map(str => ` npm run ${str} # run the "${str}" package script`), + .map(str => ` npm run ${str} # run the "${str}" package script`), Object.keys(bin || {}) .filter(cmd => distance(scmd, cmd) < scmd.length * 0.4) /* eslint-disable-next-line max-len */ - .map(str => ` npm exec ${str} # run the "${str}" command from either this or a remote npm package`) + .map(str => ` npm exec ${str} # run the "${str}" command from either this or a remote npm package`) ) - } catch (_) { + } catch { // gracefully ignore not being in a folder w/ a package.json } @@ -31,10 +31,9 @@ const didYouMean = async (path, scmd) => { return '' } - const suggestion = - best.length === 1 - ? `\n\nDid you mean this?\n${best[0]}` - : `\n\nDid you mean one of these?\n${best.slice(0, 3).join('\n')}` - return suggestion + return best.length === 1 + ? `\n\nDid you mean this?\n${best[0]}` + : `\n\nDid you mean one of these?\n${best.slice(0, 3).join('\n')}` } + module.exports = didYouMean diff --git a/deps/npm/lib/utils/display.js b/deps/npm/lib/utils/display.js index c5e5ca2b5b874a..29a1f7951d5063 100644 --- a/deps/npm/lib/utils/display.js +++ b/deps/npm/lib/utils/display.js @@ -1,214 +1,489 @@ -const { inspect } = require('util') -const npmlog = require('npmlog') -const log = require('./log-shim.js') +const { log, output, input, META } = require('proc-log') const { explain } = require('./explain-eresolve.js') +const { formatWithOptions } = require('./format') -const originalCustomInspect = Symbol('npm.display.original.util.inspect.custom') - -// These are most assuredly not a mistake -// https://eslint.org/docs/latest/rules/no-control-regex -/* eslint-disable no-control-regex */ -// \x00 through \x1f, \x7f through \x9f, not including \x09 \x0a \x0b \x0d -const hasC01 = /[\x00-\x08\x0c\x0e-\x1f\x7f-\x9f]/ -// Allows everything up to '[38;5;255m' in 8 bit notation -const allowedSGR = /^\[[0-9;]{0,8}m/ -// '[38;5;255m'.length -const sgrMaxLen = 10 - -// Strips all ANSI C0 and C1 control characters (except for SGR up to 8 bit) -function stripC01 (str) { - if (!hasC01.test(str)) { - return str - } - let result = '' - for (let i = 0; i < str.length; i++) { - const char = str[i] - const code = char.charCodeAt(0) - if (!hasC01.test(char)) { - // Most characters are in this set so continue early if we can - result = `${result}${char}` - } else if (code === 27 && allowedSGR.test(str.slice(i + 1, i + sgrMaxLen + 1))) { - // \x1b with allowed SGR - result = `${result}\x1b` - } else if (code <= 31) { - // escape all other C0 control characters besides \x7f - result = `${result}^${String.fromCharCode(code + 64)}` - } else { - // hasC01 ensures this is now a C1 control character or \x7f - result = `${result}^${String.fromCharCode(code - 64)}` +// This is the general approach to color: +// Eventually this will be exposed somewhere we can refer to these by name. +// Foreground colors only. Never set the background color. +/* + * Black # (Don't use) + * Red # Danger + * Green # Success + * Yellow # Warning + * Blue # Accent + * Magenta # Done + * Cyan # Emphasis + * White # (Don't use) + */ + +// Translates log levels to chalk colors +const COLOR_PALETTE = ({ chalk: c }) => ({ + heading: c.bold, + title: c.blueBright, + timing: c.magentaBright, + // loglevels + error: c.red, + warn: c.yellow, + notice: c.cyanBright, + http: c.green, + info: c.cyan, + verbose: c.blue, + silly: c.blue.dim, +}) + +const LEVEL_OPTIONS = { + silent: { + index: 0, + }, + error: { + index: 1, + }, + warn: { + index: 2, + }, + notice: { + index: 3, + }, + http: { + index: 4, + }, + info: { + index: 5, + }, + verbose: { + index: 6, + }, + silly: { + index: 7, + }, +} + +const LEVEL_METHODS = { + ...LEVEL_OPTIONS, + [log.KEYS.timing]: { + show: ({ timing, index }) => !!timing && index !== 0, + }, +} + +const tryJsonParse = (value) => { + if (typeof value === 'string') { + try { + return JSON.parse(value) + } catch { + return {} } } - return result + return value } -class Display { - #chalk = null +const setBlocking = (stream) => { + // Copied from https://github.com/yargs/set-blocking + // https://raw.githubusercontent.com/yargs/set-blocking/master/LICENSE.txt + /* istanbul ignore next - we trust that this works */ + if (stream._handle && stream.isTTY && typeof stream._handle.setBlocking === 'function') { + stream._handle.setBlocking(true) + } + return stream +} + +const withMeta = (handler) => (level, ...args) => { + let meta = {} + const last = args.at(-1) + if (last && typeof last === 'object' && Object.hasOwn(last, META)) { + meta = args.pop() + } + return handler(level, meta, ...args) +} - constructor () { - // pause by default until config is loaded - this.on() - log.pause() +class Display { + #logState = { + buffering: true, + buffer: [], } - static clean (output) { - if (typeof output === 'string') { - // Strings are cleaned inline - return stripC01(output) - } - if (!output || typeof output !== 'object') { - // Numbers, booleans, null all end up here and don't need cleaning - return output - } - // output && typeof output === 'object' - // We can't use hasOwn et al for detecting the original but we can use it - // for detecting the properties we set via defineProperty - if ( - output[inspect.custom] && - (!Object.hasOwn(output, originalCustomInspect)) - ) { - // Save the old one if we didn't already do it. - Object.defineProperty(output, originalCustomInspect, { - value: output[inspect.custom], - writable: true, - }) - } - if (!Object.hasOwn(output, originalCustomInspect)) { - // Put a dummy one in for when we run multiple times on the same object - Object.defineProperty(output, originalCustomInspect, { - value: function () { - return this - }, - writable: true, - }) - } - // Set the custom inspect to our own function - Object.defineProperty(output, inspect.custom, { - value: function () { - const toClean = this[originalCustomInspect]() - // Custom inspect can return things other than objects, check type again - if (typeof toClean === 'string') { - // Strings are cleaned inline - return stripC01(toClean) - } - if (!toClean || typeof toClean !== 'object') { - // Numbers, booleans, null all end up here and don't need cleaning - return toClean - } - return stripC01(inspect(toClean, { customInspect: false })) - }, - writable: true, - }) - return output + #outputState = { + buffering: true, + buffer: [], } - on () { + // colors + #noColorChalk + #stdoutChalk + #stdoutColor + #stderrChalk + #stderrColor + #logColors + + // progress + #progress + + // options + #command + #levelIndex + #timing + #json + #heading + #silent + + // display streams + #stdout + #stderr + + constructor ({ stdout, stderr }) { + this.#stdout = setBlocking(stdout) + this.#stderr = setBlocking(stderr) + + // Handlers are set immediately so they can buffer all events process.on('log', this.#logHandler) + process.on('output', this.#outputHandler) + process.on('input', this.#inputHandler) + this.#progress = new Progress({ stream: stderr }) } off () { process.off('log', this.#logHandler) - // Unbalanced calls to enable/disable progress - // will leave change listeners on the tracker - // This pretty much only happens in tests but - // this removes the event emitter listener warnings - log.tracker.removeAllListeners() - } - - load (config) { - const { - color, - chalk, - timing, - loglevel, + this.#logState.buffer.length = 0 + process.off('output', this.#outputHandler) + this.#outputState.buffer.length = 0 + process.off('input', this.#inputHandler) + this.#progress.off() + } + + get chalk () { + return { + noColor: this.#noColorChalk, + stdout: this.#stdoutChalk, + stderr: this.#stderrChalk, + } + } + + async load ({ + command, + heading, + json, + loglevel, + progress, + stderrColor, + stdoutColor, + timing, + unicode, + }) { + // get createSupportsColor from chalk directly if this lands + // https://github.com/chalk/chalk/pull/600 + const [{ Chalk }, { createSupportsColor }] = await Promise.all([ + import('chalk'), + import('supports-color'), + ]) + // we get the chalk level based on a null stream meaning chalk will only use + // what it knows about the environment to get color support since we already + // determined in our definitions that we want to show colors. + const level = Math.max(createSupportsColor(null).level, 1) + this.#noColorChalk = new Chalk({ level: 0 }) + this.#stdoutColor = stdoutColor + this.#stdoutChalk = stdoutColor ? new Chalk({ level }) : this.#noColorChalk + this.#stderrColor = stderrColor + this.#stderrChalk = stderrColor ? new Chalk({ level }) : this.#noColorChalk + this.#logColors = COLOR_PALETTE({ chalk: this.#stderrChalk }) + + this.#command = command + this.#levelIndex = LEVEL_OPTIONS[loglevel].index + this.#timing = timing + this.#json = json + this.#heading = heading + this.#silent = this.#levelIndex <= 0 + + // Emit resume event on the logs which will flush output + log.resume() + output.flush() + this.#progress.load({ unicode, - progress, - silent, - heading = 'npm', - } = config - - this.#chalk = chalk - - // npmlog is still going away someday, so this is a hack to dynamically - // set the loglevel of timing based on the timing flag, instead of making - // a breaking change to npmlog. The result is that timing logs are never - // shown except when the --timing flag is set. We also need to change - // the index of the silly level since otherwise it is set to -Infinity - // and we can't go any lower than that. silent is still set to Infinify - // because we DO want silent to hide timing levels. This allows for the - // special case of getting timing information while hiding all CLI output - // in order to get perf information that might be affected by writing to - // a terminal. XXX(npmlog): this will be removed along with npmlog - log.levels.silly = -10000 - log.levels.timing = log.levels[loglevel] + (timing ? 1 : -1) - - log.level = loglevel - log.heading = heading - - if (color) { - log.enableColor() - } else { - log.disableColor() + enabled: !!progress && !this.#silent, + }) + } + + // STREAM WRITES + + // Write formatted and (non-)colorized output to streams + #write (stream, options, ...args) { + const colors = stream === this.#stdout ? this.#stdoutColor : this.#stderrColor + const value = formatWithOptions({ colors, ...options }, ...args) + this.#progress.write(() => stream.write(value)) + } + + // HANDLERS + + // Arrow function assigned to a private class field so it can be passed + // directly as a listener and still reference "this" + #logHandler = withMeta((level, meta, ...args) => { + switch (level) { + case log.KEYS.resume: + this.#logState.buffering = false + this.#logState.buffer.forEach((item) => this.#tryWriteLog(...item)) + this.#logState.buffer.length = 0 + break + + case log.KEYS.pause: + this.#logState.buffering = true + break + + default: + if (this.#logState.buffering) { + this.#logState.buffer.push([level, meta, ...args]) + } else { + this.#tryWriteLog(level, meta, ...args) + } + break } + }) - if (unicode) { - log.enableUnicode() - } else { - log.disableUnicode() + // Arrow function assigned to a private class field so it can be passed + // directly as a listener and still reference "this" + #outputHandler = withMeta((level, meta, ...args) => { + switch (level) { + case output.KEYS.flush: + this.#outputState.buffering = false + if (meta.jsonError && this.#json) { + const json = {} + for (const item of this.#outputState.buffer) { + // index 2 skips the level and meta + Object.assign(json, tryJsonParse(item[2])) + } + this.#writeOutput( + output.KEYS.standard, + meta, + JSON.stringify({ ...json, error: meta.jsonError }, null, 2) + ) + } else { + this.#outputState.buffer.forEach((item) => this.#writeOutput(...item)) + } + this.#outputState.buffer.length = 0 + break + + case output.KEYS.buffer: + this.#outputState.buffer.push([output.KEYS.standard, meta, ...args]) + break + + default: + if (this.#outputState.buffering) { + this.#outputState.buffer.push([level, meta, ...args]) + } else { + // HACK: Check if the argument looks like a run-script banner. This can be + // replaced with proc-log.META in @npmcli/run-script + if (typeof args[0] === 'string' && args[0].startsWith('\n> ') && args[0].endsWith('\n')) { + if (this.#silent || ['exec', 'explore'].includes(this.#command)) { + // Silent mode and some specific commands always hide run script banners + break + } else if (this.#json) { + // In json mode, change output to stderr since we dont want to break json + // parsing on stdout if the user is piping to jq or something. + // XXX: in a future (breaking?) change it might make sense for run-script to + // always output these banners with proc-log.output.error if we think they + // align closer with "logging" instead of "output" + level = output.KEYS.error + } + } + this.#writeOutput(level, meta, ...args) + } + break } + }) - // if it's silent, don't show progress - if (progress && !silent) { - log.enableProgress() - } else { - log.disableProgress() + #inputHandler = withMeta((level, meta, ...args) => { + switch (level) { + case input.KEYS.start: + log.pause() + this.#outputState.buffering = true + this.#progress.off() + break + + case input.KEYS.end: + log.resume() + output.flush() + this.#progress.resume() + break + + case input.KEYS.read: { + // The convention when calling input.read is to pass in a single fn that returns + // the promise to await. resolve and reject are provided by proc-log + const [res, rej, p] = args + return input.start(() => p() + .then(res) + .catch(rej) + // Any call to procLog.input.read will render a prompt to the user, so we always + // add a single newline of output to stdout to move the cursor to the next line + .finally(() => output.standard(''))) + } } + }) - // Resume displaying logs now that we have config - log.resume() - } + // OUTPUT + + #writeOutput (level, meta, ...args) { + switch (level) { + case output.KEYS.standard: + this.#write(this.#stdout, {}, ...args) + break - log (...args) { - this.#logHandler(...args) + case output.KEYS.error: + this.#write(this.#stderr, {}, ...args) + break + } } - #logHandler = (level, ...args) => { + // LOGS + + #tryWriteLog (level, meta, ...args) { try { - this.#log(level, ...args) + // Also (and this is a really inexcusable kludge), we patch the + // log.warn() method so that when we see a peerDep override + // explanation from Arborist, we can replace the object with a + // highly abbreviated explanation of what's being overridden. + // TODO: this could probably be moved to arborist now that display is refactored + const [heading, message, expl] = args + if (level === log.KEYS.warn && heading === 'ERESOLVE' && expl && typeof expl === 'object') { + this.#writeLog(level, meta, heading, message) + this.#writeLog(level, meta, '', explain(expl, this.#stderrChalk, 2)) + return + } + this.#writeLog(level, meta, ...args) } catch (ex) { try { // if it crashed once, it might again! - this.#npmlog('verbose', `attempt to log ${inspect(args)} crashed`, ex) + this.#writeLog(log.KEYS.verbose, meta, '', `attempt to log crashed`, ...args, ex) } catch (ex2) { + // This happens if the object has an inspect method that crashes so just console.error + // with the errors but don't do anything else that might error again. // eslint-disable-next-line no-console - console.error(`attempt to log ${inspect(args)} crashed`, ex, ex2) + console.error(`attempt to log crashed`, ex, ex2) } } } - #log (...args) { - return this.#eresolveWarn(...args) || this.#npmlog(...args) + #writeLog (level, meta, ...args) { + const levelOpts = LEVEL_METHODS[level] + const show = levelOpts.show ?? (({ index }) => levelOpts.index <= index) + const force = meta.force && !this.#silent + + if (force || show({ index: this.#levelIndex, timing: this.#timing })) { + // this mutates the array so we can pass args directly to format later + const title = args.shift() + const prefix = [ + this.#logColors.heading(this.#heading), + this.#logColors[level](level), + title ? this.#logColors.title(title) : null, + ] + this.#write(this.#stderr, { prefix }, ...args) + } + } +} + +class Progress { + // Taken from https://github.com/sindresorhus/cli-spinners + // MIT License + // Copyright (c) Sindre Sorhus (https://sindresorhus.com) + static dots = { duration: 80, frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] } + static lines = { duration: 130, frames: ['-', '\\', '|', '/'] } + + #stream + #spinner + #enabled = false + + #frameIndex = 0 + #lastUpdate = 0 + #interval + #timeout + + // We are rendering is enabled option is set and we are not waiting for the render timeout + get #rendering () { + return this.#enabled && !this.#timeout + } + + // We are spinning if enabled option is set and the render interval has been set + get #spinning () { + return this.#enabled && this.#interval + } + + constructor ({ stream }) { + this.#stream = stream + } + + load ({ enabled, unicode }) { + this.#enabled = enabled + this.#spinner = unicode ? Progress.dots : Progress.lines + // Dont render the spinner for short durations + this.#render(200) + } + + off () { + if (!this.#enabled) { + return + } + clearTimeout(this.#timeout) + this.#timeout = null + clearInterval(this.#interval) + this.#interval = null + this.#frameIndex = 0 + this.#lastUpdate = 0 + this.#clearSpinner() + } + + resume () { + this.#render() } - // Explicitly call these on npmlog and not log shim - // This is the final place we should call npmlog before removing it. - #npmlog (level, ...args) { - npmlog[level](...args.map(Display.clean)) + // If we are currenting rendering the spinner we clear it + // before writing our line and then re-render the spinner after. + // If not then all we need to do is write the line + write (write) { + if (this.#spinning) { + this.#clearSpinner() + } + write() + if (this.#spinning) { + this.#render() + } + } + + #render (ms) { + if (ms) { + this.#timeout = setTimeout(() => { + this.#timeout = null + this.#renderSpinner() + }, ms) + // Make sure this timeout does not keep the process open + this.#timeout.unref() + } else { + this.#renderSpinner() + } } - // Also (and this is a really inexcusable kludge), we patch the - // log.warn() method so that when we see a peerDep override - // explanation from Arborist, we can replace the object with a - // highly abbreviated explanation of what's being overridden. - #eresolveWarn (level, heading, message, expl) { - if (level === 'warn' && - heading === 'ERESOLVE' && - expl && typeof expl === 'object' - ) { - this.#npmlog(level, heading, message) - this.#npmlog(level, '', explain(expl, this.#chalk, 2)) - // Return true to short circuit other log in chain - return true + #renderSpinner () { + if (!this.#rendering) { + return } + // We always attempt to render immediately but we only request to move to the next + // frame if it has been longer than our spinner frame duration since our last update + this.#renderFrame(Date.now() - this.#lastUpdate >= this.#spinner.duration) + clearInterval(this.#interval) + this.#interval = setInterval(() => this.#renderFrame(true), this.#spinner.duration) + } + + #renderFrame (next) { + if (next) { + this.#lastUpdate = Date.now() + this.#frameIndex++ + if (this.#frameIndex >= this.#spinner.frames.length) { + this.#frameIndex = 0 + } + } + this.#clearSpinner() + this.#stream.write(this.#spinner.frames[this.#frameIndex]) + } + + #clearSpinner () { + // Move to the start of the line and clear the rest of the line + this.#stream.cursorTo(0) + this.#stream.clearLine(1) } } diff --git a/deps/npm/lib/utils/error-message.js b/deps/npm/lib/utils/error-message.js index e3d6c3526936f8..969e56636dfe8d 100644 --- a/deps/npm/lib/utils/error-message.js +++ b/deps/npm/lib/utils/error-message.js @@ -1,20 +1,16 @@ -const { format } = require('util') -const { resolve } = require('path') -const nameValidator = require('validate-npm-package-name') -const replaceInfo = require('./replace-info.js') -const { report } = require('./explain-eresolve.js') -const log = require('./log-shim') +const { format } = require('node:util') +const { resolve } = require('node:path') +const { redactLog: replaceInfo } = require('@npmcli/redact') +const { log } = require('proc-log') const messageText = msg => msg.map(line => line.slice(1).join(' ')).join('\n') const jsonError = (er, npm, { summary, detail }) => { if (npm?.config.loaded && npm.config.get('json')) { return { - error: { - code: er.code, - summary: messageText(summary), - detail: messageText(detail), - }, + code: er.code, + summary: messageText(summary), + detail: messageText(detail), } } } @@ -33,6 +29,7 @@ const errorMessage = (er, npm) => { switch (er.code) { case 'ERESOLVE': { + const { report } = require('./explain-eresolve.js') short.push(['ERESOLVE', er.message]) detail.push(['', '']) // XXX(display): error messages are logged so we use the logColor since that is based @@ -78,9 +75,7 @@ const errorMessage = (er, npm) => { npm.config.loaded && er.dest.startsWith(npm.config.get('cache')) - const { isWindows } = require('./is-windows.js') - - if (!isWindows && (isCachePath || isCacheDest)) { + if (process.platform !== 'win32' && (isCachePath || isCacheDest)) { // user probably doesn't need this, but still add it to the debug log log.verbose(er.stack) short.push([ @@ -102,7 +97,7 @@ const errorMessage = (er, npm) => { '', [ '\nThe operation was rejected by your operating system.', - isWindows + process.platform === 'win32' /* eslint-disable-next-line max-len */ ? "It's possible that the file was already in use (by a text editor or antivirus),\n" + 'or that you lack permissions to access it.' @@ -215,6 +210,7 @@ const errorMessage = (er, npm) => { detail.push(['404', '']) detail.push(['404', '', `'${replaceInfo(er.pkgid)}' is not in this registry.`]) + const nameValidator = require('validate-npm-package-name') const valResult = nameValidator(pkg) if (!valResult.validForNewPackages) { diff --git a/deps/npm/lib/utils/explain-dep.js b/deps/npm/lib/utils/explain-dep.js index 86660d5d3ad4b0..4e9e93454e8a28 100644 --- a/deps/npm/lib/utils/explain-dep.js +++ b/deps/npm/lib/utils/explain-dep.js @@ -1,4 +1,4 @@ -const { relative } = require('path') +const { relative } = require('node:path') const explainNode = (node, depth, chalk) => printNode(node, chalk) + @@ -6,63 +6,32 @@ const explainNode = (node, depth, chalk) => explainLinksIn(node, depth, chalk) const colorType = (type, chalk) => { - const { red, yellow, cyan, magenta, blue, green, gray } = chalk - const style = type === 'extraneous' ? red - : type === 'dev' ? yellow - : type === 'optional' ? cyan - : type === 'peer' ? magenta - : type === 'bundled' ? blue - : type === 'workspace' ? green - : type === 'overridden' ? gray + const style = type === 'extraneous' ? chalk.red + : type === 'dev' ? chalk.blue + : type === 'optional' ? chalk.magenta + : type === 'peer' ? chalk.magentaBright + : type === 'bundled' ? chalk.underline.cyan + : type === 'workspace' ? chalk.blueBright + : type === 'overridden' ? chalk.dim : /* istanbul ignore next */ s => s return style(type) } const printNode = (node, chalk) => { - const { - name, - version, - location, - extraneous, - dev, - optional, - peer, - bundled, - isWorkspace, - overridden, - } = node - const { bold, dim, green } = chalk const extra = [] - if (extraneous) { - extra.push(' ' + bold(colorType('extraneous', chalk))) - } - - if (dev) { - extra.push(' ' + bold(colorType('dev', chalk))) - } - if (optional) { - extra.push(' ' + bold(colorType('optional', chalk))) - } - - if (peer) { - extra.push(' ' + bold(colorType('peer', chalk))) - } - - if (bundled) { - extra.push(' ' + bold(colorType('bundled', chalk))) - } - - if (overridden) { - extra.push(' ' + bold(colorType('overridden', chalk))) + for (const meta of ['extraneous', 'dev', 'optional', 'peer', 'bundled', 'overridden']) { + if (node[meta]) { + extra.push(` ${colorType(meta, chalk)}`) + } } - const pkgid = isWorkspace - ? green(`${name}@${version}`) - : `${bold(name)}@${bold(version)}` + const pkgid = node.isWorkspace + ? chalk.blueBright(`${node.name}@${node.version}`) + : `${node.name}@${node.version}` return `${pkgid}${extra.join('')}` + - (location ? dim(`\n${location}`) : '') + (node.location ? chalk.dim(`\n${node.location}`) : '') } const explainLinksIn = ({ linksIn }, depth, chalk) => { @@ -75,7 +44,7 @@ const explainLinksIn = ({ linksIn }, depth, chalk) => { return str.split('\n').join('\n ') } -const explainDependents = ({ name, dependents }, depth, chalk) => { +const explainDependents = ({ dependents }, depth, chalk) => { if (!dependents || !dependents.length || depth <= 0) { return '' } @@ -107,10 +76,9 @@ const explainDependents = ({ name, dependents }, depth, chalk) => { } const explainEdge = ({ name, type, bundled, from, spec, rawSpec, overridden }, depth, chalk) => { - const { bold } = chalk let dep = type === 'workspace' - ? bold(relative(from.location, spec.slice('file:'.length))) - : `${bold(name)}@"${bold(spec)}"` + ? chalk.bold(relative(from.location, spec.slice('file:'.length))) + : `${name}@"${spec}"` if (overridden) { dep = `${colorType('overridden', chalk)} ${dep} (was "${rawSpec}")` } diff --git a/deps/npm/lib/utils/format-search-stream.js b/deps/npm/lib/utils/format-search-stream.js index 046a4b1e20587b..b70bd915123da4 100644 --- a/deps/npm/lib/utils/format-search-stream.js +++ b/deps/npm/lib/utils/format-search-stream.js @@ -1,6 +1,6 @@ -const { stripVTControlCharacters } = require('node:util') +/* eslint-disable max-len */ +const { stripVTControlCharacters: strip } = require('node:util') const { Minipass } = require('minipass') -const columnify = require('columnify') // This module consumes package data in the following format: // @@ -16,14 +16,48 @@ const columnify = require('columnify') // The returned stream will format this package data // into a byte stream of formatted, displayable output. -module.exports = async (opts) => { - return opts.json ? new JSONOutputStream() : new TextOutputStream(opts) +function filter (data, exclude) { + const words = [data.name] + .concat(data.maintainers.map(m => m.username)) + .concat(data.keywords || []) + .map(f => f?.trim?.()) + .filter(Boolean) + .join(' ') + .toLowerCase() + + if (exclude.find(pattern => { + // Treats both /foo and /foo/ as regex searches + if (pattern.startsWith('/')) { + if (pattern.endsWith('/')) { + pattern = pattern.slice(0, -1) + } + return words.match(new RegExp(pattern.slice(1))) + } + return words.includes(pattern) + })) { + return false + } + + return true +} + +module.exports = (opts) => { + return opts.json ? new JSONOutputStream(opts) : new TextOutputStream(opts) } class JSONOutputStream extends Minipass { #didFirst = false + #exclude + + constructor (opts) { + super() + this.#exclude = opts.exclude + } write (obj) { + if (!filter(obj, this.#exclude)) { + return + } if (!this.#didFirst) { super.write('[\n') this.#didFirst = true @@ -41,94 +75,100 @@ class JSONOutputStream extends Minipass { } class TextOutputStream extends Minipass { - #opts - #line = 0 + #args + #chalk + #exclude + #parseable constructor (opts) { super() - this.#opts = opts + this.#args = opts.args.map(s => s.toLowerCase()).filter(Boolean) + this.#chalk = opts.npm.chalk + this.#exclude = opts.exclude + this.#parseable = opts.parseable } - write (pkg) { - return super.write(this.#prettify(pkg)) - } - - #prettify (data) { + write (data) { + if (!filter(data, this.#exclude)) { + return + } + // Normalize const pkg = { - author: data.maintainers.map((m) => `=${stripVTControlCharacters(m.username)}`).join(' '), - date: 'prehistoric', - description: stripVTControlCharacters(data.description ?? ''), - keywords: '', - name: stripVTControlCharacters(data.name), + authors: data.maintainers.map((m) => `${strip(m.username)}`).join(' '), + publisher: strip(data.publisher?.username || ''), + date: data.date ? data.date.toISOString().slice(0, 10) : 'prehistoric', + description: strip(data.description ?? ''), + keywords: [], + name: strip(data.name), version: data.version, } if (Array.isArray(data.keywords)) { - pkg.keywords = data.keywords.map((k) => stripVTControlCharacters(k)).join(' ') + pkg.keywords = data.keywords.map(strip) } else if (typeof data.keywords === 'string') { - pkg.keywords = stripVTControlCharacters(data.keywords.replace(/[,\s]+/, ' ')) - } - if (data.date) { - pkg.date = data.date.toISOString().split('T')[0] // remove time + pkg.keywords = strip(data.keywords.replace(/[,\s]+/, ' ')).split(' ') } - const columns = ['name', 'description', 'author', 'date', 'version', 'keywords'] - if (this.#opts.parseable) { - return columns.map((col) => pkg[col] && ('' + pkg[col]).replace(/\t/g, ' ')).join('\t') + let output + if (this.#parseable) { + output = [pkg.name, pkg.description, pkg.author, pkg.date, pkg.version, pkg.keywords] + .filter(Boolean) + .map(col => ('' + col).replace(/\t/g, ' ')).join('\t') + return super.write(output) } - // stdout in tap is never a tty - /* istanbul ignore next */ - const maxWidth = process.stdout.isTTY ? process.stdout.getWindowSize()[0] : Infinity - let output = columnify( - [pkg], - { - include: columns, - showHeaders: ++this.#line <= 1, - columnSplitter: ' | ', - truncate: !this.#opts.long, - config: { - name: { minWidth: 25, maxWidth: 25, truncate: false, truncateMarker: '' }, - description: { minWidth: 20, maxWidth: 20 }, - author: { minWidth: 15, maxWidth: 15 }, - date: { maxWidth: 11 }, - version: { minWidth: 8, maxWidth: 8 }, - keywords: { maxWidth: Infinity }, - }, + const keywords = pkg.keywords.map(k => { + if (this.#args.includes(k)) { + return this.#chalk.cyan(k) + } else { + return k + } + }).join(' ') + + let description = [] + for (const arg of this.#args) { + const finder = pkg.description.toLowerCase().split(arg.toLowerCase()) + let p = 0 + for (const f of finder) { + description.push(pkg.description.slice(p, p + f.length)) + const word = pkg.description.slice(p + f.length, p + f.length + arg.length) + description.push(this.#chalk.cyan(word)) + p += f.length + arg.length } - ).split('\n').map(line => line.slice(0, maxWidth)).join('\n') - - if (!this.#opts.color) { - return output } - - const colors = ['31m', '33m', '32m', '36m', '34m', '35m'] - - this.#opts.args.forEach((arg, i) => { - const markStart = String.fromCharCode(i % colors.length + 1) - const markEnd = String.fromCharCode(0) - - if (arg.charAt(0) === '/') { - output = output.replace( - new RegExp(arg.slice(1, -1), 'gi'), - bit => `${markStart}${bit}${markEnd}` - ) - } else { - // just a normal string, do the split/map thing + description = description.filter(Boolean) + let name = pkg.name + if (this.#args.includes(pkg.name)) { + name = this.#chalk.cyan(pkg.name) + } else { + name = [] + for (const arg of this.#args) { + const finder = pkg.name.toLowerCase().split(arg.toLowerCase()) let p = 0 - - output = output.toLowerCase().split(arg.toLowerCase()).map(piece => { - piece = output.slice(p, p + piece.length) - p += piece.length - const mark = `${markStart}${output.slice(p, p + arg.length)}${markEnd}` - p += arg.length - return `${piece}${mark}` - }).join('') + for (const f of finder) { + name.push(pkg.name.slice(p, p + f.length)) + const word = pkg.name.slice(p + f.length, p + f.length + arg.length) + name.push(this.#chalk.cyan(word)) + p += f.length + arg.length + } } - }) + name = this.#chalk.blue(name.join('')) + } - for (let i = 1; i <= colors.length; i++) { - output = output.split(String.fromCharCode(i)).join(`\u001B[${colors[i - 1]}`) + if (description.length) { + output = `${name}\n${description.join('')}\n` + } else { + output = `${name}\n` + } + if (pkg.publisher) { + output += `Version ${this.#chalk.blue(pkg.version)} published ${this.#chalk.blue(pkg.date)} by ${this.#chalk.blue(pkg.publisher)}\n` + } else { + output += `Version ${this.#chalk.blue(pkg.version)} published ${this.#chalk.blue(pkg.date)} by ${this.#chalk.yellow('???')}\n` + } + output += `Maintainers: ${pkg.authors}\n` + if (keywords) { + output += `Keywords: ${keywords}\n` } - return output.split('\u0000').join('\u001B[0m').trim() + output += `${this.#chalk.blue(`https://npm.im/${pkg.name}`)}\n` + return super.write(output) } } diff --git a/deps/npm/lib/utils/format.js b/deps/npm/lib/utils/format.js new file mode 100644 index 00000000000000..abfbf9e3317043 --- /dev/null +++ b/deps/npm/lib/utils/format.js @@ -0,0 +1,50 @@ +const { formatWithOptions: baseFormatWithOptions } = require('util') + +// These are most assuredly not a mistake +// https://eslint.org/docs/latest/rules/no-control-regex +// \x00 through \x1f, \x7f through \x9f, not including \x09 \x0a \x0b \x0d +/* eslint-disable-next-line no-control-regex */ +const HAS_C01 = /[\x00-\x08\x0c\x0e-\x1f\x7f-\x9f]/ + +// Allows everything up to '[38;5;255m' in 8 bit notation +const ALLOWED_SGR = /^\[[0-9;]{0,8}m/ + +// '[38;5;255m'.length +const SGR_MAX_LEN = 10 + +// Strips all ANSI C0 and C1 control characters (except for SGR up to 8 bit) +function STRIP_C01 (str) { + if (!HAS_C01.test(str)) { + return str + } + let result = '' + for (let i = 0; i < str.length; i++) { + const char = str[i] + const code = char.charCodeAt(0) + if (!HAS_C01.test(char)) { + // Most characters are in this set so continue early if we can + result = `${result}${char}` + } else if (code === 27 && ALLOWED_SGR.test(str.slice(i + 1, i + SGR_MAX_LEN + 1))) { + // \x1b with allowed SGR + result = `${result}\x1b` + } else if (code <= 31) { + // escape all other C0 control characters besides \x7f + result = `${result}^${String.fromCharCode(code + 64)}` + } else { + // hasC01 ensures this is now a C1 control character or \x7f + result = `${result}^${String.fromCharCode(code - 64)}` + } + } + return result +} + +const formatWithOptions = ({ prefix: prefixes = [], eol = '\n', ...options }, ...args) => { + const prefix = prefixes.filter(p => p != null).join(' ') + const formatted = STRIP_C01(baseFormatWithOptions(options, ...args)) + // Splitting could be changed to only `\n` once we are sure we only emit unix newlines. + // The eol param to this function will put the correct newlines in place for the returned string. + const lines = formatted.split(/\r?\n/) + return lines.reduce((acc, l) => `${acc}${prefix}${prefix && l ? ' ' : ''}${l}${eol}`, '') +} + +module.exports = { formatWithOptions } diff --git a/deps/npm/lib/workspaces/get-workspaces.js b/deps/npm/lib/utils/get-workspaces.js similarity index 100% rename from deps/npm/lib/workspaces/get-workspaces.js rename to deps/npm/lib/utils/get-workspaces.js diff --git a/deps/npm/lib/utils/completion/installed-deep.js b/deps/npm/lib/utils/installed-deep.js similarity index 100% rename from deps/npm/lib/utils/completion/installed-deep.js rename to deps/npm/lib/utils/installed-deep.js diff --git a/deps/npm/lib/utils/completion/installed-shallow.js b/deps/npm/lib/utils/installed-shallow.js similarity index 100% rename from deps/npm/lib/utils/completion/installed-shallow.js rename to deps/npm/lib/utils/installed-shallow.js diff --git a/deps/npm/lib/utils/is-windows.js b/deps/npm/lib/utils/is-windows.js index 57f6599b6ae192..63c5671d8400ee 100644 --- a/deps/npm/lib/utils/is-windows.js +++ b/deps/npm/lib/utils/is-windows.js @@ -1,6 +1,4 @@ -const isWindows = process.platform === 'win32' -const isWindowsShell = isWindows && +const isWindowsShell = (process.platform === 'win32') && !/^MINGW(32|64)$/.test(process.env.MSYSTEM) && process.env.TERM !== 'cygwin' -exports.isWindows = isWindows exports.isWindowsShell = isWindowsShell diff --git a/deps/npm/lib/utils/log-file.js b/deps/npm/lib/utils/log-file.js index 8c06f5647e761e..09e3873f2dce6c 100644 --- a/deps/npm/lib/utils/log-file.js +++ b/deps/npm/lib/utils/log-file.js @@ -1,20 +1,16 @@ const os = require('os') const { join, dirname, basename } = require('path') -const { format } = require('util') -const { glob } = require('glob') -const { Minipass } = require('minipass') const fsMiniPass = require('fs-minipass') const fs = require('fs/promises') -const log = require('./log-shim') -const Display = require('./display') +const { log } = require('proc-log') +const { formatWithOptions } = require('./format') const padZero = (n, length) => n.toString().padStart(length.toString().length, '0') -const globify = pattern => pattern.split('\\').join('/') class LogFiles { - // Default to a plain minipass stream so we can buffer + // Default to an array so we can buffer // initial writes before we know the cache location - #logStream = null + #logStream = [] // We cap log files at a certain number of log events per file. // Note that each log event can write more than one line to the @@ -32,6 +28,7 @@ class LogFiles { #path = null #logsMax = null #files = [] + #timing = false constructor ({ maxLogsPerFile = 50_000, @@ -42,23 +39,7 @@ class LogFiles { this.on() } - static format (count, level, title, ...args) { - let prefix = `${count} ${level}` - if (title) { - prefix += ` ${title}` - } - - return format(...args) - .split(/\r?\n/) - .map(Display.clean) - .reduce((lines, line) => - lines += prefix + (line ? ' ' : '') + line + os.EOL, - '' - ) - } - on () { - this.#logStream = new Minipass() process.on('log', this.#logHandler) } @@ -67,11 +48,12 @@ class LogFiles { this.#endStream() } - load ({ path, logsMax = Infinity } = {}) { + load ({ path, logsMax = Infinity, timing } = {}) { // dir is user configurable and is required to exist so // this can error if the dir is missing or not configured correctly this.#path = path this.#logsMax = logsMax + this.#timing = timing // Log stream has already ended if (!this.#logStream) { @@ -80,36 +62,40 @@ class LogFiles { log.verbose('logfile', `logs-max:${logsMax} dir:${this.#path}`) - // Pipe our initial stream to our new file stream and + // Write the contents of our array buffer to our new file stream and // set that as the new log logstream for future writes // if logs max is 0 then the user does not want a log file if (this.#logsMax > 0) { const initialFile = this.#openLogFile() if (initialFile) { - this.#logStream = this.#logStream.pipe(initialFile) + for (const item of this.#logStream) { + const formatted = this.#formatLogItem(...item) + if (formatted !== null) { + initialFile.write(formatted) + } + } + this.#logStream = initialFile } } + log.verbose('logfile', this.files[0] || 'no logfile created') + // Kickoff cleaning process, even if we aren't writing a logfile. // This is async but it will always ignore the current logfile // Return the result so it can be awaited in tests return this.#cleanLogs() } - log (...args) { - this.#logHandler(...args) - } - get files () { return this.#files } get #isBuffered () { - return this.#logStream instanceof Minipass + return Array.isArray(this.#logStream) } #endStream (output) { - if (this.#logStream) { + if (this.#logStream && !this.#isBuffered) { this.#logStream.end(output) this.#logStream = null } @@ -127,12 +113,15 @@ class LogFiles { return } - const logOutput = this.#formatLogItem(level, ...args) - if (this.#isBuffered) { // Cant do anything but buffer the output if we dont // have a file stream yet - this.#logStream.write(logOutput) + this.#logStream.push([level, ...args]) + return + } + + const logOutput = this.#formatLogItem(level, ...args) + if (logOutput === null) { return } @@ -152,9 +141,15 @@ class LogFiles { } } - #formatLogItem (...args) { + #formatLogItem (level, title, ...args) { + // Only right timing logs to logfile if explicitly requests + if (level === log.KEYS.timing && !this.#timing) { + return null + } + this.#fileLogCount += 1 - return LogFiles.format(this.#totalLogCount++, ...args) + const prefix = [this.#totalLogCount++, level, title || null] + return formatWithOptions({ prefix, eol: os.EOL, colors: false }, ...args) } #getLogFilePath (count = '') { @@ -199,17 +194,41 @@ class LogFiles { try { const logPath = this.#getLogFilePath() - const logGlob = join(dirname(logPath), basename(logPath) + const patternFileName = basename(logPath) // tell glob to only match digits - .replace(/\d/g, '[0123456789]') + .replace(/\d/g, 'd') // Handle the old (prior to 8.2.0) log file names which did not have a // counter suffix - .replace(/-\.log$/, '*.log') - ) + .replace('-.log', '') + + let files = await fs.readdir( + dirname(logPath), { + withFileTypes: true, + encoding: 'utf-8', + }) + files = files.sort((a, b) => basename(a.name).localeCompare(basename(b.name), 'en')) + + const logFiles = [] + + for (const file of files) { + if (!file.isFile()) { + continue + } + + const genericFileName = file.name.replace(/\d/g, 'd') + const filePath = join(dirname(logPath), basename(file.name)) + + // Always ignore the currently written files + if ( + genericFileName.includes(patternFileName) + && genericFileName.endsWith('.log') + && !this.#files.includes(filePath) + ) { + logFiles.push(filePath) + } + } - // Always ignore the currently written files - const files = await glob(globify(logGlob), { ignore: this.#files.map(globify), silent: true }) - const toDelete = files.length - this.#logsMax + const toDelete = logFiles.length - this.#logsMax if (toDelete <= 0) { return @@ -217,7 +236,7 @@ class LogFiles { log.silly('logfile', `start cleaning logs, removing ${toDelete} files`) - for (const file of files.slice(0, toDelete)) { + for (const file of logFiles.slice(0, toDelete)) { try { await fs.rm(file, { force: true }) } catch (e) { @@ -227,7 +246,7 @@ class LogFiles { } catch (e) { // Disable cleanup failure warnings when log writing is disabled if (this.#logsMax > 0) { - log.warn('logfile', 'error cleaning log files', e) + log.verbose('logfile', 'error cleaning log files', e) } } finally { log.silly('logfile', 'done cleaning log files') diff --git a/deps/npm/lib/utils/log-shim.js b/deps/npm/lib/utils/log-shim.js deleted file mode 100644 index 9d5a36d967413f..00000000000000 --- a/deps/npm/lib/utils/log-shim.js +++ /dev/null @@ -1,59 +0,0 @@ -const NPMLOG = require('npmlog') -const PROCLOG = require('proc-log') - -// Sets getter and optionally a setter -// otherwise setting should throw -const accessors = (obj, set) => (k) => ({ - get: () => obj[k], - set: set ? (v) => (obj[k] = v) : () => { - throw new Error(`Cant set ${k}`) - }, -}) - -// Set the value to a bound function on the object -const value = (obj) => (k) => ({ - value: (...args) => obj[k].apply(obj, args), -}) - -const properties = { - // npmlog getters/setters - level: accessors(NPMLOG, true), - heading: accessors(NPMLOG, true), - levels: accessors(NPMLOG), - gauge: accessors(NPMLOG), - stream: accessors(NPMLOG), - tracker: accessors(NPMLOG), - progressEnabled: accessors(NPMLOG), - // npmlog methods - useColor: value(NPMLOG), - enableColor: value(NPMLOG), - disableColor: value(NPMLOG), - enableUnicode: value(NPMLOG), - disableUnicode: value(NPMLOG), - enableProgress: value(NPMLOG), - disableProgress: value(NPMLOG), - clearProgress: value(NPMLOG), - showProgress: value(NPMLOG), - newItem: value(NPMLOG), - newGroup: value(NPMLOG), - // proclog methods - notice: value(PROCLOG), - error: value(PROCLOG), - warn: value(PROCLOG), - info: value(PROCLOG), - verbose: value(PROCLOG), - http: value(PROCLOG), - silly: value(PROCLOG), - pause: value(PROCLOG), - resume: value(PROCLOG), -} - -const descriptors = Object.entries(properties).reduce((acc, [k, v]) => { - acc[k] = { enumerable: true, ...v(k) } - return acc -}, {}) - -// Create an object with the allowed properties rom npm log and all -// the logging methods from proc log -// XXX: this should go away and requires of this should be replaced with proc-log + new display -module.exports = Object.freeze(Object.defineProperties({}, descriptors)) diff --git a/deps/npm/lib/utils/open-url-prompt.js b/deps/npm/lib/utils/open-url-prompt.js index 71a68c253c0505..6f4d453a959d59 100644 --- a/deps/npm/lib/utils/open-url-prompt.js +++ b/deps/npm/lib/utils/open-url-prompt.js @@ -1,4 +1,5 @@ const readline = require('readline') +const { input, output } = require('proc-log') const open = require('./open-url.js') function print (npm, title, url) { @@ -6,7 +7,7 @@ function print (npm, title, url) { const message = json ? JSON.stringify({ title, url }) : `${title}:\n${url}` - npm.output(message) + output.standard(message) } // Prompt to open URL in browser if possible @@ -33,7 +34,7 @@ const promptOpen = async (npm, url, title, prompt, emitter) => { output: process.stdout, }) - const tryOpen = await new Promise(resolve => { + const tryOpen = await input.read(() => new Promise(resolve => { rl.on('SIGINT', () => { rl.close() resolve('SIGINT') @@ -46,14 +47,10 @@ const promptOpen = async (npm, url, title, prompt, emitter) => { if (emitter && emitter.addListener) { emitter.addListener('abort', () => { rl.close() - - // clear the prompt line - npm.output('') - resolve(false) }) } - }) + })) if (tryOpen === 'SIGINT') { throw new Error('canceled') diff --git a/deps/npm/lib/utils/open-url.js b/deps/npm/lib/utils/open-url.js index 77bb1d03d8e165..46b7abc731fa1d 100644 --- a/deps/npm/lib/utils/open-url.js +++ b/deps/npm/lib/utils/open-url.js @@ -1,4 +1,5 @@ const promiseSpawn = require('@npmcli/promise-spawn') +const { output } = require('proc-log') const { URL } = require('url') @@ -16,7 +17,7 @@ const open = async (npm, url, errMsg, isFile) => { }, null, 2) : `${errMsg}:\n ${url}\n` - npm.output(alternateMsg) + output.standard(alternateMsg) } if (browser === false) { diff --git a/deps/npm/lib/utils/otplease.js b/deps/npm/lib/utils/otplease.js index b4aa1674692551..b8dd0b66ed7664 100644 --- a/deps/npm/lib/utils/otplease.js +++ b/deps/npm/lib/utils/otplease.js @@ -1,4 +1,3 @@ -const log = require('./log-shim') async function otplease (npm, opts, fn) { try { return await fn(opts) @@ -8,7 +7,6 @@ async function otplease (npm, opts, fn) { } if (isWebOTP(err)) { - log.disableProgress() const webAuth = require('./web-auth') const openUrlPrompt = require('./open-url-prompt') diff --git a/deps/npm/lib/utils/pulse-till-done.js b/deps/npm/lib/utils/pulse-till-done.js deleted file mode 100644 index 22294141474839..00000000000000 --- a/deps/npm/lib/utils/pulse-till-done.js +++ /dev/null @@ -1,26 +0,0 @@ -const log = require('./log-shim.js') - -let pulseTimer = null -const withPromise = async (promise) => { - pulseStart() - try { - return await promise - } finally { - pulseStop() - } -} - -const pulseStart = () => { - pulseTimer = pulseTimer || setInterval(() => { - log.gauge.pulse('') - }, 150) -} - -const pulseStop = () => { - clearInterval(pulseTimer) - pulseTimer = null -} - -module.exports = { - withPromise, -} diff --git a/deps/npm/lib/utils/read-user-info.js b/deps/npm/lib/utils/read-user-info.js index 1cac8ee6d2668b..4e8def4bdf1def 100644 --- a/deps/npm/lib/utils/read-user-info.js +++ b/deps/npm/lib/utils/read-user-info.js @@ -1,6 +1,6 @@ -const read = require('read') +const { read: _read } = require('read') const userValidate = require('npm-user-validate') -const log = require('./log-shim.js') +const { log, input } = require('proc-log') exports.otp = readOTP exports.password = readPassword @@ -16,17 +16,14 @@ const passwordPrompt = 'npm password: ' const usernamePrompt = 'npm username: ' const emailPrompt = 'email (this IS public): ' -function readWithProgress (opts) { - log.clearProgress() - return read(opts).finally(() => log.showProgress()) -} +const read = (...args) => input.read(() => _read(...args)) function readOTP (msg = otpPrompt, otp, isRetry) { if (isRetry && otp && /^[\d ]+$|^[A-Fa-f0-9]{64,64}$/.test(otp)) { return otp.replace(/\s+/g, '') } - return readWithProgress({ prompt: msg, default: otp || '' }) + return read({ prompt: msg, default: otp || '' }) .then((rOtp) => readOTP(msg, rOtp, true)) } @@ -35,7 +32,7 @@ function readPassword (msg = passwordPrompt, password, isRetry) { return password } - return readWithProgress({ prompt: msg, silent: true, default: password || '' }) + return read({ prompt: msg, silent: true, default: password || '' }) .then((rPassword) => readPassword(msg, rPassword, true)) } @@ -49,7 +46,7 @@ function readUsername (msg = usernamePrompt, username, isRetry) { } } - return readWithProgress({ prompt: msg, default: username || '' }) + return read({ prompt: msg, default: username || '' }) .then((rUsername) => readUsername(msg, rUsername, true)) } @@ -63,6 +60,6 @@ function readEmail (msg = emailPrompt, email, isRetry) { } } - return readWithProgress({ prompt: msg, default: email || '' }) + return read({ prompt: msg, default: email || '' }) .then((username) => readEmail(msg, username, true)) } diff --git a/deps/npm/lib/utils/reify-finish.js b/deps/npm/lib/utils/reify-finish.js index 9b43abcb7610a1..0b34a375768606 100644 --- a/deps/npm/lib/utils/reify-finish.js +++ b/deps/npm/lib/utils/reify-finish.js @@ -1,6 +1,6 @@ const reifyOutput = require('./reify-output.js') const ini = require('ini') -const { writeFile } = require('fs').promises +const { writeFile } = require('fs/promises') const { resolve } = require('path') const reifyFinish = async (npm, arb) => { diff --git a/deps/npm/lib/utils/reify-output.js b/deps/npm/lib/utils/reify-output.js index 44c913812a8efe..a858a546c4010c 100644 --- a/deps/npm/lib/utils/reify-output.js +++ b/deps/npm/lib/utils/reify-output.js @@ -9,13 +9,12 @@ // found 37 vulnerabilities (5 low, 7 moderate, 25 high) // run `npm audit fix` to fix them, or `npm audit` for details -const log = require('./log-shim.js') +const { log, output } = require('proc-log') const { depth } = require('treeverse') const ms = require('ms') const npmAuditReport = require('npm-audit-report') const { readTree: getFundingInfo } = require('libnpmfund') const auditError = require('./audit-error.js') -const Table = require('cli-table3') // TODO: output JSON if flatOptions.json is true const reifyOutput = (npm, arb) => { @@ -42,51 +41,31 @@ const reifyOutput = (npm, arb) => { } if (diff) { - let diffTable - if (npm.config.get('dry-run') || npm.config.get('long')) { - diffTable = new Table({ - chars: { - top: '', - 'top-mid': '', - 'top-left': '', - 'top-right': '', - bottom: '', - 'bottom-mid': '', - 'bottom-left': '', - 'bottom-right': '', - left: '', - 'left-mid': '', - mid: '', - 'mid-mid': '', - right: '', - 'right-mid': '', - middle: ' ', - }, - style: { - 'padding-left': 0, - 'padding-right': 0, - border: 0, - }, - }) - } + const showDiff = npm.config.get('dry-run') || npm.config.get('long') + const chalk = npm.chalk depth({ tree: diff, visit: d => { switch (d.action) { case 'REMOVE': - diffTable?.push(['remove', d.actual.name, d.actual.package.version]) + if (showDiff) { + /* eslint-disable-next-line max-len */ + output.standard(`${chalk.blue('remove')} ${d.actual.name} ${d.actual.package.version}`) + } summary.removed++ break case 'ADD': - diffTable?.push(['add', d.ideal.name, d.ideal.package.version]) + if (showDiff) { + output.standard(`${chalk.green('add')} ${d.ideal.name} ${d.ideal.package.version}`) + } actualTree.inventory.has(d.ideal) && summary.added++ break case 'CHANGE': - diffTable?.push(['change', - d.actual.name, - d.actual.package.version + ' -> ' + d.ideal.package.version, - ]) + if (showDiff) { + /* eslint-disable-next-line max-len */ + output.standard(`${chalk.cyan('change')} ${d.actual.name} ${d.actual.package.version} => ${d.ideal.package.version}`) + } summary.changed++ break default: @@ -97,10 +76,6 @@ const reifyOutput = (npm, arb) => { }, getChildren: d => d.children, }) - - if (diffTable) { - npm.output('\n' + diffTable.toString()) - } } if (npm.flatOptions.fund) { @@ -115,7 +90,7 @@ const reifyOutput = (npm, arb) => { summary.audit = npm.command === 'audit' ? auditReport : auditReport.toJSON().metadata } - npm.output(JSON.stringify(summary, null, 2)) + output.standard(JSON.stringify(summary, null, 2)) } else { packagesChangedMessage(npm, summary) packagesFundingMessage(npm, summary) @@ -134,7 +109,7 @@ const printAuditReport = (npm, report) => { if (!res || !res.report) { return } - npm.output(`\n${res.report}`) + output.standard(`\n${res.report}`) } const getAuditReport = (npm, report) => { @@ -206,7 +181,7 @@ const packagesChangedMessage = (npm, { added, removed, changed, audited }) => { } msg.push(` in ${ms(Date.now() - npm.started)}`) - npm.output(msg.join('')) + output.standard(msg.join('')) } const packagesFundingMessage = (npm, { funding }) => { @@ -214,11 +189,11 @@ const packagesFundingMessage = (npm, { funding }) => { return } - npm.output('') + output.standard('') const pkg = funding === 1 ? 'package' : 'packages' const is = funding === 1 ? 'is' : 'are' - npm.output(`${funding} ${pkg} ${is} looking for funding`) - npm.output(' run `npm fund` for details') + output.standard(`${funding} ${pkg} ${is} looking for funding`) + output.standard(' run `npm fund` for details') } module.exports = reifyOutput diff --git a/deps/npm/lib/utils/replace-info.js b/deps/npm/lib/utils/replace-info.js deleted file mode 100644 index b9ce61935ffb76..00000000000000 --- a/deps/npm/lib/utils/replace-info.js +++ /dev/null @@ -1,31 +0,0 @@ -const { cleanUrl } = require('npm-registry-fetch') -const isString = (v) => typeof v === 'string' - -// split on \s|= similar to how nopt parses options -const splitAndReplace = (str) => { - // stateful regex, don't move out of this scope - const splitChars = /[\s=]/g - - let match = null - let result = '' - let index = 0 - while (match = splitChars.exec(str)) { - result += cleanUrl(str.slice(index, match.index)) + match[0] - index = splitChars.lastIndex - } - - return result + cleanUrl(str.slice(index)) -} - -// replaces auth info in an array of arguments or in a strings -function replaceInfo (arg) { - if (isString(arg)) { - return splitAndReplace(arg) - } else if (Array.isArray(arg)) { - return arg.map((a) => isString(a) ? splitAndReplace(a) : a) - } - - return arg -} - -module.exports = replaceInfo diff --git a/deps/npm/lib/utils/tar.js b/deps/npm/lib/utils/tar.js index c25fe71614a60b..9085d9dd350165 100644 --- a/deps/npm/lib/utils/tar.js +++ b/deps/npm/lib/utils/tar.js @@ -1,8 +1,7 @@ const tar = require('tar') const ssri = require('ssri') -const log = require('./log-shim') +const { log } = require('proc-log') const formatBytes = require('./format-bytes.js') -const columnify = require('columnify') const localeCompare = require('@isaacs/string-locale-compare')('en', { sensitivity: 'case', numeric: true, @@ -12,60 +11,36 @@ const logTar = (tarball, opts = {}) => { const { unicode = false } = opts log.notice('') log.notice('', `${unicode ? '📦 ' : 'package:'} ${tarball.name}@${tarball.version}`) - log.notice('=== Tarball Contents ===') + log.notice('Tarball Contents') if (tarball.files.length) { log.notice( '', - columnify( - tarball.files - .map(f => { - const bytes = formatBytes(f.size, false) - return /^node_modules\//.test(f.path) ? null : { path: f.path, size: `${bytes}` } - }) - .filter(f => f), - { - include: ['size', 'path'], - showHeaders: false, - } - ) + tarball.files.map(f => + /^node_modules\//.test(f.path) ? null : `${formatBytes(f.size, false)} ${f.path}` + ).filter(f => f).join('\n') ) } if (tarball.bundled.length) { - log.notice('=== Bundled Dependencies ===') + log.notice('Bundled Dependencies') tarball.bundled.forEach(name => log.notice('', name)) } - log.notice('=== Tarball Details ===') - log.notice( - '', - columnify( - [ - { name: 'name:', value: tarball.name }, - { name: 'version:', value: tarball.version }, - tarball.filename && { name: 'filename:', value: tarball.filename }, - { name: 'package size:', value: formatBytes(tarball.size) }, - { name: 'unpacked size:', value: formatBytes(tarball.unpackedSize) }, - { name: 'shasum:', value: tarball.shasum }, - { - name: 'integrity:', - value: - tarball.integrity.toString().slice(0, 20) + - '[...]' + - tarball.integrity.toString().slice(80), - }, - tarball.bundled.length && { name: 'bundled deps:', value: tarball.bundled.length }, - tarball.bundled.length && { - name: 'bundled files:', - value: tarball.entryCount - tarball.files.length, - }, - tarball.bundled.length && { name: 'own files:', value: tarball.files.length }, - { name: 'total files:', value: tarball.entryCount }, - ].filter(x => x), - { - include: ['name', 'value'], - showHeaders: false, - } - ) - ) + log.notice('Tarball Details') + log.notice('', `name: ${tarball.name}`) + log.notice('', `version: ${tarball.version}`) + if (tarball.filename) { + log.notice('', `filename: ${tarball.filename}`) + } + log.notice('', `package size: ${formatBytes(tarball.size)}`) + log.notice('', `unpacked size: ${formatBytes(tarball.unpackedSize)}`) + log.notice('', `shasum: ${tarball.shasum}`) + /* eslint-disable-next-line max-len */ + log.notice('', `integrity: ${tarball.integrity.toString().slice(0, 20)}[...]${tarball.integrity.toString().slice(80)}`) + if (tarball.bundled.length) { + log.notice('', `bundled deps: ${tarball.bundled.length}`) + log.notice('', `bundled files: ${tarball.entryCount - tarball.files.length}`) + log.notice('', `own files: ${tarball.files.length}`) + } + log.notice('', `total files: ${tarball.entryCount}`) log.notice('', '') } diff --git a/deps/npm/lib/utils/timers.js b/deps/npm/lib/utils/timers.js index c215fe926afb59..16a255961fee3b 100644 --- a/deps/npm/lib/utils/timers.js +++ b/deps/npm/lib/utils/timers.js @@ -1,114 +1,87 @@ -const EE = require('events') -const fs = require('fs') -const log = require('./log-shim') +const EE = require('node:events') +const fs = require('node:fs') +const { log, time } = require('proc-log') + +const INITIAL_TIMER = 'npm' -// This is an event emiiter but on/off -// only listen on a single internal event that gets -// emitted whenever a timer ends class Timers extends EE { - file = null + #file + #timing #unfinished = new Map() #finished = {} - #onTimeEnd = Symbol('onTimeEnd') - #initialListener = null - #initialTimer = null - constructor ({ listener = null, start = 'npm' } = {}) { + constructor () { super() - this.#initialListener = listener - this.#initialTimer = start - this.#init() - } - - get unfinished () { - return this.#unfinished - } - - get finished () { - return this.#finished - } - - #init () { this.on() - if (this.#initialListener) { - this.on(this.#initialListener) - } - process.emit('time', this.#initialTimer) - this.started = this.#unfinished.get(this.#initialTimer) + time.start(INITIAL_TIMER) + this.started = this.#unfinished.get(INITIAL_TIMER) } - on (listener) { - if (listener) { - super.on(this.#onTimeEnd, listener) - } else { - process.on('time', this.#timeListener) - process.on('timeEnd', this.#timeEndListener) - } + on () { + process.on('time', this.#timeHandler) } - off (listener) { - if (listener) { - super.off(this.#onTimeEnd, listener) - } else { - this.removeAllListeners(this.#onTimeEnd) - process.off('time', this.#timeListener) - process.off('timeEnd', this.#timeEndListener) - } + off () { + process.off('time', this.#timeHandler) } - time (name, fn) { - process.emit('time', name) - const end = () => process.emit('timeEnd', name) - if (typeof fn === 'function') { - const res = fn() - return res && res.finally ? res.finally(end) : (end(), res) - } - return end + load ({ path, timing } = {}) { + this.#timing = timing + this.#file = `${path}timing.json` } - load ({ path } = {}) { - if (path) { - this.file = `${path}timing.json` + finish (metadata) { + time.end(INITIAL_TIMER) + + for (const [name, timer] of this.#unfinished) { + log.silly('unfinished npm timer', name, timer) } - } - writeFile (metadata) { - if (!this.file) { + if (!this.#timing) { + // Not in timing mode, nothing else to do here return } try { - const globalStart = this.started - const globalEnd = this.#finished.npm || Date.now() - const content = { - metadata, - timers: this.#finished, - // add any unfinished timers with their relative start/end - unfinishedTimers: [...this.#unfinished.entries()].reduce((acc, [name, start]) => { - acc[name] = [start - globalStart, globalEnd - globalStart] - return acc - }, {}), - } - fs.writeFileSync(this.file, JSON.stringify(content) + '\n') + this.#writeFile(metadata) + log.info('timing', `Timing info written to: ${this.#file}`) } catch (e) { - this.file = null log.warn('timing', `could not write timing file: ${e}`) } } - #timeListener = (name) => { - this.#unfinished.set(name, Date.now()) + #writeFile (metadata) { + const globalStart = this.started + const globalEnd = this.#finished[INITIAL_TIMER] + const content = { + metadata, + timers: this.#finished, + // add any unfinished timers with their relative start/end + unfinishedTimers: [...this.#unfinished.entries()].reduce((acc, [name, start]) => { + acc[name] = [start - globalStart, globalEnd - globalStart] + return acc + }, {}), + } + fs.writeFileSync(this.#file, JSON.stringify(content) + '\n') } - #timeEndListener = (name) => { - if (this.#unfinished.has(name)) { - const ms = Date.now() - this.#unfinished.get(name) - this.#finished[name] = ms - this.#unfinished.delete(name) - this.emit(this.#onTimeEnd, name, ms) - } else { - log.silly('timing', "Tried to end timer that doesn't exist:", name) + #timeHandler = (level, name) => { + const now = Date.now() + switch (level) { + case time.KEYS.start: + this.#unfinished.set(name, now) + break + case time.KEYS.end: { + if (this.#unfinished.has(name)) { + const ms = now - this.#unfinished.get(name) + this.#finished[name] = ms + this.#unfinished.delete(name) + log.timing(name, `Completed in ${ms}ms`) + } else { + log.silly('timing', `Tried to end timer that doesn't exist: ${name}`) + } + } } } } diff --git a/deps/npm/lib/workspaces/update-workspaces.js b/deps/npm/lib/utils/update-workspaces.js similarity index 100% rename from deps/npm/lib/workspaces/update-workspaces.js rename to deps/npm/lib/utils/update-workspaces.js diff --git a/deps/npm/lib/utils/verify-signatures.js b/deps/npm/lib/utils/verify-signatures.js new file mode 100644 index 00000000000000..f2973316c9b767 --- /dev/null +++ b/deps/npm/lib/utils/verify-signatures.js @@ -0,0 +1,389 @@ +const fetch = require('npm-registry-fetch') +const localeCompare = require('@isaacs/string-locale-compare')('en') +const npa = require('npm-package-arg') +const pacote = require('pacote') +const pMap = require('p-map') +const tufClient = require('@sigstore/tuf') +const { log, output } = require('proc-log') + +const sortAlphabetically = (a, b) => localeCompare(a.name, b.name) + +class VerifySignatures { + constructor (tree, filterSet, npm, opts) { + this.tree = tree + this.filterSet = filterSet + this.npm = npm + this.opts = opts + this.keys = new Map() + this.invalid = [] + this.missing = [] + this.checkedPackages = new Set() + this.auditedWithKeysCount = 0 + this.verifiedSignatureCount = 0 + this.verifiedAttestationCount = 0 + this.exitCode = 0 + } + + async run () { + const start = process.hrtime.bigint() + + // Find all deps in tree + const { edges, registries } = this.getEdgesOut(this.tree.inventory.values(), this.filterSet) + if (edges.size === 0) { + throw new Error('found no installed dependencies to audit') + } + + const tuf = await tufClient.initTUF({ + cachePath: this.opts.tufCache, + retry: this.opts.retry, + timeout: this.opts.timeout, + }) + await Promise.all([...registries].map(registry => this.setKeys({ registry, tuf }))) + + log.verbose('verifying registry signatures') + await pMap(edges, (e) => this.getVerifiedInfo(e), { concurrency: 20, stopOnError: true }) + + // Didn't find any dependencies that could be verified, e.g. only local + // deps, missing version, not on a registry etc. + if (!this.auditedWithKeysCount) { + throw new Error('found no dependencies to audit that were installed from ' + + 'a supported registry') + } + + const invalid = this.invalid.sort(sortAlphabetically) + const missing = this.missing.sort(sortAlphabetically) + + const hasNoInvalidOrMissing = invalid.length === 0 && missing.length === 0 + + if (!hasNoInvalidOrMissing) { + process.exitCode = 1 + } + + if (this.npm.config.get('json')) { + output.standard(JSON.stringify({ + invalid, + missing, + }, null, 2)) + return + } + const end = process.hrtime.bigint() + const elapsed = end - start + + const auditedPlural = this.auditedWithKeysCount > 1 ? 's' : '' + const timing = `audited ${this.auditedWithKeysCount} package${auditedPlural} in ` + + `${Math.floor(Number(elapsed) / 1e9)}s` + output.standard(timing) + output.standard('') + + const verifiedBold = this.npm.chalk.bold('verified') + if (this.verifiedSignatureCount) { + if (this.verifiedSignatureCount === 1) { + /* eslint-disable-next-line max-len */ + output.standard(`${this.verifiedSignatureCount} package has a ${verifiedBold} registry signature`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${this.verifiedSignatureCount} packages have ${verifiedBold} registry signatures`) + } + output.standard('') + } + + if (this.verifiedAttestationCount) { + if (this.verifiedAttestationCount === 1) { + /* eslint-disable-next-line max-len */ + output.standard(`${this.verifiedAttestationCount} package has a ${verifiedBold} attestation`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${this.verifiedAttestationCount} packages have ${verifiedBold} attestations`) + } + output.standard('') + } + + if (missing.length) { + const missingClr = this.npm.chalk.redBright('missing') + if (missing.length === 1) { + /* eslint-disable-next-line max-len */ + output.standard(`1 package has a ${missingClr} registry signature but the registry is providing signing keys:`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${missing.length} packages have ${missingClr} registry signatures but the registry is providing signing keys:`) + } + output.standard('') + missing.map(m => + output.standard(`${this.npm.chalk.red(`${m.name}@${m.version}`)} (${m.registry})`) + ) + } + + if (invalid.length) { + if (missing.length) { + output.standard('') + } + const invalidClr = this.npm.chalk.redBright('invalid') + // We can have either invalid signatures or invalid provenance + const invalidSignatures = this.invalid.filter(i => i.code === 'EINTEGRITYSIGNATURE') + if (invalidSignatures.length) { + if (invalidSignatures.length === 1) { + output.standard(`1 package has an ${invalidClr} registry signature:`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${invalidSignatures.length} packages have ${invalidClr} registry signatures:`) + } + output.standard('') + invalidSignatures.map(i => + output.standard(`${this.npm.chalk.red(`${i.name}@${i.version}`)} (${i.registry})`) + ) + output.standard('') + } + + const invalidAttestations = this.invalid.filter(i => i.code === 'EATTESTATIONVERIFY') + if (invalidAttestations.length) { + if (invalidAttestations.length === 1) { + output.standard(`1 package has an ${invalidClr} attestation:`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${invalidAttestations.length} packages have ${invalidClr} attestations:`) + } + output.standard('') + invalidAttestations.map(i => + output.standard(`${this.npm.chalk.red(`${i.name}@${i.version}`)} (${i.registry})`) + ) + output.standard('') + } + + if (invalid.length === 1) { + /* eslint-disable-next-line max-len */ + output.standard(`Someone might have tampered with this package since it was published on the registry!`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`Someone might have tampered with these packages since they were published on the registry!`) + } + output.standard('') + } + } + + getEdgesOut (nodes, filterSet) { + const edges = new Set() + const registries = new Set() + for (const node of nodes) { + for (const edge of node.edgesOut.values()) { + const filteredOut = + edge.from + && filterSet + && filterSet.size > 0 + && !filterSet.has(edge.from.target) + + if (!filteredOut) { + const spec = this.getEdgeSpec(edge) + if (spec) { + // Prefetch and cache public keys from used registries + registries.add(this.getSpecRegistry(spec)) + } + edges.add(edge) + } + } + } + return { edges, registries } + } + + async setKeys ({ registry, tuf }) { + const { host, pathname } = new URL(registry) + // Strip any trailing slashes from pathname + const regKey = `${host}${pathname.replace(/\/$/, '')}/keys.json` + let keys = await tuf.getTarget(regKey) + .then((target) => JSON.parse(target)) + .then(({ keys: ks }) => ks.map((key) => ({ + ...key, + keyid: key.keyId, + pemkey: `-----BEGIN PUBLIC KEY-----\n${key.publicKey.rawBytes}\n-----END PUBLIC KEY-----`, + expires: key.publicKey.validFor.end || null, + }))).catch(err => { + if (err.code === 'TUF_FIND_TARGET_ERROR') { + return null + } else { + throw err + } + }) + + // If keys not found in Sigstore TUF repo, fallback to registry keys API + if (!keys) { + keys = await fetch.json('/-/npm/v1/keys', { + ...this.npm.flatOptions, + registry, + }).then(({ keys: ks }) => ks.map((key) => ({ + ...key, + pemkey: `-----BEGIN PUBLIC KEY-----\n${key.key}\n-----END PUBLIC KEY-----`, + }))).catch(err => { + if (err.code === 'E404' || err.code === 'E400') { + return null + } else { + throw err + } + }) + } + + if (keys) { + this.keys.set(registry, keys) + } + } + + getEdgeType (edge) { + return edge.optional ? 'optionalDependencies' + : edge.peer ? 'peerDependencies' + : edge.dev ? 'devDependencies' + : 'dependencies' + } + + getEdgeSpec (edge) { + let name = edge.name + try { + name = npa(edge.spec).subSpec.name + } catch { + // leave it as edge.name + } + try { + return npa(`${name}@${edge.spec}`) + } catch { + // Skip packages with invalid spec + } + } + + buildRegistryConfig (registry) { + const keys = this.keys.get(registry) || [] + const parsedRegistry = new URL(registry) + const regKey = `//${parsedRegistry.host}${parsedRegistry.pathname}` + return { + [`${regKey}:_keys`]: keys, + } + } + + getSpecRegistry (spec) { + return fetch.pickRegistry(spec, this.npm.flatOptions) + } + + getValidPackageInfo (edge) { + const type = this.getEdgeType(edge) + // Skip potentially optional packages that are not on disk, as these could + // be omitted during install + if (edge.error === 'MISSING' && type !== 'dependencies') { + return + } + + const spec = this.getEdgeSpec(edge) + // Skip invalid version requirements + if (!spec) { + return + } + const node = edge.to || edge + const { version } = node.package || {} + + if (node.isWorkspace || // Skip local workspaces packages + !version || // Skip packages that don't have a installed version, e.g. optonal dependencies + !spec.registry) { // Skip if not from registry, e.g. git package + return + } + + for (const omitType of this.npm.config.get('omit')) { + if (node[omitType]) { + return + } + } + + return { + name: spec.name, + version, + type, + location: node.location, + registry: this.getSpecRegistry(spec), + } + } + + async verifySignatures (name, version, registry) { + const { + _integrity: integrity, + _signatures, + _attestations, + _resolved: resolved, + } = await pacote.manifest(`${name}@${version}`, { + verifySignatures: true, + verifyAttestations: true, + ...this.buildRegistryConfig(registry), + ...this.npm.flatOptions, + }) + const signatures = _signatures || [] + const result = { + integrity, + signatures, + attestations: _attestations, + resolved, + } + return result + } + + async getVerifiedInfo (edge) { + const info = this.getValidPackageInfo(edge) + if (!info) { + return + } + const { name, version, location, registry, type } = info + if (this.checkedPackages.has(location)) { + // we already did or are doing this one + return + } + this.checkedPackages.add(location) + + // We only "audit" or verify the signature, or the presence of it, on + // packages whose registry returns signing keys + const keys = this.keys.get(registry) || [] + if (keys.length) { + this.auditedWithKeysCount += 1 + } + + try { + const { integrity, signatures, attestations, resolved } = await this.verifySignatures( + name, version, registry + ) + + // Currently we only care about missing signatures on registries that provide a public key + // We could make this configurable in the future with a strict/paranoid mode + if (signatures.length) { + this.verifiedSignatureCount += 1 + } else if (keys.length) { + this.missing.push({ + integrity, + location, + name, + registry, + resolved, + version, + }) + } + + // Track verified attestations separately to registry signatures, as all + // packages on registries with signing keys are expected to have registry + // signatures, but not all packages have provenance and publish attestations. + if (attestations) { + this.verifiedAttestationCount += 1 + } + } catch (e) { + if (e.code === 'EINTEGRITYSIGNATURE' || e.code === 'EATTESTATIONVERIFY') { + this.invalid.push({ + code: e.code, + message: e.message, + integrity: e.integrity, + keyid: e.keyid, + location, + name, + registry, + resolved: e.resolved, + signature: e.signature, + predicateType: e.predicateType, + type, + version, + }) + } else { + throw e + } + } + } +} + +module.exports = VerifySignatures diff --git a/deps/npm/man/man1/npm-access.1 b/deps/npm/man/man1/npm-access.1 index 5231dbac1d504b..df63b4a6a5d6c6 100644 --- a/deps/npm/man/man1/npm-access.1 +++ b/deps/npm/man/man1/npm-access.1 @@ -1,11 +1,11 @@ -.TH "NPM-ACCESS" "1" "February 2024" "" "" +.TH "NPM-ACCESS" "1" "April 2024" "" "" .SH "NAME" \fBnpm-access\fR - Set access level on published packages .SS "Synopsis" .P .RS 2 .nf -npm access list packages \[lB]|| \[lB]\[rB] +npm access list packages \[lB]||\[rB] \[lB]\[rB] npm access list collaborators \[lB] \[lB]\[rB]\[rB] npm access get status \[lB]\[rB] npm access set status=public|private \[lB]\[rB] diff --git a/deps/npm/man/man1/npm-adduser.1 b/deps/npm/man/man1/npm-adduser.1 index c7cbb2cfcec253..e867396ccfc4bf 100644 --- a/deps/npm/man/man1/npm-adduser.1 +++ b/deps/npm/man/man1/npm-adduser.1 @@ -1,4 +1,4 @@ -.TH "NPM-ADDUSER" "1" "February 2024" "" "" +.TH "NPM-ADDUSER" "1" "April 2024" "" "" .SH "NAME" \fBnpm-adduser\fR - Add a registry user account .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-audit.1 b/deps/npm/man/man1/npm-audit.1 index e6b1982cb4c171..5832cb09ff9980 100644 --- a/deps/npm/man/man1/npm-audit.1 +++ b/deps/npm/man/man1/npm-audit.1 @@ -1,4 +1,4 @@ -.TH "NPM-AUDIT" "1" "February 2024" "" "" +.TH "NPM-AUDIT" "1" "April 2024" "" "" .SH "NAME" \fBnpm-audit\fR - Run a security audit .SS "Synopsis" @@ -33,6 +33,8 @@ $ npm audit signatures .fi .RE .P +The \fBaudit signatures\fR command will also verify the provenance attestations of downloaded packages. Because provenance attestations are such a new feature, security features may be added to (or changed in) the attestation format over time. To ensure that you're always able to verify attestation signatures check that you're running the latest version of the npm CLI. Please note this often means updating npm beyond the version that ships with Node.js. +.P The npm CLI supports registry signatures and signing keys provided by any registry if the following conventions are followed: .RS 0 .IP 1. 4 @@ -78,7 +80,7 @@ Public signing keys are provided at \fBregistry-host.tld/-/npm/v1/keys\fR in the Keys response: .RS 0 .IP \(bu 4 -\fBexpires\fR: null or a simplified extended \fBISO 8601 format\fR \fI\(lahttps://en.wikipedia.org/wiki/ISO_8601"\(ra\fR: \fBYYYY-MM-DDTHH:mm:ss.sssZ\fR +\fBexpires\fR: null or a simplified extended \fBISO 8601 format\fR \fI\(lahttps://en.wikipedia.org/wiki/ISO_8601\(ra\fR: \fBYYYY-MM-DDTHH:mm:ss.sssZ\fR .IP \(bu 4 \fBkeydid\fR: sha256 fingerprint of the public key .IP \(bu 4 @@ -90,7 +92,7 @@ Keys response: .RE 0 .P -See this \fBexample key's response from the public npm registry\fR \fI\(lahttps://registry.npmjs.org/-/npm/v1/keys"\(ra\fR. +See this \fBexample key's response from the public npm registry\fR \fI\(lahttps://registry.npmjs.org/-/npm/v1/keys\(ra\fR. .SS "Audit Endpoints" .P There are two audit endpoints that npm may use to fetch vulnerability information: the \fBBulk Advisory\fR endpoint and the \fBQuick Audit\fR endpoint. diff --git a/deps/npm/man/man1/npm-bugs.1 b/deps/npm/man/man1/npm-bugs.1 index 7db5b6cdb87f71..ea6371ffbe4fc1 100644 --- a/deps/npm/man/man1/npm-bugs.1 +++ b/deps/npm/man/man1/npm-bugs.1 @@ -1,4 +1,4 @@ -.TH "NPM-BUGS" "1" "February 2024" "" "" +.TH "NPM-BUGS" "1" "April 2024" "" "" .SH "NAME" \fBnpm-bugs\fR - Report bugs for a package in a web browser .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-cache.1 b/deps/npm/man/man1/npm-cache.1 index 2ec9e67be0634d..c741829317d2e1 100644 --- a/deps/npm/man/man1/npm-cache.1 +++ b/deps/npm/man/man1/npm-cache.1 @@ -1,4 +1,4 @@ -.TH "NPM-CACHE" "1" "February 2024" "" "" +.TH "NPM-CACHE" "1" "April 2024" "" "" .SH "NAME" \fBnpm-cache\fR - Manipulates packages cache .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-ci.1 b/deps/npm/man/man1/npm-ci.1 index 16ed2f6d9b5bb8..793f02006ab229 100644 --- a/deps/npm/man/man1/npm-ci.1 +++ b/deps/npm/man/man1/npm-ci.1 @@ -1,4 +1,4 @@ -.TH "NPM-CI" "1" "February 2024" "" "" +.TH "NPM-CI" "1" "April 2024" "" "" .SH "NAME" \fBnpm-ci\fR - Clean install a project .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-completion.1 b/deps/npm/man/man1/npm-completion.1 index 647d5e11ac202d..28bfb2906d1922 100644 --- a/deps/npm/man/man1/npm-completion.1 +++ b/deps/npm/man/man1/npm-completion.1 @@ -1,4 +1,4 @@ -.TH "NPM-COMPLETION" "1" "February 2024" "" "" +.TH "NPM-COMPLETION" "1" "April 2024" "" "" .SH "NAME" \fBnpm-completion\fR - Tab Completion for npm .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-config.1 b/deps/npm/man/man1/npm-config.1 index f3be24e542465d..bd572dea7c4ab8 100644 --- a/deps/npm/man/man1/npm-config.1 +++ b/deps/npm/man/man1/npm-config.1 @@ -1,4 +1,4 @@ -.TH "NPM-CONFIG" "1" "February 2024" "" "" +.TH "NPM-CONFIG" "1" "April 2024" "" "" .SH "NAME" \fBnpm-config\fR - Manage the npm configuration files .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-dedupe.1 b/deps/npm/man/man1/npm-dedupe.1 index 5480af746dcae5..529e14b0efb722 100644 --- a/deps/npm/man/man1/npm-dedupe.1 +++ b/deps/npm/man/man1/npm-dedupe.1 @@ -1,4 +1,4 @@ -.TH "NPM-DEDUPE" "1" "February 2024" "" "" +.TH "NPM-DEDUPE" "1" "April 2024" "" "" .SH "NAME" \fBnpm-dedupe\fR - Reduce duplication in the package tree .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-deprecate.1 b/deps/npm/man/man1/npm-deprecate.1 index 5e8d47a8bc77fc..2a3891596da0c6 100644 --- a/deps/npm/man/man1/npm-deprecate.1 +++ b/deps/npm/man/man1/npm-deprecate.1 @@ -1,4 +1,4 @@ -.TH "NPM-DEPRECATE" "1" "February 2024" "" "" +.TH "NPM-DEPRECATE" "1" "April 2024" "" "" .SH "NAME" \fBnpm-deprecate\fR - Deprecate a version of a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-diff.1 b/deps/npm/man/man1/npm-diff.1 index bea8bb3ef1d674..f8f0b5e7f40aac 100644 --- a/deps/npm/man/man1/npm-diff.1 +++ b/deps/npm/man/man1/npm-diff.1 @@ -1,4 +1,4 @@ -.TH "NPM-DIFF" "1" "February 2024" "" "" +.TH "NPM-DIFF" "1" "April 2024" "" "" .SH "NAME" \fBnpm-diff\fR - The registry diff command .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-dist-tag.1 b/deps/npm/man/man1/npm-dist-tag.1 index 6c4acc26b43b18..c0b6e8d70df6dc 100644 --- a/deps/npm/man/man1/npm-dist-tag.1 +++ b/deps/npm/man/man1/npm-dist-tag.1 @@ -1,4 +1,4 @@ -.TH "NPM-DIST-TAG" "1" "February 2024" "" "" +.TH "NPM-DIST-TAG" "1" "April 2024" "" "" .SH "NAME" \fBnpm-dist-tag\fR - Modify package distribution tags .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-docs.1 b/deps/npm/man/man1/npm-docs.1 index b9cc1da9abe783..be22f95c00df95 100644 --- a/deps/npm/man/man1/npm-docs.1 +++ b/deps/npm/man/man1/npm-docs.1 @@ -1,4 +1,4 @@ -.TH "NPM-DOCS" "1" "February 2024" "" "" +.TH "NPM-DOCS" "1" "April 2024" "" "" .SH "NAME" \fBnpm-docs\fR - Open documentation for a package in a web browser .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-doctor.1 b/deps/npm/man/man1/npm-doctor.1 index 42187f46922d5e..16ae2f7e41715b 100644 --- a/deps/npm/man/man1/npm-doctor.1 +++ b/deps/npm/man/man1/npm-doctor.1 @@ -1,11 +1,11 @@ -.TH "NPM-DOCTOR" "1" "February 2024" "" "" +.TH "NPM-DOCTOR" "1" "April 2024" "" "" .SH "NAME" \fBnpm-doctor\fR - Check the health of your npm environment .SS "Synopsis" .P .RS 2 .nf -npm doctor \[lB]ping\[rB] \[lB]registry\[rB] \[lB]versions\[rB] \[lB]environment\[rB] \[lB]permissions\[rB] \[lB]cache\[rB] +npm doctor \[lB]connection\[rB] \[lB]registry\[rB] \[lB]versions\[rB] \[lB]environment\[rB] \[lB]permissions\[rB] \[lB]cache\[rB] .fi .RE .P @@ -30,21 +30,21 @@ Without all of these working properly, npm may not work properly. Many issues ar Also, in addition to this, there are also very many issue reports due to using old versions of npm. Since npm is constantly improving, running \fBnpm@latest\fR is better than an old version. .P \fBnpm doctor\fR verifies the following items in your environment, and if there are any recommended changes, it will display them. By default npm runs all of these checks. You can limit what checks are ran by specifying them as extra arguments. -.SS "\fBnpm ping\fR" +.SS "\fBConnecting to the registry\fR" .P -By default, npm installs from the primary npm registry, \fBregistry.npmjs.org\fR. \fBnpm doctor\fR hits a special ping endpoint within the registry. This can also be checked with \fBnpm ping\fR. If this check fails, you may be using a proxy that needs to be configured, or may need to talk to your IT staff to get access over HTTPS to \fBregistry.npmjs.org\fR. +By default, npm installs from the primary npm registry, \fBregistry.npmjs.org\fR. \fBnpm doctor\fR hits a special connection testing endpoint within the registry. This can also be checked with \fBnpm ping\fR. If this check fails, you may be using a proxy that needs to be configured, or may need to talk to your IT staff to get access over HTTPS to \fBregistry.npmjs.org\fR. .P This check is done against whichever registry you've configured (you can see what that is by running \fBnpm config get registry\fR), and if you're using a private registry that doesn't support the \fB/whoami\fR endpoint supported by the primary registry, this check may fail. -.SS "\fBnpm -v\fR" +.SS "\fBChecking npm version\fR" .P While Node.js may come bundled with a particular version of npm, it's the policy of the CLI team that we recommend all users run \fBnpm@latest\fR if they can. As the CLI is maintained by a small team of contributors, there are only resources for a single line of development, so npm's own long-term support releases typically only receive critical security and regression fixes. The team believes that the latest tested version of npm is almost always likely to be the most functional and defect-free version of npm. -.SS "\fBnode -v\fR" +.SS "\fBChecking node version\fR" .P For most users, in most circumstances, the best version of Node will be the latest long-term support (LTS) release. Those of you who want access to new ECMAscript features or bleeding-edge changes to Node's standard library may be running a newer version, and some may be required to run an older version of Node because of enterprise change control policies. That's OK! But in general, the npm team recommends that most users run Node.js LTS. -.SS "\fBnpm config get registry\fR" +.SS "\fBChecking configured npm registry\fR" .P You may be installing from private package registries for your project or company. That's great! Others may be following tutorials or StackOverflow questions in an effort to troubleshoot problems you may be having. Sometimes, this may entail changing the registry you're pointing at. This part of \fBnpm doctor\fR just lets you, and maybe whoever's helping you with support, know that you're not using the default registry. -.SS "\fBwhich git\fR" +.SS "\fBChecking for git executable in PATH\fR" .P While it's documented in the README, it may not be obvious that npm needs Git installed to do many of the things that it does. Also, in some cases \[en] especially on Windows \[en] you may have Git set up in such a way that it's not accessible via your \fBPATH\fR so that npm can find it. This check ensures that Git is available. .SS "Permissions checks" diff --git a/deps/npm/man/man1/npm-edit.1 b/deps/npm/man/man1/npm-edit.1 index 82cd85851f0480..0f91c98e4b6cd9 100644 --- a/deps/npm/man/man1/npm-edit.1 +++ b/deps/npm/man/man1/npm-edit.1 @@ -1,4 +1,4 @@ -.TH "NPM-EDIT" "1" "February 2024" "" "" +.TH "NPM-EDIT" "1" "April 2024" "" "" .SH "NAME" \fBnpm-edit\fR - Edit an installed package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-exec.1 b/deps/npm/man/man1/npm-exec.1 index 246498125c14ca..0040f141315cd3 100644 --- a/deps/npm/man/man1/npm-exec.1 +++ b/deps/npm/man/man1/npm-exec.1 @@ -1,4 +1,4 @@ -.TH "NPM-EXEC" "1" "February 2024" "" "" +.TH "NPM-EXEC" "1" "April 2024" "" "" .SH "NAME" \fBnpm-exec\fR - Run a command from a local or remote npm package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-explain.1 b/deps/npm/man/man1/npm-explain.1 index e1bb6de84f3348..ea53b43add250b 100644 --- a/deps/npm/man/man1/npm-explain.1 +++ b/deps/npm/man/man1/npm-explain.1 @@ -1,4 +1,4 @@ -.TH "NPM-EXPLAIN" "1" "February 2024" "" "" +.TH "NPM-EXPLAIN" "1" "April 2024" "" "" .SH "NAME" \fBnpm-explain\fR - Explain installed packages .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-explore.1 b/deps/npm/man/man1/npm-explore.1 index b4800ccfa6b299..7127aff53ee73f 100644 --- a/deps/npm/man/man1/npm-explore.1 +++ b/deps/npm/man/man1/npm-explore.1 @@ -1,4 +1,4 @@ -.TH "NPM-EXPLORE" "1" "February 2024" "" "" +.TH "NPM-EXPLORE" "1" "April 2024" "" "" .SH "NAME" \fBnpm-explore\fR - Browse an installed package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-find-dupes.1 b/deps/npm/man/man1/npm-find-dupes.1 index 1f80df08c59e20..fc625fb8ebd10b 100644 --- a/deps/npm/man/man1/npm-find-dupes.1 +++ b/deps/npm/man/man1/npm-find-dupes.1 @@ -1,4 +1,4 @@ -.TH "NPM-FIND-DUPES" "1" "February 2024" "" "" +.TH "NPM-FIND-DUPES" "1" "April 2024" "" "" .SH "NAME" \fBnpm-find-dupes\fR - Find duplication in the package tree .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-fund.1 b/deps/npm/man/man1/npm-fund.1 index 22d61e036d929a..c8fb9354beb570 100644 --- a/deps/npm/man/man1/npm-fund.1 +++ b/deps/npm/man/man1/npm-fund.1 @@ -1,4 +1,4 @@ -.TH "NPM-FUND" "1" "February 2024" "" "" +.TH "NPM-FUND" "1" "April 2024" "" "" .SH "NAME" \fBnpm-fund\fR - Retrieve funding information .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-help-search.1 b/deps/npm/man/man1/npm-help-search.1 index 4a9dd82c921cde..892777ce4e6b4a 100644 --- a/deps/npm/man/man1/npm-help-search.1 +++ b/deps/npm/man/man1/npm-help-search.1 @@ -1,4 +1,4 @@ -.TH "NPM-HELP-SEARCH" "1" "February 2024" "" "" +.TH "NPM-HELP-SEARCH" "1" "April 2024" "" "" .SH "NAME" \fBnpm-help-search\fR - Search npm help documentation .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-help.1 b/deps/npm/man/man1/npm-help.1 index c2880c831f6490..bb08ed91cccb79 100644 --- a/deps/npm/man/man1/npm-help.1 +++ b/deps/npm/man/man1/npm-help.1 @@ -1,4 +1,4 @@ -.TH "NPM-HELP" "1" "February 2024" "" "" +.TH "NPM-HELP" "1" "April 2024" "" "" .SH "NAME" \fBnpm-help\fR - Get help on npm .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-hook.1 b/deps/npm/man/man1/npm-hook.1 index 2fc1b0dd667b88..ece059dfbb5257 100644 --- a/deps/npm/man/man1/npm-hook.1 +++ b/deps/npm/man/man1/npm-hook.1 @@ -1,4 +1,4 @@ -.TH "NPM-HOOK" "1" "February 2024" "" "" +.TH "NPM-HOOK" "1" "April 2024" "" "" .SH "NAME" \fBnpm-hook\fR - Manage registry hooks .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-init.1 b/deps/npm/man/man1/npm-init.1 index bfc7e48dc532a3..cc2c543925e464 100644 --- a/deps/npm/man/man1/npm-init.1 +++ b/deps/npm/man/man1/npm-init.1 @@ -1,4 +1,4 @@ -.TH "NPM-INIT" "1" "February 2024" "" "" +.TH "NPM-INIT" "1" "April 2024" "" "" .SH "NAME" \fBnpm-init\fR - Create a package.json file .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-install-ci-test.1 b/deps/npm/man/man1/npm-install-ci-test.1 index adc70da13cdf63..bd7f5b84a13016 100644 --- a/deps/npm/man/man1/npm-install-ci-test.1 +++ b/deps/npm/man/man1/npm-install-ci-test.1 @@ -1,4 +1,4 @@ -.TH "NPM-INSTALL-CI-TEST" "1" "February 2024" "" "" +.TH "NPM-INSTALL-CI-TEST" "1" "April 2024" "" "" .SH "NAME" \fBnpm-install-ci-test\fR - Install a project with a clean slate and run tests .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-install-test.1 b/deps/npm/man/man1/npm-install-test.1 index 8a0fcc72025b28..331fe854774f58 100644 --- a/deps/npm/man/man1/npm-install-test.1 +++ b/deps/npm/man/man1/npm-install-test.1 @@ -1,4 +1,4 @@ -.TH "NPM-INSTALL-TEST" "1" "February 2024" "" "" +.TH "NPM-INSTALL-TEST" "1" "April 2024" "" "" .SH "NAME" \fBnpm-install-test\fR - Install package(s) and run tests .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-install.1 b/deps/npm/man/man1/npm-install.1 index d6b5990abffd56..6d98e0e40923c0 100644 --- a/deps/npm/man/man1/npm-install.1 +++ b/deps/npm/man/man1/npm-install.1 @@ -1,4 +1,4 @@ -.TH "NPM-INSTALL" "1" "February 2024" "" "" +.TH "NPM-INSTALL" "1" "April 2024" "" "" .SH "NAME" \fBnpm-install\fR - Install a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-link.1 b/deps/npm/man/man1/npm-link.1 index a2ee4fe19a0995..174f9d1bd1baf8 100644 --- a/deps/npm/man/man1/npm-link.1 +++ b/deps/npm/man/man1/npm-link.1 @@ -1,4 +1,4 @@ -.TH "NPM-LINK" "1" "February 2024" "" "" +.TH "NPM-LINK" "1" "April 2024" "" "" .SH "NAME" \fBnpm-link\fR - Symlink a package folder .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-login.1 b/deps/npm/man/man1/npm-login.1 index 858a80ba3e19c1..1b7aea8819d6ec 100644 --- a/deps/npm/man/man1/npm-login.1 +++ b/deps/npm/man/man1/npm-login.1 @@ -1,4 +1,4 @@ -.TH "NPM-LOGIN" "1" "February 2024" "" "" +.TH "NPM-LOGIN" "1" "April 2024" "" "" .SH "NAME" \fBnpm-login\fR - Login to a registry user account .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-logout.1 b/deps/npm/man/man1/npm-logout.1 index 9151725cd4f5e2..113d6c5fab0995 100644 --- a/deps/npm/man/man1/npm-logout.1 +++ b/deps/npm/man/man1/npm-logout.1 @@ -1,4 +1,4 @@ -.TH "NPM-LOGOUT" "1" "February 2024" "" "" +.TH "NPM-LOGOUT" "1" "April 2024" "" "" .SH "NAME" \fBnpm-logout\fR - Log out of the registry .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1 index 0acb36abe2ae8a..3d4728693455e4 100644 --- a/deps/npm/man/man1/npm-ls.1 +++ b/deps/npm/man/man1/npm-ls.1 @@ -1,4 +1,4 @@ -.TH "NPM-LS" "1" "February 2024" "" "" +.TH "NPM-LS" "1" "April 2024" "" "" .SH "NAME" \fBnpm-ls\fR - List installed packages .SS "Synopsis" @@ -20,7 +20,7 @@ Positional arguments are \fBname@version-range\fR identifiers, which will limit .P .RS 2 .nf -npm@10.5.0 /path/to/npm +npm@10.7.0 /path/to/npm └─┬ init-package-json@0.0.4 └── promzard@0.1.5 .fi diff --git a/deps/npm/man/man1/npm-org.1 b/deps/npm/man/man1/npm-org.1 index 56c41d3cf2991c..002259ab5578a8 100644 --- a/deps/npm/man/man1/npm-org.1 +++ b/deps/npm/man/man1/npm-org.1 @@ -1,4 +1,4 @@ -.TH "NPM-ORG" "1" "February 2024" "" "" +.TH "NPM-ORG" "1" "April 2024" "" "" .SH "NAME" \fBnpm-org\fR - Manage orgs .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-outdated.1 b/deps/npm/man/man1/npm-outdated.1 index 8357aa2472a59c..528bc0d0e24d54 100644 --- a/deps/npm/man/man1/npm-outdated.1 +++ b/deps/npm/man/man1/npm-outdated.1 @@ -1,4 +1,4 @@ -.TH "NPM-OUTDATED" "1" "February 2024" "" "" +.TH "NPM-OUTDATED" "1" "April 2024" "" "" .SH "NAME" \fBnpm-outdated\fR - Check for outdated packages .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-owner.1 b/deps/npm/man/man1/npm-owner.1 index d11d2bf54290e5..114cd78939c6a8 100644 --- a/deps/npm/man/man1/npm-owner.1 +++ b/deps/npm/man/man1/npm-owner.1 @@ -1,4 +1,4 @@ -.TH "NPM-OWNER" "1" "February 2024" "" "" +.TH "NPM-OWNER" "1" "April 2024" "" "" .SH "NAME" \fBnpm-owner\fR - Manage package owners .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-pack.1 b/deps/npm/man/man1/npm-pack.1 index a25b769cc74edb..6c0046bce58252 100644 --- a/deps/npm/man/man1/npm-pack.1 +++ b/deps/npm/man/man1/npm-pack.1 @@ -1,4 +1,4 @@ -.TH "NPM-PACK" "1" "February 2024" "" "" +.TH "NPM-PACK" "1" "April 2024" "" "" .SH "NAME" \fBnpm-pack\fR - Create a tarball from a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-ping.1 b/deps/npm/man/man1/npm-ping.1 index 20bc98116b5e75..c6d509c56a4be4 100644 --- a/deps/npm/man/man1/npm-ping.1 +++ b/deps/npm/man/man1/npm-ping.1 @@ -1,4 +1,4 @@ -.TH "NPM-PING" "1" "February 2024" "" "" +.TH "NPM-PING" "1" "April 2024" "" "" .SH "NAME" \fBnpm-ping\fR - Ping npm registry .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-pkg.1 b/deps/npm/man/man1/npm-pkg.1 index 1c83741aff95e6..170639b8d9af70 100644 --- a/deps/npm/man/man1/npm-pkg.1 +++ b/deps/npm/man/man1/npm-pkg.1 @@ -1,4 +1,4 @@ -.TH "NPM-PKG" "1" "February 2024" "" "" +.TH "NPM-PKG" "1" "April 2024" "" "" .SH "NAME" \fBnpm-pkg\fR - Manages your package.json .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-prefix.1 b/deps/npm/man/man1/npm-prefix.1 index a9fc70239b5de3..0af03494691d7f 100644 --- a/deps/npm/man/man1/npm-prefix.1 +++ b/deps/npm/man/man1/npm-prefix.1 @@ -1,4 +1,4 @@ -.TH "NPM-PREFIX" "1" "February 2024" "" "" +.TH "NPM-PREFIX" "1" "April 2024" "" "" .SH "NAME" \fBnpm-prefix\fR - Display prefix .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-profile.1 b/deps/npm/man/man1/npm-profile.1 index 82f6af354da89e..423167e2efafc4 100644 --- a/deps/npm/man/man1/npm-profile.1 +++ b/deps/npm/man/man1/npm-profile.1 @@ -1,4 +1,4 @@ -.TH "NPM-PROFILE" "1" "February 2024" "" "" +.TH "NPM-PROFILE" "1" "April 2024" "" "" .SH "NAME" \fBnpm-profile\fR - Change settings on your registry profile .SS "Synopsis" @@ -24,27 +24,16 @@ Change your profile information on the registry. Note that this command depends .P .RS 2 .nf -+-----------------+---------------------------+ -| name | example | -+-----------------+---------------------------+ -| email | me@example.com (verified) | -+-----------------+---------------------------+ -| two factor auth | auth-and-writes | -+-----------------+---------------------------+ -| fullname | Example User | -+-----------------+---------------------------+ -| homepage | | -+-----------------+---------------------------+ -| freenode | | -+-----------------+---------------------------+ -| twitter | | -+-----------------+---------------------------+ -| github | | -+-----------------+---------------------------+ -| created | 2015-02-26T01:38:35.892Z | -+-----------------+---------------------------+ -| updated | 2017-10-02T21:29:45.922Z | -+-----------------+---------------------------+ +name: example +email: e@example.com (verified) +two-factor auth: auth-and-writes +fullname: Example User +homepage: +freenode: +twitter: +github: +created: 2015-02-26T01:38:35.892Z +updated: 2017-10-02T21:29:45.922Z .fi .RE .RS 0 diff --git a/deps/npm/man/man1/npm-prune.1 b/deps/npm/man/man1/npm-prune.1 index c54bb96caee5c8..a7162e053616dd 100644 --- a/deps/npm/man/man1/npm-prune.1 +++ b/deps/npm/man/man1/npm-prune.1 @@ -1,4 +1,4 @@ -.TH "NPM-PRUNE" "1" "February 2024" "" "" +.TH "NPM-PRUNE" "1" "April 2024" "" "" .SH "NAME" \fBnpm-prune\fR - Remove extraneous packages .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-publish.1 b/deps/npm/man/man1/npm-publish.1 index 55a90c1380b487..9ebfbaa761bb12 100644 --- a/deps/npm/man/man1/npm-publish.1 +++ b/deps/npm/man/man1/npm-publish.1 @@ -1,4 +1,4 @@ -.TH "NPM-PUBLISH" "1" "February 2024" "" "" +.TH "NPM-PUBLISH" "1" "April 2024" "" "" .SH "NAME" \fBnpm-publish\fR - Publish a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-query.1 b/deps/npm/man/man1/npm-query.1 index 3940d6e80e15e6..d2271722e13711 100644 --- a/deps/npm/man/man1/npm-query.1 +++ b/deps/npm/man/man1/npm-query.1 @@ -1,4 +1,4 @@ -.TH "NPM-QUERY" "1" "February 2024" "" "" +.TH "NPM-QUERY" "1" "April 2024" "" "" .SH "NAME" \fBnpm-query\fR - Dependency selector query .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-rebuild.1 b/deps/npm/man/man1/npm-rebuild.1 index ec29b9e036471d..9fe38d79998a7c 100644 --- a/deps/npm/man/man1/npm-rebuild.1 +++ b/deps/npm/man/man1/npm-rebuild.1 @@ -1,4 +1,4 @@ -.TH "NPM-REBUILD" "1" "February 2024" "" "" +.TH "NPM-REBUILD" "1" "April 2024" "" "" .SH "NAME" \fBnpm-rebuild\fR - Rebuild a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-repo.1 b/deps/npm/man/man1/npm-repo.1 index a909f41a882fd2..197d333c10a919 100644 --- a/deps/npm/man/man1/npm-repo.1 +++ b/deps/npm/man/man1/npm-repo.1 @@ -1,4 +1,4 @@ -.TH "NPM-REPO" "1" "February 2024" "" "" +.TH "NPM-REPO" "1" "April 2024" "" "" .SH "NAME" \fBnpm-repo\fR - Open package repository page in the browser .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-restart.1 b/deps/npm/man/man1/npm-restart.1 index f83b41709ff3e1..59acbf2c09f56c 100644 --- a/deps/npm/man/man1/npm-restart.1 +++ b/deps/npm/man/man1/npm-restart.1 @@ -1,4 +1,4 @@ -.TH "NPM-RESTART" "1" "February 2024" "" "" +.TH "NPM-RESTART" "1" "April 2024" "" "" .SH "NAME" \fBnpm-restart\fR - Restart a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-root.1 b/deps/npm/man/man1/npm-root.1 index 9819a9d9e5e9e1..e56b2f3d3afb13 100644 --- a/deps/npm/man/man1/npm-root.1 +++ b/deps/npm/man/man1/npm-root.1 @@ -1,4 +1,4 @@ -.TH "NPM-ROOT" "1" "February 2024" "" "" +.TH "NPM-ROOT" "1" "April 2024" "" "" .SH "NAME" \fBnpm-root\fR - Display npm root .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-run-script.1 b/deps/npm/man/man1/npm-run-script.1 index 513eb7de904399..d6e98845b4c411 100644 --- a/deps/npm/man/man1/npm-run-script.1 +++ b/deps/npm/man/man1/npm-run-script.1 @@ -1,4 +1,4 @@ -.TH "NPM-RUN-SCRIPT" "1" "February 2024" "" "" +.TH "NPM-RUN-SCRIPT" "1" "April 2024" "" "" .SH "NAME" \fBnpm-run-script\fR - Run arbitrary package scripts .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-sbom.1 b/deps/npm/man/man1/npm-sbom.1 index 5c3016bff248e0..b984044896eaed 100644 --- a/deps/npm/man/man1/npm-sbom.1 +++ b/deps/npm/man/man1/npm-sbom.1 @@ -1,4 +1,4 @@ -.TH "NPM-SBOM" "1" "February 2024" "" "" +.TH "NPM-SBOM" "1" "April 2024" "" "" .SH "NAME" \fBnpm-sbom\fR - Generate a Software Bill of Materials (SBOM) .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-search.1 b/deps/npm/man/man1/npm-search.1 index 3467f3256b8cb0..041bd1113010f5 100644 --- a/deps/npm/man/man1/npm-search.1 +++ b/deps/npm/man/man1/npm-search.1 @@ -1,11 +1,11 @@ -.TH "NPM-SEARCH" "1" "February 2024" "" "" +.TH "NPM-SEARCH" "1" "April 2024" "" "" .SH "NAME" \fBnpm-search\fR - Search for packages .SS "Synopsis" .P .RS 2 .nf -npm search \[lB]search terms ...\[rB] +npm search \[lB] ...\[rB] aliases: find, s, se .fi @@ -22,16 +22,6 @@ Search also allows targeting of maintainers in search results, by prefixing thei .P If a term starts with \fB/\fR, then it's interpreted as a regular expression and supports standard JavaScript RegExp syntax. In this case search will ignore a trailing \fB/\fR . (Note you must escape or quote many regular expression characters in most shells.) .SS "Configuration" -.SS "\fBlong\fR" -.RS 0 -.IP \(bu 4 -Default: false -.IP \(bu 4 -Type: Boolean -.RE 0 - -.P -Show extended information in \fBls\fR, \fBsearch\fR, and \fBhelp-search\fR. .SS "\fBjson\fR" .RS 0 .IP \(bu 4 @@ -79,6 +69,16 @@ Type: Boolean .P Show the description in \fBnpm search\fR +.SS "\fBsearchlimit\fR" +.RS 0 +.IP \(bu 4 +Default: 20 +.IP \(bu 4 +Type: Number +.RE 0 + +.P +Number of items to limit search results to. Will not apply at all to legacy searches. .SS "\fBsearchopts\fR" .RS 0 .IP \(bu 4 diff --git a/deps/npm/man/man1/npm-shrinkwrap.1 b/deps/npm/man/man1/npm-shrinkwrap.1 index 37320600e7d922..cb74dfd382f0a1 100644 --- a/deps/npm/man/man1/npm-shrinkwrap.1 +++ b/deps/npm/man/man1/npm-shrinkwrap.1 @@ -1,4 +1,4 @@ -.TH "NPM-SHRINKWRAP" "1" "February 2024" "" "" +.TH "NPM-SHRINKWRAP" "1" "April 2024" "" "" .SH "NAME" \fBnpm-shrinkwrap\fR - Lock down dependency versions for publication .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-star.1 b/deps/npm/man/man1/npm-star.1 index 22cbdb0d3be628..951ab5bdeb7eb3 100644 --- a/deps/npm/man/man1/npm-star.1 +++ b/deps/npm/man/man1/npm-star.1 @@ -1,4 +1,4 @@ -.TH "NPM-STAR" "1" "February 2024" "" "" +.TH "NPM-STAR" "1" "April 2024" "" "" .SH "NAME" \fBnpm-star\fR - Mark your favorite packages .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-stars.1 b/deps/npm/man/man1/npm-stars.1 index 1f61a034e89c89..7848df08500154 100644 --- a/deps/npm/man/man1/npm-stars.1 +++ b/deps/npm/man/man1/npm-stars.1 @@ -1,4 +1,4 @@ -.TH "NPM-STARS" "1" "February 2024" "" "" +.TH "NPM-STARS" "1" "April 2024" "" "" .SH "NAME" \fBnpm-stars\fR - View packages marked as favorites .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-start.1 b/deps/npm/man/man1/npm-start.1 index 3aebd2cb6cb71c..c46b8dabed2e89 100644 --- a/deps/npm/man/man1/npm-start.1 +++ b/deps/npm/man/man1/npm-start.1 @@ -1,4 +1,4 @@ -.TH "NPM-START" "1" "February 2024" "" "" +.TH "NPM-START" "1" "April 2024" "" "" .SH "NAME" \fBnpm-start\fR - Start a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-stop.1 b/deps/npm/man/man1/npm-stop.1 index 0129b04701b769..48ef025074040e 100644 --- a/deps/npm/man/man1/npm-stop.1 +++ b/deps/npm/man/man1/npm-stop.1 @@ -1,4 +1,4 @@ -.TH "NPM-STOP" "1" "February 2024" "" "" +.TH "NPM-STOP" "1" "April 2024" "" "" .SH "NAME" \fBnpm-stop\fR - Stop a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-team.1 b/deps/npm/man/man1/npm-team.1 index 61994725fea1ec..4bbed65d580c39 100644 --- a/deps/npm/man/man1/npm-team.1 +++ b/deps/npm/man/man1/npm-team.1 @@ -1,4 +1,4 @@ -.TH "NPM-TEAM" "1" "February 2024" "" "" +.TH "NPM-TEAM" "1" "April 2024" "" "" .SH "NAME" \fBnpm-team\fR - Manage organization teams and team memberships .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-test.1 b/deps/npm/man/man1/npm-test.1 index d30343b3032130..233c6db054a77c 100644 --- a/deps/npm/man/man1/npm-test.1 +++ b/deps/npm/man/man1/npm-test.1 @@ -1,4 +1,4 @@ -.TH "NPM-TEST" "1" "February 2024" "" "" +.TH "NPM-TEST" "1" "April 2024" "" "" .SH "NAME" \fBnpm-test\fR - Test a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-token.1 b/deps/npm/man/man1/npm-token.1 index 3eeb0763970b65..2b35907fb49681 100644 --- a/deps/npm/man/man1/npm-token.1 +++ b/deps/npm/man/man1/npm-token.1 @@ -1,4 +1,4 @@ -.TH "NPM-TOKEN" "1" "February 2024" "" "" +.TH "NPM-TOKEN" "1" "April 2024" "" "" .SH "NAME" \fBnpm-token\fR - Manage your authentication tokens .SS "Synopsis" @@ -23,23 +23,13 @@ This lets you list, create and revoke authentication tokens. .P .RS 2 .nf -+--------+---------+------------+----------+----------------+ -| id | token | created | read-only | CIDR whitelist | -+--------+---------+------------+----------+----------------+ -| 7f3134 | 1fa9ba… | 2017-10-02 | yes | | -+--------+---------+------------+----------+----------------+ -| c03241 | af7aef… | 2017-10-02 | no | 192.168.0.1/24 | -+--------+---------+------------+----------+----------------+ -| e0cf92 | 3a436a… | 2017-10-02 | no | | -+--------+---------+------------+----------+----------------+ -| 63eb9d | 74ef35… | 2017-09-28 | no | | -+--------+---------+------------+----------+----------------+ -| 2daaa8 | cbad5f… | 2017-09-26 | no | | -+--------+---------+------------+----------+----------------+ -| 68c2fe | 127e51… | 2017-09-23 | no | | -+--------+---------+------------+----------+----------------+ -| 6334e1 | 1dadd1… | 2017-09-23 | no | | -+--------+---------+------------+----------+----------------+ +Read only token npm_1f… with id 7f3134 created 2017-10-21 + +Publish token npm_af… with id c03241 created 2017-10-02 +with IP Whitelist: 192.168.0.1/24 + +Publish token npm_… with id e0cf92 created 2017-10-02 + .fi .RE .RS 0 @@ -52,15 +42,7 @@ Currently, the cli can not generate automation tokens. Please refer to the \fBdo .P .RS 2 .nf -+----------------+--------------------------------------+ -| token | a73c9572-f1b9-8983-983d-ba3ac3cc913d | -+----------------+--------------------------------------+ -| cidr_whitelist | | -+----------------+--------------------------------------+ -| readonly | false | -+----------------+--------------------------------------+ -| created | 2017-10-02T07:52:24.838Z | -+----------------+--------------------------------------+ +Created publish token a73c9572-f1b9-8983-983d-ba3ac3cc913d .fi .RE .RS 0 diff --git a/deps/npm/man/man1/npm-uninstall.1 b/deps/npm/man/man1/npm-uninstall.1 index 321b58fc391d6e..700037a7e1cbf8 100644 --- a/deps/npm/man/man1/npm-uninstall.1 +++ b/deps/npm/man/man1/npm-uninstall.1 @@ -1,4 +1,4 @@ -.TH "NPM-UNINSTALL" "1" "February 2024" "" "" +.TH "NPM-UNINSTALL" "1" "April 2024" "" "" .SH "NAME" \fBnpm-uninstall\fR - Remove a package .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-unpublish.1 b/deps/npm/man/man1/npm-unpublish.1 index 2cf081e01f7007..01697803cdfaf6 100644 --- a/deps/npm/man/man1/npm-unpublish.1 +++ b/deps/npm/man/man1/npm-unpublish.1 @@ -1,4 +1,4 @@ -.TH "NPM-UNPUBLISH" "1" "February 2024" "" "" +.TH "NPM-UNPUBLISH" "1" "April 2024" "" "" .SH "NAME" \fBnpm-unpublish\fR - Remove a package from the registry .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-unstar.1 b/deps/npm/man/man1/npm-unstar.1 index 700a7b3aa186b7..98a6980bd021d5 100644 --- a/deps/npm/man/man1/npm-unstar.1 +++ b/deps/npm/man/man1/npm-unstar.1 @@ -1,4 +1,4 @@ -.TH "NPM-UNSTAR" "1" "February 2024" "" "" +.TH "NPM-UNSTAR" "1" "April 2024" "" "" .SH "NAME" \fBnpm-unstar\fR - Remove an item from your favorite packages .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-update.1 b/deps/npm/man/man1/npm-update.1 index 833d3446c47899..af80d1b0e398b7 100644 --- a/deps/npm/man/man1/npm-update.1 +++ b/deps/npm/man/man1/npm-update.1 @@ -1,4 +1,4 @@ -.TH "NPM-UPDATE" "1" "February 2024" "" "" +.TH "NPM-UPDATE" "1" "April 2024" "" "" .SH "NAME" \fBnpm-update\fR - Update packages .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-version.1 b/deps/npm/man/man1/npm-version.1 index be406e39b084fe..3ec27ac0569159 100644 --- a/deps/npm/man/man1/npm-version.1 +++ b/deps/npm/man/man1/npm-version.1 @@ -1,4 +1,4 @@ -.TH "NPM-VERSION" "1" "February 2024" "" "" +.TH "NPM-VERSION" "1" "April 2024" "" "" .SH "NAME" \fBnpm-version\fR - Bump a package version .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-view.1 b/deps/npm/man/man1/npm-view.1 index 8258a85f30be75..39bf6ae8c9cc2e 100644 --- a/deps/npm/man/man1/npm-view.1 +++ b/deps/npm/man/man1/npm-view.1 @@ -1,4 +1,4 @@ -.TH "NPM-VIEW" "1" "February 2024" "" "" +.TH "NPM-VIEW" "1" "April 2024" "" "" .SH "NAME" \fBnpm-view\fR - View registry info .SS "Synopsis" diff --git a/deps/npm/man/man1/npm-whoami.1 b/deps/npm/man/man1/npm-whoami.1 index 6ac250c269fd34..7e38f165585c9a 100644 --- a/deps/npm/man/man1/npm-whoami.1 +++ b/deps/npm/man/man1/npm-whoami.1 @@ -1,4 +1,4 @@ -.TH "NPM-WHOAMI" "1" "February 2024" "" "" +.TH "NPM-WHOAMI" "1" "April 2024" "" "" .SH "NAME" \fBnpm-whoami\fR - Display npm username .SS "Synopsis" diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1 index aee40ff5bac8ff..6fb97e843320ea 100644 --- a/deps/npm/man/man1/npm.1 +++ b/deps/npm/man/man1/npm.1 @@ -1,4 +1,4 @@ -.TH "NPM" "1" "February 2024" "" "" +.TH "NPM" "1" "April 2024" "" "" .SH "NAME" \fBnpm\fR - javascript package manager .SS "Synopsis" @@ -12,7 +12,7 @@ npm Note: This command is unaware of workspaces. .SS "Version" .P -10.5.0 +10.7.0 .SS "Description" .P npm is the package manager for the Node JavaScript platform. It puts modules in place so that node can find them, and manages dependency conflicts intelligently. diff --git a/deps/npm/man/man1/npx.1 b/deps/npm/man/man1/npx.1 index 155451463a0729..0a4ff19f4bc901 100644 --- a/deps/npm/man/man1/npx.1 +++ b/deps/npm/man/man1/npx.1 @@ -1,4 +1,4 @@ -.TH "NPX" "1" "February 2024" "" "" +.TH "NPX" "1" "April 2024" "" "" .SH "NAME" \fBnpx\fR - Run a command from a local or remote npm package .SS "Synopsis" diff --git a/deps/npm/man/man5/folders.5 b/deps/npm/man/man5/folders.5 index de010820184ef4..12bda4e2881711 100644 --- a/deps/npm/man/man5/folders.5 +++ b/deps/npm/man/man5/folders.5 @@ -1,4 +1,4 @@ -.TH "FOLDERS" "5" "February 2024" "" "" +.TH "FOLDERS" "5" "April 2024" "" "" .SH "NAME" \fBfolders\fR - Folder Structures Used by npm .SS "Description" diff --git a/deps/npm/man/man5/install.5 b/deps/npm/man/man5/install.5 index 85a83de6062b8f..42e18760236ea4 100644 --- a/deps/npm/man/man5/install.5 +++ b/deps/npm/man/man5/install.5 @@ -1,4 +1,4 @@ -.TH "INSTALL" "5" "February 2024" "" "" +.TH "INSTALL" "5" "April 2024" "" "" .SH "NAME" \fBinstall\fR - Download and install node and npm .SS "Description" diff --git a/deps/npm/man/man5/npm-global.5 b/deps/npm/man/man5/npm-global.5 index de010820184ef4..12bda4e2881711 100644 --- a/deps/npm/man/man5/npm-global.5 +++ b/deps/npm/man/man5/npm-global.5 @@ -1,4 +1,4 @@ -.TH "FOLDERS" "5" "February 2024" "" "" +.TH "FOLDERS" "5" "April 2024" "" "" .SH "NAME" \fBfolders\fR - Folder Structures Used by npm .SS "Description" diff --git a/deps/npm/man/man5/npm-json.5 b/deps/npm/man/man5/npm-json.5 index 61405e54c35d70..f4d903e2b114cf 100644 --- a/deps/npm/man/man5/npm-json.5 +++ b/deps/npm/man/man5/npm-json.5 @@ -1,4 +1,4 @@ -.TH "PACKAGE.JSON" "5" "February 2024" "" "" +.TH "PACKAGE.JSON" "5" "April 2024" "" "" .SH "NAME" \fBpackage.json\fR - Specifics of npm's package.json handling .SS "Description" @@ -30,7 +30,7 @@ Some tips: .IP \(bu 4 Don't use the same name as a core Node module. .IP \(bu 4 -Don't put "js" or "node" in the name. It's assumed that it's js, since you're writing a package.json file, and you can specify the engine using the "engines" field. (See below.) +Don't put "js" or "node" in the name. It's assumed that it's js, since you're writing a package.json file, and you can specify the engine using the "\fBengines\fR \fI(engines)\fR" field. (See below.) .IP \(bu 4 The name will probably be passed as an argument to require(), so it should be something short, but also reasonably descriptive. .IP \(bu 4 @@ -52,7 +52,7 @@ Put a description in it. It's a string. This helps people discover your package, Put keywords in it. It's an array of strings. This helps people discover your package as it's listed in \fBnpm search\fR. .SS "homepage" .P -The url to the project homepage. +The URL to the project homepage. .P Example: .P @@ -63,7 +63,7 @@ Example: .RE .SS "bugs" .P -The url to your project's issue tracker and / or the email address to which issues should be reported. These are helpful for people who encounter issues with your package. +The URL to your project's issue tracker and / or the email address to which issues should be reported. These are helpful for people who encounter issues with your package. .P It should look like this: .P @@ -78,9 +78,9 @@ It should look like this: .fi .RE .P -You can specify either one or both values. If you want to provide only a url, you can specify the value for "bugs" as a simple string instead of an object. +You can specify either one or both values. If you want to provide only a URL, you can specify the value for "bugs" as a simple string instead of an object. .P -If a url is provided, it will be used by the \fBnpm bugs\fR command. +If a URL is provided, it will be used by the \fBnpm bugs\fR command. .SS "license" .P You should specify a license for your package so that people know how they are permitted to use it, and any restrictions you're placing on it. @@ -471,7 +471,7 @@ Do it like this: .fi .RE .P -The URL should be a publicly available (perhaps read-only) url that can be handed directly to a VCS program without any modification. It should not be a url to an html project page that you put in your browser. It's for computers. +The URL should be a publicly available (perhaps read-only) URL that can be handed directly to a VCS program without any modification. It should not be a URL to an html project page that you put in your browser. It's for computers. .P For GitHub, GitHub gist, Bitbucket, or GitLab repositories you can use the same shortcut syntax you use for \fBnpm install\fR: .P @@ -599,7 +599,7 @@ You may specify a tarball URL in place of a version range. This tarball will be downloaded and installed locally to your package at install time. .SS "Git URLs as Dependencies" .P -Git urls are of the form: +Git URLs are of the form: .P .RS 2 .nf @@ -644,7 +644,7 @@ This flow will occur if your git dependency uses \fBworkspaces\fR, or if any of If your git repository includes pre-built artifacts, you will likely want to make sure that none of the above scripts are defined, or your dependency will be rebuilt for every installation. .SS "GitHub URLs" .P -As of version 1.1.65, you can refer to GitHub urls as just "foo": "user/foo-project". Just as with git URLs, a \fBcommit-ish\fR suffix can be included. For example: +As of version 1.1.65, you can refer to GitHub URLs as just "foo": "user/foo-project". Just as with git URLs, a \fBcommit-ish\fR suffix can be included. For example: .P .RS 2 .nf @@ -808,7 +808,7 @@ If this is spelled \fB"bundledDependencies"\fR, then that is also honored. Alternatively, \fB"bundleDependencies"\fR can be defined as a boolean value. A value of \fBtrue\fR will bundle all dependencies, a value of \fBfalse\fR will bundle none. .SS "optionalDependencies" .P -If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the \fBoptionalDependencies\fR object. This is a map of package name to version or url, just like the \fBdependencies\fR object. The difference is that build failures do not cause installation to fail. Running \fBnpm install +If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the \fBoptionalDependencies\fR object. This is a map of package name to version or URL, just like the \fBdependencies\fR object. The difference is that build failures do not cause installation to fail. Running \fBnpm install --omit=optional\fR will prevent these dependencies from being installed. .P It is still your program's responsibility to handle the lack of the dependency. For example, something like this: @@ -840,6 +840,8 @@ If you need to make specific changes to dependencies of your dependencies, for e .P Overrides provide a way to replace a package in your dependency tree with another version, or another package entirely. These changes can be scoped as specific or as vague as desired. .P +Overrides are only considered in the root \fBpackage.json\fR file for a project. Overrides in installed dependencies (including npm help workspaces) are not considered in dependency tree resolution. Published packages may dictate their resolutions by pinning dependencies or using an \fB\fBnpm-shrinkwrap.json\fR\fR \fI\(la/configuring-npm/npm-shrinkwrap-json\(ra\fR file. +.P To make sure the package \fBfoo\fR is always installed as version \fB1.0.0\fR no matter what version your dependencies rely on: .P .RS 2 diff --git a/deps/npm/man/man5/npm-shrinkwrap-json.5 b/deps/npm/man/man5/npm-shrinkwrap-json.5 index b3abb0cc092c2a..36a4073b92ac02 100644 --- a/deps/npm/man/man5/npm-shrinkwrap-json.5 +++ b/deps/npm/man/man5/npm-shrinkwrap-json.5 @@ -1,4 +1,4 @@ -.TH "NPM-SHRINKWRAP.JSON" "5" "February 2024" "" "" +.TH "NPM-SHRINKWRAP.JSON" "5" "April 2024" "" "" .SH "NAME" \fBnpm-shrinkwrap.json\fR - A publishable lockfile .SS "Description" diff --git a/deps/npm/man/man5/npmrc.5 b/deps/npm/man/man5/npmrc.5 index c86c21b155dbd7..16543b3bc98520 100644 --- a/deps/npm/man/man5/npmrc.5 +++ b/deps/npm/man/man5/npmrc.5 @@ -1,4 +1,4 @@ -.TH "NPMRC" "5" "February 2024" "" "" +.TH "NPMRC" "5" "April 2024" "" "" .SH "NAME" \fBnpmrc\fR - The npm config files .SS "Description" diff --git a/deps/npm/man/man5/package-json.5 b/deps/npm/man/man5/package-json.5 index 61405e54c35d70..f4d903e2b114cf 100644 --- a/deps/npm/man/man5/package-json.5 +++ b/deps/npm/man/man5/package-json.5 @@ -1,4 +1,4 @@ -.TH "PACKAGE.JSON" "5" "February 2024" "" "" +.TH "PACKAGE.JSON" "5" "April 2024" "" "" .SH "NAME" \fBpackage.json\fR - Specifics of npm's package.json handling .SS "Description" @@ -30,7 +30,7 @@ Some tips: .IP \(bu 4 Don't use the same name as a core Node module. .IP \(bu 4 -Don't put "js" or "node" in the name. It's assumed that it's js, since you're writing a package.json file, and you can specify the engine using the "engines" field. (See below.) +Don't put "js" or "node" in the name. It's assumed that it's js, since you're writing a package.json file, and you can specify the engine using the "\fBengines\fR \fI(engines)\fR" field. (See below.) .IP \(bu 4 The name will probably be passed as an argument to require(), so it should be something short, but also reasonably descriptive. .IP \(bu 4 @@ -52,7 +52,7 @@ Put a description in it. It's a string. This helps people discover your package, Put keywords in it. It's an array of strings. This helps people discover your package as it's listed in \fBnpm search\fR. .SS "homepage" .P -The url to the project homepage. +The URL to the project homepage. .P Example: .P @@ -63,7 +63,7 @@ Example: .RE .SS "bugs" .P -The url to your project's issue tracker and / or the email address to which issues should be reported. These are helpful for people who encounter issues with your package. +The URL to your project's issue tracker and / or the email address to which issues should be reported. These are helpful for people who encounter issues with your package. .P It should look like this: .P @@ -78,9 +78,9 @@ It should look like this: .fi .RE .P -You can specify either one or both values. If you want to provide only a url, you can specify the value for "bugs" as a simple string instead of an object. +You can specify either one or both values. If you want to provide only a URL, you can specify the value for "bugs" as a simple string instead of an object. .P -If a url is provided, it will be used by the \fBnpm bugs\fR command. +If a URL is provided, it will be used by the \fBnpm bugs\fR command. .SS "license" .P You should specify a license for your package so that people know how they are permitted to use it, and any restrictions you're placing on it. @@ -471,7 +471,7 @@ Do it like this: .fi .RE .P -The URL should be a publicly available (perhaps read-only) url that can be handed directly to a VCS program without any modification. It should not be a url to an html project page that you put in your browser. It's for computers. +The URL should be a publicly available (perhaps read-only) URL that can be handed directly to a VCS program without any modification. It should not be a URL to an html project page that you put in your browser. It's for computers. .P For GitHub, GitHub gist, Bitbucket, or GitLab repositories you can use the same shortcut syntax you use for \fBnpm install\fR: .P @@ -599,7 +599,7 @@ You may specify a tarball URL in place of a version range. This tarball will be downloaded and installed locally to your package at install time. .SS "Git URLs as Dependencies" .P -Git urls are of the form: +Git URLs are of the form: .P .RS 2 .nf @@ -644,7 +644,7 @@ This flow will occur if your git dependency uses \fBworkspaces\fR, or if any of If your git repository includes pre-built artifacts, you will likely want to make sure that none of the above scripts are defined, or your dependency will be rebuilt for every installation. .SS "GitHub URLs" .P -As of version 1.1.65, you can refer to GitHub urls as just "foo": "user/foo-project". Just as with git URLs, a \fBcommit-ish\fR suffix can be included. For example: +As of version 1.1.65, you can refer to GitHub URLs as just "foo": "user/foo-project". Just as with git URLs, a \fBcommit-ish\fR suffix can be included. For example: .P .RS 2 .nf @@ -808,7 +808,7 @@ If this is spelled \fB"bundledDependencies"\fR, then that is also honored. Alternatively, \fB"bundleDependencies"\fR can be defined as a boolean value. A value of \fBtrue\fR will bundle all dependencies, a value of \fBfalse\fR will bundle none. .SS "optionalDependencies" .P -If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the \fBoptionalDependencies\fR object. This is a map of package name to version or url, just like the \fBdependencies\fR object. The difference is that build failures do not cause installation to fail. Running \fBnpm install +If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the \fBoptionalDependencies\fR object. This is a map of package name to version or URL, just like the \fBdependencies\fR object. The difference is that build failures do not cause installation to fail. Running \fBnpm install --omit=optional\fR will prevent these dependencies from being installed. .P It is still your program's responsibility to handle the lack of the dependency. For example, something like this: @@ -840,6 +840,8 @@ If you need to make specific changes to dependencies of your dependencies, for e .P Overrides provide a way to replace a package in your dependency tree with another version, or another package entirely. These changes can be scoped as specific or as vague as desired. .P +Overrides are only considered in the root \fBpackage.json\fR file for a project. Overrides in installed dependencies (including npm help workspaces) are not considered in dependency tree resolution. Published packages may dictate their resolutions by pinning dependencies or using an \fB\fBnpm-shrinkwrap.json\fR\fR \fI\(la/configuring-npm/npm-shrinkwrap-json\(ra\fR file. +.P To make sure the package \fBfoo\fR is always installed as version \fB1.0.0\fR no matter what version your dependencies rely on: .P .RS 2 diff --git a/deps/npm/man/man5/package-lock-json.5 b/deps/npm/man/man5/package-lock-json.5 index ceea2b43da89e2..c6a92af27f189c 100644 --- a/deps/npm/man/man5/package-lock-json.5 +++ b/deps/npm/man/man5/package-lock-json.5 @@ -1,4 +1,4 @@ -.TH "PACKAGE-LOCK.JSON" "5" "February 2024" "" "" +.TH "PACKAGE-LOCK.JSON" "5" "April 2024" "" "" .SH "NAME" \fBpackage-lock.json\fR - A manifestation of the manifest .SS "Description" @@ -19,6 +19,8 @@ Optimize the installation process by allowing npm to skip repeated metadata reso As of npm v7, lockfiles include enough information to gain a complete picture of the package tree, reducing the need to read \fBpackage.json\fR files, and allowing for significant performance improvements. .RE 0 +.P +When \fBnpm\fR creates or updates \fBpackage-lock.json\fR, it will infer line endings and indentation from \fBpackage.json\fR so that the formatting of both files matches. .SS "\fBpackage-lock.json\fR vs \fBnpm-shrinkwrap.json\fR" .P Both of these files have the same format, and perform similar functions in the root of a project. diff --git a/deps/npm/man/man7/config.7 b/deps/npm/man/man7/config.7 index 181a7d6a469a9e..ffbf3e50537e37 100644 --- a/deps/npm/man/man7/config.7 +++ b/deps/npm/man/man7/config.7 @@ -1,4 +1,4 @@ -.TH "CONFIG" "7" "February 2024" "" "" +.TH "CONFIG" "7" "April 2024" "" "" .SH "NAME" \fBconfig\fR - More than you probably want to know about npm configuration .SS "Description" diff --git a/deps/npm/man/man7/dependency-selectors.7 b/deps/npm/man/man7/dependency-selectors.7 index 78f451177e3172..588989321c6ad1 100644 --- a/deps/npm/man/man7/dependency-selectors.7 +++ b/deps/npm/man/man7/dependency-selectors.7 @@ -1,4 +1,4 @@ -.TH "QUERYING" "7" "February 2024" "" "" +.TH "QUERYING" "7" "April 2024" "" "" .SH "NAME" \fBQuerying\fR - Dependency Selector Syntax & Querying .SS "Description" diff --git a/deps/npm/man/man7/developers.7 b/deps/npm/man/man7/developers.7 index 8dd07548d9b873..a69fcc052a6da0 100644 --- a/deps/npm/man/man7/developers.7 +++ b/deps/npm/man/man7/developers.7 @@ -1,4 +1,4 @@ -.TH "DEVELOPERS" "7" "February 2024" "" "" +.TH "DEVELOPERS" "7" "April 2024" "" "" .SH "NAME" \fBdevelopers\fR - Developer Guide .SS "Description" diff --git a/deps/npm/man/man7/logging.7 b/deps/npm/man/man7/logging.7 index b85fb4c47cfcdc..dfbed85ffbb07f 100644 --- a/deps/npm/man/man7/logging.7 +++ b/deps/npm/man/man7/logging.7 @@ -1,4 +1,4 @@ -.TH "LOGGING" "7" "February 2024" "" "" +.TH "LOGGING" "7" "April 2024" "" "" .SH "NAME" \fBLogging\fR - Why, What & How We Log .SS "Description" diff --git a/deps/npm/man/man7/orgs.7 b/deps/npm/man/man7/orgs.7 index 36850dd961897d..181693d04032d7 100644 --- a/deps/npm/man/man7/orgs.7 +++ b/deps/npm/man/man7/orgs.7 @@ -1,4 +1,4 @@ -.TH "ORGS" "7" "February 2024" "" "" +.TH "ORGS" "7" "April 2024" "" "" .SH "NAME" \fBorgs\fR - Working with Teams & Orgs .SS "Description" diff --git a/deps/npm/man/man7/package-spec.7 b/deps/npm/man/man7/package-spec.7 index c9d309ccbbdbe0..167a6915218b94 100644 --- a/deps/npm/man/man7/package-spec.7 +++ b/deps/npm/man/man7/package-spec.7 @@ -1,4 +1,4 @@ -.TH "PACKAGE-SPEC" "7" "February 2024" "" "" +.TH "PACKAGE-SPEC" "7" "April 2024" "" "" .SH "NAME" \fBpackage-spec\fR - Package name specifier .SS "Description" diff --git a/deps/npm/man/man7/registry.7 b/deps/npm/man/man7/registry.7 index c0e4474c09010e..73f17929c427aa 100644 --- a/deps/npm/man/man7/registry.7 +++ b/deps/npm/man/man7/registry.7 @@ -1,4 +1,4 @@ -.TH "REGISTRY" "7" "February 2024" "" "" +.TH "REGISTRY" "7" "April 2024" "" "" .SH "NAME" \fBregistry\fR - The JavaScript Package Registry .SS "Description" diff --git a/deps/npm/man/man7/removal.7 b/deps/npm/man/man7/removal.7 index a846bcca25ffd3..9b091566aaf453 100644 --- a/deps/npm/man/man7/removal.7 +++ b/deps/npm/man/man7/removal.7 @@ -1,4 +1,4 @@ -.TH "REMOVAL" "7" "February 2024" "" "" +.TH "REMOVAL" "7" "April 2024" "" "" .SH "NAME" \fBremoval\fR - Cleaning the Slate .SS "Synopsis" diff --git a/deps/npm/man/man7/scope.7 b/deps/npm/man/man7/scope.7 index eb6fe9b6d822e9..437a4df173394e 100644 --- a/deps/npm/man/man7/scope.7 +++ b/deps/npm/man/man7/scope.7 @@ -1,4 +1,4 @@ -.TH "SCOPE" "7" "February 2024" "" "" +.TH "SCOPE" "7" "April 2024" "" "" .SH "NAME" \fBscope\fR - Scoped packages .SS "Description" diff --git a/deps/npm/man/man7/scripts.7 b/deps/npm/man/man7/scripts.7 index e88a9c4e69519f..b051216d26213e 100644 --- a/deps/npm/man/man7/scripts.7 +++ b/deps/npm/man/man7/scripts.7 @@ -1,4 +1,4 @@ -.TH "SCRIPTS" "7" "February 2024" "" "" +.TH "SCRIPTS" "7" "April 2024" "" "" .SH "NAME" \fBscripts\fR - How npm handles the "scripts" field .SS "Description" diff --git a/deps/npm/man/man7/workspaces.7 b/deps/npm/man/man7/workspaces.7 index 9db114e4ded21b..78242b33b18c7b 100644 --- a/deps/npm/man/man7/workspaces.7 +++ b/deps/npm/man/man7/workspaces.7 @@ -1,4 +1,4 @@ -.TH "WORKSPACES" "7" "February 2024" "" "" +.TH "WORKSPACES" "7" "April 2024" "" "" .SH "NAME" \fBworkspaces\fR - Working with workspaces .SS "Description" diff --git a/deps/npm/node_modules/@colors/colors/LICENSE b/deps/npm/node_modules/@colors/colors/LICENSE deleted file mode 100644 index 6b86056199d2ac..00000000000000 --- a/deps/npm/node_modules/@colors/colors/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -MIT License - -Original Library - - Copyright (c) Marak Squires - -Additional Functionality - - Copyright (c) Sindre Sorhus (sindresorhus.com) - - Copyright (c) DABH (https://github.com/DABH) - -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. diff --git a/deps/npm/node_modules/@colors/colors/examples/normal-usage.js b/deps/npm/node_modules/@colors/colors/examples/normal-usage.js deleted file mode 100644 index c4515653e288d7..00000000000000 --- a/deps/npm/node_modules/@colors/colors/examples/normal-usage.js +++ /dev/null @@ -1,82 +0,0 @@ -var colors = require('../lib/index'); - -console.log('First some yellow text'.yellow); - -console.log('Underline that text'.yellow.underline); - -console.log('Make it bold and red'.red.bold); - -console.log(('Double Raindows All Day Long').rainbow); - -console.log('Drop the bass'.trap); - -console.log('DROP THE RAINBOW BASS'.trap.rainbow); - -// styles not widely supported -console.log('Chains are also cool.'.bold.italic.underline.red); - -// styles not widely supported -console.log('So '.green + 'are'.underline + ' ' + 'inverse'.inverse - + ' styles! '.yellow.bold); -console.log('Zebras are so fun!'.zebra); - -// -// Remark: .strikethrough may not work with Mac OS Terminal App -// -console.log('This is ' + 'not'.strikethrough + ' fun.'); - -console.log('Background color attack!'.black.bgWhite); -console.log('Use random styles on everything!'.random); -console.log('America, Heck Yeah!'.america); - -// eslint-disable-next-line max-len -console.log('Blindingly '.brightCyan + 'bright? '.brightRed + 'Why '.brightYellow + 'not?!'.brightGreen); - -console.log('Setting themes is useful'); - -// -// Custom themes -// -console.log('Generic logging theme as JSON'.green.bold.underline); -// Load theme with JSON literal -colors.setTheme({ - silly: 'rainbow', - input: 'grey', - verbose: 'cyan', - prompt: 'grey', - info: 'green', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red', -}); - -// outputs red text -console.log('this is an error'.error); - -// outputs yellow text -console.log('this is a warning'.warn); - -// outputs grey text -console.log('this is an input'.input); - -console.log('Generic logging theme as file'.green.bold.underline); - -// Load a theme from file -try { - colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); -} catch (err) { - console.log(err); -} - -// outputs red text -console.log('this is an error'.error); - -// outputs yellow text -console.log('this is a warning'.warn); - -// outputs grey text -console.log('this is an input'.input); - -// console.log("Don't summon".zalgo) diff --git a/deps/npm/node_modules/@colors/colors/examples/safe-string.js b/deps/npm/node_modules/@colors/colors/examples/safe-string.js deleted file mode 100644 index ed5f4ca468e10f..00000000000000 --- a/deps/npm/node_modules/@colors/colors/examples/safe-string.js +++ /dev/null @@ -1,78 +0,0 @@ -var colors = require('../safe'); - -console.log(colors.yellow('First some yellow text')); - -console.log(colors.yellow.underline('Underline that text')); - -console.log(colors.red.bold('Make it bold and red')); - -console.log(colors.rainbow('Double Raindows All Day Long')); - -console.log(colors.trap('Drop the bass')); - -console.log(colors.rainbow(colors.trap('DROP THE RAINBOW BASS'))); - -// styles not widely supported -console.log(colors.bold.italic.underline.red('Chains are also cool.')); - -// styles not widely supported -console.log(colors.green('So ') + colors.underline('are') + ' ' - + colors.inverse('inverse') + colors.yellow.bold(' styles! ')); - -console.log(colors.zebra('Zebras are so fun!')); - -console.log('This is ' + colors.strikethrough('not') + ' fun.'); - - -console.log(colors.black.bgWhite('Background color attack!')); -console.log(colors.random('Use random styles on everything!')); -console.log(colors.america('America, Heck Yeah!')); - -// eslint-disable-next-line max-len -console.log(colors.brightCyan('Blindingly ') + colors.brightRed('bright? ') + colors.brightYellow('Why ') + colors.brightGreen('not?!')); - -console.log('Setting themes is useful'); - -// -// Custom themes -// -// console.log('Generic logging theme as JSON'.green.bold.underline); -// Load theme with JSON literal -colors.setTheme({ - silly: 'rainbow', - input: 'blue', - verbose: 'cyan', - prompt: 'grey', - info: 'green', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red', -}); - -// outputs red text -console.log(colors.error('this is an error')); - -// outputs yellow text -console.log(colors.warn('this is a warning')); - -// outputs blue text -console.log(colors.input('this is an input')); - - -// console.log('Generic logging theme as file'.green.bold.underline); - -// Load a theme from file -colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); - -// outputs red text -console.log(colors.error('this is an error')); - -// outputs yellow text -console.log(colors.warn('this is a warning')); - -// outputs grey text -console.log(colors.input('this is an input')); - -// console.log(colors.zalgo("Don't summon him")) diff --git a/deps/npm/node_modules/@colors/colors/lib/colors.js b/deps/npm/node_modules/@colors/colors/lib/colors.js deleted file mode 100644 index d9fb08762fde51..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/colors.js +++ /dev/null @@ -1,211 +0,0 @@ -/* - -The MIT License (MIT) - -Original Library - - Copyright (c) Marak Squires - -Additional functionality - - Copyright (c) Sindre Sorhus (sindresorhus.com) - -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. - -*/ - -var colors = {}; -module['exports'] = colors; - -colors.themes = {}; - -var util = require('util'); -var ansiStyles = colors.styles = require('./styles'); -var defineProps = Object.defineProperties; -var newLineRegex = new RegExp(/[\r\n]+/g); - -colors.supportsColor = require('./system/supports-colors').supportsColor; - -if (typeof colors.enabled === 'undefined') { - colors.enabled = colors.supportsColor() !== false; -} - -colors.enable = function() { - colors.enabled = true; -}; - -colors.disable = function() { - colors.enabled = false; -}; - -colors.stripColors = colors.strip = function(str) { - return ('' + str).replace(/\x1B\[\d+m/g, ''); -}; - -// eslint-disable-next-line no-unused-vars -var stylize = colors.stylize = function stylize(str, style) { - if (!colors.enabled) { - return str+''; - } - - var styleMap = ansiStyles[style]; - - // Stylize should work for non-ANSI styles, too - if (!styleMap && style in colors) { - // Style maps like trap operate as functions on strings; - // they don't have properties like open or close. - return colors[style](str); - } - - return styleMap.open + str + styleMap.close; -}; - -var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; -var escapeStringRegexp = function(str) { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); - } - return str.replace(matchOperatorsRe, '\\$&'); -}; - -function build(_styles) { - var builder = function builder() { - return applyStyle.apply(builder, arguments); - }; - builder._styles = _styles; - // __proto__ is used because we must return a function, but there is - // no way to create a function with a different prototype. - builder.__proto__ = proto; - return builder; -} - -var styles = (function() { - var ret = {}; - ansiStyles.grey = ansiStyles.gray; - Object.keys(ansiStyles).forEach(function(key) { - ansiStyles[key].closeRe = - new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); - ret[key] = { - get: function() { - return build(this._styles.concat(key)); - }, - }; - }); - return ret; -})(); - -var proto = defineProps(function colors() {}, styles); - -function applyStyle() { - var args = Array.prototype.slice.call(arguments); - - var str = args.map(function(arg) { - // Use weak equality check so we can colorize null/undefined in safe mode - if (arg != null && arg.constructor === String) { - return arg; - } else { - return util.inspect(arg); - } - }).join(' '); - - if (!colors.enabled || !str) { - return str; - } - - var newLinesPresent = str.indexOf('\n') != -1; - - var nestedStyles = this._styles; - - var i = nestedStyles.length; - while (i--) { - var code = ansiStyles[nestedStyles[i]]; - str = code.open + str.replace(code.closeRe, code.open) + code.close; - if (newLinesPresent) { - str = str.replace(newLineRegex, function(match) { - return code.close + match + code.open; - }); - } - } - - return str; -} - -colors.setTheme = function(theme) { - if (typeof theme === 'string') { - console.log('colors.setTheme now only accepts an object, not a string. ' + - 'If you are trying to set a theme from a file, it is now your (the ' + - 'caller\'s) responsibility to require the file. The old syntax ' + - 'looked like colors.setTheme(__dirname + ' + - '\'/../themes/generic-logging.js\'); The new syntax looks like '+ - 'colors.setTheme(require(__dirname + ' + - '\'/../themes/generic-logging.js\'));'); - return; - } - for (var style in theme) { - (function(style) { - colors[style] = function(str) { - if (typeof theme[style] === 'object') { - var out = str; - for (var i in theme[style]) { - out = colors[theme[style][i]](out); - } - return out; - } - return colors[theme[style]](str); - }; - })(style); - } -}; - -function init() { - var ret = {}; - Object.keys(styles).forEach(function(name) { - ret[name] = { - get: function() { - return build([name]); - }, - }; - }); - return ret; -} - -var sequencer = function sequencer(map, str) { - var exploded = str.split(''); - exploded = exploded.map(map); - return exploded.join(''); -}; - -// custom formatter methods -colors.trap = require('./custom/trap'); -colors.zalgo = require('./custom/zalgo'); - -// maps -colors.maps = {}; -colors.maps.america = require('./maps/america')(colors); -colors.maps.zebra = require('./maps/zebra')(colors); -colors.maps.rainbow = require('./maps/rainbow')(colors); -colors.maps.random = require('./maps/random')(colors); - -for (var map in colors.maps) { - (function(map) { - colors[map] = function(str) { - return sequencer(colors.maps[map], str); - }; - })(map); -} - -defineProps(colors, init()); diff --git a/deps/npm/node_modules/@colors/colors/lib/custom/trap.js b/deps/npm/node_modules/@colors/colors/lib/custom/trap.js deleted file mode 100644 index fbccf88dede0b8..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/custom/trap.js +++ /dev/null @@ -1,46 +0,0 @@ -module['exports'] = function runTheTrap(text, options) { - var result = ''; - text = text || 'Run the trap, drop the bass'; - text = text.split(''); - var trap = { - a: ['\u0040', '\u0104', '\u023a', '\u0245', '\u0394', '\u039b', '\u0414'], - b: ['\u00df', '\u0181', '\u0243', '\u026e', '\u03b2', '\u0e3f'], - c: ['\u00a9', '\u023b', '\u03fe'], - d: ['\u00d0', '\u018a', '\u0500', '\u0501', '\u0502', '\u0503'], - e: ['\u00cb', '\u0115', '\u018e', '\u0258', '\u03a3', '\u03be', '\u04bc', - '\u0a6c'], - f: ['\u04fa'], - g: ['\u0262'], - h: ['\u0126', '\u0195', '\u04a2', '\u04ba', '\u04c7', '\u050a'], - i: ['\u0f0f'], - j: ['\u0134'], - k: ['\u0138', '\u04a0', '\u04c3', '\u051e'], - l: ['\u0139'], - m: ['\u028d', '\u04cd', '\u04ce', '\u0520', '\u0521', '\u0d69'], - n: ['\u00d1', '\u014b', '\u019d', '\u0376', '\u03a0', '\u048a'], - o: ['\u00d8', '\u00f5', '\u00f8', '\u01fe', '\u0298', '\u047a', '\u05dd', - '\u06dd', '\u0e4f'], - p: ['\u01f7', '\u048e'], - q: ['\u09cd'], - r: ['\u00ae', '\u01a6', '\u0210', '\u024c', '\u0280', '\u042f'], - s: ['\u00a7', '\u03de', '\u03df', '\u03e8'], - t: ['\u0141', '\u0166', '\u0373'], - u: ['\u01b1', '\u054d'], - v: ['\u05d8'], - w: ['\u0428', '\u0460', '\u047c', '\u0d70'], - x: ['\u04b2', '\u04fe', '\u04fc', '\u04fd'], - y: ['\u00a5', '\u04b0', '\u04cb'], - z: ['\u01b5', '\u0240'], - }; - text.forEach(function(c) { - c = c.toLowerCase(); - var chars = trap[c] || [' ']; - var rand = Math.floor(Math.random() * chars.length); - if (typeof trap[c] !== 'undefined') { - result += trap[c][rand]; - } else { - result += c; - } - }); - return result; -}; diff --git a/deps/npm/node_modules/@colors/colors/lib/custom/zalgo.js b/deps/npm/node_modules/@colors/colors/lib/custom/zalgo.js deleted file mode 100644 index 01bdd2b802f626..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/custom/zalgo.js +++ /dev/null @@ -1,109 +0,0 @@ -// please no -module['exports'] = function zalgo(text, options) { - text = text || ' he is here '; - var soul = { - 'up': [ - '̍', '̎', '̄', '̅', - '̿', '̑', '̆', '̐', - '͒', '͗', '͑', '̇', - '̈', '̊', '͂', '̓', - '̈', '͊', '͋', '͌', - '̃', '̂', '̌', '͐', - '̀', '́', '̋', '̏', - '̒', '̓', '̔', '̽', - '̉', 'ͣ', 'ͤ', 'ͥ', - 'ͦ', 'ͧ', 'ͨ', 'ͩ', - 'ͪ', 'ͫ', 'ͬ', 'ͭ', - 'ͮ', 'ͯ', '̾', '͛', - '͆', '̚', - ], - 'down': [ - '̖', '̗', '̘', '̙', - '̜', '̝', '̞', '̟', - '̠', '̤', '̥', '̦', - '̩', '̪', '̫', '̬', - '̭', '̮', '̯', '̰', - '̱', '̲', '̳', '̹', - '̺', '̻', '̼', 'ͅ', - '͇', '͈', '͉', '͍', - '͎', '͓', '͔', '͕', - '͖', '͙', '͚', '̣', - ], - 'mid': [ - '̕', '̛', '̀', '́', - '͘', '̡', '̢', '̧', - '̨', '̴', '̵', '̶', - '͜', '͝', '͞', - '͟', '͠', '͢', '̸', - '̷', '͡', ' ҉', - ], - }; - var all = [].concat(soul.up, soul.down, soul.mid); - - function randomNumber(range) { - var r = Math.floor(Math.random() * range); - return r; - } - - function isChar(character) { - var bool = false; - all.filter(function(i) { - bool = (i === character); - }); - return bool; - } - - - function heComes(text, options) { - var result = ''; - var counts; - var l; - options = options || {}; - options['up'] = - typeof options['up'] !== 'undefined' ? options['up'] : true; - options['mid'] = - typeof options['mid'] !== 'undefined' ? options['mid'] : true; - options['down'] = - typeof options['down'] !== 'undefined' ? options['down'] : true; - options['size'] = - typeof options['size'] !== 'undefined' ? options['size'] : 'maxi'; - text = text.split(''); - for (l in text) { - if (isChar(l)) { - continue; - } - result = result + text[l]; - counts = {'up': 0, 'down': 0, 'mid': 0}; - switch (options.size) { - case 'mini': - counts.up = randomNumber(8); - counts.mid = randomNumber(2); - counts.down = randomNumber(8); - break; - case 'maxi': - counts.up = randomNumber(16) + 3; - counts.mid = randomNumber(4) + 1; - counts.down = randomNumber(64) + 3; - break; - default: - counts.up = randomNumber(8) + 1; - counts.mid = randomNumber(6) / 2; - counts.down = randomNumber(8) + 1; - break; - } - - var arr = ['up', 'mid', 'down']; - for (var d in arr) { - var index = arr[d]; - for (var i = 0; i <= counts[index]; i++) { - if (options[index]) { - result = result + soul[index][randomNumber(soul[index].length)]; - } - } - } - } - return result; - } - // don't summon him - return heComes(text, options); -}; diff --git a/deps/npm/node_modules/@colors/colors/lib/extendStringPrototype.js b/deps/npm/node_modules/@colors/colors/lib/extendStringPrototype.js deleted file mode 100644 index 46fd386a915a67..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/extendStringPrototype.js +++ /dev/null @@ -1,110 +0,0 @@ -var colors = require('./colors'); - -module['exports'] = function() { - // - // Extends prototype of native string object to allow for "foo".red syntax - // - var addProperty = function(color, func) { - String.prototype.__defineGetter__(color, func); - }; - - addProperty('strip', function() { - return colors.strip(this); - }); - - addProperty('stripColors', function() { - return colors.strip(this); - }); - - addProperty('trap', function() { - return colors.trap(this); - }); - - addProperty('zalgo', function() { - return colors.zalgo(this); - }); - - addProperty('zebra', function() { - return colors.zebra(this); - }); - - addProperty('rainbow', function() { - return colors.rainbow(this); - }); - - addProperty('random', function() { - return colors.random(this); - }); - - addProperty('america', function() { - return colors.america(this); - }); - - // - // Iterate through all default styles and colors - // - var x = Object.keys(colors.styles); - x.forEach(function(style) { - addProperty(style, function() { - return colors.stylize(this, style); - }); - }); - - function applyTheme(theme) { - // - // Remark: This is a list of methods that exist - // on String that you should not overwrite. - // - var stringPrototypeBlacklist = [ - '__defineGetter__', '__defineSetter__', '__lookupGetter__', - '__lookupSetter__', 'charAt', 'constructor', 'hasOwnProperty', - 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', - 'valueOf', 'charCodeAt', 'indexOf', 'lastIndexOf', 'length', - 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', - 'split', 'substring', 'toLocaleLowerCase', 'toLocaleUpperCase', - 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', - ]; - - Object.keys(theme).forEach(function(prop) { - if (stringPrototypeBlacklist.indexOf(prop) !== -1) { - console.log('warn: '.red + ('String.prototype' + prop).magenta + - ' is probably something you don\'t want to override. ' + - 'Ignoring style name'); - } else { - if (typeof(theme[prop]) === 'string') { - colors[prop] = colors[theme[prop]]; - addProperty(prop, function() { - return colors[prop](this); - }); - } else { - var themePropApplicator = function(str) { - var ret = str || this; - for (var t = 0; t < theme[prop].length; t++) { - ret = colors[theme[prop][t]](ret); - } - return ret; - }; - addProperty(prop, themePropApplicator); - colors[prop] = function(str) { - return themePropApplicator(str); - }; - } - } - }); - } - - colors.setTheme = function(theme) { - if (typeof theme === 'string') { - console.log('colors.setTheme now only accepts an object, not a string. ' + - 'If you are trying to set a theme from a file, it is now your (the ' + - 'caller\'s) responsibility to require the file. The old syntax ' + - 'looked like colors.setTheme(__dirname + ' + - '\'/../themes/generic-logging.js\'); The new syntax looks like '+ - 'colors.setTheme(require(__dirname + ' + - '\'/../themes/generic-logging.js\'));'); - return; - } else { - applyTheme(theme); - } - }; -}; diff --git a/deps/npm/node_modules/@colors/colors/lib/index.js b/deps/npm/node_modules/@colors/colors/lib/index.js deleted file mode 100644 index 9df5ab7df30770..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/index.js +++ /dev/null @@ -1,13 +0,0 @@ -var colors = require('./colors'); -module['exports'] = colors; - -// Remark: By default, colors will add style properties to String.prototype. -// -// If you don't wish to extend String.prototype, you can do this instead and -// native String will not be touched: -// -// var colors = require('colors/safe); -// colors.red("foo") -// -// -require('./extendStringPrototype')(); diff --git a/deps/npm/node_modules/@colors/colors/lib/maps/america.js b/deps/npm/node_modules/@colors/colors/lib/maps/america.js deleted file mode 100644 index dc96903328989f..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/maps/america.js +++ /dev/null @@ -1,10 +0,0 @@ -module['exports'] = function(colors) { - return function(letter, i, exploded) { - if (letter === ' ') return letter; - switch (i%3) { - case 0: return colors.red(letter); - case 1: return colors.white(letter); - case 2: return colors.blue(letter); - } - }; -}; diff --git a/deps/npm/node_modules/@colors/colors/lib/maps/rainbow.js b/deps/npm/node_modules/@colors/colors/lib/maps/rainbow.js deleted file mode 100644 index 874508da8ed17e..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/maps/rainbow.js +++ /dev/null @@ -1,11 +0,0 @@ -module['exports'] = function(colors) { - // RoY G BiV - var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; - return function(letter, i, exploded) { - if (letter === ' ') { - return letter; - } else { - return colors[rainbowColors[i++ % rainbowColors.length]](letter); - } - }; -}; diff --git a/deps/npm/node_modules/@colors/colors/lib/maps/random.js b/deps/npm/node_modules/@colors/colors/lib/maps/random.js deleted file mode 100644 index 3d82a39ec0fab4..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/maps/random.js +++ /dev/null @@ -1,11 +0,0 @@ -module['exports'] = function(colors) { - var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green', - 'blue', 'white', 'cyan', 'magenta', 'brightYellow', 'brightRed', - 'brightGreen', 'brightBlue', 'brightWhite', 'brightCyan', 'brightMagenta']; - return function(letter, i, exploded) { - return letter === ' ' ? letter : - colors[ - available[Math.round(Math.random() * (available.length - 2))] - ](letter); - }; -}; diff --git a/deps/npm/node_modules/@colors/colors/lib/maps/zebra.js b/deps/npm/node_modules/@colors/colors/lib/maps/zebra.js deleted file mode 100644 index fa73623544a82c..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/maps/zebra.js +++ /dev/null @@ -1,5 +0,0 @@ -module['exports'] = function(colors) { - return function(letter, i, exploded) { - return i % 2 === 0 ? letter : colors.inverse(letter); - }; -}; diff --git a/deps/npm/node_modules/@colors/colors/lib/styles.js b/deps/npm/node_modules/@colors/colors/lib/styles.js deleted file mode 100644 index 011dafd8c28f70..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/styles.js +++ /dev/null @@ -1,95 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -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. - -*/ - -var styles = {}; -module['exports'] = styles; - -var codes = { - reset: [0, 0], - - bold: [1, 22], - dim: [2, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - hidden: [8, 28], - strikethrough: [9, 29], - - black: [30, 39], - red: [31, 39], - green: [32, 39], - yellow: [33, 39], - blue: [34, 39], - magenta: [35, 39], - cyan: [36, 39], - white: [37, 39], - gray: [90, 39], - grey: [90, 39], - - brightRed: [91, 39], - brightGreen: [92, 39], - brightYellow: [93, 39], - brightBlue: [94, 39], - brightMagenta: [95, 39], - brightCyan: [96, 39], - brightWhite: [97, 39], - - bgBlack: [40, 49], - bgRed: [41, 49], - bgGreen: [42, 49], - bgYellow: [43, 49], - bgBlue: [44, 49], - bgMagenta: [45, 49], - bgCyan: [46, 49], - bgWhite: [47, 49], - bgGray: [100, 49], - bgGrey: [100, 49], - - bgBrightRed: [101, 49], - bgBrightGreen: [102, 49], - bgBrightYellow: [103, 49], - bgBrightBlue: [104, 49], - bgBrightMagenta: [105, 49], - bgBrightCyan: [106, 49], - bgBrightWhite: [107, 49], - - // legacy styles for colors pre v1.0.0 - blackBG: [40, 49], - redBG: [41, 49], - greenBG: [42, 49], - yellowBG: [43, 49], - blueBG: [44, 49], - magentaBG: [45, 49], - cyanBG: [46, 49], - whiteBG: [47, 49], - -}; - -Object.keys(codes).forEach(function(key) { - var val = codes[key]; - var style = styles[key] = []; - style.open = '\u001b[' + val[0] + 'm'; - style.close = '\u001b[' + val[1] + 'm'; -}); diff --git a/deps/npm/node_modules/@colors/colors/lib/system/has-flag.js b/deps/npm/node_modules/@colors/colors/lib/system/has-flag.js deleted file mode 100644 index a347dd4d7a697e..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/system/has-flag.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -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. -*/ - -'use strict'; - -module.exports = function(flag, argv) { - argv = argv || process.argv; - - var terminatorPos = argv.indexOf('--'); - var prefix = /^-{1,2}/.test(flag) ? '' : '--'; - var pos = argv.indexOf(prefix + flag); - - return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); -}; diff --git a/deps/npm/node_modules/@colors/colors/lib/system/supports-colors.js b/deps/npm/node_modules/@colors/colors/lib/system/supports-colors.js deleted file mode 100644 index f1f9c8ff3da284..00000000000000 --- a/deps/npm/node_modules/@colors/colors/lib/system/supports-colors.js +++ /dev/null @@ -1,151 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -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. - -*/ - -'use strict'; - -var os = require('os'); -var hasFlag = require('./has-flag.js'); - -var env = process.env; - -var forceColor = void 0; -if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) { - forceColor = false; -} else if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true') - || hasFlag('color=always')) { - forceColor = true; -} -if ('FORCE_COLOR' in env) { - forceColor = env.FORCE_COLOR.length === 0 - || parseInt(env.FORCE_COLOR, 10) !== 0; -} - -function translateLevel(level) { - if (level === 0) { - return false; - } - - return { - level: level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3, - }; -} - -function supportsColor(stream) { - if (forceColor === false) { - return 0; - } - - if (hasFlag('color=16m') || hasFlag('color=full') - || hasFlag('color=truecolor')) { - return 3; - } - - if (hasFlag('color=256')) { - return 2; - } - - if (stream && !stream.isTTY && forceColor !== true) { - return 0; - } - - var min = forceColor ? 1 : 0; - - if (process.platform === 'win32') { - // Node.js 7.5.0 is the first version of Node.js to include a patch to - // libuv that enables 256 color output on Windows. Anything earlier and it - // won't work. However, here we target Node.js 8 at minimum as it is an LTS - // release, and Node.js 7 is not. Windows 10 build 10586 is the first - // Windows release that supports 256 colors. Windows 10 build 14931 is the - // first release that supports 16m/TrueColor. - var osRelease = os.release().split('.'); - if (Number(process.versions.node.split('.')[0]) >= 8 - && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } - - return 1; - } - - if ('CI' in env) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(function(sign) { - return sign in env; - }) || env.CI_NAME === 'codeship') { - return 1; - } - - return min; - } - - if ('TEAMCITY_VERSION' in env) { - return (/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0 - ); - } - - if ('TERM_PROGRAM' in env) { - var version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); - - switch (env.TERM_PROGRAM) { - case 'iTerm.app': - return version >= 3 ? 3 : 2; - case 'Hyper': - return 3; - case 'Apple_Terminal': - return 2; - // No default - } - } - - if (/-256(color)?$/i.test(env.TERM)) { - return 2; - } - - if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { - return 1; - } - - if ('COLORTERM' in env) { - return 1; - } - - if (env.TERM === 'dumb') { - return min; - } - - return min; -} - -function getSupportLevel(stream) { - var level = supportsColor(stream); - return translateLevel(level); -} - -module.exports = { - supportsColor: getSupportLevel, - stdout: getSupportLevel(process.stdout), - stderr: getSupportLevel(process.stderr), -}; diff --git a/deps/npm/node_modules/@colors/colors/package.json b/deps/npm/node_modules/@colors/colors/package.json deleted file mode 100644 index cb87f20953886a..00000000000000 --- a/deps/npm/node_modules/@colors/colors/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "@colors/colors", - "description": "get colors in your node.js console", - "version": "1.5.0", - "author": "DABH", - "contributors": [ - { - "name": "DABH", - "url": "https://github.com/DABH" - } - ], - "homepage": "https://github.com/DABH/colors.js", - "bugs": "https://github.com/DABH/colors.js/issues", - "keywords": [ - "ansi", - "terminal", - "colors" - ], - "repository": { - "type": "git", - "url": "http://github.com/DABH/colors.js.git" - }, - "license": "MIT", - "scripts": { - "lint": "eslint . --fix", - "test": "export FORCE_COLOR=1 && node tests/basic-test.js && node tests/safe-test.js" - }, - "engines": { - "node": ">=0.1.90" - }, - "main": "lib/index.js", - "files": [ - "examples", - "lib", - "LICENSE", - "safe.js", - "themes", - "index.d.ts", - "safe.d.ts" - ], - "devDependencies": { - "eslint": "^5.2.0", - "eslint-config-google": "^0.11.0" - } -} diff --git a/deps/npm/node_modules/@colors/colors/safe.js b/deps/npm/node_modules/@colors/colors/safe.js deleted file mode 100644 index a013d542464854..00000000000000 --- a/deps/npm/node_modules/@colors/colors/safe.js +++ /dev/null @@ -1,10 +0,0 @@ -// -// Remark: Requiring this file will use the "safe" colors API, -// which will not touch String.prototype. -// -// var colors = require('colors/safe'); -// colors.red("foo") -// -// -var colors = require('./lib/colors'); -module['exports'] = colors; diff --git a/deps/npm/node_modules/@colors/colors/themes/generic-logging.js b/deps/npm/node_modules/@colors/colors/themes/generic-logging.js deleted file mode 100644 index 63adfe4ac31f9a..00000000000000 --- a/deps/npm/node_modules/@colors/colors/themes/generic-logging.js +++ /dev/null @@ -1,12 +0,0 @@ -module['exports'] = { - silly: 'rainbow', - input: 'grey', - verbose: 'cyan', - prompt: 'grey', - info: 'green', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red', -}; diff --git a/deps/npm/node_modules/@npmcli/agent/lib/agents.js b/deps/npm/node_modules/@npmcli/agent/lib/agents.js index ffd299f3d2ba69..c541b93001517e 100644 --- a/deps/npm/node_modules/@npmcli/agent/lib/agents.js +++ b/deps/npm/node_modules/@npmcli/agent/lib/agents.js @@ -65,7 +65,10 @@ module.exports = class Agent extends AgentBase { ProxyAgent = this.isSecureEndpoint(options) ? ProxyAgent[1] : ProxyAgent[0] } - const proxyAgent = new ProxyAgent(proxy, this.#options) + const proxyAgent = new ProxyAgent(proxy, { + ...this.#options, + socketOptions: { family: this.#options.family }, + }) proxyCache.set(cacheKey, proxyAgent) return proxyAgent diff --git a/deps/npm/node_modules/@npmcli/agent/package.json b/deps/npm/node_modules/@npmcli/agent/package.json index ce240b283a42c9..ef5b4e3228cc46 100644 --- a/deps/npm/node_modules/@npmcli/agent/package.json +++ b/deps/npm/node_modules/@npmcli/agent/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/agent", - "version": "2.2.1", + "version": "2.2.2", "description": "the http/https agent used by the npm cli", "main": "lib/index.js", "scripts": { @@ -36,7 +36,7 @@ "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.1" + "socks-proxy-agent": "^8.0.3" }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", diff --git a/deps/npm/node_modules/@npmcli/arborist/bin/index.js b/deps/npm/node_modules/@npmcli/arborist/bin/index.js index ff356fafab7c34..414c7eb468cd85 100755 --- a/deps/npm/node_modules/@npmcli/arborist/bin/index.js +++ b/deps/npm/node_modules/@npmcli/arborist/bin/index.js @@ -2,6 +2,7 @@ const fs = require('fs') const path = require('path') +const { time } = require('proc-log') const { bin, arb: options } = require('./lib/options') const version = require('../package.json').version @@ -72,11 +73,11 @@ for (const file of commandFiles) { log.info(name, options) - process.emit('time', totalTime) - process.emit('time', scriptTime) + const timeEnd = time.start(totalTime) + const scriptEnd = time.start(scriptTime) return command(options, (result) => { - process.emit('timeEnd', scriptTime) + scriptEnd() return { result, timing: { @@ -95,7 +96,7 @@ for (const file of commandFiles) { return err }) .then((r) => { - process.emit('timeEnd', totalTime) + timeEnd() if (bin.loglevel !== 'silent') { console[process.exitCode ? 'error' : 'log'](r) } diff --git a/deps/npm/node_modules/@npmcli/arborist/bin/lib/logging.js b/deps/npm/node_modules/@npmcli/arborist/bin/lib/logging.js index ffb5544b21463e..f06716735de74c 100644 --- a/deps/npm/node_modules/@npmcli/arborist/bin/lib/logging.js +++ b/deps/npm/node_modules/@npmcli/arborist/bin/lib/logging.js @@ -1,4 +1,4 @@ -const log = require('proc-log') +const { log } = require('proc-log') const fs = require('fs') const { dirname } = require('path') const os = require('os') diff --git a/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js b/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js index 586dee7806dd0e..a7ec534f5c5a79 100644 --- a/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js +++ b/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js @@ -4,22 +4,22 @@ const log = require('./logging.js') const timers = new Map() const finished = new Map() -process.on('time', name => { - if (timers.has(name)) { - throw new Error('conflicting timer! ' + name) - } - timers.set(name, process.hrtime.bigint()) -}) - -process.on('timeEnd', name => { - if (!timers.has(name)) { - throw new Error('timer not started! ' + name) - } - const elapsed = Number(process.hrtime.bigint() - timers.get(name)) - timers.delete(name) - finished.set(name, elapsed) - if (options.timing) { - log.info('timeEnd', `${name} ${elapsed / 1e9}s`, log.meta({ force: options.timing === 'always' })) +process.on('time', (level, name) => { + if (level === 'start') { + if (timers.has(name)) { + throw new Error('conflicting timer! ' + name) + } + timers.set(name, process.hrtime.bigint()) + } else if (level === 'end') { + if (!timers.has(name)) { + throw new Error('timer not started! ' + name) + } + const elapsed = Number(process.hrtime.bigint() - timers.get(name)) + timers.delete(name) + finished.set(name, elapsed) + if (options.timing) { + log.info('timeEnd', `${name} ${elapsed / 1e9}s`, log.meta({ force: options.timing === 'always' })) + } } }) diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js b/deps/npm/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js index c5cdc097a9fab7..2e30eb1de76264 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js @@ -1,6 +1,6 @@ // add and remove dependency specs to/from pkg manifest -const log = require('proc-log') +const { log } = require('proc-log') const localeCompare = require('@isaacs/string-locale-compare')('en') const add = ({ pkg, add, saveBundle, saveType }) => { diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js index 8ceb6b72123f68..920403d231d6db 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js @@ -11,8 +11,8 @@ const treeCheck = require('../tree-check.js') const { readdirScoped } = require('@npmcli/fs') const { lstat, readlink } = require('fs/promises') const { depth } = require('treeverse') -const log = require('proc-log') -const { cleanUrl } = require('npm-registry-fetch') +const { log, time } = require('proc-log') +const { redact } = require('@npmcli/redact') const { OK, @@ -179,7 +179,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { options.rm = null } - process.emit('time', 'idealTree') + const timeEnd = time.start('idealTree') if (!options.add && !options.rm && !options.update && this.options.global) { throw new Error('global requires add, rm, or update option') @@ -205,7 +205,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { await this.#pruneFailedOptional() await this.#checkEngineAndPlatform() } finally { - process.emit('timeEnd', 'idealTree') + timeEnd() this.finishTracker('idealTree') } @@ -278,7 +278,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { // load the initial tree, either the virtualTree from a shrinkwrap, // or just the root node from a package.json async #initTree () { - process.emit('time', 'idealTree:init') + const timeEnd = time.start('idealTree:init') let root if (this.options.global) { root = await this.#globalRootNode() @@ -356,7 +356,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { // if you want another one, load another copy. this.idealTree = tree this.virtualTree = null - process.emit('timeEnd', 'idealTree:init') + timeEnd() return tree }) } @@ -420,7 +420,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { // process the add/rm requests by modifying the root node, and the // update.names request by queueing nodes dependent on those named. async #applyUserRequests (options) { - process.emit('time', 'idealTree:userRequests') + const timeEnd = time.start('idealTree:userRequests') const tree = this.idealTree.target if (!this.options.workspaces.length) { @@ -436,7 +436,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { await Promise.all(appliedRequests) } - process.emit('timeEnd', 'idealTree:userRequests') + timeEnd() } async #applyUserRequestsToNode (tree, options) { @@ -463,7 +463,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { } const dir = resolve(nm, name) const st = await lstat(dir) - .catch(/* istanbul ignore next */ er => null) + .catch(/* istanbul ignore next */ () => null) if (st && st.isSymbolicLink()) { const target = await readlink(dir) const real = resolve(dirname(dir), target).replace(/#/g, '%23') @@ -691,7 +691,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { // if the lockfile is from node v5 or earlier, then we'll have to reload // all the manifests of everything we encounter. this is costly, but at // least it's just a one-time hit. - process.emit('time', 'idealTree:inflate') + const timeEnd = time.start('idealTree:inflate') // don't warn if we're not gonna actually write it back anyway. const heading = ancient ? 'ancient lockfile' : 'old lockfile' @@ -758,14 +758,14 @@ This is a one-time fix-up, please be patient... meta.originalLockfileVersion = defaultLockfileVersion } this.finishTracker('idealTree:inflate') - process.emit('timeEnd', 'idealTree:inflate') + timeEnd() } // at this point we have a virtual tree with the actual root node's // package deps, which may be partly or entirely incomplete, invalid // or extraneous. #buildDeps () { - process.emit('time', 'idealTree:buildDeps') + const timeEnd = time.start('idealTree:buildDeps') const tree = this.idealTree.target tree.assertRootOverrides() this.#depsQueue.push(tree) @@ -773,15 +773,14 @@ This is a one-time fix-up, please be patient... // in the override list log.silly('idealTree', 'buildDeps') this.addTracker('idealTree', tree.name, '') - return this.#buildDepStep() - .then(() => process.emit('timeEnd', 'idealTree:buildDeps')) + return this.#buildDepStep().then(timeEnd) } async #buildDepStep () { // removes tracker of previous dependency in the queue if (this.#currentDep) { const { location, name } = this.#currentDep - process.emit('timeEnd', `idealTree:${location || '#root'}`) + time.end(`idealTree:${location || '#root'}`) this.finishTracker('idealTree', name, location) this.#currentDep = null } @@ -807,7 +806,7 @@ This is a one-time fix-up, please be patient... this.#depsSeen.add(node) this.#currentDep = node - process.emit('time', `idealTree:${node.location || '#root'}`) + time.start(`idealTree:${node.location || '#root'}`) // if we're loading a _complete_ ideal tree, for a --package-lock-only // installation for example, we have to crack open the tarball and @@ -1025,7 +1024,7 @@ This is a one-time fix-up, please be patient... for (const e of this.#problemEdges(placed)) { promises.push(() => this.#fetchManifest(npa.resolve(e.name, e.spec, fromPath(placed, e))) - .catch(er => null) + .catch(() => null) ) } }, @@ -1213,7 +1212,7 @@ This is a one-time fix-up, please be patient... if (this.#manifests.has(spec.raw)) { return this.#manifests.get(spec.raw) } else { - const cleanRawSpec = cleanUrl(spec.rawSpec) + const cleanRawSpec = redact(spec.rawSpec) log.silly('fetch manifest', spec.raw.replace(spec.rawSpec, cleanRawSpec)) const o = { ...options, @@ -1274,7 +1273,7 @@ This is a one-time fix-up, please be patient... }) } - #linkFromSpec (name, spec, parent, edge) { + #linkFromSpec (name, spec, parent) { const realpath = spec.fetchSpec const { installLinks, legacyPeerDeps } = this return rpj(realpath + '/package.json').catch(() => ({})).then(pkg => { @@ -1449,7 +1448,7 @@ This is a one-time fix-up, please be patient... } #fixDepFlags () { - process.emit('time', 'idealTree:fixDepFlags') + const timeEnd = time.start('idealTree:fixDepFlags') const metaFromDisk = this.idealTree.meta.loadedFromDisk const flagsSuspect = this[_flagsSuspect] const mutateTree = this.#mutateTree @@ -1496,7 +1495,7 @@ This is a one-time fix-up, please be patient... } } - process.emit('timeEnd', 'idealTree:fixDepFlags') + timeEnd() } #idealTreePrune () { diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js index 358f3e1b1a7598..ba180f354708a2 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js @@ -30,7 +30,7 @@ const { resolve } = require('path') const { homedir } = require('os') const { depth } = require('treeverse') const mapWorkspaces = require('@npmcli/map-workspaces') -const log = require('proc-log') +const { log, time } = require('proc-log') const { saveTypeMap } = require('../add-rm-pkg-deps.js') const AuditReport = require('../audit-report.js') @@ -66,7 +66,7 @@ const lockfileVersion = lfv => { class Arborist extends Base { constructor (options = {}) { - process.emit('time', 'arborist:ctor') + const timeEnd = time.start('arborist:ctor') super(options) this.options = { nodeVersion: process.version, @@ -74,20 +74,26 @@ class Arborist extends Base { Arborist: this.constructor, binLinks: 'binLinks' in options ? !!options.binLinks : true, cache: options.cache || `${homedir()}/.npm/_cacache`, + dryRun: !!options.dryRun, + formatPackageLock: 'formatPackageLock' in options ? !!options.formatPackageLock : true, force: !!options.force, global: !!options.global, ignoreScripts: !!options.ignoreScripts, installStrategy: options.global ? 'shallow' : (options.installStrategy ? options.installStrategy : 'hoisted'), lockfileVersion: lockfileVersion(options.lockfileVersion), + packageLockOnly: !!options.packageLockOnly, packumentCache: options.packumentCache || new Map(), path: options.path || '.', rebuildBundle: 'rebuildBundle' in options ? !!options.rebuildBundle : true, replaceRegistryHost: options.replaceRegistryHost, + savePrefix: 'savePrefix' in options ? options.savePrefix : '^', scriptShell: options.scriptShell, workspaces: options.workspaces || [], workspacesEnabled: options.workspacesEnabled !== false, } - // TODO is this even used? If not is that a bug? + // TODO we only ever look at this.options.replaceRegistryHost, not + // this.replaceRegistryHost. Defaulting needs to be written back to + // this.options to work properly this.replaceRegistryHost = this.options.replaceRegistryHost = (!this.options.replaceRegistryHost || this.options.replaceRegistryHost === 'npmjs') ? 'registry.npmjs.org' : this.options.replaceRegistryHost @@ -96,8 +102,9 @@ class Arborist extends Base { throw new Error(`Invalid saveType ${options.saveType}`) } this.cache = resolve(this.options.cache) + this.diff = null this.path = resolve(this.options.path) - process.emit('timeEnd', 'arborist:ctor') + timeEnd() } // TODO: We should change these to static functions instead @@ -223,7 +230,7 @@ class Arborist extends Base { // XXX: deprecate separate method options objects. options = { ...this.options, ...options } - process.emit('time', 'audit') + const timeEnd = time.start('audit') let tree if (options.packageLock === false) { // build ideal tree @@ -246,10 +253,28 @@ class Arborist extends Base { } this.auditReport = await AuditReport.load(tree, options) const ret = options.fix ? this.reify(options) : this.auditReport - process.emit('timeEnd', 'audit') + timeEnd() this.finishTracker('audit') return ret } + + async dedupe (options = {}) { + // allow the user to set options on the ctor as well. + // XXX: deprecate separate method options objects. + options = { ...this.options, ...options } + const tree = await this.loadVirtual().catch(() => this.loadActual()) + const names = [] + for (const name of tree.inventory.query('name')) { + if (tree.inventory.query('name', name).size > 1) { + names.push(name) + } + } + return this.reify({ + ...options, + preferDedupe: true, + update: { names }, + }) + } } module.exports = Arborist diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js index f4f1bb8e443624..1e60d0f696b26d 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js @@ -1,7 +1,7 @@ const _makeIdealGraph = Symbol('makeIdealGraph') const _createIsolatedTree = Symbol.for('createIsolatedTree') const _createBundledTree = Symbol('createBundledTree') -const fs = require('fs') +const { mkdirSync } = require('fs') const pacote = require('pacote') const { join } = require('path') const { depth } = require('treeverse') @@ -108,7 +108,7 @@ module.exports = cls => class IsolatedReifier extends cls { '.store', `${node.name}@${node.version}` ) - fs.mkdirSync(dir, { recursive: true }) + mkdirSync(dir, { recursive: true }) // TODO this approach feels wrong // and shouldn't be necessary for shrinkwraps await pacote.extract(node.resolved, dir, { @@ -212,7 +212,7 @@ module.exports = cls => class IsolatedReifier extends cls { return { edges, nodes } } - async [_createIsolatedTree] (idealTree) { + async [_createIsolatedTree] () { await this[_makeIdealGraph](this.options) const proxiedIdealTree = this.idealGraph diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js index 3ab5f5983768df..81c1bd11327753 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js @@ -336,8 +336,8 @@ module.exports = cls => class ActualLoader extends cls { await this.#loadFSChildren(node.target) return Promise.all( [...node.target.children.entries()] - .filter(([name, kid]) => !did.has(kid.realpath)) - .map(([name, kid]) => this.#loadFSTree(kid)) + .filter(([, kid]) => !did.has(kid.realpath)) + .map(([, kid]) => this.#loadFSTree(kid)) ) } } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js index 9b681a47a83587..d96d4adc88a702 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js @@ -283,7 +283,7 @@ module.exports = cls => class VirtualLoader extends cls { return node } - #loadLink (location, targetLoc, target, meta) { + #loadLink (location, targetLoc, target) { const path = resolve(this.path, location) const link = new Link({ installLinks: this.installLinks, diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js index 422819b2104b7e..4f8730cde7f382 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js @@ -9,11 +9,8 @@ const binLinks = require('bin-links') const runScript = require('@npmcli/run-script') const { callLimit: promiseCallLimit } = require('promise-call-limit') const { resolve } = require('path') -const { - isNodeGypPackage, - defaultGypInstallScript, -} = require('@npmcli/node-gyp') -const log = require('proc-log') +const { isNodeGypPackage, defaultGypInstallScript } = require('@npmcli/node-gyp') +const { log, time } = require('proc-log') const boolEnv = b => b ? '1' : '' const sortNodes = (a, b) => @@ -54,7 +51,7 @@ module.exports = cls => class Builder extends cls { // separates links nodes so that it can run // prepare scripts and link bins in the expected order - process.emit('time', 'build') + const timeEnd = time.start('build') const { depNodes, @@ -70,7 +67,7 @@ module.exports = cls => class Builder extends cls { await this.#build(linkNodes, { type: 'links' }) } - process.emit('timeEnd', 'build') + timeEnd() } // if we don't have a set of nodes, then just rebuild @@ -147,7 +144,7 @@ module.exports = cls => class Builder extends cls { } async #build (nodes, { type = 'deps' }) { - process.emit('time', `build:${type}`) + const timeEnd = time.start(`build:${type}`) await this.#buildQueues(nodes) @@ -168,11 +165,11 @@ module.exports = cls => class Builder extends cls { await this.#runScripts('postinstall') } - process.emit('timeEnd', `build:${type}`) + timeEnd() } async #buildQueues (nodes) { - process.emit('time', 'build:queue') + const timeEnd = time.start('build:queue') const set = new Set() const promises = [] @@ -210,7 +207,7 @@ module.exports = cls => class Builder extends cls { } } } - process.emit('timeEnd', 'build:queue') + timeEnd() } async [_checkBins] (node) { @@ -286,7 +283,7 @@ module.exports = cls => class Builder extends cls { return } - process.emit('time', `build:run:${event}`) + const timeEnd = time.start(`build:run:${event}`) const stdio = this.options.foregroundScripts ? 'inherit' : 'pipe' const limit = this.options.foregroundScripts ? 1 : undefined await promiseCallLimit(queue.map(node => async () => { @@ -309,8 +306,7 @@ module.exports = cls => class Builder extends cls { return } - const timer = `build:run:${event}:${location}` - process.emit('time', timer) + const timeEndLocation = time.start(`build:run:${event}:${location}`) log.info('run', pkg._id, event, location, pkg.scripts[event]) const env = { npm_package_resolved: resolved, @@ -356,9 +352,9 @@ module.exports = cls => class Builder extends cls { ? this[_handleOptionalFailure](node, p) : p) - process.emit('timeEnd', timer) + timeEndLocation() }), { limit }) - process.emit('timeEnd', `build:run:${event}`) + timeEnd() } async #linkAllBins () { @@ -367,7 +363,7 @@ module.exports = cls => class Builder extends cls { return } - process.emit('time', 'build:link') + const timeEnd = time.start('build:link') const promises = [] // sort the queue by node path, so that the module-local collision // detector in bin-links will always resolve the same way. @@ -377,7 +373,7 @@ module.exports = cls => class Builder extends cls { } await promiseAllRejectLate(promises) - process.emit('timeEnd', 'build:link') + timeEnd() } async #createBinLinks (node) { @@ -385,7 +381,7 @@ module.exports = cls => class Builder extends cls { return } - process.emit('time', `build:link:${node.location}`) + const timeEnd = time.start(`build:link:${node.location}`) const p = binLinks({ pkg: node.package, @@ -399,6 +395,6 @@ module.exports = cls => class Builder extends cls { ? this[_handleOptionalFailure](node, p) : p) - process.emit('timeEnd', `build:link:${node.location}`) + timeEnd() } } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js index a70e21821ecb86..96704f6556e0da 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js @@ -7,7 +7,7 @@ const npa = require('npm-package-arg') const semver = require('semver') const debug = require('../debug.js') const { walkUp } = require('walk-up-path') -const log = require('proc-log') +const { log, time } = require('proc-log') const hgi = require('hosted-git-info') const rpj = require('read-package-json-fast') @@ -38,119 +38,96 @@ const { saveTypeMap, hasSubKey } = require('../add-rm-pkg-deps.js') const Shrinkwrap = require('../shrinkwrap.js') const { defaultLockfileVersion } = Shrinkwrap -const _retiredPaths = Symbol('retiredPaths') -const _retiredUnchanged = Symbol('retiredUnchanged') -const _sparseTreeDirs = Symbol('sparseTreeDirs') -const _sparseTreeRoots = Symbol('sparseTreeRoots') -const _savePrefix = Symbol('savePrefix') +// Part of steps (steps need refactoring before we can do anything about these) const _retireShallowNodes = Symbol.for('retireShallowNodes') -const _getBundlesByDepth = Symbol('getBundlesByDepth') -const _registryResolved = Symbol('registryResolved') -const _addNodeToTrashList = Symbol.for('addNodeToTrashList') +const _loadBundlesAndUpdateTrees = Symbol.for('loadBundlesAndUpdateTrees') +const _submitQuickAudit = Symbol('submitQuickAudit') +const _addOmitsToTrashList = Symbol('addOmitsToTrashList') +const _unpackNewModules = Symbol.for('unpackNewModules') +const _build = Symbol.for('build') // shared by rebuild mixin const _trashList = Symbol.for('trashList') const _handleOptionalFailure = Symbol.for('handleOptionalFailure') const _loadTrees = Symbol.for('loadTrees') +// defined by rebuild mixin +const _checkBins = Symbol.for('checkBins') // shared symbols for swapping out when testing +// TODO tests should not be this deep into internals const _diffTrees = Symbol.for('diffTrees') const _createSparseTree = Symbol.for('createSparseTree') const _loadShrinkwrapsAndUpdateTrees = Symbol.for('loadShrinkwrapsAndUpdateTrees') -const _shrinkwrapInflated = Symbol('shrinkwrapInflated') -const _bundleUnpacked = Symbol('bundleUnpacked') -const _bundleMissing = Symbol('bundleMissing') const _reifyNode = Symbol.for('reifyNode') -const _extractOrLink = Symbol('extractOrLink') const _updateAll = Symbol.for('updateAll') const _updateNames = Symbol.for('updateNames') -// defined by rebuild mixin -const _checkBins = Symbol.for('checkBins') -const _symlink = Symbol('symlink') -const _warnDeprecated = Symbol('warnDeprecated') -const _loadBundlesAndUpdateTrees = Symbol.for('loadBundlesAndUpdateTrees') -const _submitQuickAudit = Symbol('submitQuickAudit') -const _unpackNewModules = Symbol.for('unpackNewModules') const _moveContents = Symbol.for('moveContents') const _moveBackRetiredUnchanged = Symbol.for('moveBackRetiredUnchanged') -const _build = Symbol.for('build') const _removeTrash = Symbol.for('removeTrash') const _renamePath = Symbol.for('renamePath') const _rollbackRetireShallowNodes = Symbol.for('rollbackRetireShallowNodes') const _rollbackCreateSparseTree = Symbol.for('rollbackCreateSparseTree') const _rollbackMoveBackRetiredUnchanged = Symbol.for('rollbackMoveBackRetiredUnchanged') const _saveIdealTree = Symbol.for('saveIdealTree') -const _copyIdealToActual = Symbol('copyIdealToActual') -const _addOmitsToTrashList = Symbol('addOmitsToTrashList') -const _packageLockOnly = Symbol('packageLockOnly') -const _dryRun = Symbol('dryRun') -const _validateNodeModules = Symbol('validateNodeModules') -const _nmValidated = Symbol('nmValidated') -const _validatePath = Symbol('validatePath') const _reifyPackages = Symbol.for('reifyPackages') -const _omitDev = Symbol('omitDev') -const _omitOptional = Symbol('omitOptional') -const _omitPeer = Symbol('omitPeer') - -const _pruneBundledMetadeps = Symbol('pruneBundledMetadeps') - -// defined by Ideal mixin +// defined by build-ideal-tree mixin const _resolvedAdd = Symbol.for('resolvedAdd') const _usePackageLock = Symbol.for('usePackageLock') -const _formatPackageLock = Symbol.for('formatPackageLock') +// used by build-ideal-tree mixin +const _addNodeToTrashList = Symbol.for('addNodeToTrashList') const _createIsolatedTree = Symbol.for('createIsolatedTree') module.exports = cls => class Reifier extends cls { + #bundleMissing = new Set() // child nodes we'd EXPECT to be included in a bundle, but aren't + #bundleUnpacked = new Set() // the nodes we unpack to read their bundles + #dryRun + #nmValidated = new Set() + #omitDev + #omitPeer + #omitOptional + #retiredPaths = {} + #retiredUnchanged = {} + #savePrefix + #shrinkwrapInflated = new Set() + #sparseTreeDirs = new Set() + #sparseTreeRoots = new Set() + constructor (options) { super(options) - const { - savePrefix = '^', - packageLockOnly = false, - dryRun = false, - formatPackageLock = true, - } = options - - this[_dryRun] = !!dryRun - this[_packageLockOnly] = !!packageLockOnly - this[_savePrefix] = savePrefix - this[_formatPackageLock] = !!formatPackageLock - - this.diff = null - this[_retiredPaths] = {} - this[_shrinkwrapInflated] = new Set() - this[_retiredUnchanged] = {} - this[_sparseTreeDirs] = new Set() - this[_sparseTreeRoots] = new Set() this[_trashList] = new Set() - // the nodes we unpack to read their bundles - this[_bundleUnpacked] = new Set() - // child nodes we'd EXPECT to be included in a bundle, but aren't - this[_bundleMissing] = new Set() - this[_nmValidated] = new Set() } // public method async reify (options = {}) { const linked = (options.installStrategy || this.options.installStrategy) === 'linked' - if (this[_packageLockOnly] && this.options.global) { + if (this.options.packageLockOnly && this.options.global) { const er = new Error('cannot generate lockfile for global packages') er.code = 'ESHRINKWRAPGLOBAL' throw er } const omit = new Set(options.omit || []) - this[_omitDev] = omit.has('dev') - this[_omitOptional] = omit.has('optional') - this[_omitPeer] = omit.has('peer') + this.#omitDev = omit.has('dev') + this.#omitOptional = omit.has('optional') + this.#omitPeer = omit.has('peer') // start tracker block this.addTracker('reify') - process.emit('time', 'reify') - await this[_validatePath]() + const timeEnd = time.start('reify') + // don't create missing dirs on dry runs + if (!this.options.packageLockOnly && !this.options.dryRun) { + // we do NOT want to set ownership on this folder, especially + // recursively, because it can have other side effects to do that + // in a project directory. We just want to make it if it's missing. + await mkdir(resolve(this.path), { recursive: true }) + + // do not allow the top-level node_modules to be a symlink + await this.#validateNodeModules(resolve(this.path, 'node_modules')) + } await this[_loadTrees](options) const oldTree = this.idealTree @@ -159,7 +136,7 @@ module.exports = cls => class Reifier extends cls { // this is currently technical debt which will be resolved in a refactor // of Node/Link trees log.warn('reify', 'The "linked" install strategy is EXPERIMENTAL and may contain bugs.') - this.idealTree = await this[_createIsolatedTree](this.idealTree) + this.idealTree = await this[_createIsolatedTree]() } await this[_diffTrees]() await this[_reifyPackages]() @@ -169,37 +146,139 @@ module.exports = cls => class Reifier extends cls { this.idealTree = oldTree } await this[_saveIdealTree](options) - await this[_copyIdealToActual]() - // This is a very bad pattern and I can't wait to stop doing it - this.auditReport = await this.auditReport + // clean up any trash that is still in the tree + for (const path of this[_trashList]) { + const loc = relpath(this.idealTree.realpath, path) + const node = this.idealTree.inventory.get(loc) + if (node && node.root === this.idealTree) { + node.parent = null + } + } - this.finishTracker('reify') - process.emit('timeEnd', 'reify') - return treeCheck(this.actualTree) - } + // if we filtered to only certain nodes, then anything ELSE needs + // to be untouched in the resulting actual tree, even if it differs + // in the idealTree. Copy over anything that was in the actual and + // was not changed, delete anything in the ideal and not actual. + // Then we move the entire idealTree over to this.actualTree, and + // save the hidden lockfile. + if (this.diff && this.diff.filterSet.size) { + const reroot = new Set() - async [_validatePath] () { - // don't create missing dirs on dry runs - if (this[_packageLockOnly] || this[_dryRun]) { - return + const { filterSet } = this.diff + const seen = new Set() + for (const [loc, ideal] of this.idealTree.inventory.entries()) { + seen.add(loc) + + // if it's an ideal node from the filter set, then skip it + // because we already made whatever changes were necessary + if (filterSet.has(ideal)) { + continue + } + + // otherwise, if it's not in the actualTree, then it's not a thing + // that we actually added. And if it IS in the actualTree, then + // it's something that we left untouched, so we need to record + // that. + const actual = this.actualTree.inventory.get(loc) + if (!actual) { + ideal.root = null + } else { + if ([...actual.linksIn].some(link => filterSet.has(link))) { + seen.add(actual.location) + continue + } + const { realpath, isLink } = actual + if (isLink && ideal.isLink && ideal.realpath === realpath) { + continue + } else { + reroot.add(actual) + } + } + } + + // now find any actual nodes that may not be present in the ideal + // tree, but were left behind by virtue of not being in the filter + for (const [loc, actual] of this.actualTree.inventory.entries()) { + if (seen.has(loc)) { + continue + } + seen.add(loc) + + // we know that this is something that ISN'T in the idealTree, + // or else we will have addressed it in the previous loop. + // If it's in the filterSet, that means we intentionally removed + // it, so nothing to do here. + if (filterSet.has(actual)) { + continue + } + + reroot.add(actual) + } + + // go through the rerooted actual nodes, and move them over. + for (const actual of reroot) { + actual.root = this.idealTree + } + + // prune out any tops that lack a linkIn, they are no longer relevant. + for (const top of this.idealTree.tops) { + if (top.linksIn.size === 0) { + top.root = null + } + } + + // need to calculate dep flags, since nodes may have been marked + // as extraneous or otherwise incorrect during transit. + calcDepFlags(this.idealTree) } - // we do NOT want to set ownership on this folder, especially - // recursively, because it can have other side effects to do that - // in a project directory. We just want to make it if it's missing. - await mkdir(resolve(this.path), { recursive: true }) + // save the ideal's meta as a hidden lockfile after we actualize it + this.idealTree.meta.filename = + this.idealTree.realpath + '/node_modules/.package-lock.json' + this.idealTree.meta.hiddenLockfile = true + this.idealTree.meta.lockfileVersion = defaultLockfileVersion + + this.actualTree = this.idealTree + this.idealTree = null + + if (!this.options.global) { + await this.actualTree.meta.save() + const ignoreScripts = !!this.options.ignoreScripts + // if we aren't doing a dry run or ignoring scripts and we actually made changes to the dep + // tree, then run the dependencies scripts + if (!this.options.dryRun && !ignoreScripts && this.diff && this.diff.children.length) { + const { path, package: pkg } = this.actualTree.target + const stdio = this.options.foregroundScripts ? 'inherit' : 'pipe' + const { scripts = {} } = pkg + for (const event of ['predependencies', 'dependencies', 'postdependencies']) { + if (Object.prototype.hasOwnProperty.call(scripts, event)) { + log.info('run', pkg._id, event, scripts[event]) + await time.start(`reify:run:${event}`, () => runScript({ + event, + path, + pkg, + stdio, + scriptShell: this.options.scriptShell, + })) + } + } + } + } + // This is a very bad pattern and I can't wait to stop doing it + this.auditReport = await this.auditReport - // do not allow the top-level node_modules to be a symlink - await this[_validateNodeModules](resolve(this.path, 'node_modules')) + this.finishTracker('reify') + timeEnd() + return treeCheck(this.actualTree) } async [_reifyPackages] () { // we don't submit the audit report or write to disk on dry runs - if (this[_dryRun]) { + if (this.options.dryRun) { return } - if (this[_packageLockOnly]) { + if (this.options.packageLockOnly) { // we already have the complete tree, so just audit it now, // and that's all we have to do here. return this[_submitQuickAudit]() @@ -248,6 +327,7 @@ module.exports = cls => class Reifier extends cls { throw reifyTerminated } } catch (er) { + // TODO rollbacks shouldn't be relied on to throw err await this[rollback](er) /* istanbul ignore next - rollback throws, should never hit this */ throw er @@ -269,16 +349,15 @@ module.exports = cls => class Reifier extends cls { // when doing a local install, we load everything and figure it all out. // when doing a global install, we *only* care about the explicit requests. [_loadTrees] (options) { - process.emit('time', 'reify:loadTrees') + const timeEnd = time.start('reify:loadTrees') const bitOpt = { ...options, - complete: this[_packageLockOnly] || this[_dryRun], + complete: this.options.packageLockOnly || this.options.dryRun, } // if we're only writing a package lock, then it doesn't matter what's here - if (this[_packageLockOnly]) { - return this.buildIdealTree(bitOpt) - .then(() => process.emit('timeEnd', 'reify:loadTrees')) + if (this.options.packageLockOnly) { + return this.buildIdealTree(bitOpt).then(timeEnd) } const actualOpt = this.options.global ? { @@ -312,7 +391,7 @@ module.exports = cls => class Reifier extends cls { return Promise.all([ this.loadActual(actualOpt), this.buildIdealTree(bitOpt), - ]).then(() => process.emit('timeEnd', 'reify:loadTrees')) + ]).then(timeEnd) } // the global install space tends to have a lot of stuff in it. don't @@ -322,15 +401,15 @@ module.exports = cls => class Reifier extends cls { // explicitRequests which is set during buildIdealTree return this.buildIdealTree(bitOpt) .then(() => this.loadActual(actualOpt)) - .then(() => process.emit('timeEnd', 'reify:loadTrees')) + .then(timeEnd) } [_diffTrees] () { - if (this[_packageLockOnly]) { + if (this.options.packageLockOnly) { return } - process.emit('time', 'reify:diffTrees') + const timeEnd = time.start('reify:diffTrees') // XXX if we have an existing diff already, there should be a way // to just invalidate the parts that changed, but avoid walking the // whole tree again. @@ -384,7 +463,7 @@ module.exports = cls => class Reifier extends cls { // find all the nodes that need to change between the actual // and ideal trees. this.diff = Diff.calculate({ - shrinkwrapInflated: this[_shrinkwrapInflated], + shrinkwrapInflated: this.#shrinkwrapInflated, filterNodes, actual: this.actualTree, ideal: this.idealTree, @@ -397,7 +476,7 @@ module.exports = cls => class Reifier extends cls { // because if we remove node_modules/FOO on case-insensitive systems, // it will remove the dep that we *want* at node_modules/foo. - process.emit('timeEnd', 'reify:diffTrees') + timeEnd() } // add the node and all its bins to the list of things to be @@ -406,7 +485,7 @@ module.exports = cls => class Reifier extends cls { // replace them when rolling back on failure. [_addNodeToTrashList] (node, retire = false) { const paths = [node.path, ...node.binPaths] - const moves = this[_retiredPaths] + const moves = this.#retiredPaths log.silly('reify', 'mark', retire ? 'retired' : 'deleted', paths) for (const path of paths) { if (retire) { @@ -422,8 +501,8 @@ module.exports = cls => class Reifier extends cls { // move aside the shallowest nodes in the tree that have to be // changed or removed, so that we can rollback if necessary. [_retireShallowNodes] () { - process.emit('time', 'reify:retireShallow') - const moves = this[_retiredPaths] = {} + const timeEnd = time.start('reify:retireShallow') + const moves = this.#retiredPaths = {} for (const diff of this.diff.children) { if (diff.action === 'CHANGE' || diff.action === 'REMOVE') { // we'll have to clean these up at the end, so add them to the list @@ -433,8 +512,7 @@ module.exports = cls => class Reifier extends cls { log.silly('reify', 'moves', moves) const movePromises = Object.entries(moves) .map(([from, to]) => this[_renamePath](from, to)) - return promiseAllRejectLate(movePromises) - .then(() => process.emit('timeEnd', 'reify:retireShallow')) + return promiseAllRejectLate(movePromises).then(timeEnd) } [_renamePath] (from, to, didMkdirp = false) { @@ -456,14 +534,14 @@ module.exports = cls => class Reifier extends cls { } [_rollbackRetireShallowNodes] (er) { - process.emit('time', 'reify:rollback:retireShallow') - const moves = this[_retiredPaths] + const timeEnd = time.start('reify:rollback:retireShallow') + const moves = this.#retiredPaths const movePromises = Object.entries(moves) .map(([from, to]) => this[_renamePath](to, from)) return promiseAllRejectLate(movePromises) // ignore subsequent rollback errors - .catch(er => {}) - .then(() => process.emit('timeEnd', 'reify:rollback:retireShallow')) + .catch(() => {}) + .then(timeEnd) .then(() => { throw er }) @@ -472,11 +550,11 @@ module.exports = cls => class Reifier extends cls { // adding to the trash list will skip reifying, and delete them // if they are currently in the tree and otherwise untouched. [_addOmitsToTrashList] () { - if (!this[_omitDev] && !this[_omitOptional] && !this[_omitPeer]) { + if (!this.#omitDev && !this.#omitOptional && !this.#omitPeer) { return } - process.emit('time', 'reify:trashOmits') + const timeEnd = time.start('reify:trashOmits') for (const node of this.idealTree.inventory.values()) { const { top } = node @@ -494,26 +572,26 @@ module.exports = cls => class Reifier extends cls { // omit node if the dep type matches any omit flags that were set if ( - node.peer && this[_omitPeer] || - node.dev && this[_omitDev] || - node.optional && this[_omitOptional] || - node.devOptional && this[_omitOptional] && this[_omitDev] + node.peer && this.#omitPeer || + node.dev && this.#omitDev || + node.optional && this.#omitOptional || + node.devOptional && this.#omitOptional && this.#omitDev ) { this[_addNodeToTrashList](node) } } - process.emit('timeEnd', 'reify:trashOmits') + timeEnd() } [_createSparseTree] () { - process.emit('time', 'reify:createSparse') + const timeEnd = time.start('reify:createSparse') // if we call this fn again, we look for the previous list // so that we can avoid making the same directory multiple times const leaves = this.diff.leaves .filter(diff => { return (diff.action === 'ADD' || diff.action === 'CHANGE') && - !this[_sparseTreeDirs].has(diff.ideal.path) && + !this.#sparseTreeDirs.has(diff.ideal.path) && !diff.ideal.isLink }) .map(diff => diff.ideal) @@ -530,37 +608,36 @@ module.exports = cls => class Reifier extends cls { continue } dirsChecked.add(d) - const st = await lstat(d).catch(er => null) + const st = await lstat(d).catch(() => null) // this can happen if we have a link to a package with a name // that the filesystem treats as if it is the same thing. // would be nice to have conditional istanbul ignores here... /* istanbul ignore next - defense in depth */ if (st && !st.isDirectory()) { const retired = retirePath(d) - this[_retiredPaths][d] = retired + this.#retiredPaths[d] = retired this[_trashList].add(retired) await this[_renamePath](d, retired) } } - this[_sparseTreeDirs].add(node.path) + this.#sparseTreeDirs.add(node.path) const made = await mkdir(node.path, { recursive: true }) // if the directory already exists, made will be undefined. if that's the case // we don't want to remove it because we aren't the ones who created it so we - // omit it from the _sparseTreeRoots + // omit it from the #sparseTreeRoots if (made) { - this[_sparseTreeRoots].add(made) + this.#sparseTreeRoots.add(made) } - })) - .then(() => process.emit('timeEnd', 'reify:createSparse')) + })).then(timeEnd) } [_rollbackCreateSparseTree] (er) { - process.emit('time', 'reify:rollback:createSparse') + const timeEnd = time.start('reify:rollback:createSparse') // cut the roots of the sparse tree that were created, not the leaves - const roots = this[_sparseTreeRoots] + const roots = this.#sparseTreeRoots // also delete the moves that we retired, so that we can move them back const failures = [] - const targets = [...roots, ...Object.keys(this[_retiredPaths])] + const targets = [...roots, ...Object.keys(this.#retiredPaths)] const unlinks = targets .map(path => rm(path, { recursive: true, force: true }).catch(er => failures.push([path, er]))) return promiseAllRejectLate(unlinks).then(() => { @@ -569,7 +646,7 @@ module.exports = cls => class Reifier extends cls { log.warn('cleanup', 'Failed to remove some directories', failures) } }) - .then(() => process.emit('timeEnd', 'reify:rollback:createSparse')) + .then(timeEnd) .then(() => this[_rollbackRetireShallowNodes](er)) } @@ -577,7 +654,7 @@ module.exports = cls => class Reifier extends cls { // we need to unpack them, read that shrinkwrap file, and then update // the tree by calling loadVirtual with the node as the root. [_loadShrinkwrapsAndUpdateTrees] () { - const seen = this[_shrinkwrapInflated] + const seen = this.#shrinkwrapInflated const shrinkwraps = this.diff.leaves .filter(d => (d.action === 'CHANGE' || d.action === 'ADD' || !d.action) && d.ideal.hasShrinkwrap && !seen.has(d.ideal) && @@ -587,7 +664,7 @@ module.exports = cls => class Reifier extends cls { return } - process.emit('time', 'reify:loadShrinkwraps') + const timeEnd = time.start('reify:loadShrinkwraps') const Arborist = this.constructor return promiseAllRejectLate(shrinkwraps.map(diff => { @@ -604,7 +681,7 @@ module.exports = cls => class Reifier extends cls { .then(() => this[_createSparseTree]()) .then(() => this[_addOmitsToTrashList]()) .then(() => this[_loadShrinkwrapsAndUpdateTrees]()) - .then(() => process.emit('timeEnd', 'reify:loadShrinkwraps')) + .then(timeEnd) } // create a symlink for Links, extract for Nodes @@ -619,8 +696,7 @@ module.exports = cls => class Reifier extends cls { return node } - const timer = `reifyNode:${node.location}` - process.emit('time', timer) + const timeEnd = time.start(`reifyNode:${node.location}`) this.addTracker('reify', node.name, node.location) const { npmVersion, nodeVersion, cpu, os, libc } = this.options @@ -636,35 +712,40 @@ module.exports = cls => class Reifier extends cls { checkPlatform(node.package, false, { cpu, os, libc }) } await this[_checkBins](node) - await this[_extractOrLink](node) - await this[_warnDeprecated](node) + await this.#extractOrLink(node) + const { _id, deprecated } = node.package + // The .catch is in _handleOptionalFailure. Not ideal, this should be cleaned up. + // eslint-disable-next-line promise/always-return + if (deprecated) { + log.warn('deprecated', `${_id}: ${deprecated}`) + } }) return this[_handleOptionalFailure](node, p) .then(() => { this.finishTracker('reify', node.name, node.location) - process.emit('timeEnd', timer) + timeEnd() return node }) } // do not allow node_modules to be a symlink - async [_validateNodeModules] (nm) { - if (this.options.force || this[_nmValidated].has(nm)) { + async #validateNodeModules (nm) { + if (this.options.force || this.#nmValidated.has(nm)) { return } const st = await lstat(nm).catch(() => null) if (!st || st.isDirectory()) { - this[_nmValidated].add(nm) + this.#nmValidated.add(nm) return } log.warn('reify', 'Removing non-directory', nm) await rm(nm, { recursive: true, force: true }) } - async [_extractOrLink] (node) { + async #extractOrLink (node) { const nm = resolve(node.parent.path, 'node_modules') - await this[_validateNodeModules](nm) + await this.#validateNodeModules(nm) if (!node.isLink) { // in normal cases, node.resolved should *always* be set by now. @@ -676,7 +757,7 @@ module.exports = cls => class Reifier extends cls { // entirely, since we can't possibly reify it. let res = null if (node.resolved) { - const registryResolved = this[_registryResolved](node.resolved) + const registryResolved = this.#registryResolved(node.resolved) if (registryResolved) { res = `${node.name}@${registryResolved}` } @@ -698,7 +779,7 @@ module.exports = cls => class Reifier extends cls { return } await debug(async () => { - const st = await lstat(node.path).catch(e => null) + const st = await lstat(node.path).catch(() => null) if (st && !st.isDirectory()) { debug.log('unpacking into a non-directory', node) throw Object.assign(new Error('ENOTDIR: not a directory'), { @@ -722,10 +803,8 @@ module.exports = cls => class Reifier extends cls { // node.isLink await rm(node.path, { recursive: true, force: true }) - await this[_symlink](node) - } - async [_symlink] (node) { + // symlink const dir = dirname(node.path) const target = node.realpath const rel = relative(dir, target) @@ -733,17 +812,10 @@ module.exports = cls => class Reifier extends cls { return symlink(rel, node.path, 'junction') } - [_warnDeprecated] (node) { - const { _id, deprecated } = node.package - if (deprecated) { - log.warn('deprecated', `${_id}: ${deprecated}`) - } - } - // if the node is optional, then the failure of the promise is nonfatal // just add it and its optional set to the trash list. [_handleOptionalFailure] (node, p) { - return (node.optional ? p.catch(er => { + return (node.optional ? p.catch(() => { const set = optionalSet(node) for (node of set) { log.verbose('reify', 'failed optional dependency', node.path) @@ -752,7 +824,7 @@ module.exports = cls => class Reifier extends cls { }) : p).then(() => node) } - [_registryResolved] (resolved) { + #registryResolved (resolved) { // the default registry url is a magic value meaning "the currently // configured registry". // `resolved` must never be falsey. @@ -782,21 +854,51 @@ module.exports = cls => class Reifier extends cls { // by the contents of the package. however, in their case, rather than // shipping a virtual tree that must be reified, they ship an entire // reified actual tree that must be unpacked and not modified. - [_loadBundlesAndUpdateTrees] ( - depth = 0, bundlesByDepth = this[_getBundlesByDepth]() - ) { + [_loadBundlesAndUpdateTrees] (depth = 0, bundlesByDepth) { + let maxBundleDepth + if (!bundlesByDepth) { + bundlesByDepth = new Map() + maxBundleDepth = -1 + dfwalk({ + tree: this.diff, + visit: diff => { + const node = diff.ideal + if (!node) { + return + } + if (node.isProjectRoot) { + return + } + + const { bundleDependencies } = node.package + if (bundleDependencies && bundleDependencies.length) { + maxBundleDepth = Math.max(maxBundleDepth, node.depth) + if (!bundlesByDepth.has(node.depth)) { + bundlesByDepth.set(node.depth, [node]) + } else { + bundlesByDepth.get(node.depth).push(node) + } + } + }, + getChildren: diff => diff.children, + }) + + bundlesByDepth.set('maxBundleDepth', maxBundleDepth) + } else { + maxBundleDepth = bundlesByDepth.get('maxBundleDepth') + } + if (depth === 0) { - process.emit('time', 'reify:loadBundles') + time.start('reify:loadBundles') } - const maxBundleDepth = bundlesByDepth.get('maxBundleDepth') if (depth > maxBundleDepth) { // if we did something, then prune the tree and update the diffs if (maxBundleDepth !== -1) { - this[_pruneBundledMetadeps](bundlesByDepth) + this.#pruneBundledMetadeps(bundlesByDepth) this[_diffTrees]() } - process.emit('timeEnd', 'reify:loadBundles') + time.end('reify:loadBundles') return } @@ -814,7 +916,7 @@ module.exports = cls => class Reifier extends cls { // extract all the nodes with bundles return promiseCallLimit(set.map(node => { return () => { - this[_bundleUnpacked].add(node) + this.#bundleUnpacked.add(node) return this[_reifyNode](node) } }), { rejectLate: true }) @@ -843,46 +945,15 @@ module.exports = cls => class Reifier extends cls { }, }) for (const name of notTransplanted) { - this[_bundleMissing].add(node.children.get(name)) + this.#bundleMissing.add(node.children.get(name)) } }))) // move onto the next level of bundled items .then(() => this[_loadBundlesAndUpdateTrees](depth + 1, bundlesByDepth)) } - [_getBundlesByDepth] () { - const bundlesByDepth = new Map() - let maxBundleDepth = -1 - dfwalk({ - tree: this.diff, - visit: diff => { - const node = diff.ideal - if (!node) { - return - } - if (node.isProjectRoot) { - return - } - - const { bundleDependencies } = node.package - if (bundleDependencies && bundleDependencies.length) { - maxBundleDepth = Math.max(maxBundleDepth, node.depth) - if (!bundlesByDepth.has(node.depth)) { - bundlesByDepth.set(node.depth, [node]) - } else { - bundlesByDepth.get(node.depth).push(node) - } - } - }, - getChildren: diff => diff.children, - }) - - bundlesByDepth.set('maxBundleDepth', maxBundleDepth) - return bundlesByDepth - } - // https://github.com/npm/cli/issues/1597#issuecomment-667639545 - [_pruneBundledMetadeps] (bundlesByDepth) { + #pruneBundledMetadeps (bundlesByDepth) { const bundleShadowed = new Set() // Example dep graph: @@ -981,7 +1052,7 @@ module.exports = cls => class Reifier extends cls { // before finishing the reify() and returning the tree. Thus, we do // NOT return the promise, as the intent is for this to run in parallel // with the reification, and be resolved at a later time. - process.emit('time', 'reify:audit') + const timeEnd = time.start('reify:audit') const options = { ...this.options } const tree = this.idealTree @@ -995,7 +1066,7 @@ module.exports = cls => class Reifier extends cls { } this.auditReport = AuditReport.load(tree, options).then(res => { - process.emit('timeEnd', 'reify:audit') + timeEnd() return res }) } @@ -1005,7 +1076,7 @@ module.exports = cls => class Reifier extends cls { // kicking off each unpack job. If any fail, we rm the sparse // tree entirely and try to put everything back where it was. [_unpackNewModules] () { - process.emit('time', 'reify:unpack') + const timeEnd = time.start('reify:unpack') const unpacks = [] dfwalk({ tree: this.diff, @@ -1016,9 +1087,9 @@ module.exports = cls => class Reifier extends cls { } const node = diff.ideal - const bd = this[_bundleUnpacked].has(node) - const sw = this[_shrinkwrapInflated].has(node) - const bundleMissing = this[_bundleMissing].has(node) + const bd = this.#bundleUnpacked.has(node) + const sw = this.#shrinkwrapInflated.has(node) + const bundleMissing = this.#bundleMissing.has(node) // check whether we still need to unpack this one. // test the inDepBundle last, since that's potentially a tree walk. @@ -1038,8 +1109,7 @@ module.exports = cls => class Reifier extends cls { }, getChildren: diff => diff.children, }) - return promiseAllRejectLate(unpacks) - .then(() => process.emit('timeEnd', 'reify:unpack')) + return promiseAllRejectLate(unpacks).then(timeEnd) } // This is the part where we move back the unchanging nodes that were @@ -1054,9 +1124,9 @@ module.exports = cls => class Reifier extends cls { // This is sort of an inverse diff tree, of all the nodes where // the actualTree and idealTree _don't_ differ, starting from the // shallowest nodes that we moved aside in the first place. - process.emit('time', 'reify:unretire') - const moves = this[_retiredPaths] - this[_retiredUnchanged] = {} + const timeEnd = time.start('reify:unretire') + const moves = this.#retiredPaths + this.#retiredUnchanged = {} return promiseAllRejectLate(this.diff.children.map(diff => { // skip if nothing was retired if (diff.action !== 'CHANGE' && diff.action !== 'REMOVE') { @@ -1079,7 +1149,7 @@ module.exports = cls => class Reifier extends cls { } }) - this[_retiredUnchanged][retireFolder] = [] + this.#retiredUnchanged[retireFolder] = [] return promiseAllRejectLate(diff.unchanged.map(node => { // no need to roll back links, since we'll just delete them anyway if (node.isLink) { @@ -1088,11 +1158,11 @@ module.exports = cls => class Reifier extends cls { } // will have been moved/unpacked along with bundler - if (node.inDepBundle && !this[_bundleMissing].has(node)) { + if (node.inDepBundle && !this.#bundleMissing.has(node)) { return } - this[_retiredUnchanged][retireFolder].push(node) + this.#retiredUnchanged[retireFolder].push(node) const rel = relative(realFolder, node.path) const fromPath = resolve(retireFolder, rel) @@ -1102,8 +1172,7 @@ module.exports = cls => class Reifier extends cls { const dir = bd && bd.length ? node.path + '/node_modules' : node.path return mkdir(dir, { recursive: true }).then(() => this[_moveContents](node, fromPath)) })) - })) - .then(() => process.emit('timeEnd', 'reify:unretire')) + })).then(timeEnd) } // move the contents from the fromPath to the node.path @@ -1120,10 +1189,10 @@ module.exports = cls => class Reifier extends cls { } [_rollbackMoveBackRetiredUnchanged] (er) { - const moves = this[_retiredPaths] + const moves = this.#retiredPaths // flip the mapping around to go back const realFolders = new Map(Object.entries(moves).map(([k, v]) => [v, k])) - const promises = Object.entries(this[_retiredUnchanged]) + const promises = Object.entries(this.#retiredUnchanged) .map(([retireFolder, nodes]) => promiseAllRejectLate(nodes.map(node => { const realFolder = realFolders.get(retireFolder) const rel = relative(realFolder, node.path) @@ -1135,7 +1204,7 @@ module.exports = cls => class Reifier extends cls { } [_build] () { - process.emit('time', 'reify:build') + const timeEnd = time.start('reify:build') // for all the things being installed, run their appropriate scripts // run in tip->root order, so as to be more likely to build a node's @@ -1167,8 +1236,7 @@ module.exports = cls => class Reifier extends cls { } } - return this.rebuild({ nodes, handleOptionalFailure: true }) - .then(() => process.emit('timeEnd', 'reify:build')) + return this.rebuild({ nodes, handleOptionalFailure: true }).then(timeEnd) } // the tree is pretty much built now, so it's cleanup time. @@ -1176,7 +1244,7 @@ module.exports = cls => class Reifier extends cls { // If this fails, there isn't much we can do but tell the user about it. // Thankfully, it's pretty unlikely that it'll fail, since rm is a node builtin. async [_removeTrash] () { - process.emit('time', 'reify:trash') + const timeEnd = time.start('reify:trash') const promises = [] const failures = [] const _rm = path => rm(path, { recursive: true, force: true }).catch(er => failures.push([path, er])) @@ -1189,7 +1257,8 @@ module.exports = cls => class Reifier extends cls { if (failures.length) { log.warn('cleanup', 'Failed to remove some directories', failures) } - process.emit('timeEnd', 'reify:trash') + + timeEnd() } // last but not least, we save the ideal tree metadata to the package-lock @@ -1215,14 +1284,14 @@ module.exports = cls => class Reifier extends cls { const saveIdealTree = !( (!save && !hasUpdates) || this.options.global - || this[_dryRun] + || this.options.dryRun ) if (!saveIdealTree) { return false } - process.emit('time', 'reify:save') + const timeEnd = time.start('reify:save') const updatedTrees = new Set() const updateNodes = nodes => { @@ -1251,7 +1320,7 @@ module.exports = cls => class Reifier extends cls { const isLocalDep = req.type === 'directory' || req.type === 'file' if (req.registry) { const version = child.version - const prefixRange = version ? this[_savePrefix] + version : '*' + const prefixRange = version ? this.options.savePrefix + version : '*' // if we installed a range, then we save the range specified // if it is not a subset of the ^x.y.z. eg, installing a range // of `1.x <1.2.3` will not be saved as `^1.2.0`, because that @@ -1286,7 +1355,7 @@ module.exports = cls => class Reifier extends cls { // using their relative path if (edge.type === 'workspace') { const { version } = edge.to.target - const prefixRange = version ? this[_savePrefix] + version : '*' + const prefixRange = version ? this.options.savePrefix + version : '*' newSpec = prefixRange } else { // save the relative path in package.json @@ -1455,154 +1524,12 @@ module.exports = cls => class Reifier extends cls { // TODO this ignores options.save await this.idealTree.meta.save({ - format: (this[_formatPackageLock] && format) ? format - : this[_formatPackageLock], + format: (this.options.formatPackageLock && format) ? format + : this.options.formatPackageLock, }) } - process.emit('timeEnd', 'reify:save') + timeEnd() return true } - - async [_copyIdealToActual] () { - // clean up any trash that is still in the tree - for (const path of this[_trashList]) { - const loc = relpath(this.idealTree.realpath, path) - const node = this.idealTree.inventory.get(loc) - if (node && node.root === this.idealTree) { - node.parent = null - } - } - - // if we filtered to only certain nodes, then anything ELSE needs - // to be untouched in the resulting actual tree, even if it differs - // in the idealTree. Copy over anything that was in the actual and - // was not changed, delete anything in the ideal and not actual. - // Then we move the entire idealTree over to this.actualTree, and - // save the hidden lockfile. - if (this.diff && this.diff.filterSet.size) { - const reroot = new Set() - - const { filterSet } = this.diff - const seen = new Set() - for (const [loc, ideal] of this.idealTree.inventory.entries()) { - seen.add(loc) - - // if it's an ideal node from the filter set, then skip it - // because we already made whatever changes were necessary - if (filterSet.has(ideal)) { - continue - } - - // otherwise, if it's not in the actualTree, then it's not a thing - // that we actually added. And if it IS in the actualTree, then - // it's something that we left untouched, so we need to record - // that. - const actual = this.actualTree.inventory.get(loc) - if (!actual) { - ideal.root = null - } else { - if ([...actual.linksIn].some(link => filterSet.has(link))) { - seen.add(actual.location) - continue - } - const { realpath, isLink } = actual - if (isLink && ideal.isLink && ideal.realpath === realpath) { - continue - } else { - reroot.add(actual) - } - } - } - - // now find any actual nodes that may not be present in the ideal - // tree, but were left behind by virtue of not being in the filter - for (const [loc, actual] of this.actualTree.inventory.entries()) { - if (seen.has(loc)) { - continue - } - seen.add(loc) - - // we know that this is something that ISN'T in the idealTree, - // or else we will have addressed it in the previous loop. - // If it's in the filterSet, that means we intentionally removed - // it, so nothing to do here. - if (filterSet.has(actual)) { - continue - } - - reroot.add(actual) - } - - // go through the rerooted actual nodes, and move them over. - for (const actual of reroot) { - actual.root = this.idealTree - } - - // prune out any tops that lack a linkIn, they are no longer relevant. - for (const top of this.idealTree.tops) { - if (top.linksIn.size === 0) { - top.root = null - } - } - - // need to calculate dep flags, since nodes may have been marked - // as extraneous or otherwise incorrect during transit. - calcDepFlags(this.idealTree) - } - - // save the ideal's meta as a hidden lockfile after we actualize it - this.idealTree.meta.filename = - this.idealTree.realpath + '/node_modules/.package-lock.json' - this.idealTree.meta.hiddenLockfile = true - this.idealTree.meta.lockfileVersion = defaultLockfileVersion - - this.actualTree = this.idealTree - this.idealTree = null - - if (!this.options.global) { - await this.actualTree.meta.save() - const ignoreScripts = !!this.options.ignoreScripts - // if we aren't doing a dry run or ignoring scripts and we actually made changes to the dep - // tree, then run the dependencies scripts - if (!this[_dryRun] && !ignoreScripts && this.diff && this.diff.children.length) { - const { path, package: pkg } = this.actualTree.target - const stdio = this.options.foregroundScripts ? 'inherit' : 'pipe' - const { scripts = {} } = pkg - for (const event of ['predependencies', 'dependencies', 'postdependencies']) { - if (Object.prototype.hasOwnProperty.call(scripts, event)) { - const timer = `reify:run:${event}` - process.emit('time', timer) - log.info('run', pkg._id, event, scripts[event]) - await runScript({ - event, - path, - pkg, - stdio, - scriptShell: this.options.scriptShell, - }) - process.emit('timeEnd', timer) - } - } - } - } - } - - async dedupe (options = {}) { - // allow the user to set options on the ctor as well. - // XXX: deprecate separate method options objects. - options = { ...this.options, ...options } - const tree = await this.loadVirtual().catch(() => this.loadActual()) - const names = [] - for (const name of tree.inventory.query('name')) { - if (tree.inventory.query('name', name).size > 1) { - names.push(name) - } - } - return this.reify({ - ...options, - preferDedupe: true, - update: { names }, - }) - } } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/audit-report.js b/deps/npm/node_modules/@npmcli/arborist/lib/audit-report.js index 387919f610829e..f7700ce9119de3 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/audit-report.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/audit-report.js @@ -13,7 +13,7 @@ const _fixAvailable = Symbol('fixAvailable') const _checkTopNode = Symbol('checkTopNode') const _init = Symbol('init') const _omit = Symbol('omit') -const log = require('proc-log') +const { log, time } = require('proc-log') const fetch = require('npm-registry-fetch') @@ -117,7 +117,7 @@ class AuditReport extends Map { } async [_init] () { - process.emit('time', 'auditReport:init') + const timeEnd = time.start('auditReport:init') const promises = [] for (const [name, advisories] of Object.entries(this.report)) { @@ -210,7 +210,8 @@ class AuditReport extends Map { } } } - process.emit('timeEnd', 'auditReport:init') + + timeEnd() } [_checkTopNode] (topNode, vuln, spec) { @@ -306,7 +307,7 @@ class AuditReport extends Map { return null } - process.emit('time', 'auditReport:getReport') + const timeEnd = time.start('auditReport:getReport') try { try { // first try the super fast bulk advisory listing @@ -347,7 +348,7 @@ class AuditReport extends Map { this.error = er return null } finally { - process.emit('timeEnd', 'auditReport:getReport') + timeEnd() } } } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/dep-valid.js b/deps/npm/node_modules/@npmcli/arborist/lib/dep-valid.js index 4afb5e47cf111f..58656e8dbbad29 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/dep-valid.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/dep-valid.js @@ -124,7 +124,7 @@ const linkValid = (child, requested, requestor) => { return isLink && relative(child.realpath, requested.fetchSpec) === '' } -const tarballValid = (child, requested, requestor) => { +const tarballValid = (child, requested) => { if (child.isLink) { return false } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/inventory.js b/deps/npm/node_modules/@npmcli/arborist/lib/inventory.js index 0885034666b50a..7b3f294fdab2c3 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/inventory.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/inventory.js @@ -130,7 +130,7 @@ class Inventory extends Map { return super.get(node.location) === node } - set (k, v) { + set () { throw new Error('direct set() not supported, use inventory.add(node)') } } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js b/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js index e757d0c38a6d70..fca36eb6856137 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js @@ -8,8 +8,8 @@ // a result. const localeCompare = require('@isaacs/string-locale-compare')('en') -const log = require('proc-log') -const { cleanUrl } = require('npm-registry-fetch') +const { log } = require('proc-log') +const { redact } = require('@npmcli/redact') const deepestNestingTarget = require('./deepest-nesting-target.js') const CanPlaceDep = require('./can-place-dep.js') const { @@ -188,7 +188,7 @@ class PlaceDep { `${this.dep.name}@${this.dep.version}`, this.canPlace.description, `for: ${this.edge.from.package._id || this.edge.from.location}`, - `want: ${cleanUrl(this.edge.spec || '*')}` + `want: ${redact(this.edge.spec || '*')}` ) const placementType = this.canPlace.canPlace === CONFLICT diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/query-selector-all.js b/deps/npm/node_modules/@npmcli/arborist/lib/query-selector-all.js index ce49201ce624c6..77640a3803d13b 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/query-selector-all.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/query-selector-all.js @@ -3,7 +3,7 @@ const { resolve } = require('path') const { parser, arrayDelimiter } = require('@npmcli/query') const localeCompare = require('@isaacs/string-locale-compare')('en') -const log = require('proc-log') +const { log } = require('proc-log') const { minimatch } = require('minimatch') const npa = require('npm-package-arg') const pacote = require('pacote') @@ -257,7 +257,12 @@ class Results { for (const edge of node.edgesOut.values()) { if (edge.missing) { const pkg = { name: edge.name, version: edge.spec } - res.push(new this.#targetNode.constructor({ pkg })) + const item = new this.#targetNode.constructor({ pkg }) + item.queryContext = { + missing: true, + } + item.edgesIn = new Set([edge]) + res.push(item) } } return res @@ -645,27 +650,27 @@ class Results { // operators for attribute selectors const attributeOperators = { // attribute value is equivalent - '=' ({ attr, value, insensitive }) { + '=' ({ attr, value }) { return attr === value }, // attribute value contains word - '~=' ({ attr, value, insensitive }) { + '~=' ({ attr, value }) { return (attr.match(/\w+/g) || []).includes(value) }, // attribute value contains string - '*=' ({ attr, value, insensitive }) { + '*=' ({ attr, value }) { return attr.includes(value) }, // attribute value is equal or starts with - '|=' ({ attr, value, insensitive }) { + '|=' ({ attr, value }) { return attr.startsWith(`${value}-`) }, // attribute value starts with - '^=' ({ attr, value, insensitive }) { + '^=' ({ attr, value }) { return attr.startsWith(value) }, // attribute value ends with - '$=' ({ attr, value, insensitive }) { + '$=' ({ attr, value }) { return attr.endsWith(value) }, } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js index e6525ffe67b65d..026abc55ccba18 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js @@ -33,7 +33,7 @@ const mismatch = (a, b) => a && b && a !== b // After calling this.commit(), any nodes not present in the tree will have // been removed from the shrinkwrap data as well. -const log = require('proc-log') +const { log } = require('proc-log') const YarnLock = require('./yarn-lock.js') const { readFile, @@ -1145,6 +1145,7 @@ class Shrinkwrap { throw new Error('run load() before saving data') } + // This must be called before the lockfile conversion check below since it sets properties as part of `commit()` const json = this.toString(options) if ( !this.hiddenLockfile @@ -1155,6 +1156,7 @@ class Shrinkwrap { `Converting lock file (${relative(process.cwd(), this.filename)}) from v${this.originalLockfileVersion} -> v${this.lockfileVersion}` ) } + return Promise.all([ writeFile(this.filename, json).catch(er => { if (this.hiddenLockfile) { diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/tracker.js b/deps/npm/node_modules/@npmcli/arborist/lib/tracker.js index 5acb32a5a7cfd9..4a754d995dfcd2 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/tracker.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/tracker.js @@ -1,12 +1,12 @@ -const npmlog = require('npmlog') +const proggy = require('proggy') module.exports = cls => class Tracker extends cls { #progress = new Map() - #setProgress - constructor (options = {}) { - super(options) - this.#setProgress = !!options.progress + #createTracker (key, name) { + const tracker = new proggy.Tracker(name ?? key) + tracker.on('done', () => this.#progress.delete(key)) + this.#progress.set(key, tracker) } addTracker (section, subsection = null, key = null) { @@ -26,22 +26,17 @@ module.exports = cls => class Tracker extends cls { this.#onError(`Tracker "${section}" already exists`) } else if (!hasTracker && subsection === null) { // 1. no existing tracker, no subsection - // Create a new tracker from npmlog - // starts progress bar - if (this.#setProgress && this.#progress.size === 0) { - npmlog.enableProgress() - } - - this.#progress.set(section, npmlog.newGroup(section)) + // Create a new progress tracker + this.#createTracker(section) } else if (!hasTracker && subsection !== null) { // 2. no parent tracker and subsection this.#onError(`Parent tracker "${section}" does not exist`) } else if (!hasTracker || !hasSubtracker) { // 3. existing parent tracker, no subsection tracker - // Create a new subtracker in this.#progress from parent tracker - this.#progress.set(`${section}:${key}`, - this.#progress.get(section).newGroup(`${section}:${subsection}`) - ) + // Create a new subtracker and update parents + const parentTracker = this.#progress.get(section) + parentTracker.update(parentTracker.value, parentTracker.total + 1) + this.#createTracker(`${section}:${key}`, `${section}:${subsection}`) } // 4. existing parent tracker, existing subsection tracker // skip it @@ -70,32 +65,22 @@ module.exports = cls => class Tracker extends cls { this.finishTracker(section, key) } } - // remove parent tracker this.#progress.get(section).finish() - this.#progress.delete(section) - - // remove progress bar if all - // trackers are finished - if (this.#setProgress && this.#progress.size === 0) { - npmlog.disableProgress() - } } else if (!hasTracker && subsection === null) { // 1. no existing parent tracker, no subsection this.#onError(`Tracker "${section}" does not exist`) } else if (!hasTracker || hasSubtracker) { // 2. subtracker exists // Finish subtracker and remove from this.#progress + const parentTracker = this.#progress.get(section) + parentTracker.update(parentTracker.value + 1) this.#progress.get(`${section}:${key}`).finish() - this.#progress.delete(`${section}:${key}`) } // 3. existing parent tracker, no subsection } #onError (msg) { - if (this.#setProgress) { - npmlog.disableProgress() - } throw new Error(msg) } } diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json index c761bc10d6cec2..11c0ab4df3b529 100644 --- a/deps/npm/node_modules/@npmcli/arborist/package.json +++ b/deps/npm/node_modules/@npmcli/arborist/package.json @@ -1,34 +1,35 @@ { "name": "@npmcli/arborist", - "version": "7.4.0", + "version": "7.5.1", "description": "Manage node_modules trees", "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/fs": "^3.1.0", - "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/installed-package-contents": "^2.1.0", "@npmcli/map-workspaces": "^3.0.2", - "@npmcli/metavuln-calculator": "^7.0.0", + "@npmcli/metavuln-calculator": "^7.1.0", "@npmcli/name-from-folder": "^2.0.0", "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.0.0", + "@npmcli/package-json": "^5.1.0", "@npmcli/query": "^3.1.0", - "@npmcli/run-script": "^7.0.2", + "@npmcli/redact": "^2.0.0", + "@npmcli/run-script": "^8.1.0", "bin-links": "^4.0.1", "cacache": "^18.0.0", "common-ancestor-path": "^1.0.1", "hosted-git-info": "^7.0.1", "json-parse-even-better-errors": "^3.0.0", "json-stringify-nice": "^1.1.4", - "minimatch": "^9.0.0", + "minimatch": "^9.0.4", "nopt": "^7.0.0", "npm-install-checks": "^6.2.0", - "npm-package-arg": "^11.0.1", + "npm-package-arg": "^11.0.2", "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^16.0.0", - "npmlog": "^7.0.1", - "pacote": "^17.0.4", + "npm-registry-fetch": "^17.0.0", + "pacote": "^18.0.1", "parse-conflict-json": "^3.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.2.0", + "proggy": "^2.0.0", "promise-all-reject-late": "^1.0.0", "promise-call-limit": "^3.0.1", "read-package-json-fast": "^3.0.2", @@ -61,7 +62,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/arborist" }, "author": "GitHub Inc.", diff --git a/deps/npm/node_modules/@npmcli/config/lib/definitions/definitions.js b/deps/npm/node_modules/@npmcli/config/lib/definitions/definitions.js index 09b0eceeea6b21..57ab1716118386 100644 --- a/deps/npm/node_modules/@npmcli/config/lib/definitions/definitions.js +++ b/deps/npm/node_modules/@npmcli/config/lib/definitions/definitions.js @@ -1,19 +1,16 @@ -const definitions = {} -module.exports = definitions - const Definition = require('./definition.js') const ciInfo = require('ci-info') -const querystring = require('querystring') -const { join } = require('path') +const querystring = require('node:querystring') +const { join } = require('node:path') const isWindows = process.platform === 'win32' // used by cafile flattening to flatOptions.ca -const fs = require('fs') +const { readFileSync } = require('fs') const maybeReadFile = file => { try { - return fs.readFileSync(file, 'utf8') + return readFileSync(file, 'utf8') } catch (er) { if (er.code !== 'ENOENT') { throw er @@ -91,20 +88,12 @@ const cache = `${cacheRoot}/${cacheExtra}` // weird to pull out of the config module. // TODO: use better type definition/validation API, nopt's is so weird. const { - semver: { type: semver }, + semver: { type: Semver }, Umask: { type: Umask }, url: { type: url }, path: { type: path }, } = require('../type-defs.js') -const define = (key, def) => { - /* istanbul ignore if - this should never happen, prevents mistakes below */ - if (definitions[key]) { - throw new Error(`defining key more than once: ${key}`) - } - definitions[key] = new Definition(key, def) -} - // basic flattening function, just copy it over camelCase const flatten = (key, obj, flatOptions) => { const camel = key.replace(/-([a-z])/g, (_0, _1) => _1.toUpperCase()) @@ -135,12 +124,20 @@ const flatten = (key, obj, flatOptions) => { // while fixing some Arborist bug, we won't have to hunt through too // many places. -// Define all config keys we know about +// XXX: We should really deprecate all these `--save-blah` switches +// in favor of a single `--save-type` option. The unfortunate shortcut +// we took for `--save-peer --save-optional` being `--save-type=peerOptional` +// makes this tricky, and likely a breaking change. + +// Define all config keys we know about. They are indexed by their own key for +// ease of lookup later. This duplication is an optimization so that we don't +// have to do an extra function call just to "reuse" the key in both places. -define('_auth', { - default: null, - type: [null, String], - description: ` +const definitions = { + _auth: new Definition('_auth', { + default: null, + type: [null, String], + description: ` A basic-auth string to use when authenticating against the npm registry. This will ONLY be used to authenticate against the npm registry. For other registries you will need to scope it like "//other-registry.tld/:_auth" @@ -149,16 +146,15 @@ define('_auth', { is safer to use a registry-provided authentication bearer token stored in the ~/.npmrc file by running \`npm login\`. `, - flatten, -}) - -define('access', { - default: null, - defaultDescription: ` + flatten, + }), + access: new Definition('access', { + default: null, + defaultDescription: ` 'public' for new packages, existing packages it will not change the current level `, - type: [null, 'restricted', 'public'], - description: ` + type: [null, 'restricted', 'public'], + description: ` If you do not want your scoped package to be publicly viewable (and installable) set \`--access=restricted\`. @@ -169,131 +165,121 @@ define('access', { publish will change the access for an existing package the same way that \`npm access set status\` would. `, - flatten, -}) - -define('all', { - default: false, - type: Boolean, - short: 'a', - description: ` + flatten, + }), + all: new Definition('all', { + default: false, + type: Boolean, + short: 'a', + description: ` When running \`npm outdated\` and \`npm ls\`, setting \`--all\` will show all outdated or installed packages, rather than only those directly depended upon by the current project. `, - flatten, -}) - -define('allow-same-version', { - default: false, - type: Boolean, - description: ` + flatten, + }), + 'allow-same-version': new Definition('allow-same-version', { + default: false, + type: Boolean, + description: ` Prevents throwing an error when \`npm version\` is used to set the new version to the same value as the current version. `, - flatten, -}) - -define('also', { - default: null, - type: [null, 'dev', 'development'], - description: ` - When set to \`dev\` or \`development\`, this is an alias for - \`--include=dev\`. - `, - deprecated: 'Please use --include=dev instead.', - flatten (key, obj, flatOptions) { - definitions.omit.flatten('omit', obj, flatOptions) - }, -}) - -define('audit', { - default: true, - type: Boolean, - description: ` - When "true" submit audit reports alongside the current npm command to the - default registry and all registries configured for scopes. See the - documentation for [\`npm audit\`](/commands/npm-audit) for details on what - is submitted. - `, - flatten, -}) - -define('audit-level', { - default: null, - type: [null, 'info', 'low', 'moderate', 'high', 'critical', 'none'], - description: ` + flatten, + }), + also: new Definition('also', { + default: null, + type: [null, 'dev', 'development'], + description: ` + When set to \`dev\` or \`development\`, this is an alias for + \`--include=dev\`. + `, + deprecated: 'Please use --include=dev instead.', + flatten (key, obj, flatOptions) { + definitions.omit.flatten('omit', obj, flatOptions) + }, + }), + audit: new Definition('audit', { + default: true, + type: Boolean, + description: ` + When "true" submit audit reports alongside the current npm command to the + default registry and all registries configured for scopes. See the + documentation for [\`npm audit\`](/commands/npm-audit) for details on what + is submitted. + `, + flatten, + }), + 'audit-level': new Definition('audit-level', { + default: null, + type: [null, 'info', 'low', 'moderate', 'high', 'critical', 'none'], + description: ` The minimum level of vulnerability for \`npm audit\` to exit with a non-zero exit code. - `, - flatten, -}) - -define('auth-type', { - default: 'web', - type: ['legacy', 'web'], - description: ` - What authentication strategy to use with \`login\`. - Note that if an \`otp\` config is given, this value will always be set to \`legacy\`. - `, - flatten, -}) - -define('before', { - default: null, - type: [null, Date], - description: ` - If passed to \`npm install\`, will rebuild the npm tree such that only - versions that were available **on or before** the \`--before\` time get - installed. If there's no versions available for the current set of - direct dependencies, the command will error. - - If the requested version is a \`dist-tag\` and the given tag does not - pass the \`--before\` filter, the most recent version less than or equal - to that tag will be used. For example, \`foo@latest\` might install - \`foo@1.2\` even though \`latest\` is \`2.0\`. - `, - flatten, -}) - -define('bin-links', { - default: true, - type: Boolean, - description: ` - Tells npm to create symlinks (or \`.cmd\` shims on Windows) for package - executables. - - Set to false to have it not do this. This can be used to work around the - fact that some file systems don't support symlinks, even on ostensibly - Unix systems. - `, - flatten, -}) - -define('browser', { - default: null, - defaultDescription: ` + `, + flatten, + }), + 'auth-type': new Definition('auth-type', { + default: 'web', + type: ['legacy', 'web'], + description: ` + What authentication strategy to use with \`login\`. + Note that if an \`otp\` config is given, this value will always be set to \`legacy\`. + `, + flatten, + }), + before: new Definition('before', { + default: null, + type: [null, Date], + description: ` + If passed to \`npm install\`, will rebuild the npm tree such that only + versions that were available **on or before** the \`--before\` time get + installed. If there's no versions available for the current set of + direct dependencies, the command will error. + + If the requested version is a \`dist-tag\` and the given tag does not + pass the \`--before\` filter, the most recent version less than or equal + to that tag will be used. For example, \`foo@latest\` might install + \`foo@1.2\` even though \`latest\` is \`2.0\`. + `, + flatten, + }), + 'bin-links': new Definition('bin-links', { + default: true, + type: Boolean, + description: ` + Tells npm to create symlinks (or \`.cmd\` shims on Windows) for package + executables. + + Set to false to have it not do this. This can be used to work around the + fact that some file systems don't support symlinks, even on ostensibly + Unix systems. + `, + flatten, + }), + browser: new Definition('browser', { + default: null, + defaultDescription: ` OS X: \`"open"\`, Windows: \`"start"\`, Others: \`"xdg-open"\` - `, - type: [null, Boolean, String], - description: ` + `, + type: [null, Boolean, String], + description: ` The browser that is called by npm commands to open websites. Set to \`false\` to suppress browser behavior and instead print urls to terminal. Set to \`true\` to use default system URL opener. - `, - flatten, -}) - -define('ca', { - default: null, - type: [null, String, Array], - description: ` + `, + flatten, + }), + ca: new Definition('ca', { + default: null, + type: [null, String, Array], + description: ` The Certificate Authority signing certificate that is trusted for SSL connections to the registry. Values should be in PEM format (Windows - calls it "Base-64 encoded X.509 (.CER)") with newlines replaced by the + calls it "Base-64 encoded X.509 (.CER)") with newlines replaced by the string "\\n". For example: \`\`\`ini @@ -312,2124 +298,1979 @@ define('ca', { See also the \`strict-ssl\` config. `, - flatten, -}) - -define('cache', { - default: cache, - defaultDescription: ` - Windows: \`%LocalAppData%\\npm-cache\`, Posix: \`~/.npm\` - `, - type: path, - description: ` - The location of npm's cache directory. - `, - flatten (key, obj, flatOptions) { - flatOptions.cache = join(obj.cache, '_cacache') - flatOptions.npxCache = join(obj.cache, '_npx') - flatOptions.tufCache = join(obj.cache, '_tuf') - }, -}) - -define('cache-max', { - default: Infinity, - type: Number, - description: ` - \`--cache-max=0\` is an alias for \`--prefer-online\` - `, - deprecated: ` - This option has been deprecated in favor of \`--prefer-online\` - `, - flatten (key, obj, flatOptions) { - if (obj[key] <= 0) { - flatOptions.preferOnline = true - } - }, -}) - -define('cache-min', { - default: 0, - type: Number, - description: ` - \`--cache-min=9999 (or bigger)\` is an alias for \`--prefer-offline\`. - `, - deprecated: ` - This option has been deprecated in favor of \`--prefer-offline\`. - `, - flatten (key, obj, flatOptions) { - if (obj[key] >= 9999) { - flatOptions.preferOffline = true - } - }, -}) - -define('cafile', { - default: null, - type: path, - description: ` - A path to a file containing one or multiple Certificate Authority signing - certificates. Similar to the \`ca\` setting, but allows for multiple - CA's, as well as for the CA information to be stored in a file on disk. - `, - flatten (key, obj, flatOptions) { - // always set to null in defaults - if (!obj.cafile) { - return - } - - const raw = maybeReadFile(obj.cafile) - if (!raw) { - return - } - - const delim = '-----END CERTIFICATE-----' - flatOptions.ca = raw.replace(/\r\n/g, '\n').split(delim) - .filter(section => section.trim()) - .map(section => section.trimLeft() + delim) - }, -}) - -define('call', { - default: '', - type: String, - short: 'c', - description: ` - Optional companion option for \`npm exec\`, \`npx\` that allows for - specifying a custom command to be run along with the installed packages. - - \`\`\`bash - npm exec --package yo --package generator-node --call "yo node" - \`\`\` - `, - flatten, -}) - -define('cert', { - default: null, - type: [null, String], - description: ` - A client certificate to pass when accessing the registry. Values should - be in PEM format (Windows calls it "Base-64 encoded X.509 (.CER)") with - newlines replaced by the string "\\n". For example: - - \`\`\`ini - cert="-----BEGIN CERTIFICATE-----\\nXXXX\\nXXXX\\n-----END CERTIFICATE-----" - \`\`\` - - It is _not_ the path to a certificate file, though you can set a registry-scoped - "certfile" path like "//other-registry.tld/:certfile=/path/to/cert.pem". - `, - deprecated: ` - \`key\` and \`cert\` are no longer used for most registry operations. - Use registry scoped \`keyfile\` and \`certfile\` instead. - Example: - //other-registry.tld/:keyfile=/path/to/key.pem - //other-registry.tld/:certfile=/path/to/cert.crt - `, - flatten, -}) - -define('cidr', { - default: null, - type: [null, String, Array], - description: ` - This is a list of CIDR address to be used when configuring limited access - tokens with the \`npm token create\` command. - `, - flatten, -}) - -// This should never be directly used, the flattened value is the derived value -// and is sent to other modules, and is also exposed as `npm.color` for use -// inside npm itself. -define('color', { - default: !process.env.NO_COLOR || process.env.NO_COLOR === '0', - usage: '--color|--no-color|--color always', - defaultDescription: ` - true unless the NO_COLOR environ is set to something other than '0' - `, - type: ['always', Boolean], - description: ` - If false, never shows colors. If \`"always"\` then always shows colors. - If true, then only prints color codes for tty file descriptors. - `, - flatten (key, obj, flatOptions) { - flatOptions.color = !obj.color ? false - : obj.color === 'always' ? true - : !!process.stdout.isTTY - flatOptions.logColor = !obj.color ? false - : obj.color === 'always' ? true - : !!process.stderr.isTTY - }, -}) - -define('commit-hooks', { - default: true, - type: Boolean, - description: ` - Run git commit hooks when using the \`npm version\` command. - `, - flatten, -}) - -define('cpu', { - default: null, - type: [null, String], - description: ` - Override CPU architecture of native modules to install. - Acceptable values are same as \`cpu\` field of package.json, - which comes from \`process.arch\`. - `, - flatten, -}) - -define('os', { - default: null, - type: [null, String], - description: ` - Override OS of native modules to install. - Acceptable values are same as \`os\` field of package.json, - which comes from \`process.platform\`. - `, - flatten, -}) - -define('libc', { - default: null, - type: [null, String], - description: ` - Override libc of native modules to install. - Acceptable values are same as \`libc\` field of package.json - `, - flatten, -}) - -define('depth', { - default: null, - defaultDescription: ` - \`Infinity\` if \`--all\` is set, otherwise \`1\` - `, - type: [null, Number], - description: ` - The depth to go when recursing packages for \`npm ls\`. - - If not set, \`npm ls\` will show only the immediate dependencies of the - root project. If \`--all\` is set, then npm will show all dependencies - by default. - `, - flatten, -}) - -define('description', { - default: true, - type: Boolean, - usage: '--no-description', - description: ` - Show the description in \`npm search\` - `, - flatten (key, obj, flatOptions) { - flatOptions.search = flatOptions.search || { limit: 20 } - flatOptions.search[key] = obj[key] - }, -}) - -define('dev', { - default: false, - type: Boolean, - description: ` - Alias for \`--include=dev\`. - `, - deprecated: 'Please use --include=dev instead.', - flatten (key, obj, flatOptions) { - definitions.omit.flatten('omit', obj, flatOptions) - }, -}) - -define('diff', { - default: [], - hint: '', - type: [String, Array], - description: ` - Define arguments to compare in \`npm diff\`. - `, - flatten, -}) - -define('diff-ignore-all-space', { - default: false, - type: Boolean, - description: ` - Ignore whitespace when comparing lines in \`npm diff\`. - `, - flatten, -}) - -define('diff-name-only', { - default: false, - type: Boolean, - description: ` - Prints only filenames when using \`npm diff\`. - `, - flatten, -}) - -define('diff-no-prefix', { - default: false, - type: Boolean, - description: ` - Do not show any source or destination prefix in \`npm diff\` output. - - Note: this causes \`npm diff\` to ignore the \`--diff-src-prefix\` and - \`--diff-dst-prefix\` configs. - `, - flatten, -}) - -define('diff-dst-prefix', { - default: 'b/', - hint: '', - type: String, - description: ` - Destination prefix to be used in \`npm diff\` output. - `, - flatten, -}) - -define('diff-src-prefix', { - default: 'a/', - hint: '', - type: String, - description: ` - Source prefix to be used in \`npm diff\` output. - `, - flatten, -}) - -define('diff-text', { - default: false, - type: Boolean, - description: ` - Treat all files as text in \`npm diff\`. - `, - flatten, -}) - -define('diff-unified', { - default: 3, - type: Number, - description: ` - The number of lines of context to print in \`npm diff\`. - `, - flatten, -}) - -define('dry-run', { - default: false, - type: Boolean, - description: ` - Indicates that you don't want npm to make any changes and that it should - only report what it would have done. This can be passed into any of the - commands that modify your local installation, eg, \`install\`, - \`update\`, \`dedupe\`, \`uninstall\`, as well as \`pack\` and - \`publish\`. - - Note: This is NOT honored by other network related commands, eg - \`dist-tags\`, \`owner\`, etc. - `, - flatten, -}) - -define('editor', { - default: editor, - defaultDescription: ` - The EDITOR or VISUAL environment variables, or '%SYSTEMROOT%\\notepad.exe' on Windows, - or 'vi' on Unix systems - `, - type: String, - description: ` - The command to run for \`npm edit\` and \`npm config edit\`. - `, - flatten, -}) - -define('engine-strict', { - default: false, - type: Boolean, - description: ` - If set to true, then npm will stubbornly refuse to install (or even - consider installing) any package that claims to not be compatible with - the current Node.js version. - - This can be overridden by setting the \`--force\` flag. - `, - flatten, -}) - -define('expect-results', { - default: null, - type: [null, Boolean], - exclusive: ['expect-result-count'], - description: ` - Tells npm whether or not to expect results from the command. - Can be either true (expect some results) or false (expect no results). - `, -}) - -define('expect-result-count', { - default: null, - type: [null, Number], - hint: '', - exclusive: ['expect-results'], - description: ` - Tells to expect a specific number of results from the command. - `, -}) - -define('fetch-retries', { - default: 2, - type: Number, - description: ` - The "retries" config for the \`retry\` module to use when fetching - packages from the registry. - - npm will retry idempotent read requests to the registry in the case - of network failures or 5xx HTTP errors. - `, - flatten (key, obj, flatOptions) { - flatOptions.retry = flatOptions.retry || {} - flatOptions.retry.retries = obj[key] - }, -}) - -define('fetch-retry-factor', { - default: 10, - type: Number, - description: ` - The "factor" config for the \`retry\` module to use when fetching - packages. - `, - flatten (key, obj, flatOptions) { - flatOptions.retry = flatOptions.retry || {} - flatOptions.retry.factor = obj[key] - }, -}) - -define('fetch-retry-maxtimeout', { - default: 60000, - defaultDescription: '60000 (1 minute)', - type: Number, - description: ` - The "maxTimeout" config for the \`retry\` module to use when fetching - packages. - `, - flatten (key, obj, flatOptions) { - flatOptions.retry = flatOptions.retry || {} - flatOptions.retry.maxTimeout = obj[key] - }, -}) - -define('fetch-retry-mintimeout', { - default: 10000, - defaultDescription: '10000 (10 seconds)', - type: Number, - description: ` - The "minTimeout" config for the \`retry\` module to use when fetching - packages. - `, - flatten (key, obj, flatOptions) { - flatOptions.retry = flatOptions.retry || {} - flatOptions.retry.minTimeout = obj[key] - }, -}) - -define('fetch-timeout', { - default: 5 * 60 * 1000, - defaultDescription: `${5 * 60 * 1000} (5 minutes)`, - type: Number, - description: ` - The maximum amount of time to wait for HTTP requests to complete. - `, - flatten (key, obj, flatOptions) { - flatOptions.timeout = obj[key] - }, -}) - -define('force', { - default: false, - type: Boolean, - short: 'f', - description: ` - Removes various protections against unfortunate side effects, common - mistakes, unnecessary performance degradation, and malicious input. - - * Allow clobbering non-npm files in global installs. - * Allow the \`npm version\` command to work on an unclean git repository. - * Allow deleting the cache folder with \`npm cache clean\`. - * Allow installing packages that have an \`engines\` declaration - requiring a different version of npm. - * Allow installing packages that have an \`engines\` declaration - requiring a different version of \`node\`, even if \`--engine-strict\` - is enabled. - * Allow \`npm audit fix\` to install modules outside your stated - dependency range (including SemVer-major changes). - * Allow unpublishing all versions of a published package. - * Allow conflicting peerDependencies to be installed in the root project. - * Implicitly set \`--yes\` during \`npm init\`. - * Allow clobbering existing values in \`npm pkg\` - * Allow unpublishing of entire packages (not just a single version). - - If you don't have a clear idea of what you want to do, it is strongly - recommended that you do not use this option! - `, - flatten, -}) - -define('foreground-scripts', { - default: false, - defaultDescription: `\`false\` unless when using \`npm pack\` or \`npm publish\` where it - defaults to \`true\``, - type: Boolean, - description: ` - Run all build scripts (ie, \`preinstall\`, \`install\`, and - \`postinstall\`) scripts for installed packages in the foreground - process, sharing standard input, output, and error with the main npm - process. - - Note that this will generally make installs run slower, and be much - noisier, but can be useful for debugging. - `, - flatten, -}) - -define('format-package-lock', { - default: true, - type: Boolean, - description: ` - Format \`package-lock.json\` or \`npm-shrinkwrap.json\` as a human - readable file. - `, - flatten, -}) - -define('fund', { - default: true, - type: Boolean, - description: ` - When "true" displays the message at the end of each \`npm install\` - acknowledging the number of dependencies looking for funding. - See [\`npm fund\`](/commands/npm-fund) for details. - `, - flatten, -}) - -define('git', { - default: 'git', - type: String, - description: ` - The command to use for git commands. If git is installed on the - computer, but is not in the \`PATH\`, then set this to the full path to - the git binary. - `, - flatten, -}) - -define('git-tag-version', { - default: true, - type: Boolean, - description: ` - Tag the commit when using the \`npm version\` command. Setting this to - false results in no commit being made at all. - `, - flatten, -}) - -define('global', { - default: false, - type: Boolean, - short: 'g', - description: ` - Operates in "global" mode, so that packages are installed into the - \`prefix\` folder instead of the current working directory. See - [folders](/configuring-npm/folders) for more on the differences in - behavior. - - * packages are installed into the \`{prefix}/lib/node_modules\` folder, - instead of the current working directory. - * bin files are linked to \`{prefix}/bin\` - * man pages are linked to \`{prefix}/share/man\` - `, - flatten: (key, obj, flatOptions) => { - flatten(key, obj, flatOptions) - if (flatOptions.global) { - flatOptions.location = 'global' - } - }, -}) - -// the globalconfig has its default defined outside of this module -define('globalconfig', { - type: path, - default: '', - defaultDescription: ` - The global --prefix setting plus 'etc/npmrc'. For example, - '/usr/local/etc/npmrc' - `, - description: ` - The config file to read for global config options. - `, - flatten, -}) - -define('global-style', { - default: false, - type: Boolean, - description: ` - Only install direct dependencies in the top level \`node_modules\`, - but hoist on deeper dependencies. - Sets \`--install-strategy=shallow\`. - `, - deprecated: ` - This option has been deprecated in favor of \`--install-strategy=shallow\` - `, - flatten (key, obj, flatOptions) { - if (obj[key]) { - obj['install-strategy'] = 'shallow' - flatOptions.installStrategy = 'shallow' - } - }, -}) - -define('heading', { - default: 'npm', - type: String, - description: ` - The string that starts all the debugging log output. - `, - flatten, -}) - -define('https-proxy', { - default: null, - type: [null, url], - description: ` - A proxy to use for outgoing https requests. If the \`HTTPS_PROXY\` or - \`https_proxy\` or \`HTTP_PROXY\` or \`http_proxy\` environment variables - are set, proxy settings will be honored by the underlying - \`make-fetch-happen\` library. - `, - flatten, -}) - -define('if-present', { - default: false, - type: Boolean, - envExport: false, - description: ` - If true, npm will not exit with an error code when \`run-script\` is - invoked for a script that isn't defined in the \`scripts\` section of - \`package.json\`. This option can be used when it's desirable to - optionally run a script when it's present and fail if the script fails. - This is useful, for example, when running scripts that may only apply for - some builds in an otherwise generic CI setup. - `, - flatten, -}) - -define('ignore-scripts', { - default: false, - type: Boolean, - description: ` - If true, npm does not run scripts specified in package.json files. - - Note that commands explicitly intended to run a particular script, such - as \`npm start\`, \`npm stop\`, \`npm restart\`, \`npm test\`, and \`npm - run-script\` will still run their intended script if \`ignore-scripts\` is - set, but they will *not* run any pre- or post-scripts. - `, - flatten, -}) - -define('include', { - default: [], - type: [Array, 'prod', 'dev', 'optional', 'peer'], - description: ` - Option that allows for defining which types of dependencies to install. - - This is the inverse of \`--omit=\`. - - Dependency types specified in \`--include\` will not be omitted, - regardless of the order in which omit/include are specified on the - command-line. - `, - flatten (key, obj, flatOptions) { - // just call the omit flattener, it reads from obj.include - definitions.omit.flatten('omit', obj, flatOptions) - }, -}) - -define('include-staged', { - default: false, - type: Boolean, - description: ` - Allow installing "staged" published packages, as defined by [npm RFC PR - #92](https://github.com/npm/rfcs/pull/92). - - This is experimental, and not implemented by the npm public registry. - `, - flatten, -}) - -define('include-workspace-root', { - default: false, - type: Boolean, - envExport: false, - description: ` - Include the workspace root when workspaces are enabled for a command. - - When false, specifying individual workspaces via the \`workspace\` config, - or all workspaces via the \`workspaces\` flag, will cause npm to operate only - on the specified workspaces, and not on the root project. - `, - flatten, -}) - -define('init-author-email', { - default: '', - hint: '', - type: String, - description: ` - The value \`npm init\` should use by default for the package author's - email. - `, -}) - -define('init-author-name', { - default: '', - hint: '', - type: String, - description: ` - The value \`npm init\` should use by default for the package author's name. - `, -}) - -define('init-author-url', { - default: '', - type: ['', url], - hint: '', - description: ` - The value \`npm init\` should use by default for the package author's homepage. - `, -}) - -define('init-license', { - default: 'ISC', - hint: '', - type: String, - description: ` - The value \`npm init\` should use by default for the package license. - `, -}) - -define('init-module', { - default: '~/.npm-init.js', - type: path, - hint: '', - description: ` - A module that will be loaded by the \`npm init\` command. See the - documentation for the - [init-package-json](https://github.com/npm/init-package-json) module for - more information, or [npm init](/commands/npm-init). - `, -}) - -define('init-version', { - default: '1.0.0', - type: semver, - hint: '', - description: ` - The value that \`npm init\` should use by default for the package - version number, if not already set in package.json. - `, -}) - -// these "aliases" are historically supported in .npmrc files, unfortunately -// They should be removed in a future npm version. -define('init.author.email', { - default: '', - type: String, - deprecated: ` - Use \`--init-author-email\` instead.`, - description: ` - Alias for \`--init-author-email\` - `, -}) - -define('init.author.name', { - default: '', - type: String, - deprecated: ` - Use \`--init-author-name\` instead. - `, - description: ` - Alias for \`--init-author-name\` - `, -}) - -define('init.author.url', { - default: '', - type: ['', url], - deprecated: ` - Use \`--init-author-url\` instead. - `, - description: ` - Alias for \`--init-author-url\` - `, -}) - -define('init.license', { - default: 'ISC', - type: String, - deprecated: ` - Use \`--init-license\` instead. - `, - description: ` - Alias for \`--init-license\` - `, -}) - -define('init.module', { - default: '~/.npm-init.js', - type: path, - deprecated: ` - Use \`--init-module\` instead. - `, - description: ` - Alias for \`--init-module\` - `, -}) - -define('init.version', { - default: '1.0.0', - type: semver, - deprecated: ` - Use \`--init-version\` instead. - `, - description: ` - Alias for \`--init-version\` - `, -}) - -define('install-links', { - default: false, - type: Boolean, - description: ` - When set file: protocol dependencies will be packed and installed as - regular dependencies instead of creating a symlink. This option has - no effect on workspaces. - `, - flatten, -}) - -define('install-strategy', { - default: 'hoisted', - type: ['hoisted', 'nested', 'shallow', 'linked'], - description: ` - Sets the strategy for installing packages in node_modules. - hoisted (default): Install non-duplicated in top-level, and duplicated as - necessary within directory structure. - nested: (formerly --legacy-bundling) install in place, no hoisting. - shallow (formerly --global-style) only install direct deps at top-level. - linked: (experimental) install in node_modules/.store, link in place, - unhoisted. - `, - flatten, -}) - -define('json', { - default: false, - type: Boolean, - description: ` - Whether or not to output JSON data, rather than the normal output. - - * In \`npm pkg set\` it enables parsing set values with JSON.parse() - before saving them to your \`package.json\`. - - Not supported by all npm commands. - `, - flatten, -}) - -define('key', { - default: null, - type: [null, String], - description: ` - A client key to pass when accessing the registry. Values should be in - PEM format with newlines replaced by the string "\\n". For example: - - \`\`\`ini - key="-----BEGIN PRIVATE KEY-----\\nXXXX\\nXXXX\\n-----END PRIVATE KEY-----" - \`\`\` - - It is _not_ the path to a key file, though you can set a registry-scoped - "keyfile" path like "//other-registry.tld/:keyfile=/path/to/key.pem". - `, - deprecated: ` - \`key\` and \`cert\` are no longer used for most registry operations. - Use registry scoped \`keyfile\` and \`certfile\` instead. - Example: - //other-registry.tld/:keyfile=/path/to/key.pem - //other-registry.tld/:certfile=/path/to/cert.crt - `, - flatten, -}) - -define('legacy-bundling', { - default: false, - type: Boolean, - description: ` - Instead of hoisting package installs in \`node_modules\`, install packages - in the same manner that they are depended on. This may cause very deep - directory structures and duplicate package installs as there is no - de-duplicating. - Sets \`--install-strategy=nested\`. - `, - deprecated: ` - This option has been deprecated in favor of \`--install-strategy=nested\` - `, - flatten (key, obj, flatOptions) { - if (obj[key]) { - obj['install-strategy'] = 'nested' - flatOptions.installStrategy = 'nested' - } - }, -}) - -define('legacy-peer-deps', { - default: false, - type: Boolean, - description: ` - Causes npm to completely ignore \`peerDependencies\` when building a - package tree, as in npm versions 3 through 6. - - If a package cannot be installed because of overly strict - \`peerDependencies\` that collide, it provides a way to move forward - resolving the situation. - - This differs from \`--omit=peer\`, in that \`--omit=peer\` will avoid - unpacking \`peerDependencies\` on disk, but will still design a tree such - that \`peerDependencies\` _could_ be unpacked in a correct place. - - Use of \`legacy-peer-deps\` is not recommended, as it will not enforce - the \`peerDependencies\` contract that meta-dependencies may rely on. - `, - flatten, -}) - -define('link', { - default: false, - type: Boolean, - description: ` - Used with \`npm ls\`, limiting output to only those packages that are - linked. - `, -}) - -define('local-address', { - default: null, - type: getLocalAddresses(), - typeDescription: 'IP Address', - description: ` - The IP address of the local interface to use when making connections to - the npm registry. Must be IPv4 in versions of Node prior to 0.12. - `, - flatten, -}) - -define('sbom-format', { - default: null, - type: [ - 'cyclonedx', - 'spdx', - ], - description: ` - SBOM format to use when generating SBOMs. - `, - flatten, -}) - -define('sbom-type', { - default: 'library', - type: [ - 'library', - 'application', - 'framework', - ], - description: ` - The type of package described by the generated SBOM. For SPDX, this is the - value for the \`primaryPackagePurpose\` field. For CycloneDX, this is the - value for the \`type\` field. - `, - flatten, -}) - -define('location', { - default: 'user', - short: 'L', - type: [ - 'global', - 'user', - 'project', - ], - defaultDescription: ` - "user" unless \`--global\` is passed, which will also set this value to "global" - `, - description: ` - When passed to \`npm config\` this refers to which config file to use. - - When set to "global" mode, packages are installed into the \`prefix\` folder - instead of the current working directory. See - [folders](/configuring-npm/folders) for more on the differences in behavior. - - * packages are installed into the \`{prefix}/lib/node_modules\` folder, - instead of the current working directory. - * bin files are linked to \`{prefix}/bin\` - * man pages are linked to \`{prefix}/share/man\` - `, - flatten: (key, obj, flatOptions) => { - flatten(key, obj, flatOptions) - if (flatOptions.global) { - flatOptions.location = 'global' - } - if (obj.location === 'global') { - flatOptions.global = true - } - }, -}) - -define('lockfile-version', { - default: null, - type: [null, 1, 2, 3, '1', '2', '3'], - defaultDescription: ` - Version 3 if no lockfile, auto-converting v1 lockfiles to v3, otherwise - maintain current lockfile version.`, - description: ` - Set the lockfile format version to be used in package-lock.json and - npm-shrinkwrap-json files. Possible options are: - - 1: The lockfile version used by npm versions 5 and 6. Lacks some data that - is used during the install, resulting in slower and possibly less - deterministic installs. Prevents lockfile churn when interoperating with - older npm versions. - - 2: The default lockfile version used by npm version 7 and 8. Includes both - the version 1 lockfile data and version 3 lockfile data, for maximum - determinism and interoperability, at the expense of more bytes on disk. - - 3: Only the new lockfile information introduced in npm version 7. Smaller - on disk than lockfile version 2, but not interoperable with older npm - versions. Ideal if all users are on npm version 7 and higher. - `, - flatten: (key, obj, flatOptions) => { - flatOptions.lockfileVersion = obj[key] && parseInt(obj[key], 10) - }, -}) - -define('loglevel', { - default: 'notice', - type: [ - 'silent', - 'error', - 'warn', - 'notice', - 'http', - 'info', - 'verbose', - 'silly', - ], - description: ` - What level of logs to report. All logs are written to a debug log, - with the path to that file printed if the execution of a command fails. - - Any logs of a higher level than the setting are shown. The default is - "notice". - - See also the \`foreground-scripts\` config. - `, - flatten (key, obj, flatOptions) { - flatOptions.silent = obj[key] === 'silent' - }, -}) - -define('logs-dir', { - default: null, - type: [null, path], - defaultDescription: ` - A directory named \`_logs\` inside the cache -`, - description: ` - The location of npm's log directory. See [\`npm - logging\`](/using-npm/logging) for more information. - `, -}) - -define('logs-max', { - default: 10, - type: Number, - description: ` - The maximum number of log files to store. - - If set to 0, no log files will be written for the current run. - `, -}) - -define('long', { - default: false, - type: Boolean, - short: 'l', - description: ` - Show extended information in \`ls\`, \`search\`, and \`help-search\`. - `, -}) - -define('maxsockets', { - default: 15, - type: Number, - description: ` - The maximum number of connections to use per origin (protocol/host/port - combination). - `, - flatten (key, obj, flatOptions) { - flatOptions.maxSockets = obj[key] - }, -}) - -define('message', { - default: '%s', - type: String, - short: 'm', - description: ` - Commit message which is used by \`npm version\` when creating version commit. - - Any "%s" in the message will be replaced with the version number. - `, - flatten, -}) - -define('node-options', { - default: null, - type: [null, String], - description: ` - Options to pass through to Node.js via the \`NODE_OPTIONS\` environment - variable. This does not impact how npm itself is executed but it does - impact how lifecycle scripts are called. - `, -}) - -define('noproxy', { - default: '', - defaultDescription: ` - The value of the NO_PROXY environment variable - `, - type: [String, Array], - description: ` - Domain extensions that should bypass any proxies. - - Also accepts a comma-delimited string. - `, - flatten (key, obj, flatOptions) { - if (Array.isArray(obj[key])) { - flatOptions.noProxy = obj[key].join(',') - } else { - flatOptions.noProxy = obj[key] - } - }, -}) - -define('offline', { - default: false, - type: Boolean, - description: ` - Force offline mode: no network requests will be done during install. To allow - the CLI to fill in missing cache data, see \`--prefer-offline\`. - `, - flatten, -}) - -define('omit', { - default: process.env.NODE_ENV === 'production' ? ['dev'] : [], - defaultDescription: ` - 'dev' if the \`NODE_ENV\` environment variable is set to 'production', - otherwise empty. - `, - type: [Array, 'dev', 'optional', 'peer'], - description: ` - Dependency types to omit from the installation tree on disk. - - Note that these dependencies _are_ still resolved and added to the - \`package-lock.json\` or \`npm-shrinkwrap.json\` file. They are just - not physically installed on disk. - - If a package type appears in both the \`--include\` and \`--omit\` - lists, then it will be included. - - If the resulting omit list includes \`'dev'\`, then the \`NODE_ENV\` - environment variable will be set to \`'production'\` for all lifecycle - scripts. - `, - flatten (key, obj, flatOptions) { - flatOptions.omit = buildOmitList(obj) - }, -}) - -define('omit-lockfile-registry-resolved', { - default: false, - type: Boolean, - description: ` - This option causes npm to create lock files without a \`resolved\` key for - registry dependencies. Subsequent installs will need to resolve tarball - endpoints with the configured registry, likely resulting in a longer install - time. - `, - flatten, -}) - -define('only', { - default: null, - type: [null, 'prod', 'production'], - deprecated: ` - Use \`--omit=dev\` to omit dev dependencies from the install. - `, - description: ` - When set to \`prod\` or \`production\`, this is an alias for - \`--omit=dev\`. - `, - flatten (key, obj, flatOptions) { - definitions.omit.flatten('omit', obj, flatOptions) - }, -}) - -define('optional', { - default: null, - type: [null, Boolean], - deprecated: ` - Use \`--omit=optional\` to exclude optional dependencies, or - \`--include=optional\` to include them. - - Default value does install optional deps unless otherwise omitted. - `, - description: ` - Alias for --include=optional or --omit=optional - `, - flatten (key, obj, flatOptions) { - definitions.omit.flatten('omit', obj, flatOptions) - }, -}) - -define('otp', { - default: null, - type: [null, String], - description: ` - This is a one-time password from a two-factor authenticator. It's needed - when publishing or changing package permissions with \`npm access\`. - - If not set, and a registry response fails with a challenge for a one-time - password, npm will prompt on the command line for one. - `, - flatten (key, obj, flatOptions) { - flatten(key, obj, flatOptions) - if (obj.otp) { - obj['auth-type'] = 'legacy' - flatten('auth-type', obj, flatOptions) - } - }, -}) - -define('package', { - default: [], - hint: '', - type: [String, Array], - description: ` - The package or packages to install for [\`npm exec\`](/commands/npm-exec) - `, - flatten, -}) - -define('package-lock', { - default: true, - type: Boolean, - description: ` - If set to false, then ignore \`package-lock.json\` files when installing. - This will also prevent _writing_ \`package-lock.json\` if \`save\` is - true. - `, - flatten: (key, obj, flatOptions) => { - flatten(key, obj, flatOptions) - if (flatOptions.packageLockOnly) { - flatOptions.packageLock = true - } - }, -}) - -define('package-lock-only', { - default: false, - type: Boolean, - description: ` - If set to true, the current operation will only use the \`package-lock.json\`, - ignoring \`node_modules\`. - - For \`update\` this means only the \`package-lock.json\` will be updated, - instead of checking \`node_modules\` and downloading dependencies. - - For \`list\` this means the output will be based on the tree described by the - \`package-lock.json\`, rather than the contents of \`node_modules\`. - `, - flatten: (key, obj, flatOptions) => { - flatten(key, obj, flatOptions) - if (flatOptions.packageLockOnly) { - flatOptions.packageLock = true - } - }, -}) - -define('pack-destination', { - default: '.', - type: String, - description: ` - Directory in which \`npm pack\` will save tarballs. - `, - flatten, -}) - -define('parseable', { - default: false, - type: Boolean, - short: 'p', - description: ` - Output parseable results from commands that write to standard output. For - \`npm search\`, this will be tab-separated table format. - `, - flatten, -}) - -define('prefer-dedupe', { - default: false, - type: Boolean, - description: ` - Prefer to deduplicate packages if possible, rather than - choosing a newer version of a dependency. - `, - flatten, -}) - -define('prefer-offline', { - default: false, - type: Boolean, - description: ` - If true, staleness checks for cached data will be bypassed, but missing - data will be requested from the server. To force full offline mode, use - \`--offline\`. - `, - flatten, -}) - -define('prefer-online', { - default: false, - type: Boolean, - description: ` - If true, staleness checks for cached data will be forced, making the CLI - look for updates immediately even for fresh package data. - `, - flatten, -}) - -// `prefix` has its default defined outside of this module -define('prefix', { - type: path, - short: 'C', - default: '', - defaultDescription: ` - In global mode, the folder where the node executable is installed. - Otherwise, the nearest parent folder containing either a package.json - file or a node_modules folder. - `, - description: ` - The location to install global items. If set on the command line, then - it forces non-global commands to run in the specified folder. - `, -}) - -define('preid', { - default: '', - hint: 'prerelease-id', - type: String, - description: ` - The "prerelease identifier" to use as a prefix for the "prerelease" part - of a semver. Like the \`rc\` in \`1.2.0-rc.8\`. - `, - flatten, -}) - -define('production', { - default: null, - type: [null, Boolean], - deprecated: 'Use `--omit=dev` instead.', - description: 'Alias for `--omit=dev`', - flatten (key, obj, flatOptions) { - definitions.omit.flatten('omit', obj, flatOptions) - }, -}) - -define('progress', { - default: !ciInfo.isCI, - defaultDescription: ` - \`true\` unless running in a known CI system - `, - type: Boolean, - description: ` - When set to \`true\`, npm will display a progress bar during time - intensive operations, if \`process.stderr\` is a TTY. - - Set to \`false\` to suppress the progress bar. - `, - flatten (key, obj, flatOptions) { - flatOptions.progress = !obj.progress ? false - : !!process.stderr.isTTY && process.env.TERM !== 'dumb' - }, -}) - -define('provenance', { - default: false, - type: Boolean, - exclusive: ['provenance-file'], - description: ` - When publishing from a supported cloud CI/CD system, the package will be - publicly linked to where it was built and published from. - `, - flatten, -}) - -define('provenance-file', { - default: null, - type: path, - hint: '', - exclusive: ['provenance'], - description: ` - When publishing, the provenance bundle at the given path will be used. - `, - flatten, -}) - -define('proxy', { - default: null, - type: [null, false, url], // allow proxy to be disabled explicitly - description: ` - A proxy to use for outgoing http requests. If the \`HTTP_PROXY\` or - \`http_proxy\` environment variables are set, proxy settings will be - honored by the underlying \`request\` library. - `, - flatten, -}) - -define('read-only', { - default: false, - type: Boolean, - description: ` - This is used to mark a token as unable to publish when configuring - limited access tokens with the \`npm token create\` command. - `, - flatten, -}) - -define('rebuild-bundle', { - default: true, - type: Boolean, - description: ` - Rebuild bundled dependencies after installation. - `, - flatten, -}) - -define('registry', { - default: 'https://registry.npmjs.org/', - type: url, - description: ` - The base URL of the npm registry. - `, - flatten, -}) - -define('replace-registry-host', { - default: 'npmjs', - hint: ' | hostname', - type: ['npmjs', 'never', 'always', String], - description: ` - Defines behavior for replacing the registry host in a lockfile with the - configured registry. - - The default behavior is to replace package dist URLs from the default - registry (https://registry.npmjs.org) to the configured registry. If set to - "never", then use the registry value. If set to "always", then replace the - registry host with the configured host every time. - - You may also specify a bare hostname (e.g., "registry.npmjs.org"). - `, - flatten, -}) - -define('save', { - default: true, - defaultDescription: `\`true\` unless when using \`npm update\` where it - defaults to \`false\``, - usage: '-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer|--save-bundle', - type: Boolean, - short: 'S', - description: ` - Save installed packages to a \`package.json\` file as dependencies. - - When used with the \`npm rm\` command, removes the dependency from - \`package.json\`. - - Will also prevent writing to \`package-lock.json\` if set to \`false\`. - `, - flatten, -}) - -define('save-bundle', { - default: false, - type: Boolean, - short: 'B', - description: ` - If a package would be saved at install time by the use of \`--save\`, - \`--save-dev\`, or \`--save-optional\`, then also put it in the - \`bundleDependencies\` list. - - Ignored if \`--save-peer\` is set, since peerDependencies cannot be bundled. - `, - flatten (key, obj, flatOptions) { - // XXX update arborist to just ignore it if resulting saveType is peer - // otherwise this won't have the expected effect: - // - // npm config set save-peer true - // npm i foo --save-bundle --save-prod <-- should bundle - flatOptions.saveBundle = obj['save-bundle'] && !obj['save-peer'] - }, -}) + flatten, + }), + cache: new Definition('cache', { + default: cache, + defaultDescription: ` + Windows: \`%LocalAppData%\\npm-cache\`, Posix: \`~/.npm\` + `, + type: path, + description: ` + The location of npm's cache directory. + `, + flatten (key, obj, flatOptions) { + flatOptions.cache = join(obj.cache, '_cacache') + flatOptions.npxCache = join(obj.cache, '_npx') + flatOptions.tufCache = join(obj.cache, '_tuf') + }, + }), + 'cache-max': new Definition('cache-max', { + default: Infinity, + type: Number, + description: ` + \`--cache-max=0\` is an alias for \`--prefer-online\` + `, + deprecated: ` + This option has been deprecated in favor of \`--prefer-online\` + `, + flatten (key, obj, flatOptions) { + if (obj[key] <= 0) { + flatOptions.preferOnline = true + } + }, + }), + 'cache-min': new Definition('cache-min', { + default: 0, + type: Number, + description: ` + \`--cache-min=9999 (or bigger)\` is an alias for \`--prefer-offline\`. + `, + deprecated: ` + This option has been deprecated in favor of \`--prefer-offline\`. + `, + flatten (key, obj, flatOptions) { + if (obj[key] >= 9999) { + flatOptions.preferOffline = true + } + }, + }), + cafile: new Definition('cafile', { + default: null, + type: path, + description: ` + A path to a file containing one or multiple Certificate Authority signing + certificates. Similar to the \`ca\` setting, but allows for multiple + CA's, as well as for the CA information to be stored in a file on disk. + `, + flatten (key, obj, flatOptions) { + // always set to null in defaults + if (!obj.cafile) { + return + } -// XXX: We should really deprecate all these `--save-blah` switches -// in favor of a single `--save-type` option. The unfortunate shortcut -// we took for `--save-peer --save-optional` being `--save-type=peerOptional` -// makes this tricky, and likely a breaking change. + const raw = maybeReadFile(obj.cafile) + if (!raw) { + return + } -define('save-dev', { - default: false, - type: Boolean, - short: 'D', - description: ` - Save installed packages to a package.json file as \`devDependencies\`. - `, - flatten (key, obj, flatOptions) { - if (!obj[key]) { - if (flatOptions.saveType === 'dev') { - delete flatOptions.saveType + const delim = '-----END CERTIFICATE-----' + flatOptions.ca = raw.replace(/\r\n/g, '\n').split(delim) + .filter(section => section.trim()) + .map(section => section.trimLeft() + delim) + }, + }), + call: new Definition('call', { + default: '', + type: String, + short: 'c', + description: ` + Optional companion option for \`npm exec\`, \`npx\` that allows for + specifying a custom command to be run along with the installed packages. + + \`\`\`bash + npm exec --package yo --package generator-node --call "yo node" + \`\`\` + `, + flatten, + }), + cert: new Definition('cert', { + default: null, + type: [null, String], + description: ` + A client certificate to pass when accessing the registry. Values should + be in PEM format (Windows calls it "Base-64 encoded X.509 (.CER)") with + newlines replaced by the string "\\n". For example: + + \`\`\`ini + cert="-----BEGIN CERTIFICATE-----\\nXXXX\\nXXXX\\n-----END CERTIFICATE-----" + \`\`\` + + It is _not_ the path to a certificate file, though you can set a registry-scoped + "certfile" path like "//other-registry.tld/:certfile=/path/to/cert.pem". + `, + deprecated: ` + \`key\` and \`cert\` are no longer used for most registry operations. + Use registry scoped \`keyfile\` and \`certfile\` instead. + Example: + //other-registry.tld/:keyfile=/path/to/key.pem + //other-registry.tld/:certfile=/path/to/cert.crt + `, + flatten, + }), + cidr: new Definition('cidr', { + default: null, + type: [null, String, Array], + description: ` + This is a list of CIDR address to be used when configuring limited access + tokens with the \`npm token create\` command. + `, + flatten, + }), + // This should never be directly used, the flattened value is the derived value + // and is sent to other modules, and is also exposed as `npm.color` for use + // inside npm itself. + color: new Definition('color', { + default: !process.env.NO_COLOR || process.env.NO_COLOR === '0', + usage: '--color|--no-color|--color always', + defaultDescription: ` + true unless the NO_COLOR environ is set to something other than '0' + `, + type: ['always', Boolean], + description: ` + If false, never shows colors. If \`"always"\` then always shows colors. + If true, then only prints color codes for tty file descriptors. + `, + flatten (key, obj, flatOptions) { + flatOptions.color = !obj.color ? false + : obj.color === 'always' ? true + : !!process.stdout.isTTY + flatOptions.logColor = !obj.color ? false + : obj.color === 'always' ? true + : !!process.stderr.isTTY + }, + }), + 'commit-hooks': new Definition('commit-hooks', { + default: true, + type: Boolean, + description: ` + Run git commit hooks when using the \`npm version\` command. + `, + flatten, + }), + cpu: new Definition('cpu', { + default: null, + type: [null, String], + description: ` + Override CPU architecture of native modules to install. + Acceptable values are same as \`cpu\` field of package.json, + which comes from \`process.arch\`. + `, + flatten, + }), + depth: new Definition('depth', { + default: null, + defaultDescription: ` + \`Infinity\` if \`--all\` is set, otherwise \`1\` + `, + type: [null, Number], + description: ` + The depth to go when recursing packages for \`npm ls\`. + + If not set, \`npm ls\` will show only the immediate dependencies of the + root project. If \`--all\` is set, then npm will show all dependencies + by default. + `, + flatten, + }), + description: new Definition('description', { + default: true, + type: Boolean, + usage: '--no-description', + description: ` + Show the description in \`npm search\` + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || { limit: 20 } + flatOptions.search[key] = obj[key] + }, + }), + dev: new Definition('dev', { + default: false, + type: Boolean, + description: ` + Alias for \`--include=dev\`. + `, + deprecated: 'Please use --include=dev instead.', + flatten (key, obj, flatOptions) { + definitions.omit.flatten('omit', obj, flatOptions) + }, + }), + diff: new Definition('diff', { + default: [], + hint: '', + type: [String, Array], + description: ` + Define arguments to compare in \`npm diff\`. + `, + flatten, + }), + 'diff-ignore-all-space': new Definition('diff-ignore-all-space', { + default: false, + type: Boolean, + description: ` + Ignore whitespace when comparing lines in \`npm diff\`. + `, + flatten, + }), + 'diff-name-only': new Definition('diff-name-only', { + default: false, + type: Boolean, + description: ` + Prints only filenames when using \`npm diff\`. + `, + flatten, + }), + 'diff-no-prefix': new Definition('diff-no-prefix', { + default: false, + type: Boolean, + description: ` + Do not show any source or destination prefix in \`npm diff\` output. + + Note: this causes \`npm diff\` to ignore the \`--diff-src-prefix\` and + \`--diff-dst-prefix\` configs. + `, + flatten, + }), + 'diff-dst-prefix': new Definition('diff-dst-prefix', { + default: 'b/', + hint: '', + type: String, + description: ` + Destination prefix to be used in \`npm diff\` output. + `, + flatten, + }), + 'diff-src-prefix': new Definition('diff-src-prefix', { + default: 'a/', + hint: '', + type: String, + description: ` + Source prefix to be used in \`npm diff\` output. + `, + flatten, + }), + 'diff-text': new Definition('diff-text', { + default: false, + type: Boolean, + description: ` + Treat all files as text in \`npm diff\`. + `, + flatten, + }), + 'diff-unified': new Definition('diff-unified', { + default: 3, + type: Number, + description: ` + The number of lines of context to print in \`npm diff\`. + `, + flatten, + }), + 'dry-run': new Definition('dry-run', { + default: false, + type: Boolean, + description: ` + Indicates that you don't want npm to make any changes and that it should + only report what it would have done. This can be passed into any of the + commands that modify your local installation, eg, \`install\`, + \`update\`, \`dedupe\`, \`uninstall\`, as well as \`pack\` and + \`publish\`. + + Note: This is NOT honored by other network related commands, eg + \`dist-tags\`, \`owner\`, etc. + `, + flatten, + }), + editor: new Definition('editor', { + default: editor, + defaultDescription: ` + The EDITOR or VISUAL environment variables, or '%SYSTEMROOT%\\notepad.exe' on Windows, + or 'vi' on Unix systems + `, + type: String, + description: ` + The command to run for \`npm edit\` and \`npm config edit\`. + `, + flatten, + }), + 'engine-strict': new Definition('engine-strict', { + default: false, + type: Boolean, + description: ` + If set to true, then npm will stubbornly refuse to install (or even + consider installing) any package that claims to not be compatible with + the current Node.js version. + + This can be overridden by setting the \`--force\` flag. + `, + flatten, + }), + 'expect-result-count': new Definition('expect-result-count', { + default: null, + type: [null, Number], + hint: '', + exclusive: ['expect-results'], + description: ` + Tells to expect a specific number of results from the command. + `, + }), + 'expect-results': new Definition('expect-results', { + default: null, + type: [null, Boolean], + exclusive: ['expect-result-count'], + description: ` + Tells npm whether or not to expect results from the command. + Can be either true (expect some results) or false (expect no results). + `, + }), + 'fetch-retries': new Definition('fetch-retries', { + default: 2, + type: Number, + description: ` + The "retries" config for the \`retry\` module to use when fetching + packages from the registry. + + npm will retry idempotent read requests to the registry in the case + of network failures or 5xx HTTP errors. + `, + flatten (key, obj, flatOptions) { + flatOptions.retry = flatOptions.retry || {} + flatOptions.retry.retries = obj[key] + }, + }), + 'fetch-retry-factor': new Definition('fetch-retry-factor', { + default: 10, + type: Number, + description: ` + The "factor" config for the \`retry\` module to use when fetching + packages. + `, + flatten (key, obj, flatOptions) { + flatOptions.retry = flatOptions.retry || {} + flatOptions.retry.factor = obj[key] + }, + }), + 'fetch-retry-maxtimeout': new Definition('fetch-retry-maxtimeout', { + default: 60000, + defaultDescription: '60000 (1 minute)', + type: Number, + description: ` + The "maxTimeout" config for the \`retry\` module to use when fetching + packages. + `, + flatten (key, obj, flatOptions) { + flatOptions.retry = flatOptions.retry || {} + flatOptions.retry.maxTimeout = obj[key] + }, + }), + 'fetch-retry-mintimeout': new Definition('fetch-retry-mintimeout', { + default: 10000, + defaultDescription: '10000 (10 seconds)', + type: Number, + description: ` + The "minTimeout" config for the \`retry\` module to use when fetching + packages. + `, + flatten (key, obj, flatOptions) { + flatOptions.retry = flatOptions.retry || {} + flatOptions.retry.minTimeout = obj[key] + }, + }), + 'fetch-timeout': new Definition('fetch-timeout', { + default: 5 * 60 * 1000, + defaultDescription: `${5 * 60 * 1000} (5 minutes)`, + type: Number, + description: ` + The maximum amount of time to wait for HTTP requests to complete. + `, + flatten (key, obj, flatOptions) { + flatOptions.timeout = obj[key] + }, + }), + force: new Definition('force', { + default: false, + type: Boolean, + short: 'f', + description: ` + Removes various protections against unfortunate side effects, common + mistakes, unnecessary performance degradation, and malicious input. + + * Allow clobbering non-npm files in global installs. + * Allow the \`npm version\` command to work on an unclean git repository. + * Allow deleting the cache folder with \`npm cache clean\`. + * Allow installing packages that have an \`engines\` declaration + requiring a different version of npm. + * Allow installing packages that have an \`engines\` declaration + requiring a different version of \`node\`, even if \`--engine-strict\` + is enabled. + * Allow \`npm audit fix\` to install modules outside your stated + dependency range (including SemVer-major changes). + * Allow unpublishing all versions of a published package. + * Allow conflicting peerDependencies to be installed in the root project. + * Implicitly set \`--yes\` during \`npm init\`. + * Allow clobbering existing values in \`npm pkg\` + * Allow unpublishing of entire packages (not just a single version). + + If you don't have a clear idea of what you want to do, it is strongly + recommended that you do not use this option! + `, + flatten, + }), + 'foreground-scripts': new Definition('foreground-scripts', { + default: false, + defaultDescription: `\`false\` unless when using \`npm pack\` or \`npm publish\` where it + defaults to \`true\``, + type: Boolean, + description: ` + Run all build scripts (ie, \`preinstall\`, \`install\`, and + \`postinstall\`) scripts for installed packages in the foreground + process, sharing standard input, output, and error with the main npm + process. + + Note that this will generally make installs run slower, and be much + noisier, but can be useful for debugging. + `, + flatten, + }), + 'format-package-lock': new Definition('format-package-lock', { + default: true, + type: Boolean, + description: ` + Format \`package-lock.json\` or \`npm-shrinkwrap.json\` as a human + readable file. + `, + flatten, + }), + fund: new Definition('fund', { + default: true, + type: Boolean, + description: ` + When "true" displays the message at the end of each \`npm install\` + acknowledging the number of dependencies looking for funding. + See [\`npm fund\`](/commands/npm-fund) for details. + `, + flatten, + }), + git: new Definition('git', { + default: 'git', + type: String, + description: ` + The command to use for git commands. If git is installed on the + computer, but is not in the \`PATH\`, then set this to the full path to + the git binary. + `, + flatten, + }), + 'git-tag-version': new Definition('git-tag-version', { + default: true, + type: Boolean, + description: ` + Tag the commit when using the \`npm version\` command. Setting this to + false results in no commit being made at all. + `, + flatten, + }), + global: new Definition('global', { + default: false, + type: Boolean, + short: 'g', + description: ` + Operates in "global" mode, so that packages are installed into the + \`prefix\` folder instead of the current working directory. See + [folders](/configuring-npm/folders) for more on the differences in + behavior. + + * packages are installed into the \`{prefix}/lib/node_modules\` folder, + instead of the current working directory. + * bin files are linked to \`{prefix}/bin\` + * man pages are linked to \`{prefix}/share/man\` + `, + flatten: (key, obj, flatOptions) => { + flatten(key, obj, flatOptions) + if (flatOptions.global) { + flatOptions.location = 'global' + } + }, + }), + // the globalconfig has its default defined outside of this module + globalconfig: new Definition('globalconfig', { + type: path, + default: '', + defaultDescription: ` + The global --prefix setting plus 'etc/npmrc'. For example, + '/usr/local/etc/npmrc' + `, + description: ` + The config file to read for global config options. + `, + flatten, + }), + 'global-style': new Definition('global-style', { + default: false, + type: Boolean, + description: ` + Only install direct dependencies in the top level \`node_modules\`, + but hoist on deeper dependencies. + Sets \`--install-strategy=shallow\`. + `, + deprecated: ` + This option has been deprecated in favor of \`--install-strategy=shallow\` + `, + flatten (key, obj, flatOptions) { + if (obj[key]) { + obj['install-strategy'] = 'shallow' + flatOptions.installStrategy = 'shallow' + } + }, + }), + heading: new Definition('heading', { + default: 'npm', + type: String, + description: ` + The string that starts all the debugging log output. + `, + flatten, + }), + 'https-proxy': new Definition('https-proxy', { + default: null, + type: [null, url], + description: ` + A proxy to use for outgoing https requests. If the \`HTTPS_PROXY\` or + \`https_proxy\` or \`HTTP_PROXY\` or \`http_proxy\` environment variables + are set, proxy settings will be honored by the underlying + \`make-fetch-happen\` library. + `, + flatten, + }), + 'if-present': new Definition('if-present', { + default: false, + type: Boolean, + envExport: false, + description: ` + If true, npm will not exit with an error code when \`run-script\` is + invoked for a script that isn't defined in the \`scripts\` section of + \`package.json\`. This option can be used when it's desirable to + optionally run a script when it's present and fail if the script fails. + This is useful, for example, when running scripts that may only apply for + some builds in an otherwise generic CI setup. + `, + flatten, + }), + 'ignore-scripts': new Definition('ignore-scripts', { + default: false, + type: Boolean, + description: ` + If true, npm does not run scripts specified in package.json files. + + Note that commands explicitly intended to run a particular script, such + as \`npm start\`, \`npm stop\`, \`npm restart\`, \`npm test\`, and \`npm + run-script\` will still run their intended script if \`ignore-scripts\` is + set, but they will *not* run any pre- or post-scripts. + `, + flatten, + }), + include: new Definition('include', { + default: [], + type: [Array, 'prod', 'dev', 'optional', 'peer'], + description: ` + Option that allows for defining which types of dependencies to install. + + This is the inverse of \`--omit=\`. + + Dependency types specified in \`--include\` will not be omitted, + regardless of the order in which omit/include are specified on the + command-line. + `, + flatten (key, obj, flatOptions) { + // just call the omit flattener, it reads from obj.include + definitions.omit.flatten('omit', obj, flatOptions) + }, + }), + 'include-staged': new Definition('include-staged', { + default: false, + type: Boolean, + description: ` + Allow installing "staged" published packages, as defined by [npm RFC PR + #92](https://github.com/npm/rfcs/pull/92). + + This is experimental, and not implemented by the npm public registry. + `, + flatten, + }), + 'include-workspace-root': new Definition('include-workspace-root', { + default: false, + type: Boolean, + envExport: false, + description: ` + Include the workspace root when workspaces are enabled for a command. + + When false, specifying individual workspaces via the \`workspace\` config, + or all workspaces via the \`workspaces\` flag, will cause npm to operate only + on the specified workspaces, and not on the root project. + `, + flatten, + }), + 'init-author-email': new Definition('init-author-email', { + default: '', + hint: '', + type: String, + description: ` + The value \`npm init\` should use by default for the package author's + email. + `, + }), + 'init-author-name': new Definition('init-author-name', { + default: '', + hint: '', + type: String, + description: ` + The value \`npm init\` should use by default for the package author's name. + `, + }), + 'init-author-url': new Definition('init-author-url', { + default: '', + type: ['', url], + hint: '', + description: ` + The value \`npm init\` should use by default for the package author's homepage. + `, + }), + 'init-license': new Definition('init-license', { + default: 'ISC', + hint: '', + type: String, + description: ` + The value \`npm init\` should use by default for the package license. + `, + }), + 'init-module': new Definition('init-module', { + default: '~/.npm-init.js', + type: path, + hint: '', + description: ` + A module that will be loaded by the \`npm init\` command. See the + documentation for the + [init-package-json](https://github.com/npm/init-package-json) module for + more information, or [npm init](/commands/npm-init). + `, + }), + 'init-version': new Definition('init-version', { + default: '1.0.0', + type: Semver, + hint: '', + description: ` + The value that \`npm init\` should use by default for the package + version number, if not already set in package.json. + `, + }), + // these "aliases" are historically supported in .npmrc files, unfortunately + // They should be removed in a future npm version. + 'init.author.email': new Definition('init.author.email', { + default: '', + type: String, + deprecated: ` + Use \`--init-author-email\` instead.`, + description: ` + Alias for \`--init-author-email\` + `, + }), + 'init.author.name': new Definition('init.author.name', { + default: '', + type: String, + deprecated: ` + Use \`--init-author-name\` instead. + `, + description: ` + Alias for \`--init-author-name\` + `, + }), + 'init.author.url': new Definition('init.author.url', { + default: '', + type: ['', url], + deprecated: ` + Use \`--init-author-url\` instead. + `, + description: ` + Alias for \`--init-author-url\` + `, + }), + 'init.license': new Definition('init.license', { + default: 'ISC', + type: String, + deprecated: ` + Use \`--init-license\` instead. + `, + description: ` + Alias for \`--init-license\` + `, + }), + 'init.module': new Definition('init.module', { + default: '~/.npm-init.js', + type: path, + deprecated: ` + Use \`--init-module\` instead. + `, + description: ` + Alias for \`--init-module\` + `, + }), + 'init.version': new Definition('init.version', { + default: '1.0.0', + type: Semver, + deprecated: ` + Use \`--init-version\` instead. + `, + description: ` + Alias for \`--init-version\` + `, + }), + 'install-links': new Definition('install-links', { + default: false, + type: Boolean, + description: ` + When set file: protocol dependencies will be packed and installed as + regular dependencies instead of creating a symlink. This option has + no effect on workspaces. + `, + flatten, + }), + 'install-strategy': new Definition('install-strategy', { + default: 'hoisted', + type: ['hoisted', 'nested', 'shallow', 'linked'], + description: ` + Sets the strategy for installing packages in node_modules. + hoisted (default): Install non-duplicated in top-level, and duplicated as + necessary within directory structure. + nested: (formerly --legacy-bundling) install in place, no hoisting. + shallow (formerly --global-style) only install direct deps at top-level. + linked: (experimental) install in node_modules/.store, link in place, + unhoisted. + `, + flatten, + }), + json: new Definition('json', { + default: false, + type: Boolean, + description: ` + Whether or not to output JSON data, rather than the normal output. + + * In \`npm pkg set\` it enables parsing set values with JSON.parse() + before saving them to your \`package.json\`. + + Not supported by all npm commands. + `, + flatten, + }), + key: new Definition('key', { + default: null, + type: [null, String], + description: ` + A client key to pass when accessing the registry. Values should be in + PEM format with newlines replaced by the string "\\n". For example: + + \`\`\`ini + key="-----BEGIN PRIVATE KEY-----\\nXXXX\\nXXXX\\n-----END PRIVATE KEY-----" + \`\`\` + + It is _not_ the path to a key file, though you can set a registry-scoped + "keyfile" path like "//other-registry.tld/:keyfile=/path/to/key.pem". + `, + deprecated: ` + \`key\` and \`cert\` are no longer used for most registry operations. + Use registry scoped \`keyfile\` and \`certfile\` instead. + Example: + //other-registry.tld/:keyfile=/path/to/key.pem + //other-registry.tld/:certfile=/path/to/cert.crt + `, + flatten, + }), + 'legacy-bundling': new Definition('legacy-bundling', { + default: false, + type: Boolean, + description: ` + Instead of hoisting package installs in \`node_modules\`, install packages + in the same manner that they are depended on. This may cause very deep + directory structures and duplicate package installs as there is no + de-duplicating. + Sets \`--install-strategy=nested\`. + `, + deprecated: ` + This option has been deprecated in favor of \`--install-strategy=nested\` + `, + flatten (key, obj, flatOptions) { + if (obj[key]) { + obj['install-strategy'] = 'nested' + flatOptions.installStrategy = 'nested' + } + }, + }), + 'legacy-peer-deps': new Definition('legacy-peer-deps', { + default: false, + type: Boolean, + description: ` + Causes npm to completely ignore \`peerDependencies\` when building a + package tree, as in npm versions 3 through 6. + + If a package cannot be installed because of overly strict + \`peerDependencies\` that collide, it provides a way to move forward + resolving the situation. + + This differs from \`--omit=peer\`, in that \`--omit=peer\` will avoid + unpacking \`peerDependencies\` on disk, but will still design a tree such + that \`peerDependencies\` _could_ be unpacked in a correct place. + + Use of \`legacy-peer-deps\` is not recommended, as it will not enforce + the \`peerDependencies\` contract that meta-dependencies may rely on. + `, + flatten, + }), + libc: new Definition('libc', { + default: null, + type: [null, String], + description: ` + Override libc of native modules to install. + Acceptable values are same as \`libc\` field of package.json + `, + flatten, + }), + link: new Definition('link', { + default: false, + type: Boolean, + description: ` + Used with \`npm ls\`, limiting output to only those packages that are + linked. + `, + }), + 'local-address': new Definition('local-address', { + default: null, + type: getLocalAddresses(), + typeDescription: 'IP Address', + description: ` + The IP address of the local interface to use when making connections to + the npm registry. Must be IPv4 in versions of Node prior to 0.12. + `, + flatten, + }), + location: new Definition('location', { + default: 'user', + short: 'L', + type: [ + 'global', + 'user', + 'project', + ], + defaultDescription: ` + "user" unless \`--global\` is passed, which will also set this value to "global" + `, + description: ` + When passed to \`npm config\` this refers to which config file to use. + + When set to "global" mode, packages are installed into the \`prefix\` folder + instead of the current working directory. See + [folders](/configuring-npm/folders) for more on the differences in behavior. + + * packages are installed into the \`{prefix}/lib/node_modules\` folder, + instead of the current working directory. + * bin files are linked to \`{prefix}/bin\` + * man pages are linked to \`{prefix}/share/man\` + `, + flatten: (key, obj, flatOptions) => { + flatten(key, obj, flatOptions) + if (flatOptions.global) { + flatOptions.location = 'global' + } + if (obj.location === 'global') { + flatOptions.global = true + } + }, + }), + 'lockfile-version': new Definition('lockfile-version', { + default: null, + type: [null, 1, 2, 3, '1', '2', '3'], + defaultDescription: ` + Version 3 if no lockfile, auto-converting v1 lockfiles to v3, otherwise + maintain current lockfile version.`, + description: ` + Set the lockfile format version to be used in package-lock.json and + npm-shrinkwrap-json files. Possible options are: + + 1: The lockfile version used by npm versions 5 and 6. Lacks some data that + is used during the install, resulting in slower and possibly less + deterministic installs. Prevents lockfile churn when interoperating with + older npm versions. + + 2: The default lockfile version used by npm version 7 and 8. Includes both + the version 1 lockfile data and version 3 lockfile data, for maximum + determinism and interoperability, at the expense of more bytes on disk. + + 3: Only the new lockfile information introduced in npm version 7. Smaller + on disk than lockfile version 2, but not interoperable with older npm + versions. Ideal if all users are on npm version 7 and higher. + `, + flatten: (key, obj, flatOptions) => { + flatOptions.lockfileVersion = obj[key] && parseInt(obj[key], 10) + }, + }), + loglevel: new Definition('loglevel', { + default: 'notice', + type: [ + 'silent', + 'error', + 'warn', + 'notice', + 'http', + 'info', + 'verbose', + 'silly', + ], + description: ` + What level of logs to report. All logs are written to a debug log, + with the path to that file printed if the execution of a command fails. + + Any logs of a higher level than the setting are shown. The default is + "notice". + + See also the \`foreground-scripts\` config. + `, + flatten (key, obj, flatOptions) { + flatOptions.silent = obj[key] === 'silent' + }, + }), + 'logs-dir': new Definition('logs-dir', { + default: null, + type: [null, path], + defaultDescription: ` + A directory named \`_logs\` inside the cache + `, + description: ` + The location of npm's log directory. See [\`npm + logging\`](/using-npm/logging) for more information. + `, + }), + 'logs-max': new Definition('logs-max', { + default: 10, + type: Number, + description: ` + The maximum number of log files to store. + + If set to 0, no log files will be written for the current run. + `, + }), + long: new Definition('long', { + default: false, + type: Boolean, + short: 'l', + description: ` + Show extended information in \`ls\`, \`search\`, and \`help-search\`. + `, + }), + maxsockets: new Definition('maxsockets', { + default: 15, + type: Number, + description: ` + The maximum number of connections to use per origin (protocol/host/port + combination). + `, + flatten (key, obj, flatOptions) { + flatOptions.maxSockets = obj[key] + }, + }), + message: new Definition('message', { + default: '%s', + type: String, + short: 'm', + description: ` + Commit message which is used by \`npm version\` when creating version commit. + + Any "%s" in the message will be replaced with the version number. + `, + flatten, + }), + 'node-options': new Definition('node-options', { + default: null, + type: [null, String], + description: ` + Options to pass through to Node.js via the \`NODE_OPTIONS\` environment + variable. This does not impact how npm itself is executed but it does + impact how lifecycle scripts are called. + `, + }), + noproxy: new Definition('noproxy', { + default: '', + defaultDescription: ` + The value of the NO_PROXY environment variable + `, + type: [String, Array], + description: ` + Domain extensions that should bypass any proxies. + + Also accepts a comma-delimited string. + `, + flatten (key, obj, flatOptions) { + if (Array.isArray(obj[key])) { + flatOptions.noProxy = obj[key].join(',') + } else { + flatOptions.noProxy = obj[key] + } + }, + }), + offline: new Definition('offline', { + default: false, + type: Boolean, + description: ` + Force offline mode: no network requests will be done during install. To allow + the CLI to fill in missing cache data, see \`--prefer-offline\`. + `, + flatten, + }), + omit: new Definition('omit', { + default: process.env.NODE_ENV === 'production' ? ['dev'] : [], + defaultDescription: ` + 'dev' if the \`NODE_ENV\` environment variable is set to 'production', + otherwise empty. + `, + type: [Array, 'dev', 'optional', 'peer'], + description: ` + Dependency types to omit from the installation tree on disk. + + Note that these dependencies _are_ still resolved and added to the + \`package-lock.json\` or \`npm-shrinkwrap.json\` file. They are just + not physically installed on disk. + + If a package type appears in both the \`--include\` and \`--omit\` + lists, then it will be included. + + If the resulting omit list includes \`'dev'\`, then the \`NODE_ENV\` + environment variable will be set to \`'production'\` for all lifecycle + scripts. + `, + flatten (key, obj, flatOptions) { + flatOptions.omit = buildOmitList(obj) + }, + }), + 'omit-lockfile-registry-resolved': new Definition('omit-lockfile-registry-resolved', { + default: false, + type: Boolean, + description: ` + This option causes npm to create lock files without a \`resolved\` key for + registry dependencies. Subsequent installs will need to resolve tarball + endpoints with the configured registry, likely resulting in a longer install + time. + `, + flatten, + }), + only: new Definition('only', { + default: null, + type: [null, 'prod', 'production'], + deprecated: ` + Use \`--omit=dev\` to omit dev dependencies from the install. + `, + description: ` + When set to \`prod\` or \`production\`, this is an alias for + \`--omit=dev\`. + `, + flatten (key, obj, flatOptions) { + definitions.omit.flatten('omit', obj, flatOptions) + }, + }), + optional: new Definition('optional', { + default: null, + type: [null, Boolean], + deprecated: ` + Use \`--omit=optional\` to exclude optional dependencies, or + \`--include=optional\` to include them. + + Default value does install optional deps unless otherwise omitted. + `, + description: ` + Alias for --include=optional or --omit=optional + `, + flatten (key, obj, flatOptions) { + definitions.omit.flatten('omit', obj, flatOptions) + }, + }), + os: new Definition('os', { + default: null, + type: [null, String], + description: ` + Override OS of native modules to install. + Acceptable values are same as \`os\` field of package.json, + which comes from \`process.platform\`. + `, + flatten, + }), + otp: new Definition('otp', { + default: null, + type: [null, String], + description: ` + This is a one-time password from a two-factor authenticator. It's needed + when publishing or changing package permissions with \`npm access\`. + + If not set, and a registry response fails with a challenge for a one-time + password, npm will prompt on the command line for one. + `, + flatten (key, obj, flatOptions) { + flatten(key, obj, flatOptions) + if (obj.otp) { + obj['auth-type'] = 'legacy' + flatten('auth-type', obj, flatOptions) + } + }, + }), + package: new Definition('package', { + default: [], + hint: '', + type: [String, Array], + description: ` + The package or packages to install for [\`npm exec\`](/commands/npm-exec) + `, + flatten, + }), + 'package-lock': new Definition('package-lock', { + default: true, + type: Boolean, + description: ` + If set to false, then ignore \`package-lock.json\` files when installing. + This will also prevent _writing_ \`package-lock.json\` if \`save\` is + true. + `, + flatten: (key, obj, flatOptions) => { + flatten(key, obj, flatOptions) + if (flatOptions.packageLockOnly) { + flatOptions.packageLock = true + } + }, + }), + 'package-lock-only': new Definition('package-lock-only', { + default: false, + type: Boolean, + description: ` + If set to true, the current operation will only use the \`package-lock.json\`, + ignoring \`node_modules\`. + + For \`update\` this means only the \`package-lock.json\` will be updated, + instead of checking \`node_modules\` and downloading dependencies. + + For \`list\` this means the output will be based on the tree described by the + \`package-lock.json\`, rather than the contents of \`node_modules\`. + `, + flatten: (key, obj, flatOptions) => { + flatten(key, obj, flatOptions) + if (flatOptions.packageLockOnly) { + flatOptions.packageLock = true + } + }, + }), + 'pack-destination': new Definition('pack-destination', { + default: '.', + type: String, + description: ` + Directory in which \`npm pack\` will save tarballs. + `, + flatten, + }), + parseable: new Definition('parseable', { + default: false, + type: Boolean, + short: 'p', + description: ` + Output parseable results from commands that write to standard output. For + \`npm search\`, this will be tab-separated table format. + `, + flatten, + }), + 'prefer-dedupe': new Definition('prefer-dedupe', { + default: false, + type: Boolean, + description: ` + Prefer to deduplicate packages if possible, rather than + choosing a newer version of a dependency. + `, + flatten, + }), + 'prefer-offline': new Definition('prefer-offline', { + default: false, + type: Boolean, + description: ` + If true, staleness checks for cached data will be bypassed, but missing + data will be requested from the server. To force full offline mode, use + \`--offline\`. + `, + flatten, + }), + 'prefer-online': new Definition('prefer-online', { + default: false, + type: Boolean, + description: ` + If true, staleness checks for cached data will be forced, making the CLI + look for updates immediately even for fresh package data. + `, + flatten, + }), + // `prefix` has its default defined outside of this module + prefix: new Definition('prefix', { + type: path, + short: 'C', + default: '', + defaultDescription: ` + In global mode, the folder where the node executable is installed. + Otherwise, the nearest parent folder containing either a package.json + file or a node_modules folder. + `, + description: ` + The location to install global items. If set on the command line, then + it forces non-global commands to run in the specified folder. + `, + }), + preid: new Definition('preid', { + default: '', + hint: 'prerelease-id', + type: String, + description: ` + The "prerelease identifier" to use as a prefix for the "prerelease" part + of a semver. Like the \`rc\` in \`1.2.0-rc.8\`. + `, + flatten, + }), + production: new Definition('production', { + default: null, + type: [null, Boolean], + deprecated: 'Use `--omit=dev` instead.', + description: 'Alias for `--omit=dev`', + flatten (key, obj, flatOptions) { + definitions.omit.flatten('omit', obj, flatOptions) + }, + }), + progress: new Definition('progress', { + default: !ciInfo.isCI, + defaultDescription: ` + \`true\` unless running in a known CI system + `, + type: Boolean, + description: ` + When set to \`true\`, npm will display a progress bar during time + intensive operations, if \`process.stderr\` is a TTY. + + Set to \`false\` to suppress the progress bar. + `, + flatten (key, obj, flatOptions) { + flatOptions.progress = !obj.progress ? false + : !!process.stderr.isTTY && process.env.TERM !== 'dumb' + }, + }), + provenance: new Definition('provenance', { + default: false, + type: Boolean, + exclusive: ['provenance-file'], + description: ` + When publishing from a supported cloud CI/CD system, the package will be + publicly linked to where it was built and published from. + `, + flatten, + }), + 'provenance-file': new Definition('provenance-file', { + default: null, + type: path, + hint: '', + exclusive: ['provenance'], + description: ` + When publishing, the provenance bundle at the given path will be used. + `, + flatten, + }), + proxy: new Definition('proxy', { + default: null, + type: [null, false, url], // allow proxy to be disabled explicitly + description: ` + A proxy to use for outgoing http requests. If the \`HTTP_PROXY\` or + \`http_proxy\` environment variables are set, proxy settings will be + honored by the underlying \`request\` library. + `, + flatten, + }), + 'read-only': new Definition('read-only', { + default: false, + type: Boolean, + description: ` + This is used to mark a token as unable to publish when configuring + limited access tokens with the \`npm token create\` command. + `, + flatten, + }), + 'rebuild-bundle': new Definition('rebuild-bundle', { + default: true, + type: Boolean, + description: ` + Rebuild bundled dependencies after installation. + `, + flatten, + }), + registry: new Definition('registry', { + default: 'https://registry.npmjs.org/', + type: url, + description: ` + The base URL of the npm registry. + `, + flatten, + }), + 'replace-registry-host': new Definition('replace-registry-host', { + default: 'npmjs', + hint: ' | hostname', + type: ['npmjs', 'never', 'always', String], + description: ` + Defines behavior for replacing the registry host in a lockfile with the + configured registry. + + The default behavior is to replace package dist URLs from the default + registry (https://registry.npmjs.org) to the configured registry. If set to + "never", then use the registry value. If set to "always", then replace the + registry host with the configured host every time. + + You may also specify a bare hostname (e.g., "registry.npmjs.org"). + `, + flatten, + }), + save: new Definition('save', { + default: true, + defaultDescription: `\`true\` unless when using \`npm update\` where it + defaults to \`false\``, + usage: '-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer|--save-bundle', + type: Boolean, + short: 'S', + description: ` + Save installed packages to a \`package.json\` file as dependencies. + + When used with the \`npm rm\` command, removes the dependency from + \`package.json\`. + + Will also prevent writing to \`package-lock.json\` if set to \`false\`. + `, + flatten, + }), + 'save-bundle': new Definition('save-bundle', { + default: false, + type: Boolean, + short: 'B', + description: ` + If a package would be saved at install time by the use of \`--save\`, + \`--save-dev\`, or \`--save-optional\`, then also put it in the + \`bundleDependencies\` list. + + Ignored if \`--save-peer\` is set, since peerDependencies cannot be bundled. + `, + flatten (key, obj, flatOptions) { + // XXX update arborist to just ignore it if resulting saveType is peer + // otherwise this won't have the expected effect: + // + // npm config set save-peer true + // npm i foo --save-bundle --save-prod <-- should bundle + flatOptions.saveBundle = obj['save-bundle'] && !obj['save-peer'] + }, + }), + 'save-dev': new Definition('save-dev', { + default: false, + type: Boolean, + short: 'D', + description: ` + Save installed packages to a package.json file as \`devDependencies\`. + `, + flatten (key, obj, flatOptions) { + if (!obj[key]) { + if (flatOptions.saveType === 'dev') { + delete flatOptions.saveType + } + return } - return - } - flatOptions.saveType = 'dev' - }, -}) - -define('save-exact', { - default: false, - type: Boolean, - short: 'E', - description: ` - Dependencies saved to package.json will be configured with an exact - version rather than using npm's default semver range operator. - `, - flatten (key, obj, flatOptions) { - // just call the save-prefix flattener, it reads from obj['save-exact'] - definitions['save-prefix'].flatten('save-prefix', obj, flatOptions) - }, -}) - -define('save-optional', { - default: false, - type: Boolean, - short: 'O', - description: ` - Save installed packages to a package.json file as - \`optionalDependencies\`. - `, - flatten (key, obj, flatOptions) { - if (!obj[key]) { - if (flatOptions.saveType === 'optional') { - delete flatOptions.saveType - } else if (flatOptions.saveType === 'peerOptional') { - flatOptions.saveType = 'peer' + flatOptions.saveType = 'dev' + }, + }), + 'save-exact': new Definition('save-exact', { + default: false, + type: Boolean, + short: 'E', + description: ` + Dependencies saved to package.json will be configured with an exact + version rather than using npm's default semver range operator. + `, + flatten (key, obj, flatOptions) { + // just call the save-prefix flattener, it reads from obj['save-exact'] + definitions['save-prefix'].flatten('save-prefix', obj, flatOptions) + }, + }), + 'save-optional': new Definition('save-optional', { + default: false, + type: Boolean, + short: 'O', + description: ` + Save installed packages to a package.json file as + \`optionalDependencies\`. + `, + flatten (key, obj, flatOptions) { + if (!obj[key]) { + if (flatOptions.saveType === 'optional') { + delete flatOptions.saveType + } else if (flatOptions.saveType === 'peerOptional') { + flatOptions.saveType = 'peer' + } + return } - return - } - if (flatOptions.saveType === 'peerOptional') { - return - } + if (flatOptions.saveType === 'peerOptional') { + return + } - if (flatOptions.saveType === 'peer') { - flatOptions.saveType = 'peerOptional' - } else { - flatOptions.saveType = 'optional' - } - }, -}) - -define('save-peer', { - default: false, - type: Boolean, - description: ` - Save installed packages to a package.json file as \`peerDependencies\` - `, - flatten (key, obj, flatOptions) { - if (!obj[key]) { if (flatOptions.saveType === 'peer') { - delete flatOptions.saveType - } else if (flatOptions.saveType === 'peerOptional') { + flatOptions.saveType = 'peerOptional' + } else { flatOptions.saveType = 'optional' } - return - } - - if (flatOptions.saveType === 'peerOptional') { - return - } - - if (flatOptions.saveType === 'optional') { - flatOptions.saveType = 'peerOptional' - } else { - flatOptions.saveType = 'peer' - } - }, -}) - -define('save-prefix', { - default: '^', - type: String, - description: ` - Configure how versions of packages installed to a package.json file via - \`--save\` or \`--save-dev\` get prefixed. - - For example if a package has version \`1.2.3\`, by default its version is - set to \`^1.2.3\` which allows minor upgrades for that package, but after - \`npm config set save-prefix='~'\` it would be set to \`~1.2.3\` which - only allows patch upgrades. - `, - flatten (key, obj, flatOptions) { - flatOptions.savePrefix = obj['save-exact'] ? '' : obj['save-prefix'] - obj['save-prefix'] = flatOptions.savePrefix - }, -}) - -define('save-prod', { - default: false, - type: Boolean, - short: 'P', - description: ` - Save installed packages into \`dependencies\` specifically. This is - useful if a package already exists in \`devDependencies\` or - \`optionalDependencies\`, but you want to move it to be a non-optional - production dependency. - - This is the default behavior if \`--save\` is true, and neither - \`--save-dev\` or \`--save-optional\` are true. - `, - flatten (key, obj, flatOptions) { - if (!obj[key]) { - if (flatOptions.saveType === 'prod') { - delete flatOptions.saveType + }, + }), + 'save-peer': new Definition('save-peer', { + default: false, + type: Boolean, + description: ` + Save installed packages to a package.json file as \`peerDependencies\` + `, + flatten (key, obj, flatOptions) { + if (!obj[key]) { + if (flatOptions.saveType === 'peer') { + delete flatOptions.saveType + } else if (flatOptions.saveType === 'peerOptional') { + flatOptions.saveType = 'optional' + } + return } - return - } - - flatOptions.saveType = 'prod' - }, -}) - -define('scope', { - default: '', - defaultDescription: ` - the scope of the current project, if any, or "" - `, - type: String, - hint: '<@scope>', - description: ` - Associate an operation with a scope for a scoped registry. - - Useful when logging in to or out of a private registry: - - \`\`\` - # log in, linking the scope to the custom registry - npm login --scope=@mycorp --registry=https://registry.mycorp.com - # log out, removing the link and the auth token - npm logout --scope=@mycorp - \`\`\` - - This will cause \`@mycorp\` to be mapped to the registry for future - installation of packages specified according to the pattern - \`@mycorp/package\`. - - This will also cause \`npm init\` to create a scoped package. - - \`\`\` - # accept all defaults, and create a package named "@foo/whatever", - # instead of just named "whatever" - npm init --scope=@foo --yes - \`\`\` - `, - flatten (key, obj, flatOptions) { - const value = obj[key] - const scope = value && !/^@/.test(value) ? `@${value}` : value - flatOptions.scope = scope - // projectScope is kept for compatibility with npm-registry-fetch - flatOptions.projectScope = scope - }, -}) - -define('script-shell', { - default: null, - defaultDescription: ` - '/bin/sh' on POSIX systems, 'cmd.exe' on Windows - `, - type: [null, String], - description: ` - The shell to use for scripts run with the \`npm exec\`, - \`npm run\` and \`npm init \` commands. - `, - flatten (key, obj, flatOptions) { - flatOptions.scriptShell = obj[key] || undefined - }, -}) - -define('searchexclude', { - default: '', - type: String, - description: ` - Space-separated options that limit the results from search. - `, - flatten (key, obj, flatOptions) { - flatOptions.search = flatOptions.search || { limit: 20 } - flatOptions.search.exclude = obj[key].toLowerCase() - }, -}) - -define('searchlimit', { - default: 20, - type: Number, - description: ` - Number of items to limit search results to. Will not apply at all to - legacy searches. - `, - flatten (key, obj, flatOptions) { - flatOptions.search = flatOptions.search || {} - flatOptions.search.limit = obj[key] - }, -}) - -define('searchopts', { - default: '', - type: String, - description: ` - Space-separated options that are always passed to search. - `, - flatten (key, obj, flatOptions) { - flatOptions.search = flatOptions.search || { limit: 20 } - flatOptions.search.opts = querystring.parse(obj[key]) - }, -}) - -define('searchstaleness', { - default: 15 * 60, - type: Number, - description: ` - The age of the cache, in seconds, before another registry request is made - if using legacy search endpoint. - `, - flatten (key, obj, flatOptions) { - flatOptions.search = flatOptions.search || { limit: 20 } - flatOptions.search.staleness = obj[key] - }, -}) - -define('shell', { - default: shell, - defaultDescription: ` - SHELL environment variable, or "bash" on Posix, or "cmd.exe" on Windows - `, - type: String, - description: ` - The shell to run for the \`npm explore\` command. - `, - flatten, -}) - -define('shrinkwrap', { - default: true, - type: Boolean, - deprecated: ` - Use the --package-lock setting instead. - `, - description: ` - Alias for --package-lock - `, - flatten (key, obj, flatOptions) { - obj['package-lock'] = obj.shrinkwrap - definitions['package-lock'].flatten('package-lock', obj, flatOptions) - }, -}) - -define('sign-git-commit', { - default: false, - type: Boolean, - description: ` - If set to true, then the \`npm version\` command will commit the new - package version using \`-S\` to add a signature. - - Note that git requires you to have set up GPG keys in your git configs - for this to work properly. - `, - flatten, -}) - -define('sign-git-tag', { - default: false, - type: Boolean, - description: ` - If set to true, then the \`npm version\` command will tag the version - using \`-s\` to add a signature. - - Note that git requires you to have set up GPG keys in your git configs - for this to work properly. - `, - flatten, -}) - -define('strict-peer-deps', { - default: false, - type: Boolean, - description: ` - If set to \`true\`, and \`--legacy-peer-deps\` is not set, then _any_ - conflicting \`peerDependencies\` will be treated as an install failure, - even if npm could reasonably guess the appropriate resolution based on - non-peer dependency relationships. - - By default, conflicting \`peerDependencies\` deep in the dependency graph - will be resolved using the nearest non-peer dependency specification, - even if doing so will result in some packages receiving a peer dependency - outside the range set in their package's \`peerDependencies\` object. - - When such an override is performed, a warning is printed, explaining the - conflict and the packages involved. If \`--strict-peer-deps\` is set, - then this warning is treated as a failure. - `, - flatten, -}) - -define('strict-ssl', { - default: true, - type: Boolean, - description: ` - Whether or not to do SSL key validation when making requests to the - registry via https. - - See also the \`ca\` config. - `, - flatten (key, obj, flatOptions) { - flatOptions.strictSSL = obj[key] - }, -}) - -define('tag', { - default: 'latest', - type: String, - description: ` - If you ask npm to install a package and don't tell it a specific version, - then it will install the specified tag. - - Also the tag that is added to the package@version specified by the \`npm - tag\` command, if no explicit tag is given. - - When used by the \`npm diff\` command, this is the tag used to fetch the - tarball that will be compared with the local files by default. - `, - flatten (key, obj, flatOptions) { - flatOptions.defaultTag = obj[key] - }, -}) - -define('tag-version-prefix', { - default: 'v', - type: String, - description: ` - If set, alters the prefix used when tagging a new version when performing - a version increment using \`npm version\`. To remove the prefix - altogether, set it to the empty string: \`""\`. - - Because other tools may rely on the convention that npm version tags look - like \`v1.0.0\`, _only use this property if it is absolutely necessary_. - In particular, use care when overriding this setting for public packages. - `, - flatten, -}) - -define('timing', { - default: false, - type: Boolean, - description: ` - If true, writes timing information to a process specific json file in - the cache or \`logs-dir\`. The file name ends with \`-timing.json\`. - - You can quickly view it with this [json](https://npm.im/json) command - line: \`cat ~/.npm/_logs/*-timing.json | npm exec -- json -g\`. - - Timing information will also be reported in the terminal. To suppress this - while still writing the timing file, use \`--silent\`. - `, -}) - -define('umask', { - default: 0, - type: Umask, - description: ` - The "umask" value to use when setting the file creation mode on files and - folders. - - Folders and executables are given a mode which is \`0o777\` masked - against this value. Other files are given a mode which is \`0o666\` - masked against this value. - - Note that the underlying system will _also_ apply its own umask value to - files and folders that are created, and npm does not circumvent this, but - rather adds the \`--umask\` config to it. - - Thus, the effective default umask value on most POSIX systems is 0o22, - meaning that folders and executables are created with a mode of 0o755 and - other files are created with a mode of 0o644. - `, - flatten, -}) - -define('unicode', { - default: unicode, - defaultDescription: ` - false on windows, true on mac/unix systems with a unicode locale, as - defined by the \`LC_ALL\`, \`LC_CTYPE\`, or \`LANG\` environment variables. - `, - type: Boolean, - description: ` - When set to true, npm uses unicode characters in the tree output. When - false, it uses ascii characters instead of unicode glyphs. - `, - flatten, -}) - -define('update-notifier', { - default: true, - type: Boolean, - description: ` - Set to false to suppress the update notification when using an older - version of npm than the latest. - `, -}) - -define('usage', { - default: false, - type: Boolean, - short: ['?', 'H', 'h'], - description: ` - Show short usage output about the command specified. - `, -}) - -define('user-agent', { - default: 'npm/{npm-version} ' + - 'node/{node-version} ' + - '{platform} ' + - '{arch} ' + - 'workspaces/{workspaces} ' + - '{ci}', - type: String, - description: ` - Sets the User-Agent request header. The following fields are replaced - with their actual counterparts: - - * \`{npm-version}\` - The npm version in use - * \`{node-version}\` - The Node.js version in use - * \`{platform}\` - The value of \`process.platform\` - * \`{arch}\` - The value of \`process.arch\` - * \`{workspaces}\` - Set to \`true\` if the \`workspaces\` or \`workspace\` - options are set. - * \`{ci}\` - The value of the \`ci-name\` config, if set, prefixed with - \`ci/\`, or an empty string if \`ci-name\` is empty. - `, - flatten (key, obj, flatOptions) { - const value = obj[key] - const ciName = ciInfo.name?.toLowerCase().split(' ').join('-') || null - let inWorkspaces = false - if (obj.workspaces || obj.workspace && obj.workspace.length) { - inWorkspaces = true - } - flatOptions.userAgent = - value.replace(/\{node-version\}/gi, process.version) - .replace(/\{npm-version\}/gi, obj['npm-version']) - .replace(/\{platform\}/gi, process.platform) - .replace(/\{arch\}/gi, process.arch) - .replace(/\{workspaces\}/gi, inWorkspaces) - .replace(/\{ci\}/gi, ciName ? `ci/${ciName}` : '') - .trim() - - // We can't clobber the original or else subsequent flattening will fail - // (i.e. when we change the underlying config values) - // obj[key] = flatOptions.userAgent - - // user-agent is a unique kind of config item that gets set from a template - // and ends up translated. Because of this, the normal "should we set this - // to process.env also doesn't work - process.env.npm_config_user_agent = flatOptions.userAgent - }, -}) - -define('userconfig', { - default: '~/.npmrc', - type: path, - description: ` - The location of user-level configuration settings. - - This may be overridden by the \`npm_config_userconfig\` environment - variable or the \`--userconfig\` command line option, but may _not_ - be overridden by settings in the \`globalconfig\` file. - `, -}) - -define('version', { - default: false, - type: Boolean, - short: 'v', - description: ` - If true, output the npm version and exit successfully. - - Only relevant when specified explicitly on the command line. - `, -}) - -define('versions', { - default: false, - type: Boolean, - description: ` - If true, output the npm version as well as node's \`process.versions\` - map and the version in the current working directory's \`package.json\` - file if one exists, and exit successfully. + if (flatOptions.saveType === 'peerOptional') { + return + } - Only relevant when specified explicitly on the command line. - `, -}) + if (flatOptions.saveType === 'optional') { + flatOptions.saveType = 'peerOptional' + } else { + flatOptions.saveType = 'peer' + } + }, + }), + 'save-prefix': new Definition('save-prefix', { + default: '^', + type: String, + description: ` + Configure how versions of packages installed to a package.json file via + \`--save\` or \`--save-dev\` get prefixed. + + For example if a package has version \`1.2.3\`, by default its version is + set to \`^1.2.3\` which allows minor upgrades for that package, but after + \`npm config set save-prefix='~'\` it would be set to \`~1.2.3\` which + only allows patch upgrades. + `, + flatten (key, obj, flatOptions) { + flatOptions.savePrefix = obj['save-exact'] ? '' : obj['save-prefix'] + obj['save-prefix'] = flatOptions.savePrefix + }, + }), + 'save-prod': new Definition('save-prod', { + default: false, + type: Boolean, + short: 'P', + description: ` + Save installed packages into \`dependencies\` specifically. This is + useful if a package already exists in \`devDependencies\` or + \`optionalDependencies\`, but you want to move it to be a non-optional + production dependency. + + This is the default behavior if \`--save\` is true, and neither + \`--save-dev\` or \`--save-optional\` are true. + `, + flatten (key, obj, flatOptions) { + if (!obj[key]) { + if (flatOptions.saveType === 'prod') { + delete flatOptions.saveType + } + return + } -define('viewer', { - default: isWindows ? 'browser' : 'man', - defaultDescription: ` - "man" on Posix, "browser" on Windows - `, - type: String, - description: ` - The program to use to view help content. + flatOptions.saveType = 'prod' + }, + }), + 'sbom-format': new Definition('sbom-format', { + default: null, + type: [ + 'cyclonedx', + 'spdx', + ], + description: ` + SBOM format to use when generating SBOMs. + `, + flatten, + }), + 'sbom-type': new Definition('sbom-type', { + default: 'library', + type: [ + 'library', + 'application', + 'framework', + ], + description: ` + The type of package described by the generated SBOM. For SPDX, this is the + value for the \`primaryPackagePurpose\` field. For CycloneDX, this is the + value for the \`type\` field. + `, + flatten, + }), + scope: new Definition('scope', { + default: '', + defaultDescription: ` + the scope of the current project, if any, or "" + `, + type: String, + hint: '<@scope>', + description: ` + Associate an operation with a scope for a scoped registry. + + Useful when logging in to or out of a private registry: + + \`\`\` + # log in, linking the scope to the custom registry + npm login --scope=@mycorp --registry=https://registry.mycorp.com + + # log out, removing the link and the auth token + npm logout --scope=@mycorp + \`\`\` + + This will cause \`@mycorp\` to be mapped to the registry for future + installation of packages specified according to the pattern + \`@mycorp/package\`. + + This will also cause \`npm init\` to create a scoped package. + + \`\`\` + # accept all defaults, and create a package named "@foo/whatever", + # instead of just named "whatever" + npm init --scope=@foo --yes + \`\`\` + `, + flatten (key, obj, flatOptions) { + const value = obj[key] + const scope = value && !/^@/.test(value) ? `@${value}` : value + flatOptions.scope = scope + // projectScope is kept for compatibility with npm-registry-fetch + flatOptions.projectScope = scope + }, + }), + 'script-shell': new Definition('script-shell', { + default: null, + defaultDescription: ` + '/bin/sh' on POSIX systems, 'cmd.exe' on Windows + `, + type: [null, String], + description: ` + The shell to use for scripts run with the \`npm exec\`, + \`npm run\` and \`npm init \` commands. + `, + flatten (key, obj, flatOptions) { + flatOptions.scriptShell = obj[key] || undefined + }, + }), + searchexclude: new Definition('searchexclude', { + default: '', + type: String, + description: ` + Space-separated options that limit the results from search. + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || { limit: 20 } + flatOptions.search.exclude = obj[key].toLowerCase() + }, + }), + searchlimit: new Definition('searchlimit', { + default: 20, + type: Number, + description: ` + Number of items to limit search results to. Will not apply at all to + legacy searches. + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || {} + flatOptions.search.limit = obj[key] + }, + }), + searchopts: new Definition('searchopts', { + default: '', + type: String, + description: ` + Space-separated options that are always passed to search. + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || { limit: 20 } + flatOptions.search.opts = querystring.parse(obj[key]) + }, + }), + searchstaleness: new Definition('searchstaleness', { + default: 15 * 60, + type: Number, + description: ` + The age of the cache, in seconds, before another registry request is made + if using legacy search endpoint. + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || { limit: 20 } + flatOptions.search.staleness = obj[key] + }, + }), + shell: new Definition('shell', { + default: shell, + defaultDescription: ` + SHELL environment variable, or "bash" on Posix, or "cmd.exe" on Windows + `, + type: String, + description: ` + The shell to run for the \`npm explore\` command. + `, + flatten, + }), + shrinkwrap: new Definition('shrinkwrap', { + default: true, + type: Boolean, + deprecated: ` + Use the --package-lock setting instead. + `, + description: ` + Alias for --package-lock + `, + flatten (key, obj, flatOptions) { + obj['package-lock'] = obj.shrinkwrap + definitions['package-lock'].flatten('package-lock', obj, flatOptions) + }, + }), + 'sign-git-commit': new Definition('sign-git-commit', { + default: false, + type: Boolean, + description: ` + If set to true, then the \`npm version\` command will commit the new + package version using \`-S\` to add a signature. + + Note that git requires you to have set up GPG keys in your git configs + for this to work properly. + `, + flatten, + }), + 'sign-git-tag': new Definition('sign-git-tag', { + default: false, + type: Boolean, + description: ` + If set to true, then the \`npm version\` command will tag the version + using \`-s\` to add a signature. + + Note that git requires you to have set up GPG keys in your git configs + for this to work properly. + `, + flatten, + }), + 'strict-peer-deps': new Definition('strict-peer-deps', { + default: false, + type: Boolean, + description: ` + If set to \`true\`, and \`--legacy-peer-deps\` is not set, then _any_ + conflicting \`peerDependencies\` will be treated as an install failure, + even if npm could reasonably guess the appropriate resolution based on + non-peer dependency relationships. + + By default, conflicting \`peerDependencies\` deep in the dependency graph + will be resolved using the nearest non-peer dependency specification, + even if doing so will result in some packages receiving a peer dependency + outside the range set in their package's \`peerDependencies\` object. + + When such an override is performed, a warning is printed, explaining the + conflict and the packages involved. If \`--strict-peer-deps\` is set, + then this warning is treated as a failure. + `, + flatten, + }), + 'strict-ssl': new Definition('strict-ssl', { + default: true, + type: Boolean, + description: ` + Whether or not to do SSL key validation when making requests to the + registry via https. + + See also the \`ca\` config. + `, + flatten (key, obj, flatOptions) { + flatOptions.strictSSL = obj[key] + }, + }), + tag: new Definition('tag', { + default: 'latest', + type: String, + description: ` + If you ask npm to install a package and don't tell it a specific version, + then it will install the specified tag. + + Also the tag that is added to the package@version specified by the \`npm + tag\` command, if no explicit tag is given. + + When used by the \`npm diff\` command, this is the tag used to fetch the + tarball that will be compared with the local files by default. + `, + flatten (key, obj, flatOptions) { + flatOptions.defaultTag = obj[key] + }, + }), + 'tag-version-prefix': new Definition('tag-version-prefix', { + default: 'v', + type: String, + description: ` + If set, alters the prefix used when tagging a new version when performing + a version increment using \`npm version\`. To remove the prefix + altogether, set it to the empty string: \`""\`. + + Because other tools may rely on the convention that npm version tags look + like \`v1.0.0\`, _only use this property if it is absolutely necessary_. + In particular, use care when overriding this setting for public packages. + `, + flatten, + }), + timing: new Definition('timing', { + default: false, + type: Boolean, + description: ` + If true, writes timing information to a process specific json file in + the cache or \`logs-dir\`. The file name ends with \`-timing.json\`. + + You can quickly view it with this [json](https://npm.im/json) command + line: \`cat ~/.npm/_logs/*-timing.json | npm exec -- json -g\`. + + Timing information will also be reported in the terminal. To suppress this + while still writing the timing file, use \`--silent\`. + `, + }), + umask: new Definition('umask', { + default: 0, + type: Umask, + description: ` + The "umask" value to use when setting the file creation mode on files and + folders. + + Folders and executables are given a mode which is \`0o777\` masked + against this value. Other files are given a mode which is \`0o666\` + masked against this value. + + Note that the underlying system will _also_ apply its own umask value to + files and folders that are created, and npm does not circumvent this, but + rather adds the \`--umask\` config to it. + + Thus, the effective default umask value on most POSIX systems is 0o22, + meaning that folders and executables are created with a mode of 0o755 and + other files are created with a mode of 0o644. + `, + flatten, + }), + unicode: new Definition('unicode', { + default: unicode, + defaultDescription: ` + false on windows, true on mac/unix systems with a unicode locale, as + defined by the \`LC_ALL\`, \`LC_CTYPE\`, or \`LANG\` environment variables. + `, + type: Boolean, + description: ` + When set to true, npm uses unicode characters in the tree output. When + false, it uses ascii characters instead of unicode glyphs. + `, + flatten, + }), + 'update-notifier': new Definition('update-notifier', { + default: true, + type: Boolean, + description: ` + Set to false to suppress the update notification when using an older + version of npm than the latest. + `, + }), + usage: new Definition('usage', { + default: false, + type: Boolean, + short: ['?', 'H', 'h'], + description: ` + Show short usage output about the command specified. + `, + }), + 'user-agent': new Definition('user-agent', { + default: 'npm/{npm-version} ' + + 'node/{node-version} ' + + '{platform} ' + + '{arch} ' + + 'workspaces/{workspaces} ' + + '{ci}', + type: String, + description: ` + Sets the User-Agent request header. The following fields are replaced + with their actual counterparts: + + * \`{npm-version}\` - The npm version in use + * \`{node-version}\` - The Node.js version in use + * \`{platform}\` - The value of \`process.platform\` + * \`{arch}\` - The value of \`process.arch\` + * \`{workspaces}\` - Set to \`true\` if the \`workspaces\` or \`workspace\` + options are set. + * \`{ci}\` - The value of the \`ci-name\` config, if set, prefixed with + \`ci/\`, or an empty string if \`ci-name\` is empty. + `, + flatten (key, obj, flatOptions) { + const value = obj[key] + const ciName = ciInfo.name?.toLowerCase().split(' ').join('-') || null + let inWorkspaces = false + if (obj.workspaces || obj.workspace && obj.workspace.length) { + inWorkspaces = true + } + flatOptions.userAgent = + value.replace(/\{node-version\}/gi, process.version) + .replace(/\{npm-version\}/gi, obj['npm-version']) + .replace(/\{platform\}/gi, process.platform) + .replace(/\{arch\}/gi, process.arch) + .replace(/\{workspaces\}/gi, inWorkspaces) + .replace(/\{ci\}/gi, ciName ? `ci/${ciName}` : '') + .trim() + + // We can't clobber the original or else subsequent flattening will fail + // (i.e. when we change the underlying config values) + // obj[key] = flatOptions.userAgent + + // user-agent is a unique kind of config item that gets set from a template + // and ends up translated. Because of this, the normal "should we set this + // to process.env also doesn't work + process.env.npm_config_user_agent = flatOptions.userAgent + }, + }), + userconfig: new Definition('userconfig', { + default: '~/.npmrc', + type: path, + description: ` + The location of user-level configuration settings. + + This may be overridden by the \`npm_config_userconfig\` environment + variable or the \`--userconfig\` command line option, but may _not_ + be overridden by settings in the \`globalconfig\` file. + `, + }), + version: new Definition('version', { + default: false, + type: Boolean, + short: 'v', + description: ` + If true, output the npm version and exit successfully. + + Only relevant when specified explicitly on the command line. + `, + }), + versions: new Definition('versions', { + default: false, + type: Boolean, + description: ` + If true, output the npm version as well as node's \`process.versions\` + map and the version in the current working directory's \`package.json\` + file if one exists, and exit successfully. + + Only relevant when specified explicitly on the command line. + `, + }), + viewer: new Definition('viewer', { + default: isWindows ? 'browser' : 'man', + defaultDescription: ` + "man" on Posix, "browser" on Windows + `, + type: String, + description: ` + The program to use to view help content. + + Set to \`"browser"\` to view html help content in the default web browser. + `, + }), + which: new Definition('which', { + default: null, + hint: '', + type: [null, Number], + description: ` + If there are multiple funding sources, which 1-indexed source URL to open. + `, + }), + workspace: new Definition('workspace', { + default: [], + type: [String, Array], + hint: '', + short: 'w', + envExport: false, + description: ` + Enable running a command in the context of the configured workspaces of the + current project while filtering by running only the workspaces defined by + this configuration option. + + Valid values for the \`workspace\` config are either: + + * Workspace names + * Path to a workspace directory + * Path to a parent workspace directory (will result in selecting all + workspaces within that folder) + + When set for the \`npm init\` command, this may be set to the folder of + a workspace which does not yet exist, to create the folder and set it + up as a brand new workspace within the project. + `, + flatten: (key, obj, flatOptions) => { + definitions['user-agent'].flatten('user-agent', obj, flatOptions) + }, + }), + workspaces: new Definition('workspaces', { + default: null, + type: [null, Boolean], + short: 'ws', + envExport: false, + description: ` + Set to true to run the command in the context of **all** configured + workspaces. + + Explicitly setting this to false will cause commands like \`install\` to + ignore workspaces altogether. + When not set explicitly: + + - Commands that operate on the \`node_modules\` tree (install, update, + etc.) will link workspaces into the \`node_modules\` folder. + - Commands that do other things (test, exec, publish, etc.) will operate + on the root project, _unless_ one or more workspaces are specified in + the \`workspace\` config. + `, + flatten: (key, obj, flatOptions) => { + definitions['user-agent'].flatten('user-agent', obj, flatOptions) + + // TODO: this is a derived value, and should be reworked when we have a + // pattern for derived value + + // workspacesEnabled is true whether workspaces is null or true + // commands contextually work with workspaces or not regardless of + // configuration, so we need an option specifically to disable workspaces + flatOptions.workspacesEnabled = obj[key] !== false + }, + }), + 'workspaces-update': new Definition('workspaces-update', { + default: true, + type: Boolean, + description: ` + If set to true, the npm cli will run an update after operations that may + possibly change the workspaces installed to the \`node_modules\` folder. + `, + flatten, + }), + yes: new Definition('yes', { + default: null, + type: [null, Boolean], + short: 'y', + description: ` + Automatically answer "yes" to any prompts that npm might print on + the command line. + `, + }), +} - Set to \`"browser"\` to view html help content in the default web browser. - `, -}) - -define('which', { - default: null, - hint: '', - type: [null, Number], - description: ` - If there are multiple funding sources, which 1-indexed source URL to open. - `, -}) - -define('workspace', { - default: [], - type: [String, Array], - hint: '', - short: 'w', - envExport: false, - description: ` - Enable running a command in the context of the configured workspaces of the - current project while filtering by running only the workspaces defined by - this configuration option. - - Valid values for the \`workspace\` config are either: - - * Workspace names - * Path to a workspace directory - * Path to a parent workspace directory (will result in selecting all - workspaces within that folder) - - When set for the \`npm init\` command, this may be set to the folder of - a workspace which does not yet exist, to create the folder and set it - up as a brand new workspace within the project. - `, - flatten: (key, obj, flatOptions) => { - definitions['user-agent'].flatten('user-agent', obj, flatOptions) - }, -}) - -define('workspaces', { - default: null, - type: [null, Boolean], - short: 'ws', - envExport: false, - description: ` - Set to true to run the command in the context of **all** configured - workspaces. - - Explicitly setting this to false will cause commands like \`install\` to - ignore workspaces altogether. - When not set explicitly: - - - Commands that operate on the \`node_modules\` tree (install, update, - etc.) will link workspaces into the \`node_modules\` folder. - - Commands that do other things (test, exec, publish, etc.) will operate - on the root project, _unless_ one or more workspaces are specified in - the \`workspace\` config. - `, - flatten: (key, obj, flatOptions) => { - definitions['user-agent'].flatten('user-agent', obj, flatOptions) - - // TODO: this is a derived value, and should be reworked when we have a - // pattern for derived value - - // workspacesEnabled is true whether workspaces is null or true - // commands contextually work with workspaces or not regardless of - // configuration, so we need an option specifically to disable workspaces - flatOptions.workspacesEnabled = obj[key] !== false - }, -}) - -define('workspaces-update', { - default: true, - type: Boolean, - description: ` - If set to true, the npm cli will run an update after operations that may - possibly change the workspaces installed to the \`node_modules\` folder. - `, - flatten, -}) - -define('yes', { - default: null, - type: [null, Boolean], - short: 'y', - description: ` - Automatically answer "yes" to any prompts that npm might print on - the command line. - `, -}) +module.exports = definitions diff --git a/deps/npm/node_modules/@npmcli/config/lib/index.js b/deps/npm/node_modules/@npmcli/config/lib/index.js index b09ecc478f64fd..c99292db9afb40 100644 --- a/deps/npm/node_modules/@npmcli/config/lib/index.js +++ b/deps/npm/node_modules/@npmcli/config/lib/index.js @@ -2,12 +2,10 @@ const { walkUp } = require('walk-up-path') const ini = require('ini') const nopt = require('nopt') -const mapWorkspaces = require('@npmcli/map-workspaces') -const rpj = require('read-package-json-fast') -const log = require('proc-log') +const { log, time } = require('proc-log') -const { resolve, dirname, join } = require('path') -const { homedir } = require('os') +const { resolve, dirname, join } = require('node:path') +const { homedir } = require('node:os') const { readFile, writeFile, @@ -28,35 +26,12 @@ const dirExists = (...p) => stat(resolve(...p)) const hasOwnProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key) -// define a custom getter, but turn into a normal prop -// if we set it. otherwise it can't be set on child objects -const settableGetter = (obj, key, get) => { - Object.defineProperty(obj, key, { - get, - set (value) { - Object.defineProperty(obj, key, { - value, - configurable: true, - writable: true, - enumerable: true, - }) - }, - configurable: true, - enumerable: true, - }) -} - const typeDefs = require('./type-defs.js') const nerfDart = require('./nerf-dart.js') const envReplace = require('./env-replace.js') const parseField = require('./parse-field.js') -const typeDescription = require('./type-description.js') const setEnvs = require('./set-envs.js') -const { - ErrInvalidAuth, -} = require('./errors.js') - // types that can be saved back to const confFileTypes = new Set([ 'global', @@ -226,7 +201,7 @@ class Config { } // create the object for flat options passed to deps - process.emit('time', 'config:load:flatten') + const timeEnd = time.start('config:load:flatten') this.#flatOptions = {} // walk from least priority to highest for (const { data } of this.data.values()) { @@ -234,7 +209,7 @@ class Config { } this.#flatOptions.nodeBin = this.execPath this.#flatOptions.npmBin = this.npmBin - process.emit('timeEnd', 'config:load:flatten') + timeEnd() return this.#flatOptions } @@ -258,37 +233,24 @@ class Config { throw new Error('attempting to load npm config multiple times') } - process.emit('time', 'config:load') // first load the defaults, which sets the global prefix - process.emit('time', 'config:load:defaults') this.loadDefaults() - process.emit('timeEnd', 'config:load:defaults') // next load the builtin config, as this sets new effective defaults - process.emit('time', 'config:load:builtin') await this.loadBuiltinConfig() - process.emit('timeEnd', 'config:load:builtin') // cli and env are not async, and can set the prefix, relevant to project - process.emit('time', 'config:load:cli') this.loadCLI() - process.emit('timeEnd', 'config:load:cli') - process.emit('time', 'config:load:env') this.loadEnv() - process.emit('timeEnd', 'config:load:env') // next project config, which can affect userconfig location - process.emit('time', 'config:load:project') await this.loadProjectConfig() - process.emit('timeEnd', 'config:load:project') + // then user config, which can affect globalconfig location - process.emit('time', 'config:load:user') await this.loadUserConfig() - process.emit('timeEnd', 'config:load:user') + // last but not least, global config file - process.emit('time', 'config:load:global') await this.loadGlobalConfig() - process.emit('timeEnd', 'config:load:global') // set this before calling setEnvs, so that we don't have to share // private attributes, as that module also does a bunch of get operations @@ -297,11 +259,7 @@ class Config { // set proper globalPrefix now that everything is loaded this.globalPrefix = this.get('prefix') - process.emit('time', 'config:load:setEnvs') this.setEnvs() - process.emit('timeEnd', 'config:load:setEnvs') - - process.emit('timeEnd', 'config:load') } loadDefaults () { @@ -329,7 +287,21 @@ class Config { // default the globalconfig file to that location, instead of the default // global prefix. It's weird that `npm get globalconfig --prefix=/foo` // returns `/foo/etc/npmrc`, but better to not change it at this point. - settableGetter(data, 'globalconfig', () => resolve(this.#get('prefix'), 'etc/npmrc')) + // define a custom getter, but turn into a normal prop + // if we set it. otherwise it can't be set on child objects + Object.defineProperty(data, 'globalconfig', { + get: () => resolve(this.#get('prefix'), 'etc/npmrc'), + set (value) { + Object.defineProperty(data, 'globalconfig', { + value, + configurable: true, + writable: true, + enumerable: true, + }) + }, + configurable: true, + enumerable: true, + }) } loadHome () { @@ -444,6 +416,7 @@ class Config { } if (authProblems.length) { + const { ErrInvalidAuth } = require('./errors.js') throw new ErrInvalidAuth(authProblems) } @@ -512,6 +485,7 @@ class Config { } invalidHandler (k, val, type, source, where) { + const typeDescription = require('./type-description.js') log.warn( 'invalid config', k + '=' + JSON.stringify(val), @@ -583,7 +557,7 @@ class Config { const k = envReplace(key, this.env) const v = this.parseField(value, k) if (where !== 'default') { - this.#checkDeprecated(k, where, obj, [key, value]) + this.#checkDeprecated(k) if (this.definitions[key]?.exclusive) { for (const exclusive of this.definitions[key].exclusive) { if (!this.isDefault(exclusive)) { @@ -597,7 +571,7 @@ class Config { } } - #checkDeprecated (key, where, obj, kv) { + #checkDeprecated (key) { // XXX(npm9+) make this throw an error if (this.deprecated[key]) { log.warn('config', key, this.deprecated[key]) @@ -610,8 +584,8 @@ class Config { } async #loadFile (file, type) { - process.emit('time', 'config:load:file:' + file) // only catch the error from readFile, not from the loadObject call + log.silly(`config:load:file:${file}`) await readFile(file, 'utf8').then( data => { const parsedConfig = ini.parse(data) @@ -624,7 +598,6 @@ class Config { }, er => this.#loadObject(null, type, file, er) ) - process.emit('timeEnd', 'config:load:file:' + file) } loadBuiltinConfig () { @@ -696,6 +669,7 @@ class Config { } if (this.localPrefix && hasPackageJson) { + const rpj = require('read-package-json-fast') // if we already set localPrefix but this dir has a package.json // then we need to see if `p` is a workspace root by reading its package.json // however, if reading it fails then we should just move on @@ -704,6 +678,7 @@ class Config { continue } + const mapWorkspaces = require('@npmcli/map-workspaces') const workspaces = await mapWorkspaces({ cwd: p, pkg }) for (const w of workspaces.values()) { if (w === this.localPrefix) { @@ -764,7 +739,7 @@ class Config { const iniData = ini.stringify(conf.raw).trim() + '\n' if (!iniData.trim()) { // ignore the unlink error (eg, if file doesn't exist) - await unlink(conf.source).catch(er => {}) + await unlink(conf.source).catch(() => {}) return } const dir = dirname(conf.source) @@ -799,12 +774,9 @@ class Config { this.delete(`${nerfed}:keyfile`, level) } - setCredentialsByURI (uri, { token, username, password, email, certfile, keyfile }) { + setCredentialsByURI (uri, { token, username, password, certfile, keyfile }) { const nerfed = nerfDart(uri) - // email is either provided, a top level key, or nothing - email = email || this.get('email', 'user') - // field that hasn't been used as documented for a LONG time, // and as of npm 7.10.0, isn't used at all. We just always // send auth if we have it, only to the URIs under the nerf dart. diff --git a/deps/npm/node_modules/@npmcli/config/lib/nerf-dart.js b/deps/npm/node_modules/@npmcli/config/lib/nerf-dart.js index d6ae4aa2aa7e2a..030d92a82270d2 100644 --- a/deps/npm/node_modules/@npmcli/config/lib/nerf-dart.js +++ b/deps/npm/node_modules/@npmcli/config/lib/nerf-dart.js @@ -1,4 +1,4 @@ -const { URL } = require('url') +const { URL } = require('node:url') /** * Maps a URL to an identifier. diff --git a/deps/npm/node_modules/@npmcli/config/lib/parse-field.js b/deps/npm/node_modules/@npmcli/config/lib/parse-field.js index 099b0b4eaf1a83..9ac3d21cae8b71 100644 --- a/deps/npm/node_modules/@npmcli/config/lib/parse-field.js +++ b/deps/npm/node_modules/@npmcli/config/lib/parse-field.js @@ -1,7 +1,7 @@ // Parse a field, coercing it to the best type available. const typeDefs = require('./type-defs.js') const envReplace = require('./env-replace.js') -const { resolve } = require('path') +const { resolve } = require('node:path') const { parse: umaskParse } = require('./umask.js') diff --git a/deps/npm/node_modules/@npmcli/config/lib/type-defs.js b/deps/npm/node_modules/@npmcli/config/lib/type-defs.js index 20a827c3d164e9..3c9dfe19ded113 100644 --- a/deps/npm/node_modules/@npmcli/config/lib/type-defs.js +++ b/deps/npm/node_modules/@npmcli/config/lib/type-defs.js @@ -1,10 +1,12 @@ const nopt = require('nopt') -const { Umask, validate: validateUmask } = require('./umask.js') +const { validate: validateUmask } = require('./umask.js') -const semver = require('semver') +class Umask {} +class Semver {} +const semverValid = require('semver/functions/valid') const validateSemver = (data, k, val) => { - const valid = semver.valid(val) + const valid = semverValid(val) if (!valid) { return false } @@ -23,7 +25,7 @@ const validatePath = (data, k, val) => { module.exports = { ...nopt.typeDefs, semver: { - type: semver, + type: Semver, validate: validateSemver, description: 'full valid SemVer string', }, diff --git a/deps/npm/node_modules/@npmcli/config/lib/umask.js b/deps/npm/node_modules/@npmcli/config/lib/umask.js index 4d9ebbdc965451..2ddc5ca7822326 100644 --- a/deps/npm/node_modules/@npmcli/config/lib/umask.js +++ b/deps/npm/node_modules/@npmcli/config/lib/umask.js @@ -1,4 +1,3 @@ -class Umask {} const parse = val => { // this is run via nopt and parse field where everything is // converted to a string first, ignoring coverage for now @@ -33,4 +32,4 @@ const validate = (data, k, val) => { } } -module.exports = { Umask, parse, validate } +module.exports = { parse, validate } diff --git a/deps/npm/node_modules/@npmcli/config/package.json b/deps/npm/node_modules/@npmcli/config/package.json index 28102bea2781aa..8c59bc3ae3dff6 100644 --- a/deps/npm/node_modules/@npmcli/config/package.json +++ b/deps/npm/node_modules/@npmcli/config/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/config", - "version": "8.2.0", + "version": "8.3.1", "files": [ "bin/", "lib/" @@ -9,7 +9,7 @@ "description": "Configuration management for the npm cli", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/config" }, "author": "GitHub Inc.", @@ -38,9 +38,9 @@ "dependencies": { "@npmcli/map-workspaces": "^3.0.2", "ci-info": "^4.0.0", - "ini": "^4.1.0", + "ini": "^4.1.2", "nopt": "^7.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.2.0", "read-package-json-fast": "^3.0.2", "semver": "^7.3.5", "walk-up-path": "^3.0.1" diff --git a/deps/npm/node_modules/@npmcli/disparity-colors/lib/index.js b/deps/npm/node_modules/@npmcli/disparity-colors/lib/index.js deleted file mode 100644 index 3d2aa56be92536..00000000000000 --- a/deps/npm/node_modules/@npmcli/disparity-colors/lib/index.js +++ /dev/null @@ -1,34 +0,0 @@ -const ansi = require('ansi-styles') - -const colors = { - removed: ansi.red, - added: ansi.green, - header: ansi.yellow, - section: ansi.magenta, -} - -function colorize (str, opts) { - let headerLength = (opts || {}).headerLength - if (typeof headerLength !== 'number' || Number.isNaN(headerLength)) { - headerLength = 2 - } - - const color = (colorStr, colorId) => { - const { open, close } = colors[colorId] - // avoid highlighting the "\n" (would highlight till the end of the line) - return colorStr.replace(/[^\n\r]+/g, open + '$&' + close) - } - - // this RegExp will include all the `\n` chars into the lines, easier to join - const lines = ((typeof str === 'string' && str) || '').split(/^/m) - - const start = color(lines.slice(0, headerLength).join(''), 'header') - const end = lines.slice(headerLength).join('') - .replace(/^-.*/gm, color('$&', 'removed')) - .replace(/^\+.*/gm, color('$&', 'added')) - .replace(/^@@.+@@/gm, color('$&', 'section')) - - return start + end -} - -module.exports = colorize diff --git a/deps/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/index.js b/deps/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/index.js deleted file mode 100644 index 5d82581a13f990..00000000000000 --- a/deps/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/index.js +++ /dev/null @@ -1,163 +0,0 @@ -'use strict'; - -const wrapAnsi16 = (fn, offset) => (...args) => { - const code = fn(...args); - return `\u001B[${code + offset}m`; -}; - -const wrapAnsi256 = (fn, offset) => (...args) => { - const code = fn(...args); - return `\u001B[${38 + offset};5;${code}m`; -}; - -const wrapAnsi16m = (fn, offset) => (...args) => { - const rgb = fn(...args); - return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; -}; - -const ansi2ansi = n => n; -const rgb2rgb = (r, g, b) => [r, g, b]; - -const setLazyProperty = (object, property, get) => { - Object.defineProperty(object, property, { - get: () => { - const value = get(); - - Object.defineProperty(object, property, { - value, - enumerable: true, - configurable: true - }); - - return value; - }, - enumerable: true, - configurable: true - }); -}; - -/** @type {typeof import('color-convert')} */ -let colorConvert; -const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { - if (colorConvert === undefined) { - colorConvert = require('color-convert'); - } - - const offset = isBackground ? 10 : 0; - const styles = {}; - - for (const [sourceSpace, suite] of Object.entries(colorConvert)) { - const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace; - if (sourceSpace === targetSpace) { - styles[name] = wrap(identity, offset); - } else if (typeof suite === 'object') { - styles[name] = wrap(suite[targetSpace], offset); - } - } - - return styles; -}; - -function assembleStyles() { - const codes = new Map(); - const styles = { - modifier: { - reset: [0, 0], - // 21 isn't widely supported and 22 does the same thing - bold: [1, 22], - dim: [2, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - hidden: [8, 28], - strikethrough: [9, 29] - }, - color: { - black: [30, 39], - red: [31, 39], - green: [32, 39], - yellow: [33, 39], - blue: [34, 39], - magenta: [35, 39], - cyan: [36, 39], - white: [37, 39], - - // Bright color - blackBright: [90, 39], - redBright: [91, 39], - greenBright: [92, 39], - yellowBright: [93, 39], - blueBright: [94, 39], - magentaBright: [95, 39], - cyanBright: [96, 39], - whiteBright: [97, 39] - }, - bgColor: { - bgBlack: [40, 49], - bgRed: [41, 49], - bgGreen: [42, 49], - bgYellow: [43, 49], - bgBlue: [44, 49], - bgMagenta: [45, 49], - bgCyan: [46, 49], - bgWhite: [47, 49], - - // Bright color - bgBlackBright: [100, 49], - bgRedBright: [101, 49], - bgGreenBright: [102, 49], - bgYellowBright: [103, 49], - bgBlueBright: [104, 49], - bgMagentaBright: [105, 49], - bgCyanBright: [106, 49], - bgWhiteBright: [107, 49] - } - }; - - // Alias bright black as gray (and grey) - styles.color.gray = styles.color.blackBright; - styles.bgColor.bgGray = styles.bgColor.bgBlackBright; - styles.color.grey = styles.color.blackBright; - styles.bgColor.bgGrey = styles.bgColor.bgBlackBright; - - for (const [groupName, group] of Object.entries(styles)) { - for (const [styleName, style] of Object.entries(group)) { - styles[styleName] = { - open: `\u001B[${style[0]}m`, - close: `\u001B[${style[1]}m` - }; - - group[styleName] = styles[styleName]; - - codes.set(style[0], style[1]); - } - - Object.defineProperty(styles, groupName, { - value: group, - enumerable: false - }); - } - - Object.defineProperty(styles, 'codes', { - value: codes, - enumerable: false - }); - - styles.color.close = '\u001B[39m'; - styles.bgColor.close = '\u001B[49m'; - - setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false)); - setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false)); - setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false)); - setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true)); - setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true)); - setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true)); - - return styles; -} - -// Make the export immutable -Object.defineProperty(module, 'exports', { - enumerable: true, - get: assembleStyles -}); diff --git a/deps/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/license b/deps/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/license deleted file mode 100644 index e7af2f77107d73..00000000000000 --- a/deps/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/license +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -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. diff --git a/deps/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/package.json b/deps/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/package.json deleted file mode 100644 index 75393284d7e474..00000000000000 --- a/deps/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/package.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "ansi-styles", - "version": "4.3.0", - "description": "ANSI escape codes for styling strings in the terminal", - "license": "MIT", - "repository": "chalk/ansi-styles", - "funding": "https://github.com/chalk/ansi-styles?sponsor=1", - "author": { - "name": "Sindre Sorhus", - "email": "sindresorhus@gmail.com", - "url": "sindresorhus.com" - }, - "engines": { - "node": ">=8" - }, - "scripts": { - "test": "xo && ava && tsd", - "screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor" - }, - "files": [ - "index.js", - "index.d.ts" - ], - "keywords": [ - "ansi", - "styles", - "color", - "colour", - "colors", - "terminal", - "console", - "cli", - "string", - "tty", - "escape", - "formatting", - "rgb", - "256", - "shell", - "xterm", - "log", - "logging", - "command-line", - "text" - ], - "dependencies": { - "color-convert": "^2.0.1" - }, - "devDependencies": { - "@types/color-convert": "^1.9.0", - "ava": "^2.3.0", - "svg-term-cli": "^2.1.1", - "tsd": "^0.11.0", - "xo": "^0.25.3" - } -} diff --git a/deps/npm/node_modules/@npmcli/disparity-colors/package.json b/deps/npm/node_modules/@npmcli/disparity-colors/package.json deleted file mode 100644 index 17eb4846c353c4..00000000000000 --- a/deps/npm/node_modules/@npmcli/disparity-colors/package.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "name": "@npmcli/disparity-colors", - "version": "3.0.0", - "main": "lib/index.js", - "files": [ - "bin/", - "lib/" - ], - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "description": "Colorizes unified diff output", - "repository": { - "type": "git", - "url": "https://github.com/npm/disparity-colors.git" - }, - "keywords": [ - "disparity", - "npm", - "npmcli", - "diff", - "char", - "unified", - "multiline", - "string", - "color", - "ansi", - "terminal", - "cli", - "tty" - ], - "author": "GitHub Inc.", - "contributors": [ - { - "name": "Ruy Adorno", - "url": "https://ruyadorno.com", - "twitter": "ruyadorno" - } - ], - "license": "ISC", - "scripts": { - "lint": "eslint \"**/*.js\"", - "pretest": "npm run lint", - "test": "tap", - "snap": "tap", - "postlint": "template-oss-check", - "template-oss-apply": "template-oss-apply --force", - "lintfix": "npm run lint -- --fix", - "posttest": "npm run lint" - }, - "tap": { - "check-coverage": true, - "nyc-arg": [ - "--exclude", - "tap-snapshots/**" - ] - }, - "devDependencies": { - "@npmcli/eslint-config": "^3.0.1", - "@npmcli/template-oss": "4.5.1", - "tap": "^16.0.1" - }, - "dependencies": { - "ansi-styles": "^4.3.0" - }, - "templateOSS": { - "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.5.1" - } -} diff --git a/deps/npm/node_modules/@npmcli/git/lib/is.js b/deps/npm/node_modules/@npmcli/git/lib/is.js index e2542f21577272..f5a0e8754f10dc 100644 --- a/deps/npm/node_modules/@npmcli/git/lib/is.js +++ b/deps/npm/node_modules/@npmcli/git/lib/is.js @@ -1,6 +1,4 @@ // not an airtight indicator, but a good gut-check to even bother trying -const { promisify } = require('util') -const fs = require('fs') -const stat = promisify(fs.stat) +const { stat } = require('fs/promises') module.exports = ({ cwd = process.cwd() } = {}) => stat(cwd + '/.git').then(() => true, () => false) diff --git a/deps/npm/node_modules/@npmcli/git/lib/spawn.js b/deps/npm/node_modules/@npmcli/git/lib/spawn.js index 5e96eb5542b5a6..03c1cbde215477 100644 --- a/deps/npm/node_modules/@npmcli/git/lib/spawn.js +++ b/deps/npm/node_modules/@npmcli/git/lib/spawn.js @@ -1,6 +1,6 @@ const spawn = require('@npmcli/promise-spawn') const promiseRetry = require('promise-retry') -const log = require('proc-log') +const { log } = require('proc-log') const makeError = require('./make-error.js') const makeOpts = require('./opts.js') diff --git a/deps/npm/node_modules/@npmcli/git/package.json b/deps/npm/node_modules/@npmcli/git/package.json index 485c1f43dddb90..f7117f13a9399c 100644 --- a/deps/npm/node_modules/@npmcli/git/package.json +++ b/deps/npm/node_modules/@npmcli/git/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/git", - "version": "5.0.4", + "version": "5.0.6", "main": "lib/index.js", "files": [ "bin/", @@ -40,7 +40,7 @@ "@npmcli/promise-spawn": "^7.0.0", "lru-cache": "^10.0.1", "npm-pick-manifest": "^9.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.0.0", "promise-inflight": "^1.0.1", "promise-retry": "^2.0.1", "semver": "^7.3.5", diff --git a/deps/npm/node_modules/@npmcli/installed-package-contents/bin/index.js b/deps/npm/node_modules/@npmcli/installed-package-contents/bin/index.js new file mode 100755 index 00000000000000..7b83b23bf168c0 --- /dev/null +++ b/deps/npm/node_modules/@npmcli/installed-package-contents/bin/index.js @@ -0,0 +1,44 @@ +#! /usr/bin/env node + +const { relative } = require('path') +const pkgContents = require('../') + +const usage = `Usage: + installed-package-contents [-d --depth=] + +Lists the files installed for a package specified by . + +Options: + -d --depth= Provide a numeric value ("Infinity" is allowed) + to specify how deep in the file tree to traverse. + Default=1 + -h --help Show this usage information` + +const options = {} + +process.argv.slice(2).forEach(arg => { + let match + if ((match = arg.match(/^(?:--depth=|-d)([0-9]+|Infinity)/))) { + options.depth = +match[1] + } else if (arg === '-h' || arg === '--help') { + console.log(usage) + process.exit(0) + } else { + options.path = arg + } +}) + +if (!options.path) { + console.error('ERROR: no path provided') + console.error(usage) + process.exit(1) +} + +const cwd = process.cwd() + +pkgContents(options) + .then(list => list.sort().forEach(p => console.log(relative(cwd, p)))) + .catch(/* istanbul ignore next - pretty unusual */ er => { + console.error(er) + process.exit(1) + }) diff --git a/deps/npm/node_modules/@npmcli/installed-package-contents/lib/index.js b/deps/npm/node_modules/@npmcli/installed-package-contents/lib/index.js old mode 100755 new mode 100644 index 20b25c4bc8437d..ab1486cd01d003 --- a/deps/npm/node_modules/@npmcli/installed-package-contents/lib/index.js +++ b/deps/npm/node_modules/@npmcli/installed-package-contents/lib/index.js @@ -1,5 +1,3 @@ -#! /usr/bin/env node - // to GET CONTENTS for folder at PATH (which may be a PACKAGE): // - if PACKAGE, read path/package.json // - if bins in ../node_modules/.bin, add those to result @@ -19,53 +17,46 @@ // - add GET CONTENTS of bundled deps, PACKAGE=true, depth + 1 const bundled = require('npm-bundled') -const { promisify } = require('util') -const fs = require('fs') -const readFile = promisify(fs.readFile) -const readdir = promisify(fs.readdir) -const stat = promisify(fs.stat) -const lstat = promisify(fs.lstat) -const { relative, resolve, basename, dirname } = require('path') +const { readFile, readdir, stat } = require('fs/promises') +const { resolve, basename, dirname } = require('path') const normalizePackageBin = require('npm-normalize-package-bin') -const readPackage = ({ path, packageJsonCache }) => - packageJsonCache.has(path) ? Promise.resolve(packageJsonCache.get(path)) +const readPackage = ({ path, packageJsonCache }) => packageJsonCache.has(path) + ? Promise.resolve(packageJsonCache.get(path)) : readFile(path).then(json => { const pkg = normalizePackageBin(JSON.parse(json)) packageJsonCache.set(path, pkg) return pkg - }) - .catch(er => null) + }).catch(() => null) // just normalize bundle deps and bin, that's all we care about here. const normalized = Symbol('package data has been normalized') -const rpj = ({ path, packageJsonCache }) => - readPackage({ path, packageJsonCache }) - .then(pkg => { - if (!pkg || pkg[normalized]) { - return pkg - } - if (pkg.bundledDependencies && !pkg.bundleDependencies) { - pkg.bundleDependencies = pkg.bundledDependencies - delete pkg.bundledDependencies - } - const bd = pkg.bundleDependencies - if (bd === true) { - pkg.bundleDependencies = [ - ...Object.keys(pkg.dependencies || {}), - ...Object.keys(pkg.optionalDependencies || {}), - ] - } - if (typeof bd === 'object' && !Array.isArray(bd)) { - pkg.bundleDependencies = Object.keys(bd) - } - pkg[normalized] = true +const rpj = ({ path, packageJsonCache }) => readPackage({ path, packageJsonCache }) + .then(pkg => { + if (!pkg || pkg[normalized]) { return pkg - }) + } + if (pkg.bundledDependencies && !pkg.bundleDependencies) { + pkg.bundleDependencies = pkg.bundledDependencies + delete pkg.bundledDependencies + } + const bd = pkg.bundleDependencies + if (bd === true) { + pkg.bundleDependencies = [ + ...Object.keys(pkg.dependencies || {}), + ...Object.keys(pkg.optionalDependencies || {}), + ] + } + if (typeof bd === 'object' && !Array.isArray(bd)) { + pkg.bundleDependencies = Object.keys(bd) + } + pkg[normalized] = true + return pkg + }) const pkgContents = async ({ path, - depth, + depth = 1, currentDepth = 0, pkg = null, result = null, @@ -105,7 +96,7 @@ const pkgContents = async ({ }) const bins = await Promise.all( - binFiles.map(b => stat(b).then(() => b).catch((er) => null)) + binFiles.map(b => stat(b).then(() => b).catch(() => null)) ) bins.filter(b => b).forEach(b => result.add(b)) } @@ -136,18 +127,6 @@ const pkgContents = async ({ const recursePromises = [] - // if we didn't get withFileTypes support, tack that on - if (typeof dirEntries[0] === 'string') { - // use a map so we can return a promise, but we mutate dirEntries in place - // this is much slower than getting the entries from the readdir call, - // but polyfills support for node versions before 10.10 - await Promise.all(dirEntries.map(async (name, index) => { - const p = resolve(path, name) - const st = await lstat(p) - dirEntries[index] = Object.assign(st, { name }) - })) - } - for (const entry of dirEntries) { const p = resolve(path, entry.name) if (entry.isDirectory() === false) { @@ -195,48 +174,8 @@ const pkgContents = async ({ return result } -module.exports = ({ path, depth = 1, packageJsonCache }) => pkgContents({ +module.exports = ({ path, ...opts }) => pkgContents({ path: resolve(path), - depth, + ...opts, pkg: true, - packageJsonCache, }).then(results => [...results]) - -if (require.main === module) { - const options = { path: null, depth: 1 } - const usage = `Usage: - installed-package-contents [-d --depth=] - -Lists the files installed for a package specified by . - -Options: - -d --depth= Provide a numeric value ("Infinity" is allowed) - to specify how deep in the file tree to traverse. - Default=1 - -h --help Show this usage information` - - process.argv.slice(2).forEach(arg => { - let match - if ((match = arg.match(/^--depth=([0-9]+|Infinity)/)) || - (match = arg.match(/^-d([0-9]+|Infinity)/))) { - options.depth = +match[1] - } else if (arg === '-h' || arg === '--help') { - console.log(usage) - process.exit(0) - } else { - options.path = arg - } - }) - if (!options.path) { - console.error('ERROR: no path provided') - console.error(usage) - process.exit(1) - } - const cwd = process.cwd() - module.exports(options) - .then(list => list.sort().forEach(p => console.log(relative(cwd, p)))) - .catch(/* istanbul ignore next - pretty unusual */ er => { - console.error(er) - process.exit(1) - }) -} diff --git a/deps/npm/node_modules/@npmcli/installed-package-contents/package.json b/deps/npm/node_modules/@npmcli/installed-package-contents/package.json index 3554754123e618..132256430a6c18 100644 --- a/deps/npm/node_modules/@npmcli/installed-package-contents/package.json +++ b/deps/npm/node_modules/@npmcli/installed-package-contents/package.json @@ -1,17 +1,17 @@ { "name": "@npmcli/installed-package-contents", - "version": "2.0.2", + "version": "2.1.0", "description": "Get the list of files installed in a package in node_modules, including bundled dependencies", "author": "GitHub Inc.", "main": "lib/index.js", "bin": { - "installed-package-contents": "lib/index.js" + "installed-package-contents": "bin/index.js" }, "license": "ISC", "scripts": { "test": "tap", "snap": "tap", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "postlint": "template-oss-check", "template-oss-apply": "template-oss-apply --force", "lintfix": "npm run lint -- --fix", @@ -19,8 +19,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.11.4", - "require-inject": "^1.4.4", + "@npmcli/template-oss": "4.21.4", "tap": "^16.3.0" }, "dependencies": { @@ -40,7 +39,8 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.11.4" + "version": "4.21.4", + "publish": true }, "tap": { "nyc-arg": [ diff --git a/deps/npm/node_modules/@npmcli/map-workspaces/lib/index.js b/deps/npm/node_modules/@npmcli/map-workspaces/lib/index.js index 501dad870a2b75..b20bf5de5d631e 100644 --- a/deps/npm/node_modules/@npmcli/map-workspaces/lib/index.js +++ b/deps/npm/node_modules/@npmcli/map-workspaces/lib/index.js @@ -5,23 +5,49 @@ const { minimatch } = require('minimatch') const rpj = require('read-package-json-fast') const { glob } = require('glob') -function appendNegatedPatterns (patterns) { - const results = [] - for (let pattern of patterns) { +function appendNegatedPatterns (allPatterns) { + const patterns = [] + const negatedPatterns = [] + for (let pattern of allPatterns) { const excl = pattern.match(/^!+/) if (excl) { pattern = pattern.slice(excl[0].length) } - // strip off any / from the start of the pattern. /foo => foo - pattern = pattern.replace(/^\/+/, '') + // strip off any / or ./ from the start of the pattern. /foo => foo + pattern = pattern.replace(/^\.?\/+/, '') // an odd number of ! means a negated pattern. !!foo ==> foo const negate = excl && excl[0].length % 2 === 1 - results.push({ pattern, negate }) + if (negate) { + negatedPatterns.push(pattern) + } else { + // remove negated patterns that appeared before this pattern to avoid + // ignoring paths that were matched afterwards + // e.g: ['packages/**', '!packages/b/**', 'packages/b/a'] + // in the above list, the last pattern overrides the negated pattern + // right before it. In effect, the above list would become: + // ['packages/**', 'packages/b/a'] + // The order matters here which is why we must do it inside the loop + // as opposed to doing it all together at the end. + for (let i = 0; i < negatedPatterns.length; ++i) { + const negatedPattern = negatedPatterns[i] + if (minimatch(pattern, negatedPattern)) { + negatedPatterns.splice(i, 1) + } + } + patterns.push(pattern) + } } - return results + // use the negated patterns to eagerly remove all the patterns that + // can be removed to avoid unnecessary crawling + for (const negated of negatedPatterns) { + for (const pattern of minimatch.match(patterns, negated)) { + patterns.splice(patterns.indexOf(pattern), 1) + } + } + return { patterns, negatedPatterns } } function getPatterns (workspaces) { @@ -77,11 +103,11 @@ async function mapWorkspaces (opts = {}) { } const { workspaces = [] } = opts.pkg - const patterns = getPatterns(workspaces) + const { patterns, negatedPatterns } = getPatterns(workspaces) const results = new Map() const seen = new Map() - if (!patterns.length) { + if (!patterns.length && !negatedPatterns.length) { return results } @@ -89,52 +115,54 @@ async function mapWorkspaces (opts = {}) { ...opts, ignore: [ ...opts.ignore || [], - ...['**/node_modules/**'], + '**/node_modules/**', + // just ignore the negated patterns to avoid unnecessary crawling + ...negatedPatterns, ], }) const getPackagePathname = pkgPathmame(opts) - for (const item of patterns) { - let matches = await glob(getGlobPattern(item.pattern), getGlobOpts()) - // preserves glob@8 behavior - matches = matches.sort((a, b) => a.localeCompare(b, 'en')) - - for (const match of matches) { - let pkg - const packageJsonPathname = getPackagePathname(match, 'package.json') - const packagePathname = path.dirname(packageJsonPathname) - - try { - pkg = await rpj(packageJsonPathname) - } catch (err) { - if (err.code === 'ENOENT') { - continue - } else { - throw err - } - } + let matches = await glob(patterns.map((p) => getGlobPattern(p)), getGlobOpts()) + // preserves glob@8 behavior + matches = matches.sort((a, b) => a.localeCompare(b, 'en')) + + // we must preserve the order of results according to the given list of + // workspace patterns + const orderedMatches = [] + for (const pattern of patterns) { + orderedMatches.push(...matches.filter((m) => { + return minimatch(m, pattern, { partial: true, windowsPathsNoEscape: true }) + })) + } - const name = getPackageName(pkg, packagePathname) + for (const match of orderedMatches) { + let pkg + const packageJsonPathname = getPackagePathname(match, 'package.json') - let seenPackagePathnames = seen.get(name) - if (!seenPackagePathnames) { - seenPackagePathnames = new Set() - seen.set(name, seenPackagePathnames) - } - if (item.negate) { - seenPackagePathnames.delete(packagePathname) + try { + pkg = await rpj(packageJsonPathname) + } catch (err) { + if (err.code === 'ENOENT') { + continue } else { - seenPackagePathnames.add(packagePathname) + throw err } } + + const packagePathname = path.dirname(packageJsonPathname) + const name = getPackageName(pkg, packagePathname) + + let seenPackagePathnames = seen.get(name) + if (!seenPackagePathnames) { + seenPackagePathnames = new Set() + seen.set(name, seenPackagePathnames) + } + seenPackagePathnames.add(packagePathname) } const errorMessageArray = ['must not have multiple workspaces with the same name'] for (const [packageName, seenPackagePathnames] of seen) { - if (seenPackagePathnames.size === 0) { - continue - } if (seenPackagePathnames.size > 1) { addDuplicateErrorMessages(errorMessageArray, packageName, seenPackagePathnames) } else { @@ -177,30 +205,25 @@ mapWorkspaces.virtual = function (opts = {}) { const { workspaces = [] } = packages[''] || {} // uses a pathname-keyed map in order to negate the exact items const results = new Map() - const patterns = getPatterns(workspaces) - if (!patterns.length) { + const { patterns, negatedPatterns } = getPatterns(workspaces) + if (!patterns.length && !negatedPatterns.length) { return results } - patterns.push({ pattern: '**/node_modules/**', negate: true }) - - const getPackagePathname = pkgPathmame(opts) + negatedPatterns.push('**/node_modules/**') - for (const packageKey of Object.keys(packages)) { - if (packageKey === '') { - continue + const packageKeys = Object.keys(packages) + for (const pattern of negatedPatterns) { + for (const packageKey of minimatch.match(packageKeys, pattern)) { + packageKeys.splice(packageKeys.indexOf(packageKey), 1) } + } - for (const item of patterns) { - if (minimatch(packageKey, item.pattern)) { - const packagePathname = getPackagePathname(packageKey) - const name = getPackageName(packages[packageKey], packagePathname) - - if (item.negate) { - results.delete(packagePathname) - } else { - results.set(packagePathname, name) - } - } + const getPackagePathname = pkgPathmame(opts) + for (const pattern of patterns) { + for (const packageKey of minimatch.match(packageKeys, pattern)) { + const packagePathname = getPackagePathname(packageKey) + const name = getPackageName(packages[packageKey], packagePathname) + results.set(packagePathname, name) } } diff --git a/deps/npm/node_modules/@npmcli/map-workspaces/package.json b/deps/npm/node_modules/@npmcli/map-workspaces/package.json index 64cb7f9d3f1177..e6292b06bd2b43 100644 --- a/deps/npm/node_modules/@npmcli/map-workspaces/package.json +++ b/deps/npm/node_modules/@npmcli/map-workspaces/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/map-workspaces", - "version": "3.0.4", + "version": "3.0.6", "main": "lib/index.js", "files": [ "bin/", @@ -25,7 +25,7 @@ "author": "GitHub Inc.", "license": "ISC", "scripts": { - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "pretest": "npm run lint", "test": "tap", "snap": "tap", @@ -43,7 +43,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.14.1", + "@npmcli/template-oss": "4.21.3", "tap": "^16.0.1" }, "dependencies": { @@ -54,7 +54,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.14.1", + "version": "4.21.3", "publish": "true" } } diff --git a/deps/npm/node_modules/@npmcli/metavuln-calculator/lib/index.js b/deps/npm/node_modules/@npmcli/metavuln-calculator/lib/index.js index 668f55942c5065..2a4e08395e7edd 100644 --- a/deps/npm/node_modules/@npmcli/metavuln-calculator/lib/index.js +++ b/deps/npm/node_modules/@npmcli/metavuln-calculator/lib/index.js @@ -3,6 +3,7 @@ // class handles all the IO with the registry and cache. const pacote = require('pacote') const cacache = require('cacache') +const { time } = require('proc-log') const Advisory = require('./advisory.js') const { homedir } = require('os') const jsonParse = require('json-parse-even-better-errors') @@ -48,34 +49,33 @@ class Calculator { async [_calculate] (name, source) { const k = `security-advisory:${name}:${source.id}` - const t = `metavuln:calculate:${k}` - process.emit('time', t) + const timeEnd = time.start(`metavuln:calculate:${k}`) const advisory = new Advisory(name, source, this[_options]) // load packument and cached advisory const [cached, packument] = await Promise.all([ this[_cacheGet](advisory), this[_packument](name), ]) - process.emit('time', `metavuln:load:${k}`) + const timeEndLoad = time.start(`metavuln:load:${k}`) advisory.load(cached, packument) - process.emit('timeEnd', `metavuln:load:${k}`) + timeEndLoad() if (advisory.updated) { await this[_cachePut](advisory) } this[_advisories].set(k, advisory) - process.emit('timeEnd', t) + timeEnd() return advisory } async [_cachePut] (advisory) { const { name, id } = advisory const key = `security-advisory:${name}:${id}` - process.emit('time', `metavuln:cache:put:${key}`) + const timeEnd = time.start(`metavuln:cache:put:${key}`) const data = JSON.stringify(advisory) const options = { ...this[_options] } this[_cacheData].set(key, jsonParse(data)) await cacache.put(this[_cache], key, data, options).catch(() => {}) - process.emit('timeEnd', `metavuln:cache:put:${key}`) + timeEnd() } async [_cacheGet] (advisory) { @@ -87,12 +87,12 @@ class Calculator { return this[_cacheData].get(key) } - process.emit('time', `metavuln:cache:get:${key}`) + const timeEnd = time.start(`metavuln:cache:get:${key}`) const p = cacache.get(this[_cache], key, { ...this[_options] }) .catch(() => ({ data: '{}' })) .then(({ data }) => { data = jsonParse(data) - process.emit('timeEnd', `metavuln:cache:get:${key}`) + timeEnd() this[_cacheData].set(key, data) return data }) @@ -105,7 +105,7 @@ class Calculator { return this[_packuments].get(name) } - process.emit('time', `metavuln:packument:${name}`) + const timeEnd = time.start(`metavuln:packument:${name}`) const p = pacote.packument(name, { ...this[_options] }) .catch((er) => { // presumably not something from the registry. @@ -116,7 +116,7 @@ class Calculator { } }) .then(paku => { - process.emit('timeEnd', `metavuln:packument:${name}`) + timeEnd() this[_packuments].set(name, paku) return paku }) diff --git a/deps/npm/node_modules/@npmcli/metavuln-calculator/package.json b/deps/npm/node_modules/@npmcli/metavuln-calculator/package.json index 4d0af031d54148..74c23ad62bd7a5 100644 --- a/deps/npm/node_modules/@npmcli/metavuln-calculator/package.json +++ b/deps/npm/node_modules/@npmcli/metavuln-calculator/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/metavuln-calculator", - "version": "7.0.0", + "version": "7.1.0", "main": "lib/index.js", "files": [ "bin/", @@ -19,7 +19,7 @@ "snap": "tap", "postsnap": "npm run lint", "eslint": "eslint", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "lintfix": "npm run lint -- --fix", "postlint": "template-oss-check", "template-oss-apply": "template-oss-apply --force" @@ -34,14 +34,15 @@ }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.18.0", + "@npmcli/template-oss": "4.21.4", "require-inject": "^1.4.4", "tap": "^16.0.1" }, "dependencies": { "cacache": "^18.0.0", "json-parse-even-better-errors": "^3.0.0", - "pacote": "^17.0.0", + "pacote": "^18.0.0", + "proc-log": "^4.1.0", "semver": "^7.3.5" }, "engines": { @@ -49,7 +50,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.18.0", + "version": "4.21.4", "publish": "true", "ciVersions": [ "16.14.0", diff --git a/deps/npm/node_modules/@npmcli/package-json/lib/index.js b/deps/npm/node_modules/@npmcli/package-json/lib/index.js index 0cc41c685a39e7..6d1b760727ba60 100644 --- a/deps/npm/node_modules/@npmcli/package-json/lib/index.js +++ b/deps/npm/node_modules/@npmcli/package-json/lib/index.js @@ -167,6 +167,12 @@ class PackageJson { return this } + fromContent (data) { + this.#manifest = data + this.#canSave = false + return this + } + // Load data from a comment // /**package { "name": "foo", "version": "1.2.3", ... } **/ fromComment (data) { diff --git a/deps/npm/node_modules/@npmcli/package-json/lib/normalize.js b/deps/npm/node_modules/@npmcli/package-json/lib/normalize.js index 204d4d8a8e7dd6..e3b37984884279 100644 --- a/deps/npm/node_modules/@npmcli/package-json/lib/normalize.js +++ b/deps/npm/node_modules/@npmcli/package-json/lib/normalize.js @@ -1,12 +1,30 @@ -const semver = require('semver') +const valid = require('semver/functions/valid') +const clean = require('semver/functions/clean') const fs = require('fs/promises') -const { glob } = require('glob') -const legacyFixer = require('normalize-package-data/lib/fixer.js') -const legacyMakeWarning = require('normalize-package-data/lib/make_warning.js') const path = require('path') -const log = require('proc-log') -const git = require('@npmcli/git') -const hostedGitInfo = require('hosted-git-info') +const { log } = require('proc-log') + +/** + * @type {import('hosted-git-info')} + */ +let _hostedGitInfo +function lazyHostedGitInfo () { + if (!_hostedGitInfo) { + _hostedGitInfo = require('hosted-git-info') + } + return _hostedGitInfo +} + +/** + * @type {import('glob').glob} + */ +let _glob +function lazyLoadGlob () { + if (!_glob) { + _glob = require('glob').glob + } + return _glob +} // used to be npm-normalize-package-bin function normalizePackageBin (pkg, changes) { @@ -130,10 +148,10 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) if (!data.version) { data.version = '' } else { - if (!semver.valid(data.version, loose)) { + if (!valid(data.version, loose)) { throw new Error(`Invalid version: "${data.version}"`) } - const version = semver.clean(data.version, loose) + const version = clean(data.version, loose) if (version !== data.version) { changes?.push(`"version" was cleaned and set to "${version}"`) data.version = version @@ -208,7 +226,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // add "install" attribute if any "*.gyp" files exist if (steps.includes('gypfile')) { if (!scripts.install && !scripts.preinstall && data.gypfile !== false) { - const files = await glob('*.gyp', { cwd: pkg.path }) + const files = await lazyLoadGlob()('*.gyp', { cwd: pkg.path }) if (files.length) { scripts.install = 'node-gyp rebuild' data.scripts = scripts @@ -275,7 +293,11 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // populate "readme" attribute if (steps.includes('readme') && !data.readme) { const mdre = /\.m?a?r?k?d?o?w?n?$/i - const files = await glob('{README,README.*}', { cwd: pkg.path, nocase: true, mark: true }) + const files = await lazyLoadGlob()('{README,README.*}', { + cwd: pkg.path, + nocase: true, + mark: true, + }) let readmeFile for (const file of files) { // don't accept directories. @@ -306,7 +328,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) if (steps.includes('mans') && !data.man && data.directories?.man) { const manDir = data.directories.man const cwd = path.resolve(pkg.path, manDir) - const files = await glob('**/*.[0-9]', { cwd }) + const files = await lazyLoadGlob()('**/*.[0-9]', { cwd }) data.man = files.map(man => path.relative(pkg.path, path.join(cwd, man)).split(path.sep).join('/') ) @@ -319,7 +341,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // expand "directories.bin" if (steps.includes('binDir') && data.directories?.bin && !data.bin) { const binsDir = path.resolve(pkg.path, path.join('.', path.join('/', data.directories.bin))) - const bins = await glob('**', { cwd: binsDir }) + const bins = await lazyLoadGlob()('**', { cwd: binsDir }) data.bin = bins.reduce((acc, binFile) => { if (binFile && !binFile.startsWith('.')) { const binName = path.basename(binFile) @@ -333,6 +355,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // populate "gitHead" attribute if (steps.includes('gitHead') && !data.gitHead) { + const git = require('@npmcli/git') const gitRoot = await git.find({ cwd: pkg.path, root }) let head if (gitRoot) { @@ -446,7 +469,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) } } if (data.repository.url) { - const hosted = hostedGitInfo.fromUrl(data.repository.url) + const hosted = lazyHostedGitInfo().fromUrl(data.repository.url) let r if (hosted) { if (hosted.getDefaultRepresentation() === 'shortcut') { @@ -506,7 +529,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) changes?.push(`Removed invalid "${deps}.${d}"`) delete data[deps][d] } - const hosted = hostedGitInfo.fromUrl(data[deps][d])?.toString() + const hosted = lazyHostedGitInfo().fromUrl(data[deps][d])?.toString() if (hosted && hosted !== data[deps][d]) { changes?.push(`Normalized git reference to "${deps}.${d}"`) data[deps][d] = hosted.toString() @@ -518,6 +541,8 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) } if (steps.includes('normalizeData')) { + const legacyFixer = require('normalize-package-data/lib/fixer.js') + const legacyMakeWarning = require('normalize-package-data/lib/make_warning.js') legacyFixer.warn = function () { changes?.push(legacyMakeWarning.apply(null, arguments)) } diff --git a/deps/npm/node_modules/@npmcli/package-json/package.json b/deps/npm/node_modules/@npmcli/package-json/package.json index ab320e8695ca3d..98236f604ecbd7 100644 --- a/deps/npm/node_modules/@npmcli/package-json/package.json +++ b/deps/npm/node_modules/@npmcli/package-json/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/package-json", - "version": "5.0.0", + "version": "5.1.0", "description": "Programmatic API to update package.json", "main": "lib/index.js", "files": [ @@ -10,7 +10,7 @@ "scripts": { "snap": "tap", "test": "tap", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "lintfix": "npm run lint -- --fix", "posttest": "npm run lint", "postsnap": "npm run lintfix --", @@ -25,8 +25,8 @@ "license": "ISC", "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.18.0", - "read-package-json": "^6.0.4", + "@npmcli/template-oss": "4.21.4", + "read-package-json": "^7.0.0", "read-package-json-fast": "^3.0.2", "tap": "^16.0.1" }, @@ -36,7 +36,7 @@ "hosted-git-info": "^7.0.0", "json-parse-even-better-errors": "^3.0.0", "normalize-package-data": "^6.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.0.0", "semver": "^7.5.3" }, "repository": { @@ -48,14 +48,8 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.18.0", - "publish": "true", - "ciVersions": [ - "16.14.0", - "16.x", - "18.0.0", - "18.x" - ] + "version": "4.21.4", + "publish": "true" }, "tap": { "nyc-arg": [ diff --git a/deps/npm/node_modules/cli-table3/LICENSE b/deps/npm/node_modules/@npmcli/redact/LICENSE similarity index 94% rename from deps/npm/node_modules/cli-table3/LICENSE rename to deps/npm/node_modules/@npmcli/redact/LICENSE index a09b7de012ac85..c21644115c85d0 100644 --- a/deps/npm/node_modules/cli-table3/LICENSE +++ b/deps/npm/node_modules/@npmcli/redact/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2014 James Talmage +Copyright (c) 2024 npm Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/deps/npm/node_modules/@npmcli/redact/lib/deep-map.js b/deps/npm/node_modules/@npmcli/redact/lib/deep-map.js new file mode 100644 index 00000000000000..ad042dbdfc5341 --- /dev/null +++ b/deps/npm/node_modules/@npmcli/redact/lib/deep-map.js @@ -0,0 +1,59 @@ +const deepMap = (input, handler = v => v, path = ['$'], seen = new Set([input])) => { + if (Array.isArray(input)) { + const result = [] + for (let i = 0; i < input.length; i++) { + const element = input[i] + const elementPath = [...path, i] + if (element instanceof Object) { + if (!seen.has(element)) { // avoid getting stuck in circular reference + seen.add(element) + result.push(deepMap(handler(element, elementPath), handler, elementPath, seen)) + } + } else { + result.push(handler(element, elementPath)) + } + } + return result + } + + if (input === null) { + return null + } else if (typeof input === 'object' || typeof input === 'function') { + const result = {} + + if (input instanceof Error) { + // `name` property is not included in `Object.getOwnPropertyNames(error)` + result.errorType = input.name + } + + for (const propertyName of Object.getOwnPropertyNames(input)) { + // skip logging internal properties + if (propertyName.startsWith('_')) { + continue + } + + try { + const property = input[propertyName] + const propertyPath = [...path, propertyName] + if (property instanceof Object) { + if (!seen.has(property)) { // avoid getting stuck in circular reference + seen.add(property) + result[propertyName] = deepMap( + handler(property, propertyPath), handler, propertyPath, seen + ) + } + } else { + result[propertyName] = handler(property, propertyPath) + } + } catch (err) { + // a getter may throw an error + result[propertyName] = `[error getting value: ${err.message}]` + } + } + return result + } + + return handler(input, path) +} + +module.exports = { deepMap } diff --git a/deps/npm/node_modules/@npmcli/redact/lib/index.js b/deps/npm/node_modules/@npmcli/redact/lib/index.js new file mode 100644 index 00000000000000..9b10c7f6a0081d --- /dev/null +++ b/deps/npm/node_modules/@npmcli/redact/lib/index.js @@ -0,0 +1,44 @@ +const matchers = require('./matchers') +const { redactUrlPassword } = require('./utils') + +const REPLACE = '***' + +const redact = (value) => { + if (typeof value !== 'string' || !value) { + return value + } + return redactUrlPassword(value, REPLACE) + .replace(matchers.NPM_SECRET.pattern, `npm_${REPLACE}`) + .replace(matchers.UUID.pattern, REPLACE) +} + +// split on \s|= similar to how nopt parses options +const splitAndRedact = (str) => { + // stateful regex, don't move out of this scope + const splitChars = /[\s=]/g + + let match = null + let result = '' + let index = 0 + while (match = splitChars.exec(str)) { + result += redact(str.slice(index, match.index)) + match[0] + index = splitChars.lastIndex + } + + return result + redact(str.slice(index)) +} + +// replaces auth info in an array of arguments or in a strings +const redactLog = (arg) => { + if (typeof arg === 'string') { + return splitAndRedact(arg) + } else if (Array.isArray(arg)) { + return arg.map((a) => typeof a === 'string' ? splitAndRedact(a) : a) + } + return arg +} + +module.exports = { + redact, + redactLog, +} diff --git a/deps/npm/node_modules/@npmcli/redact/lib/matchers.js b/deps/npm/node_modules/@npmcli/redact/lib/matchers.js new file mode 100644 index 00000000000000..fe9b9071de8a16 --- /dev/null +++ b/deps/npm/node_modules/@npmcli/redact/lib/matchers.js @@ -0,0 +1,81 @@ +const TYPE_REGEX = 'regex' +const TYPE_URL = 'url' +const TYPE_PATH = 'path' + +const NPM_SECRET = { + type: TYPE_REGEX, + pattern: /\b(npms?_)[a-zA-Z0-9]{36,48}\b/gi, + replacement: `[REDACTED_NPM_SECRET]`, +} + +const AUTH_HEADER = { + type: TYPE_REGEX, + pattern: /\b(Basic\s+|Bearer\s+)[\w+=\-.]+\b/gi, + replacement: `[REDACTED_AUTH_HEADER]`, +} + +const JSON_WEB_TOKEN = { + type: TYPE_REGEX, + pattern: /\b[A-Za-z0-9-_]{10,}(?!\.\d+\.)\.[A-Za-z0-9-_]{3,}\.[A-Za-z0-9-_]{20,}\b/gi, + replacement: `[REDACTED_JSON_WEB_TOKEN]`, +} + +const UUID = { + type: TYPE_REGEX, + pattern: /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi, + replacement: `[REDACTED_UUID]`, +} + +const URL_MATCHER = { + type: TYPE_REGEX, + pattern: /(?:https?|ftp):\/\/[^\s/"$.?#].[^\s"]*/gi, + replacement: '[REDACTED_URL]', +} + +const DEEP_HEADER_AUTHORIZATION = { + type: TYPE_PATH, + predicate: ({ path }) => path.endsWith('.headers.authorization'), + replacement: '[REDACTED_HEADER_AUTHORIZATION]', +} + +const DEEP_HEADER_SET_COOKIE = { + type: TYPE_PATH, + predicate: ({ path }) => path.endsWith('.headers.set-cookie'), + replacement: '[REDACTED_HEADER_SET_COOKIE]', +} + +const REWRITE_REQUEST = { + type: TYPE_PATH, + predicate: ({ path }) => path.endsWith('.request'), + replacement: (input) => ({ + method: input?.method, + path: input?.path, + headers: input?.headers, + url: input?.url, + }), +} + +const REWRITE_RESPONSE = { + type: TYPE_PATH, + predicate: ({ path }) => path.endsWith('.response'), + replacement: (input) => ({ + data: input?.data, + status: input?.status, + headers: input?.headers, + }), +} + +module.exports = { + TYPE_REGEX, + TYPE_URL, + TYPE_PATH, + NPM_SECRET, + AUTH_HEADER, + JSON_WEB_TOKEN, + UUID, + URL_MATCHER, + DEEP_HEADER_AUTHORIZATION, + DEEP_HEADER_SET_COOKIE, + REWRITE_REQUEST, + REWRITE_RESPONSE, +} diff --git a/deps/npm/node_modules/@npmcli/redact/lib/server.js b/deps/npm/node_modules/@npmcli/redact/lib/server.js new file mode 100644 index 00000000000000..669e834da6131d --- /dev/null +++ b/deps/npm/node_modules/@npmcli/redact/lib/server.js @@ -0,0 +1,34 @@ +const { + AUTH_HEADER, + JSON_WEB_TOKEN, + NPM_SECRET, + DEEP_HEADER_AUTHORIZATION, + DEEP_HEADER_SET_COOKIE, + REWRITE_REQUEST, + REWRITE_RESPONSE, +} = require('./matchers') + +const { + redactUrlMatcher, + redactUrlPasswordMatcher, + redactMatchers, +} = require('./utils') + +const { deepMap } = require('./deep-map') + +const _redact = redactMatchers( + NPM_SECRET, + AUTH_HEADER, + JSON_WEB_TOKEN, + DEEP_HEADER_AUTHORIZATION, + DEEP_HEADER_SET_COOKIE, + REWRITE_REQUEST, + REWRITE_RESPONSE, + redactUrlMatcher( + redactUrlPasswordMatcher() + ) +) + +const redact = (input) => deepMap(input, (value, path) => _redact(value, { path })) + +module.exports = { redact } diff --git a/deps/npm/node_modules/@npmcli/redact/lib/utils.js b/deps/npm/node_modules/@npmcli/redact/lib/utils.js new file mode 100644 index 00000000000000..8395ab25fc373e --- /dev/null +++ b/deps/npm/node_modules/@npmcli/redact/lib/utils.js @@ -0,0 +1,202 @@ +const { + URL_MATCHER, + TYPE_URL, + TYPE_REGEX, + TYPE_PATH, +} = require('./matchers') + +/** + * creates a string of asterisks, + * this forces a minimum asterisk for security purposes + */ +const asterisk = (length = 0) => { + length = typeof length === 'string' ? length.length : length + if (length < 8) { + return '*'.repeat(8) + } + return '*'.repeat(length) +} + +/** + * escapes all special regex chars + * @see https://stackoverflow.com/a/9310752 + * @see https://github.com/tc39/proposal-regex-escaping + */ +const escapeRegExp = (text) => { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, `\\$&`) +} + +/** + * provieds a regex "or" of the url versions of a string + */ +const urlEncodeRegexGroup = (value) => { + const decoded = decodeURIComponent(value) + const encoded = encodeURIComponent(value) + const union = [...new Set([encoded, decoded, value])].map(escapeRegExp).join('|') + return union +} + +/** + * a tagged template literal that returns a regex ensures all variables are excaped + */ +const urlEncodeRegexTag = (strings, ...values) => { + let pattern = '' + for (let i = 0; i < values.length; i++) { + pattern += strings[i] + `(${urlEncodeRegexGroup(values[i])})` + } + pattern += strings[strings.length - 1] + return new RegExp(pattern) +} + +/** + * creates a matcher for redacting url hostname + */ +const redactUrlHostnameMatcher = ({ hostname, replacement } = {}) => ({ + type: TYPE_URL, + predicate: ({ url }) => url.hostname === hostname, + pattern: ({ url }) => { + return urlEncodeRegexTag`(^${url.protocol}//${url.username}:.+@)?${url.hostname}` + }, + replacement: `$1${replacement || asterisk()}`, +}) + +/** + * creates a matcher for redacting url search / query parameter values + */ +const redactUrlSearchParamsMatcher = ({ param, replacement } = {}) => ({ + type: TYPE_URL, + predicate: ({ url }) => url.searchParams.has(param), + pattern: ({ url }) => urlEncodeRegexTag`(${param}=)${url.searchParams.get(param)}`, + replacement: `$1${replacement || asterisk()}`, +}) + +/** creates a matcher for redacting the url password */ +const redactUrlPasswordMatcher = ({ replacement } = {}) => ({ + type: TYPE_URL, + predicate: ({ url }) => url.password, + pattern: ({ url }) => urlEncodeRegexTag`(^${url.protocol}//${url.username}:)${url.password}`, + replacement: `$1${replacement || asterisk()}`, +}) + +const redactUrlReplacement = (...matchers) => (subValue) => { + try { + const url = new URL(subValue) + return redactMatchers(...matchers)(subValue, { url }) + } catch (err) { + return subValue + } +} + +/** + * creates a matcher / submatcher for urls, this function allows you to first + * collect all urls within a larger string and then pass those urls to a + * submatcher + * + * @example + * console.log("this will first match all urls, then pass those urls to the password patcher") + * redactMatchers(redactUrlMatcher(redactUrlPasswordMatcher())) + * + * @example + * console.log( + * "this will assume you are passing in a string that is a url, and will redact the password" + * ) + * redactMatchers(redactUrlPasswordMatcher()) + * + */ +const redactUrlMatcher = (...matchers) => { + return { + ...URL_MATCHER, + replacement: redactUrlReplacement(...matchers), + } +} + +const matcherFunctions = { + [TYPE_REGEX]: (matcher) => (value) => { + if (typeof value === 'string') { + value = value.replace(matcher.pattern, matcher.replacement) + } + return value + }, + [TYPE_URL]: (matcher) => (value, ctx) => { + if (typeof value === 'string') { + try { + const url = ctx?.url || new URL(value) + const { predicate, pattern } = matcher + const predicateValue = predicate({ url }) + if (predicateValue) { + value = value.replace(pattern({ url }), matcher.replacement) + } + } catch (_e) { + return value + } + } + return value + }, + [TYPE_PATH]: (matcher) => (value, ctx) => { + const rawPath = ctx?.path + const path = rawPath.join('.').toLowerCase() + const { predicate, replacement } = matcher + const replace = typeof replacement === 'function' ? replacement : () => replacement + const shouldRun = predicate({ rawPath, path }) + if (shouldRun) { + value = replace(value, { rawPath, path }) + } + return value + }, +} + +/** converts a matcher to a function */ +const redactMatcher = (matcher) => { + return matcherFunctions[matcher.type](matcher) +} + +/** converts a series of matchers to a function */ +const redactMatchers = (...matchers) => (value, ctx) => { + const flatMatchers = matchers.flat() + return flatMatchers.reduce((result, matcher) => { + const fn = (typeof matcher === 'function') ? matcher : redactMatcher(matcher) + return fn(result, ctx) + }, value) +} + +/** + * replacement handler, keeping $1 (if it exists) and replacing the + * rest of the string with asterisks, maintaining string length + */ +const redactDynamicReplacement = () => (value, start) => { + if (typeof start === 'number') { + return asterisk(value) + } + return start + asterisk(value.substring(start.length).length) +} + +/** + * replacement handler, keeping $1 (if it exists) and replacing the + * rest of the string with a fixed number of asterisks + */ +const redactFixedReplacement = (length) => (_value, start) => { + if (typeof start === 'number') { + return asterisk(length) + } + return start + asterisk(length) +} + +const redactUrlPassword = (value, replacement) => { + return redactMatchers(redactUrlPasswordMatcher({ replacement }))(value) +} + +module.exports = { + asterisk, + escapeRegExp, + urlEncodeRegexGroup, + urlEncodeRegexTag, + redactUrlHostnameMatcher, + redactUrlSearchParamsMatcher, + redactUrlPasswordMatcher, + redactUrlMatcher, + redactUrlReplacement, + redactDynamicReplacement, + redactFixedReplacement, + redactMatchers, + redactUrlPassword, +} diff --git a/deps/npm/node_modules/@npmcli/redact/package.json b/deps/npm/node_modules/@npmcli/redact/package.json new file mode 100644 index 00000000000000..2bcee9ea0884b4 --- /dev/null +++ b/deps/npm/node_modules/@npmcli/redact/package.json @@ -0,0 +1,51 @@ +{ + "name": "@npmcli/redact", + "version": "2.0.0", + "description": "Redact sensitive npm information from output", + "main": "lib/index.js", + "exports": { + ".": "./lib/index.js", + "./server": "./lib/server.js", + "./package.json": "./package.json" + }, + "scripts": { + "test": "tap", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", + "postlint": "template-oss-check", + "template-oss-apply": "template-oss-apply --force", + "lintfix": "npm run lint -- --fix", + "snap": "tap", + "posttest": "npm run lint" + }, + "keywords": [], + "author": "GitHub Inc.", + "license": "ISC", + "files": [ + "bin/", + "lib/" + ], + "repository": { + "type": "git", + "url": "https://github.com/npm/redact.git" + }, + "templateOSS": { + "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", + "version": "4.21.3", + "publish": true + }, + "tap": { + "nyc-arg": [ + "--exclude", + "tap-snapshots/**" + ], + "timeout": 120 + }, + "devDependencies": { + "@npmcli/eslint-config": "^4.0.2", + "@npmcli/template-oss": "4.21.3", + "tap": "^16.3.10" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } +} diff --git a/deps/npm/node_modules/@npmcli/run-script/lib/run-script-pkg.js b/deps/npm/node_modules/@npmcli/run-script/lib/run-script-pkg.js index ea33db56298586..9900c96315f85f 100644 --- a/deps/npm/node_modules/@npmcli/run-script/lib/run-script-pkg.js +++ b/deps/npm/node_modules/@npmcli/run-script/lib/run-script-pkg.js @@ -5,19 +5,6 @@ const { isNodeGypPackage, defaultGypInstallScript } = require('@npmcli/node-gyp' const signalManager = require('./signal-manager.js') const isServerPackage = require('./is-server-package.js') -// you wouldn't like me when I'm angry... -const bruce = (id, event, cmd, args) => { - let banner = id - ? `\n> ${id} ${event}\n` - : `\n> ${event}\n` - banner += `> ${cmd.trim().replace(/\n/g, '\n> ')}` - if (args.length) { - banner += ` ${args.join(' ')}` - } - banner += '\n' - return banner -} - const runScriptPkg = async options => { const { event, @@ -29,8 +16,6 @@ const runScriptPkg = async options => { pkg, args = [], stdioString, - // note: only used when stdio:inherit - banner = true, // how long to wait for a process.kill signal // only exposed here so that we can make the test go a bit faster. signalTimeout = 500, @@ -59,9 +44,22 @@ const runScriptPkg = async options => { return { code: 0, signal: null } } - if (stdio === 'inherit' && banner !== false) { - // we're dumping to the parent's stdout, so print the banner - console.log(bruce(pkg._id, event, cmd, args)) + let inputEnd = () => {} + if (stdio === 'inherit') { + let banner + if (pkg._id) { + banner = `\n> ${pkg._id} ${event}\n` + } else { + banner = `\n> ${event}\n` + } + banner += `> ${cmd.trim().replace(/\n/g, '\n> ')}` + if (args.length) { + banner += ` ${args.join(' ')}` + } + banner += '\n' + const { output, input } = require('proc-log') + output.standard(banner) + inputEnd = input.start() } const [spawnShell, spawnArgs, spawnOpts] = makeSpawnArgs({ @@ -108,7 +106,7 @@ const runScriptPkg = async options => { } else { throw er } - }) + }).finally(inputEnd) } module.exports = runScriptPkg diff --git a/deps/npm/node_modules/@npmcli/run-script/package.json b/deps/npm/node_modules/@npmcli/run-script/package.json index 1c98b1b170e265..8a83e726fbeb2c 100644 --- a/deps/npm/node_modules/@npmcli/run-script/package.json +++ b/deps/npm/node_modules/@npmcli/run-script/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/run-script", - "version": "7.0.4", + "version": "8.1.0", "description": "Run a lifecycle script for a package (descendant of npm-lifecycle)", "author": "GitHub Inc.", "license": "ISC", @@ -16,7 +16,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.21.3", + "@npmcli/template-oss": "4.21.4", "spawk": "^1.8.1", "tap": "^16.0.1" }, @@ -25,6 +25,7 @@ "@npmcli/package-json": "^5.0.0", "@npmcli/promise-spawn": "^7.0.0", "node-gyp": "^10.0.0", + "proc-log": "^4.0.0", "which": "^4.0.0" }, "files": [ @@ -41,7 +42,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.21.3", + "version": "4.21.4", "publish": "true" }, "tap": { diff --git a/deps/npm/node_modules/@sigstore/bundle/dist/build.js b/deps/npm/node_modules/@sigstore/bundle/dist/build.js index 6990f5451a2d33..65c71b100ad58f 100644 --- a/deps/npm/node_modules/@sigstore/bundle/dist/build.js +++ b/deps/npm/node_modules/@sigstore/bundle/dist/build.js @@ -21,7 +21,9 @@ const bundle_1 = require("./bundle"); // Message signature bundle - $case: 'messageSignature' function toMessageSignatureBundle(options) { return { - mediaType: bundle_1.BUNDLE_V02_MEDIA_TYPE, + mediaType: options.singleCertificate + ? bundle_1.BUNDLE_V03_MEDIA_TYPE + : bundle_1.BUNDLE_V02_MEDIA_TYPE, content: { $case: 'messageSignature', messageSignature: { @@ -39,7 +41,9 @@ exports.toMessageSignatureBundle = toMessageSignatureBundle; // DSSE envelope bundle - $case: 'dsseEnvelope' function toDSSEBundle(options) { return { - mediaType: bundle_1.BUNDLE_V02_MEDIA_TYPE, + mediaType: options.singleCertificate + ? bundle_1.BUNDLE_V03_MEDIA_TYPE + : bundle_1.BUNDLE_V02_MEDIA_TYPE, content: { $case: 'dsseEnvelope', dsseEnvelope: toEnvelope(options), @@ -71,12 +75,20 @@ function toVerificationMaterial(options) { } function toKeyContent(options) { if (options.certificate) { - return { - $case: 'x509CertificateChain', - x509CertificateChain: { - certificates: [{ rawBytes: options.certificate }], - }, - }; + if (options.singleCertificate) { + return { + $case: 'certificate', + certificate: { rawBytes: options.certificate }, + }; + } + else { + return { + $case: 'x509CertificateChain', + x509CertificateChain: { + certificates: [{ rawBytes: options.certificate }], + }, + }; + } } else { return { diff --git a/deps/npm/node_modules/@sigstore/bundle/dist/bundle.js b/deps/npm/node_modules/@sigstore/bundle/dist/bundle.js index 60574b309c09cb..dbd35df2ca2bb3 100644 --- a/deps/npm/node_modules/@sigstore/bundle/dist/bundle.js +++ b/deps/npm/node_modules/@sigstore/bundle/dist/bundle.js @@ -1,9 +1,10 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.isBundleWithDsseEnvelope = exports.isBundleWithMessageSignature = exports.isBundleWithPublicKey = exports.isBundleWithCertificateChain = exports.BUNDLE_V03_MEDIA_TYPE = exports.BUNDLE_V02_MEDIA_TYPE = exports.BUNDLE_V01_MEDIA_TYPE = void 0; +exports.isBundleWithDsseEnvelope = exports.isBundleWithMessageSignature = exports.isBundleWithPublicKey = exports.isBundleWithCertificateChain = exports.BUNDLE_V03_MEDIA_TYPE = exports.BUNDLE_V03_LEGACY_MEDIA_TYPE = exports.BUNDLE_V02_MEDIA_TYPE = exports.BUNDLE_V01_MEDIA_TYPE = void 0; exports.BUNDLE_V01_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.1'; exports.BUNDLE_V02_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.2'; -exports.BUNDLE_V03_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.3'; +exports.BUNDLE_V03_LEGACY_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.3'; +exports.BUNDLE_V03_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle.v0.3+json'; // Type guards for bundle variants. function isBundleWithCertificateChain(b) { return b.verificationMaterial.content.$case === 'x509CertificateChain'; diff --git a/deps/npm/node_modules/@sigstore/bundle/dist/index.js b/deps/npm/node_modules/@sigstore/bundle/dist/index.js index f2b50994e9b1f5..1b012acad4d85b 100644 --- a/deps/npm/node_modules/@sigstore/bundle/dist/index.js +++ b/deps/npm/node_modules/@sigstore/bundle/dist/index.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.isBundleV01 = exports.assertBundleV02 = exports.assertBundleV01 = exports.assertBundleLatest = exports.assertBundle = exports.envelopeToJSON = exports.envelopeFromJSON = exports.bundleToJSON = exports.bundleFromJSON = exports.ValidationError = exports.isBundleWithPublicKey = exports.isBundleWithMessageSignature = exports.isBundleWithDsseEnvelope = exports.isBundleWithCertificateChain = exports.BUNDLE_V03_MEDIA_TYPE = exports.BUNDLE_V02_MEDIA_TYPE = exports.BUNDLE_V01_MEDIA_TYPE = exports.toMessageSignatureBundle = exports.toDSSEBundle = void 0; +exports.isBundleV01 = exports.assertBundleV02 = exports.assertBundleV01 = exports.assertBundleLatest = exports.assertBundle = exports.envelopeToJSON = exports.envelopeFromJSON = exports.bundleToJSON = exports.bundleFromJSON = exports.ValidationError = exports.isBundleWithPublicKey = exports.isBundleWithMessageSignature = exports.isBundleWithDsseEnvelope = exports.isBundleWithCertificateChain = exports.BUNDLE_V03_MEDIA_TYPE = exports.BUNDLE_V03_LEGACY_MEDIA_TYPE = exports.BUNDLE_V02_MEDIA_TYPE = exports.BUNDLE_V01_MEDIA_TYPE = exports.toMessageSignatureBundle = exports.toDSSEBundle = void 0; /* Copyright 2023 The Sigstore Authors. @@ -22,6 +22,7 @@ Object.defineProperty(exports, "toMessageSignatureBundle", { enumerable: true, g var bundle_1 = require("./bundle"); Object.defineProperty(exports, "BUNDLE_V01_MEDIA_TYPE", { enumerable: true, get: function () { return bundle_1.BUNDLE_V01_MEDIA_TYPE; } }); Object.defineProperty(exports, "BUNDLE_V02_MEDIA_TYPE", { enumerable: true, get: function () { return bundle_1.BUNDLE_V02_MEDIA_TYPE; } }); +Object.defineProperty(exports, "BUNDLE_V03_LEGACY_MEDIA_TYPE", { enumerable: true, get: function () { return bundle_1.BUNDLE_V03_LEGACY_MEDIA_TYPE; } }); Object.defineProperty(exports, "BUNDLE_V03_MEDIA_TYPE", { enumerable: true, get: function () { return bundle_1.BUNDLE_V03_MEDIA_TYPE; } }); Object.defineProperty(exports, "isBundleWithCertificateChain", { enumerable: true, get: function () { return bundle_1.isBundleWithCertificateChain; } }); Object.defineProperty(exports, "isBundleWithDsseEnvelope", { enumerable: true, get: function () { return bundle_1.isBundleWithDsseEnvelope; } }); diff --git a/deps/npm/node_modules/@sigstore/bundle/dist/validate.js b/deps/npm/node_modules/@sigstore/bundle/dist/validate.js index 6a59ecc230f4ac..67079cd1f680a9 100644 --- a/deps/npm/node_modules/@sigstore/bundle/dist/validate.js +++ b/deps/npm/node_modules/@sigstore/bundle/dist/validate.js @@ -74,7 +74,8 @@ function validateBundleBase(b) { const invalidValues = []; // Media type validation if (b.mediaType === undefined || - !b.mediaType.startsWith('application/vnd.dev.sigstore.bundle+json;version=')) { + (!b.mediaType.match(/^application\/vnd\.dev\.sigstore\.bundle\+json;version=\d\.\d/) && + !b.mediaType.match(/^application\/vnd\.dev\.sigstore\.bundle\.v\d\.\d\+json/))) { invalidValues.push('mediaType'); } // Content-related validation diff --git a/deps/npm/node_modules/@sigstore/bundle/package.json b/deps/npm/node_modules/@sigstore/bundle/package.json index 2cac185f73895b..ab96ba7e8b2ca6 100644 --- a/deps/npm/node_modules/@sigstore/bundle/package.json +++ b/deps/npm/node_modules/@sigstore/bundle/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/bundle", - "version": "2.2.0", + "version": "2.3.1", "description": "Sigstore bundle type", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -27,7 +27,7 @@ "provenance": true }, "dependencies": { - "@sigstore/protobuf-specs": "^0.3.0" + "@sigstore/protobuf-specs": "^0.3.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" diff --git a/deps/npm/node_modules/@sigstore/core/dist/crypto.js b/deps/npm/node_modules/@sigstore/core/dist/crypto.js index c5d899d003e1d4..dbe65b165d3574 100644 --- a/deps/npm/node_modules/@sigstore/core/dist/crypto.js +++ b/deps/npm/node_modules/@sigstore/core/dist/crypto.js @@ -21,12 +21,12 @@ limitations under the License. */ const crypto_1 = __importDefault(require("crypto")); const SHA256_ALGORITHM = 'sha256'; -function createPublicKey(key) { +function createPublicKey(key, type = 'spki') { if (typeof key === 'string') { return crypto_1.default.createPublicKey(key); } else { - return crypto_1.default.createPublicKey({ key, format: 'der', type: 'spki' }); + return crypto_1.default.createPublicKey({ key, format: 'der', type: type }); } } exports.createPublicKey = createPublicKey; diff --git a/deps/npm/node_modules/@sigstore/core/package.json b/deps/npm/node_modules/@sigstore/core/package.json index b9f901652ef0fd..621ff1715bcd1c 100644 --- a/deps/npm/node_modules/@sigstore/core/package.json +++ b/deps/npm/node_modules/@sigstore/core/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/core", - "version": "1.0.0", + "version": "1.1.0", "description": "Base library for Sigstore", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/deps/npm/node_modules/@sigstore/protobuf-specs/dist/__generated__/sigstore_trustroot.js b/deps/npm/node_modules/@sigstore/protobuf-specs/dist/__generated__/sigstore_trustroot.js index 05e566767cdb24..9984f7879c73f1 100644 --- a/deps/npm/node_modules/@sigstore/protobuf-specs/dist/__generated__/sigstore_trustroot.js +++ b/deps/npm/node_modules/@sigstore/protobuf-specs/dist/__generated__/sigstore_trustroot.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.TrustedRoot = exports.CertificateAuthority = exports.TransparencyLogInstance = void 0; +exports.ClientTrustConfig = exports.SigningConfig = exports.TrustedRoot = exports.CertificateAuthority = exports.TransparencyLogInstance = void 0; /* eslint-disable */ const sigstore_common_1 = require("./sigstore_common"); function createBaseTransparencyLogInstance() { @@ -98,6 +98,58 @@ exports.TrustedRoot = { return obj; }, }; +function createBaseSigningConfig() { + return { caUrl: "", oidcUrl: "", tlogUrls: [], tsaUrls: [] }; +} +exports.SigningConfig = { + fromJSON(object) { + return { + caUrl: isSet(object.caUrl) ? String(object.caUrl) : "", + oidcUrl: isSet(object.oidcUrl) ? String(object.oidcUrl) : "", + tlogUrls: Array.isArray(object?.tlogUrls) ? object.tlogUrls.map((e) => String(e)) : [], + tsaUrls: Array.isArray(object?.tsaUrls) ? object.tsaUrls.map((e) => String(e)) : [], + }; + }, + toJSON(message) { + const obj = {}; + message.caUrl !== undefined && (obj.caUrl = message.caUrl); + message.oidcUrl !== undefined && (obj.oidcUrl = message.oidcUrl); + if (message.tlogUrls) { + obj.tlogUrls = message.tlogUrls.map((e) => e); + } + else { + obj.tlogUrls = []; + } + if (message.tsaUrls) { + obj.tsaUrls = message.tsaUrls.map((e) => e); + } + else { + obj.tsaUrls = []; + } + return obj; + }, +}; +function createBaseClientTrustConfig() { + return { mediaType: "", trustedRoot: undefined, signingConfig: undefined }; +} +exports.ClientTrustConfig = { + fromJSON(object) { + return { + mediaType: isSet(object.mediaType) ? String(object.mediaType) : "", + trustedRoot: isSet(object.trustedRoot) ? exports.TrustedRoot.fromJSON(object.trustedRoot) : undefined, + signingConfig: isSet(object.signingConfig) ? exports.SigningConfig.fromJSON(object.signingConfig) : undefined, + }; + }, + toJSON(message) { + const obj = {}; + message.mediaType !== undefined && (obj.mediaType = message.mediaType); + message.trustedRoot !== undefined && + (obj.trustedRoot = message.trustedRoot ? exports.TrustedRoot.toJSON(message.trustedRoot) : undefined); + message.signingConfig !== undefined && + (obj.signingConfig = message.signingConfig ? exports.SigningConfig.toJSON(message.signingConfig) : undefined); + return obj; + }, +}; function isSet(value) { return value !== null && value !== undefined; } diff --git a/deps/npm/node_modules/@sigstore/protobuf-specs/package.json b/deps/npm/node_modules/@sigstore/protobuf-specs/package.json index 047a67a7a2e208..4fefe51c761fd8 100644 --- a/deps/npm/node_modules/@sigstore/protobuf-specs/package.json +++ b/deps/npm/node_modules/@sigstore/protobuf-specs/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/protobuf-specs", - "version": "0.3.0", + "version": "0.3.1", "description": "code-signing for npm packages", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -21,11 +21,11 @@ }, "homepage": "https://github.com/sigstore/protobuf-specs#readme", "devDependencies": { - "@tsconfig/node14": "^1.0.3", + "@tsconfig/node16": "^16.1.1", "@types/node": "^18.14.0", "typescript": "^4.9.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } } diff --git a/deps/npm/node_modules/@sigstore/sign/dist/bundler/bundle.js b/deps/npm/node_modules/@sigstore/sign/dist/bundler/bundle.js index f01aac252b304a..7c2ca9164f0dfe 100644 --- a/deps/npm/node_modules/@sigstore/sign/dist/bundler/bundle.js +++ b/deps/npm/node_modules/@sigstore/sign/dist/bundler/bundle.js @@ -56,7 +56,7 @@ function toMessageSignatureBundle(artifact, signature) { } exports.toMessageSignatureBundle = toMessageSignatureBundle; // DSSE envelope bundle - $case: 'dsseEnvelope' -function toDSSEBundle(artifact, signature) { +function toDSSEBundle(artifact, signature, singleCertificate) { return sigstore.toDSSEBundle({ artifact: artifact.data, artifactType: artifact.type, @@ -65,6 +65,7 @@ function toDSSEBundle(artifact, signature) { ? util_1.pem.toDER(signature.key.certificate) : undefined, keyHint: signature.key.$case === 'publicKey' ? signature.key.hint : undefined, + singleCertificate, }); } exports.toDSSEBundle = toDSSEBundle; diff --git a/deps/npm/node_modules/@sigstore/sign/dist/bundler/dsse.js b/deps/npm/node_modules/@sigstore/sign/dist/bundler/dsse.js index 486d289aea38cb..621700df93842a 100644 --- a/deps/npm/node_modules/@sigstore/sign/dist/bundler/dsse.js +++ b/deps/npm/node_modules/@sigstore/sign/dist/bundler/dsse.js @@ -23,6 +23,7 @@ const bundle_1 = require("./bundle"); class DSSEBundleBuilder extends base_1.BaseBundleBuilder { constructor(options) { super(options); + this.singleCertificate = options.singleCertificate ?? false; } // DSSE requires the artifact to be pre-encoded with the payload type // before the signature is generated. @@ -32,7 +33,7 @@ class DSSEBundleBuilder extends base_1.BaseBundleBuilder { } // Packages the artifact and signature into a DSSE bundle async package(artifact, signature) { - return (0, bundle_1.toDSSEBundle)(artifactDefaults(artifact), signature); + return (0, bundle_1.toDSSEBundle)(artifactDefaults(artifact), signature, this.singleCertificate); } } exports.DSSEBundleBuilder = DSSEBundleBuilder; diff --git a/deps/npm/node_modules/@sigstore/sign/package.json b/deps/npm/node_modules/@sigstore/sign/package.json index 4302f6e07a2a82..09eea0a39e8771 100644 --- a/deps/npm/node_modules/@sigstore/sign/package.json +++ b/deps/npm/node_modules/@sigstore/sign/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/sign", - "version": "2.2.3", + "version": "2.3.0", "description": "Sigstore signing library", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -27,14 +27,14 @@ }, "devDependencies": { "@sigstore/jest": "^0.0.0", - "@sigstore/mock": "^0.6.5", + "@sigstore/mock": "^0.7.0", "@sigstore/rekor-types": "^2.0.0", "@types/make-fetch-happen": "^10.0.4" }, "dependencies": { - "@sigstore/bundle": "^2.2.0", + "@sigstore/bundle": "^2.3.0", "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.0", + "@sigstore/protobuf-specs": "^0.3.1", "make-fetch-happen": "^13.0.0" }, "engines": { diff --git a/deps/npm/node_modules/@sigstore/tuf/package.json b/deps/npm/node_modules/@sigstore/tuf/package.json index 0e5fab2a2762d8..fc842df1814700 100644 --- a/deps/npm/node_modules/@sigstore/tuf/package.json +++ b/deps/npm/node_modules/@sigstore/tuf/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/tuf", - "version": "2.3.1", + "version": "2.3.2", "description": "Client for the Sigstore TUF repository", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/deps/npm/node_modules/@sigstore/tuf/seeds.json b/deps/npm/node_modules/@sigstore/tuf/seeds.json index a0051cea67b7b5..e8d97d5fa7a672 100644 --- a/deps/npm/node_modules/@sigstore/tuf/seeds.json +++ b/deps/npm/node_modules/@sigstore/tuf/seeds.json @@ -1 +1 @@ -{"https://tuf-repo-cdn.sigstore.dev":{"root.json":"ewoJInNpZ25lZCI6IHsKCQkiX3R5cGUiOiAicm9vdCIsCgkJInNwZWNfdmVyc2lvbiI6ICIxLjAiLAoJCSJ2ZXJzaW9uIjogOCwKCQkiZXhwaXJlcyI6ICIyMDI0LTAzLTI2VDA0OjM4OjU1WiIsCgkJImtleXMiOiB7CgkJCSIyNWEwZWI0NTBmZDNlZTJiZDc5MjE4Yzk2M2RjZTNmMWNjNjExOGJhZGYyNTFiZjE0OWYwYmQwN2Q1Y2FiZTk5IjogewoJCQkJImtleXR5cGUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCgkJCQkic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAoJCQkJImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKCQkJCQkic2hhMjU2IiwKCQkJCQkic2hhNTEyIgoJCQkJXSwKCQkJCSJrZXl2YWwiOiB7CgkJCQkJInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFRVhzejNTWlhGYjhqTVY0Mmo2cEpseWpialI4S1xuTjNCd29jZXhxNkxNSWI1cXNXS09RdkxOMTZOVWVmTGM0SHN3T291bVJzVlZhYWpTcFFTNmZvYmtSdz09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKCQkJCX0KCQkJfSwKCQkJIjJlNjFjZDBjYmY0YThmNDU4MDliZGE5ZjdmNzhjMGQzM2FkMTE4NDJmZjk0YWUzNDA4NzNlMjY2NGRjODQzZGUiOiB7CgkJCQkia2V5dHlwZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCgkJCQkia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwoJCQkJCSJzaGEyNTYiLAoJCQkJCSJzaGE1MTIiCgkJCQldLAoJCQkJImtleXZhbCI6IHsKCQkJCQkicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUwZ2hyaDkyTHcxWXIzaWRHVjVXcUN0TURCOEN4XG4rRDhoZEM0dzJaTE5JcGxWUm9WR0xza1lhM2doZU15T2ppSjhrUGkxNWFRMi8vN1Arb2o3VXZKUEd3PT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgoJCQkJfQoJCQl9LAoJCQkiNDViMjgzODI1ZWIxODRjYWJkNTgyZWIxN2I3NGZjOGVkNDA0ZjY4Y2Y0NTJhY2FiZGFkMmVkNmY5MGNlMjE2YiI6IHsKCQkJCSJrZXl0eXBlIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAoJCQkJInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCgkJCQkJInNoYTI1NiIsCgkJCQkJInNoYTUxMiIKCQkJCV0sCgkJCQkia2V5dmFsIjogewoJCQkJCSJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUxyV3ZOdDk0djRSMDg1RUxlZUNNeEhwN1BsZEZcbjAvVDFHeHVrVWgyT0R1Z2dMR0pFMHBjMWU4Q1NCZjZDUzkxRndvOUZVT3VSc2pCVWxkK1ZxU3lDZFE9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCgkJCQl9CgkJCX0sCgkJCSI3Zjc1MTNiMjU0MjlhNjQ0NzNlMTBjZTNhZDJmM2RhMzcyYmJkZDE0YjY1ZDA3YmJhZjU0N2U3YzhiYmJlNjJiIjogewoJCQkJImtleXR5cGUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCgkJCQkic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAoJCQkJImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKCQkJCQkic2hhMjU2IiwKCQkJCQkic2hhNTEyIgoJCQkJXSwKCQkJCSJrZXl2YWwiOiB7CgkJCQkJInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFaW5pa1NzQVFtWWtOZUg1ZVlxL0NuSXpMYWFjT1xueGxTYWF3UURPd3FLeS90Q3F4cTV4eFBTSmMyMUs0V0loczlHeU9rS2Z6dWVZM0dJTHpjTUpaNGNXdz09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKCQkJCX0KCQkJfSwKCQkJImUxODYzYmEwMjA3MDMyMmViYzYyNmRjZWNmOWQ4ODFhM2EzOGMzNWMzYjQxYTgzNzY1YjZhZDZjMzdlYWVjMmEiOiB7CgkJCQkia2V5dHlwZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCgkJCQkia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwoJCQkJCSJzaGEyNTYiLAoJCQkJCSJzaGE1MTIiCgkJCQldLAoJCQkJImtleXZhbCI6IHsKCQkJCQkicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVXUmlHcjUraiszSjVTc0grWnRyNW5FMkgyd083XG5CVituTzNzOTNnTGNhMThxVE96SFkxb1d5QUdEeWtNU3NHVFVCU3Q5RCtBbjBLZktzRDJtZlNNNDJRPT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgoJCQkJfQoJCQl9LAoJCQkiZjUzMTJmNTQyYzIxMjczZDk0ODVhNDkzOTQzODZjNDU3NTgwNDc3MDY2N2YyZGRiNTliM2JmMDY2OWZkZGQyZiI6IHsKCQkJCSJrZXl0eXBlIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAoJCQkJInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCgkJCQkJInNoYTI1NiIsCgkJCQkJInNoYTUxMiIKCQkJCV0sCgkJCQkia2V5dmFsIjogewoJCQkJCSJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXpCelZPbUhDUG9qTVZMU0kzNjRXaWlWOE5QckRcbjZJZ1J4Vmxpc2t6L3YreTNKRVI1bWNWR2NPTmxpRGNXTUM1SjJsZkhtalBOUGhiNEg3eG04THpmU0E9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCgkJCQl9CgkJCX0sCgkJCSJmZjUxZTE3ZmNmMjUzMTE5YjcwMzNmNmY1NzUxMjYzMWRhNGEwOTY5NDQyYWZjZjlmYzhiMTQxYzdmMmJlOTljIjogewoJCQkJImtleXR5cGUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCgkJCQkic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAoJCQkJImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKCQkJCQkic2hhMjU2IiwKCQkJCQkic2hhNTEyIgoJCQkJXSwKCQkJCSJrZXl2YWwiOiB7CgkJCQkJInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFeThYS3NtaEJZREk4SmMwR3d6QnhlS2F4MGNtNVxuU1RLRVU2NUhQRnVuVW40MXNUOHBpMEZqTTRJa0h6L1lVbXdtTFVPMFd0N2x4aGo2QmtMSUs0cVlBdz09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKCQkJCX0KCQkJfQoJCX0sCgkJInJvbGVzIjogewoJCQkicm9vdCI6IHsKCQkJCSJrZXlpZHMiOiBbCgkJCQkJImZmNTFlMTdmY2YyNTMxMTliNzAzM2Y2ZjU3NTEyNjMxZGE0YTA5Njk0NDJhZmNmOWZjOGIxNDFjN2YyYmU5OWMiLAoJCQkJCSIyNWEwZWI0NTBmZDNlZTJiZDc5MjE4Yzk2M2RjZTNmMWNjNjExOGJhZGYyNTFiZjE0OWYwYmQwN2Q1Y2FiZTk5IiwKCQkJCQkiZjUzMTJmNTQyYzIxMjczZDk0ODVhNDkzOTQzODZjNDU3NTgwNDc3MDY2N2YyZGRiNTliM2JmMDY2OWZkZGQyZiIsCgkJCQkJIjdmNzUxM2IyNTQyOWE2NDQ3M2UxMGNlM2FkMmYzZGEzNzJiYmRkMTRiNjVkMDdiYmFmNTQ3ZTdjOGJiYmU2MmIiLAoJCQkJCSIyZTYxY2QwY2JmNGE4ZjQ1ODA5YmRhOWY3Zjc4YzBkMzNhZDExODQyZmY5NGFlMzQwODczZTI2NjRkYzg0M2RlIgoJCQkJXSwKCQkJCSJ0aHJlc2hvbGQiOiAzCgkJCX0sCgkJCSJzbmFwc2hvdCI6IHsKCQkJCSJrZXlpZHMiOiBbCgkJCQkJIjQ1YjI4MzgyNWViMTg0Y2FiZDU4MmViMTdiNzRmYzhlZDQwNGY2OGNmNDUyYWNhYmRhZDJlZDZmOTBjZTIxNmIiCgkJCQldLAoJCQkJInRocmVzaG9sZCI6IDEKCQkJfSwKCQkJInRhcmdldHMiOiB7CgkJCQkia2V5aWRzIjogWwoJCQkJCSJmZjUxZTE3ZmNmMjUzMTE5YjcwMzNmNmY1NzUxMjYzMWRhNGEwOTY5NDQyYWZjZjlmYzhiMTQxYzdmMmJlOTljIiwKCQkJCQkiMjVhMGViNDUwZmQzZWUyYmQ3OTIxOGM5NjNkY2UzZjFjYzYxMThiYWRmMjUxYmYxNDlmMGJkMDdkNWNhYmU5OSIsCgkJCQkJImY1MzEyZjU0MmMyMTI3M2Q5NDg1YTQ5Mzk0Mzg2YzQ1NzU4MDQ3NzA2NjdmMmRkYjU5YjNiZjA2NjlmZGRkMmYiLAoJCQkJCSI3Zjc1MTNiMjU0MjlhNjQ0NzNlMTBjZTNhZDJmM2RhMzcyYmJkZDE0YjY1ZDA3YmJhZjU0N2U3YzhiYmJlNjJiIiwKCQkJCQkiMmU2MWNkMGNiZjRhOGY0NTgwOWJkYTlmN2Y3OGMwZDMzYWQxMTg0MmZmOTRhZTM0MDg3M2UyNjY0ZGM4NDNkZSIKCQkJCV0sCgkJCQkidGhyZXNob2xkIjogMwoJCQl9LAoJCQkidGltZXN0YW1wIjogewoJCQkJImtleWlkcyI6IFsKCQkJCQkiZTE4NjNiYTAyMDcwMzIyZWJjNjI2ZGNlY2Y5ZDg4MWEzYTM4YzM1YzNiNDFhODM3NjViNmFkNmMzN2VhZWMyYSIKCQkJCV0sCgkJCQkidGhyZXNob2xkIjogMQoJCQl9CgkJfSwKCQkiY29uc2lzdGVudF9zbmFwc2hvdCI6IHRydWUKCX0sCgkic2lnbmF0dXJlcyI6IFsKCQl7CgkJCSJrZXlpZCI6ICJmNTMxMmY1NDJjMjEyNzNkOTQ4NWE0OTM5NDM4NmM0NTc1ODA0NzcwNjY3ZjJkZGI1OWIzYmYwNjY5ZmRkZDJmIiwKCQkJInNpZyI6ICIzMDQ0MDIyMDI0YjgwMzZiMzc0ZjcwNzE3MjNmM2YyY2IxOTc5YzQyZTVkYTE5MTBmMGIxNzg4MzVhZDU0NmUzYzM2MDgzNjMwMjIwNzE0MGNjZDQwOGFmY2Y4NzIwZGQ5YmVhN2YwMDMyNTc2OGMzYWE0N2MyMmQ1MzFjODQ5Yzk3NGZkNTBlNDVkZCIKCQl9LAoJCXsKCQkJImtleWlkIjogIjdmNzUxM2IyNTQyOWE2NDQ3M2UxMGNlM2FkMmYzZGEzNzJiYmRkMTRiNjVkMDdiYmFmNTQ3ZTdjOGJiYmU2MmIiLAoJCQkic2lnIjogIjMwNDYwMjIxMDBkY2IxYTk2ZWNiZmMwNTc2OGEzYzczNzI2YTkyZDY4MWRhNzhlYWVjMDY4YTlhMGNmZTEzYTEyZGI2NzJlNDRiMDIyMTAwYTBkYWU3YmMyZTZiOTUzZTIxNWY1N2NjNjE0ZWI3MTY2MGI5NDYxZDZkYzg2MjY0YjBiNzRhNGYyZTEzMDdlMSIKCQl9LAoJCXsKCQkJImtleWlkIjogIjJlNjFjZDBjYmY0YThmNDU4MDliZGE5ZjdmNzhjMGQzM2FkMTE4NDJmZjk0YWUzNDA4NzNlMjY2NGRjODQzZGUiLAoJCQkic2lnIjogIjMwNDYwMjIxMDBjNDcwOGQ5NDA3N2NiM2Q2ZGQ2MGViZDJkZDY2NTQ1ZTdhZmIwNDY0Y2UyNTkzYTVmMjNmNmUzNjA0YjlmMjFlMDIyMTAwOTkyZTk2OWNkNTA2OWVhYjE3NDM5YjJiYTYwNzQzZmU0MjI4NzdiYzFhMWM0NmU5MzVhNmQ1Y2I0N2IzY2ZjNiIKCQl9LAoJCXsKCQkJImtleWlkIjogIjI1YTBlYjQ1MGZkM2VlMmJkNzkyMThjOTYzZGNlM2YxY2M2MTE4YmFkZjI1MWJmMTQ5ZjBiZDA3ZDVjYWJlOTkiLAoJCQkic2lnIjogIjMwNDUwMjIwNTFmYWE2YjZmYzM3MzczMGI5N2MxYTRjZDkyZDAzZWZkOThiODNkNGM5YzkzYmY0ZjQwNGQxZjg4ZWEyZWIxODAyMjEwMGY3MWFjMWNkNzNkY2JhOTUwZjQyMTBiMTJmOWEwNWI4MTQwYjA0OTAyNDdjNTMzOTE5MWU4NDJiODY4MTU1YjQiCgkJfQoJXQp9","targets":{"trusted_root.json":"ewogICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRldi5zaWdzdG9yZS50cnVzdGVkcm9vdCtqc29uO3ZlcnNpb249MC4xIiwKICAidGxvZ3MiOiBbCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vcmVrb3Iuc2lnc3RvcmUuZGV2IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUyRzJZKzJ0YWJkVFY1QmNHaUJJeDBhOWZBRndya0JibUxTR3RrczRMM3FYNnlZWTB6dWZCbmhDOFVyL2l5NTVHaFdQLzlBL2JZMkxoQzMwTTkrUll0dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDEtMTJUMTE6NTM6MjcuMDAwWiIKICAgICAgICB9CiAgICAgIH0sCiAgICAgICJsb2dJZCI6IHsKICAgICAgICAia2V5SWQiOiAid05JOWF0UUdseitWV2ZPNkxSeWdINFFVZlkvOFc0UkZ3aVQ1aTVXUmdCMD0iCiAgICAgIH0KICAgIH0KICBdLAogICJjZXJ0aWZpY2F0ZUF1dGhvcml0aWVzIjogWwogICAgewogICAgICAic3ViamVjdCI6IHsKICAgICAgICAib3JnYW5pemF0aW9uIjogInNpZ3N0b3JlLmRldiIsCiAgICAgICAgImNvbW1vbk5hbWUiOiAic2lnc3RvcmUiCiAgICAgIH0sCiAgICAgICJ1cmkiOiAiaHR0cHM6Ly9mdWxjaW8uc2lnc3RvcmUuZGV2IiwKICAgICAgImNlcnRDaGFpbiI6IHsKICAgICAgICAiY2VydGlmaWNhdGVzIjogWwogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQitEQ0NBWDZnQXdJQkFnSVROVmtEWm9DaW9mUERzeTdkZm02Z2VMYnVoekFLQmdncWhrak9QUVFEQXpBcU1SVXdFd1lEVlFRS0V3eHphV2R6ZEc5eVpTNWtaWFl4RVRBUEJnTlZCQU1UQ0hOcFozTjBiM0psTUI0WERUSXhNRE13TnpBek1qQXlPVm9YRFRNeE1ESXlNekF6TWpBeU9Wb3dLakVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SRXdEd1lEVlFRREV3aHphV2R6ZEc5eVpUQjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkxTeUE3SWk1aytwTk84WkVXWTB5bGVtV0Rvd09rTmEza0wrR1pFNVo1R1dlaEw5L0E5YlJOQTNSYnJzWjVpMEpjYXN0YVJMN1NwNWZwL2pENWR4cWMvVWRUVm5sdlMxNmFuKzJZZnN3ZS9RdUxvbFJVQ3JjT0UyKzJpQTUrdHpkNk5tTUdRd0RnWURWUjBQQVFIL0JBUURBZ0VHTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFFd0hRWURWUjBPQkJZRUZNakZIUUJCbWlRcE1sRWs2dzJ1U3UxS0J0UHNNQjhHQTFVZEl3UVlNQmFBRk1qRkhRQkJtaVFwTWxFazZ3MnVTdTFLQnRQc01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01IOGxpV0pmTXVpNnZYWEJoakRnWTRNd3NsbU4vVEp4VmUvODNXckZvbXdtTmYwNTZ5MVg0OEY5YzRtM2Ezb3pYQUl4QUtqUmF5NS9hai9qc0tLR0lrbVFhdGpJOHV1cEhyLytDeEZ2YUpXbXBZcU5rTERHUlUrOW9yemg1aEkyUnJjdWFRPT0iCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMDdUMDM6MjA6MjkuMDAwWiIsCiAgICAgICAgImVuZCI6ICIyMDIyLTEyLTMxVDIzOjU5OjU5Ljk5OVoiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAic2lnc3RvcmUuZGV2IiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJzaWdzdG9yZSIKICAgICAgfSwKICAgICAgInVyaSI6ICJodHRwczovL2Z1bGNpby5zaWdzdG9yZS5kZXYiLAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlDR2pDQ0FhR2dBd0lCQWdJVUFMblZpVmZuVTBickphc21Sa0hybi9VbmZhUXdDZ1lJS29aSXpqMEVBd013S2pFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUkV3RHdZRFZRUURFd2h6YVdkemRHOXlaVEFlRncweU1qQTBNVE15TURBMk1UVmFGdzB6TVRFd01EVXhNelUyTlRoYU1EY3hGVEFUQmdOVkJBb1RESE5wWjNOMGIzSmxMbVJsZGpFZU1Cd0dBMVVFQXhNVmMybG5jM1J2Y21VdGFXNTBaWEp0WldScFlYUmxNSFl3RUFZSEtvWkl6ajBDQVFZRks0RUVBQ0lEWWdBRThSVlMveXNIK05PdnVEWnlQSVp0aWxnVUY5TmxhcllwQWQ5SFAxdkJCSDFVNUNWNzdMU1M3czBaaUg0bkU3SHY3cHRTNkx2dlIvU1RrNzk4TFZnTXpMbEo0SGVJZkYzdEhTYWV4TGNZcFNBU3Ixa1MwTi9SZ0JKei85aldDaVhubzNzd2VUQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0V3WURWUjBsQkF3d0NnWUlLd1lCQlFVSEF3TXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFkQmdOVkhRNEVGZ1FVMzlQcHoxWWtFWmI1cU5qcEtGV2l4aTRZWkQ4d0h3WURWUjBqQkJnd0ZvQVVXTUFlWDVGRnBXYXBlc3lRb1pNaTBDckZ4Zm93Q2dZSUtvWkl6ajBFQXdNRFp3QXdaQUl3UENzUUs0RFlpWllEUElhRGk1SEZLbmZ4WHg2QVNTVm1FUmZzeW5ZQmlYMlg2U0pSblpVODQvOURaZG5GdnZ4bUFqQk90NlFwQmxjNEovMER4dmtUQ3FwY2x2emlMNkJDQ1BuamRsSUIzUHUzQnhzUG15Z1VZN0lpMnpiZENkbGlpb3c9IgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUI5ekNDQVh5Z0F3SUJBZ0lVQUxaTkFQRmR4SFB3amVEbG9Ed3lZQ2hBTy80d0NnWUlLb1pJemowRUF3TXdLakVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SRXdEd1lEVlFRREV3aHphV2R6ZEc5eVpUQWVGdzB5TVRFd01EY3hNelUyTlRsYUZ3MHpNVEV3TURVeE16VTJOVGhhTUNveEZUQVRCZ05WQkFvVERITnBaM04wYjNKbExtUmxkakVSTUE4R0ExVUVBeE1JYzJsbmMzUnZjbVV3ZGpBUUJnY3Foa2pPUFFJQkJnVXJnUVFBSWdOaUFBVDdYZUZUNHJiM1BRR3dTNElhanRMazMvT2xucGdhbmdhQmNsWXBzWUJyNWkrNHluQjA3Y2ViM0xQME9JT1pkeGV4WDY5YzVpVnV5SlJRK0h6MDV5aStVRjN1QldBbEhwaVM1c2gwK0gyR0hFN1NYcmsxRUM1bTFUcjE5TDlnZzkyall6QmhNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUll3QjVma1VXbFpxbDZ6SkNoa3lMUUtzWEYrakFmQmdOVkhTTUVHREFXZ0JSWXdCNWZrVVdsWnFsNnpKQ2hreUxRS3NYRitqQUtCZ2dxaGtqT1BRUURBd05wQURCbUFqRUFqMW5IZVhacCsxM05XQk5hK0VEc0RQOEcxV1dnMXRDTVdQL1dIUHFwYVZvMGpoc3dlTkZaZ1NzMGVFN3dZSTRxQWpFQTJXQjlvdDk4c0lrb0YzdlpZZGQzL1Z0V0I1YjlUTk1lYTdJeC9zdEo1VGZjTExlQUJMRTRCTkpPc1E0dm5CSEoiCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjItMDQtMTNUMjA6MDY6MTUuMDAwWiIKICAgICAgfQogICAgfQogIF0sCiAgImN0bG9ncyI6IFsKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9jdGZlLnNpZ3N0b3JlLmRldi90ZXN0IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUViZndSK1JKdWRYc2NnUkJScEtYMVhGRHkzUHl1ZER4ei9TZm5SaTFmVDhla3BmQmQyTzF1b3o3anIzWjhuS3p4QTY5RVVRK2VGQ0ZJM3pldWJQV1U3dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMTRUMDA6MDA6MDAuMDAwWiIsCiAgICAgICAgICAiZW5kIjogIjIwMjItMTAtMzFUMjM6NTk6NTkuOTk5WiIKICAgICAgICB9CiAgICAgIH0sCiAgICAgICJsb2dJZCI6IHsKICAgICAgICAia2V5SWQiOiAiQ0dDUzhDaFMvMmhGMGRGcko0U2NSV2NZckJZOXd6alNiZWE4SWdZMmIzST0iCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vY3RmZS5zaWdzdG9yZS5kZXYvMjAyMiIsCiAgICAgICJoYXNoQWxnb3JpdGhtIjogIlNIQTJfMjU2IiwKICAgICAgInB1YmxpY0tleSI6IHsKICAgICAgICAicmF3Qnl0ZXMiOiAiTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFaVBTbEZpMENtRlRmRWpDVXFGOUh1Q0VjWVhOS0FhWWFsSUptQlo4eXllelBqVHFoeHJLQnBNbmFvY1Z0TEpCSTFlTTN1WG5RelFHQUpkSjRnczlGeXc9PSIsCiAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICJ2YWxpZEZvciI6IHsKICAgICAgICAgICJzdGFydCI6ICIyMDIyLTEwLTIwVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgfQogICAgICB9LAogICAgICAibG9nSWQiOiB7CiAgICAgICAgImtleUlkIjogIjNUMHdhc2JIRVRKakdSNGNtV2MzQXFKS1hyamVQSzMvaDRweWdDOHA3bzQ9IgogICAgICB9CiAgICB9CiAgXSwKICAidGltZXN0YW1wQXV0aG9yaXRpZXMiOiBbCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAiR2l0SHViLCBJbmMuIiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJJbnRlcm5hbCBTZXJ2aWNlcyBSb290IgogICAgICB9LAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlCM0RDQ0FXS2dBd0lCQWdJVWNoa05zSDM2WGEwNGIxTHFJYytxcjlEVmVjTXdDZ1lJS29aSXpqMEVBd013TWpFVk1CTUdBMVVFQ2hNTVIybDBTSFZpTENCSmJtTXVNUmt3RndZRFZRUURFeEJVVTBFZ2FXNTBaWEp0WldScFlYUmxNQjRYRFRJek1EUXhOREF3TURBd01Gb1hEVEkwTURReE16QXdNREF3TUZvd01qRVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVJrd0Z3WURWUVFERXhCVVUwRWdWR2x0WlhOMFlXMXdhVzVuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFVUQ1Wk5iU3FZTWQ2cjhxcE9PRVg5aWJHblpUOUdzdVhPaHIvZjhVOUZKdWdCR0V4S1lwNDBPVUxTMGVyalpXN3hWOXhWNTJObkpmNU9lRHE0ZTVaS3FOV01GUXdEZ1lEVlIwUEFRSC9CQVFEQWdlQU1CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUlNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVhVzFSdWRPZ1Z0MGxlcVkwV0tZYnVQcjQ3d0F3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl3YlVIOUh2RDRlakNaSk9XUW5xQWxrcVVSbGx2dTlNOCtWcUxiaVJLK3pTZlpDWndzaWxqUm44TVFRUlNrWEVFNUFqRUFnK1Z4cXRvamZWZnU4RGh6emhDeDlHS0VUYkpIYjE5aVY3Mm1NS1ViREFGbXpaNmJROGI1NFpiOHRpZHk1YVdlIgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUNFRENDQVpXZ0F3SUJBZ0lVWDhaTzVRWFA3dk40ZE1RNWU5c1UzbnViOE9nd0NnWUlLb1pJemowRUF3TXdPREVWTUJNR0ExVUVDaE1NUjJsMFNIVmlMQ0JKYm1NdU1SOHdIUVlEVlFRREV4WkpiblJsY201aGJDQlRaWEoyYVdObGN5QlNiMjkwTUI0WERUSXpNRFF4TkRBd01EQXdNRm9YRFRJNE1EUXhNakF3TURBd01Gb3dNakVWTUJNR0ExVUVDaE1NUjJsMFNIVmlMQ0JKYm1NdU1Sa3dGd1lEVlFRREV4QlVVMEVnYVc1MFpYSnRaV1JwWVhSbE1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFdk1MWS9kVFZidklKWUFOQXVzekV3Sm5RRTFsbGZ0eW55TUtJTWhoNDhIbXFiVnI1eWd5YnpzTFJMVktiQldPZFoyMWFlSnorZ1ppeXRaZXRxY3lGOVdsRVI1TkVNZjZKVjdaTm9qUXB4SHE0UkhHb0dTY2VRdi9xdlRpWnhFREtvMll3WkRBT0JnTlZIUThCQWY4RUJBTUNBUVl3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZEJnTlZIUTRFRmdRVWFXMVJ1ZE9nVnQwbGVxWTBXS1lidVByNDd3QXdId1lEVlIwakJCZ3dGb0FVOU5ZWWxvYm5BRzRjMC9xanh5SC9scS93eitRd0NnWUlLb1pJemowRUF3TURhUUF3WmdJeEFLMUIxODV5Z0NySVlGbElzM0dqc3dqbndTTUc2TFk4d29MVmRha0tEWnhWYThmOGNxTXMxRGhjeEowKzA5dzk1UUl4QU8rdEJ6Wms3dmpVSjlpSmdENFI2WldUeFFXS3FObTc0ak85OW8rbzlzdjRGSS9TWlRaVEZ5TW4wSUpFSGRObXlBPT0iCiAgICAgICAgICB9LAogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQjlEQ0NBWHFnQXdJQkFnSVVhL0pBa2RVaks0SlV3c3F0YWlSSkdXaHFMU293Q2dZSUtvWkl6ajBFQXdNd09ERVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVI4d0hRWURWUVFERXhaSmJuUmxjbTVoYkNCVFpYSjJhV05sY3lCU2IyOTBNQjRYRFRJek1EUXhOREF3TURBd01Gb1hEVE16TURReE1UQXdNREF3TUZvd09ERVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVI4d0hRWURWUVFERXhaSmJuUmxjbTVoYkNCVFpYSjJhV05sY3lCU2IyOTBNSFl3RUFZSEtvWkl6ajBDQVFZRks0RUVBQ0lEWWdBRWY5akZBWHh6NGt4NjhBSFJNT2tGQmhmbERjTVR2emFYejR4L0ZDY1hqSi8xcUVLb24vcVBJR25hVVJza0R0eU5iTkRPcGVKVERERnF0NDhpTVBybnpweDZJWndxZW1mVUpONHhCRVpmemErcFl0L2l5b2QrOXRacjIwUlJXU3YvbzBVd1F6QU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFqQWRCZ05WSFE0RUZnUVU5TllZbG9ibkFHNGMwL3FqeHlIL2xxL3d6K1F3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl4QUxaTFo4QmdSWHpLeExNTU45VklsTytlNGhyQm5OQmdGN3R6N0hucm93djJOZXRaRXJJQUNLRnltQmx2V0R2dE1BSXdaTytraTZzc1ExYnNabzk4TzhtRUFmMk5aN2lpQ2dERFUwVndqZWNvNnp5ZWgwekJUczkvN2dWNkFITlE1M3hEIgogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfSwKICAgICAgInZhbGlkRm9yIjogewogICAgICAgICJzdGFydCI6ICIyMDIzLTA0LTE0VDAwOjAwOjAwLjAwMFoiCiAgICAgIH0KICAgIH0KICBdCn0K","registry.npmjs.org%2Fkeys.json":"ewogICAgImtleXMiOiBbCiAgICAgICAgewogICAgICAgICAgICAia2V5SWQiOiAiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLAogICAgICAgICAgICAia2V5VXNhZ2UiOiAibnBtOnNpZ25hdHVyZXMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTFPbGIzek1BRkZ4WEtIaUlrUU81Y0ozWWhsNWk2VVBwK0lodXRlQkpidUhjQTVVb2dLbzBFV3RsV3dXNktTYUtvVE5FWUw3SmxDUWlWbmtoQmt0VWdnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIxOTk5LTAxLTAxVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICAgImtleUlkIjogIlNIQTI1NjpqbDNid3N3dTgwUGpqb2tDZ2gwbzJ3NWMyVTRMaFFBRTU3Z2o5Y3oxa3pBIiwKICAgICAgICAgICAgImtleVVzYWdlIjogIm5wbTphdHRlc3RhdGlvbnMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTFPbGIzek1BRkZ4WEtIaUlrUU81Y0ozWWhsNWk2VVBwK0lodXRlQkpidUhjQTVVb2dLbzBFV3RsV3dXNktTYUtvVE5FWUw3SmxDUWlWbmtoQmt0VWdnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIyMDIyLTEyLTAxVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICBdCn0K"}}} +{"https://tuf-repo-cdn.sigstore.dev":{"root.json":"ewoJInNpZ25lZCI6IHsKCQkiX3R5cGUiOiAicm9vdCIsCgkJInNwZWNfdmVyc2lvbiI6ICIxLjAiLAoJCSJ2ZXJzaW9uIjogOSwKCQkiZXhwaXJlcyI6ICIyMDI0LTA5LTEyVDA2OjUzOjEwWiIsCgkJImtleXMiOiB7CgkJCSIxZTFkNjVjZTk4YjEwYWRkYWQ0NzY0ZmViZjdkZGEyZDA0MzZiM2QzYTM4OTM1NzljMGRkZGFlYTIwZTU0ODQ5IjogewoJCQkJImtleXR5cGUiOiAiZWNkc2EiLAoJCQkJInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCgkJCQkJInNoYTI1NiIsCgkJCQkJInNoYTUxMiIKCQkJCV0sCgkJCQkia2V5dmFsIjogewoJCQkJCSJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXpCelZPbUhDUG9qTVZMU0kzNjRXaWlWOE5QckRcbjZJZ1J4Vmxpc2t6L3YreTNKRVI1bWNWR2NPTmxpRGNXTUM1SjJsZkhtalBOUGhiNEg3eG04THpmU0E9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCgkJCQl9CgkJCX0sCgkJCSIyMzBlMjEyNjE2Mjc0YTQxOTVjZGMyOGU5ZmNlNzgyYzIwZTZjNzIwZjFhODExYjQwZjk4MjI4Mzc2YmRkM2FjIjogewoJCQkJImtleXR5cGUiOiAiZWNkc2EiLAoJCQkJInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCgkJCQkJInNoYTI1NiIsCgkJCQkJInNoYTUxMiIKCQkJCV0sCgkJCQkia2V5dmFsIjogewoJCQkJCSJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUxyV3ZOdDk0djRSMDg1RUxlZUNNeEhwN1BsZEZcbjAvVDFHeHVrVWgyT0R1Z2dMR0pFMHBjMWU4Q1NCZjZDUzkxRndvOUZVT3VSc2pCVWxkK1ZxU3lDZFE9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCgkJCQl9CgkJCX0sCgkJCSIzYzM0NGFhMDY4ZmQ0Y2M0ZTg3ZGM1MGI2MTJjMDI0MzFmYmM3NzFlOTUwMDM5OTM2ODNhMmIwYmYyNjBjZjBlIjogewoJCQkJImtleXR5cGUiOiAiZWNkc2EiLAoJCQkJInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCgkJCQkJInNoYTI1NiIsCgkJCQkJInNoYTUxMiIKCQkJCV0sCgkJCQkia2V5dmFsIjogewoJCQkJCSJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXk4WEtzbWhCWURJOEpjMEd3ekJ4ZUtheDBjbTVcblNUS0VVNjVIUEZ1blVuNDFzVDhwaTBGak00SWtIei9ZVW13bUxVTzBXdDdseGhqNkJrTElLNHFZQXc9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCgkJCQl9CgkJCX0sCgkJCSI5MjNiYjM5ZTYwZGQ2ZmEyYzMxZTZlYTU1NDczYWE5M2I2NGRkNGU1M2UxNmZiZTQyZjZhMjA3ZDNmOTdkZTJkIjogewoJCQkJImtleXR5cGUiOiAiZWNkc2EiLAoJCQkJInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCgkJCQkJInNoYTI1NiIsCgkJCQkJInNoYTUxMiIKCQkJCV0sCgkJCQkia2V5dmFsIjogewoJCQkJCSJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVdSaUdyNStqKzNKNVNzSCtadHI1bkUySDJ3TzdcbkJWK25PM3M5M2dMY2ExOHFUT3pIWTFvV3lBR0R5a01Tc0dUVUJTdDlEK0FuMEtmS3NEMm1mU000MlE9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCgkJCQl9CgkJCX0sCgkJCSJlMmY1OWFjYjk0ODg1MTk0MDdlMThjYmZjOTMyOTUxMGJlMDNjMDRhY2E5OTI5ZDJmMDMwMTM0M2ZlYzg1NTIzIjogewoJCQkJImtleXR5cGUiOiAiZWNkc2EiLAoJCQkJInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCgkJCQkJInNoYTI1NiIsCgkJCQkJInNoYTUxMiIKCQkJCV0sCgkJCQkia2V5dmFsIjogewoJCQkJCSJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRWluaWtTc0FRbVlrTmVINWVZcS9Dbkl6TGFhY09cbnhsU2Fhd1FET3dxS3kvdENxeHE1eHhQU0pjMjFLNFdJaHM5R3lPa0tmenVlWTNHSUx6Y01KWjRjV3c9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCgkJCQl9CgkJCX0sCgkJCSJlYzgxNjY5NzM0ZTAxNzk5NmM1Yjg1ZjNkMDJjM2RlMWRkNDYzN2ExNTIwMTlmZTFhZjEyNWQyZjkzNjhiOTVlIjogewoJCQkJImtleXR5cGUiOiAiZWNkc2EiLAoJCQkJInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCgkJCQkJInNoYTI1NiIsCgkJCQkJInNoYTUxMiIKCQkJCV0sCgkJCQkia2V5dmFsIjogewoJCQkJCSJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUVYc3ozU1pYRmI4ak1WNDJqNnBKbHlqYmpSOEtcbk4zQndvY2V4cTZMTUliNXFzV0tPUXZMTjE2TlVlZkxjNEhzd09vdW1Sc1ZWYWFqU3BRUzZmb2JrUnc9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCgkJCQl9CgkJCX0sCgkJCSJmZGZhODNhMDdiNWE4MzU4OWI4N2RlZDQxZjc3ZjM5ZDIzMmFkOTFmN2NjZTUyODY4ZGFjZDA2YmEwODk4NDlmIjogewoJCQkJImtleXR5cGUiOiAiZWNkc2EiLAoJCQkJInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCgkJCQkJInNoYTI1NiIsCgkJCQkJInNoYTUxMiIKCQkJCV0sCgkJCQkia2V5dmFsIjogewoJCQkJCSJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTBnaHJoOTJMdzFZcjNpZEdWNVdxQ3RNREI4Q3hcbitEOGhkQzR3MlpMTklwbFZSb1ZHTHNrWWEzZ2hlTXlPamlKOGtQaTE1YVEyLy83UCtvajdVdkpQR3c9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCgkJCQl9CgkJCX0KCQl9LAoJCSJyb2xlcyI6IHsKCQkJInJvb3QiOiB7CgkJCQkia2V5aWRzIjogWwoJCQkJCSIzYzM0NGFhMDY4ZmQ0Y2M0ZTg3ZGM1MGI2MTJjMDI0MzFmYmM3NzFlOTUwMDM5OTM2ODNhMmIwYmYyNjBjZjBlIiwKCQkJCQkiZWM4MTY2OTczNGUwMTc5OTZjNWI4NWYzZDAyYzNkZTFkZDQ2MzdhMTUyMDE5ZmUxYWYxMjVkMmY5MzY4Yjk1ZSIsCgkJCQkJIjFlMWQ2NWNlOThiMTBhZGRhZDQ3NjRmZWJmN2RkYTJkMDQzNmIzZDNhMzg5MzU3OWMwZGRkYWVhMjBlNTQ4NDkiLAoJCQkJCSJlMmY1OWFjYjk0ODg1MTk0MDdlMThjYmZjOTMyOTUxMGJlMDNjMDRhY2E5OTI5ZDJmMDMwMTM0M2ZlYzg1NTIzIiwKCQkJCQkiZmRmYTgzYTA3YjVhODM1ODliODdkZWQ0MWY3N2YzOWQyMzJhZDkxZjdjY2U1Mjg2OGRhY2QwNmJhMDg5ODQ5ZiIKCQkJCV0sCgkJCQkidGhyZXNob2xkIjogMwoJCQl9LAoJCQkic25hcHNob3QiOiB7CgkJCQkia2V5aWRzIjogWwoJCQkJCSIyMzBlMjEyNjE2Mjc0YTQxOTVjZGMyOGU5ZmNlNzgyYzIwZTZjNzIwZjFhODExYjQwZjk4MjI4Mzc2YmRkM2FjIgoJCQkJXSwKCQkJCSJ0aHJlc2hvbGQiOiAxCgkJCX0sCgkJCSJ0YXJnZXRzIjogewoJCQkJImtleWlkcyI6IFsKCQkJCQkiM2MzNDRhYTA2OGZkNGNjNGU4N2RjNTBiNjEyYzAyNDMxZmJjNzcxZTk1MDAzOTkzNjgzYTJiMGJmMjYwY2YwZSIsCgkJCQkJImVjODE2Njk3MzRlMDE3OTk2YzViODVmM2QwMmMzZGUxZGQ0NjM3YTE1MjAxOWZlMWFmMTI1ZDJmOTM2OGI5NWUiLAoJCQkJCSIxZTFkNjVjZTk4YjEwYWRkYWQ0NzY0ZmViZjdkZGEyZDA0MzZiM2QzYTM4OTM1NzljMGRkZGFlYTIwZTU0ODQ5IiwKCQkJCQkiZTJmNTlhY2I5NDg4NTE5NDA3ZTE4Y2JmYzkzMjk1MTBiZTAzYzA0YWNhOTkyOWQyZjAzMDEzNDNmZWM4NTUyMyIsCgkJCQkJImZkZmE4M2EwN2I1YTgzNTg5Yjg3ZGVkNDFmNzdmMzlkMjMyYWQ5MWY3Y2NlNTI4NjhkYWNkMDZiYTA4OTg0OWYiCgkJCQldLAoJCQkJInRocmVzaG9sZCI6IDMKCQkJfSwKCQkJInRpbWVzdGFtcCI6IHsKCQkJCSJrZXlpZHMiOiBbCgkJCQkJIjkyM2JiMzllNjBkZDZmYTJjMzFlNmVhNTU0NzNhYTkzYjY0ZGQ0ZTUzZTE2ZmJlNDJmNmEyMDdkM2Y5N2RlMmQiCgkJCQldLAoJCQkJInRocmVzaG9sZCI6IDEKCQkJfQoJCX0sCgkJImNvbnNpc3RlbnRfc25hcHNob3QiOiB0cnVlCgl9LAoJInNpZ25hdHVyZXMiOiBbCgkJewoJCQkia2V5aWQiOiAiZmY1MWUxN2ZjZjI1MzExOWI3MDMzZjZmNTc1MTI2MzFkYTRhMDk2OTQ0MmFmY2Y5ZmM4YjE0MWM3ZjJiZTk5YyIsCgkJCSJzaWciOiAiMzA0NTAyMjEwMDhiNzhmODk0YzNjZmVkM2JkNDg2Mzc5YzRlMGUwZGZiM2U3ZGQ4Y2JjNGQ1NTk4ZDI4MThlZWExYmEzYzc1NTAwMjIwMjlkM2QwNmU4OWQwNGQzNzg0OTk4NWRjNDZjMGUxMGRjNWIxZmM2OGRjNzBhZjFlYzk5MTAzMDNhMWYzZWUyZiIKCQl9LAoJCXsKCQkJImtleWlkIjogIjI1YTBlYjQ1MGZkM2VlMmJkNzkyMThjOTYzZGNlM2YxY2M2MTE4YmFkZjI1MWJmMTQ5ZjBiZDA3ZDVjYWJlOTkiLAoJCQkic2lnIjogIjMwNDUwMjIxMDA5ZTZiOTBiOTM1ZTA5YjgzN2E5MGQ0NDAyZWFhMjdkNWVhMjZlYjc4OTE5NDhiYTBlZDcwOTA4NDEyNDhmNDM2MDIyMDAzZGMyMjUxYzRkNGE3OTk5YjkxZTlhZDA4Njg3NjVhZTA5YWM3MjY5Mjc5ZjJhNzg5OWJhZmVmN2EyZDkyNjAiCgkJfSwKCQl7CgkJCSJrZXlpZCI6ICJmNTMxMmY1NDJjMjEyNzNkOTQ4NWE0OTM5NDM4NmM0NTc1ODA0NzcwNjY3ZjJkZGI1OWIzYmYwNjY5ZmRkZDJmIiwKCQkJInNpZyI6ICIzMDQ0MDIyMDA5OWU5MDdkY2Y5MGI3YjZlMTA5ZmQxZDZlNDQyMDA2ZmNjYmI0ODg5NGFhYWZmNDdhYjgyNGIwM2ZiMzVkMGQwMjIwMmFhMGEwNmMyMWE0MjMzZjM3OTAwYTQ4YmM4Nzc3ZDNiNDdmNTllM2EzODYxNmNlNjMxYTA0ZGY1N2Y5NjczNiIKCQl9LAoJCXsKCQkJImtleWlkIjogIjNjMzQ0YWEwNjhmZDRjYzRlODdkYzUwYjYxMmMwMjQzMWZiYzc3MWU5NTAwMzk5MzY4M2EyYjBiZjI2MGNmMGUiLAoJCQkic2lnIjogIjMwNDUwMjIxMDA4Yjc4Zjg5NGMzY2ZlZDNiZDQ4NjM3OWM0ZTBlMGRmYjNlN2RkOGNiYzRkNTU5OGQyODE4ZWVhMWJhM2M3NTUwMDIyMDI5ZDNkMDZlODlkMDRkMzc4NDk5ODVkYzQ2YzBlMTBkYzViMWZjNjhkYzcwYWYxZWM5OTEwMzAzYTFmM2VlMmYiCgkJfSwKCQl7CgkJCSJrZXlpZCI6ICJlYzgxNjY5NzM0ZTAxNzk5NmM1Yjg1ZjNkMDJjM2RlMWRkNDYzN2ExNTIwMTlmZTFhZjEyNWQyZjkzNjhiOTVlIiwKCQkJInNpZyI6ICIzMDQ1MDIyMTAwOWU2YjkwYjkzNWUwOWI4MzdhOTBkNDQwMmVhYTI3ZDVlYTI2ZWI3ODkxOTQ4YmEwZWQ3MDkwODQxMjQ4ZjQzNjAyMjAwM2RjMjI1MWM0ZDRhNzk5OWI5MWU5YWQwODY4NzY1YWUwOWFjNzI2OTI3OWYyYTc4OTliYWZlZjdhMmQ5MjYwIgoJCX0sCgkJewoJCQkia2V5aWQiOiAiZTJmNTlhY2I5NDg4NTE5NDA3ZTE4Y2JmYzkzMjk1MTBiZTAzYzA0YWNhOTkyOWQyZjAzMDEzNDNmZWM4NTUyMyIsCgkJCSJzaWciOiAiMzA0NTAyMjAwZTU2MTNiOTAxZTBmM2UwOGVjZWFiZGRjNzNmOThiNTBkZGY4OTJlOTk4ZDBiMzY5YzZlM2Q0NTFhYzQ4ODc1MDIyMTAwOTQwY2Y5MmQxZjQzZWUyZTVjZGJiMjI1NzJiYjUyOTI1ZWQzODYzYTY4OGY3ZmZkZDRiZDJlMmU1NmYwMjhiMyIKCQl9LAoJCXsKCQkJImtleWlkIjogIjJlNjFjZDBjYmY0YThmNDU4MDliZGE5ZjdmNzhjMGQzM2FkMTE4NDJmZjk0YWUzNDA4NzNlMjY2NGRjODQzZGUiLAoJCQkic2lnIjogIjMwNDUwMjIwMmNmZjQ0ZjIyMTVkN2E0N2IyOGI4ZjVmNTgwYzJjZmJiZDFiZmNmY2JiZTc4ZGUzMjMwNDViMmMwYmFkYzVlOTAyMjEwMGM3NDM5NDllYjNmNGVhNWE0YjlhZTI3YWM2ZWRkZWExZjBmZjliZmQwMDRmOGE5YTlkMThjNmU0MTQyYjZlNzUiCgkJfSwKCQl7CgkJCSJrZXlpZCI6ICIxZTFkNjVjZTk4YjEwYWRkYWQ0NzY0ZmViZjdkZGEyZDA0MzZiM2QzYTM4OTM1NzljMGRkZGFlYTIwZTU0ODQ5IiwKCQkJInNpZyI6ICIzMDQ0MDIyMDA5OWU5MDdkY2Y5MGI3YjZlMTA5ZmQxZDZlNDQyMDA2ZmNjYmI0ODg5NGFhYWZmNDdhYjgyNGIwM2ZiMzVkMGQwMjIwMmFhMGEwNmMyMWE0MjMzZjM3OTAwYTQ4YmM4Nzc3ZDNiNDdmNTllM2EzODYxNmNlNjMxYTA0ZGY1N2Y5NjczNiIKCQl9LAoJCXsKCQkJImtleWlkIjogImZkZmE4M2EwN2I1YTgzNTg5Yjg3ZGVkNDFmNzdmMzlkMjMyYWQ5MWY3Y2NlNTI4NjhkYWNkMDZiYTA4OTg0OWYiLAoJCQkic2lnIjogIjMwNDUwMjIwMmNmZjQ0ZjIyMTVkN2E0N2IyOGI4ZjVmNTgwYzJjZmJiZDFiZmNmY2JiZTc4ZGUzMjMwNDViMmMwYmFkYzVlOTAyMjEwMGM3NDM5NDllYjNmNGVhNWE0YjlhZTI3YWM2ZWRkZWExZjBmZjliZmQwMDRmOGE5YTlkMThjNmU0MTQyYjZlNzUiCgkJfSwKCQl7CgkJCSJrZXlpZCI6ICI3Zjc1MTNiMjU0MjlhNjQ0NzNlMTBjZTNhZDJmM2RhMzcyYmJkZDE0YjY1ZDA3YmJhZjU0N2U3YzhiYmJlNjJiIiwKCQkJInNpZyI6ICIzMDQ1MDIyMDBlNTYxM2I5MDFlMGYzZTA4ZWNlYWJkZGM3M2Y5OGI1MGRkZjg5MmU5OThkMGIzNjljNmUzZDQ1MWFjNDg4NzUwMjIxMDA5NDBjZjkyZDFmNDNlZTJlNWNkYmIyMjU3MmJiNTI5MjVlZDM4NjNhNjg4ZjdmZmRkNGJkMmUyZTU2ZjAyOGIzIgoJCX0KCV0KfQ==","targets":{"trusted_root.json":"ewogICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRldi5zaWdzdG9yZS50cnVzdGVkcm9vdCtqc29uO3ZlcnNpb249MC4xIiwKICAidGxvZ3MiOiBbCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vcmVrb3Iuc2lnc3RvcmUuZGV2IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUyRzJZKzJ0YWJkVFY1QmNHaUJJeDBhOWZBRndya0JibUxTR3RrczRMM3FYNnlZWTB6dWZCbmhDOFVyL2l5NTVHaFdQLzlBL2JZMkxoQzMwTTkrUll0dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDEtMTJUMTE6NTM6MjcuMDAwWiIKICAgICAgICB9CiAgICAgIH0sCiAgICAgICJsb2dJZCI6IHsKICAgICAgICAia2V5SWQiOiAid05JOWF0UUdseitWV2ZPNkxSeWdINFFVZlkvOFc0UkZ3aVQ1aTVXUmdCMD0iCiAgICAgIH0KICAgIH0KICBdLAogICJjZXJ0aWZpY2F0ZUF1dGhvcml0aWVzIjogWwogICAgewogICAgICAic3ViamVjdCI6IHsKICAgICAgICAib3JnYW5pemF0aW9uIjogInNpZ3N0b3JlLmRldiIsCiAgICAgICAgImNvbW1vbk5hbWUiOiAic2lnc3RvcmUiCiAgICAgIH0sCiAgICAgICJ1cmkiOiAiaHR0cHM6Ly9mdWxjaW8uc2lnc3RvcmUuZGV2IiwKICAgICAgImNlcnRDaGFpbiI6IHsKICAgICAgICAiY2VydGlmaWNhdGVzIjogWwogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQitEQ0NBWDZnQXdJQkFnSVROVmtEWm9DaW9mUERzeTdkZm02Z2VMYnVoekFLQmdncWhrak9QUVFEQXpBcU1SVXdFd1lEVlFRS0V3eHphV2R6ZEc5eVpTNWtaWFl4RVRBUEJnTlZCQU1UQ0hOcFozTjBiM0psTUI0WERUSXhNRE13TnpBek1qQXlPVm9YRFRNeE1ESXlNekF6TWpBeU9Wb3dLakVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SRXdEd1lEVlFRREV3aHphV2R6ZEc5eVpUQjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkxTeUE3SWk1aytwTk84WkVXWTB5bGVtV0Rvd09rTmEza0wrR1pFNVo1R1dlaEw5L0E5YlJOQTNSYnJzWjVpMEpjYXN0YVJMN1NwNWZwL2pENWR4cWMvVWRUVm5sdlMxNmFuKzJZZnN3ZS9RdUxvbFJVQ3JjT0UyKzJpQTUrdHpkNk5tTUdRd0RnWURWUjBQQVFIL0JBUURBZ0VHTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFFd0hRWURWUjBPQkJZRUZNakZIUUJCbWlRcE1sRWs2dzJ1U3UxS0J0UHNNQjhHQTFVZEl3UVlNQmFBRk1qRkhRQkJtaVFwTWxFazZ3MnVTdTFLQnRQc01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01IOGxpV0pmTXVpNnZYWEJoakRnWTRNd3NsbU4vVEp4VmUvODNXckZvbXdtTmYwNTZ5MVg0OEY5YzRtM2Ezb3pYQUl4QUtqUmF5NS9hai9qc0tLR0lrbVFhdGpJOHV1cEhyLytDeEZ2YUpXbXBZcU5rTERHUlUrOW9yemg1aEkyUnJjdWFRPT0iCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMDdUMDM6MjA6MjkuMDAwWiIsCiAgICAgICAgImVuZCI6ICIyMDIyLTEyLTMxVDIzOjU5OjU5Ljk5OVoiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAic2lnc3RvcmUuZGV2IiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJzaWdzdG9yZSIKICAgICAgfSwKICAgICAgInVyaSI6ICJodHRwczovL2Z1bGNpby5zaWdzdG9yZS5kZXYiLAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlDR2pDQ0FhR2dBd0lCQWdJVUFMblZpVmZuVTBickphc21Sa0hybi9VbmZhUXdDZ1lJS29aSXpqMEVBd013S2pFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUkV3RHdZRFZRUURFd2h6YVdkemRHOXlaVEFlRncweU1qQTBNVE15TURBMk1UVmFGdzB6TVRFd01EVXhNelUyTlRoYU1EY3hGVEFUQmdOVkJBb1RESE5wWjNOMGIzSmxMbVJsZGpFZU1Cd0dBMVVFQXhNVmMybG5jM1J2Y21VdGFXNTBaWEp0WldScFlYUmxNSFl3RUFZSEtvWkl6ajBDQVFZRks0RUVBQ0lEWWdBRThSVlMveXNIK05PdnVEWnlQSVp0aWxnVUY5TmxhcllwQWQ5SFAxdkJCSDFVNUNWNzdMU1M3czBaaUg0bkU3SHY3cHRTNkx2dlIvU1RrNzk4TFZnTXpMbEo0SGVJZkYzdEhTYWV4TGNZcFNBU3Ixa1MwTi9SZ0JKei85aldDaVhubzNzd2VUQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0V3WURWUjBsQkF3d0NnWUlLd1lCQlFVSEF3TXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFkQmdOVkhRNEVGZ1FVMzlQcHoxWWtFWmI1cU5qcEtGV2l4aTRZWkQ4d0h3WURWUjBqQkJnd0ZvQVVXTUFlWDVGRnBXYXBlc3lRb1pNaTBDckZ4Zm93Q2dZSUtvWkl6ajBFQXdNRFp3QXdaQUl3UENzUUs0RFlpWllEUElhRGk1SEZLbmZ4WHg2QVNTVm1FUmZzeW5ZQmlYMlg2U0pSblpVODQvOURaZG5GdnZ4bUFqQk90NlFwQmxjNEovMER4dmtUQ3FwY2x2emlMNkJDQ1BuamRsSUIzUHUzQnhzUG15Z1VZN0lpMnpiZENkbGlpb3c9IgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUI5ekNDQVh5Z0F3SUJBZ0lVQUxaTkFQRmR4SFB3amVEbG9Ed3lZQ2hBTy80d0NnWUlLb1pJemowRUF3TXdLakVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SRXdEd1lEVlFRREV3aHphV2R6ZEc5eVpUQWVGdzB5TVRFd01EY3hNelUyTlRsYUZ3MHpNVEV3TURVeE16VTJOVGhhTUNveEZUQVRCZ05WQkFvVERITnBaM04wYjNKbExtUmxkakVSTUE4R0ExVUVBeE1JYzJsbmMzUnZjbVV3ZGpBUUJnY3Foa2pPUFFJQkJnVXJnUVFBSWdOaUFBVDdYZUZUNHJiM1BRR3dTNElhanRMazMvT2xucGdhbmdhQmNsWXBzWUJyNWkrNHluQjA3Y2ViM0xQME9JT1pkeGV4WDY5YzVpVnV5SlJRK0h6MDV5aStVRjN1QldBbEhwaVM1c2gwK0gyR0hFN1NYcmsxRUM1bTFUcjE5TDlnZzkyall6QmhNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUll3QjVma1VXbFpxbDZ6SkNoa3lMUUtzWEYrakFmQmdOVkhTTUVHREFXZ0JSWXdCNWZrVVdsWnFsNnpKQ2hreUxRS3NYRitqQUtCZ2dxaGtqT1BRUURBd05wQURCbUFqRUFqMW5IZVhacCsxM05XQk5hK0VEc0RQOEcxV1dnMXRDTVdQL1dIUHFwYVZvMGpoc3dlTkZaZ1NzMGVFN3dZSTRxQWpFQTJXQjlvdDk4c0lrb0YzdlpZZGQzL1Z0V0I1YjlUTk1lYTdJeC9zdEo1VGZjTExlQUJMRTRCTkpPc1E0dm5CSEoiCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjItMDQtMTNUMjA6MDY6MTUuMDAwWiIKICAgICAgfQogICAgfQogIF0sCiAgImN0bG9ncyI6IFsKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9jdGZlLnNpZ3N0b3JlLmRldi90ZXN0IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUViZndSK1JKdWRYc2NnUkJScEtYMVhGRHkzUHl1ZER4ei9TZm5SaTFmVDhla3BmQmQyTzF1b3o3anIzWjhuS3p4QTY5RVVRK2VGQ0ZJM3pldWJQV1U3dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMTRUMDA6MDA6MDAuMDAwWiIsCiAgICAgICAgICAiZW5kIjogIjIwMjItMTAtMzFUMjM6NTk6NTkuOTk5WiIKICAgICAgICB9CiAgICAgIH0sCiAgICAgICJsb2dJZCI6IHsKICAgICAgICAia2V5SWQiOiAiQ0dDUzhDaFMvMmhGMGRGcko0U2NSV2NZckJZOXd6alNiZWE4SWdZMmIzST0iCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vY3RmZS5zaWdzdG9yZS5kZXYvMjAyMiIsCiAgICAgICJoYXNoQWxnb3JpdGhtIjogIlNIQTJfMjU2IiwKICAgICAgInB1YmxpY0tleSI6IHsKICAgICAgICAicmF3Qnl0ZXMiOiAiTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFaVBTbEZpMENtRlRmRWpDVXFGOUh1Q0VjWVhOS0FhWWFsSUptQlo4eXllelBqVHFoeHJLQnBNbmFvY1Z0TEpCSTFlTTN1WG5RelFHQUpkSjRnczlGeXc9PSIsCiAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICJ2YWxpZEZvciI6IHsKICAgICAgICAgICJzdGFydCI6ICIyMDIyLTEwLTIwVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgfQogICAgICB9LAogICAgICAibG9nSWQiOiB7CiAgICAgICAgImtleUlkIjogIjNUMHdhc2JIRVRKakdSNGNtV2MzQXFKS1hyamVQSzMvaDRweWdDOHA3bzQ9IgogICAgICB9CiAgICB9CiAgXSwKICAidGltZXN0YW1wQXV0aG9yaXRpZXMiOiBbCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAiR2l0SHViLCBJbmMuIiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJJbnRlcm5hbCBTZXJ2aWNlcyBSb290IgogICAgICB9LAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlCM0RDQ0FXS2dBd0lCQWdJVWNoa05zSDM2WGEwNGIxTHFJYytxcjlEVmVjTXdDZ1lJS29aSXpqMEVBd013TWpFVk1CTUdBMVVFQ2hNTVIybDBTSFZpTENCSmJtTXVNUmt3RndZRFZRUURFeEJVVTBFZ2FXNTBaWEp0WldScFlYUmxNQjRYRFRJek1EUXhOREF3TURBd01Gb1hEVEkwTURReE16QXdNREF3TUZvd01qRVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVJrd0Z3WURWUVFERXhCVVUwRWdWR2x0WlhOMFlXMXdhVzVuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFVUQ1Wk5iU3FZTWQ2cjhxcE9PRVg5aWJHblpUOUdzdVhPaHIvZjhVOUZKdWdCR0V4S1lwNDBPVUxTMGVyalpXN3hWOXhWNTJObkpmNU9lRHE0ZTVaS3FOV01GUXdEZ1lEVlIwUEFRSC9CQVFEQWdlQU1CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUlNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVhVzFSdWRPZ1Z0MGxlcVkwV0tZYnVQcjQ3d0F3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl3YlVIOUh2RDRlakNaSk9XUW5xQWxrcVVSbGx2dTlNOCtWcUxiaVJLK3pTZlpDWndzaWxqUm44TVFRUlNrWEVFNUFqRUFnK1Z4cXRvamZWZnU4RGh6emhDeDlHS0VUYkpIYjE5aVY3Mm1NS1ViREFGbXpaNmJROGI1NFpiOHRpZHk1YVdlIgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUNFRENDQVpXZ0F3SUJBZ0lVWDhaTzVRWFA3dk40ZE1RNWU5c1UzbnViOE9nd0NnWUlLb1pJemowRUF3TXdPREVWTUJNR0ExVUVDaE1NUjJsMFNIVmlMQ0JKYm1NdU1SOHdIUVlEVlFRREV4WkpiblJsY201aGJDQlRaWEoyYVdObGN5QlNiMjkwTUI0WERUSXpNRFF4TkRBd01EQXdNRm9YRFRJNE1EUXhNakF3TURBd01Gb3dNakVWTUJNR0ExVUVDaE1NUjJsMFNIVmlMQ0JKYm1NdU1Sa3dGd1lEVlFRREV4QlVVMEVnYVc1MFpYSnRaV1JwWVhSbE1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFdk1MWS9kVFZidklKWUFOQXVzekV3Sm5RRTFsbGZ0eW55TUtJTWhoNDhIbXFiVnI1eWd5YnpzTFJMVktiQldPZFoyMWFlSnorZ1ppeXRaZXRxY3lGOVdsRVI1TkVNZjZKVjdaTm9qUXB4SHE0UkhHb0dTY2VRdi9xdlRpWnhFREtvMll3WkRBT0JnTlZIUThCQWY4RUJBTUNBUVl3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZEJnTlZIUTRFRmdRVWFXMVJ1ZE9nVnQwbGVxWTBXS1lidVByNDd3QXdId1lEVlIwakJCZ3dGb0FVOU5ZWWxvYm5BRzRjMC9xanh5SC9scS93eitRd0NnWUlLb1pJemowRUF3TURhUUF3WmdJeEFLMUIxODV5Z0NySVlGbElzM0dqc3dqbndTTUc2TFk4d29MVmRha0tEWnhWYThmOGNxTXMxRGhjeEowKzA5dzk1UUl4QU8rdEJ6Wms3dmpVSjlpSmdENFI2WldUeFFXS3FObTc0ak85OW8rbzlzdjRGSS9TWlRaVEZ5TW4wSUpFSGRObXlBPT0iCiAgICAgICAgICB9LAogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQjlEQ0NBWHFnQXdJQkFnSVVhL0pBa2RVaks0SlV3c3F0YWlSSkdXaHFMU293Q2dZSUtvWkl6ajBFQXdNd09ERVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVI4d0hRWURWUVFERXhaSmJuUmxjbTVoYkNCVFpYSjJhV05sY3lCU2IyOTBNQjRYRFRJek1EUXhOREF3TURBd01Gb1hEVE16TURReE1UQXdNREF3TUZvd09ERVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVI4d0hRWURWUVFERXhaSmJuUmxjbTVoYkNCVFpYSjJhV05sY3lCU2IyOTBNSFl3RUFZSEtvWkl6ajBDQVFZRks0RUVBQ0lEWWdBRWY5akZBWHh6NGt4NjhBSFJNT2tGQmhmbERjTVR2emFYejR4L0ZDY1hqSi8xcUVLb24vcVBJR25hVVJza0R0eU5iTkRPcGVKVERERnF0NDhpTVBybnpweDZJWndxZW1mVUpONHhCRVpmemErcFl0L2l5b2QrOXRacjIwUlJXU3YvbzBVd1F6QU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFqQWRCZ05WSFE0RUZnUVU5TllZbG9ibkFHNGMwL3FqeHlIL2xxL3d6K1F3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl4QUxaTFo4QmdSWHpLeExNTU45VklsTytlNGhyQm5OQmdGN3R6N0hucm93djJOZXRaRXJJQUNLRnltQmx2V0R2dE1BSXdaTytraTZzc1ExYnNabzk4TzhtRUFmMk5aN2lpQ2dERFUwVndqZWNvNnp5ZWgwekJUczkvN2dWNkFITlE1M3hEIgogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfSwKICAgICAgInZhbGlkRm9yIjogewogICAgICAgICJzdGFydCI6ICIyMDIzLTA0LTE0VDAwOjAwOjAwLjAwMFoiCiAgICAgIH0KICAgIH0KICBdCn0K","registry.npmjs.org%2Fkeys.json":"ewogICAgImtleXMiOiBbCiAgICAgICAgewogICAgICAgICAgICAia2V5SWQiOiAiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLAogICAgICAgICAgICAia2V5VXNhZ2UiOiAibnBtOnNpZ25hdHVyZXMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTFPbGIzek1BRkZ4WEtIaUlrUU81Y0ozWWhsNWk2VVBwK0lodXRlQkpidUhjQTVVb2dLbzBFV3RsV3dXNktTYUtvVE5FWUw3SmxDUWlWbmtoQmt0VWdnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIxOTk5LTAxLTAxVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICAgImtleUlkIjogIlNIQTI1NjpqbDNid3N3dTgwUGpqb2tDZ2gwbzJ3NWMyVTRMaFFBRTU3Z2o5Y3oxa3pBIiwKICAgICAgICAgICAgImtleVVzYWdlIjogIm5wbTphdHRlc3RhdGlvbnMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTFPbGIzek1BRkZ4WEtIaUlrUU81Y0ozWWhsNWk2VVBwK0lodXRlQkpidUhjQTVVb2dLbzBFV3RsV3dXNktTYUtvVE5FWUw3SmxDUWlWbmtoQmt0VWdnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIyMDIyLTEyLTAxVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICBdCn0K"}}} diff --git a/deps/npm/node_modules/@sigstore/verify/dist/tlog/intoto.js b/deps/npm/node_modules/@sigstore/verify/dist/tlog/intoto.js index e706887a95043a..74c7f50d763e1d 100644 --- a/deps/npm/node_modules/@sigstore/verify/dist/tlog/intoto.js +++ b/deps/npm/node_modules/@sigstore/verify/dist/tlog/intoto.js @@ -42,11 +42,12 @@ function verifyIntoto002TLogBody(tlogEntry, content) { // Signature is double-base64-encoded in the tlog entry const tlogSig = base64Decode(tlogEntry.spec.content.envelope.signatures[0].sig); // Ensure that the signature in the bundle's DSSE matches tlog entry - if (!content.compareSignature(Buffer.from(tlogSig, 'base64'))) + if (!content.compareSignature(Buffer.from(tlogSig, 'base64'))) { throw new error_1.VerificationError({ code: 'TLOG_BODY_ERROR', message: 'tlog entry signature mismatch', }); + } // Ensure the digest of the bundle's DSSE payload matches the digest in the // tlog entry const tlogHash = tlogEntry.spec.content.payloadHash?.value || ''; diff --git a/deps/npm/node_modules/@sigstore/verify/dist/trust/index.js b/deps/npm/node_modules/@sigstore/verify/dist/trust/index.js index 7991f351949a00..954de558415902 100644 --- a/deps/npm/node_modules/@sigstore/verify/dist/trust/index.js +++ b/deps/npm/node_modules/@sigstore/verify/dist/trust/index.js @@ -17,6 +17,7 @@ See the License for the specific language governing permissions and limitations under the License. */ const core_1 = require("@sigstore/core"); +const protobuf_specs_1 = require("@sigstore/protobuf-specs"); const error_1 = require("../error"); const BEGINNING_OF_TIME = new Date(0); const END_OF_TIME = new Date(8640000000000000); @@ -35,9 +36,17 @@ function toTrustMaterial(root, keys) { } exports.toTrustMaterial = toTrustMaterial; function createTLogAuthority(tlogInstance) { + const keyDetails = tlogInstance.publicKey.keyDetails; + const keyType = keyDetails === protobuf_specs_1.PublicKeyDetails.PKCS1_RSA_PKCS1V5 || + keyDetails === protobuf_specs_1.PublicKeyDetails.PKIX_RSA_PKCS1V5 || + keyDetails === protobuf_specs_1.PublicKeyDetails.PKIX_RSA_PKCS1V15_2048_SHA256 || + keyDetails === protobuf_specs_1.PublicKeyDetails.PKIX_RSA_PKCS1V15_3072_SHA256 || + keyDetails === protobuf_specs_1.PublicKeyDetails.PKIX_RSA_PKCS1V15_4096_SHA256 + ? 'pkcs1' + : 'spki'; return { logID: tlogInstance.logId.keyId, - publicKey: core_1.crypto.createPublicKey(tlogInstance.publicKey.rawBytes), + publicKey: core_1.crypto.createPublicKey(tlogInstance.publicKey.rawBytes, keyType), validFor: { start: tlogInstance.publicKey.validFor?.start || BEGINNING_OF_TIME, end: tlogInstance.publicKey.validFor?.end || END_OF_TIME, diff --git a/deps/npm/node_modules/@sigstore/verify/package.json b/deps/npm/node_modules/@sigstore/verify/package.json index dcfb587e084a6c..edd6566e10ece7 100644 --- a/deps/npm/node_modules/@sigstore/verify/package.json +++ b/deps/npm/node_modules/@sigstore/verify/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/verify", - "version": "1.1.0", + "version": "1.2.0", "description": "Verification of Sigstore signatures", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -26,9 +26,9 @@ "provenance": true }, "dependencies": { - "@sigstore/protobuf-specs": "^0.3.0", - "@sigstore/bundle": "^2.2.0", - "@sigstore/core": "^1.0.0" + "@sigstore/protobuf-specs": "^0.3.1", + "@sigstore/bundle": "^2.3.1", + "@sigstore/core": "^1.1.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" diff --git a/deps/npm/node_modules/agent-base/LICENSE b/deps/npm/node_modules/agent-base/LICENSE new file mode 100644 index 00000000000000..008728cb51847d --- /dev/null +++ b/deps/npm/node_modules/agent-base/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2013 Nathan Rajlich + +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. \ No newline at end of file diff --git a/deps/npm/node_modules/agent-base/dist/index.js b/deps/npm/node_modules/agent-base/dist/index.js index 7bafc8c68604f3..69396356e74db7 100644 --- a/deps/npm/node_modules/agent-base/dist/index.js +++ b/deps/npm/node_modules/agent-base/dist/index.js @@ -27,7 +27,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Agent = void 0; +const net = __importStar(require("net")); const http = __importStar(require("http")); +const https_1 = require("https"); __exportStar(require("./helpers"), exports); const INTERNAL = Symbol('AgentBaseInternalState'); class Agent extends http.Agent { @@ -64,14 +66,72 @@ class Agent extends http.Agent { .some((l) => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); } + // In order to support async signatures in `connect()` and Node's native + // connection pooling in `http.Agent`, the array of sockets for each origin + // has to be updated synchronously. This is so the length of the array is + // accurate when `addRequest()` is next called. We achieve this by creating a + // fake socket and adding it to `sockets[origin]` and incrementing + // `totalSocketCount`. + incrementSockets(name) { + // If `maxSockets` and `maxTotalSockets` are both Infinity then there is no + // need to create a fake socket because Node.js native connection pooling + // will never be invoked. + if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) { + return null; + } + // All instances of `sockets` are expected TypeScript errors. The + // alternative is to add it as a private property of this class but that + // will break TypeScript subclassing. + if (!this.sockets[name]) { + // @ts-expect-error `sockets` is readonly in `@types/node` + this.sockets[name] = []; + } + const fakeSocket = new net.Socket({ writable: false }); + this.sockets[name].push(fakeSocket); + // @ts-expect-error `totalSocketCount` isn't defined in `@types/node` + this.totalSocketCount++; + return fakeSocket; + } + decrementSockets(name, socket) { + if (!this.sockets[name] || socket === null) { + return; + } + const sockets = this.sockets[name]; + const index = sockets.indexOf(socket); + if (index !== -1) { + sockets.splice(index, 1); + // @ts-expect-error `totalSocketCount` isn't defined in `@types/node` + this.totalSocketCount--; + if (sockets.length === 0) { + // @ts-expect-error `sockets` is readonly in `@types/node` + delete this.sockets[name]; + } + } + } + // In order to properly update the socket pool, we need to call `getName()` on + // the core `https.Agent` if it is a secureEndpoint. + getName(options) { + const secureEndpoint = typeof options.secureEndpoint === 'boolean' + ? options.secureEndpoint + : this.isSecureEndpoint(options); + if (secureEndpoint) { + // @ts-expect-error `getName()` isn't defined in `@types/node` + return https_1.Agent.prototype.getName.call(this, options); + } + // @ts-expect-error `getName()` isn't defined in `@types/node` + return super.getName(options); + } createSocket(req, options, cb) { const connectOpts = { ...options, secureEndpoint: this.isSecureEndpoint(options), }; + const name = this.getName(connectOpts); + const fakeSocket = this.incrementSockets(name); Promise.resolve() .then(() => this.connect(req, connectOpts)) .then((socket) => { + this.decrementSockets(name, fakeSocket); if (socket instanceof http.Agent) { // @ts-expect-error `addRequest()` isn't defined in `@types/node` return socket.addRequest(req, connectOpts); @@ -79,7 +139,10 @@ class Agent extends http.Agent { this[INTERNAL].currentSocket = socket; // @ts-expect-error `createSocket()` isn't defined in `@types/node` super.createSocket(req, options, cb); - }, cb); + }, (err) => { + this.decrementSockets(name, fakeSocket); + cb(err); + }); } createConnection() { const socket = this[INTERNAL].currentSocket; diff --git a/deps/npm/node_modules/agent-base/package.json b/deps/npm/node_modules/agent-base/package.json index 7178f4983f4fb9..8e95171707fef1 100644 --- a/deps/npm/node_modules/agent-base/package.json +++ b/deps/npm/node_modules/agent-base/package.json @@ -1,6 +1,6 @@ { "name": "agent-base", - "version": "7.1.0", + "version": "7.1.1", "description": "Turn a function into an `http.Agent` instance", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/deps/npm/node_modules/are-we-there-yet/LICENSE.md b/deps/npm/node_modules/are-we-there-yet/LICENSE.md deleted file mode 100644 index 845be76f64e789..00000000000000 --- a/deps/npm/node_modules/are-we-there-yet/LICENSE.md +++ /dev/null @@ -1,18 +0,0 @@ -ISC License - -Copyright npm, Inc. - -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 NPM DISCLAIMS ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO -EVENT SHALL NPM 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. diff --git a/deps/npm/node_modules/are-we-there-yet/lib/index.js b/deps/npm/node_modules/are-we-there-yet/lib/index.js deleted file mode 100644 index 57d8743fdad177..00000000000000 --- a/deps/npm/node_modules/are-we-there-yet/lib/index.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict' -exports.TrackerGroup = require('./tracker-group.js') -exports.Tracker = require('./tracker.js') -exports.TrackerStream = require('./tracker-stream.js') diff --git a/deps/npm/node_modules/are-we-there-yet/lib/tracker-base.js b/deps/npm/node_modules/are-we-there-yet/lib/tracker-base.js deleted file mode 100644 index 1b5e0dc30c49bb..00000000000000 --- a/deps/npm/node_modules/are-we-there-yet/lib/tracker-base.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict' -const EventEmitter = require('events') - -let trackerId = 0 -class TrackerBase extends EventEmitter { - constructor (name) { - super() - this.id = ++trackerId - this.name = name - } -} - -module.exports = TrackerBase diff --git a/deps/npm/node_modules/are-we-there-yet/lib/tracker-group.js b/deps/npm/node_modules/are-we-there-yet/lib/tracker-group.js deleted file mode 100644 index 162c22584cdc53..00000000000000 --- a/deps/npm/node_modules/are-we-there-yet/lib/tracker-group.js +++ /dev/null @@ -1,112 +0,0 @@ -'use strict' -const TrackerBase = require('./tracker-base.js') -const Tracker = require('./tracker.js') -const TrackerStream = require('./tracker-stream.js') - -class TrackerGroup extends TrackerBase { - parentGroup = null - trackers = [] - completion = {} - weight = {} - totalWeight = 0 - finished = false - bubbleChange = bubbleChange(this) - - nameInTree () { - var names = [] - var from = this - while (from) { - names.unshift(from.name) - from = from.parentGroup - } - return names.join('/') - } - - addUnit (unit, weight) { - if (unit.addUnit) { - var toTest = this - while (toTest) { - if (unit === toTest) { - throw new Error( - 'Attempted to add tracker group ' + - unit.name + ' to tree that already includes it ' + - this.nameInTree(this)) - } - toTest = toTest.parentGroup - } - unit.parentGroup = this - } - this.weight[unit.id] = weight || 1 - this.totalWeight += this.weight[unit.id] - this.trackers.push(unit) - this.completion[unit.id] = unit.completed() - unit.on('change', this.bubbleChange) - if (!this.finished) { - this.emit('change', unit.name, this.completion[unit.id], unit) - } - return unit - } - - completed () { - if (this.trackers.length === 0) { - return 0 - } - var valPerWeight = 1 / this.totalWeight - var completed = 0 - for (var ii = 0; ii < this.trackers.length; ii++) { - var trackerId = this.trackers[ii].id - completed += - valPerWeight * this.weight[trackerId] * this.completion[trackerId] - } - return completed - } - - newGroup (name, weight) { - return this.addUnit(new TrackerGroup(name), weight) - } - - newItem (name, todo, weight) { - return this.addUnit(new Tracker(name, todo), weight) - } - - newStream (name, todo, weight) { - return this.addUnit(new TrackerStream(name, todo), weight) - } - - finish () { - this.finished = true - if (!this.trackers.length) { - this.addUnit(new Tracker(), 1, true) - } - for (var ii = 0; ii < this.trackers.length; ii++) { - var tracker = this.trackers[ii] - tracker.finish() - tracker.removeListener('change', this.bubbleChange) - } - this.emit('change', this.name, 1, this) - } - - debug (depth = 0) { - const indent = ' '.repeat(depth) - let output = `${indent}${this.name || 'top'}: ${this.completed()}\n` - - this.trackers.forEach(function (tracker) { - output += tracker instanceof TrackerGroup - ? tracker.debug(depth + 1) - : `${indent} ${tracker.name}: ${tracker.completed()}\n` - }) - return output - } -} - -function bubbleChange (trackerGroup) { - return function (name, completed, tracker) { - trackerGroup.completion[tracker.id] = completed - if (trackerGroup.finished) { - return - } - trackerGroup.emit('change', name || trackerGroup.name, trackerGroup.completed(), trackerGroup) - } -} - -module.exports = TrackerGroup diff --git a/deps/npm/node_modules/are-we-there-yet/lib/tracker-stream.js b/deps/npm/node_modules/are-we-there-yet/lib/tracker-stream.js deleted file mode 100644 index 75e44df309150f..00000000000000 --- a/deps/npm/node_modules/are-we-there-yet/lib/tracker-stream.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict' -const stream = require('stream') -const Tracker = require('./tracker.js') - -class TrackerStream extends stream.Transform { - constructor (name, size, options) { - super(options) - this.tracker = new Tracker(name, size) - this.name = name - this.id = this.tracker.id - this.tracker.on('change', this.trackerChange.bind(this)) - } - - trackerChange (name, completion) { - this.emit('change', name, completion, this) - } - - _transform (data, encoding, cb) { - this.tracker.completeWork(data.length ? data.length : 1) - this.push(data) - cb() - } - - _flush (cb) { - this.tracker.finish() - cb() - } - - completed () { - return this.tracker.completed() - } - - addWork (work) { - return this.tracker.addWork(work) - } - - finish () { - return this.tracker.finish() - } -} - -module.exports = TrackerStream diff --git a/deps/npm/node_modules/are-we-there-yet/lib/tracker.js b/deps/npm/node_modules/are-we-there-yet/lib/tracker.js deleted file mode 100644 index 02e879ce6e3e26..00000000000000 --- a/deps/npm/node_modules/are-we-there-yet/lib/tracker.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' -const TrackerBase = require('./tracker-base.js') - -class Tracker extends TrackerBase { - constructor (name, todo) { - super(name) - this.workDone = 0 - this.workTodo = todo || 0 - } - - completed () { - return this.workTodo === 0 ? 0 : this.workDone / this.workTodo - } - - addWork (work) { - this.workTodo += work - this.emit('change', this.name, this.completed(), this) - } - - completeWork (work) { - this.workDone += work - if (this.workDone > this.workTodo) { - this.workDone = this.workTodo - } - this.emit('change', this.name, this.completed(), this) - } - - finish () { - this.workTodo = this.workDone = 1 - this.emit('change', this.name, 1, this) - } -} - -module.exports = Tracker diff --git a/deps/npm/node_modules/binary-extensions/binary-extensions.json b/deps/npm/node_modules/binary-extensions/binary-extensions.json index 4aab3837893a2c..ac08048e40e2df 100644 --- a/deps/npm/node_modules/binary-extensions/binary-extensions.json +++ b/deps/npm/node_modules/binary-extensions/binary-extensions.json @@ -7,6 +7,9 @@ "a", "aac", "adp", + "afdesign", + "afphoto", + "afpub", "ai", "aif", "aiff", diff --git a/deps/npm/node_modules/binary-extensions/license b/deps/npm/node_modules/binary-extensions/license index 401b1c731bcd3e..5493a1a6e3f9a5 100644 --- a/deps/npm/node_modules/binary-extensions/license +++ b/deps/npm/node_modules/binary-extensions/license @@ -1,6 +1,7 @@ MIT License -Copyright (c) 2019 Sindre Sorhus (https://sindresorhus.com), Paul Miller (https://paulmillr.com) +Copyright (c) Sindre Sorhus (https://sindresorhus.com) +Copyright (c) Paul Miller (https://paulmillr.com) 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: diff --git a/deps/npm/node_modules/binary-extensions/package.json b/deps/npm/node_modules/binary-extensions/package.json index c4d3641735b91b..4710c339aeb2d5 100644 --- a/deps/npm/node_modules/binary-extensions/package.json +++ b/deps/npm/node_modules/binary-extensions/package.json @@ -1,14 +1,16 @@ { "name": "binary-extensions", - "version": "2.2.0", + "version": "2.3.0", "description": "List of binary file extensions", "license": "MIT", "repository": "sindresorhus/binary-extensions", + "funding": "https://github.com/sponsors/sindresorhus", "author": { "name": "Sindre Sorhus", "email": "sindresorhus@gmail.com", - "url": "sindresorhus.com" + "url": "https://sindresorhus.com" }, + "sideEffects": false, "engines": { "node": ">=8" }, diff --git a/deps/npm/node_modules/builtins/index.js b/deps/npm/node_modules/builtins/index.js index b715278437cbcf..01d23876aae325 100644 --- a/deps/npm/node_modules/builtins/index.js +++ b/deps/npm/node_modules/builtins/index.js @@ -1,6 +1,6 @@ 'use strict' -const semver = require('semver') +const satisfies = require('semver/functions/satisfies') const permanentModules = [ 'assert', @@ -60,7 +60,7 @@ module.exports = ({ version = process.version, experimental = false } = {}) => { const builtins = [...permanentModules] for (const [name, semverRange] of Object.entries(versionLockedModules)) { - if (version === '*' || semver.satisfies(version, semverRange)) { + if (version === '*' || satisfies(version, semverRange)) { builtins.push(name) } } @@ -69,7 +69,7 @@ module.exports = ({ version = process.version, experimental = false } = {}) => { for (const [name, semverRange] of Object.entries(experimentalModules)) { if ( !builtins.includes(name) && - (version === '*' || semver.satisfies(version, semverRange)) + (version === '*' || satisfies(version, semverRange)) ) { builtins.push(name) } diff --git a/deps/npm/node_modules/builtins/package.json b/deps/npm/node_modules/builtins/package.json index 1c43660c7483fe..d37e02e0768180 100644 --- a/deps/npm/node_modules/builtins/package.json +++ b/deps/npm/node_modules/builtins/package.json @@ -1,20 +1,19 @@ { "name": "builtins", - "version": "5.0.1", + "version": "5.1.0", "description": "List of node.js builtin modules", "repository": "juliangruber/builtins", "license": "MIT", "main": "index.js", "files": [], "scripts": { - "test": "prettier-standard && standard && node-core-test" + "test": "standard --fix && node--test" }, "dependencies": { "semver": "^7.0.0" }, "devDependencies": { - "node-core-test": "^1.4.0", - "prettier-standard": "^15.0.1", - "standard": "^14.3.4" + "standard": "^17.0.0", + "test": "^3.0.0" } } diff --git a/deps/npm/node_modules/cidr-regex/package.json b/deps/npm/node_modules/cidr-regex/package.json index 4f743464075e3e..262da56e2ee676 100644 --- a/deps/npm/node_modules/cidr-regex/package.json +++ b/deps/npm/node_modules/cidr-regex/package.json @@ -1,6 +1,6 @@ { "name": "cidr-regex", - "version": "4.0.3", + "version": "4.0.5", "description": "Regular expression for matching IP addresses in CIDR notation", "author": "silverwind ", "contributors": [ @@ -22,11 +22,12 @@ "ip-regex": "^5.0.0" }, "devDependencies": { - "eslint": "8.37.0", - "eslint-config-silverwind": "65.1.3", - "tsd": "0.28.1", - "updates": "13.2.9", - "versions": "10.4.2", - "vitest": "0.29.8" + "eslint": "8.57.0", + "eslint-config-silverwind": "83.0.1", + "tsd": "0.31.0", + "updates": "16.0.0", + "versions": "12.0.1", + "vitest": "1.4.0", + "vitest-config-silverwind": "7.0.3" } } diff --git a/deps/npm/node_modules/cli-table3/index.js b/deps/npm/node_modules/cli-table3/index.js deleted file mode 100644 index b49d920dd3ef69..00000000000000 --- a/deps/npm/node_modules/cli-table3/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./src/table'); \ No newline at end of file diff --git a/deps/npm/node_modules/cli-table3/package.json b/deps/npm/node_modules/cli-table3/package.json deleted file mode 100644 index 6e84bf66675054..00000000000000 --- a/deps/npm/node_modules/cli-table3/package.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "name": "cli-table3", - "version": "0.6.3", - "description": "Pretty unicode tables for the command line. Based on the original cli-table.", - "main": "index.js", - "types": "index.d.ts", - "files": [ - "src/", - "index.d.ts", - "index.js" - ], - "directories": { - "test": "test" - }, - "dependencies": { - "string-width": "^4.2.0" - }, - "devDependencies": { - "cli-table": "^0.3.1", - "eslint": "^6.0.0", - "eslint-config-prettier": "^6.0.0", - "eslint-plugin-prettier": "^3.0.0", - "jest": "^25.2.4", - "jest-runner-eslint": "^0.7.0", - "lerna-changelog": "^1.0.1", - "prettier": "2.3.2" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - }, - "scripts": { - "changelog": "lerna-changelog", - "docs": "node ./scripts/update-docs.js", - "prettier": "prettier --write '{examples,lib,scripts,src,test}/**/*.js'", - "test": "jest --color", - "test:watch": "jest --color --watchAll --notify" - }, - "repository": { - "type": "git", - "url": "https://github.com/cli-table/cli-table3.git" - }, - "keywords": [ - "node", - "command", - "line", - "cli", - "table", - "tables", - "tabular", - "unicode", - "colors", - "grid" - ], - "author": "James Talmage", - "license": "MIT", - "bugs": { - "url": "https://github.com/cli-table/cli-table3/issues" - }, - "homepage": "https://github.com/cli-table/cli-table3", - "engines": { - "node": "10.* || >= 12.*" - }, - "changelog": { - "repo": "cli-table/cli-table3", - "labels": { - "breaking": ":boom: Breaking Change", - "enhancement": ":rocket: Enhancement", - "bug": ":bug: Bug Fix", - "documentation": ":memo: Documentation", - "internal": ":house: Internal" - } - }, - "jest": { - "projects": [ - { - "displayName": "test", - "testMatch": [ - "/test/**/*.js" - ] - }, - { - "runner": "jest-runner-eslint", - "displayName": "lint", - "testMatch": [ - "/examples/**/*.js", - "/lib/**/*.js", - "/scripts/**/*.js", - "/src/**/*.js", - "/test/**/*.js" - ] - } - ] - }, - "prettier": { - "printWidth": 120, - "tabWidth": 2, - "singleQuote": true, - "trailingComma": "es5" - } -} diff --git a/deps/npm/node_modules/cli-table3/src/cell.js b/deps/npm/node_modules/cli-table3/src/cell.js deleted file mode 100644 index 8c3df35d194076..00000000000000 --- a/deps/npm/node_modules/cli-table3/src/cell.js +++ /dev/null @@ -1,409 +0,0 @@ -const { info, debug } = require('./debug'); -const utils = require('./utils'); - -class Cell { - /** - * A representation of a cell within the table. - * Implementations must have `init` and `draw` methods, - * as well as `colSpan`, `rowSpan`, `desiredHeight` and `desiredWidth` properties. - * @param options - * @constructor - */ - constructor(options) { - this.setOptions(options); - - /** - * Each cell will have it's `x` and `y` values set by the `layout-manager` prior to - * `init` being called; - * @type {Number} - */ - this.x = null; - this.y = null; - } - - setOptions(options) { - if (['boolean', 'number', 'string'].indexOf(typeof options) !== -1) { - options = { content: '' + options }; - } - options = options || {}; - this.options = options; - let content = options.content; - if (['boolean', 'number', 'string'].indexOf(typeof content) !== -1) { - this.content = String(content); - } else if (!content) { - this.content = this.options.href || ''; - } else { - throw new Error('Content needs to be a primitive, got: ' + typeof content); - } - this.colSpan = options.colSpan || 1; - this.rowSpan = options.rowSpan || 1; - if (this.options.href) { - Object.defineProperty(this, 'href', { - get() { - return this.options.href; - }, - }); - } - } - - mergeTableOptions(tableOptions, cells) { - this.cells = cells; - - let optionsChars = this.options.chars || {}; - let tableChars = tableOptions.chars; - let chars = (this.chars = {}); - CHAR_NAMES.forEach(function (name) { - setOption(optionsChars, tableChars, name, chars); - }); - - this.truncate = this.options.truncate || tableOptions.truncate; - - let style = (this.options.style = this.options.style || {}); - let tableStyle = tableOptions.style; - setOption(style, tableStyle, 'padding-left', this); - setOption(style, tableStyle, 'padding-right', this); - this.head = style.head || tableStyle.head; - this.border = style.border || tableStyle.border; - - this.fixedWidth = tableOptions.colWidths[this.x]; - this.lines = this.computeLines(tableOptions); - - this.desiredWidth = utils.strlen(this.content) + this.paddingLeft + this.paddingRight; - this.desiredHeight = this.lines.length; - } - - computeLines(tableOptions) { - const tableWordWrap = tableOptions.wordWrap || tableOptions.textWrap; - const { wordWrap = tableWordWrap } = this.options; - if (this.fixedWidth && wordWrap) { - this.fixedWidth -= this.paddingLeft + this.paddingRight; - if (this.colSpan) { - let i = 1; - while (i < this.colSpan) { - this.fixedWidth += tableOptions.colWidths[this.x + i]; - i++; - } - } - const { wrapOnWordBoundary: tableWrapOnWordBoundary = true } = tableOptions; - const { wrapOnWordBoundary = tableWrapOnWordBoundary } = this.options; - return this.wrapLines(utils.wordWrap(this.fixedWidth, this.content, wrapOnWordBoundary)); - } - return this.wrapLines(this.content.split('\n')); - } - - wrapLines(computedLines) { - const lines = utils.colorizeLines(computedLines); - if (this.href) { - return lines.map((line) => utils.hyperlink(this.href, line)); - } - return lines; - } - - /** - * Initializes the Cells data structure. - * - * @param tableOptions - A fully populated set of tableOptions. - * In addition to the standard default values, tableOptions must have fully populated the - * `colWidths` and `rowWidths` arrays. Those arrays must have lengths equal to the number - * of columns or rows (respectively) in this table, and each array item must be a Number. - * - */ - init(tableOptions) { - let x = this.x; - let y = this.y; - this.widths = tableOptions.colWidths.slice(x, x + this.colSpan); - this.heights = tableOptions.rowHeights.slice(y, y + this.rowSpan); - this.width = this.widths.reduce(sumPlusOne, -1); - this.height = this.heights.reduce(sumPlusOne, -1); - - this.hAlign = this.options.hAlign || tableOptions.colAligns[x]; - this.vAlign = this.options.vAlign || tableOptions.rowAligns[y]; - - this.drawRight = x + this.colSpan == tableOptions.colWidths.length; - } - - /** - * Draws the given line of the cell. - * This default implementation defers to methods `drawTop`, `drawBottom`, `drawLine` and `drawEmpty`. - * @param lineNum - can be `top`, `bottom` or a numerical line number. - * @param spanningCell - will be a number if being called from a RowSpanCell, and will represent how - * many rows below it's being called from. Otherwise it's undefined. - * @returns {String} The representation of this line. - */ - draw(lineNum, spanningCell) { - if (lineNum == 'top') return this.drawTop(this.drawRight); - if (lineNum == 'bottom') return this.drawBottom(this.drawRight); - let content = utils.truncate(this.content, 10, this.truncate); - if (!lineNum) { - info(`${this.y}-${this.x}: ${this.rowSpan - lineNum}x${this.colSpan} Cell ${content}`); - } else { - // debug(`${lineNum}-${this.x}: 1x${this.colSpan} RowSpanCell ${content}`); - } - let padLen = Math.max(this.height - this.lines.length, 0); - let padTop; - switch (this.vAlign) { - case 'center': - padTop = Math.ceil(padLen / 2); - break; - case 'bottom': - padTop = padLen; - break; - default: - padTop = 0; - } - if (lineNum < padTop || lineNum >= padTop + this.lines.length) { - return this.drawEmpty(this.drawRight, spanningCell); - } - let forceTruncation = this.lines.length > this.height && lineNum + 1 >= this.height; - return this.drawLine(lineNum - padTop, this.drawRight, forceTruncation, spanningCell); - } - - /** - * Renders the top line of the cell. - * @param drawRight - true if this method should render the right edge of the cell. - * @returns {String} - */ - drawTop(drawRight) { - let content = []; - if (this.cells) { - //TODO: cells should always exist - some tests don't fill it in though - this.widths.forEach(function (width, index) { - content.push(this._topLeftChar(index)); - content.push(utils.repeat(this.chars[this.y == 0 ? 'top' : 'mid'], width)); - }, this); - } else { - content.push(this._topLeftChar(0)); - content.push(utils.repeat(this.chars[this.y == 0 ? 'top' : 'mid'], this.width)); - } - if (drawRight) { - content.push(this.chars[this.y == 0 ? 'topRight' : 'rightMid']); - } - return this.wrapWithStyleColors('border', content.join('')); - } - - _topLeftChar(offset) { - let x = this.x + offset; - let leftChar; - if (this.y == 0) { - leftChar = x == 0 ? 'topLeft' : offset == 0 ? 'topMid' : 'top'; - } else { - if (x == 0) { - leftChar = 'leftMid'; - } else { - leftChar = offset == 0 ? 'midMid' : 'bottomMid'; - if (this.cells) { - //TODO: cells should always exist - some tests don't fill it in though - let spanAbove = this.cells[this.y - 1][x] instanceof Cell.ColSpanCell; - if (spanAbove) { - leftChar = offset == 0 ? 'topMid' : 'mid'; - } - if (offset == 0) { - let i = 1; - while (this.cells[this.y][x - i] instanceof Cell.ColSpanCell) { - i++; - } - if (this.cells[this.y][x - i] instanceof Cell.RowSpanCell) { - leftChar = 'leftMid'; - } - } - } - } - } - return this.chars[leftChar]; - } - - wrapWithStyleColors(styleProperty, content) { - if (this[styleProperty] && this[styleProperty].length) { - try { - let colors = require('@colors/colors/safe'); - for (let i = this[styleProperty].length - 1; i >= 0; i--) { - colors = colors[this[styleProperty][i]]; - } - return colors(content); - } catch (e) { - return content; - } - } else { - return content; - } - } - - /** - * Renders a line of text. - * @param lineNum - Which line of text to render. This is not necessarily the line within the cell. - * There may be top-padding above the first line of text. - * @param drawRight - true if this method should render the right edge of the cell. - * @param forceTruncationSymbol - `true` if the rendered text should end with the truncation symbol even - * if the text fits. This is used when the cell is vertically truncated. If `false` the text should - * only include the truncation symbol if the text will not fit horizontally within the cell width. - * @param spanningCell - a number of if being called from a RowSpanCell. (how many rows below). otherwise undefined. - * @returns {String} - */ - drawLine(lineNum, drawRight, forceTruncationSymbol, spanningCell) { - let left = this.chars[this.x == 0 ? 'left' : 'middle']; - if (this.x && spanningCell && this.cells) { - let cellLeft = this.cells[this.y + spanningCell][this.x - 1]; - while (cellLeft instanceof ColSpanCell) { - cellLeft = this.cells[cellLeft.y][cellLeft.x - 1]; - } - if (!(cellLeft instanceof RowSpanCell)) { - left = this.chars['rightMid']; - } - } - let leftPadding = utils.repeat(' ', this.paddingLeft); - let right = drawRight ? this.chars['right'] : ''; - let rightPadding = utils.repeat(' ', this.paddingRight); - let line = this.lines[lineNum]; - let len = this.width - (this.paddingLeft + this.paddingRight); - if (forceTruncationSymbol) line += this.truncate || '…'; - let content = utils.truncate(line, len, this.truncate); - content = utils.pad(content, len, ' ', this.hAlign); - content = leftPadding + content + rightPadding; - return this.stylizeLine(left, content, right); - } - - stylizeLine(left, content, right) { - left = this.wrapWithStyleColors('border', left); - right = this.wrapWithStyleColors('border', right); - if (this.y === 0) { - content = this.wrapWithStyleColors('head', content); - } - return left + content + right; - } - - /** - * Renders the bottom line of the cell. - * @param drawRight - true if this method should render the right edge of the cell. - * @returns {String} - */ - drawBottom(drawRight) { - let left = this.chars[this.x == 0 ? 'bottomLeft' : 'bottomMid']; - let content = utils.repeat(this.chars.bottom, this.width); - let right = drawRight ? this.chars['bottomRight'] : ''; - return this.wrapWithStyleColors('border', left + content + right); - } - - /** - * Renders a blank line of text within the cell. Used for top and/or bottom padding. - * @param drawRight - true if this method should render the right edge of the cell. - * @param spanningCell - a number of if being called from a RowSpanCell. (how many rows below). otherwise undefined. - * @returns {String} - */ - drawEmpty(drawRight, spanningCell) { - let left = this.chars[this.x == 0 ? 'left' : 'middle']; - if (this.x && spanningCell && this.cells) { - let cellLeft = this.cells[this.y + spanningCell][this.x - 1]; - while (cellLeft instanceof ColSpanCell) { - cellLeft = this.cells[cellLeft.y][cellLeft.x - 1]; - } - if (!(cellLeft instanceof RowSpanCell)) { - left = this.chars['rightMid']; - } - } - let right = drawRight ? this.chars['right'] : ''; - let content = utils.repeat(' ', this.width); - return this.stylizeLine(left, content, right); - } -} - -class ColSpanCell { - /** - * A Cell that doesn't do anything. It just draws empty lines. - * Used as a placeholder in column spanning. - * @constructor - */ - constructor() {} - - draw(lineNum) { - if (typeof lineNum === 'number') { - debug(`${this.y}-${this.x}: 1x1 ColSpanCell`); - } - return ''; - } - - init() {} - - mergeTableOptions() {} -} - -class RowSpanCell { - /** - * A placeholder Cell for a Cell that spans multiple rows. - * It delegates rendering to the original cell, but adds the appropriate offset. - * @param originalCell - * @constructor - */ - constructor(originalCell) { - this.originalCell = originalCell; - } - - init(tableOptions) { - let y = this.y; - let originalY = this.originalCell.y; - this.cellOffset = y - originalY; - this.offset = findDimension(tableOptions.rowHeights, originalY, this.cellOffset); - } - - draw(lineNum) { - if (lineNum == 'top') { - return this.originalCell.draw(this.offset, this.cellOffset); - } - if (lineNum == 'bottom') { - return this.originalCell.draw('bottom'); - } - debug(`${this.y}-${this.x}: 1x${this.colSpan} RowSpanCell for ${this.originalCell.content}`); - return this.originalCell.draw(this.offset + 1 + lineNum); - } - - mergeTableOptions() {} -} - -function firstDefined(...args) { - return args.filter((v) => v !== undefined && v !== null).shift(); -} - -// HELPER FUNCTIONS -function setOption(objA, objB, nameB, targetObj) { - let nameA = nameB.split('-'); - if (nameA.length > 1) { - nameA[1] = nameA[1].charAt(0).toUpperCase() + nameA[1].substr(1); - nameA = nameA.join(''); - targetObj[nameA] = firstDefined(objA[nameA], objA[nameB], objB[nameA], objB[nameB]); - } else { - targetObj[nameB] = firstDefined(objA[nameB], objB[nameB]); - } -} - -function findDimension(dimensionTable, startingIndex, span) { - let ret = dimensionTable[startingIndex]; - for (let i = 1; i < span; i++) { - ret += 1 + dimensionTable[startingIndex + i]; - } - return ret; -} - -function sumPlusOne(a, b) { - return a + b + 1; -} - -let CHAR_NAMES = [ - 'top', - 'top-mid', - 'top-left', - 'top-right', - 'bottom', - 'bottom-mid', - 'bottom-left', - 'bottom-right', - 'left', - 'left-mid', - 'mid', - 'mid-mid', - 'right', - 'right-mid', - 'middle', -]; - -module.exports = Cell; -module.exports.ColSpanCell = ColSpanCell; -module.exports.RowSpanCell = RowSpanCell; diff --git a/deps/npm/node_modules/cli-table3/src/debug.js b/deps/npm/node_modules/cli-table3/src/debug.js deleted file mode 100644 index 6acfb030321597..00000000000000 --- a/deps/npm/node_modules/cli-table3/src/debug.js +++ /dev/null @@ -1,28 +0,0 @@ -let messages = []; -let level = 0; - -const debug = (msg, min) => { - if (level >= min) { - messages.push(msg); - } -}; - -debug.WARN = 1; -debug.INFO = 2; -debug.DEBUG = 3; - -debug.reset = () => { - messages = []; -}; - -debug.setDebugLevel = (v) => { - level = v; -}; - -debug.warn = (msg) => debug(msg, debug.WARN); -debug.info = (msg) => debug(msg, debug.INFO); -debug.debug = (msg) => debug(msg, debug.DEBUG); - -debug.debugMessages = () => messages; - -module.exports = debug; diff --git a/deps/npm/node_modules/cli-table3/src/layout-manager.js b/deps/npm/node_modules/cli-table3/src/layout-manager.js deleted file mode 100644 index 3937452274d721..00000000000000 --- a/deps/npm/node_modules/cli-table3/src/layout-manager.js +++ /dev/null @@ -1,254 +0,0 @@ -const { warn, debug } = require('./debug'); -const Cell = require('./cell'); -const { ColSpanCell, RowSpanCell } = Cell; - -(function () { - function next(alloc, col) { - if (alloc[col] > 0) { - return next(alloc, col + 1); - } - return col; - } - - function layoutTable(table) { - let alloc = {}; - table.forEach(function (row, rowIndex) { - let col = 0; - row.forEach(function (cell) { - cell.y = rowIndex; - // Avoid erroneous call to next() on first row - cell.x = rowIndex ? next(alloc, col) : col; - const rowSpan = cell.rowSpan || 1; - const colSpan = cell.colSpan || 1; - if (rowSpan > 1) { - for (let cs = 0; cs < colSpan; cs++) { - alloc[cell.x + cs] = rowSpan; - } - } - col = cell.x + colSpan; - }); - Object.keys(alloc).forEach((idx) => { - alloc[idx]--; - if (alloc[idx] < 1) delete alloc[idx]; - }); - }); - } - - function maxWidth(table) { - let mw = 0; - table.forEach(function (row) { - row.forEach(function (cell) { - mw = Math.max(mw, cell.x + (cell.colSpan || 1)); - }); - }); - return mw; - } - - function maxHeight(table) { - return table.length; - } - - function cellsConflict(cell1, cell2) { - let yMin1 = cell1.y; - let yMax1 = cell1.y - 1 + (cell1.rowSpan || 1); - let yMin2 = cell2.y; - let yMax2 = cell2.y - 1 + (cell2.rowSpan || 1); - let yConflict = !(yMin1 > yMax2 || yMin2 > yMax1); - - let xMin1 = cell1.x; - let xMax1 = cell1.x - 1 + (cell1.colSpan || 1); - let xMin2 = cell2.x; - let xMax2 = cell2.x - 1 + (cell2.colSpan || 1); - let xConflict = !(xMin1 > xMax2 || xMin2 > xMax1); - - return yConflict && xConflict; - } - - function conflictExists(rows, x, y) { - let i_max = Math.min(rows.length - 1, y); - let cell = { x: x, y: y }; - for (let i = 0; i <= i_max; i++) { - let row = rows[i]; - for (let j = 0; j < row.length; j++) { - if (cellsConflict(cell, row[j])) { - return true; - } - } - } - return false; - } - - function allBlank(rows, y, xMin, xMax) { - for (let x = xMin; x < xMax; x++) { - if (conflictExists(rows, x, y)) { - return false; - } - } - return true; - } - - function addRowSpanCells(table) { - table.forEach(function (row, rowIndex) { - row.forEach(function (cell) { - for (let i = 1; i < cell.rowSpan; i++) { - let rowSpanCell = new RowSpanCell(cell); - rowSpanCell.x = cell.x; - rowSpanCell.y = cell.y + i; - rowSpanCell.colSpan = cell.colSpan; - insertCell(rowSpanCell, table[rowIndex + i]); - } - }); - }); - } - - function addColSpanCells(cellRows) { - for (let rowIndex = cellRows.length - 1; rowIndex >= 0; rowIndex--) { - let cellColumns = cellRows[rowIndex]; - for (let columnIndex = 0; columnIndex < cellColumns.length; columnIndex++) { - let cell = cellColumns[columnIndex]; - for (let k = 1; k < cell.colSpan; k++) { - let colSpanCell = new ColSpanCell(); - colSpanCell.x = cell.x + k; - colSpanCell.y = cell.y; - cellColumns.splice(columnIndex + 1, 0, colSpanCell); - } - } - } - } - - function insertCell(cell, row) { - let x = 0; - while (x < row.length && row[x].x < cell.x) { - x++; - } - row.splice(x, 0, cell); - } - - function fillInTable(table) { - let h_max = maxHeight(table); - let w_max = maxWidth(table); - debug(`Max rows: ${h_max}; Max cols: ${w_max}`); - for (let y = 0; y < h_max; y++) { - for (let x = 0; x < w_max; x++) { - if (!conflictExists(table, x, y)) { - let opts = { x: x, y: y, colSpan: 1, rowSpan: 1 }; - x++; - while (x < w_max && !conflictExists(table, x, y)) { - opts.colSpan++; - x++; - } - let y2 = y + 1; - while (y2 < h_max && allBlank(table, y2, opts.x, opts.x + opts.colSpan)) { - opts.rowSpan++; - y2++; - } - let cell = new Cell(opts); - cell.x = opts.x; - cell.y = opts.y; - warn(`Missing cell at ${cell.y}-${cell.x}.`); - insertCell(cell, table[y]); - } - } - } - } - - function generateCells(rows) { - return rows.map(function (row) { - if (!Array.isArray(row)) { - let key = Object.keys(row)[0]; - row = row[key]; - if (Array.isArray(row)) { - row = row.slice(); - row.unshift(key); - } else { - row = [key, row]; - } - } - return row.map(function (cell) { - return new Cell(cell); - }); - }); - } - - function makeTableLayout(rows) { - let cellRows = generateCells(rows); - layoutTable(cellRows); - fillInTable(cellRows); - addRowSpanCells(cellRows); - addColSpanCells(cellRows); - return cellRows; - } - - module.exports = { - makeTableLayout: makeTableLayout, - layoutTable: layoutTable, - addRowSpanCells: addRowSpanCells, - maxWidth: maxWidth, - fillInTable: fillInTable, - computeWidths: makeComputeWidths('colSpan', 'desiredWidth', 'x', 1), - computeHeights: makeComputeWidths('rowSpan', 'desiredHeight', 'y', 1), - }; -})(); - -function makeComputeWidths(colSpan, desiredWidth, x, forcedMin) { - return function (vals, table) { - let result = []; - let spanners = []; - let auto = {}; - table.forEach(function (row) { - row.forEach(function (cell) { - if ((cell[colSpan] || 1) > 1) { - spanners.push(cell); - } else { - result[cell[x]] = Math.max(result[cell[x]] || 0, cell[desiredWidth] || 0, forcedMin); - } - }); - }); - - vals.forEach(function (val, index) { - if (typeof val === 'number') { - result[index] = val; - } - }); - - //spanners.forEach(function(cell){ - for (let k = spanners.length - 1; k >= 0; k--) { - let cell = spanners[k]; - let span = cell[colSpan]; - let col = cell[x]; - let existingWidth = result[col]; - let editableCols = typeof vals[col] === 'number' ? 0 : 1; - if (typeof existingWidth === 'number') { - for (let i = 1; i < span; i++) { - existingWidth += 1 + result[col + i]; - if (typeof vals[col + i] !== 'number') { - editableCols++; - } - } - } else { - existingWidth = desiredWidth === 'desiredWidth' ? cell.desiredWidth - 1 : 1; - if (!auto[col] || auto[col] < existingWidth) { - auto[col] = existingWidth; - } - } - - if (cell[desiredWidth] > existingWidth) { - let i = 0; - while (editableCols > 0 && cell[desiredWidth] > existingWidth) { - if (typeof vals[col + i] !== 'number') { - let dif = Math.round((cell[desiredWidth] - existingWidth) / editableCols); - existingWidth += dif; - result[col + i] += dif; - editableCols--; - } - i++; - } - } - } - - Object.assign(vals, result, auto); - for (let j = 0; j < vals.length; j++) { - vals[j] = Math.max(forcedMin, vals[j] || 0); - } - }; -} diff --git a/deps/npm/node_modules/cli-table3/src/table.js b/deps/npm/node_modules/cli-table3/src/table.js deleted file mode 100644 index eb4a9bda9a3649..00000000000000 --- a/deps/npm/node_modules/cli-table3/src/table.js +++ /dev/null @@ -1,106 +0,0 @@ -const debug = require('./debug'); -const utils = require('./utils'); -const tableLayout = require('./layout-manager'); - -class Table extends Array { - constructor(opts) { - super(); - - const options = utils.mergeOptions(opts); - Object.defineProperty(this, 'options', { - value: options, - enumerable: options.debug, - }); - - if (options.debug) { - switch (typeof options.debug) { - case 'boolean': - debug.setDebugLevel(debug.WARN); - break; - case 'number': - debug.setDebugLevel(options.debug); - break; - case 'string': - debug.setDebugLevel(parseInt(options.debug, 10)); - break; - default: - debug.setDebugLevel(debug.WARN); - debug.warn(`Debug option is expected to be boolean, number, or string. Received a ${typeof options.debug}`); - } - Object.defineProperty(this, 'messages', { - get() { - return debug.debugMessages(); - }, - }); - } - } - - toString() { - let array = this; - let headersPresent = this.options.head && this.options.head.length; - if (headersPresent) { - array = [this.options.head]; - if (this.length) { - array.push.apply(array, this); - } - } else { - this.options.style.head = []; - } - - let cells = tableLayout.makeTableLayout(array); - - cells.forEach(function (row) { - row.forEach(function (cell) { - cell.mergeTableOptions(this.options, cells); - }, this); - }, this); - - tableLayout.computeWidths(this.options.colWidths, cells); - tableLayout.computeHeights(this.options.rowHeights, cells); - - cells.forEach(function (row) { - row.forEach(function (cell) { - cell.init(this.options); - }, this); - }, this); - - let result = []; - - for (let rowIndex = 0; rowIndex < cells.length; rowIndex++) { - let row = cells[rowIndex]; - let heightOfRow = this.options.rowHeights[rowIndex]; - - if (rowIndex === 0 || !this.options.style.compact || (rowIndex == 1 && headersPresent)) { - doDraw(row, 'top', result); - } - - for (let lineNum = 0; lineNum < heightOfRow; lineNum++) { - doDraw(row, lineNum, result); - } - - if (rowIndex + 1 == cells.length) { - doDraw(row, 'bottom', result); - } - } - - return result.join('\n'); - } - - get width() { - let str = this.toString().split('\n'); - return str[0].length; - } -} - -Table.reset = () => debug.reset(); - -function doDraw(row, lineNum, result) { - let line = []; - row.forEach(function (cell) { - line.push(cell.draw(lineNum)); - }); - let str = line.join(''); - if (str.length) result.push(str); -} - -module.exports = Table; diff --git a/deps/npm/node_modules/cli-table3/src/utils.js b/deps/npm/node_modules/cli-table3/src/utils.js deleted file mode 100644 index c922c5b9adb62c..00000000000000 --- a/deps/npm/node_modules/cli-table3/src/utils.js +++ /dev/null @@ -1,336 +0,0 @@ -const stringWidth = require('string-width'); - -function codeRegex(capture) { - return capture ? /\u001b\[((?:\d*;){0,5}\d*)m/g : /\u001b\[(?:\d*;){0,5}\d*m/g; -} - -function strlen(str) { - let code = codeRegex(); - let stripped = ('' + str).replace(code, ''); - let split = stripped.split('\n'); - return split.reduce(function (memo, s) { - return stringWidth(s) > memo ? stringWidth(s) : memo; - }, 0); -} - -function repeat(str, times) { - return Array(times + 1).join(str); -} - -function pad(str, len, pad, dir) { - let length = strlen(str); - if (len + 1 >= length) { - let padlen = len - length; - switch (dir) { - case 'right': { - str = repeat(pad, padlen) + str; - break; - } - case 'center': { - let right = Math.ceil(padlen / 2); - let left = padlen - right; - str = repeat(pad, left) + str + repeat(pad, right); - break; - } - default: { - str = str + repeat(pad, padlen); - break; - } - } - } - return str; -} - -let codeCache = {}; - -function addToCodeCache(name, on, off) { - on = '\u001b[' + on + 'm'; - off = '\u001b[' + off + 'm'; - codeCache[on] = { set: name, to: true }; - codeCache[off] = { set: name, to: false }; - codeCache[name] = { on: on, off: off }; -} - -//https://github.com/Marak/colors.js/blob/master/lib/styles.js -addToCodeCache('bold', 1, 22); -addToCodeCache('italics', 3, 23); -addToCodeCache('underline', 4, 24); -addToCodeCache('inverse', 7, 27); -addToCodeCache('strikethrough', 9, 29); - -function updateState(state, controlChars) { - let controlCode = controlChars[1] ? parseInt(controlChars[1].split(';')[0]) : 0; - if ((controlCode >= 30 && controlCode <= 39) || (controlCode >= 90 && controlCode <= 97)) { - state.lastForegroundAdded = controlChars[0]; - return; - } - if ((controlCode >= 40 && controlCode <= 49) || (controlCode >= 100 && controlCode <= 107)) { - state.lastBackgroundAdded = controlChars[0]; - return; - } - if (controlCode === 0) { - for (let i in state) { - /* istanbul ignore else */ - if (Object.prototype.hasOwnProperty.call(state, i)) { - delete state[i]; - } - } - return; - } - let info = codeCache[controlChars[0]]; - if (info) { - state[info.set] = info.to; - } -} - -function readState(line) { - let code = codeRegex(true); - let controlChars = code.exec(line); - let state = {}; - while (controlChars !== null) { - updateState(state, controlChars); - controlChars = code.exec(line); - } - return state; -} - -function unwindState(state, ret) { - let lastBackgroundAdded = state.lastBackgroundAdded; - let lastForegroundAdded = state.lastForegroundAdded; - - delete state.lastBackgroundAdded; - delete state.lastForegroundAdded; - - Object.keys(state).forEach(function (key) { - if (state[key]) { - ret += codeCache[key].off; - } - }); - - if (lastBackgroundAdded && lastBackgroundAdded != '\u001b[49m') { - ret += '\u001b[49m'; - } - if (lastForegroundAdded && lastForegroundAdded != '\u001b[39m') { - ret += '\u001b[39m'; - } - - return ret; -} - -function rewindState(state, ret) { - let lastBackgroundAdded = state.lastBackgroundAdded; - let lastForegroundAdded = state.lastForegroundAdded; - - delete state.lastBackgroundAdded; - delete state.lastForegroundAdded; - - Object.keys(state).forEach(function (key) { - if (state[key]) { - ret = codeCache[key].on + ret; - } - }); - - if (lastBackgroundAdded && lastBackgroundAdded != '\u001b[49m') { - ret = lastBackgroundAdded + ret; - } - if (lastForegroundAdded && lastForegroundAdded != '\u001b[39m') { - ret = lastForegroundAdded + ret; - } - - return ret; -} - -function truncateWidth(str, desiredLength) { - if (str.length === strlen(str)) { - return str.substr(0, desiredLength); - } - - while (strlen(str) > desiredLength) { - str = str.slice(0, -1); - } - - return str; -} - -function truncateWidthWithAnsi(str, desiredLength) { - let code = codeRegex(true); - let split = str.split(codeRegex()); - let splitIndex = 0; - let retLen = 0; - let ret = ''; - let myArray; - let state = {}; - - while (retLen < desiredLength) { - myArray = code.exec(str); - let toAdd = split[splitIndex]; - splitIndex++; - if (retLen + strlen(toAdd) > desiredLength) { - toAdd = truncateWidth(toAdd, desiredLength - retLen); - } - ret += toAdd; - retLen += strlen(toAdd); - - if (retLen < desiredLength) { - if (!myArray) { - break; - } // full-width chars may cause a whitespace which cannot be filled - ret += myArray[0]; - updateState(state, myArray); - } - } - - return unwindState(state, ret); -} - -function truncate(str, desiredLength, truncateChar) { - truncateChar = truncateChar || '…'; - let lengthOfStr = strlen(str); - if (lengthOfStr <= desiredLength) { - return str; - } - desiredLength -= strlen(truncateChar); - - let ret = truncateWidthWithAnsi(str, desiredLength); - - return ret + truncateChar; -} - -function defaultOptions() { - return { - chars: { - top: '─', - 'top-mid': '┬', - 'top-left': '┌', - 'top-right': '┐', - bottom: '─', - 'bottom-mid': '┴', - 'bottom-left': '└', - 'bottom-right': '┘', - left: '│', - 'left-mid': '├', - mid: '─', - 'mid-mid': '┼', - right: '│', - 'right-mid': '┤', - middle: '│', - }, - truncate: '…', - colWidths: [], - rowHeights: [], - colAligns: [], - rowAligns: [], - style: { - 'padding-left': 1, - 'padding-right': 1, - head: ['red'], - border: ['grey'], - compact: false, - }, - head: [], - }; -} - -function mergeOptions(options, defaults) { - options = options || {}; - defaults = defaults || defaultOptions(); - let ret = Object.assign({}, defaults, options); - ret.chars = Object.assign({}, defaults.chars, options.chars); - ret.style = Object.assign({}, defaults.style, options.style); - return ret; -} - -// Wrap on word boundary -function wordWrap(maxLength, input) { - let lines = []; - let split = input.split(/(\s+)/g); - let line = []; - let lineLength = 0; - let whitespace; - for (let i = 0; i < split.length; i += 2) { - let word = split[i]; - let newLength = lineLength + strlen(word); - if (lineLength > 0 && whitespace) { - newLength += whitespace.length; - } - if (newLength > maxLength) { - if (lineLength !== 0) { - lines.push(line.join('')); - } - line = [word]; - lineLength = strlen(word); - } else { - line.push(whitespace || '', word); - lineLength = newLength; - } - whitespace = split[i + 1]; - } - if (lineLength) { - lines.push(line.join('')); - } - return lines; -} - -// Wrap text (ignoring word boundaries) -function textWrap(maxLength, input) { - let lines = []; - let line = ''; - function pushLine(str, ws) { - if (line.length && ws) line += ws; - line += str; - while (line.length > maxLength) { - lines.push(line.slice(0, maxLength)); - line = line.slice(maxLength); - } - } - let split = input.split(/(\s+)/g); - for (let i = 0; i < split.length; i += 2) { - pushLine(split[i], i && split[i - 1]); - } - if (line.length) lines.push(line); - return lines; -} - -function multiLineWordWrap(maxLength, input, wrapOnWordBoundary = true) { - let output = []; - input = input.split('\n'); - const handler = wrapOnWordBoundary ? wordWrap : textWrap; - for (let i = 0; i < input.length; i++) { - output.push.apply(output, handler(maxLength, input[i])); - } - return output; -} - -function colorizeLines(input) { - let state = {}; - let output = []; - for (let i = 0; i < input.length; i++) { - let line = rewindState(state, input[i]); - state = readState(line); - let temp = Object.assign({}, state); - output.push(unwindState(temp, line)); - } - return output; -} - -/** - * Credit: Matheus Sampaio https://github.com/matheussampaio - */ -function hyperlink(url, text) { - const OSC = '\u001B]'; - const BEL = '\u0007'; - const SEP = ';'; - - return [OSC, '8', SEP, SEP, url || text, BEL, text, OSC, '8', SEP, SEP, BEL].join(''); -} - -module.exports = { - strlen: strlen, - repeat: repeat, - pad: pad, - truncate: truncate, - mergeOptions: mergeOptions, - wordWrap: multiLineWordWrap, - colorizeLines: colorizeLines, - hyperlink, -}; diff --git a/deps/npm/node_modules/clone/LICENSE b/deps/npm/node_modules/clone/LICENSE deleted file mode 100644 index cc3c87bc3bfd85..00000000000000 --- a/deps/npm/node_modules/clone/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -Copyright © 2011-2015 Paul Vorbach - -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, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/deps/npm/node_modules/clone/clone.iml b/deps/npm/node_modules/clone/clone.iml deleted file mode 100644 index 30de8aee9ba303..00000000000000 --- a/deps/npm/node_modules/clone/clone.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/deps/npm/node_modules/clone/clone.js b/deps/npm/node_modules/clone/clone.js deleted file mode 100644 index ba200c2f99288d..00000000000000 --- a/deps/npm/node_modules/clone/clone.js +++ /dev/null @@ -1,166 +0,0 @@ -var clone = (function() { -'use strict'; - -/** - * Clones (copies) an Object using deep copying. - * - * This function supports circular references by default, but if you are certain - * there are no circular references in your object, you can save some CPU time - * by calling clone(obj, false). - * - * Caution: if `circular` is false and `parent` contains circular references, - * your program may enter an infinite loop and crash. - * - * @param `parent` - the object to be cloned - * @param `circular` - set to true if the object to be cloned may contain - * circular references. (optional - true by default) - * @param `depth` - set to a number if the object is only to be cloned to - * a particular depth. (optional - defaults to Infinity) - * @param `prototype` - sets the prototype to be used when cloning an object. - * (optional - defaults to parent prototype). -*/ -function clone(parent, circular, depth, prototype) { - var filter; - if (typeof circular === 'object') { - depth = circular.depth; - prototype = circular.prototype; - filter = circular.filter; - circular = circular.circular - } - // maintain two arrays for circular references, where corresponding parents - // and children have the same index - var allParents = []; - var allChildren = []; - - var useBuffer = typeof Buffer != 'undefined'; - - if (typeof circular == 'undefined') - circular = true; - - if (typeof depth == 'undefined') - depth = Infinity; - - // recurse this function so we don't reset allParents and allChildren - function _clone(parent, depth) { - // cloning null always returns null - if (parent === null) - return null; - - if (depth == 0) - return parent; - - var child; - var proto; - if (typeof parent != 'object') { - return parent; - } - - if (clone.__isArray(parent)) { - child = []; - } else if (clone.__isRegExp(parent)) { - child = new RegExp(parent.source, __getRegExpFlags(parent)); - if (parent.lastIndex) child.lastIndex = parent.lastIndex; - } else if (clone.__isDate(parent)) { - child = new Date(parent.getTime()); - } else if (useBuffer && Buffer.isBuffer(parent)) { - if (Buffer.allocUnsafe) { - // Node.js >= 4.5.0 - child = Buffer.allocUnsafe(parent.length); - } else { - // Older Node.js versions - child = new Buffer(parent.length); - } - parent.copy(child); - return child; - } else { - if (typeof prototype == 'undefined') { - proto = Object.getPrototypeOf(parent); - child = Object.create(proto); - } - else { - child = Object.create(prototype); - proto = prototype; - } - } - - if (circular) { - var index = allParents.indexOf(parent); - - if (index != -1) { - return allChildren[index]; - } - allParents.push(parent); - allChildren.push(child); - } - - for (var i in parent) { - var attrs; - if (proto) { - attrs = Object.getOwnPropertyDescriptor(proto, i); - } - - if (attrs && attrs.set == null) { - continue; - } - child[i] = _clone(parent[i], depth - 1); - } - - return child; - } - - return _clone(parent, depth); -} - -/** - * Simple flat clone using prototype, accepts only objects, usefull for property - * override on FLAT configuration object (no nested props). - * - * USE WITH CAUTION! This may not behave as you wish if you do not know how this - * works. - */ -clone.clonePrototype = function clonePrototype(parent) { - if (parent === null) - return null; - - var c = function () {}; - c.prototype = parent; - return new c(); -}; - -// private utility functions - -function __objToStr(o) { - return Object.prototype.toString.call(o); -}; -clone.__objToStr = __objToStr; - -function __isDate(o) { - return typeof o === 'object' && __objToStr(o) === '[object Date]'; -}; -clone.__isDate = __isDate; - -function __isArray(o) { - return typeof o === 'object' && __objToStr(o) === '[object Array]'; -}; -clone.__isArray = __isArray; - -function __isRegExp(o) { - return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; -}; -clone.__isRegExp = __isRegExp; - -function __getRegExpFlags(re) { - var flags = ''; - if (re.global) flags += 'g'; - if (re.ignoreCase) flags += 'i'; - if (re.multiline) flags += 'm'; - return flags; -}; -clone.__getRegExpFlags = __getRegExpFlags; - -return clone; -})(); - -if (typeof module === 'object' && module.exports) { - module.exports = clone; -} diff --git a/deps/npm/node_modules/clone/package.json b/deps/npm/node_modules/clone/package.json deleted file mode 100644 index 3ddd242f4a5108..00000000000000 --- a/deps/npm/node_modules/clone/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "clone", - "description": "deep cloning of objects and arrays", - "tags": [ - "clone", - "object", - "array", - "function", - "date" - ], - "version": "1.0.4", - "repository": { - "type": "git", - "url": "git://github.com/pvorb/node-clone.git" - }, - "bugs": { - "url": "https://github.com/pvorb/node-clone/issues" - }, - "main": "clone.js", - "author": "Paul Vorbach (http://paul.vorba.ch/)", - "contributors": [ - "Blake Miner (http://www.blakeminer.com/)", - "Tian You (http://blog.axqd.net/)", - "George Stagas (http://stagas.com/)", - "Tobiasz Cudnik (https://github.com/TobiaszCudnik)", - "Pavel Lang (https://github.com/langpavel)", - "Dan MacTough (http://yabfog.com/)", - "w1nk (https://github.com/w1nk)", - "Hugh Kennedy (http://twitter.com/hughskennedy)", - "Dustin Diaz (http://dustindiaz.com)", - "Ilya Shaisultanov (https://github.com/diversario)", - "Nathan MacInnes (http://macinn.es/)", - "Benjamin E. Coe (https://twitter.com/benjamincoe)", - "Nathan Zadoks (https://github.com/nathan7)", - "Róbert Oroszi (https://github.com/oroce)", - "Aurélio A. Heckert (http://softwarelivre.org/aurium)", - "Guy Ellis (http://www.guyellisrocks.com/)" - ], - "license": "MIT", - "engines": { - "node": ">=0.8" - }, - "dependencies": {}, - "devDependencies": { - "nodeunit": "~0.9.0" - }, - "optionalDependencies": {}, - "scripts": { - "test": "nodeunit test.js" - } -} diff --git a/deps/npm/node_modules/color-support/README.md b/deps/npm/node_modules/color-support/README.md deleted file mode 100644 index f89aa17d3526a3..00000000000000 --- a/deps/npm/node_modules/color-support/README.md +++ /dev/null @@ -1,129 +0,0 @@ -# color-support - -A module which will endeavor to guess your terminal's level of color -support. - -[![Build Status](https://travis-ci.org/isaacs/color-support.svg?branch=master)](https://travis-ci.org/isaacs/color-support) [![Coverage Status](https://coveralls.io/repos/github/isaacs/color-support/badge.svg?branch=master)](https://coveralls.io/github/isaacs/color-support?branch=master) - -This is similar to `supports-color`, but it does not read -`process.argv`. - -1. If not in a node environment, not supported. - -2. If stdout is not a TTY, not supported, unless the `ignoreTTY` - option is set. - -3. If the `TERM` environ is `dumb`, not supported, unless the - `ignoreDumb` option is set. - -4. If on Windows, then support 16 colors. - -5. If using Tmux, then support 256 colors. - -7. Handle continuous-integration servers. If `CI` or - `TEAMCITY_VERSION` are set in the environment, and `TRAVIS` is not - set, then color is not supported, unless `ignoreCI` option is set. - -6. Guess based on the `TERM_PROGRAM` environ. These terminals support - 16m colors: - - - `iTerm.app` version 3.x supports 16m colors, below support 256 - - `MacTerm` supports 16m colors - - `Apple_Terminal` supports 256 colors - - Have more things that belong on this list? Send a PR! - -8. Make a guess based on the `TERM` environment variable. Any - `xterm-256color` will get 256 colors. Any screen, xterm, vt100, - color, ansi, cygwin, or linux `TERM` will get 16 colors. - -9. If `COLORTERM` environment variable is set, then support 16 colors. - -10. At this point, we assume that color is not supported. - -## USAGE - -```javascript -var testColorSupport = require('color-support') -var colorSupport = testColorSupport(/* options object */) - -if (!colorSupport) { - console.log('color is not supported') -} else if (colorSupport.has16m) { - console.log('\x1b[38;2;102;194;255m16m colors\x1b[0m') -} else if (colorSupport.has256) { - console.log('\x1b[38;5;119m256 colors\x1b[0m') -} else if (colorSupport.hasBasic) { - console.log('\x1b[31mbasic colors\x1b[0m') -} else { - console.log('this is impossible, but colors are not supported') -} -``` - -If you don't have any options to set, you can also just look at the -flags which will all be set on the test function itself. (Of course, -this doesn't return a falsey value when colors aren't supported, and -doesn't allow you to set options.) - -```javascript -var colorSupport = require('color-support') - -if (colorSupport.has16m) { - console.log('\x1b[38;2;102;194;255m16m colors\x1b[0m') -} else if (colorSupport.has256) { - console.log('\x1b[38;5;119m256 colors\x1b[0m') -} else if (colorSupport.hasBasic) { - console.log('\x1b[31mbasic colors\x1b[0m') -} else { - console.log('colors are not supported') -} -``` - -## Options - -You can pass in the following options. - -* ignoreTTY - default false. Ignore the `isTTY` check. -* ignoreDumb - default false. Ignore `TERM=dumb` environ check. -* ignoreCI - default false. Ignore `CI` environ check. -* env - Object for environment vars. Defaults to `process.env`. -* stream - Stream for `isTTY` check. Defaults to `process.stdout`. -* term - String for `TERM` checking. Defaults to `env.TERM`. -* alwaysReturn - default false. Return an object when colors aren't - supported (instead of returning `false`). -* level - A number from 0 to 3. This will return a result for the - specified level. This is useful if you want to be able to set the - color support level explicitly as a number in an environment - variable or config, but then use the object flags in your program. - Except for `alwaysReturn` to return an object for level 0, all other - options are ignored, since no checking is done if a level is - explicitly set. - -## Return Value - -If no color support is available, then `false` is returned by default, -unless the `alwaysReturn` flag is set to `true`. This is so that the -simple question of "can I use colors or not" can treat any truthy -return as "yes". - -Otherwise, the return object has the following fields: - -* `level` - A number from 0 to 3 - * `0` - No color support - * `1` - Basic (16) color support - * `2` - 256 color support - * `3` - 16 million (true) color support -* `hasBasic` - Boolean -* `has256` - Boolean -* `has16m` - Boolean - -## CLI - -You can run the `color-support` bin from the command line which will -just dump the values as this module calculates them in whatever env -it's run. It takes no command line arguments. - -## Credits - -This is a spiritual, if not actual, fork of -[supports-color](http://npm.im/supports-color) by the ever prolific -[Sindre Sorhus](http://npm.im/~sindresorhus). diff --git a/deps/npm/node_modules/color-support/bin.js b/deps/npm/node_modules/color-support/bin.js deleted file mode 100755 index 3c0a9672180835..00000000000000 --- a/deps/npm/node_modules/color-support/bin.js +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node -var colorSupport = require('./')({alwaysReturn: true }) -console.log(JSON.stringify(colorSupport, null, 2)) diff --git a/deps/npm/node_modules/color-support/browser.js b/deps/npm/node_modules/color-support/browser.js deleted file mode 100644 index ab5c6631a35b80..00000000000000 --- a/deps/npm/node_modules/color-support/browser.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = colorSupport({ alwaysReturn: true }, colorSupport) - -function colorSupport(options, obj) { - obj = obj || {} - options = options || {} - obj.level = 0 - obj.hasBasic = false - obj.has256 = false - obj.has16m = false - if (!options.alwaysReturn) { - return false - } - return obj -} diff --git a/deps/npm/node_modules/color-support/index.js b/deps/npm/node_modules/color-support/index.js deleted file mode 100644 index 6b6f3b28194243..00000000000000 --- a/deps/npm/node_modules/color-support/index.js +++ /dev/null @@ -1,134 +0,0 @@ -// call it on itself so we can test the export val for basic stuff -module.exports = colorSupport({ alwaysReturn: true }, colorSupport) - -function hasNone (obj, options) { - obj.level = 0 - obj.hasBasic = false - obj.has256 = false - obj.has16m = false - if (!options.alwaysReturn) { - return false - } - return obj -} - -function hasBasic (obj) { - obj.hasBasic = true - obj.has256 = false - obj.has16m = false - obj.level = 1 - return obj -} - -function has256 (obj) { - obj.hasBasic = true - obj.has256 = true - obj.has16m = false - obj.level = 2 - return obj -} - -function has16m (obj) { - obj.hasBasic = true - obj.has256 = true - obj.has16m = true - obj.level = 3 - return obj -} - -function colorSupport (options, obj) { - options = options || {} - - obj = obj || {} - - // if just requesting a specific level, then return that. - if (typeof options.level === 'number') { - switch (options.level) { - case 0: - return hasNone(obj, options) - case 1: - return hasBasic(obj) - case 2: - return has256(obj) - case 3: - return has16m(obj) - } - } - - obj.level = 0 - obj.hasBasic = false - obj.has256 = false - obj.has16m = false - - if (typeof process === 'undefined' || - !process || - !process.stdout || - !process.env || - !process.platform) { - return hasNone(obj, options) - } - - var env = options.env || process.env - var stream = options.stream || process.stdout - var term = options.term || env.TERM || '' - var platform = options.platform || process.platform - - if (!options.ignoreTTY && !stream.isTTY) { - return hasNone(obj, options) - } - - if (!options.ignoreDumb && term === 'dumb' && !env.COLORTERM) { - return hasNone(obj, options) - } - - if (platform === 'win32') { - return hasBasic(obj) - } - - if (env.TMUX) { - return has256(obj) - } - - if (!options.ignoreCI && (env.CI || env.TEAMCITY_VERSION)) { - if (env.TRAVIS) { - return has256(obj) - } else { - return hasNone(obj, options) - } - } - - // TODO: add more term programs - switch (env.TERM_PROGRAM) { - case 'iTerm.app': - var ver = env.TERM_PROGRAM_VERSION || '0.' - if (/^[0-2]\./.test(ver)) { - return has256(obj) - } else { - return has16m(obj) - } - - case 'HyperTerm': - case 'Hyper': - return has16m(obj) - - case 'MacTerm': - return has16m(obj) - - case 'Apple_Terminal': - return has256(obj) - } - - if (/^xterm-256/.test(term)) { - return has256(obj) - } - - if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(term)) { - return hasBasic(obj) - } - - if (env.COLORTERM) { - return hasBasic(obj) - } - - return hasNone(obj, options) -} diff --git a/deps/npm/node_modules/color-support/package.json b/deps/npm/node_modules/color-support/package.json deleted file mode 100644 index f3e3b77145d6ba..00000000000000 --- a/deps/npm/node_modules/color-support/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "color-support", - "version": "1.1.3", - "description": "A module which will endeavor to guess your terminal's level of color support.", - "main": "index.js", - "browser": "browser.js", - "bin": "bin.js", - "devDependencies": { - "tap": "^10.3.3" - }, - "scripts": { - "test": "tap test/*.js --100 -J", - "preversion": "npm test", - "postversion": "npm publish", - "postpublish": "git push origin --all; git push origin --tags" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/isaacs/color-support.git" - }, - "keywords": [ - "terminal", - "color", - "support", - "xterm", - "truecolor", - "256" - ], - "author": "Isaac Z. Schlueter (http://blog.izs.me/)", - "license": "ISC", - "files": [ - "browser.js", - "index.js", - "bin.js" - ] -} diff --git a/deps/npm/node_modules/columnify/LICENSE b/deps/npm/node_modules/columnify/LICENSE deleted file mode 100644 index ed47678e61c408..00000000000000 --- a/deps/npm/node_modules/columnify/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Tim Oxley - -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. diff --git a/deps/npm/node_modules/columnify/Makefile b/deps/npm/node_modules/columnify/Makefile deleted file mode 100644 index 3a67c57a3b1e08..00000000000000 --- a/deps/npm/node_modules/columnify/Makefile +++ /dev/null @@ -1,9 +0,0 @@ - -all: columnify.js - -prepublish: all - -columnify.js: index.js package.json - babel index.js > columnify.js - -.PHONY: all prepublish diff --git a/deps/npm/node_modules/columnify/columnify.js b/deps/npm/node_modules/columnify/columnify.js deleted file mode 100644 index dcef9236e18436..00000000000000 --- a/deps/npm/node_modules/columnify/columnify.js +++ /dev/null @@ -1,306 +0,0 @@ -"use strict"; - -var wcwidth = require('./width'); - -var _require = require('./utils'), - padRight = _require.padRight, - padCenter = _require.padCenter, - padLeft = _require.padLeft, - splitIntoLines = _require.splitIntoLines, - splitLongWords = _require.splitLongWords, - truncateString = _require.truncateString; - -var DEFAULT_HEADING_TRANSFORM = function DEFAULT_HEADING_TRANSFORM(key) { - return key.toUpperCase(); -}; - -var DEFAULT_DATA_TRANSFORM = function DEFAULT_DATA_TRANSFORM(cell, column, index) { - return cell; -}; - -var DEFAULTS = Object.freeze({ - maxWidth: Infinity, - minWidth: 0, - columnSplitter: ' ', - truncate: false, - truncateMarker: '…', - preserveNewLines: false, - paddingChr: ' ', - showHeaders: true, - headingTransform: DEFAULT_HEADING_TRANSFORM, - dataTransform: DEFAULT_DATA_TRANSFORM -}); - -module.exports = function (items) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - - var columnConfigs = options.config || {}; - delete options.config; // remove config so doesn't appear on every column. - - var maxLineWidth = options.maxLineWidth || Infinity; - if (maxLineWidth === 'auto') maxLineWidth = process.stdout.columns || Infinity; - delete options.maxLineWidth; // this is a line control option, don't pass it to column - - // Option defaults inheritance: - // options.config[columnName] => options => DEFAULTS - options = mixin({}, DEFAULTS, options); - - options.config = options.config || Object.create(null); - - options.spacing = options.spacing || '\n'; // probably useless - options.preserveNewLines = !!options.preserveNewLines; - options.showHeaders = !!options.showHeaders; - options.columns = options.columns || options.include; // alias include/columns, prefer columns if supplied - var columnNames = options.columns || []; // optional user-supplied columns to include - - items = toArray(items, columnNames); - - // if not suppled column names, automatically determine columns from data keys - if (!columnNames.length) { - items.forEach(function (item) { - for (var columnName in item) { - if (columnNames.indexOf(columnName) === -1) columnNames.push(columnName); - } - }); - } - - // initialize column defaults (each column inherits from options.config) - var columns = columnNames.reduce(function (columns, columnName) { - var column = Object.create(options); - columns[columnName] = mixin(column, columnConfigs[columnName]); - return columns; - }, Object.create(null)); - - // sanitize column settings - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - column.name = columnName; - column.maxWidth = Math.ceil(column.maxWidth); - column.minWidth = Math.ceil(column.minWidth); - column.truncate = !!column.truncate; - column.align = column.align || 'left'; - }); - - // sanitize data - items = items.map(function (item) { - var result = Object.create(null); - columnNames.forEach(function (columnName) { - // null/undefined -> '' - result[columnName] = item[columnName] != null ? item[columnName] : ''; - // toString everything - result[columnName] = '' + result[columnName]; - if (columns[columnName].preserveNewLines) { - // merge non-newline whitespace chars - result[columnName] = result[columnName].replace(/[^\S\n]/gmi, ' '); - } else { - // merge all whitespace chars - result[columnName] = result[columnName].replace(/\s/gmi, ' '); - } - }); - return result; - }); - - // transform data cells - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - items = items.map(function (item, index) { - var col = Object.create(column); - item[columnName] = column.dataTransform(item[columnName], col, index); - - var changedKeys = Object.keys(col); - // disable default heading transform if we wrote to column.name - if (changedKeys.indexOf('name') !== -1) { - if (column.headingTransform !== DEFAULT_HEADING_TRANSFORM) return; - column.headingTransform = function (heading) { - return heading; - }; - } - changedKeys.forEach(function (key) { - return column[key] = col[key]; - }); - return item; - }); - }); - - // add headers - var headers = {}; - if (options.showHeaders) { - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - - if (!column.showHeaders) { - headers[columnName] = ''; - return; - } - - headers[columnName] = column.headingTransform(column.name); - }); - items.unshift(headers); - } - // get actual max-width between min & max - // based on length of data in columns - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - column.width = items.map(function (item) { - return item[columnName]; - }).reduce(function (min, cur) { - // if already at maxWidth don't bother testing - if (min >= column.maxWidth) return min; - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur)))); - }, 0); - }); - - // split long words so they can break onto multiple lines - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - items = items.map(function (item) { - item[columnName] = splitLongWords(item[columnName], column.width, column.truncateMarker); - return item; - }); - }); - - // wrap long lines. each item is now an array of lines. - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - items = items.map(function (item, index) { - var cell = item[columnName]; - item[columnName] = splitIntoLines(cell, column.width); - - // if truncating required, only include first line + add truncation char - if (column.truncate && item[columnName].length > 1) { - item[columnName] = splitIntoLines(cell, column.width - wcwidth(column.truncateMarker)); - var firstLine = item[columnName][0]; - if (!endsWith(firstLine, column.truncateMarker)) item[columnName][0] += column.truncateMarker; - item[columnName] = item[columnName].slice(0, 1); - } - return item; - }); - }); - - // recalculate column widths from truncated output/lines - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - column.width = items.map(function (item) { - return item[columnName].reduce(function (min, cur) { - if (min >= column.maxWidth) return min; - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur)))); - }, 0); - }).reduce(function (min, cur) { - if (min >= column.maxWidth) return min; - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, cur))); - }, 0); - }); - - var rows = createRows(items, columns, columnNames, options.paddingChr); // merge lines into rows - // conceive output - return rows.reduce(function (output, row) { - return output.concat(row.reduce(function (rowOut, line) { - return rowOut.concat(line.join(options.columnSplitter)); - }, [])); - }, []).map(function (line) { - return truncateString(line, maxLineWidth); - }).join(options.spacing); -}; - -/** - * Convert wrapped lines into rows with padded values. - * - * @param Array items data to process - * @param Array columns column width settings for wrapping - * @param Array columnNames column ordering - * @return Array items wrapped in arrays, corresponding to lines - */ - -function createRows(items, columns, columnNames, paddingChr) { - return items.map(function (item) { - var row = []; - var numLines = 0; - columnNames.forEach(function (columnName) { - numLines = Math.max(numLines, item[columnName].length); - }); - // combine matching lines of each rows - - var _loop = function _loop(i) { - row[i] = row[i] || []; - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - var val = item[columnName][i] || ''; // || '' ensures empty columns get padded - if (column.align === 'right') row[i].push(padLeft(val, column.width, paddingChr));else if (column.align === 'center' || column.align === 'centre') row[i].push(padCenter(val, column.width, paddingChr));else row[i].push(padRight(val, column.width, paddingChr)); - }); - }; - - for (var i = 0; i < numLines; i++) { - _loop(i); - } - return row; - }); -} - -/** - * Object.assign - * - * @return Object Object with properties mixed in. - */ - -function mixin() { - if (Object.assign) return Object.assign.apply(Object, arguments); - return ObjectAssign.apply(undefined, arguments); -} - -function ObjectAssign(target, firstSource) { - "use strict"; - - if (target === undefined || target === null) throw new TypeError("Cannot convert first argument to object"); - - var to = Object(target); - - var hasPendingException = false; - var pendingException; - - for (var i = 1; i < arguments.length; i++) { - var nextSource = arguments[i]; - if (nextSource === undefined || nextSource === null) continue; - - var keysArray = Object.keys(Object(nextSource)); - for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { - var nextKey = keysArray[nextIndex]; - try { - var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); - if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey]; - } catch (e) { - if (!hasPendingException) { - hasPendingException = true; - pendingException = e; - } - } - } - - if (hasPendingException) throw pendingException; - } - return to; -} - -/** - * Adapted from String.prototype.endsWith polyfill. - */ - -function endsWith(target, searchString, position) { - position = position || target.length; - position = position - searchString.length; - var lastIndex = target.lastIndexOf(searchString); - return lastIndex !== -1 && lastIndex === position; -} - -function toArray(items, columnNames) { - if (Array.isArray(items)) return items; - var rows = []; - for (var key in items) { - var item = {}; - item[columnNames[0] || 'key'] = key; - item[columnNames[1] || 'value'] = items[key]; - rows.push(item); - } - return rows; -} - diff --git a/deps/npm/node_modules/columnify/index.js b/deps/npm/node_modules/columnify/index.js deleted file mode 100644 index 221269b3e76b72..00000000000000 --- a/deps/npm/node_modules/columnify/index.js +++ /dev/null @@ -1,297 +0,0 @@ -"use strict" - -const wcwidth = require('./width') -const { - padRight, - padCenter, - padLeft, - splitIntoLines, - splitLongWords, - truncateString -} = require('./utils') - -const DEFAULT_HEADING_TRANSFORM = key => key.toUpperCase() - -const DEFAULT_DATA_TRANSFORM = (cell, column, index) => cell - -const DEFAULTS = Object.freeze({ - maxWidth: Infinity, - minWidth: 0, - columnSplitter: ' ', - truncate: false, - truncateMarker: '…', - preserveNewLines: false, - paddingChr: ' ', - showHeaders: true, - headingTransform: DEFAULT_HEADING_TRANSFORM, - dataTransform: DEFAULT_DATA_TRANSFORM -}) - -module.exports = function(items, options = {}) { - - let columnConfigs = options.config || {} - delete options.config // remove config so doesn't appear on every column. - - let maxLineWidth = options.maxLineWidth || Infinity - if (maxLineWidth === 'auto') maxLineWidth = process.stdout.columns || Infinity - delete options.maxLineWidth // this is a line control option, don't pass it to column - - // Option defaults inheritance: - // options.config[columnName] => options => DEFAULTS - options = mixin({}, DEFAULTS, options) - - options.config = options.config || Object.create(null) - - options.spacing = options.spacing || '\n' // probably useless - options.preserveNewLines = !!options.preserveNewLines - options.showHeaders = !!options.showHeaders; - options.columns = options.columns || options.include // alias include/columns, prefer columns if supplied - let columnNames = options.columns || [] // optional user-supplied columns to include - - items = toArray(items, columnNames) - - // if not suppled column names, automatically determine columns from data keys - if (!columnNames.length) { - items.forEach(function(item) { - for (let columnName in item) { - if (columnNames.indexOf(columnName) === -1) columnNames.push(columnName) - } - }) - } - - // initialize column defaults (each column inherits from options.config) - let columns = columnNames.reduce((columns, columnName) => { - let column = Object.create(options) - columns[columnName] = mixin(column, columnConfigs[columnName]) - return columns - }, Object.create(null)) - - // sanitize column settings - columnNames.forEach(columnName => { - let column = columns[columnName] - column.name = columnName - column.maxWidth = Math.ceil(column.maxWidth) - column.minWidth = Math.ceil(column.minWidth) - column.truncate = !!column.truncate - column.align = column.align || 'left' - }) - - // sanitize data - items = items.map(item => { - let result = Object.create(null) - columnNames.forEach(columnName => { - // null/undefined -> '' - result[columnName] = item[columnName] != null ? item[columnName] : '' - // toString everything - result[columnName] = '' + result[columnName] - if (columns[columnName].preserveNewLines) { - // merge non-newline whitespace chars - result[columnName] = result[columnName].replace(/[^\S\n]/gmi, ' ') - } else { - // merge all whitespace chars - result[columnName] = result[columnName].replace(/\s/gmi, ' ') - } - }) - return result - }) - - // transform data cells - columnNames.forEach(columnName => { - let column = columns[columnName] - items = items.map((item, index) => { - let col = Object.create(column) - item[columnName] = column.dataTransform(item[columnName], col, index) - - let changedKeys = Object.keys(col) - // disable default heading transform if we wrote to column.name - if (changedKeys.indexOf('name') !== -1) { - if (column.headingTransform !== DEFAULT_HEADING_TRANSFORM) return - column.headingTransform = heading => heading - } - changedKeys.forEach(key => column[key] = col[key]) - return item - }) - }) - - // add headers - let headers = {} - if(options.showHeaders) { - columnNames.forEach(columnName => { - let column = columns[columnName] - - if(!column.showHeaders){ - headers[columnName] = ''; - return; - } - - headers[columnName] = column.headingTransform(column.name) - }) - items.unshift(headers) - } - // get actual max-width between min & max - // based on length of data in columns - columnNames.forEach(columnName => { - let column = columns[columnName] - column.width = items - .map(item => item[columnName]) - .reduce((min, cur) => { - // if already at maxWidth don't bother testing - if (min >= column.maxWidth) return min - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur)))) - }, 0) - }) - - // split long words so they can break onto multiple lines - columnNames.forEach(columnName => { - let column = columns[columnName] - items = items.map(item => { - item[columnName] = splitLongWords(item[columnName], column.width, column.truncateMarker) - return item - }) - }) - - // wrap long lines. each item is now an array of lines. - columnNames.forEach(columnName => { - let column = columns[columnName] - items = items.map((item, index) => { - let cell = item[columnName] - item[columnName] = splitIntoLines(cell, column.width) - - // if truncating required, only include first line + add truncation char - if (column.truncate && item[columnName].length > 1) { - item[columnName] = splitIntoLines(cell, column.width - wcwidth(column.truncateMarker)) - let firstLine = item[columnName][0] - if (!endsWith(firstLine, column.truncateMarker)) item[columnName][0] += column.truncateMarker - item[columnName] = item[columnName].slice(0, 1) - } - return item - }) - }) - - // recalculate column widths from truncated output/lines - columnNames.forEach(columnName => { - let column = columns[columnName] - column.width = items.map(item => { - return item[columnName].reduce((min, cur) => { - if (min >= column.maxWidth) return min - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur)))) - }, 0) - }).reduce((min, cur) => { - if (min >= column.maxWidth) return min - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, cur))) - }, 0) - }) - - - let rows = createRows(items, columns, columnNames, options.paddingChr) // merge lines into rows - // conceive output - return rows.reduce((output, row) => { - return output.concat(row.reduce((rowOut, line) => { - return rowOut.concat(line.join(options.columnSplitter)) - }, [])) - }, []) - .map(line => truncateString(line, maxLineWidth)) - .join(options.spacing) -} - -/** - * Convert wrapped lines into rows with padded values. - * - * @param Array items data to process - * @param Array columns column width settings for wrapping - * @param Array columnNames column ordering - * @return Array items wrapped in arrays, corresponding to lines - */ - -function createRows(items, columns, columnNames, paddingChr) { - return items.map(item => { - let row = [] - let numLines = 0 - columnNames.forEach(columnName => { - numLines = Math.max(numLines, item[columnName].length) - }) - // combine matching lines of each rows - for (let i = 0; i < numLines; i++) { - row[i] = row[i] || [] - columnNames.forEach(columnName => { - let column = columns[columnName] - let val = item[columnName][i] || '' // || '' ensures empty columns get padded - if (column.align === 'right') row[i].push(padLeft(val, column.width, paddingChr)) - else if (column.align === 'center' || column.align === 'centre') row[i].push(padCenter(val, column.width, paddingChr)) - else row[i].push(padRight(val, column.width, paddingChr)) - }) - } - return row - }) -} - -/** - * Object.assign - * - * @return Object Object with properties mixed in. - */ - -function mixin(...args) { - if (Object.assign) return Object.assign(...args) - return ObjectAssign(...args) -} - -function ObjectAssign(target, firstSource) { - "use strict"; - if (target === undefined || target === null) - throw new TypeError("Cannot convert first argument to object"); - - var to = Object(target); - - var hasPendingException = false; - var pendingException; - - for (var i = 1; i < arguments.length; i++) { - var nextSource = arguments[i]; - if (nextSource === undefined || nextSource === null) - continue; - - var keysArray = Object.keys(Object(nextSource)); - for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { - var nextKey = keysArray[nextIndex]; - try { - var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); - if (desc !== undefined && desc.enumerable) - to[nextKey] = nextSource[nextKey]; - } catch (e) { - if (!hasPendingException) { - hasPendingException = true; - pendingException = e; - } - } - } - - if (hasPendingException) - throw pendingException; - } - return to; -} - -/** - * Adapted from String.prototype.endsWith polyfill. - */ - -function endsWith(target, searchString, position) { - position = position || target.length; - position = position - searchString.length; - let lastIndex = target.lastIndexOf(searchString); - return lastIndex !== -1 && lastIndex === position; -} - - -function toArray(items, columnNames) { - if (Array.isArray(items)) return items - let rows = [] - for (let key in items) { - let item = {} - item[columnNames[0] || 'key'] = key - item[columnNames[1] || 'value'] = items[key] - rows.push(item) - } - return rows -} diff --git a/deps/npm/node_modules/columnify/package.json b/deps/npm/node_modules/columnify/package.json deleted file mode 100644 index 29565407a8cd7b..00000000000000 --- a/deps/npm/node_modules/columnify/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "columnify", - "version": "1.6.0", - "description": "Render data in text columns. Supports in-column text-wrap.", - "main": "columnify.js", - "scripts": { - "pretest": "npm prune", - "test": "make prepublish && tape test/*.js | tap-spec", - "bench": "npm test && node bench", - "prepublish": "make prepublish" - }, - "babel": { - "presets": [ - "es2015" - ] - }, - "author": "Tim Oxley", - "license": "MIT", - "devDependencies": { - "babel-cli": "^6.26.0", - "babel-preset-es2015": "^6.3.13", - "chalk": "^1.1.1", - "tap-spec": "^5.0.0", - "tape": "^4.4.0" - }, - "repository": { - "type": "git", - "url": "git://github.com/timoxley/columnify.git" - }, - "keywords": [ - "column", - "text", - "ansi", - "console", - "terminal", - "wrap", - "table" - ], - "bugs": { - "url": "https://github.com/timoxley/columnify/issues" - }, - "homepage": "https://github.com/timoxley/columnify", - "engines": { - "node": ">=8.0.0" - }, - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - }, - "directories": { - "test": "test" - } -} diff --git a/deps/npm/node_modules/columnify/utils.js b/deps/npm/node_modules/columnify/utils.js deleted file mode 100644 index df3e6cc44e8561..00000000000000 --- a/deps/npm/node_modules/columnify/utils.js +++ /dev/null @@ -1,193 +0,0 @@ -"use strict" - -var wcwidth = require('./width') - -/** - * repeat string `str` up to total length of `len` - * - * @param String str string to repeat - * @param Number len total length of output string - */ - -function repeatString(str, len) { - return Array.apply(null, {length: len + 1}).join(str).slice(0, len) -} - -/** - * Pad `str` up to total length `max` with `chr`. - * If `str` is longer than `max`, padRight will return `str` unaltered. - * - * @param String str string to pad - * @param Number max total length of output string - * @param String chr optional. Character to pad with. default: ' ' - * @return String padded str - */ - -function padRight(str, max, chr) { - str = str != null ? str : '' - str = String(str) - var length = max - wcwidth(str) - if (length <= 0) return str - return str + repeatString(chr || ' ', length) -} - -/** - * Pad `str` up to total length `max` with `chr`. - * If `str` is longer than `max`, padCenter will return `str` unaltered. - * - * @param String str string to pad - * @param Number max total length of output string - * @param String chr optional. Character to pad with. default: ' ' - * @return String padded str - */ - -function padCenter(str, max, chr) { - str = str != null ? str : '' - str = String(str) - var length = max - wcwidth(str) - if (length <= 0) return str - var lengthLeft = Math.floor(length/2) - var lengthRight = length - lengthLeft - return repeatString(chr || ' ', lengthLeft) + str + repeatString(chr || ' ', lengthRight) -} - -/** - * Pad `str` up to total length `max` with `chr`, on the left. - * If `str` is longer than `max`, padRight will return `str` unaltered. - * - * @param String str string to pad - * @param Number max total length of output string - * @param String chr optional. Character to pad with. default: ' ' - * @return String padded str - */ - -function padLeft(str, max, chr) { - str = str != null ? str : '' - str = String(str) - var length = max - wcwidth(str) - if (length <= 0) return str - return repeatString(chr || ' ', length) + str -} - -/** - * Split a String `str` into lines of maxiumum length `max`. - * Splits on word boundaries. Preserves existing new lines. - * - * @param String str string to split - * @param Number max length of each line - * @return Array Array containing lines. - */ - -function splitIntoLines(str, max) { - function _splitIntoLines(str, max) { - return str.trim().split(' ').reduce(function(lines, word) { - var line = lines[lines.length - 1] - if (line && wcwidth(line.join(' ')) + wcwidth(word) < max) { - lines[lines.length - 1].push(word) // add to line - } - else lines.push([word]) // new line - return lines - }, []).map(function(l) { - return l.join(' ') - }) - } - return str.split('\n').map(function(str) { - return _splitIntoLines(str, max) - }).reduce(function(lines, line) { - return lines.concat(line) - }, []) -} - -/** - * Add spaces and `truncationChar` between words of - * `str` which are longer than `max`. - * - * @param String str string to split - * @param Number max length of each line - * @param Number truncationChar character to append to split words - * @return String - */ - -function splitLongWords(str, max, truncationChar) { - str = str.trim() - var result = [] - var words = str.split(' ') - var remainder = '' - - var truncationWidth = wcwidth(truncationChar) - - while (remainder || words.length) { - if (remainder) { - var word = remainder - remainder = '' - } else { - var word = words.shift() - } - - if (wcwidth(word) > max) { - // slice is based on length no wcwidth - var i = 0 - var wwidth = 0 - var limit = max - truncationWidth - while (i < word.length) { - var w = wcwidth(word.charAt(i)) - if (w + wwidth > limit) { - break - } - wwidth += w - ++i - } - - remainder = word.slice(i) // get remainder - // save remainder for next loop - - word = word.slice(0, i) // grab truncated word - word += truncationChar // add trailing … or whatever - } - result.push(word) - } - - return result.join(' ') -} - - -/** - * Truncate `str` into total width `max` - * If `str` is shorter than `max`, will return `str` unaltered. - * - * @param String str string to truncated - * @param Number max total wcwidth of output string - * @return String truncated str - */ - -function truncateString(str, max) { - - str = str != null ? str : '' - str = String(str) - - if(max == Infinity) return str - - var i = 0 - var wwidth = 0 - while (i < str.length) { - var w = wcwidth(str.charAt(i)) - if(w + wwidth > max) - break - wwidth += w - ++i - } - return str.slice(0, i) -} - - - -/** - * Exports - */ - -module.exports.padRight = padRight -module.exports.padCenter = padCenter -module.exports.padLeft = padLeft -module.exports.splitIntoLines = splitIntoLines -module.exports.splitLongWords = splitLongWords -module.exports.truncateString = truncateString diff --git a/deps/npm/node_modules/columnify/width.js b/deps/npm/node_modules/columnify/width.js deleted file mode 100644 index a9f5333b40b2fa..00000000000000 --- a/deps/npm/node_modules/columnify/width.js +++ /dev/null @@ -1,6 +0,0 @@ -var stripAnsi = require('strip-ansi') -var wcwidth = require('wcwidth') - -module.exports = function(str) { - return wcwidth(stripAnsi(str)) -} diff --git a/deps/npm/node_modules/console-control-strings/LICENSE b/deps/npm/node_modules/console-control-strings/LICENSE deleted file mode 100644 index e756052969b780..00000000000000 --- a/deps/npm/node_modules/console-control-strings/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2014, Rebecca Turner - -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. diff --git a/deps/npm/node_modules/console-control-strings/index.js b/deps/npm/node_modules/console-control-strings/index.js deleted file mode 100644 index bf890348ec6e35..00000000000000 --- a/deps/npm/node_modules/console-control-strings/index.js +++ /dev/null @@ -1,125 +0,0 @@ -'use strict' - -// These tables borrowed from `ansi` - -var prefix = '\x1b[' - -exports.up = function up (num) { - return prefix + (num || '') + 'A' -} - -exports.down = function down (num) { - return prefix + (num || '') + 'B' -} - -exports.forward = function forward (num) { - return prefix + (num || '') + 'C' -} - -exports.back = function back (num) { - return prefix + (num || '') + 'D' -} - -exports.nextLine = function nextLine (num) { - return prefix + (num || '') + 'E' -} - -exports.previousLine = function previousLine (num) { - return prefix + (num || '') + 'F' -} - -exports.horizontalAbsolute = function horizontalAbsolute (num) { - if (num == null) throw new Error('horizontalAboslute requires a column to position to') - return prefix + num + 'G' -} - -exports.eraseData = function eraseData () { - return prefix + 'J' -} - -exports.eraseLine = function eraseLine () { - return prefix + 'K' -} - -exports.goto = function (x, y) { - return prefix + y + ';' + x + 'H' -} - -exports.gotoSOL = function () { - return '\r' -} - -exports.beep = function () { - return '\x07' -} - -exports.hideCursor = function hideCursor () { - return prefix + '?25l' -} - -exports.showCursor = function showCursor () { - return prefix + '?25h' -} - -var colors = { - reset: 0, -// styles - bold: 1, - italic: 3, - underline: 4, - inverse: 7, -// resets - stopBold: 22, - stopItalic: 23, - stopUnderline: 24, - stopInverse: 27, -// colors - white: 37, - black: 30, - blue: 34, - cyan: 36, - green: 32, - magenta: 35, - red: 31, - yellow: 33, - bgWhite: 47, - bgBlack: 40, - bgBlue: 44, - bgCyan: 46, - bgGreen: 42, - bgMagenta: 45, - bgRed: 41, - bgYellow: 43, - - grey: 90, - brightBlack: 90, - brightRed: 91, - brightGreen: 92, - brightYellow: 93, - brightBlue: 94, - brightMagenta: 95, - brightCyan: 96, - brightWhite: 97, - - bgGrey: 100, - bgBrightBlack: 100, - bgBrightRed: 101, - bgBrightGreen: 102, - bgBrightYellow: 103, - bgBrightBlue: 104, - bgBrightMagenta: 105, - bgBrightCyan: 106, - bgBrightWhite: 107 -} - -exports.color = function color (colorWith) { - if (arguments.length !== 1 || !Array.isArray(colorWith)) { - colorWith = Array.prototype.slice.call(arguments) - } - return prefix + colorWith.map(colorNameToCode).join(';') + 'm' -} - -function colorNameToCode (color) { - if (colors[color] != null) return colors[color] - throw new Error('Unknown color or style name: ' + color) -} diff --git a/deps/npm/node_modules/console-control-strings/package.json b/deps/npm/node_modules/console-control-strings/package.json deleted file mode 100644 index eb6c62ae2dac76..00000000000000 --- a/deps/npm/node_modules/console-control-strings/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "console-control-strings", - "version": "1.1.0", - "description": "A library of cross-platform tested terminal/console command strings for doing things like color and cursor positioning. This is a subset of both ansi and vt100. All control codes included work on both Windows & Unix-like OSes, except where noted.", - "main": "index.js", - "directories": { - "test": "test" - }, - "scripts": { - "test": "standard && tap test/*.js" - }, - "repository": { - "type": "git", - "url": "https://github.com/iarna/console-control-strings" - }, - "keywords": [], - "author": "Rebecca Turner (http://re-becca.org/)", - "license": "ISC", - "files": [ - "LICENSE", - "index.js" - ], - "devDependencies": { - "standard": "^7.1.2", - "tap": "^5.7.2" - } -} diff --git a/deps/npm/node_modules/defaults/LICENSE b/deps/npm/node_modules/defaults/LICENSE deleted file mode 100644 index 11eb6fdebf3b63..00000000000000 --- a/deps/npm/node_modules/defaults/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2022 Sindre Sorhus -Copyright (c) 2015 Elijah Insua - -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. diff --git a/deps/npm/node_modules/defaults/index.js b/deps/npm/node_modules/defaults/index.js deleted file mode 100644 index cb7d75c9c6beb0..00000000000000 --- a/deps/npm/node_modules/defaults/index.js +++ /dev/null @@ -1,13 +0,0 @@ -var clone = require('clone'); - -module.exports = function(options, defaults) { - options = options || {}; - - Object.keys(defaults).forEach(function(key) { - if (typeof options[key] === 'undefined') { - options[key] = clone(defaults[key]); - } - }); - - return options; -}; \ No newline at end of file diff --git a/deps/npm/node_modules/defaults/package.json b/deps/npm/node_modules/defaults/package.json deleted file mode 100644 index 44f72b1714ce4e..00000000000000 --- a/deps/npm/node_modules/defaults/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "defaults", - "version": "1.0.4", - "description": "merge single level defaults over a config object", - "main": "index.js", - "funding": "https://github.com/sponsors/sindresorhus", - "scripts": { - "test": "node test.js" - }, - "repository": { - "type": "git", - "url": "git://github.com/sindresorhus/node-defaults.git" - }, - "keywords": [ - "config", - "defaults", - "options", - "object", - "merge", - "assign", - "properties", - "deep" - ], - "author": "Elijah Insua ", - "license": "MIT", - "readmeFilename": "README.md", - "dependencies": { - "clone": "^1.0.2" - }, - "devDependencies": { - "tap": "^2.0.0" - } -} diff --git a/deps/npm/node_modules/defaults/test.js b/deps/npm/node_modules/defaults/test.js deleted file mode 100644 index 60e0ffba8b4aab..00000000000000 --- a/deps/npm/node_modules/defaults/test.js +++ /dev/null @@ -1,34 +0,0 @@ -var defaults = require('./'), - test = require('tap').test; - -test("ensure options is an object", function(t) { - var options = defaults(false, { a : true }); - t.ok(options.a); - t.end() -}); - -test("ensure defaults override keys", function(t) { - var result = defaults({}, { a: false, b: true }); - t.ok(result.b, 'b merges over undefined'); - t.equal(result.a, false, 'a merges over undefined'); - t.end(); -}); - -test("ensure defined keys are not overwritten", function(t) { - var result = defaults({ b: false }, { a: false, b: true }); - t.equal(result.b, false, 'b not merged'); - t.equal(result.a, false, 'a merges over undefined'); - t.end(); -}); - -test("ensure defaults clone nested objects", function(t) { - var d = { a: [1,2,3], b: { hello : 'world' } }; - var result = defaults({}, d); - t.equal(result.a.length, 3, 'objects should be clones'); - t.ok(result.a !== d.a, 'objects should be clones'); - - t.equal(Object.keys(result.b).length, 1, 'objects should be clones'); - t.ok(result.b !== d.b, 'objects should be clones'); - t.end(); -}); - diff --git a/deps/npm/node_modules/gauge/LICENSE.md b/deps/npm/node_modules/gauge/LICENSE.md deleted file mode 100644 index 5fc208ff122e08..00000000000000 --- a/deps/npm/node_modules/gauge/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ - - -ISC License - -Copyright npm, Inc. - -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 NPM DISCLAIMS ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO -EVENT SHALL NPM 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. diff --git a/deps/npm/node_modules/gauge/lib/base-theme.js b/deps/npm/node_modules/gauge/lib/base-theme.js deleted file mode 100644 index 00bf5684cddab8..00000000000000 --- a/deps/npm/node_modules/gauge/lib/base-theme.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' -var spin = require('./spin.js') -var progressBar = require('./progress-bar.js') - -module.exports = { - activityIndicator: function (values, theme, width) { - if (values.spun == null) { - return - } - return spin(theme, values.spun) - }, - progressbar: function (values, theme, width) { - if (values.completed == null) { - return - } - return progressBar(theme, width, values.completed) - }, -} diff --git a/deps/npm/node_modules/gauge/lib/error.js b/deps/npm/node_modules/gauge/lib/error.js deleted file mode 100644 index d9914ba5335d25..00000000000000 --- a/deps/npm/node_modules/gauge/lib/error.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' -var util = require('util') - -var User = exports.User = function User (msg) { - var err = new Error(msg) - Error.captureStackTrace(err, User) - err.code = 'EGAUGE' - return err -} - -exports.MissingTemplateValue = function MissingTemplateValue (item, values) { - var err = new User(util.format('Missing template value "%s"', item.type)) - Error.captureStackTrace(err, MissingTemplateValue) - err.template = item - err.values = values - return err -} - -exports.Internal = function Internal (msg) { - var err = new Error(msg) - Error.captureStackTrace(err, Internal) - err.code = 'EGAUGEINTERNAL' - return err -} diff --git a/deps/npm/node_modules/gauge/lib/has-color.js b/deps/npm/node_modules/gauge/lib/has-color.js deleted file mode 100644 index 16cba0eb47d332..00000000000000 --- a/deps/npm/node_modules/gauge/lib/has-color.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict' -var colorSupport = require('color-support') - -module.exports = colorSupport().hasBasic diff --git a/deps/npm/node_modules/gauge/lib/index.js b/deps/npm/node_modules/gauge/lib/index.js deleted file mode 100644 index be94f53f3b5f46..00000000000000 --- a/deps/npm/node_modules/gauge/lib/index.js +++ /dev/null @@ -1,289 +0,0 @@ -'use strict' -var Plumbing = require('./plumbing.js') -var hasUnicode = require('has-unicode') -var hasColor = require('./has-color.js') -var onExit = require('signal-exit').onExit -var defaultThemes = require('./themes') -var setInterval = require('./set-interval.js') -var process = require('./process.js') -var setImmediate = require('./set-immediate') - -module.exports = Gauge - -function callWith (obj, method) { - return function () { - return method.call(obj) - } -} - -function Gauge (arg1, arg2) { - var options, writeTo - if (arg1 && arg1.write) { - writeTo = arg1 - options = arg2 || {} - } else if (arg2 && arg2.write) { - writeTo = arg2 - options = arg1 || {} - } else { - writeTo = process.stderr - options = arg1 || arg2 || {} - } - - this._status = { - spun: 0, - section: '', - subsection: '', - } - this._paused = false // are we paused for back pressure? - this._disabled = true // are all progress bar updates disabled? - this._showing = false // do we WANT the progress bar on screen - this._onScreen = false // IS the progress bar on screen - this._needsRedraw = false // should we print something at next tick? - this._hideCursor = options.hideCursor == null ? true : options.hideCursor - this._fixedFramerate = options.fixedFramerate == null - ? !(/^v0\.8\./.test(process.version)) - : options.fixedFramerate - this._lastUpdateAt = null - this._updateInterval = options.updateInterval == null ? 50 : options.updateInterval - - this._themes = options.themes || defaultThemes - this._theme = options.theme - var theme = this._computeTheme(options.theme) - var template = options.template || [ - { type: 'progressbar', length: 20 }, - { type: 'activityIndicator', kerning: 1, length: 1 }, - { type: 'section', kerning: 1, default: '' }, - { type: 'subsection', kerning: 1, default: '' }, - ] - this.setWriteTo(writeTo, options.tty) - var PlumbingClass = options.Plumbing || Plumbing - this._gauge = new PlumbingClass(theme, template, this.getWidth()) - - this._$$doRedraw = callWith(this, this._doRedraw) - this._$$handleSizeChange = callWith(this, this._handleSizeChange) - - this._cleanupOnExit = options.cleanupOnExit == null || options.cleanupOnExit - this._removeOnExit = null - - if (options.enabled || (options.enabled == null && this._tty && this._tty.isTTY)) { - this.enable() - } else { - this.disable() - } -} -Gauge.prototype = {} - -Gauge.prototype.isEnabled = function () { - return !this._disabled -} - -Gauge.prototype.setTemplate = function (template) { - this._gauge.setTemplate(template) - if (this._showing) { - this._requestRedraw() - } -} - -Gauge.prototype._computeTheme = function (theme) { - if (!theme) { - theme = {} - } - if (typeof theme === 'string') { - theme = this._themes.getTheme(theme) - } else if ( - Object.keys(theme).length === 0 || theme.hasUnicode != null || theme.hasColor != null - ) { - var useUnicode = theme.hasUnicode == null ? hasUnicode() : theme.hasUnicode - var useColor = theme.hasColor == null ? hasColor : theme.hasColor - theme = this._themes.getDefault({ - hasUnicode: useUnicode, - hasColor: useColor, - platform: theme.platform, - }) - } - return theme -} - -Gauge.prototype.setThemeset = function (themes) { - this._themes = themes - this.setTheme(this._theme) -} - -Gauge.prototype.setTheme = function (theme) { - this._gauge.setTheme(this._computeTheme(theme)) - if (this._showing) { - this._requestRedraw() - } - this._theme = theme -} - -Gauge.prototype._requestRedraw = function () { - this._needsRedraw = true - if (!this._fixedFramerate) { - this._doRedraw() - } -} - -Gauge.prototype.getWidth = function () { - return ((this._tty && this._tty.columns) || 80) - 1 -} - -Gauge.prototype.setWriteTo = function (writeTo, tty) { - var enabled = !this._disabled - if (enabled) { - this.disable() - } - this._writeTo = writeTo - this._tty = tty || - (writeTo === process.stderr && process.stdout.isTTY && process.stdout) || - (writeTo.isTTY && writeTo) || - this._tty - if (this._gauge) { - this._gauge.setWidth(this.getWidth()) - } - if (enabled) { - this.enable() - } -} - -Gauge.prototype.enable = function () { - if (!this._disabled) { - return - } - this._disabled = false - if (this._tty) { - this._enableEvents() - } - if (this._showing) { - this.show() - } -} - -Gauge.prototype.disable = function () { - if (this._disabled) { - return - } - if (this._showing) { - this._lastUpdateAt = null - this._showing = false - this._doRedraw() - this._showing = true - } - this._disabled = true - if (this._tty) { - this._disableEvents() - } -} - -Gauge.prototype._enableEvents = function () { - if (this._cleanupOnExit) { - this._removeOnExit = onExit(callWith(this, this.disable)) - } - this._tty.on('resize', this._$$handleSizeChange) - if (this._fixedFramerate) { - this.redrawTracker = setInterval(this._$$doRedraw, this._updateInterval) - if (this.redrawTracker.unref) { - this.redrawTracker.unref() - } - } -} - -Gauge.prototype._disableEvents = function () { - this._tty.removeListener('resize', this._$$handleSizeChange) - if (this._fixedFramerate) { - clearInterval(this.redrawTracker) - } - if (this._removeOnExit) { - this._removeOnExit() - } -} - -Gauge.prototype.hide = function (cb) { - if (this._disabled) { - return cb && process.nextTick(cb) - } - if (!this._showing) { - return cb && process.nextTick(cb) - } - this._showing = false - this._doRedraw() - cb && setImmediate(cb) -} - -Gauge.prototype.show = function (section, completed) { - this._showing = true - if (typeof section === 'string') { - this._status.section = section - } else if (typeof section === 'object') { - var sectionKeys = Object.keys(section) - for (var ii = 0; ii < sectionKeys.length; ++ii) { - var key = sectionKeys[ii] - this._status[key] = section[key] - } - } - if (completed != null) { - this._status.completed = completed - } - if (this._disabled) { - return - } - this._requestRedraw() -} - -Gauge.prototype.pulse = function (subsection) { - this._status.subsection = subsection || '' - this._status.spun++ - if (this._disabled) { - return - } - if (!this._showing) { - return - } - this._requestRedraw() -} - -Gauge.prototype._handleSizeChange = function () { - this._gauge.setWidth(this._tty.columns - 1) - this._requestRedraw() -} - -Gauge.prototype._doRedraw = function () { - if (this._disabled || this._paused) { - return - } - if (!this._fixedFramerate) { - var now = Date.now() - if (this._lastUpdateAt && now - this._lastUpdateAt < this._updateInterval) { - return - } - this._lastUpdateAt = now - } - if (!this._showing && this._onScreen) { - this._onScreen = false - var result = this._gauge.hide() - if (this._hideCursor) { - result += this._gauge.showCursor() - } - return this._writeTo.write(result) - } - if (!this._showing && !this._onScreen) { - return - } - if (this._showing && !this._onScreen) { - this._onScreen = true - this._needsRedraw = true - if (this._hideCursor) { - this._writeTo.write(this._gauge.hideCursor()) - } - } - if (!this._needsRedraw) { - return - } - if (!this._writeTo.write(this._gauge.show(this._status))) { - this._paused = true - this._writeTo.on('drain', callWith(this, function () { - this._paused = false - this._doRedraw() - })) - } -} diff --git a/deps/npm/node_modules/gauge/lib/plumbing.js b/deps/npm/node_modules/gauge/lib/plumbing.js deleted file mode 100644 index c4dc3e074b95e8..00000000000000 --- a/deps/npm/node_modules/gauge/lib/plumbing.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict' -var consoleControl = require('console-control-strings') -var renderTemplate = require('./render-template.js') -var validate = require('aproba') - -var Plumbing = module.exports = function (theme, template, width) { - if (!width) { - width = 80 - } - validate('OAN', [theme, template, width]) - this.showing = false - this.theme = theme - this.width = width - this.template = template -} -Plumbing.prototype = {} - -Plumbing.prototype.setTheme = function (theme) { - validate('O', [theme]) - this.theme = theme -} - -Plumbing.prototype.setTemplate = function (template) { - validate('A', [template]) - this.template = template -} - -Plumbing.prototype.setWidth = function (width) { - validate('N', [width]) - this.width = width -} - -Plumbing.prototype.hide = function () { - return consoleControl.gotoSOL() + consoleControl.eraseLine() -} - -Plumbing.prototype.hideCursor = consoleControl.hideCursor - -Plumbing.prototype.showCursor = consoleControl.showCursor - -Plumbing.prototype.show = function (status) { - var values = Object.create(this.theme) - for (var key in status) { - values[key] = status[key] - } - - return renderTemplate(this.width, this.template, values).trim() + - consoleControl.color('reset') + - consoleControl.eraseLine() + consoleControl.gotoSOL() -} diff --git a/deps/npm/node_modules/gauge/lib/process.js b/deps/npm/node_modules/gauge/lib/process.js deleted file mode 100644 index 05e85694d755b6..00000000000000 --- a/deps/npm/node_modules/gauge/lib/process.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict' -// this exists so we can replace it during testing -module.exports = process diff --git a/deps/npm/node_modules/gauge/lib/progress-bar.js b/deps/npm/node_modules/gauge/lib/progress-bar.js deleted file mode 100644 index 184ff2500aae4d..00000000000000 --- a/deps/npm/node_modules/gauge/lib/progress-bar.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict' -var validate = require('aproba') -var renderTemplate = require('./render-template.js') -var wideTruncate = require('./wide-truncate') -var stringWidth = require('string-width') - -module.exports = function (theme, width, completed) { - validate('ONN', [theme, width, completed]) - if (completed < 0) { - completed = 0 - } - if (completed > 1) { - completed = 1 - } - if (width <= 0) { - return '' - } - var sofar = Math.round(width * completed) - var rest = width - sofar - var template = [ - { type: 'complete', value: repeat(theme.complete, sofar), length: sofar }, - { type: 'remaining', value: repeat(theme.remaining, rest), length: rest }, - ] - return renderTemplate(width, template, theme) -} - -// lodash's way of repeating -function repeat (string, width) { - var result = '' - var n = width - do { - if (n % 2) { - result += string - } - n = Math.floor(n / 2) - /* eslint no-self-assign: 0 */ - string += string - } while (n && stringWidth(result) < width) - - return wideTruncate(result, width) -} diff --git a/deps/npm/node_modules/gauge/lib/render-template.js b/deps/npm/node_modules/gauge/lib/render-template.js deleted file mode 100644 index d1b52c0f48095a..00000000000000 --- a/deps/npm/node_modules/gauge/lib/render-template.js +++ /dev/null @@ -1,222 +0,0 @@ -'use strict' -var align = require('wide-align') -var validate = require('aproba') -var wideTruncate = require('./wide-truncate') -var error = require('./error') -var TemplateItem = require('./template-item') - -function renderValueWithValues (values) { - return function (item) { - return renderValue(item, values) - } -} - -var renderTemplate = module.exports = function (width, template, values) { - var items = prepareItems(width, template, values) - var rendered = items.map(renderValueWithValues(values)).join('') - return align.left(wideTruncate(rendered, width), width) -} - -function preType (item) { - var cappedTypeName = item.type[0].toUpperCase() + item.type.slice(1) - return 'pre' + cappedTypeName -} - -function postType (item) { - var cappedTypeName = item.type[0].toUpperCase() + item.type.slice(1) - return 'post' + cappedTypeName -} - -function hasPreOrPost (item, values) { - if (!item.type) { - return - } - return values[preType(item)] || values[postType(item)] -} - -function generatePreAndPost (baseItem, parentValues) { - var item = Object.assign({}, baseItem) - var values = Object.create(parentValues) - var template = [] - var pre = preType(item) - var post = postType(item) - if (values[pre]) { - template.push({ value: values[pre] }) - values[pre] = null - } - item.minLength = null - item.length = null - item.maxLength = null - template.push(item) - values[item.type] = values[item.type] - if (values[post]) { - template.push({ value: values[post] }) - values[post] = null - } - return function ($1, $2, length) { - return renderTemplate(length, template, values) - } -} - -function prepareItems (width, template, values) { - function cloneAndObjectify (item, index, arr) { - var cloned = new TemplateItem(item, width) - var type = cloned.type - if (cloned.value == null) { - if (!(type in values)) { - if (cloned.default == null) { - throw new error.MissingTemplateValue(cloned, values) - } else { - cloned.value = cloned.default - } - } else { - cloned.value = values[type] - } - } - if (cloned.value == null || cloned.value === '') { - return null - } - cloned.index = index - cloned.first = index === 0 - cloned.last = index === arr.length - 1 - if (hasPreOrPost(cloned, values)) { - cloned.value = generatePreAndPost(cloned, values) - } - return cloned - } - - var output = template.map(cloneAndObjectify).filter(function (item) { - return item != null - }) - - var remainingSpace = width - var variableCount = output.length - - function consumeSpace (length) { - if (length > remainingSpace) { - length = remainingSpace - } - remainingSpace -= length - } - - function finishSizing (item, length) { - if (item.finished) { - throw new error.Internal('Tried to finish template item that was already finished') - } - if (length === Infinity) { - throw new error.Internal('Length of template item cannot be infinity') - } - if (length != null) { - item.length = length - } - item.minLength = null - item.maxLength = null - --variableCount - item.finished = true - if (item.length == null) { - item.length = item.getBaseLength() - } - if (item.length == null) { - throw new error.Internal('Finished template items must have a length') - } - consumeSpace(item.getLength()) - } - - output.forEach(function (item) { - if (!item.kerning) { - return - } - var prevPadRight = item.first ? 0 : output[item.index - 1].padRight - if (!item.first && prevPadRight < item.kerning) { - item.padLeft = item.kerning - prevPadRight - } - if (!item.last) { - item.padRight = item.kerning - } - }) - - // Finish any that have a fixed (literal or intuited) length - output.forEach(function (item) { - if (item.getBaseLength() == null) { - return - } - finishSizing(item) - }) - - var resized = 0 - var resizing - var hunkSize - do { - resizing = false - hunkSize = Math.round(remainingSpace / variableCount) - output.forEach(function (item) { - if (item.finished) { - return - } - if (!item.maxLength) { - return - } - if (item.getMaxLength() < hunkSize) { - finishSizing(item, item.maxLength) - resizing = true - } - }) - } while (resizing && resized++ < output.length) - if (resizing) { - throw new error.Internal('Resize loop iterated too many times while determining maxLength') - } - - resized = 0 - do { - resizing = false - hunkSize = Math.round(remainingSpace / variableCount) - output.forEach(function (item) { - if (item.finished) { - return - } - if (!item.minLength) { - return - } - if (item.getMinLength() >= hunkSize) { - finishSizing(item, item.minLength) - resizing = true - } - }) - } while (resizing && resized++ < output.length) - if (resizing) { - throw new error.Internal('Resize loop iterated too many times while determining minLength') - } - - hunkSize = Math.round(remainingSpace / variableCount) - output.forEach(function (item) { - if (item.finished) { - return - } - finishSizing(item, hunkSize) - }) - - return output -} - -function renderFunction (item, values, length) { - validate('OON', arguments) - if (item.type) { - return item.value(values, values[item.type + 'Theme'] || {}, length) - } else { - return item.value(values, {}, length) - } -} - -function renderValue (item, values) { - var length = item.getBaseLength() - var value = typeof item.value === 'function' ? renderFunction(item, values, length) : item.value - if (value == null || value === '') { - return '' - } - var alignWith = align[item.align] || align.left - var leftPadding = item.padLeft ? align.left('', item.padLeft) : '' - var rightPadding = item.padRight ? align.right('', item.padRight) : '' - var truncated = wideTruncate(String(value), length) - var aligned = alignWith(truncated, length) - return leftPadding + aligned + rightPadding -} diff --git a/deps/npm/node_modules/gauge/lib/set-immediate.js b/deps/npm/node_modules/gauge/lib/set-immediate.js deleted file mode 100644 index 6650a485c49933..00000000000000 --- a/deps/npm/node_modules/gauge/lib/set-immediate.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict' -var process = require('./process') -try { - module.exports = setImmediate -} catch (ex) { - module.exports = process.nextTick -} diff --git a/deps/npm/node_modules/gauge/lib/set-interval.js b/deps/npm/node_modules/gauge/lib/set-interval.js deleted file mode 100644 index 576198793c5504..00000000000000 --- a/deps/npm/node_modules/gauge/lib/set-interval.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict' -// this exists so we can replace it during testing -module.exports = setInterval diff --git a/deps/npm/node_modules/gauge/lib/spin.js b/deps/npm/node_modules/gauge/lib/spin.js deleted file mode 100644 index 34142ee31acc7c..00000000000000 --- a/deps/npm/node_modules/gauge/lib/spin.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict' - -module.exports = function spin (spinstr, spun) { - return spinstr[spun % spinstr.length] -} diff --git a/deps/npm/node_modules/gauge/lib/template-item.js b/deps/npm/node_modules/gauge/lib/template-item.js deleted file mode 100644 index e307e9b7421e73..00000000000000 --- a/deps/npm/node_modules/gauge/lib/template-item.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict' -var stringWidth = require('string-width') - -module.exports = TemplateItem - -function isPercent (num) { - if (typeof num !== 'string') { - return false - } - return num.slice(-1) === '%' -} - -function percent (num) { - return Number(num.slice(0, -1)) / 100 -} - -function TemplateItem (values, outputLength) { - this.overallOutputLength = outputLength - this.finished = false - this.type = null - this.value = null - this.length = null - this.maxLength = null - this.minLength = null - this.kerning = null - this.align = 'left' - this.padLeft = 0 - this.padRight = 0 - this.index = null - this.first = null - this.last = null - if (typeof values === 'string') { - this.value = values - } else { - for (var prop in values) { - this[prop] = values[prop] - } - } - // Realize percents - if (isPercent(this.length)) { - this.length = Math.round(this.overallOutputLength * percent(this.length)) - } - if (isPercent(this.minLength)) { - this.minLength = Math.round(this.overallOutputLength * percent(this.minLength)) - } - if (isPercent(this.maxLength)) { - this.maxLength = Math.round(this.overallOutputLength * percent(this.maxLength)) - } - return this -} - -TemplateItem.prototype = {} - -TemplateItem.prototype.getBaseLength = function () { - var length = this.length - if ( - length == null && - typeof this.value === 'string' && - this.maxLength == null && - this.minLength == null - ) { - length = stringWidth(this.value) - } - return length -} - -TemplateItem.prototype.getLength = function () { - var length = this.getBaseLength() - if (length == null) { - return null - } - return length + this.padLeft + this.padRight -} - -TemplateItem.prototype.getMaxLength = function () { - if (this.maxLength == null) { - return null - } - return this.maxLength + this.padLeft + this.padRight -} - -TemplateItem.prototype.getMinLength = function () { - if (this.minLength == null) { - return null - } - return this.minLength + this.padLeft + this.padRight -} diff --git a/deps/npm/node_modules/gauge/lib/theme-set.js b/deps/npm/node_modules/gauge/lib/theme-set.js deleted file mode 100644 index 643d7dbb1da346..00000000000000 --- a/deps/npm/node_modules/gauge/lib/theme-set.js +++ /dev/null @@ -1,122 +0,0 @@ -'use strict' - -module.exports = function () { - return ThemeSetProto.newThemeSet() -} - -var ThemeSetProto = {} - -ThemeSetProto.baseTheme = require('./base-theme.js') - -ThemeSetProto.newTheme = function (parent, theme) { - if (!theme) { - theme = parent - parent = this.baseTheme - } - return Object.assign({}, parent, theme) -} - -ThemeSetProto.getThemeNames = function () { - return Object.keys(this.themes) -} - -ThemeSetProto.addTheme = function (name, parent, theme) { - this.themes[name] = this.newTheme(parent, theme) -} - -ThemeSetProto.addToAllThemes = function (theme) { - var themes = this.themes - Object.keys(themes).forEach(function (name) { - Object.assign(themes[name], theme) - }) - Object.assign(this.baseTheme, theme) -} - -ThemeSetProto.getTheme = function (name) { - if (!this.themes[name]) { - throw this.newMissingThemeError(name) - } - return this.themes[name] -} - -ThemeSetProto.setDefault = function (opts, name) { - if (name == null) { - name = opts - opts = {} - } - var platform = opts.platform == null ? 'fallback' : opts.platform - var hasUnicode = !!opts.hasUnicode - var hasColor = !!opts.hasColor - if (!this.defaults[platform]) { - this.defaults[platform] = { true: {}, false: {} } - } - this.defaults[platform][hasUnicode][hasColor] = name -} - -ThemeSetProto.getDefault = function (opts) { - if (!opts) { - opts = {} - } - var platformName = opts.platform || process.platform - var platform = this.defaults[platformName] || this.defaults.fallback - var hasUnicode = !!opts.hasUnicode - var hasColor = !!opts.hasColor - if (!platform) { - throw this.newMissingDefaultThemeError(platformName, hasUnicode, hasColor) - } - if (!platform[hasUnicode][hasColor]) { - if (hasUnicode && hasColor && platform[!hasUnicode][hasColor]) { - hasUnicode = false - } else if (hasUnicode && hasColor && platform[hasUnicode][!hasColor]) { - hasColor = false - } else if (hasUnicode && hasColor && platform[!hasUnicode][!hasColor]) { - hasUnicode = false - hasColor = false - } else if (hasUnicode && !hasColor && platform[!hasUnicode][hasColor]) { - hasUnicode = false - } else if (!hasUnicode && hasColor && platform[hasUnicode][!hasColor]) { - hasColor = false - } else if (platform === this.defaults.fallback) { - throw this.newMissingDefaultThemeError(platformName, hasUnicode, hasColor) - } - } - if (platform[hasUnicode][hasColor]) { - return this.getTheme(platform[hasUnicode][hasColor]) - } else { - return this.getDefault(Object.assign({}, opts, { platform: 'fallback' })) - } -} - -ThemeSetProto.newMissingThemeError = function newMissingThemeError (name) { - var err = new Error('Could not find a gauge theme named "' + name + '"') - Error.captureStackTrace.call(err, newMissingThemeError) - err.theme = name - err.code = 'EMISSINGTHEME' - return err -} - -ThemeSetProto.newMissingDefaultThemeError = - function newMissingDefaultThemeError (platformName, hasUnicode, hasColor) { - var err = new Error( - 'Could not find a gauge theme for your platform/unicode/color use combo:\n' + - ' platform = ' + platformName + '\n' + - ' hasUnicode = ' + hasUnicode + '\n' + - ' hasColor = ' + hasColor) - Error.captureStackTrace.call(err, newMissingDefaultThemeError) - err.platform = platformName - err.hasUnicode = hasUnicode - err.hasColor = hasColor - err.code = 'EMISSINGTHEME' - return err - } - -ThemeSetProto.newThemeSet = function () { - var themeset = function (opts) { - return themeset.getDefault(opts) - } - return Object.assign(themeset, ThemeSetProto, { - themes: Object.assign({}, this.themes), - baseTheme: Object.assign({}, this.baseTheme), - defaults: JSON.parse(JSON.stringify(this.defaults || {})), - }) -} diff --git a/deps/npm/node_modules/gauge/lib/themes.js b/deps/npm/node_modules/gauge/lib/themes.js deleted file mode 100644 index d2e62bbccb3d82..00000000000000 --- a/deps/npm/node_modules/gauge/lib/themes.js +++ /dev/null @@ -1,56 +0,0 @@ -'use strict' -var color = require('console-control-strings').color -var ThemeSet = require('./theme-set.js') - -var themes = module.exports = new ThemeSet() - -themes.addTheme('ASCII', { - preProgressbar: '[', - postProgressbar: ']', - progressbarTheme: { - complete: '#', - remaining: '.', - }, - activityIndicatorTheme: '-\\|/', - preSubsection: '>', -}) - -themes.addTheme('colorASCII', themes.getTheme('ASCII'), { - progressbarTheme: { - preComplete: color('bgBrightWhite', 'brightWhite'), - complete: '#', - postComplete: color('reset'), - preRemaining: color('bgBrightBlack', 'brightBlack'), - remaining: '.', - postRemaining: color('reset'), - }, -}) - -themes.addTheme('brailleSpinner', { - preProgressbar: '(', - postProgressbar: ')', - progressbarTheme: { - complete: '#', - remaining: '⠂', - }, - activityIndicatorTheme: '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏', - preSubsection: '>', -}) - -themes.addTheme('colorBrailleSpinner', themes.getTheme('brailleSpinner'), { - progressbarTheme: { - preComplete: color('bgBrightWhite', 'brightWhite'), - complete: '#', - postComplete: color('reset'), - preRemaining: color('bgBrightBlack', 'brightBlack'), - remaining: '⠂', - postRemaining: color('reset'), - }, -}) - -themes.setDefault({}, 'ASCII') -themes.setDefault({ hasColor: true }, 'colorASCII') -themes.setDefault({ platform: 'darwin', hasUnicode: true }, 'brailleSpinner') -themes.setDefault({ platform: 'darwin', hasUnicode: true, hasColor: true }, 'colorBrailleSpinner') -themes.setDefault({ platform: 'linux', hasUnicode: true }, 'brailleSpinner') -themes.setDefault({ platform: 'linux', hasUnicode: true, hasColor: true }, 'colorBrailleSpinner') diff --git a/deps/npm/node_modules/gauge/lib/wide-truncate.js b/deps/npm/node_modules/gauge/lib/wide-truncate.js deleted file mode 100644 index 5284a699ac3fb5..00000000000000 --- a/deps/npm/node_modules/gauge/lib/wide-truncate.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict' -var stringWidth = require('string-width') -var stripAnsi = require('strip-ansi') - -module.exports = wideTruncate - -function wideTruncate (str, target) { - if (stringWidth(str) === 0) { - return str - } - if (target <= 0) { - return '' - } - if (stringWidth(str) <= target) { - return str - } - - // We compute the number of bytes of ansi sequences here and add - // that to our initial truncation to ensure that we don't slice one - // that we want to keep in half. - var noAnsi = stripAnsi(str) - var ansiSize = str.length + noAnsi.length - var truncated = str.slice(0, target + ansiSize) - - // we have to shrink the result to account for our ansi sequence buffer - // (if an ansi sequence was truncated) and double width characters. - while (stringWidth(truncated) > target) { - truncated = truncated.slice(0, -1) - } - return truncated -} diff --git a/deps/npm/node_modules/gauge/package.json b/deps/npm/node_modules/gauge/package.json deleted file mode 100644 index 449d9dd3ed3920..00000000000000 --- a/deps/npm/node_modules/gauge/package.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "name": "gauge", - "version": "5.0.1", - "description": "A terminal based horizontal gauge", - "main": "lib", - "scripts": { - "test": "tap", - "lint": "eslint \"**/*.js\"", - "postlint": "template-oss-check", - "lintfix": "npm run lint -- --fix", - "snap": "tap", - "posttest": "npm run lint", - "template-oss-apply": "template-oss-apply --force" - }, - "repository": { - "type": "git", - "url": "https://github.com/npm/gauge.git" - }, - "keywords": [ - "progressbar", - "progress", - "gauge" - ], - "author": "GitHub Inc.", - "license": "ISC", - "bugs": { - "url": "https://github.com/npm/gauge/issues" - }, - "homepage": "https://github.com/npm/gauge", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^4.0.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.14.1", - "readable-stream": "^4.0.0", - "tap": "^16.0.1" - }, - "files": [ - "bin/", - "lib/" - ], - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "tap": { - "branches": 79, - "statements": 89, - "functions": 92, - "lines": 90, - "nyc-arg": [ - "--exclude", - "tap-snapshots/**" - ] - }, - "templateOSS": { - "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.14.1", - "publish": "true" - } -} diff --git a/deps/npm/node_modules/glob/README.md b/deps/npm/node_modules/glob/README.md index 9f6e80fe665672..92c202afa1df8d 100644 --- a/deps/npm/node_modules/glob/README.md +++ b/deps/npm/node_modules/glob/README.md @@ -422,7 +422,7 @@ share the previously loaded cache. `process.cwd()`. See also: "Windows, CWDs, Drive Letters, and UNC Paths", below. - This option may be eiher a string path or a `file://` URL + This option may be either a string path or a `file://` URL object or string. - `root` A string path resolved against the `cwd` option, which @@ -509,6 +509,9 @@ share the previously loaded cache. - `nodir` Do not match directories, only files. (Note: to match _only_ directories, put a `/` at the end of the pattern.) + Note: when `follow` and `nodir` are both set, then symbolic + links to directories are also omitted. + - `stat` Call `lstat()` on all entries, whether required or not to determine whether it's a valid match. When used with `withFileTypes`, this means that matches will include data such @@ -539,6 +542,9 @@ share the previously loaded cache. it is not the first item in the pattern, or none if it is the first item in the pattern, following the same behavior as Bash. + Note: when `follow` and `nodir` are both set, then symbolic + links to directories are also omitted. + - `realpath` Set to true to call `fs.realpath` on all of the results. In the case of an entry that cannot be resolved, the entry is omitted. This incurs a slight performance penalty, of diff --git a/deps/npm/node_modules/glob/dist/commonjs/ignore.d.ts.map b/deps/npm/node_modules/glob/dist/commonjs/ignore.d.ts.map index be7831769d33ed..21ab57b94d1a76 100644 --- a/deps/npm/node_modules/glob/dist/commonjs/ignore.d.ts.map +++ b/deps/npm/node_modules/glob/dist/commonjs/ignore.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../../src/ignore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO,CAAA;IAC9B,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO,CAAA;CACvC;AASD;;GAEG;AACH,qBAAa,MAAO,YAAW,UAAU;IACvC,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,gBAAgB,EAAE,SAAS,EAAE,CAAA;IAC7B,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,gBAAgB,EAAE,SAAS,EAAE,CAAA;gBAG3B,OAAO,EAAE,MAAM,EAAE,EACjB,EACE,OAAO,EACP,MAAM,EACN,KAAK,EACL,UAAU,EACV,QAA0B,GAC3B,EAAE,cAAc;IAsDnB,OAAO,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO;IAczB,eAAe,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO;CAWlC"} \ No newline at end of file +{"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../../src/ignore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO,CAAA;IAC9B,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO,CAAA;CACvC;AASD;;GAEG;AACH,qBAAa,MAAO,YAAW,UAAU;IACvC,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,gBAAgB,EAAE,SAAS,EAAE,CAAA;IAC7B,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,gBAAgB,EAAE,SAAS,EAAE,CAAA;gBAG3B,OAAO,EAAE,MAAM,EAAE,EACjB,EACE,OAAO,EACP,MAAM,EACN,KAAK,EACL,UAAU,EACV,QAA0B,GAC3B,EAAE,cAAc;IA4DnB,OAAO,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO;IAczB,eAAe,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO;CAWlC"} \ No newline at end of file diff --git a/deps/npm/node_modules/glob/dist/commonjs/ignore.js b/deps/npm/node_modules/glob/dist/commonjs/ignore.js index 6cffb49f8ed27c..3c0daeff86ff87 100644 --- a/deps/npm/node_modules/glob/dist/commonjs/ignore.js +++ b/deps/npm/node_modules/glob/dist/commonjs/ignore.js @@ -57,6 +57,12 @@ class Ignore { if (!parsed || !globParts) { throw new Error('invalid pattern object'); } + // strip off leading ./ portions + // https://github.com/isaacs/node-glob/issues/570 + while (parsed[0] === '.' && globParts[0] === '.') { + parsed.shift(); + globParts.shift(); + } /* c8 ignore stop */ const p = new pattern_js_1.Pattern(parsed, globParts, 0, platform); const m = new minimatch_1.Minimatch(p.globString(), mmopts); diff --git a/deps/npm/node_modules/glob/dist/commonjs/ignore.js.map b/deps/npm/node_modules/glob/dist/commonjs/ignore.js.map index 3533cfc8811e90..30a4f731ee6048 100644 --- a/deps/npm/node_modules/glob/dist/commonjs/ignore.js.map +++ b/deps/npm/node_modules/glob/dist/commonjs/ignore.js.map @@ -1 +1 @@ -{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/ignore.ts"],"names":[],"mappings":"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","sourcesContent":["// give it a pattern, and it'll be able to tell you if\n// a given path should be ignored.\n// Ignoring a path ignores its children if the pattern ends in /**\n// Ignores are always parsed in dot:true mode\n\nimport { Minimatch } from 'minimatch'\nimport { Path } from 'path-scurry'\nimport { Pattern } from './pattern.js'\nimport { GlobWalkerOpts } from './walker.js'\n\nexport interface IgnoreLike {\n ignored?: (p: Path) => boolean\n childrenIgnored?: (p: Path) => boolean\n}\n\nconst defaultPlatform: NodeJS.Platform =\n typeof process === 'object' &&\n process &&\n typeof process.platform === 'string'\n ? process.platform\n : 'linux'\n\n/**\n * Class used to process ignored patterns\n */\nexport class Ignore implements IgnoreLike {\n relative: Minimatch[]\n relativeChildren: Minimatch[]\n absolute: Minimatch[]\n absoluteChildren: Minimatch[]\n\n constructor(\n ignored: string[],\n {\n nobrace,\n nocase,\n noext,\n noglobstar,\n platform = defaultPlatform,\n }: GlobWalkerOpts\n ) {\n this.relative = []\n this.absolute = []\n this.relativeChildren = []\n this.absoluteChildren = []\n const mmopts = {\n dot: true,\n nobrace,\n nocase,\n noext,\n noglobstar,\n optimizationLevel: 2,\n platform,\n nocomment: true,\n nonegate: true,\n }\n\n // this is a little weird, but it gives us a clean set of optimized\n // minimatch matchers, without getting tripped up if one of them\n // ends in /** inside a brace section, and it's only inefficient at\n // the start of the walk, not along it.\n // It'd be nice if the Pattern class just had a .test() method, but\n // handling globstars is a bit of a pita, and that code already lives\n // in minimatch anyway.\n // Another way would be if maybe Minimatch could take its set/globParts\n // as an option, and then we could at least just use Pattern to test\n // for absolute-ness.\n // Yet another way, Minimatch could take an array of glob strings, and\n // a cwd option, and do the right thing.\n for (const ign of ignored) {\n const mm = new Minimatch(ign, mmopts)\n for (let i = 0; i < mm.set.length; i++) {\n const parsed = mm.set[i]\n const globParts = mm.globParts[i]\n /* c8 ignore start */\n if (!parsed || !globParts) {\n throw new Error('invalid pattern object')\n }\n /* c8 ignore stop */\n const p = new Pattern(parsed, globParts, 0, platform)\n const m = new Minimatch(p.globString(), mmopts)\n const children = globParts[globParts.length - 1] === '**'\n const absolute = p.isAbsolute()\n if (absolute) this.absolute.push(m)\n else this.relative.push(m)\n if (children) {\n if (absolute) this.absoluteChildren.push(m)\n else this.relativeChildren.push(m)\n }\n }\n }\n }\n\n ignored(p: Path): boolean {\n const fullpath = p.fullpath()\n const fullpaths = `${fullpath}/`\n const relative = p.relative() || '.'\n const relatives = `${relative}/`\n for (const m of this.relative) {\n if (m.match(relative) || m.match(relatives)) return true\n }\n for (const m of this.absolute) {\n if (m.match(fullpath) || m.match(fullpaths)) return true\n }\n return false\n }\n\n childrenIgnored(p: Path): boolean {\n const fullpath = p.fullpath() + '/'\n const relative = (p.relative() || '.') + '/'\n for (const m of this.relativeChildren) {\n if (m.match(relative)) return true\n }\n for (const m of this.absoluteChildren) {\n if (m.match(fullpath)) return true\n }\n return false\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/ignore.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,kCAAkC;AAClC,kEAAkE;AAClE,6CAA6C;;;AAE7C,yCAAqC;AAErC,6CAAsC;AAQtC,MAAM,eAAe,GACnB,OAAO,OAAO,KAAK,QAAQ;IAC3B,OAAO;IACP,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;IAClC,CAAC,CAAC,OAAO,CAAC,QAAQ;IAClB,CAAC,CAAC,OAAO,CAAA;AAEb;;GAEG;AACH,MAAa,MAAM;IACjB,QAAQ,CAAa;IACrB,gBAAgB,CAAa;IAC7B,QAAQ,CAAa;IACrB,gBAAgB,CAAa;IAE7B,YACE,OAAiB,EACjB,EACE,OAAO,EACP,MAAM,EACN,KAAK,EACL,UAAU,EACV,QAAQ,GAAG,eAAe,GACX;QAEjB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;QAClB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;QAClB,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAA;QAC1B,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAA;QAC1B,MAAM,MAAM,GAAG;YACb,GAAG,EAAE,IAAI;YACT,OAAO;YACP,MAAM;YACN,KAAK;YACL,UAAU;YACV,iBAAiB,EAAE,CAAC;YACpB,QAAQ;YACR,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,IAAI;SACf,CAAA;QAED,mEAAmE;QACnE,gEAAgE;QAChE,mEAAmE;QACnE,uCAAuC;QACvC,mEAAmE;QACnE,qEAAqE;QACrE,uBAAuB;QACvB,uEAAuE;QACvE,oEAAoE;QACpE,qBAAqB;QACrB,sEAAsE;QACtE,wCAAwC;QACxC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE;YACzB,MAAM,EAAE,GAAG,IAAI,qBAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;YACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBACtC,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;gBACxB,MAAM,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;gBACjC,qBAAqB;gBACrB,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE;oBACzB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAA;iBAC1C;gBACD,gCAAgC;gBAChC,iDAAiD;gBACjD,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;oBAChD,MAAM,CAAC,KAAK,EAAE,CAAA;oBACd,SAAS,CAAC,KAAK,EAAE,CAAA;iBAClB;gBACD,oBAAoB;gBACpB,MAAM,CAAC,GAAG,IAAI,oBAAO,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAA;gBACrD,MAAM,CAAC,GAAG,IAAI,qBAAS,CAAC,CAAC,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,CAAA;gBAC/C,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,CAAA;gBACzD,MAAM,QAAQ,GAAG,CAAC,CAAC,UAAU,EAAE,CAAA;gBAC/B,IAAI,QAAQ;oBAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;;oBAC9B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBAC1B,IAAI,QAAQ,EAAE;oBACZ,IAAI,QAAQ;wBAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;;wBACtC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;iBACnC;aACF;SACF;IACH,CAAC;IAED,OAAO,CAAC,CAAO;QACb,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAA;QAC7B,MAAM,SAAS,GAAG,GAAG,QAAQ,GAAG,CAAA;QAChC,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,GAAG,CAAA;QACpC,MAAM,SAAS,GAAG,GAAG,QAAQ,GAAG,CAAA;QAChC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAC7B,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAA;SACzD;QACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAC7B,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAA;SACzD;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,eAAe,CAAC,CAAO;QACrB,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAA;QACnC,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,GAAG,CAAC,GAAG,GAAG,CAAA;QAC5C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACrC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;gBAAE,OAAO,IAAI,CAAA;SACnC;QACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACrC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;gBAAE,OAAO,IAAI,CAAA;SACnC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;CACF;AAnGD,wBAmGC","sourcesContent":["// give it a pattern, and it'll be able to tell you if\n// a given path should be ignored.\n// Ignoring a path ignores its children if the pattern ends in /**\n// Ignores are always parsed in dot:true mode\n\nimport { Minimatch } from 'minimatch'\nimport { Path } from 'path-scurry'\nimport { Pattern } from './pattern.js'\nimport { GlobWalkerOpts } from './walker.js'\n\nexport interface IgnoreLike {\n ignored?: (p: Path) => boolean\n childrenIgnored?: (p: Path) => boolean\n}\n\nconst defaultPlatform: NodeJS.Platform =\n typeof process === 'object' &&\n process &&\n typeof process.platform === 'string'\n ? process.platform\n : 'linux'\n\n/**\n * Class used to process ignored patterns\n */\nexport class Ignore implements IgnoreLike {\n relative: Minimatch[]\n relativeChildren: Minimatch[]\n absolute: Minimatch[]\n absoluteChildren: Minimatch[]\n\n constructor(\n ignored: string[],\n {\n nobrace,\n nocase,\n noext,\n noglobstar,\n platform = defaultPlatform,\n }: GlobWalkerOpts\n ) {\n this.relative = []\n this.absolute = []\n this.relativeChildren = []\n this.absoluteChildren = []\n const mmopts = {\n dot: true,\n nobrace,\n nocase,\n noext,\n noglobstar,\n optimizationLevel: 2,\n platform,\n nocomment: true,\n nonegate: true,\n }\n\n // this is a little weird, but it gives us a clean set of optimized\n // minimatch matchers, without getting tripped up if one of them\n // ends in /** inside a brace section, and it's only inefficient at\n // the start of the walk, not along it.\n // It'd be nice if the Pattern class just had a .test() method, but\n // handling globstars is a bit of a pita, and that code already lives\n // in minimatch anyway.\n // Another way would be if maybe Minimatch could take its set/globParts\n // as an option, and then we could at least just use Pattern to test\n // for absolute-ness.\n // Yet another way, Minimatch could take an array of glob strings, and\n // a cwd option, and do the right thing.\n for (const ign of ignored) {\n const mm = new Minimatch(ign, mmopts)\n for (let i = 0; i < mm.set.length; i++) {\n const parsed = mm.set[i]\n const globParts = mm.globParts[i]\n /* c8 ignore start */\n if (!parsed || !globParts) {\n throw new Error('invalid pattern object')\n }\n // strip off leading ./ portions\n // https://github.com/isaacs/node-glob/issues/570\n while (parsed[0] === '.' && globParts[0] === '.') {\n parsed.shift()\n globParts.shift()\n }\n /* c8 ignore stop */\n const p = new Pattern(parsed, globParts, 0, platform)\n const m = new Minimatch(p.globString(), mmopts)\n const children = globParts[globParts.length - 1] === '**'\n const absolute = p.isAbsolute()\n if (absolute) this.absolute.push(m)\n else this.relative.push(m)\n if (children) {\n if (absolute) this.absoluteChildren.push(m)\n else this.relativeChildren.push(m)\n }\n }\n }\n }\n\n ignored(p: Path): boolean {\n const fullpath = p.fullpath()\n const fullpaths = `${fullpath}/`\n const relative = p.relative() || '.'\n const relatives = `${relative}/`\n for (const m of this.relative) {\n if (m.match(relative) || m.match(relatives)) return true\n }\n for (const m of this.absolute) {\n if (m.match(fullpath) || m.match(fullpaths)) return true\n }\n return false\n }\n\n childrenIgnored(p: Path): boolean {\n const fullpath = p.fullpath() + '/'\n const relative = (p.relative() || '.') + '/'\n for (const m of this.relativeChildren) {\n if (m.match(relative)) return true\n }\n for (const m of this.absoluteChildren) {\n if (m.match(fullpath)) return true\n }\n return false\n }\n}\n"]} \ No newline at end of file diff --git a/deps/npm/node_modules/glob/dist/commonjs/package.json b/deps/npm/node_modules/glob/dist/commonjs/package.json index 0292b9956f2e40..5bbefffbabee39 100644 --- a/deps/npm/node_modules/glob/dist/commonjs/package.json +++ b/deps/npm/node_modules/glob/dist/commonjs/package.json @@ -1 +1,3 @@ -{"type":"commonjs"} \ No newline at end of file +{ + "type": "commonjs" +} diff --git a/deps/npm/node_modules/glob/dist/commonjs/walker.d.ts.map b/deps/npm/node_modules/glob/dist/commonjs/walker.d.ts.map index 7c8df20b2f323c..2cae287c2e1f42 100644 --- a/deps/npm/node_modules/glob/dist/commonjs/walker.d.ts.map +++ b/deps/npm/node_modules/glob/dist/commonjs/walker.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"walker.d.ts","sourceRoot":"","sources":["../../src/walker.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAClC,OAAO,EAAU,UAAU,EAAE,MAAM,aAAa,CAAA;AAOhD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAA;IAClB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,UAAU,CAAA;IACvC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;IAGnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG;IAC9C,aAAa,EAAE,IAAI,CAAA;CACpB,CAAA;AACD,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG;IAC/C,aAAa,EAAE,KAAK,CAAA;CACrB,CAAA;AACD,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG;IAC/C,aAAa,CAAC,EAAE,SAAS,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,cAAc,IAAI,CAAC,SAAS,gBAAgB,GACrE,IAAI,GACJ,CAAC,SAAS,iBAAiB,GAC3B,MAAM,GACN,CAAC,SAAS,iBAAiB,GAC3B,MAAM,GACN,IAAI,GAAG,MAAM,CAAA;AAEjB,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,cAAc,IAAI,CAAC,SAAS,gBAAgB,GACtE,GAAG,CAAC,IAAI,CAAC,GACT,CAAC,SAAS,iBAAiB,GAC3B,GAAG,CAAC,MAAM,CAAC,GACX,CAAC,SAAS,iBAAiB,GAC3B,GAAG,CAAC,MAAM,CAAC,GACX,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,CAAA;AAEtB,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,cAAc,IAC9C,CAAC,SAAS,gBAAgB,GACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,GACpB,CAAC,SAAS,iBAAiB,GAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,GACxB,CAAC,SAAS,iBAAiB,GAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,GACxB,QAAQ,CAAC,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAA;AAY5C;;GAEG;AACH,8BAAsB,QAAQ,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc;;IACtE,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,IAAI,EAAE,CAAC,CAAA;IACP,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAkB;IACjC,MAAM,EAAE,OAAO,CAAQ;IACvB,OAAO,EAAE,OAAO,CAAQ;IAIxB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;gBAEJ,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IA8BpD,KAAK;IAGL,MAAM;IAUN,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG;IAahB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAYpE,cAAc,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS;IAUrE,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS;IAYzD,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;IACtC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAE1C,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO;IAsBhC,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtE,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAK3D,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG;IAOvD,OAAO,CACL,MAAM,EAAE,IAAI,EACZ,QAAQ,EAAE,OAAO,EAAE,EACnB,SAAS,EAAE,SAAS,EACpB,EAAE,EAAE,MAAM,GAAG;IA2Cf,OAAO,CACL,MAAM,EAAE,IAAI,EACZ,OAAO,EAAE,IAAI,EAAE,EACf,SAAS,EAAE,SAAS,EACpB,EAAE,EAAE,MAAM,GAAG;IAsBf,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG;IAO3D,WAAW,CACT,MAAM,EAAE,IAAI,EACZ,QAAQ,EAAE,OAAO,EAAE,EACnB,SAAS,EAAE,SAAS,EACpB,EAAE,EAAE,MAAM,GAAG;IAqCf,WAAW,CACT,MAAM,EAAE,IAAI,EACZ,OAAO,EAAE,IAAI,EAAE,EACf,SAAS,EAAE,SAAS,EACpB,EAAE,EAAE,MAAM,GAAG;CAoBhB;AAED,qBAAa,UAAU,CACrB,CAAC,SAAS,cAAc,GAAG,cAAc,CACzC,SAAQ,QAAQ,CAAC,CAAC,CAAC;IACnB,OAAO,EAAE,CAAC,SAAS,gBAAgB,GAC/B,GAAG,CAAC,IAAI,CAAC,GACT,CAAC,SAAS,iBAAiB,GAC3B,GAAG,CAAC,MAAM,CAAC,GACX,CAAC,SAAS,iBAAiB,GAC3B,GAAG,CAAC,MAAM,CAAC,GACX,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,CAAA;gBAEV,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAKpD,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;IAKvB,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAiBjC,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC;CAWvB;AAED,qBAAa,UAAU,CACrB,CAAC,SAAS,cAAc,GAAG,cAAc,CACzC,SAAQ,QAAQ,CAAC,CAAC,CAAC;IACnB,OAAO,EAAE,CAAC,SAAS,gBAAgB,GAC/B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,GACpB,CAAC,SAAS,iBAAiB,GAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,GACxB,CAAC,SAAS,iBAAiB,GAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,GACxB,QAAQ,CAAC,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAA;gBAE9B,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAUpD,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;IAM7B,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC;IAYxB,UAAU,IAAI,WAAW,CAAC,CAAC,CAAC;CAO7B"} \ No newline at end of file +{"version":3,"file":"walker.d.ts","sourceRoot":"","sources":["../../src/walker.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/deps/npm/node_modules/glob/dist/commonjs/walker.js b/deps/npm/node_modules/glob/dist/commonjs/walker.js index 9651ce1164016c..20cec70fdf95f5 100644 --- a/deps/npm/node_modules/glob/dist/commonjs/walker.js +++ b/deps/npm/node_modules/glob/dist/commonjs/walker.js @@ -96,13 +96,26 @@ class GlobUtil { e = rpc; } const needStat = e.isUnknown() || this.opts.stat; - return this.matchCheckTest(needStat ? await e.lstat() : e, ifDir); + const s = needStat ? await e.lstat() : e; + if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) { + const target = await s.realpath(); + /* c8 ignore start */ + if (target && (target.isUnknown() || this.opts.stat)) { + await target.lstat(); + } + /* c8 ignore stop */ + } + return this.matchCheckTest(s, ifDir); } matchCheckTest(e, ifDir) { return e && (this.maxDepth === Infinity || e.depth() <= this.maxDepth) && (!ifDir || e.canReaddir()) && (!this.opts.nodir || !e.isDirectory()) && + (!this.opts.nodir || + !this.opts.follow || + !e.isSymbolicLink() || + !e.realpathCached()?.isDirectory()) && !this.#ignored(e) ? e : undefined; @@ -118,7 +131,14 @@ class GlobUtil { e = rpc; } const needStat = e.isUnknown() || this.opts.stat; - return this.matchCheckTest(needStat ? e.lstatSync() : e, ifDir); + const s = needStat ? e.lstatSync() : e; + if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) { + const target = s.realpathSync(); + if (target && (target?.isUnknown() || this.opts.stat)) { + target.lstatSync(); + } + } + return this.matchCheckTest(s, ifDir); } matchFinish(e, absolute) { if (this.#ignored(e)) diff --git a/deps/npm/node_modules/glob/dist/commonjs/walker.js.map b/deps/npm/node_modules/glob/dist/commonjs/walker.js.map index ad1cd5f8379893..5c2a58531858b0 100644 --- a/deps/npm/node_modules/glob/dist/commonjs/walker.js.map +++ b/deps/npm/node_modules/glob/dist/commonjs/walker.js.map @@ -1 +1 @@ -{"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/walker.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Single-use utility classes to provide functionality to the {@link Glob}\n * methods.\n *\n * @module\n */\nimport { Minipass } from 'minipass'\nimport { Path } from 'path-scurry'\nimport { Ignore, IgnoreLike } from './ignore.js'\n\n// XXX can we somehow make it so that it NEVER processes a given path more than\n// once, enough that the match set tracking is no longer needed? that'd speed\n// things up a lot. Or maybe bring back nounique, and skip it in that case?\n\n// a single minimatch set entry with 1 or more parts\nimport { Pattern } from './pattern.js'\nimport { Processor } from './processor.js'\n\nexport interface GlobWalkerOpts {\n absolute?: boolean\n allowWindowsEscape?: boolean\n cwd?: string | URL\n dot?: boolean\n dotRelative?: boolean\n follow?: boolean\n ignore?: string | string[] | IgnoreLike\n mark?: boolean\n matchBase?: boolean\n // Note: maxDepth here means \"maximum actual Path.depth()\",\n // not \"maximum depth beyond cwd\"\n maxDepth?: number\n nobrace?: boolean\n nocase?: boolean\n nodir?: boolean\n noext?: boolean\n noglobstar?: boolean\n platform?: NodeJS.Platform\n posix?: boolean\n realpath?: boolean\n root?: string\n stat?: boolean\n signal?: AbortSignal\n windowsPathsNoEscape?: boolean\n withFileTypes?: boolean\n}\n\nexport type GWOFileTypesTrue = GlobWalkerOpts & {\n withFileTypes: true\n}\nexport type GWOFileTypesFalse = GlobWalkerOpts & {\n withFileTypes: false\n}\nexport type GWOFileTypesUnset = GlobWalkerOpts & {\n withFileTypes?: undefined\n}\n\nexport type Result = O extends GWOFileTypesTrue\n ? Path\n : O extends GWOFileTypesFalse\n ? string\n : O extends GWOFileTypesUnset\n ? string\n : Path | string\n\nexport type Matches = O extends GWOFileTypesTrue\n ? Set\n : O extends GWOFileTypesFalse\n ? Set\n : O extends GWOFileTypesUnset\n ? Set\n : Set\n\nexport type MatchStream =\n O extends GWOFileTypesTrue\n ? Minipass\n : O extends GWOFileTypesFalse\n ? Minipass\n : O extends GWOFileTypesUnset\n ? Minipass\n : Minipass\n\nconst makeIgnore = (\n ignore: string | string[] | IgnoreLike,\n opts: GlobWalkerOpts\n): IgnoreLike =>\n typeof ignore === 'string'\n ? new Ignore([ignore], opts)\n : Array.isArray(ignore)\n ? new Ignore(ignore, opts)\n : ignore\n\n/**\n * basic walking utilities that all the glob walker types use\n */\nexport abstract class GlobUtil {\n path: Path\n patterns: Pattern[]\n opts: O\n seen: Set = new Set()\n paused: boolean = false\n aborted: boolean = false\n #onResume: (() => any)[] = []\n #ignore?: IgnoreLike\n #sep: '\\\\' | '/'\n signal?: AbortSignal\n maxDepth: number\n\n constructor(patterns: Pattern[], path: Path, opts: O)\n constructor(patterns: Pattern[], path: Path, opts: O) {\n this.patterns = patterns\n this.path = path\n this.opts = opts\n this.#sep = !opts.posix && opts.platform === 'win32' ? '\\\\' : '/'\n if (opts.ignore) {\n this.#ignore = makeIgnore(opts.ignore, opts)\n }\n // ignore, always set with maxDepth, but it's optional on the\n // GlobOptions type\n /* c8 ignore start */\n this.maxDepth = opts.maxDepth || Infinity\n /* c8 ignore stop */\n if (opts.signal) {\n this.signal = opts.signal\n this.signal.addEventListener('abort', () => {\n this.#onResume.length = 0\n })\n }\n }\n\n #ignored(path: Path): boolean {\n return this.seen.has(path) || !!this.#ignore?.ignored?.(path)\n }\n #childrenIgnored(path: Path): boolean {\n return !!this.#ignore?.childrenIgnored?.(path)\n }\n\n // backpressure mechanism\n pause() {\n this.paused = true\n }\n resume() {\n /* c8 ignore start */\n if (this.signal?.aborted) return\n /* c8 ignore stop */\n this.paused = false\n let fn: (() => any) | undefined = undefined\n while (!this.paused && (fn = this.#onResume.shift())) {\n fn()\n }\n }\n onResume(fn: () => any) {\n if (this.signal?.aborted) return\n /* c8 ignore start */\n if (!this.paused) {\n fn()\n } else {\n /* c8 ignore stop */\n this.#onResume.push(fn)\n }\n }\n\n // do the requisite realpath/stat checking, and return the path\n // to add or undefined to filter it out.\n async matchCheck(e: Path, ifDir: boolean): Promise {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || (await e.realpath())\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n return this.matchCheckTest(needStat ? await e.lstat() : e, ifDir)\n }\n\n matchCheckTest(e: Path | undefined, ifDir: boolean): Path | undefined {\n return e &&\n (this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&\n (!ifDir || e.canReaddir()) &&\n (!this.opts.nodir || !e.isDirectory()) &&\n !this.#ignored(e)\n ? e\n : undefined\n }\n\n matchCheckSync(e: Path, ifDir: boolean): Path | undefined {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || e.realpathSync()\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n return this.matchCheckTest(needStat ? e.lstatSync() : e, ifDir)\n }\n\n abstract matchEmit(p: Result): void\n abstract matchEmit(p: string | Path): void\n\n matchFinish(e: Path, absolute: boolean) {\n if (this.#ignored(e)) return\n const abs =\n this.opts.absolute === undefined ? absolute : this.opts.absolute\n this.seen.add(e)\n const mark = this.opts.mark && e.isDirectory() ? this.#sep : ''\n // ok, we have what we need!\n if (this.opts.withFileTypes) {\n this.matchEmit(e)\n } else if (abs) {\n const abs = this.opts.posix ? e.fullpathPosix() : e.fullpath()\n this.matchEmit(abs + mark)\n } else {\n const rel = this.opts.posix ? e.relativePosix() : e.relative()\n const pre =\n this.opts.dotRelative && !rel.startsWith('..' + this.#sep)\n ? '.' + this.#sep\n : ''\n this.matchEmit(!rel ? '.' + mark : pre + rel + mark)\n }\n }\n\n async match(e: Path, absolute: boolean, ifDir: boolean): Promise {\n const p = await this.matchCheck(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n matchSync(e: Path, absolute: boolean, ifDir: boolean): void {\n const p = this.matchCheckSync(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n walkCB(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() => this.walkCB2(target, patterns, processor, cb))\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const childrenCached = t.readdirCached()\n if (t.calledReaddir())\n this.walkCB3(t, childrenCached, processor, next)\n else {\n t.readdirCB(\n (_, entries) => this.walkCB3(t, entries, processor, next),\n true\n )\n }\n }\n\n next()\n }\n\n walkCB3(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2(target, patterns, processor.child(), next)\n }\n\n next()\n }\n\n walkCBSync(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2Sync(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2Sync(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() =>\n this.walkCB2Sync(target, patterns, processor, cb)\n )\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const children = t.readdirSync()\n this.walkCB3Sync(t, children, processor, next)\n }\n\n next()\n }\n\n walkCB3Sync(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2Sync(target, patterns, processor.child(), next)\n }\n\n next()\n }\n}\n\nexport class GlobWalker<\n O extends GlobWalkerOpts = GlobWalkerOpts\n> extends GlobUtil {\n matches: O extends GWOFileTypesTrue\n ? Set\n : O extends GWOFileTypesFalse\n ? Set\n : O extends GWOFileTypesUnset\n ? Set\n : Set\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.matches = new Set() as Matches\n }\n\n matchEmit(e: Result): void\n matchEmit(e: Path | string): void {\n this.matches.add(e)\n }\n\n async walk(): Promise> {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n await this.path.lstat()\n }\n await new Promise((res, rej) => {\n this.walkCB(this.path, this.patterns, () => {\n if (this.signal?.aborted) {\n rej(this.signal.reason)\n } else {\n res(this.matches)\n }\n })\n })\n return this.matches\n }\n\n walkSync(): Matches {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n // nothing for the callback to do, because this never pauses\n this.walkCBSync(this.path, this.patterns, () => {\n if (this.signal?.aborted) throw this.signal.reason\n })\n return this.matches\n }\n}\n\nexport class GlobStream<\n O extends GlobWalkerOpts = GlobWalkerOpts\n> extends GlobUtil {\n results: O extends GWOFileTypesTrue\n ? Minipass\n : O extends GWOFileTypesFalse\n ? Minipass\n : O extends GWOFileTypesUnset\n ? Minipass\n : Minipass\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.results = new Minipass({\n signal: this.signal,\n objectMode: true,\n }) as MatchStream\n this.results.on('drain', () => this.resume())\n this.results.on('resume', () => this.resume())\n }\n\n matchEmit(e: Result): void\n matchEmit(e: Path | string): void {\n this.results.write(e)\n if (!this.results.flowing) this.pause()\n }\n\n stream(): MatchStream {\n const target = this.path\n if (target.isUnknown()) {\n target.lstat().then(() => {\n this.walkCB(target, this.patterns, () => this.results.end())\n })\n } else {\n this.walkCB(target, this.patterns, () => this.results.end())\n }\n return this.results\n }\n\n streamSync(): MatchStream {\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n this.walkCBSync(this.path, this.patterns, () => this.results.end())\n return this.results\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/walker.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,uCAAmC;AAEnC,2CAAgD;AAQhD,iDAA0C;AAiE1C,MAAM,UAAU,GAAG,CACjB,MAAsC,EACtC,IAAoB,EACR,EAAE,CACd,OAAO,MAAM,KAAK,QAAQ;IACxB,CAAC,CAAC,IAAI,kBAAM,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;IAC5B,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QACvB,CAAC,CAAC,IAAI,kBAAM,CAAC,MAAM,EAAE,IAAI,CAAC;QAC1B,CAAC,CAAC,MAAM,CAAA;AAEZ;;GAEG;AACH,MAAsB,QAAQ;IAC5B,IAAI,CAAM;IACV,QAAQ,CAAW;IACnB,IAAI,CAAG;IACP,IAAI,GAAc,IAAI,GAAG,EAAQ,CAAA;IACjC,MAAM,GAAY,KAAK,CAAA;IACvB,OAAO,GAAY,KAAK,CAAA;IACxB,SAAS,GAAkB,EAAE,CAAA;IAC7B,OAAO,CAAa;IACpB,IAAI,CAAY;IAChB,MAAM,CAAc;IACpB,QAAQ,CAAQ;IAGhB,YAAY,QAAmB,EAAE,IAAU,EAAE,IAAO;QAClD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAA;QACjE,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;SAC7C;QACD,6DAA6D;QAC7D,mBAAmB;QACnB,qBAAqB;QACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAA;QACzC,oBAAoB;QACpB,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;YACzB,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;gBACzC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAA;YAC3B,CAAC,CAAC,CAAA;SACH;IACH,CAAC;IAED,QAAQ,CAAC,IAAU;QACjB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,CAAA;IAC/D,CAAC;IACD,gBAAgB,CAAC,IAAU;QACzB,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC,IAAI,CAAC,CAAA;IAChD,CAAC;IAED,yBAAyB;IACzB,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;IACpB,CAAC;IACD,MAAM;QACJ,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,OAAM;QAChC,oBAAoB;QACpB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,EAAE,GAA4B,SAAS,CAAA;QAC3C,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE;YACpD,EAAE,EAAE,CAAA;SACL;IACH,CAAC;IACD,QAAQ,CAAC,EAAa;QACpB,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,OAAM;QAChC,qBAAqB;QACrB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAChB,EAAE,EAAE,CAAA;SACL;aAAM;YACL,oBAAoB;YACpB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;SACxB;IACH,CAAC;IAED,+DAA+D;IAC/D,wCAAwC;IACxC,KAAK,CAAC,UAAU,CAAC,CAAO,EAAE,KAAc;QACtC,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAA;QAC9C,IAAI,GAAqB,CAAA;QACzB,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACtB,GAAG,GAAG,CAAC,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;YAChD,IAAI,CAAC,GAAG;gBAAE,OAAO,SAAS,CAAA;YAC1B,CAAC,GAAG,GAAG,CAAA;SACR;QACD,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;QAChD,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QACxC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE,cAAc,EAAE,EAAE;YAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAA;YACjC,qBAAqB;YACrB,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACpD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;aACrB;YACD,oBAAoB;SACrB;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACtC,CAAC;IAED,cAAc,CAAC,CAAmB,EAAE,KAAc;QAChD,OAAO,CAAC;YACN,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC;YAC1D,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;YAC1B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACtC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;gBACf,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;gBACjB,CAAC,CAAC,CAAC,cAAc,EAAE;gBACnB,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,CAAC;YACrC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YACjB,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,SAAS,CAAA;IACf,CAAC;IAED,cAAc,CAAC,CAAO,EAAE,KAAc;QACpC,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAA;QAC9C,IAAI,GAAqB,CAAA;QACzB,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACtB,GAAG,GAAG,CAAC,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,YAAY,EAAE,CAAA;YAC5C,IAAI,CAAC,GAAG;gBAAE,OAAO,SAAS,CAAA;YAC1B,CAAC,GAAG,GAAG,CAAA;SACR;QACD,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;QAChD,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QACtC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE,cAAc,EAAE,EAAE;YAC9D,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,EAAE,CAAA;YAC/B,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACrD,MAAM,CAAC,SAAS,EAAE,CAAA;aACnB;SACF;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACtC,CAAC;IAKD,WAAW,CAAC,CAAO,EAAE,QAAiB;QACpC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAM;QAC5B,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAA;QAClE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;QAC/D,4BAA4B;QAC5B,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YAC3B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;SAClB;aAAM,IAAI,GAAG,EAAE;YACd,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;YAC9D,IAAI,CAAC,SAAS,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;SAC3B;aAAM;YACL,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;YAC9D,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;gBACxD,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI;gBACjB,CAAC,CAAC,EAAE,CAAA;YACR,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,CAAA;SACrD;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,CAAO,EAAE,QAAiB,EAAE,KAAc;QACpD,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;QACzC,IAAI,CAAC;YAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;IACtC,CAAC;IAED,SAAS,CAAC,CAAO,EAAE,QAAiB,EAAE,KAAc;QAClD,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;QACvC,IAAI,CAAC;YAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;IACtC,CAAC;IAED,MAAM,CAAC,MAAY,EAAE,QAAmB,EAAE,EAAa;QACrD,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,EAAE,EAAE,CAAA;QAC9B,oBAAoB;QACpB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,wBAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IAC9D,CAAC;IAED,OAAO,CACL,MAAY,EACZ,QAAmB,EACnB,SAAoB,EACpB,EAAa;QAEb,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,EAAE,CAAA;QAC9C,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,EAAE,EAAE,CAAA;QAC9B,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,CAAA;YAClE,OAAM;SACP;QACD,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAE3C,qEAAqE;QACrE,4DAA4D;QAC5D,yDAAyD;QACzD,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,EAAE,KAAK,KAAK,CAAC;gBAAE,EAAE,EAAE,CAAA;QACzB,CAAC,CAAA;QAED,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE;YAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAQ;YAC9B,KAAK,EAAE,CAAA;YACP,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;SAClD;QAED,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,cAAc,EAAE,EAAE;YAC1C,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE;gBAC5D,SAAQ;aACT;YACD,KAAK,EAAE,CAAA;YACP,MAAM,cAAc,GAAG,CAAC,CAAC,aAAa,EAAE,CAAA;YACxC,IAAI,CAAC,CAAC,aAAa,EAAE;gBACnB,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,CAAC,CAAA;iBAC7C;gBACH,CAAC,CAAC,SAAS,CACT,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,EACzD,IAAI,CACL,CAAA;aACF;SACF;QAED,IAAI,EAAE,CAAA;IACR,CAAC;IAED,OAAO,CACL,MAAY,EACZ,OAAe,EACf,SAAoB,EACpB,EAAa;QAEb,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAEpD,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,EAAE,KAAK,KAAK,CAAC;gBAAE,EAAE,EAAE,CAAA;QACzB,CAAC,CAAA;QAED,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE;YAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAQ;YAC9B,KAAK,EAAE,CAAA;YACP,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;SAClD;QACD,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;YAC7D,KAAK,EAAE,CAAA;YACP,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAA;SACxD;QAED,IAAI,EAAE,CAAA;IACR,CAAC;IAED,UAAU,CAAC,MAAY,EAAE,QAAmB,EAAE,EAAa;QACzD,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,EAAE,EAAE,CAAA;QAC9B,oBAAoB;QACpB,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,wBAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IAClE,CAAC;IAED,WAAW,CACT,MAAY,EACZ,QAAmB,EACnB,SAAoB,EACpB,EAAa;QAEb,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,EAAE,CAAA;QAC9C,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,EAAE,EAAE,CAAA;QAC9B,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CACjB,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,CAAC,CAClD,CAAA;YACD,OAAM;SACP;QACD,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAE3C,qEAAqE;QACrE,4DAA4D;QAC5D,yDAAyD;QACzD,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,EAAE,KAAK,KAAK,CAAC;gBAAE,EAAE,EAAE,CAAA;QACzB,CAAC,CAAA;QAED,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE;YAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAQ;YAC9B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;SACnC;QAED,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,cAAc,EAAE,EAAE;YAC1C,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE;gBAC5D,SAAQ;aACT;YACD,KAAK,EAAE,CAAA;YACP,MAAM,QAAQ,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;YAChC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,CAAA;SAC/C;QAED,IAAI,EAAE,CAAA;IACR,CAAC;IAED,WAAW,CACT,MAAY,EACZ,OAAe,EACf,SAAoB,EACpB,EAAa;QAEb,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAEpD,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,EAAE,KAAK,KAAK,CAAC;gBAAE,EAAE,EAAE,CAAA;QACzB,CAAC,CAAA;QAED,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE;YAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAQ;YAC9B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;SACnC;QACD,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;YAC7D,KAAK,EAAE,CAAA;YACP,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAA;SAC5D;QAED,IAAI,EAAE,CAAA;IACR,CAAC;CACF;AAtTD,4BAsTC;AAED,MAAa,UAEX,SAAQ,QAAW;IACnB,OAAO,CAMe;IAEtB,YAAY,QAAmB,EAAE,IAAU,EAAE,IAAO;QAClD,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAgB,CAAA;IACxC,CAAC;IAGD,SAAS,CAAC,CAAgB;QACxB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA;QAClD,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;YACzB,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;SACxB;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACzC,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE;oBACxB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;iBACxB;qBAAM;oBACL,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;iBAClB;YACH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,QAAQ;QACN,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA;QAClD,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;YACzB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAA;SACtB;QACD,4DAA4D;QAC5D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC7C,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA;QACpD,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;CACF;AAjDD,gCAiDC;AAED,MAAa,UAEX,SAAQ,QAAW;IACnB,OAAO,CAMmC;IAE1C,YAAY,QAAmB,EAAE,IAAU,EAAE,IAAO;QAClD,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,mBAAQ,CAAC;YAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI;SACjB,CAAmB,CAAA;QACpB,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;QAC7C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;IAChD,CAAC;IAGD,SAAS,CAAC,CAAgB;QACxB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACrB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,IAAI,CAAC,KAAK,EAAE,CAAA;IACzC,CAAC;IAED,MAAM;QACJ,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAA;QACxB,IAAI,MAAM,CAAC,SAAS,EAAE,EAAE;YACtB,MAAM,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;gBACvB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;YAC9D,CAAC,CAAC,CAAA;SACH;aAAM;YACL,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;SAC7D;QACD,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;YACzB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAA;SACtB;QACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;QACnE,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;CACF;AA9CD,gCA8CC","sourcesContent":["/**\n * Single-use utility classes to provide functionality to the {@link Glob}\n * methods.\n *\n * @module\n */\nimport { Minipass } from 'minipass'\nimport { Path } from 'path-scurry'\nimport { Ignore, IgnoreLike } from './ignore.js'\n\n// XXX can we somehow make it so that it NEVER processes a given path more than\n// once, enough that the match set tracking is no longer needed? that'd speed\n// things up a lot. Or maybe bring back nounique, and skip it in that case?\n\n// a single minimatch set entry with 1 or more parts\nimport { Pattern } from './pattern.js'\nimport { Processor } from './processor.js'\n\nexport interface GlobWalkerOpts {\n absolute?: boolean\n allowWindowsEscape?: boolean\n cwd?: string | URL\n dot?: boolean\n dotRelative?: boolean\n follow?: boolean\n ignore?: string | string[] | IgnoreLike\n mark?: boolean\n matchBase?: boolean\n // Note: maxDepth here means \"maximum actual Path.depth()\",\n // not \"maximum depth beyond cwd\"\n maxDepth?: number\n nobrace?: boolean\n nocase?: boolean\n nodir?: boolean\n noext?: boolean\n noglobstar?: boolean\n platform?: NodeJS.Platform\n posix?: boolean\n realpath?: boolean\n root?: string\n stat?: boolean\n signal?: AbortSignal\n windowsPathsNoEscape?: boolean\n withFileTypes?: boolean\n}\n\nexport type GWOFileTypesTrue = GlobWalkerOpts & {\n withFileTypes: true\n}\nexport type GWOFileTypesFalse = GlobWalkerOpts & {\n withFileTypes: false\n}\nexport type GWOFileTypesUnset = GlobWalkerOpts & {\n withFileTypes?: undefined\n}\n\nexport type Result = O extends GWOFileTypesTrue\n ? Path\n : O extends GWOFileTypesFalse\n ? string\n : O extends GWOFileTypesUnset\n ? string\n : Path | string\n\nexport type Matches = O extends GWOFileTypesTrue\n ? Set\n : O extends GWOFileTypesFalse\n ? Set\n : O extends GWOFileTypesUnset\n ? Set\n : Set\n\nexport type MatchStream =\n O extends GWOFileTypesTrue\n ? Minipass\n : O extends GWOFileTypesFalse\n ? Minipass\n : O extends GWOFileTypesUnset\n ? Minipass\n : Minipass\n\nconst makeIgnore = (\n ignore: string | string[] | IgnoreLike,\n opts: GlobWalkerOpts\n): IgnoreLike =>\n typeof ignore === 'string'\n ? new Ignore([ignore], opts)\n : Array.isArray(ignore)\n ? new Ignore(ignore, opts)\n : ignore\n\n/**\n * basic walking utilities that all the glob walker types use\n */\nexport abstract class GlobUtil {\n path: Path\n patterns: Pattern[]\n opts: O\n seen: Set = new Set()\n paused: boolean = false\n aborted: boolean = false\n #onResume: (() => any)[] = []\n #ignore?: IgnoreLike\n #sep: '\\\\' | '/'\n signal?: AbortSignal\n maxDepth: number\n\n constructor(patterns: Pattern[], path: Path, opts: O)\n constructor(patterns: Pattern[], path: Path, opts: O) {\n this.patterns = patterns\n this.path = path\n this.opts = opts\n this.#sep = !opts.posix && opts.platform === 'win32' ? '\\\\' : '/'\n if (opts.ignore) {\n this.#ignore = makeIgnore(opts.ignore, opts)\n }\n // ignore, always set with maxDepth, but it's optional on the\n // GlobOptions type\n /* c8 ignore start */\n this.maxDepth = opts.maxDepth || Infinity\n /* c8 ignore stop */\n if (opts.signal) {\n this.signal = opts.signal\n this.signal.addEventListener('abort', () => {\n this.#onResume.length = 0\n })\n }\n }\n\n #ignored(path: Path): boolean {\n return this.seen.has(path) || !!this.#ignore?.ignored?.(path)\n }\n #childrenIgnored(path: Path): boolean {\n return !!this.#ignore?.childrenIgnored?.(path)\n }\n\n // backpressure mechanism\n pause() {\n this.paused = true\n }\n resume() {\n /* c8 ignore start */\n if (this.signal?.aborted) return\n /* c8 ignore stop */\n this.paused = false\n let fn: (() => any) | undefined = undefined\n while (!this.paused && (fn = this.#onResume.shift())) {\n fn()\n }\n }\n onResume(fn: () => any) {\n if (this.signal?.aborted) return\n /* c8 ignore start */\n if (!this.paused) {\n fn()\n } else {\n /* c8 ignore stop */\n this.#onResume.push(fn)\n }\n }\n\n // do the requisite realpath/stat checking, and return the path\n // to add or undefined to filter it out.\n async matchCheck(e: Path, ifDir: boolean): Promise {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || (await e.realpath())\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n const s = needStat ? await e.lstat() : e\n if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {\n const target = await s.realpath()\n /* c8 ignore start */\n if (target && (target.isUnknown() || this.opts.stat)) {\n await target.lstat()\n }\n /* c8 ignore stop */\n }\n return this.matchCheckTest(s, ifDir)\n }\n\n matchCheckTest(e: Path | undefined, ifDir: boolean): Path | undefined {\n return e &&\n (this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&\n (!ifDir || e.canReaddir()) &&\n (!this.opts.nodir || !e.isDirectory()) &&\n (!this.opts.nodir ||\n !this.opts.follow ||\n !e.isSymbolicLink() ||\n !e.realpathCached()?.isDirectory()) &&\n !this.#ignored(e)\n ? e\n : undefined\n }\n\n matchCheckSync(e: Path, ifDir: boolean): Path | undefined {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || e.realpathSync()\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n const s = needStat ? e.lstatSync() : e\n if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {\n const target = s.realpathSync()\n if (target && (target?.isUnknown() || this.opts.stat)) {\n target.lstatSync()\n }\n }\n return this.matchCheckTest(s, ifDir)\n }\n\n abstract matchEmit(p: Result): void\n abstract matchEmit(p: string | Path): void\n\n matchFinish(e: Path, absolute: boolean) {\n if (this.#ignored(e)) return\n const abs =\n this.opts.absolute === undefined ? absolute : this.opts.absolute\n this.seen.add(e)\n const mark = this.opts.mark && e.isDirectory() ? this.#sep : ''\n // ok, we have what we need!\n if (this.opts.withFileTypes) {\n this.matchEmit(e)\n } else if (abs) {\n const abs = this.opts.posix ? e.fullpathPosix() : e.fullpath()\n this.matchEmit(abs + mark)\n } else {\n const rel = this.opts.posix ? e.relativePosix() : e.relative()\n const pre =\n this.opts.dotRelative && !rel.startsWith('..' + this.#sep)\n ? '.' + this.#sep\n : ''\n this.matchEmit(!rel ? '.' + mark : pre + rel + mark)\n }\n }\n\n async match(e: Path, absolute: boolean, ifDir: boolean): Promise {\n const p = await this.matchCheck(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n matchSync(e: Path, absolute: boolean, ifDir: boolean): void {\n const p = this.matchCheckSync(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n walkCB(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() => this.walkCB2(target, patterns, processor, cb))\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const childrenCached = t.readdirCached()\n if (t.calledReaddir())\n this.walkCB3(t, childrenCached, processor, next)\n else {\n t.readdirCB(\n (_, entries) => this.walkCB3(t, entries, processor, next),\n true\n )\n }\n }\n\n next()\n }\n\n walkCB3(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2(target, patterns, processor.child(), next)\n }\n\n next()\n }\n\n walkCBSync(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2Sync(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2Sync(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() =>\n this.walkCB2Sync(target, patterns, processor, cb)\n )\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const children = t.readdirSync()\n this.walkCB3Sync(t, children, processor, next)\n }\n\n next()\n }\n\n walkCB3Sync(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2Sync(target, patterns, processor.child(), next)\n }\n\n next()\n }\n}\n\nexport class GlobWalker<\n O extends GlobWalkerOpts = GlobWalkerOpts\n> extends GlobUtil {\n matches: O extends GWOFileTypesTrue\n ? Set\n : O extends GWOFileTypesFalse\n ? Set\n : O extends GWOFileTypesUnset\n ? Set\n : Set\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.matches = new Set() as Matches\n }\n\n matchEmit(e: Result): void\n matchEmit(e: Path | string): void {\n this.matches.add(e)\n }\n\n async walk(): Promise> {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n await this.path.lstat()\n }\n await new Promise((res, rej) => {\n this.walkCB(this.path, this.patterns, () => {\n if (this.signal?.aborted) {\n rej(this.signal.reason)\n } else {\n res(this.matches)\n }\n })\n })\n return this.matches\n }\n\n walkSync(): Matches {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n // nothing for the callback to do, because this never pauses\n this.walkCBSync(this.path, this.patterns, () => {\n if (this.signal?.aborted) throw this.signal.reason\n })\n return this.matches\n }\n}\n\nexport class GlobStream<\n O extends GlobWalkerOpts = GlobWalkerOpts\n> extends GlobUtil {\n results: O extends GWOFileTypesTrue\n ? Minipass\n : O extends GWOFileTypesFalse\n ? Minipass\n : O extends GWOFileTypesUnset\n ? Minipass\n : Minipass\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.results = new Minipass({\n signal: this.signal,\n objectMode: true,\n }) as MatchStream\n this.results.on('drain', () => this.resume())\n this.results.on('resume', () => this.resume())\n }\n\n matchEmit(e: Result): void\n matchEmit(e: Path | string): void {\n this.results.write(e)\n if (!this.results.flowing) this.pause()\n }\n\n stream(): MatchStream {\n const target = this.path\n if (target.isUnknown()) {\n target.lstat().then(() => {\n this.walkCB(target, this.patterns, () => this.results.end())\n })\n } else {\n this.walkCB(target, this.patterns, () => this.results.end())\n }\n return this.results\n }\n\n streamSync(): MatchStream {\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n this.walkCBSync(this.path, this.patterns, () => this.results.end())\n return this.results\n }\n}\n"]} \ No newline at end of file diff --git a/deps/npm/node_modules/glob/dist/esm/ignore.d.ts.map b/deps/npm/node_modules/glob/dist/esm/ignore.d.ts.map index be7831769d33ed..21ab57b94d1a76 100644 --- a/deps/npm/node_modules/glob/dist/esm/ignore.d.ts.map +++ b/deps/npm/node_modules/glob/dist/esm/ignore.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../../src/ignore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO,CAAA;IAC9B,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO,CAAA;CACvC;AASD;;GAEG;AACH,qBAAa,MAAO,YAAW,UAAU;IACvC,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,gBAAgB,EAAE,SAAS,EAAE,CAAA;IAC7B,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,gBAAgB,EAAE,SAAS,EAAE,CAAA;gBAG3B,OAAO,EAAE,MAAM,EAAE,EACjB,EACE,OAAO,EACP,MAAM,EACN,KAAK,EACL,UAAU,EACV,QAA0B,GAC3B,EAAE,cAAc;IAsDnB,OAAO,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO;IAczB,eAAe,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO;CAWlC"} \ No newline at end of file +{"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../../src/ignore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO,CAAA;IAC9B,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO,CAAA;CACvC;AASD;;GAEG;AACH,qBAAa,MAAO,YAAW,UAAU;IACvC,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,gBAAgB,EAAE,SAAS,EAAE,CAAA;IAC7B,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,gBAAgB,EAAE,SAAS,EAAE,CAAA;gBAG3B,OAAO,EAAE,MAAM,EAAE,EACjB,EACE,OAAO,EACP,MAAM,EACN,KAAK,EACL,UAAU,EACV,QAA0B,GAC3B,EAAE,cAAc;IA4DnB,OAAO,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO;IAczB,eAAe,CAAC,CAAC,EAAE,IAAI,GAAG,OAAO;CAWlC"} \ No newline at end of file diff --git a/deps/npm/node_modules/glob/dist/esm/ignore.js b/deps/npm/node_modules/glob/dist/esm/ignore.js index e8cbaf96b3a809..2b2808d0dfe0f1 100644 --- a/deps/npm/node_modules/glob/dist/esm/ignore.js +++ b/deps/npm/node_modules/glob/dist/esm/ignore.js @@ -54,6 +54,12 @@ export class Ignore { if (!parsed || !globParts) { throw new Error('invalid pattern object'); } + // strip off leading ./ portions + // https://github.com/isaacs/node-glob/issues/570 + while (parsed[0] === '.' && globParts[0] === '.') { + parsed.shift(); + globParts.shift(); + } /* c8 ignore stop */ const p = new Pattern(parsed, globParts, 0, platform); const m = new Minimatch(p.globString(), mmopts); diff --git a/deps/npm/node_modules/glob/dist/esm/ignore.js.map b/deps/npm/node_modules/glob/dist/esm/ignore.js.map index 736e4466180177..baa7eb2efa01df 100644 --- a/deps/npm/node_modules/glob/dist/esm/ignore.js.map +++ b/deps/npm/node_modules/glob/dist/esm/ignore.js.map @@ -1 +1 @@ -{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/ignore.ts"],"names":[],"mappings":"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","sourcesContent":["// give it a pattern, and it'll be able to tell you if\n// a given path should be ignored.\n// Ignoring a path ignores its children if the pattern ends in /**\n// Ignores are always parsed in dot:true mode\n\nimport { Minimatch } from 'minimatch'\nimport { Path } from 'path-scurry'\nimport { Pattern } from './pattern.js'\nimport { GlobWalkerOpts } from './walker.js'\n\nexport interface IgnoreLike {\n ignored?: (p: Path) => boolean\n childrenIgnored?: (p: Path) => boolean\n}\n\nconst defaultPlatform: NodeJS.Platform =\n typeof process === 'object' &&\n process &&\n typeof process.platform === 'string'\n ? process.platform\n : 'linux'\n\n/**\n * Class used to process ignored patterns\n */\nexport class Ignore implements IgnoreLike {\n relative: Minimatch[]\n relativeChildren: Minimatch[]\n absolute: Minimatch[]\n absoluteChildren: Minimatch[]\n\n constructor(\n ignored: string[],\n {\n nobrace,\n nocase,\n noext,\n noglobstar,\n platform = defaultPlatform,\n }: GlobWalkerOpts\n ) {\n this.relative = []\n this.absolute = []\n this.relativeChildren = []\n this.absoluteChildren = []\n const mmopts = {\n dot: true,\n nobrace,\n nocase,\n noext,\n noglobstar,\n optimizationLevel: 2,\n platform,\n nocomment: true,\n nonegate: true,\n }\n\n // this is a little weird, but it gives us a clean set of optimized\n // minimatch matchers, without getting tripped up if one of them\n // ends in /** inside a brace section, and it's only inefficient at\n // the start of the walk, not along it.\n // It'd be nice if the Pattern class just had a .test() method, but\n // handling globstars is a bit of a pita, and that code already lives\n // in minimatch anyway.\n // Another way would be if maybe Minimatch could take its set/globParts\n // as an option, and then we could at least just use Pattern to test\n // for absolute-ness.\n // Yet another way, Minimatch could take an array of glob strings, and\n // a cwd option, and do the right thing.\n for (const ign of ignored) {\n const mm = new Minimatch(ign, mmopts)\n for (let i = 0; i < mm.set.length; i++) {\n const parsed = mm.set[i]\n const globParts = mm.globParts[i]\n /* c8 ignore start */\n if (!parsed || !globParts) {\n throw new Error('invalid pattern object')\n }\n /* c8 ignore stop */\n const p = new Pattern(parsed, globParts, 0, platform)\n const m = new Minimatch(p.globString(), mmopts)\n const children = globParts[globParts.length - 1] === '**'\n const absolute = p.isAbsolute()\n if (absolute) this.absolute.push(m)\n else this.relative.push(m)\n if (children) {\n if (absolute) this.absoluteChildren.push(m)\n else this.relativeChildren.push(m)\n }\n }\n }\n }\n\n ignored(p: Path): boolean {\n const fullpath = p.fullpath()\n const fullpaths = `${fullpath}/`\n const relative = p.relative() || '.'\n const relatives = `${relative}/`\n for (const m of this.relative) {\n if (m.match(relative) || m.match(relatives)) return true\n }\n for (const m of this.absolute) {\n if (m.match(fullpath) || m.match(fullpaths)) return true\n }\n return false\n }\n\n childrenIgnored(p: Path): boolean {\n const fullpath = p.fullpath() + '/'\n const relative = (p.relative() || '.') + '/'\n for (const m of this.relativeChildren) {\n if (m.match(relative)) return true\n }\n for (const m of this.absoluteChildren) {\n if (m.match(fullpath)) return true\n }\n return false\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/ignore.ts"],"names":[],"mappings":"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","sourcesContent":["// give it a pattern, and it'll be able to tell you if\n// a given path should be ignored.\n// Ignoring a path ignores its children if the pattern ends in /**\n// Ignores are always parsed in dot:true mode\n\nimport { Minimatch } from 'minimatch'\nimport { Path } from 'path-scurry'\nimport { Pattern } from './pattern.js'\nimport { GlobWalkerOpts } from './walker.js'\n\nexport interface IgnoreLike {\n ignored?: (p: Path) => boolean\n childrenIgnored?: (p: Path) => boolean\n}\n\nconst defaultPlatform: NodeJS.Platform =\n typeof process === 'object' &&\n process &&\n typeof process.platform === 'string'\n ? process.platform\n : 'linux'\n\n/**\n * Class used to process ignored patterns\n */\nexport class Ignore implements IgnoreLike {\n relative: Minimatch[]\n relativeChildren: Minimatch[]\n absolute: Minimatch[]\n absoluteChildren: Minimatch[]\n\n constructor(\n ignored: string[],\n {\n nobrace,\n nocase,\n noext,\n noglobstar,\n platform = defaultPlatform,\n }: GlobWalkerOpts\n ) {\n this.relative = []\n this.absolute = []\n this.relativeChildren = []\n this.absoluteChildren = []\n const mmopts = {\n dot: true,\n nobrace,\n nocase,\n noext,\n noglobstar,\n optimizationLevel: 2,\n platform,\n nocomment: true,\n nonegate: true,\n }\n\n // this is a little weird, but it gives us a clean set of optimized\n // minimatch matchers, without getting tripped up if one of them\n // ends in /** inside a brace section, and it's only inefficient at\n // the start of the walk, not along it.\n // It'd be nice if the Pattern class just had a .test() method, but\n // handling globstars is a bit of a pita, and that code already lives\n // in minimatch anyway.\n // Another way would be if maybe Minimatch could take its set/globParts\n // as an option, and then we could at least just use Pattern to test\n // for absolute-ness.\n // Yet another way, Minimatch could take an array of glob strings, and\n // a cwd option, and do the right thing.\n for (const ign of ignored) {\n const mm = new Minimatch(ign, mmopts)\n for (let i = 0; i < mm.set.length; i++) {\n const parsed = mm.set[i]\n const globParts = mm.globParts[i]\n /* c8 ignore start */\n if (!parsed || !globParts) {\n throw new Error('invalid pattern object')\n }\n // strip off leading ./ portions\n // https://github.com/isaacs/node-glob/issues/570\n while (parsed[0] === '.' && globParts[0] === '.') {\n parsed.shift()\n globParts.shift()\n }\n /* c8 ignore stop */\n const p = new Pattern(parsed, globParts, 0, platform)\n const m = new Minimatch(p.globString(), mmopts)\n const children = globParts[globParts.length - 1] === '**'\n const absolute = p.isAbsolute()\n if (absolute) this.absolute.push(m)\n else this.relative.push(m)\n if (children) {\n if (absolute) this.absoluteChildren.push(m)\n else this.relativeChildren.push(m)\n }\n }\n }\n }\n\n ignored(p: Path): boolean {\n const fullpath = p.fullpath()\n const fullpaths = `${fullpath}/`\n const relative = p.relative() || '.'\n const relatives = `${relative}/`\n for (const m of this.relative) {\n if (m.match(relative) || m.match(relatives)) return true\n }\n for (const m of this.absolute) {\n if (m.match(fullpath) || m.match(fullpaths)) return true\n }\n return false\n }\n\n childrenIgnored(p: Path): boolean {\n const fullpath = p.fullpath() + '/'\n const relative = (p.relative() || '.') + '/'\n for (const m of this.relativeChildren) {\n if (m.match(relative)) return true\n }\n for (const m of this.absoluteChildren) {\n if (m.match(fullpath)) return true\n }\n return false\n }\n}\n"]} \ No newline at end of file diff --git a/deps/npm/node_modules/glob/dist/esm/package.json b/deps/npm/node_modules/glob/dist/esm/package.json index 7c34deb5837d8d..3dbc1ca591c055 100644 --- a/deps/npm/node_modules/glob/dist/esm/package.json +++ b/deps/npm/node_modules/glob/dist/esm/package.json @@ -1 +1,3 @@ -{"type":"module"} \ No newline at end of file +{ + "type": "module" +} diff --git a/deps/npm/node_modules/glob/dist/esm/walker.d.ts.map b/deps/npm/node_modules/glob/dist/esm/walker.d.ts.map index 7c8df20b2f323c..2cae287c2e1f42 100644 --- a/deps/npm/node_modules/glob/dist/esm/walker.d.ts.map +++ b/deps/npm/node_modules/glob/dist/esm/walker.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"walker.d.ts","sourceRoot":"","sources":["../../src/walker.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"walker.d.ts","sourceRoot":"","sources":["../../src/walker.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/deps/npm/node_modules/glob/dist/esm/walker.js b/deps/npm/node_modules/glob/dist/esm/walker.js index 6f3358b0c39a32..b58472e9de4fbc 100644 --- a/deps/npm/node_modules/glob/dist/esm/walker.js +++ b/deps/npm/node_modules/glob/dist/esm/walker.js @@ -93,13 +93,26 @@ export class GlobUtil { e = rpc; } const needStat = e.isUnknown() || this.opts.stat; - return this.matchCheckTest(needStat ? await e.lstat() : e, ifDir); + const s = needStat ? await e.lstat() : e; + if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) { + const target = await s.realpath(); + /* c8 ignore start */ + if (target && (target.isUnknown() || this.opts.stat)) { + await target.lstat(); + } + /* c8 ignore stop */ + } + return this.matchCheckTest(s, ifDir); } matchCheckTest(e, ifDir) { return e && (this.maxDepth === Infinity || e.depth() <= this.maxDepth) && (!ifDir || e.canReaddir()) && (!this.opts.nodir || !e.isDirectory()) && + (!this.opts.nodir || + !this.opts.follow || + !e.isSymbolicLink() || + !e.realpathCached()?.isDirectory()) && !this.#ignored(e) ? e : undefined; @@ -115,7 +128,14 @@ export class GlobUtil { e = rpc; } const needStat = e.isUnknown() || this.opts.stat; - return this.matchCheckTest(needStat ? e.lstatSync() : e, ifDir); + const s = needStat ? e.lstatSync() : e; + if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) { + const target = s.realpathSync(); + if (target && (target?.isUnknown() || this.opts.stat)) { + target.lstatSync(); + } + } + return this.matchCheckTest(s, ifDir); } matchFinish(e, absolute) { if (this.#ignored(e)) diff --git a/deps/npm/node_modules/glob/dist/esm/walker.js.map b/deps/npm/node_modules/glob/dist/esm/walker.js.map index 8756bfca294503..62f35d4a1a2955 100644 --- a/deps/npm/node_modules/glob/dist/esm/walker.js.map +++ b/deps/npm/node_modules/glob/dist/esm/walker.js.map @@ -1 +1 @@ -{"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/walker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAEnC,OAAO,EAAE,MAAM,EAAc,MAAM,aAAa,CAAA;AAQhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAiE1C,MAAM,UAAU,GAAG,CACjB,MAAsC,EACtC,IAAoB,EACR,EAAE,CACd,OAAO,MAAM,KAAK,QAAQ;IACxB,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;IAC5B,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QACvB,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC;QAC1B,CAAC,CAAC,MAAM,CAAA;AAEZ;;GAEG;AACH,MAAM,OAAgB,QAAQ;IAC5B,IAAI,CAAM;IACV,QAAQ,CAAW;IACnB,IAAI,CAAG;IACP,IAAI,GAAc,IAAI,GAAG,EAAQ,CAAA;IACjC,MAAM,GAAY,KAAK,CAAA;IACvB,OAAO,GAAY,KAAK,CAAA;IACxB,SAAS,GAAkB,EAAE,CAAA;IAC7B,OAAO,CAAa;IACpB,IAAI,CAAY;IAChB,MAAM,CAAc;IACpB,QAAQ,CAAQ;IAGhB,YAAY,QAAmB,EAAE,IAAU,EAAE,IAAO;QAClD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAA;QACjE,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;SAC7C;QACD,6DAA6D;QAC7D,mBAAmB;QACnB,qBAAqB;QACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAA;QACzC,oBAAoB;QACpB,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;YACzB,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;gBACzC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAA;YAC3B,CAAC,CAAC,CAAA;SACH;IACH,CAAC;IAED,QAAQ,CAAC,IAAU;QACjB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,CAAA;IAC/D,CAAC;IACD,gBAAgB,CAAC,IAAU;QACzB,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC,IAAI,CAAC,CAAA;IAChD,CAAC;IAED,yBAAyB;IACzB,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;IACpB,CAAC;IACD,MAAM;QACJ,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,OAAM;QAChC,oBAAoB;QACpB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,EAAE,GAA4B,SAAS,CAAA;QAC3C,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE;YACpD,EAAE,EAAE,CAAA;SACL;IACH,CAAC;IACD,QAAQ,CAAC,EAAa;QACpB,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,OAAM;QAChC,qBAAqB;QACrB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAChB,EAAE,EAAE,CAAA;SACL;aAAM;YACL,oBAAoB;YACpB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;SACxB;IACH,CAAC;IAED,+DAA+D;IAC/D,wCAAwC;IACxC,KAAK,CAAC,UAAU,CAAC,CAAO,EAAE,KAAc;QACtC,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAA;QAC9C,IAAI,GAAqB,CAAA;QACzB,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACtB,GAAG,GAAG,CAAC,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;YAChD,IAAI,CAAC,GAAG;gBAAE,OAAO,SAAS,CAAA;YAC1B,CAAC,GAAG,GAAG,CAAA;SACR;QACD,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;QAChD,OAAO,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACnE,CAAC;IAED,cAAc,CAAC,CAAmB,EAAE,KAAc;QAChD,OAAO,CAAC;YACN,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC;YAC1D,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;YAC1B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACtC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YACjB,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,SAAS,CAAA;IACf,CAAC;IAED,cAAc,CAAC,CAAO,EAAE,KAAc;QACpC,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAA;QAC9C,IAAI,GAAqB,CAAA;QACzB,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACtB,GAAG,GAAG,CAAC,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,YAAY,EAAE,CAAA;YAC5C,IAAI,CAAC,GAAG;gBAAE,OAAO,SAAS,CAAA;YAC1B,CAAC,GAAG,GAAG,CAAA;SACR;QACD,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;QAChD,OAAO,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACjE,CAAC;IAKD,WAAW,CAAC,CAAO,EAAE,QAAiB;QACpC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAM;QAC5B,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAA;QAClE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;QAC/D,4BAA4B;QAC5B,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YAC3B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;SAClB;aAAM,IAAI,GAAG,EAAE;YACd,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;YAC9D,IAAI,CAAC,SAAS,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;SAC3B;aAAM;YACL,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;YAC9D,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;gBACxD,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI;gBACjB,CAAC,CAAC,EAAE,CAAA;YACR,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,CAAA;SACrD;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,CAAO,EAAE,QAAiB,EAAE,KAAc;QACpD,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;QACzC,IAAI,CAAC;YAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;IACtC,CAAC;IAED,SAAS,CAAC,CAAO,EAAE,QAAiB,EAAE,KAAc;QAClD,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;QACvC,IAAI,CAAC;YAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;IACtC,CAAC;IAED,MAAM,CAAC,MAAY,EAAE,QAAmB,EAAE,EAAa;QACrD,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,EAAE,EAAE,CAAA;QAC9B,oBAAoB;QACpB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IAC9D,CAAC;IAED,OAAO,CACL,MAAY,EACZ,QAAmB,EACnB,SAAoB,EACpB,EAAa;QAEb,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,EAAE,CAAA;QAC9C,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,EAAE,EAAE,CAAA;QAC9B,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,CAAA;YAClE,OAAM;SACP;QACD,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAE3C,qEAAqE;QACrE,4DAA4D;QAC5D,yDAAyD;QACzD,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,EAAE,KAAK,KAAK,CAAC;gBAAE,EAAE,EAAE,CAAA;QACzB,CAAC,CAAA;QAED,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE;YAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAQ;YAC9B,KAAK,EAAE,CAAA;YACP,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;SAClD;QAED,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,cAAc,EAAE,EAAE;YAC1C,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE;gBAC5D,SAAQ;aACT;YACD,KAAK,EAAE,CAAA;YACP,MAAM,cAAc,GAAG,CAAC,CAAC,aAAa,EAAE,CAAA;YACxC,IAAI,CAAC,CAAC,aAAa,EAAE;gBACnB,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,CAAC,CAAA;iBAC7C;gBACH,CAAC,CAAC,SAAS,CACT,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,EACzD,IAAI,CACL,CAAA;aACF;SACF;QAED,IAAI,EAAE,CAAA;IACR,CAAC;IAED,OAAO,CACL,MAAY,EACZ,OAAe,EACf,SAAoB,EACpB,EAAa;QAEb,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAEpD,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,EAAE,KAAK,KAAK,CAAC;gBAAE,EAAE,EAAE,CAAA;QACzB,CAAC,CAAA;QAED,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE;YAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAQ;YAC9B,KAAK,EAAE,CAAA;YACP,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;SAClD;QACD,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;YAC7D,KAAK,EAAE,CAAA;YACP,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAA;SACxD;QAED,IAAI,EAAE,CAAA;IACR,CAAC;IAED,UAAU,CAAC,MAAY,EAAE,QAAmB,EAAE,EAAa;QACzD,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,EAAE,EAAE,CAAA;QAC9B,oBAAoB;QACpB,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IAClE,CAAC;IAED,WAAW,CACT,MAAY,EACZ,QAAmB,EACnB,SAAoB,EACpB,EAAa;QAEb,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,EAAE,CAAA;QAC9C,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,EAAE,EAAE,CAAA;QAC9B,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CACjB,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,CAAC,CAClD,CAAA;YACD,OAAM;SACP;QACD,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAE3C,qEAAqE;QACrE,4DAA4D;QAC5D,yDAAyD;QACzD,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,EAAE,KAAK,KAAK,CAAC;gBAAE,EAAE,EAAE,CAAA;QACzB,CAAC,CAAA;QAED,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE;YAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAQ;YAC9B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;SACnC;QAED,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,cAAc,EAAE,EAAE;YAC1C,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE;gBAC5D,SAAQ;aACT;YACD,KAAK,EAAE,CAAA;YACP,MAAM,QAAQ,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;YAChC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,CAAA;SAC/C;QAED,IAAI,EAAE,CAAA;IACR,CAAC;IAED,WAAW,CACT,MAAY,EACZ,OAAe,EACf,SAAoB,EACpB,EAAa;QAEb,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAEpD,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,EAAE,KAAK,KAAK,CAAC;gBAAE,EAAE,EAAE,CAAA;QACzB,CAAC,CAAA;QAED,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE;YAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAQ;YAC9B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;SACnC;QACD,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;YAC7D,KAAK,EAAE,CAAA;YACP,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAA;SAC5D;QAED,IAAI,EAAE,CAAA;IACR,CAAC;CACF;AAED,MAAM,OAAO,UAEX,SAAQ,QAAW;IACnB,OAAO,CAMe;IAEtB,YAAY,QAAmB,EAAE,IAAU,EAAE,IAAO;QAClD,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAgB,CAAA;IACxC,CAAC;IAGD,SAAS,CAAC,CAAgB;QACxB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA;QAClD,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;YACzB,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;SACxB;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACzC,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE;oBACxB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;iBACxB;qBAAM;oBACL,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;iBAClB;YACH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,QAAQ;QACN,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA;QAClD,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;YACzB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAA;SACtB;QACD,4DAA4D;QAC5D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC7C,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA;QACpD,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;CACF;AAED,MAAM,OAAO,UAEX,SAAQ,QAAW;IACnB,OAAO,CAMmC;IAE1C,YAAY,QAAmB,EAAE,IAAU,EAAE,IAAO;QAClD,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,QAAQ,CAAC;YAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI;SACjB,CAAmB,CAAA;QACpB,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;QAC7C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;IAChD,CAAC;IAGD,SAAS,CAAC,CAAgB;QACxB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACrB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,IAAI,CAAC,KAAK,EAAE,CAAA;IACzC,CAAC;IAED,MAAM;QACJ,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAA;QACxB,IAAI,MAAM,CAAC,SAAS,EAAE,EAAE;YACtB,MAAM,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;gBACvB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;YAC9D,CAAC,CAAC,CAAA;SACH;aAAM;YACL,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;SAC7D;QACD,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;YACzB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAA;SACtB;QACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;QACnE,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;CACF","sourcesContent":["/**\n * Single-use utility classes to provide functionality to the {@link Glob}\n * methods.\n *\n * @module\n */\nimport { Minipass } from 'minipass'\nimport { Path } from 'path-scurry'\nimport { Ignore, IgnoreLike } from './ignore.js'\n\n// XXX can we somehow make it so that it NEVER processes a given path more than\n// once, enough that the match set tracking is no longer needed? that'd speed\n// things up a lot. Or maybe bring back nounique, and skip it in that case?\n\n// a single minimatch set entry with 1 or more parts\nimport { Pattern } from './pattern.js'\nimport { Processor } from './processor.js'\n\nexport interface GlobWalkerOpts {\n absolute?: boolean\n allowWindowsEscape?: boolean\n cwd?: string | URL\n dot?: boolean\n dotRelative?: boolean\n follow?: boolean\n ignore?: string | string[] | IgnoreLike\n mark?: boolean\n matchBase?: boolean\n // Note: maxDepth here means \"maximum actual Path.depth()\",\n // not \"maximum depth beyond cwd\"\n maxDepth?: number\n nobrace?: boolean\n nocase?: boolean\n nodir?: boolean\n noext?: boolean\n noglobstar?: boolean\n platform?: NodeJS.Platform\n posix?: boolean\n realpath?: boolean\n root?: string\n stat?: boolean\n signal?: AbortSignal\n windowsPathsNoEscape?: boolean\n withFileTypes?: boolean\n}\n\nexport type GWOFileTypesTrue = GlobWalkerOpts & {\n withFileTypes: true\n}\nexport type GWOFileTypesFalse = GlobWalkerOpts & {\n withFileTypes: false\n}\nexport type GWOFileTypesUnset = GlobWalkerOpts & {\n withFileTypes?: undefined\n}\n\nexport type Result = O extends GWOFileTypesTrue\n ? Path\n : O extends GWOFileTypesFalse\n ? string\n : O extends GWOFileTypesUnset\n ? string\n : Path | string\n\nexport type Matches = O extends GWOFileTypesTrue\n ? Set\n : O extends GWOFileTypesFalse\n ? Set\n : O extends GWOFileTypesUnset\n ? Set\n : Set\n\nexport type MatchStream =\n O extends GWOFileTypesTrue\n ? Minipass\n : O extends GWOFileTypesFalse\n ? Minipass\n : O extends GWOFileTypesUnset\n ? Minipass\n : Minipass\n\nconst makeIgnore = (\n ignore: string | string[] | IgnoreLike,\n opts: GlobWalkerOpts\n): IgnoreLike =>\n typeof ignore === 'string'\n ? new Ignore([ignore], opts)\n : Array.isArray(ignore)\n ? new Ignore(ignore, opts)\n : ignore\n\n/**\n * basic walking utilities that all the glob walker types use\n */\nexport abstract class GlobUtil {\n path: Path\n patterns: Pattern[]\n opts: O\n seen: Set = new Set()\n paused: boolean = false\n aborted: boolean = false\n #onResume: (() => any)[] = []\n #ignore?: IgnoreLike\n #sep: '\\\\' | '/'\n signal?: AbortSignal\n maxDepth: number\n\n constructor(patterns: Pattern[], path: Path, opts: O)\n constructor(patterns: Pattern[], path: Path, opts: O) {\n this.patterns = patterns\n this.path = path\n this.opts = opts\n this.#sep = !opts.posix && opts.platform === 'win32' ? '\\\\' : '/'\n if (opts.ignore) {\n this.#ignore = makeIgnore(opts.ignore, opts)\n }\n // ignore, always set with maxDepth, but it's optional on the\n // GlobOptions type\n /* c8 ignore start */\n this.maxDepth = opts.maxDepth || Infinity\n /* c8 ignore stop */\n if (opts.signal) {\n this.signal = opts.signal\n this.signal.addEventListener('abort', () => {\n this.#onResume.length = 0\n })\n }\n }\n\n #ignored(path: Path): boolean {\n return this.seen.has(path) || !!this.#ignore?.ignored?.(path)\n }\n #childrenIgnored(path: Path): boolean {\n return !!this.#ignore?.childrenIgnored?.(path)\n }\n\n // backpressure mechanism\n pause() {\n this.paused = true\n }\n resume() {\n /* c8 ignore start */\n if (this.signal?.aborted) return\n /* c8 ignore stop */\n this.paused = false\n let fn: (() => any) | undefined = undefined\n while (!this.paused && (fn = this.#onResume.shift())) {\n fn()\n }\n }\n onResume(fn: () => any) {\n if (this.signal?.aborted) return\n /* c8 ignore start */\n if (!this.paused) {\n fn()\n } else {\n /* c8 ignore stop */\n this.#onResume.push(fn)\n }\n }\n\n // do the requisite realpath/stat checking, and return the path\n // to add or undefined to filter it out.\n async matchCheck(e: Path, ifDir: boolean): Promise {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || (await e.realpath())\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n return this.matchCheckTest(needStat ? await e.lstat() : e, ifDir)\n }\n\n matchCheckTest(e: Path | undefined, ifDir: boolean): Path | undefined {\n return e &&\n (this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&\n (!ifDir || e.canReaddir()) &&\n (!this.opts.nodir || !e.isDirectory()) &&\n !this.#ignored(e)\n ? e\n : undefined\n }\n\n matchCheckSync(e: Path, ifDir: boolean): Path | undefined {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || e.realpathSync()\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n return this.matchCheckTest(needStat ? e.lstatSync() : e, ifDir)\n }\n\n abstract matchEmit(p: Result): void\n abstract matchEmit(p: string | Path): void\n\n matchFinish(e: Path, absolute: boolean) {\n if (this.#ignored(e)) return\n const abs =\n this.opts.absolute === undefined ? absolute : this.opts.absolute\n this.seen.add(e)\n const mark = this.opts.mark && e.isDirectory() ? this.#sep : ''\n // ok, we have what we need!\n if (this.opts.withFileTypes) {\n this.matchEmit(e)\n } else if (abs) {\n const abs = this.opts.posix ? e.fullpathPosix() : e.fullpath()\n this.matchEmit(abs + mark)\n } else {\n const rel = this.opts.posix ? e.relativePosix() : e.relative()\n const pre =\n this.opts.dotRelative && !rel.startsWith('..' + this.#sep)\n ? '.' + this.#sep\n : ''\n this.matchEmit(!rel ? '.' + mark : pre + rel + mark)\n }\n }\n\n async match(e: Path, absolute: boolean, ifDir: boolean): Promise {\n const p = await this.matchCheck(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n matchSync(e: Path, absolute: boolean, ifDir: boolean): void {\n const p = this.matchCheckSync(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n walkCB(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() => this.walkCB2(target, patterns, processor, cb))\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const childrenCached = t.readdirCached()\n if (t.calledReaddir())\n this.walkCB3(t, childrenCached, processor, next)\n else {\n t.readdirCB(\n (_, entries) => this.walkCB3(t, entries, processor, next),\n true\n )\n }\n }\n\n next()\n }\n\n walkCB3(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2(target, patterns, processor.child(), next)\n }\n\n next()\n }\n\n walkCBSync(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2Sync(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2Sync(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() =>\n this.walkCB2Sync(target, patterns, processor, cb)\n )\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const children = t.readdirSync()\n this.walkCB3Sync(t, children, processor, next)\n }\n\n next()\n }\n\n walkCB3Sync(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2Sync(target, patterns, processor.child(), next)\n }\n\n next()\n }\n}\n\nexport class GlobWalker<\n O extends GlobWalkerOpts = GlobWalkerOpts\n> extends GlobUtil {\n matches: O extends GWOFileTypesTrue\n ? Set\n : O extends GWOFileTypesFalse\n ? Set\n : O extends GWOFileTypesUnset\n ? Set\n : Set\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.matches = new Set() as Matches\n }\n\n matchEmit(e: Result): void\n matchEmit(e: Path | string): void {\n this.matches.add(e)\n }\n\n async walk(): Promise> {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n await this.path.lstat()\n }\n await new Promise((res, rej) => {\n this.walkCB(this.path, this.patterns, () => {\n if (this.signal?.aborted) {\n rej(this.signal.reason)\n } else {\n res(this.matches)\n }\n })\n })\n return this.matches\n }\n\n walkSync(): Matches {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n // nothing for the callback to do, because this never pauses\n this.walkCBSync(this.path, this.patterns, () => {\n if (this.signal?.aborted) throw this.signal.reason\n })\n return this.matches\n }\n}\n\nexport class GlobStream<\n O extends GlobWalkerOpts = GlobWalkerOpts\n> extends GlobUtil {\n results: O extends GWOFileTypesTrue\n ? Minipass\n : O extends GWOFileTypesFalse\n ? Minipass\n : O extends GWOFileTypesUnset\n ? Minipass\n : Minipass\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.results = new Minipass({\n signal: this.signal,\n objectMode: true,\n }) as MatchStream\n this.results.on('drain', () => this.resume())\n this.results.on('resume', () => this.resume())\n }\n\n matchEmit(e: Result): void\n matchEmit(e: Path | string): void {\n this.results.write(e)\n if (!this.results.flowing) this.pause()\n }\n\n stream(): MatchStream {\n const target = this.path\n if (target.isUnknown()) {\n target.lstat().then(() => {\n this.walkCB(target, this.patterns, () => this.results.end())\n })\n } else {\n this.walkCB(target, this.patterns, () => this.results.end())\n }\n return this.results\n }\n\n streamSync(): MatchStream {\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n this.walkCBSync(this.path, this.patterns, () => this.results.end())\n return this.results\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/walker.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Single-use utility classes to provide functionality to the {@link Glob}\n * methods.\n *\n * @module\n */\nimport { Minipass } from 'minipass'\nimport { Path } from 'path-scurry'\nimport { Ignore, IgnoreLike } from './ignore.js'\n\n// XXX can we somehow make it so that it NEVER processes a given path more than\n// once, enough that the match set tracking is no longer needed? that'd speed\n// things up a lot. Or maybe bring back nounique, and skip it in that case?\n\n// a single minimatch set entry with 1 or more parts\nimport { Pattern } from './pattern.js'\nimport { Processor } from './processor.js'\n\nexport interface GlobWalkerOpts {\n absolute?: boolean\n allowWindowsEscape?: boolean\n cwd?: string | URL\n dot?: boolean\n dotRelative?: boolean\n follow?: boolean\n ignore?: string | string[] | IgnoreLike\n mark?: boolean\n matchBase?: boolean\n // Note: maxDepth here means \"maximum actual Path.depth()\",\n // not \"maximum depth beyond cwd\"\n maxDepth?: number\n nobrace?: boolean\n nocase?: boolean\n nodir?: boolean\n noext?: boolean\n noglobstar?: boolean\n platform?: NodeJS.Platform\n posix?: boolean\n realpath?: boolean\n root?: string\n stat?: boolean\n signal?: AbortSignal\n windowsPathsNoEscape?: boolean\n withFileTypes?: boolean\n}\n\nexport type GWOFileTypesTrue = GlobWalkerOpts & {\n withFileTypes: true\n}\nexport type GWOFileTypesFalse = GlobWalkerOpts & {\n withFileTypes: false\n}\nexport type GWOFileTypesUnset = GlobWalkerOpts & {\n withFileTypes?: undefined\n}\n\nexport type Result = O extends GWOFileTypesTrue\n ? Path\n : O extends GWOFileTypesFalse\n ? string\n : O extends GWOFileTypesUnset\n ? string\n : Path | string\n\nexport type Matches = O extends GWOFileTypesTrue\n ? Set\n : O extends GWOFileTypesFalse\n ? Set\n : O extends GWOFileTypesUnset\n ? Set\n : Set\n\nexport type MatchStream =\n O extends GWOFileTypesTrue\n ? Minipass\n : O extends GWOFileTypesFalse\n ? Minipass\n : O extends GWOFileTypesUnset\n ? Minipass\n : Minipass\n\nconst makeIgnore = (\n ignore: string | string[] | IgnoreLike,\n opts: GlobWalkerOpts\n): IgnoreLike =>\n typeof ignore === 'string'\n ? new Ignore([ignore], opts)\n : Array.isArray(ignore)\n ? new Ignore(ignore, opts)\n : ignore\n\n/**\n * basic walking utilities that all the glob walker types use\n */\nexport abstract class GlobUtil {\n path: Path\n patterns: Pattern[]\n opts: O\n seen: Set = new Set()\n paused: boolean = false\n aborted: boolean = false\n #onResume: (() => any)[] = []\n #ignore?: IgnoreLike\n #sep: '\\\\' | '/'\n signal?: AbortSignal\n maxDepth: number\n\n constructor(patterns: Pattern[], path: Path, opts: O)\n constructor(patterns: Pattern[], path: Path, opts: O) {\n this.patterns = patterns\n this.path = path\n this.opts = opts\n this.#sep = !opts.posix && opts.platform === 'win32' ? '\\\\' : '/'\n if (opts.ignore) {\n this.#ignore = makeIgnore(opts.ignore, opts)\n }\n // ignore, always set with maxDepth, but it's optional on the\n // GlobOptions type\n /* c8 ignore start */\n this.maxDepth = opts.maxDepth || Infinity\n /* c8 ignore stop */\n if (opts.signal) {\n this.signal = opts.signal\n this.signal.addEventListener('abort', () => {\n this.#onResume.length = 0\n })\n }\n }\n\n #ignored(path: Path): boolean {\n return this.seen.has(path) || !!this.#ignore?.ignored?.(path)\n }\n #childrenIgnored(path: Path): boolean {\n return !!this.#ignore?.childrenIgnored?.(path)\n }\n\n // backpressure mechanism\n pause() {\n this.paused = true\n }\n resume() {\n /* c8 ignore start */\n if (this.signal?.aborted) return\n /* c8 ignore stop */\n this.paused = false\n let fn: (() => any) | undefined = undefined\n while (!this.paused && (fn = this.#onResume.shift())) {\n fn()\n }\n }\n onResume(fn: () => any) {\n if (this.signal?.aborted) return\n /* c8 ignore start */\n if (!this.paused) {\n fn()\n } else {\n /* c8 ignore stop */\n this.#onResume.push(fn)\n }\n }\n\n // do the requisite realpath/stat checking, and return the path\n // to add or undefined to filter it out.\n async matchCheck(e: Path, ifDir: boolean): Promise {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || (await e.realpath())\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n const s = needStat ? await e.lstat() : e\n if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {\n const target = await s.realpath()\n /* c8 ignore start */\n if (target && (target.isUnknown() || this.opts.stat)) {\n await target.lstat()\n }\n /* c8 ignore stop */\n }\n return this.matchCheckTest(s, ifDir)\n }\n\n matchCheckTest(e: Path | undefined, ifDir: boolean): Path | undefined {\n return e &&\n (this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&\n (!ifDir || e.canReaddir()) &&\n (!this.opts.nodir || !e.isDirectory()) &&\n (!this.opts.nodir ||\n !this.opts.follow ||\n !e.isSymbolicLink() ||\n !e.realpathCached()?.isDirectory()) &&\n !this.#ignored(e)\n ? e\n : undefined\n }\n\n matchCheckSync(e: Path, ifDir: boolean): Path | undefined {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || e.realpathSync()\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n const s = needStat ? e.lstatSync() : e\n if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {\n const target = s.realpathSync()\n if (target && (target?.isUnknown() || this.opts.stat)) {\n target.lstatSync()\n }\n }\n return this.matchCheckTest(s, ifDir)\n }\n\n abstract matchEmit(p: Result): void\n abstract matchEmit(p: string | Path): void\n\n matchFinish(e: Path, absolute: boolean) {\n if (this.#ignored(e)) return\n const abs =\n this.opts.absolute === undefined ? absolute : this.opts.absolute\n this.seen.add(e)\n const mark = this.opts.mark && e.isDirectory() ? this.#sep : ''\n // ok, we have what we need!\n if (this.opts.withFileTypes) {\n this.matchEmit(e)\n } else if (abs) {\n const abs = this.opts.posix ? e.fullpathPosix() : e.fullpath()\n this.matchEmit(abs + mark)\n } else {\n const rel = this.opts.posix ? e.relativePosix() : e.relative()\n const pre =\n this.opts.dotRelative && !rel.startsWith('..' + this.#sep)\n ? '.' + this.#sep\n : ''\n this.matchEmit(!rel ? '.' + mark : pre + rel + mark)\n }\n }\n\n async match(e: Path, absolute: boolean, ifDir: boolean): Promise {\n const p = await this.matchCheck(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n matchSync(e: Path, absolute: boolean, ifDir: boolean): void {\n const p = this.matchCheckSync(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n walkCB(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() => this.walkCB2(target, patterns, processor, cb))\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const childrenCached = t.readdirCached()\n if (t.calledReaddir())\n this.walkCB3(t, childrenCached, processor, next)\n else {\n t.readdirCB(\n (_, entries) => this.walkCB3(t, entries, processor, next),\n true\n )\n }\n }\n\n next()\n }\n\n walkCB3(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2(target, patterns, processor.child(), next)\n }\n\n next()\n }\n\n walkCBSync(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2Sync(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2Sync(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() =>\n this.walkCB2Sync(target, patterns, processor, cb)\n )\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const children = t.readdirSync()\n this.walkCB3Sync(t, children, processor, next)\n }\n\n next()\n }\n\n walkCB3Sync(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2Sync(target, patterns, processor.child(), next)\n }\n\n next()\n }\n}\n\nexport class GlobWalker<\n O extends GlobWalkerOpts = GlobWalkerOpts\n> extends GlobUtil {\n matches: O extends GWOFileTypesTrue\n ? Set\n : O extends GWOFileTypesFalse\n ? Set\n : O extends GWOFileTypesUnset\n ? Set\n : Set\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.matches = new Set() as Matches\n }\n\n matchEmit(e: Result): void\n matchEmit(e: Path | string): void {\n this.matches.add(e)\n }\n\n async walk(): Promise> {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n await this.path.lstat()\n }\n await new Promise((res, rej) => {\n this.walkCB(this.path, this.patterns, () => {\n if (this.signal?.aborted) {\n rej(this.signal.reason)\n } else {\n res(this.matches)\n }\n })\n })\n return this.matches\n }\n\n walkSync(): Matches {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n // nothing for the callback to do, because this never pauses\n this.walkCBSync(this.path, this.patterns, () => {\n if (this.signal?.aborted) throw this.signal.reason\n })\n return this.matches\n }\n}\n\nexport class GlobStream<\n O extends GlobWalkerOpts = GlobWalkerOpts\n> extends GlobUtil {\n results: O extends GWOFileTypesTrue\n ? Minipass\n : O extends GWOFileTypesFalse\n ? Minipass\n : O extends GWOFileTypesUnset\n ? Minipass\n : Minipass\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.results = new Minipass({\n signal: this.signal,\n objectMode: true,\n }) as MatchStream\n this.results.on('drain', () => this.resume())\n this.results.on('resume', () => this.resume())\n }\n\n matchEmit(e: Result): void\n matchEmit(e: Path | string): void {\n this.results.write(e)\n if (!this.results.flowing) this.pause()\n }\n\n stream(): MatchStream {\n const target = this.path\n if (target.isUnknown()) {\n target.lstat().then(() => {\n this.walkCB(target, this.patterns, () => this.results.end())\n })\n } else {\n this.walkCB(target, this.patterns, () => this.results.end())\n }\n return this.results\n }\n\n streamSync(): MatchStream {\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n this.walkCBSync(this.path, this.patterns, () => this.results.end())\n return this.results\n }\n}\n"]} \ No newline at end of file diff --git a/deps/npm/node_modules/glob/package.json b/deps/npm/node_modules/glob/package.json index ae0dfae17460bc..2caac096136c98 100644 --- a/deps/npm/node_modules/glob/package.json +++ b/deps/npm/node_modules/glob/package.json @@ -2,7 +2,7 @@ "author": "Isaac Z. Schlueter (https://blog.izs.me/)", "name": "glob", "description": "the most correct and second fastest glob implementation in JavaScript", - "version": "10.3.10", + "version": "10.3.12", "type": "module", "tshy": { "main": true, @@ -67,21 +67,22 @@ }, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" }, "devDependencies": { - "@types/node": "^20.3.2", + "@types/node": "^20.11.30", "memfs": "^3.4.13", "mkdirp": "^3.0.1", "prettier": "^2.8.3", "rimraf": "^5.0.1", "sync-content": "^1.0.2", - "tap": "^18.1.4", - "tshy": "^1.2.2", - "typedoc": "^0.25.1", + "tap": "^18.7.2", + "ts-node": "^10.9.2", + "tshy": "^1.12.0", + "typedoc": "^0.25.12", "typescript": "^5.2.2" }, "tap": { diff --git a/deps/npm/node_modules/has-unicode/LICENSE b/deps/npm/node_modules/has-unicode/LICENSE deleted file mode 100644 index d42e25e95655bb..00000000000000 --- a/deps/npm/node_modules/has-unicode/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -Copyright (c) 2014, Rebecca Turner - -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. - diff --git a/deps/npm/node_modules/has-unicode/index.js b/deps/npm/node_modules/has-unicode/index.js deleted file mode 100644 index 9b0fe445401311..00000000000000 --- a/deps/npm/node_modules/has-unicode/index.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict" -var os = require("os") - -var hasUnicode = module.exports = function () { - // Recent Win32 platforms (>XP) CAN support unicode in the console but - // don't have to, and in non-english locales often use traditional local - // code pages. There's no way, short of windows system calls or execing - // the chcp command line program to figure this out. As such, we default - // this to false and encourage your users to override it via config if - // appropriate. - if (os.type() == "Windows_NT") { return false } - - var isUTF8 = /UTF-?8$/i - var ctype = process.env.LC_ALL || process.env.LC_CTYPE || process.env.LANG - return isUTF8.test(ctype) -} diff --git a/deps/npm/node_modules/has-unicode/package.json b/deps/npm/node_modules/has-unicode/package.json deleted file mode 100644 index ebe9d76d621587..00000000000000 --- a/deps/npm/node_modules/has-unicode/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "has-unicode", - "version": "2.0.1", - "description": "Try to guess if your terminal supports unicode", - "main": "index.js", - "scripts": { - "test": "tap test/*.js" - }, - "repository": { - "type": "git", - "url": "https://github.com/iarna/has-unicode" - }, - "keywords": [ - "unicode", - "terminal" - ], - "files": [ - "index.js" - ], - "author": "Rebecca Turner ", - "license": "ISC", - "bugs": { - "url": "https://github.com/iarna/has-unicode/issues" - }, - "homepage": "https://github.com/iarna/has-unicode", - "devDependencies": { - "require-inject": "^1.3.0", - "tap": "^2.3.1" - } -} diff --git a/deps/npm/node_modules/hasown/package.json b/deps/npm/node_modules/hasown/package.json index 1b03e9d3018bde..8502e13dd5c835 100644 --- a/deps/npm/node_modules/hasown/package.json +++ b/deps/npm/node_modules/hasown/package.json @@ -1,6 +1,6 @@ { "name": "hasown", - "version": "2.0.1", + "version": "2.0.2", "description": "A robust, ES3 compatible, \"has own property\" predicate.", "main": "index.js", "exports": { @@ -18,6 +18,7 @@ "postlint": "npm run tsc", "pretest": "npm run lint", "tsc": "tsc -p .", + "posttsc": "attw -P", "tests-only": "nyc tape 'test/**/*.js'", "test": "npm run tests-only", "posttest": "aud --production", @@ -50,7 +51,9 @@ "function-bind": "^1.1.2" }, "devDependencies": { + "@arethetypeswrong/cli": "^0.15.1", "@ljharb/eslint-config": "^21.1.0", + "@ljharb/tsconfig": "^0.2.0", "@types/function-bind": "^1.1.10", "@types/mock-property": "^1.0.2", "@types/tape": "^5.6.4", @@ -63,7 +66,7 @@ "npmignore": "^0.3.1", "nyc": "^10.3.2", "safe-publish-latest": "^2.0.0", - "tape": "^5.7.4", + "tape": "^5.7.5", "typescript": "next" }, "engines": { diff --git a/deps/npm/node_modules/hasown/tsconfig.json b/deps/npm/node_modules/hasown/tsconfig.json index fdab34fe311577..0930c565850326 100644 --- a/deps/npm/node_modules/hasown/tsconfig.json +++ b/deps/npm/node_modules/hasown/tsconfig.json @@ -1,49 +1,6 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - - /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - "typeRoots": ["types"], /* Specify multiple folders that act like './node_modules/@types'. */ - "resolveJsonModule": true, /* Enable importing .json files. */ - // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ - - /* JavaScript Support */ - "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - "declarationMap": true, /* Create sourcemaps for d.ts files. */ - "noEmit": true, /* Disable emitting files from a compilation. */ - - /* Interop Constraints */ - "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - - /* Completeness */ - //"skipLibCheck": true /* Skip type checking all .d.ts files. */ - }, + "extends": "@ljharb/tsconfig", "exclude": [ - "coverage" - ] + "coverage", + ], } diff --git a/deps/npm/node_modules/ini/lib/ini.js b/deps/npm/node_modules/ini/lib/ini.js index 724d69d85a0e45..0e8623ee699294 100644 --- a/deps/npm/node_modules/ini/lib/ini.js +++ b/deps/npm/node_modules/ini/lib/ini.js @@ -225,7 +225,7 @@ const safe = val => { return val.split(';').join('\\;').split('#').join('\\#') } -const unsafe = (val, doUnesc) => { +const unsafe = val => { val = (val || '').trim() if (isQuoted(val)) { // remove the single quotes before calling JSON.parse diff --git a/deps/npm/node_modules/ini/package.json b/deps/npm/node_modules/ini/package.json index c1a50e93c07f9a..caa36d223f09ca 100644 --- a/deps/npm/node_modules/ini/package.json +++ b/deps/npm/node_modules/ini/package.json @@ -2,7 +2,7 @@ "author": "GitHub Inc.", "name": "ini", "description": "An ini encoder/decoder for node", - "version": "4.1.1", + "version": "4.1.2", "repository": { "type": "git", "url": "https://github.com/npm/ini.git" @@ -10,7 +10,7 @@ "main": "lib/ini.js", "scripts": { "eslint": "eslint", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "lintfix": "npm run lint -- --fix", "test": "tap", "snap": "tap", @@ -20,7 +20,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.15.1", + "@npmcli/template-oss": "4.21.3", "tap": "^16.0.1" }, "license": "ISC", @@ -33,7 +33,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.15.1", + "version": "4.21.3", "publish": "true" }, "tap": { diff --git a/deps/npm/node_modules/init-package-json/lib/init-package-json.js b/deps/npm/node_modules/init-package-json/lib/init-package-json.js index 077ebd96ffc529..23fd3dc94dbe4b 100644 --- a/deps/npm/node_modules/init-package-json/lib/init-package-json.js +++ b/deps/npm/node_modules/init-package-json/lib/init-package-json.js @@ -1,29 +1,28 @@ const promzard = require('promzard') const path = require('path') -const fs = require('fs/promises') const semver = require('semver') -const read = require('read') +const { read } = require('read') const util = require('util') -const rpj = require('read-package-json') +const PackageJson = require('@npmcli/package-json') const def = require.resolve('./default-input.js') -// to validate the data object at the end as a worthwhile package -// and assign default values for things. -const _extraSet = rpj.extraSet -const _rpj = util.promisify(rpj) -const _rpjExtras = util.promisify(rpj.extras) -const readPkgJson = async (file, pkg) => { - // only do a few of these. no need for mans or contributors if they're in the files - rpj.extraSet = _extraSet.filter(f => f.name !== 'authors' && f.name !== 'mans') - const p = pkg ? _rpjExtras(file, pkg) : _rpj(file) - return p.catch(() => ({})).finally(() => rpj.extraSet = _extraSet) -} +const extras = [ + 'bundleDependencies', + 'gypfile', + 'serverjs', + 'scriptpath', + 'readme', + 'bin', + 'githead', + 'fillTypes', + 'normalizeData', +] const isYes = (c) => !!(c.get('yes') || c.get('y') || c.get('force') || c.get('f')) -const getConfig = (c = {}) => { +const getConfig = (c) => { // accept either a plain-jane object, or a config object with a "get" method. if (typeof c.get !== 'function') { const data = c @@ -35,25 +34,31 @@ const getConfig = (c = {}) => { return c } +// Coverage disabled because this is just walking back the fixPeople +// normalization from the normalizeData step and we don't need to re-test all +// of those paths. +/* istanbul ignore next */ const stringifyPerson = (p) => { - if (typeof p === 'string') { - return p - } - const { name = '', url, web, email, mail } = p + const { name, url, web, email, mail } = p const u = url || web const e = email || mail return `${name}${e ? ` <${e}>` : ''}${u ? ` (${u})` : ''}` } - -async function init (dir, input = def, c = {}) { +async function init (dir, + // TODO test for non-default definitions + /* istanbul ignore next */ + input = def, + c = {}) { const config = getConfig(c) const yes = isYes(config) const packageFile = path.resolve(dir, 'package.json') - const pkg = await readPkgJson(packageFile) + // read what's already there to inform our prompts + const pkg = await PackageJson.load(dir, { create: true }) + await pkg.normalize() - if (!semver.valid(pkg.version)) { - delete pkg.version + if (!semver.valid(pkg.content.version)) { + delete pkg.content.version } // make sure that the input is valid. if not, use the default @@ -61,73 +66,67 @@ async function init (dir, input = def, c = {}) { yes, config, filename: packageFile, - dirname: path.dirname(packageFile), - basename: path.basename(path.dirname(packageFile)), - package: pkg, + dirname: dir, + basename: path.basename(dir), + package: pkg.content, }, { backupFile: def }) for (const [k, v] of Object.entries(pzData)) { if (v != null) { - pkg[k] = v + pkg.content[k] = v } } - const pkgExtras = await readPkgJson(packageFile, pkg) + await pkg.normalize({ steps: extras }) - // turn the objects into somewhat more humane strings. - if (pkgExtras.author) { - pkgExtras.author = stringifyPerson(pkgExtras.author) - } - - for (const set of ['maintainers', 'contributors']) { - if (Array.isArray(pkgExtras[set])) { - pkgExtras[set] = pkgExtras[set].map(stringifyPerson) - } + // turn the objects back into somewhat more humane strings. + // "normalizeData" does this and there isn't a way to choose which of those steps happen + if (pkg.content.author) { + pkg.content.author = stringifyPerson(pkg.content.author) } // no need for the readme now. - delete pkgExtras.readme - delete pkgExtras.readmeFilename + delete pkg.content.readme + delete pkg.content.readmeFilename // really don't want to have this lying around in the file - delete pkgExtras._id + delete pkg.content._id // ditto - delete pkgExtras.gitHead + delete pkg.content.gitHead // if the repo is empty, remove it. - if (!pkgExtras.repository) { - delete pkgExtras.repository + if (!pkg.content.repository) { + delete pkg.content.repository } // readJson filters out empty descriptions, but init-package-json // traditionally leaves them alone - if (!pkgExtras.description) { - pkgExtras.description = pzData.description + if (!pkg.content.description) { + pkg.content.description = pzData.description } // optionalDependencies don't need to be repeated in two places - if (pkgExtras.dependencies) { - if (pkgExtras.optionalDependencies) { - for (const name of Object.keys(pkgExtras.optionalDependencies)) { - delete pkgExtras.dependencies[name] + if (pkg.content.dependencies) { + if (pkg.content.optionalDependencies) { + for (const name of Object.keys(pkg.content.optionalDependencies)) { + delete pkg.content.dependencies[name] } } - if (Object.keys(pkgExtras.dependencies).length === 0) { - delete pkgExtras.dependencies + if (Object.keys(pkg.content.dependencies).length === 0) { + delete pkg.content.dependencies } } - const stringified = JSON.stringify(pkgExtras, null, 2) + '\n' + const stringified = JSON.stringify(pkg.content, null, 2) + '\n' const msg = util.format('%s:\n\n%s\n', packageFile, stringified) - const write = () => fs.writeFile(packageFile, stringified, 'utf8') if (yes) { - await write() + await pkg.save() if (!config.get('silent')) { console.log(`Wrote to ${msg}`) } - return pkgExtras + return pkg.content } console.log(`About to write to ${msg}`) @@ -137,8 +136,8 @@ async function init (dir, input = def, c = {}) { return } - await write() - return pkgExtras + await pkg.save() + return pkg.content } module.exports = init diff --git a/deps/npm/node_modules/init-package-json/package.json b/deps/npm/node_modules/init-package-json/package.json index a164169a74df3c..e867964e101569 100644 --- a/deps/npm/node_modules/init-package-json/package.json +++ b/deps/npm/node_modules/init-package-json/package.json @@ -1,10 +1,10 @@ { "name": "init-package-json", - "version": "6.0.0", + "version": "6.0.2", "main": "lib/init-package-json.js", "scripts": { "test": "tap", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "postlint": "template-oss-check", "lintfix": "npm run lint -- --fix", "snap": "tap", @@ -19,28 +19,24 @@ "license": "ISC", "description": "A node module to get your node module started", "dependencies": { + "@npmcli/package-json": "^5.0.0", "npm-package-arg": "^11.0.0", "promzard": "^1.0.0", - "read": "^2.0.0", - "read-package-json": "^7.0.0", + "read": "^3.0.1", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4", "validate-npm-package-name": "^5.0.0" }, "devDependencies": { - "@npmcli/config": "^7.0.0", + "@npmcli/config": "^8.2.0", "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.18.0", + "@npmcli/template-oss": "4.21.3", "tap": "^16.0.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" }, "tap": { - "statements": 95, - "branches": 78, - "lines": 94, - "jobs": 1, "test-ignore": "fixtures/", "nyc-arg": [ "--exclude", @@ -63,13 +59,7 @@ ], "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.18.0", - "publish": true, - "ciVersions": [ - "16.14.0", - "16.x", - "18.0.0", - "18.x" - ] + "version": "4.21.3", + "publish": true } } diff --git a/deps/npm/node_modules/is-cidr/LICENSE b/deps/npm/node_modules/is-cidr/LICENSE deleted file mode 100644 index 9669c20f85511d..00000000000000 --- a/deps/npm/node_modules/is-cidr/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) silverwind -All rights reserved. - -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. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. diff --git a/deps/npm/node_modules/is-cidr/package.json b/deps/npm/node_modules/is-cidr/package.json index d6971b3b33bd83..baf6fa55fe4522 100644 --- a/deps/npm/node_modules/is-cidr/package.json +++ b/deps/npm/node_modules/is-cidr/package.json @@ -1,6 +1,6 @@ { "name": "is-cidr", - "version": "5.0.3", + "version": "5.0.5", "description": "Check if a string is an IP address in CIDR notation", "author": "silverwind ", "contributors": [ @@ -19,14 +19,15 @@ "index.d.ts" ], "dependencies": { - "cidr-regex": "4.0.3" + "cidr-regex": "^4.0.4" }, "devDependencies": { - "eslint": "8.37.0", - "eslint-config-silverwind": "65.1.3", - "tsd": "0.28.1", - "updates": "13.2.9", - "versions": "10.4.2", - "vitest": "0.29.8" + "eslint": "8.57.0", + "eslint-config-silverwind": "83.0.1", + "tsd": "0.31.0", + "updates": "16.0.0", + "versions": "12.0.1", + "vitest": "1.4.0", + "vitest-config-silverwind": "7.0.3" } } diff --git a/deps/npm/node_modules/libnpmaccess/package.json b/deps/npm/node_modules/libnpmaccess/package.json index 8b8459dcec251b..59b5afa7c7b5f6 100644 --- a/deps/npm/node_modules/libnpmaccess/package.json +++ b/deps/npm/node_modules/libnpmaccess/package.json @@ -1,6 +1,6 @@ { "name": "libnpmaccess", - "version": "8.0.2", + "version": "8.0.5", "description": "programmatic library for `npm access` commands", "author": "GitHub Inc.", "license": "ISC", @@ -23,14 +23,14 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmaccess" }, "bugs": "https://github.com/npm/libnpmaccess/issues", "homepage": "https://npmjs.com/package/libnpmaccess", "dependencies": { - "npm-package-arg": "^11.0.1", - "npm-registry-fetch": "^16.0.0" + "npm-package-arg": "^11.0.2", + "npm-registry-fetch": "^17.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" diff --git a/deps/npm/node_modules/libnpmdiff/lib/format-diff.js b/deps/npm/node_modules/libnpmdiff/lib/format-diff.js index 211386cb5390ee..a6606d94b8b302 100644 --- a/deps/npm/node_modules/libnpmdiff/lib/format-diff.js +++ b/deps/npm/node_modules/libnpmdiff/lib/format-diff.js @@ -1,10 +1,24 @@ -const EOL = '\n' - -const colorizeDiff = require('@npmcli/disparity-colors') const jsDiff = require('diff') const shouldPrintPatch = require('./should-print-patch.js') +const colors = { + // red + removed: { open: '\x1B[31m', close: '\x1B[39m' }, + // green + added: { open: '\x1B[32m', close: '\x1B[39m' }, + // blue + header: { open: '\x1B[34m', close: '\x1B[39m' }, + // cyan + section: { open: '\x1B[36m', close: '\x1B[39m' }, +} + +const color = (colorStr, colorId) => { + const { open, close } = colors[colorId] + // avoid highlighting the "\n" (would highlight till the end of the line) + return colorStr.replace(/[^\n\r]+/g, open + '$&' + close) +} + const formatDiff = ({ files, opts = {}, refs, versions }) => { let res = '' const srcPrefix = opts.diffNoPrefix ? '' : opts.diffSrcPrefix || 'a/' @@ -35,7 +49,7 @@ const formatDiff = ({ files, opts = {}, refs, versions }) => { } if (opts.diffNameOnly) { - res += `${filename}${EOL}` + res += `${filename}\n` continue } @@ -43,7 +57,7 @@ const formatDiff = ({ files, opts = {}, refs, versions }) => { let headerLength = 0 const header = str => { headerLength++ - patch += `${str}${EOL}` + patch += `${str}\n` } // manually build a git diff-compatible header @@ -85,9 +99,17 @@ const formatDiff = ({ files, opts = {}, refs, versions }) => { header(`+++ ${names.b}`) } - res += (opts.color - ? colorizeDiff(patch, { headerLength }) - : patch) + if (opts.color) { + // this RegExp will include all the `\n` chars into the lines, easier to join + const lines = patch.split(/^/m) + res += color(lines.slice(0, headerLength).join(''), 'header') + res += lines.slice(headerLength).join('') + .replace(/^-.*/gm, color('$&', 'removed')) + .replace(/^\+.*/gm, color('$&', 'added')) + .replace(/^@@.+@@/gm, color('$&', 'section')) + } else { + res += patch + } } return res.trim() diff --git a/deps/npm/node_modules/libnpmdiff/lib/tarball.js b/deps/npm/node_modules/libnpmdiff/lib/tarball.js index 930d624f2d5b6a..41ea84a6885a5e 100644 --- a/deps/npm/node_modules/libnpmdiff/lib/tarball.js +++ b/deps/npm/node_modules/libnpmdiff/lib/tarball.js @@ -9,7 +9,7 @@ const tar = require('tar') // returns a simplified tarball when reading files from node_modules folder, // thus avoiding running the prepare scripts and the extra logic from packlist -const nodeModulesTarball = (manifest, opts) => +const nodeModulesTarball = (manifest) => pkgContents({ path: manifest._resolved, depth: 1 }) .then(files => files.map(file => relative(manifest._resolved, file)) diff --git a/deps/npm/node_modules/libnpmdiff/package.json b/deps/npm/node_modules/libnpmdiff/package.json index b130b128cf7372..d601ff61ca0218 100644 --- a/deps/npm/node_modules/libnpmdiff/package.json +++ b/deps/npm/node_modules/libnpmdiff/package.json @@ -1,10 +1,10 @@ { "name": "libnpmdiff", - "version": "6.0.7", + "version": "6.1.1", "description": "The registry diff", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmdiff" }, "main": "lib/index.js", @@ -47,14 +47,13 @@ }, "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/disparity-colors": "^3.0.0", - "@npmcli/installed-package-contents": "^2.0.2", - "binary-extensions": "^2.2.0", + "@npmcli/installed-package-contents": "^2.1.0", + "binary-extensions": "^2.3.0", "diff": "^5.1.0", - "minimatch": "^9.0.0", - "npm-package-arg": "^11.0.1", - "pacote": "^17.0.4", - "tar": "^6.2.0" + "minimatch": "^9.0.4", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.1", + "tar": "^6.2.1" }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", diff --git a/deps/npm/node_modules/libnpmexec/README.md b/deps/npm/node_modules/libnpmexec/README.md index fb4a1e32b18df7..acd037c110b4ba 100644 --- a/deps/npm/node_modules/libnpmexec/README.md +++ b/deps/npm/node_modules/libnpmexec/README.md @@ -35,7 +35,6 @@ await libexec({ - `localBin`: Location to the `node_modules/.bin` folder of the local project to start scanning for bin files **String**, defaults to `./node_modules/.bin`. **libexec** will walk up the directory structure looking for `node_modules/.bin` folders in parent folders that might satisfy the current `arg` and will use that bin if found. - `locationMsg`: Overrides "at location" message when entering interactive mode **String** - `globalBin`: Location to the global space bin folder, same as: `$(npm bin -g)` **String**, defaults to empty string. - - `output`: A function to print output to **Function** - `packages`: A list of packages to be used (possibly fetch from the registry) **Array**, defaults to `[]` - `path`: Location to where to read local project info (`package.json`) **String**, defaults to `.` - `runPath`: Location to where to execute the script **String**, defaults to `.` diff --git a/deps/npm/node_modules/libnpmexec/lib/index.js b/deps/npm/node_modules/libnpmexec/lib/index.js index 34bb20769bc2c7..28cba79a7f227a 100644 --- a/deps/npm/node_modules/libnpmexec/lib/index.js +++ b/deps/npm/node_modules/libnpmexec/lib/index.js @@ -4,19 +4,16 @@ const { mkdir } = require('fs/promises') const Arborist = require('@npmcli/arborist') const ciInfo = require('ci-info') const crypto = require('crypto') -const log = require('proc-log') +const { log, input } = require('proc-log') const npa = require('npm-package-arg') -const npmlog = require('npmlog') const pacote = require('pacote') -const read = require('read') +const { read } = require('read') const semver = require('semver') - const { fileExists, localFileExists } = require('./file-exists.js') const getBinFromManifest = require('./get-bin-from-manifest.js') const noTTY = require('./no-tty.js') const runScript = require('./run-script.js') const isWindows = require('./is-windows.js') - const { dirname, resolve } = require('path') const binPaths = [] @@ -84,7 +81,6 @@ const exec = async (opts) => { locationMsg = undefined, globalBin = '', globalPath, - output, // dereference values because we manipulate it later packages: [...packages] = [], path = '.', @@ -99,7 +95,6 @@ const exec = async (opts) => { call, flatOptions, locationMsg, - output, path, binPaths, runPath, @@ -245,27 +240,24 @@ const exec = async (opts) => { if (add.length) { if (!yes) { - const missingPackages = add.map(a => `${a.replace(/@$/, '')}`) + const addList = add.map(a => `${a.replace(/@$/, '')}`) + // set -n to always say no if (yes === false) { // Error message lists missing package(s) when process is canceled /* eslint-disable-next-line max-len */ - throw new Error(`npx canceled due to missing packages and no YES option: ${JSON.stringify(missingPackages)}`) + throw new Error(`npx canceled due to missing packages and no YES option: ${JSON.stringify(addList)}`) } if (noTTY() || ciInfo.isCI) { - log.warn('exec', `The following package${ - add.length === 1 ? ' was' : 's were' - } not found and will be installed: ${ - add.map((pkg) => pkg.replace(/@$/, '')).join(', ') - }`) + /* eslint-disable-next-line max-len */ + log.warn('exec', `The following package${add.length === 1 ? ' was' : 's were'} not found and will be installed: ${addList.join(', ')}`) } else { - const addList = missingPackages.join('\n') + '\n' - const prompt = `Need to install the following packages:\n${ - addList - }Ok to proceed? ` - npmlog.clearProgress() - const confirm = await read({ prompt, default: 'y' }) + const confirm = await input.read(() => read({ + /* eslint-disable-next-line max-len */ + prompt: `Need to install the following packages:\n${addList.join('\n')}\nOk to proceed? `, + default: 'y', + })) if (confirm.trim().toLowerCase().charAt(0) !== 'y') { throw new Error('canceled') } diff --git a/deps/npm/node_modules/libnpmexec/lib/run-script.js b/deps/npm/node_modules/libnpmexec/lib/run-script.js index 89dcf2e653036e..1f621edcbc9aa2 100644 --- a/deps/npm/node_modules/libnpmexec/lib/run-script.js +++ b/deps/npm/node_modules/libnpmexec/lib/run-script.js @@ -1,8 +1,7 @@ const ciInfo = require('ci-info') const runScript = require('@npmcli/run-script') const readPackageJson = require('read-package-json-fast') -const npmlog = require('npmlog') -const log = require('proc-log') +const { log, output } = require('proc-log') const noTTY = require('./no-tty.js') const run = async ({ @@ -10,7 +9,6 @@ const run = async ({ call, flatOptions, locationMsg, - output = () => {}, path, binPaths, runPath, @@ -21,8 +19,7 @@ const run = async ({ // do the fakey runScript dance // still should work if no package.json in cwd - const realPkg = await readPackageJson(`${path}/package.json`) - .catch(() => ({})) + const realPkg = await readPackageJson(`${path}/package.json`).catch(() => ({})) const pkg = { ...realPkg, scripts: { @@ -31,41 +28,34 @@ const run = async ({ }, } - npmlog.disableProgress() - - try { - if (script === scriptShell) { - if (!noTTY()) { - if (ciInfo.isCI) { - return log.warn('exec', 'Interactive mode disabled in CI environment') - } + if (script === scriptShell) { + if (!noTTY()) { + if (ciInfo.isCI) { + return log.warn('exec', 'Interactive mode disabled in CI environment') + } - locationMsg = locationMsg || ` at location:\n${flatOptions.chalk.dim(runPath)}` + const { chalk } = flatOptions - output(`${ - flatOptions.chalk.reset('\nEntering npm script environment') - }${ - flatOptions.chalk.reset(locationMsg) - }${ - flatOptions.chalk.bold('\nType \'exit\' or ^D when finished\n') - }`) - } + output.standard(`${ + chalk.reset('\nEntering npm script environment') + }${ + chalk.reset(locationMsg || ` at location:\n${chalk.dim(runPath)}`) + }${ + chalk.bold('\nType \'exit\' or ^D when finished\n') + }`) } - return await runScript({ - ...flatOptions, - pkg, - banner: false, - // we always run in cwd, not --prefix - path: runPath, - binPaths, - event: 'npx', - args, - stdio: 'inherit', - scriptShell, - }) - } finally { - npmlog.enableProgress() } + return runScript({ + ...flatOptions, + pkg, + // we always run in cwd, not --prefix + path: runPath, + binPaths, + event: 'npx', + args, + stdio: 'inherit', + scriptShell, + }) } module.exports = run diff --git a/deps/npm/node_modules/libnpmexec/package.json b/deps/npm/node_modules/libnpmexec/package.json index 2b4fb559ba4a2e..fcb30087cb5d22 100644 --- a/deps/npm/node_modules/libnpmexec/package.json +++ b/deps/npm/node_modules/libnpmexec/package.json @@ -1,6 +1,6 @@ { "name": "libnpmexec", - "version": "7.0.8", + "version": "8.1.0", "files": [ "bin/", "lib/" @@ -12,7 +12,7 @@ "description": "npm exec (npx) programmatic API", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmexec" }, "keywords": [ @@ -60,13 +60,12 @@ }, "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/run-script": "^7.0.2", + "@npmcli/run-script": "^8.1.0", "ci-info": "^4.0.0", - "npm-package-arg": "^11.0.1", - "npmlog": "^7.0.1", - "pacote": "^17.0.4", - "proc-log": "^3.0.0", - "read": "^2.0.0", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.1", + "proc-log": "^4.2.0", + "read": "^3.0.1", "read-package-json-fast": "^3.0.2", "semver": "^7.3.7", "walk-up-path": "^3.0.1" diff --git a/deps/npm/node_modules/libnpmfund/lib/index.js b/deps/npm/node_modules/libnpmfund/lib/index.js index a53893dc1cf87b..39b69afc0abcc5 100644 --- a/deps/npm/node_modules/libnpmfund/lib/index.js +++ b/deps/npm/node_modules/libnpmfund/lib/index.js @@ -133,7 +133,7 @@ function readTree (tree, opts) { }) return directDepsWithFunding.reduce( - (res, { node, fundingItem }, i) => { + (res, { node, fundingItem }) => { if (!fundingItem || fundingItem.length === 0 || !node) { diff --git a/deps/npm/node_modules/libnpmfund/package.json b/deps/npm/node_modules/libnpmfund/package.json index 66889c1fa6d5b5..70a53646910a57 100644 --- a/deps/npm/node_modules/libnpmfund/package.json +++ b/deps/npm/node_modules/libnpmfund/package.json @@ -1,6 +1,6 @@ { "name": "libnpmfund", - "version": "5.0.5", + "version": "5.0.9", "main": "lib/index.js", "files": [ "bin/", @@ -9,7 +9,7 @@ "description": "Programmatic API for npm fund", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmfund" }, "keywords": [ diff --git a/deps/npm/node_modules/libnpmhook/package.json b/deps/npm/node_modules/libnpmhook/package.json index 0bd822abba2c3f..2cfa16df091be3 100644 --- a/deps/npm/node_modules/libnpmhook/package.json +++ b/deps/npm/node_modules/libnpmhook/package.json @@ -1,6 +1,6 @@ { "name": "libnpmhook", - "version": "10.0.1", + "version": "10.0.4", "description": "programmatic API for managing npm registry hooks", "main": "lib/index.js", "files": [ @@ -18,7 +18,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmhook" }, "keywords": [ @@ -31,7 +31,7 @@ "license": "ISC", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^16.0.0" + "npm-registry-fetch": "^17.0.0" }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", diff --git a/deps/npm/node_modules/libnpmorg/package.json b/deps/npm/node_modules/libnpmorg/package.json index a0aedb79b6084c..1a7486bfc681d2 100644 --- a/deps/npm/node_modules/libnpmorg/package.json +++ b/deps/npm/node_modules/libnpmorg/package.json @@ -1,6 +1,6 @@ { "name": "libnpmorg", - "version": "6.0.2", + "version": "6.0.5", "description": "Programmatic api for `npm org` commands", "author": "GitHub Inc.", "main": "lib/index.js", @@ -35,14 +35,14 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmorg" }, "bugs": "https://github.com/npm/libnpmorg/issues", "homepage": "https://npmjs.com/package/libnpmorg", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^16.0.0" + "npm-registry-fetch": "^17.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" diff --git a/deps/npm/node_modules/libnpmpack/lib/index.js b/deps/npm/node_modules/libnpmpack/lib/index.js index 70d67d360f0d9b..c71716cf544285 100644 --- a/deps/npm/node_modules/libnpmpack/lib/index.js +++ b/deps/npm/node_modules/libnpmpack/lib/index.js @@ -4,9 +4,8 @@ const pacote = require('pacote') const npa = require('npm-package-arg') const runScript = require('@npmcli/run-script') const path = require('path') -const util = require('util') const Arborist = require('@npmcli/arborist') -const writeFile = util.promisify(require('fs').writeFile) +const { writeFile } = require('fs/promises') module.exports = pack async function pack (spec = 'file:.', opts = {}) { @@ -15,10 +14,6 @@ async function pack (spec = 'file:.', opts = {}) { const manifest = await pacote.manifest(spec, opts) - // Default to true if no log options passed, set to false if we're in silent - // mode - const banner = !opts.silent - const stdio = opts.foregroundScripts ? 'inherit' : 'pipe' if (spec.type === 'directory' && !opts.ignoreScripts) { @@ -29,7 +24,6 @@ async function pack (spec = 'file:.', opts = {}) { path: spec.fetchSpec, stdio, pkg: manifest, - banner, }) } @@ -56,7 +50,6 @@ async function pack (spec = 'file:.', opts = {}) { path: spec.fetchSpec, stdio, pkg: manifest, - banner, env: { npm_package_from: tarball.from, npm_package_resolved: tarball.resolved, diff --git a/deps/npm/node_modules/libnpmpack/package.json b/deps/npm/node_modules/libnpmpack/package.json index 1d504fca4ec9b6..9e40f294cc54f6 100644 --- a/deps/npm/node_modules/libnpmpack/package.json +++ b/deps/npm/node_modules/libnpmpack/package.json @@ -1,6 +1,6 @@ { "name": "libnpmpack", - "version": "6.0.7", + "version": "7.0.1", "description": "Programmatic API for the bits behind npm pack", "author": "GitHub Inc.", "main": "lib/index.js", @@ -30,16 +30,16 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmpack" }, "bugs": "https://github.com/npm/libnpmpack/issues", "homepage": "https://npmjs.com/package/libnpmpack", "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/run-script": "^7.0.2", - "npm-package-arg": "^11.0.1", - "pacote": "^17.0.4" + "@npmcli/run-script": "^8.1.0", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" diff --git a/deps/npm/node_modules/libnpmpublish/lib/publish.js b/deps/npm/node_modules/libnpmpublish/lib/publish.js index b0ef782a166c66..9ffbc934263099 100644 --- a/deps/npm/node_modules/libnpmpublish/lib/publish.js +++ b/deps/npm/node_modules/libnpmpublish/lib/publish.js @@ -1,7 +1,7 @@ const { fixer } = require('normalize-package-data') const npmFetch = require('npm-registry-fetch') const npa = require('npm-package-arg') -const log = require('proc-log') +const { log } = require('proc-log') const semver = require('semver') const { URL } = require('url') const ssri = require('ssri') diff --git a/deps/npm/node_modules/libnpmpublish/package.json b/deps/npm/node_modules/libnpmpublish/package.json index 67f63816d90d59..31faaa7b59f266 100644 --- a/deps/npm/node_modules/libnpmpublish/package.json +++ b/deps/npm/node_modules/libnpmpublish/package.json @@ -1,6 +1,6 @@ { "name": "libnpmpublish", - "version": "9.0.4", + "version": "9.0.7", "description": "Programmatic API for the bits behind npm publish and unpublish", "author": "GitHub Inc.", "main": "lib/index.js", @@ -32,7 +32,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmpublish" }, "bugs": "https://github.com/npm/cli/issues", @@ -40,9 +40,9 @@ "dependencies": { "ci-info": "^4.0.0", "normalize-package-data": "^6.0.0", - "npm-package-arg": "^11.0.1", - "npm-registry-fetch": "^16.0.0", - "proc-log": "^3.0.0", + "npm-package-arg": "^11.0.2", + "npm-registry-fetch": "^17.0.0", + "proc-log": "^4.2.0", "semver": "^7.3.7", "sigstore": "^2.2.0", "ssri": "^10.0.5" diff --git a/deps/npm/node_modules/libnpmsearch/package.json b/deps/npm/node_modules/libnpmsearch/package.json index 42cb78839081cd..cb21747310eaec 100644 --- a/deps/npm/node_modules/libnpmsearch/package.json +++ b/deps/npm/node_modules/libnpmsearch/package.json @@ -1,6 +1,6 @@ { "name": "libnpmsearch", - "version": "7.0.1", + "version": "7.0.4", "description": "Programmatic API for searching in npm and compatible registries.", "author": "GitHub Inc.", "main": "lib/index.js", @@ -32,13 +32,13 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmsearch" }, "bugs": "https://github.com/npm/libnpmsearch/issues", "homepage": "https://npmjs.com/package/libnpmsearch", "dependencies": { - "npm-registry-fetch": "^16.0.0" + "npm-registry-fetch": "^17.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" diff --git a/deps/npm/node_modules/libnpmteam/package.json b/deps/npm/node_modules/libnpmteam/package.json index bafeeb3fcdc4c6..94f264bd93bf7c 100644 --- a/deps/npm/node_modules/libnpmteam/package.json +++ b/deps/npm/node_modules/libnpmteam/package.json @@ -1,7 +1,7 @@ { "name": "libnpmteam", "description": "npm Team management APIs", - "version": "6.0.1", + "version": "6.0.4", "author": "GitHub Inc.", "license": "ISC", "main": "lib/index.js", @@ -22,7 +22,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmteam" }, "files": [ @@ -32,7 +32,7 @@ "homepage": "https://npmjs.com/package/libnpmteam", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^16.0.0" + "npm-registry-fetch": "^17.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" diff --git a/deps/npm/node_modules/libnpmversion/README.md b/deps/npm/node_modules/libnpmversion/README.md index ac9ee50ae35d91..857c4d52dc1831 100644 --- a/deps/npm/node_modules/libnpmversion/README.md +++ b/deps/npm/node_modules/libnpmversion/README.md @@ -31,7 +31,6 @@ npmVersion(arg, { ignoreScripts: false, // do not run pre/post/version lifecycle scripts scriptShell: '/bin/bash', // shell to run lifecycle scripts in message: 'v%s', // message for tag and commit, replace %s with the version - silent: false, // passed to @npmcli/run-script to control whether it logs }).then(newVersion => { console.error('version updated!', newVersion) }) diff --git a/deps/npm/node_modules/libnpmversion/lib/enforce-clean.js b/deps/npm/node_modules/libnpmversion/lib/enforce-clean.js index 721f146221c155..25ebb5590e9171 100644 --- a/deps/npm/node_modules/libnpmversion/lib/enforce-clean.js +++ b/deps/npm/node_modules/libnpmversion/lib/enforce-clean.js @@ -1,5 +1,5 @@ const git = require('@npmcli/git') -const log = require('proc-log') +const { log } = require('proc-log') // returns true if it's cool to do git stuff // throws if it's unclean, and not forced. diff --git a/deps/npm/node_modules/libnpmversion/lib/index.js b/deps/npm/node_modules/libnpmversion/lib/index.js index 95acd11b5e4331..4d2fb45945a7b9 100644 --- a/deps/npm/node_modules/libnpmversion/lib/index.js +++ b/deps/npm/node_modules/libnpmversion/lib/index.js @@ -15,7 +15,6 @@ module.exports = async (newversion, opts = {}) => { scriptShell = undefined, preid = null, message = 'v%s', - silent, } = opts const pkg = opts.pkg || await readJson(path + '/package.json') @@ -35,6 +34,5 @@ module.exports = async (newversion, opts = {}) => { preid, pkg, message, - silent, }) } diff --git a/deps/npm/node_modules/libnpmversion/lib/read-json.js b/deps/npm/node_modules/libnpmversion/lib/read-json.js index 2dd0f7aa4902e8..32c7289507697f 100644 --- a/deps/npm/node_modules/libnpmversion/lib/read-json.js +++ b/deps/npm/node_modules/libnpmversion/lib/read-json.js @@ -1,7 +1,6 @@ // can't use read-package-json-fast, because we want to ensure // that we make as few changes as possible, even for safety issues. -const { promisify } = require('util') -const readFile = promisify(require('fs').readFile) +const { readFile } = require('fs/promises') const parse = require('json-parse-even-better-errors') module.exports = async path => parse(await readFile(path)) diff --git a/deps/npm/node_modules/libnpmversion/lib/version.js b/deps/npm/node_modules/libnpmversion/lib/version.js index f14b95e3233f06..bfcd8a521496d5 100644 --- a/deps/npm/node_modules/libnpmversion/lib/version.js +++ b/deps/npm/node_modules/libnpmversion/lib/version.js @@ -8,7 +8,7 @@ const readJson = require('./read-json.js') const git = require('@npmcli/git') const commit = require('./commit.js') const tag = require('./tag.js') -const log = require('proc-log') +const { log } = require('proc-log') const runScript = require('@npmcli/run-script') @@ -20,7 +20,6 @@ module.exports = async (newversion, opts) => { ignoreScripts, preid, pkg, - silent, } = opts const { valid, clean, inc } = semver @@ -65,7 +64,6 @@ module.exports = async (newversion, opts) => { pkg, stdio: 'inherit', event: 'preversion', - banner: !silent, env: { npm_old_version: current, npm_new_version: newV, @@ -101,7 +99,6 @@ module.exports = async (newversion, opts) => { pkg, stdio: 'inherit', event: 'version', - banner: !silent, env: { npm_old_version: current, npm_new_version: newV, @@ -128,7 +125,6 @@ module.exports = async (newversion, opts) => { pkg, stdio: 'inherit', event: 'postversion', - banner: !silent, env: { npm_old_version: current, npm_new_version: newV, diff --git a/deps/npm/node_modules/libnpmversion/lib/write-json.js b/deps/npm/node_modules/libnpmversion/lib/write-json.js index f066d72c67e124..425be8e8e3efb2 100644 --- a/deps/npm/node_modules/libnpmversion/lib/write-json.js +++ b/deps/npm/node_modules/libnpmversion/lib/write-json.js @@ -1,6 +1,5 @@ // write the json back, preserving the line breaks and indent -const { promisify } = require('util') -const writeFile = promisify(require('fs').writeFile) +const { writeFile } = require('fs/promises') const kIndent = Symbol.for('indent') const kNewline = Symbol.for('newline') diff --git a/deps/npm/node_modules/libnpmversion/package.json b/deps/npm/node_modules/libnpmversion/package.json index 782eeca7d2b795..43b0d2ff825d7b 100644 --- a/deps/npm/node_modules/libnpmversion/package.json +++ b/deps/npm/node_modules/libnpmversion/package.json @@ -1,6 +1,6 @@ { "name": "libnpmversion", - "version": "5.0.2", + "version": "6.0.1", "main": "lib/index.js", "files": [ "bin/", @@ -9,7 +9,7 @@ "description": "library to do the things that 'npm version' does", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmversion" }, "author": "GitHub Inc.", @@ -37,10 +37,10 @@ "tap": "^16.3.8" }, "dependencies": { - "@npmcli/git": "^5.0.3", - "@npmcli/run-script": "^7.0.2", + "@npmcli/git": "^5.0.6", + "@npmcli/run-script": "^8.1.0", "json-parse-even-better-errors": "^3.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.2.0", "semver": "^7.3.7" }, "engines": { diff --git a/deps/npm/node_modules/lru-cache/dist/commonjs/index.min.js b/deps/npm/node_modules/lru-cache/dist/commonjs/index.min.js new file mode 100644 index 00000000000000..b7149f5415a45f --- /dev/null +++ b/deps/npm/node_modules/lru-cache/dist/commonjs/index.min.js @@ -0,0 +1,2 @@ +"use strict";var G=(o,t,e)=>{if(!t.has(o))throw TypeError("Cannot "+e)};var j=(o,t,e)=>(G(o,t,"read from private field"),e?e.call(o):t.get(o)),I=(o,t,e)=>{if(t.has(o))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(o):t.set(o,e)},D=(o,t,e,i)=>(G(o,t,"write to private field"),i?i.call(o,e):t.set(o,e),e);Object.defineProperty(exports,"__esModule",{value:!0});exports.LRUCache=void 0;var T=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date,N=new Set,L=typeof process=="object"&&process?process:{},P=(o,t,e,i)=>{typeof L.emitWarning=="function"?L.emitWarning(o,t,e,i):console.error(`[${e}] ${t}: ${o}`)},W=globalThis.AbortController,M=globalThis.AbortSignal;if(typeof W>"u"){M=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(i,s){this._onabort.push(s)}},W=class{constructor(){t()}signal=new M;abort(i){if(!this.signal.aborted){this.signal.reason=i,this.signal.aborted=!0;for(let s of this.signal._onabort)s(i);this.signal.onabort?.(i)}}};let o=L.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",t=()=>{o&&(o=!1,P("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",t))}}var V=o=>!N.has(o),Y=Symbol("type"),A=o=>o&&o===Math.floor(o)&&o>0&&isFinite(o),H=o=>A(o)?o<=Math.pow(2,8)?Uint8Array:o<=Math.pow(2,16)?Uint16Array:o<=Math.pow(2,32)?Uint32Array:o<=Number.MAX_SAFE_INTEGER?E:null:null,E=class extends Array{constructor(t){super(t),this.fill(0)}},v,z=class{heap;length;static create(t){let e=H(t);if(!e)return[];D(z,v,!0);let i=new z(t,e);return D(z,v,!1),i}constructor(t,e){if(!j(z,v))throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},R=z;v=new WeakMap,I(R,v,!1);var C=class{#g;#f;#p;#w;#C;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#n;#S;#s;#i;#t;#l;#c;#o;#h;#_;#r;#b;#y;#u;#m;#T;#a;static unsafeExposeInternals(t){return{starts:t.#y,ttls:t.#u,sizes:t.#b,keyMap:t.#s,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#c,get head(){return t.#o},get tail(){return t.#h},free:t.#_,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#D(e,i,s,n),moveToTail:e=>t.#v(e),indexes:e=>t.#A(e),rindexes:e=>t.#F(e),isStale:e=>t.#d(e)}}get max(){return this.#g}get maxSize(){return this.#f}get calculatedSize(){return this.#S}get size(){return this.#n}get fetchMethod(){return this.#C}get dispose(){return this.#p}get disposeAfter(){return this.#w}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:h,updateAgeOnHas:l,allowStale:r,dispose:g,disposeAfter:b,noDisposeOnSet:f,noUpdateTTL:u,maxSize:c=0,maxEntrySize:F=0,sizeCalculation:d,fetchMethod:S,noDeleteOnFetchRejection:a,noDeleteOnStaleGet:w,allowStaleOnFetchRejection:y,allowStaleOnFetchAbort:p,ignoreFetchAbort:_}=t;if(e!==0&&!A(e))throw new TypeError("max option must be a nonnegative integer");let O=e?H(e):Array;if(!O)throw new Error("invalid max value: "+e);if(this.#g=e,this.#f=c,this.maxEntrySize=F||this.#f,this.sizeCalculation=d,this.sizeCalculation){if(!this.#f&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(S!==void 0&&typeof S!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#C=S,this.#T=!!S,this.#s=new Map,this.#i=new Array(e).fill(void 0),this.#t=new Array(e).fill(void 0),this.#l=new O(e),this.#c=new O(e),this.#o=0,this.#h=0,this.#_=R.create(e),this.#n=0,this.#S=0,typeof g=="function"&&(this.#p=g),typeof b=="function"?(this.#w=b,this.#r=[]):(this.#w=void 0,this.#r=void 0),this.#m=!!this.#p,this.#a=!!this.#w,this.noDisposeOnSet=!!f,this.noUpdateTTL=!!u,this.noDeleteOnFetchRejection=!!a,this.allowStaleOnFetchRejection=!!y,this.allowStaleOnFetchAbort=!!p,this.ignoreFetchAbort=!!_,this.maxEntrySize!==0){if(this.#f!==0&&!A(this.#f))throw new TypeError("maxSize must be a positive integer if specified");if(!A(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#I()}if(this.allowStale=!!r,this.noDeleteOnStaleGet=!!w,this.updateAgeOnGet=!!h,this.updateAgeOnHas=!!l,this.ttlResolution=A(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!A(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#L()}if(this.#g===0&&this.ttl===0&&this.#f===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#g&&!this.#f){let m="LRU_CACHE_UNBOUNDED";V(m)&&(N.add(m),P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",m,C))}}getRemainingTTL(t){return this.#s.has(t)?1/0:0}#L(){let t=new E(this.#g),e=new E(this.#g);this.#u=t,this.#y=e,this.#U=(n,h,l=T.now())=>{if(e[n]=h!==0?l:0,t[n]=h,h!==0&&this.ttlAutopurge){let r=setTimeout(()=>{this.#d(n)&&this.delete(this.#i[n])},h+1);r.unref&&r.unref()}},this.#z=n=>{e[n]=t[n]!==0?T.now():0},this.#O=(n,h)=>{if(t[h]){let l=t[h],r=e[h];if(!l||!r)return;n.ttl=l,n.start=r,n.now=i||s();let g=n.now-r;n.remainingTTL=l-g}};let i=0,s=()=>{let n=T.now();if(this.ttlResolution>0){i=n;let h=setTimeout(()=>i=0,this.ttlResolution);h.unref&&h.unref()}return n};this.getRemainingTTL=n=>{let h=this.#s.get(n);if(h===void 0)return 0;let l=t[h],r=e[h];if(!l||!r)return 1/0;let g=(i||s())-r;return l-g},this.#d=n=>{let h=e[n],l=t[n];return!!l&&!!h&&(i||s())-h>l}}#z=()=>{};#O=()=>{};#U=()=>{};#d=()=>!1;#I(){let t=new E(this.#g);this.#S=0,this.#b=t,this.#E=e=>{this.#S-=t[e],t[e]=0},this.#x=(e,i,s,n)=>{if(this.#e(i))return 0;if(!A(s))if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!A(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");return s},this.#R=(e,i,s)=>{if(t[e]=i,this.#f){let n=this.#f-t[e];for(;this.#S>n;)this.#W(!0)}this.#S+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#S)}}#E=t=>{};#R=(t,e,i)=>{};#x=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#h;!(!this.#G(e)||((t||!this.#d(e))&&(yield e),e===this.#o));)e=this.#c[e]}*#F({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#o;!(!this.#G(e)||((t||!this.#d(e))&&(yield e),e===this.#h));)e=this.#l[e]}#G(t){return t!==void 0&&this.#s.get(this.#i[t])===t}*entries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#F())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#F()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#F())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(t,e={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.get(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#F()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#F({allowStale:!0}))this.#d(e)&&(this.delete(this.#i[e]),t=!0);return t}info(t){let e=this.#s.get(t);if(e===void 0)return;let i=this.#t[e],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#u&&this.#y){let h=this.#u[e],l=this.#y[e];if(h&&l){let r=h-(T.now()-l);n.ttl=r,n.start=Date.now()}}return this.#b&&(n.size=this.#b[e]),n}dump(){let t=[];for(let e of this.#A({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let h={value:n};if(this.#u&&this.#y){h.ttl=this.#u[e];let l=T.now()-this.#y[e];h.start=Math.floor(Date.now()-l)}this.#b&&(h.size=this.#b[e]),t.unshift([i,h])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=T.now()-s}this.set(e,i.value,i)}}set(t,e,i={}){if(e===void 0)return this.delete(t),this;let{ttl:s=this.ttl,start:n,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:l=this.sizeCalculation,status:r}=i,{noUpdateTTL:g=this.noUpdateTTL}=i,b=this.#x(t,e,i.size||0,l);if(this.maxEntrySize&&b>this.maxEntrySize)return r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this.delete(t),this;let f=this.#n===0?void 0:this.#s.get(t);if(f===void 0)f=this.#n===0?this.#h:this.#_.length!==0?this.#_.pop():this.#n===this.#g?this.#W(!1):this.#n,this.#i[f]=t,this.#t[f]=e,this.#s.set(t,f),this.#l[this.#h]=f,this.#c[f]=this.#h,this.#h=f,this.#n++,this.#R(f,b,r),r&&(r.set="add"),g=!1;else{this.#v(f);let u=this.#t[f];if(e!==u){if(this.#T&&this.#e(u)){u.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:c}=u;c!==void 0&&!h&&(this.#m&&this.#p?.(c,t,"set"),this.#a&&this.#r?.push([c,t,"set"]))}else h||(this.#m&&this.#p?.(u,t,"set"),this.#a&&this.#r?.push([u,t,"set"]));if(this.#E(f),this.#R(f,b,r),this.#t[f]=e,r){r.set="replace";let c=u&&this.#e(u)?u.__staleWhileFetching:u;c!==void 0&&(r.oldValue=c)}}else r&&(r.set="update")}if(s!==0&&!this.#u&&this.#L(),this.#u&&(g||this.#U(f,s,n),r&&this.#O(r,f)),!h&&this.#a&&this.#r){let u=this.#r,c;for(;c=u?.shift();)this.#w?.(...c)}return this}pop(){try{for(;this.#n;){let t=this.#t[this.#o];if(this.#W(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#a&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#w?.(...e)}}}#W(t){let e=this.#o,i=this.#i[e],s=this.#t[e];return this.#T&&this.#e(s)?s.__abortController.abort(new Error("evicted")):(this.#m||this.#a)&&(this.#m&&this.#p?.(s,i,"evict"),this.#a&&this.#r?.push([s,i,"evict"])),this.#E(e),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#_.push(e)),this.#n===1?(this.#o=this.#h=0,this.#_.length=0):this.#o=this.#l[e],this.#s.delete(i),this.#n--,e}has(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#s.get(t);if(n!==void 0){let h=this.#t[n];if(this.#e(h)&&h.__staleWhileFetching===void 0)return!1;if(this.#d(n))s&&(s.has="stale",this.#O(s,n));else return i&&this.#z(n),s&&(s.has="hit",this.#O(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{allowStale:i=this.allowStale}=e,s=this.#s.get(t);if(s===void 0||!i&&this.#d(s))return;let n=this.#t[s];return this.#e(n)?n.__staleWhileFetching:n}#D(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let h=new W,{signal:l}=i;l?.addEventListener("abort",()=>h.abort(l.reason),{signal:h.signal});let r={signal:h.signal,options:i,context:s},g=(d,S=!1)=>{let{aborted:a}=h.signal,w=i.ignoreFetchAbort&&d!==void 0;if(i.status&&(a&&!S?(i.status.fetchAborted=!0,i.status.fetchError=h.signal.reason,w&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),a&&!w&&!S)return f(h.signal.reason);let y=c;return this.#t[e]===c&&(d===void 0?y.__staleWhileFetching?this.#t[e]=y.__staleWhileFetching:this.delete(t):(i.status&&(i.status.fetchUpdated=!0),this.set(t,d,r.options))),d},b=d=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=d),f(d)),f=d=>{let{aborted:S}=h.signal,a=S&&i.allowStaleOnFetchAbort,w=a||i.allowStaleOnFetchRejection,y=w||i.noDeleteOnFetchRejection,p=c;if(this.#t[e]===c&&(!y||p.__staleWhileFetching===void 0?this.delete(t):a||(this.#t[e]=p.__staleWhileFetching)),w)return i.status&&p.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),p.__staleWhileFetching;if(p.__returned===p)throw d},u=(d,S)=>{let a=this.#C?.(t,n,r);a&&a instanceof Promise&&a.then(w=>d(w===void 0?void 0:w),S),h.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(d(void 0),i.allowStaleOnFetchAbort&&(d=w=>g(w,!0)))})};i.status&&(i.status.fetchDispatched=!0);let c=new Promise(u).then(g,b),F=Object.assign(c,{__abortController:h,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.set(t,F,{...r.options,status:void 0}),e=this.#s.get(t)):this.#t[e]=F,F}#e(t){if(!this.#T)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof W}async fetch(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:h=this.ttl,noDisposeOnSet:l=this.noDisposeOnSet,size:r=0,sizeCalculation:g=this.sizeCalculation,noUpdateTTL:b=this.noUpdateTTL,noDeleteOnFetchRejection:f=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:u=this.allowStaleOnFetchRejection,ignoreFetchAbort:c=this.ignoreFetchAbort,allowStaleOnFetchAbort:F=this.allowStaleOnFetchAbort,context:d,forceRefresh:S=!1,status:a,signal:w}=e;if(!this.#T)return a&&(a.fetch="get"),this.get(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:a});let y={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:h,noDisposeOnSet:l,size:r,sizeCalculation:g,noUpdateTTL:b,noDeleteOnFetchRejection:f,allowStaleOnFetchRejection:u,allowStaleOnFetchAbort:F,ignoreFetchAbort:c,status:a,signal:w},p=this.#s.get(t);if(p===void 0){a&&(a.fetch="miss");let _=this.#D(t,p,y,d);return _.__returned=_}else{let _=this.#t[p];if(this.#e(_)){let x=i&&_.__staleWhileFetching!==void 0;return a&&(a.fetch="inflight",x&&(a.returnedStale=!0)),x?_.__staleWhileFetching:_.__returned=_}let O=this.#d(p);if(!S&&!O)return a&&(a.fetch="hit"),this.#v(p),s&&this.#z(p),a&&this.#O(a,p),_;let m=this.#D(t,p,y,d),U=m.__staleWhileFetching!==void 0&&i;return a&&(a.fetch=O?"stale":"refresh",U&&O&&(a.returnedStale=!0)),U?m.__staleWhileFetching:m.__returned=m}}get(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:h}=e,l=this.#s.get(t);if(l!==void 0){let r=this.#t[l],g=this.#e(r);return h&&this.#O(h,l),this.#d(l)?(h&&(h.get="stale"),g?(h&&i&&r.__staleWhileFetching!==void 0&&(h.returnedStale=!0),i?r.__staleWhileFetching:void 0):(n||this.delete(t),h&&i&&(h.returnedStale=!0),i?r:void 0)):(h&&(h.get="hit"),g?r.__staleWhileFetching:(this.#v(l),s&&this.#z(l),r))}else h&&(h.get="miss")}#j(t,e){this.#c[e]=t,this.#l[t]=e}#v(t){t!==this.#h&&(t===this.#o?this.#o=this.#l[t]:this.#j(this.#c[t],this.#l[t]),this.#j(this.#h,t),this.#h=t)}delete(t){let e=!1;if(this.#n!==0){let i=this.#s.get(t);if(i!==void 0)if(e=!0,this.#n===1)this.clear();else{this.#E(i);let s=this.#t[i];if(this.#e(s)?s.__abortController.abort(new Error("deleted")):(this.#m||this.#a)&&(this.#m&&this.#p?.(s,t,"delete"),this.#a&&this.#r?.push([s,t,"delete"])),this.#s.delete(t),this.#i[i]=void 0,this.#t[i]=void 0,i===this.#h)this.#h=this.#c[i];else if(i===this.#o)this.#o=this.#l[i];else{let n=this.#c[i];this.#l[n]=this.#l[i];let h=this.#l[i];this.#c[h]=this.#c[i]}this.#n--,this.#_.push(i)}}if(this.#a&&this.#r?.length){let i=this.#r,s;for(;s=i?.shift();)this.#w?.(...s)}return e}clear(){for(let t of this.#F({allowStale:!0})){let e=this.#t[t];if(this.#e(e))e.__abortController.abort(new Error("deleted"));else{let i=this.#i[t];this.#m&&this.#p?.(e,i,"delete"),this.#a&&this.#r?.push([e,i,"delete"])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#u&&this.#y&&(this.#u.fill(0),this.#y.fill(0)),this.#b&&this.#b.fill(0),this.#o=0,this.#h=0,this.#_.length=0,this.#S=0,this.#n=0,this.#a&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#w?.(...e)}}};exports.LRUCache=C; +//# sourceMappingURL=index.min.js.map diff --git a/deps/npm/node_modules/lru-cache/dist/esm/index.min.js b/deps/npm/node_modules/lru-cache/dist/esm/index.min.js new file mode 100644 index 00000000000000..4285815f9abb17 --- /dev/null +++ b/deps/npm/node_modules/lru-cache/dist/esm/index.min.js @@ -0,0 +1,2 @@ +var G=(o,t,e)=>{if(!t.has(o))throw TypeError("Cannot "+e)};var I=(o,t,e)=>(G(o,t,"read from private field"),e?e.call(o):t.get(o)),j=(o,t,e)=>{if(t.has(o))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(o):t.set(o,e)},D=(o,t,e,i)=>(G(o,t,"write to private field"),i?i.call(o,e):t.set(o,e),e);var O=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date,M=new Set,L=typeof process=="object"&&process?process:{},P=(o,t,e,i)=>{typeof L.emitWarning=="function"?L.emitWarning(o,t,e,i):console.error(`[${e}] ${t}: ${o}`)},W=globalThis.AbortController,N=globalThis.AbortSignal;if(typeof W>"u"){N=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(i,s){this._onabort.push(s)}},W=class{constructor(){t()}signal=new N;abort(i){if(!this.signal.aborted){this.signal.reason=i,this.signal.aborted=!0;for(let s of this.signal._onabort)s(i);this.signal.onabort?.(i)}}};let o=L.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",t=()=>{o&&(o=!1,P("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",t))}}var V=o=>!M.has(o),Y=Symbol("type"),A=o=>o&&o===Math.floor(o)&&o>0&&isFinite(o),H=o=>A(o)?o<=Math.pow(2,8)?Uint8Array:o<=Math.pow(2,16)?Uint16Array:o<=Math.pow(2,32)?Uint32Array:o<=Number.MAX_SAFE_INTEGER?E:null:null,E=class extends Array{constructor(t){super(t),this.fill(0)}},v,z=class{heap;length;static create(t){let e=H(t);if(!e)return[];D(z,v,!0);let i=new z(t,e);return D(z,v,!1),i}constructor(t,e){if(!I(z,v))throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},C=z;v=new WeakMap,j(C,v,!1);var R=class{#g;#f;#p;#w;#C;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#n;#S;#s;#i;#t;#l;#c;#o;#h;#_;#r;#b;#y;#u;#m;#O;#a;static unsafeExposeInternals(t){return{starts:t.#y,ttls:t.#u,sizes:t.#b,keyMap:t.#s,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#c,get head(){return t.#o},get tail(){return t.#h},free:t.#_,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#D(e,i,s,n),moveToTail:e=>t.#v(e),indexes:e=>t.#A(e),rindexes:e=>t.#F(e),isStale:e=>t.#d(e)}}get max(){return this.#g}get maxSize(){return this.#f}get calculatedSize(){return this.#S}get size(){return this.#n}get fetchMethod(){return this.#C}get dispose(){return this.#p}get disposeAfter(){return this.#w}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:h,updateAgeOnHas:l,allowStale:r,dispose:g,disposeAfter:b,noDisposeOnSet:f,noUpdateTTL:u,maxSize:c=0,maxEntrySize:F=0,sizeCalculation:d,fetchMethod:S,noDeleteOnFetchRejection:a,noDeleteOnStaleGet:w,allowStaleOnFetchRejection:y,allowStaleOnFetchAbort:p,ignoreFetchAbort:_}=t;if(e!==0&&!A(e))throw new TypeError("max option must be a nonnegative integer");let T=e?H(e):Array;if(!T)throw new Error("invalid max value: "+e);if(this.#g=e,this.#f=c,this.maxEntrySize=F||this.#f,this.sizeCalculation=d,this.sizeCalculation){if(!this.#f&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(S!==void 0&&typeof S!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#C=S,this.#O=!!S,this.#s=new Map,this.#i=new Array(e).fill(void 0),this.#t=new Array(e).fill(void 0),this.#l=new T(e),this.#c=new T(e),this.#o=0,this.#h=0,this.#_=C.create(e),this.#n=0,this.#S=0,typeof g=="function"&&(this.#p=g),typeof b=="function"?(this.#w=b,this.#r=[]):(this.#w=void 0,this.#r=void 0),this.#m=!!this.#p,this.#a=!!this.#w,this.noDisposeOnSet=!!f,this.noUpdateTTL=!!u,this.noDeleteOnFetchRejection=!!a,this.allowStaleOnFetchRejection=!!y,this.allowStaleOnFetchAbort=!!p,this.ignoreFetchAbort=!!_,this.maxEntrySize!==0){if(this.#f!==0&&!A(this.#f))throw new TypeError("maxSize must be a positive integer if specified");if(!A(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#j()}if(this.allowStale=!!r,this.noDeleteOnStaleGet=!!w,this.updateAgeOnGet=!!h,this.updateAgeOnHas=!!l,this.ttlResolution=A(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!A(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#L()}if(this.#g===0&&this.ttl===0&&this.#f===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#g&&!this.#f){let m="LRU_CACHE_UNBOUNDED";V(m)&&(M.add(m),P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",m,R))}}getRemainingTTL(t){return this.#s.has(t)?1/0:0}#L(){let t=new E(this.#g),e=new E(this.#g);this.#u=t,this.#y=e,this.#x=(n,h,l=O.now())=>{if(e[n]=h!==0?l:0,t[n]=h,h!==0&&this.ttlAutopurge){let r=setTimeout(()=>{this.#d(n)&&this.delete(this.#i[n])},h+1);r.unref&&r.unref()}},this.#z=n=>{e[n]=t[n]!==0?O.now():0},this.#T=(n,h)=>{if(t[h]){let l=t[h],r=e[h];if(!l||!r)return;n.ttl=l,n.start=r,n.now=i||s();let g=n.now-r;n.remainingTTL=l-g}};let i=0,s=()=>{let n=O.now();if(this.ttlResolution>0){i=n;let h=setTimeout(()=>i=0,this.ttlResolution);h.unref&&h.unref()}return n};this.getRemainingTTL=n=>{let h=this.#s.get(n);if(h===void 0)return 0;let l=t[h],r=e[h];if(!l||!r)return 1/0;let g=(i||s())-r;return l-g},this.#d=n=>{let h=e[n],l=t[n];return!!l&&!!h&&(i||s())-h>l}}#z=()=>{};#T=()=>{};#x=()=>{};#d=()=>!1;#j(){let t=new E(this.#g);this.#S=0,this.#b=t,this.#E=e=>{this.#S-=t[e],t[e]=0},this.#U=(e,i,s,n)=>{if(this.#e(i))return 0;if(!A(s))if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!A(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");return s},this.#W=(e,i,s)=>{if(t[e]=i,this.#f){let n=this.#f-t[e];for(;this.#S>n;)this.#R(!0)}this.#S+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#S)}}#E=t=>{};#W=(t,e,i)=>{};#U=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#h;!(!this.#G(e)||((t||!this.#d(e))&&(yield e),e===this.#o));)e=this.#c[e]}*#F({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#o;!(!this.#G(e)||((t||!this.#d(e))&&(yield e),e===this.#h));)e=this.#l[e]}#G(t){return t!==void 0&&this.#s.get(this.#i[t])===t}*entries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#F())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#F()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#F())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(t,e={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.get(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#F()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#F({allowStale:!0}))this.#d(e)&&(this.delete(this.#i[e]),t=!0);return t}info(t){let e=this.#s.get(t);if(e===void 0)return;let i=this.#t[e],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#u&&this.#y){let h=this.#u[e],l=this.#y[e];if(h&&l){let r=h-(O.now()-l);n.ttl=r,n.start=Date.now()}}return this.#b&&(n.size=this.#b[e]),n}dump(){let t=[];for(let e of this.#A({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let h={value:n};if(this.#u&&this.#y){h.ttl=this.#u[e];let l=O.now()-this.#y[e];h.start=Math.floor(Date.now()-l)}this.#b&&(h.size=this.#b[e]),t.unshift([i,h])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=O.now()-s}this.set(e,i.value,i)}}set(t,e,i={}){if(e===void 0)return this.delete(t),this;let{ttl:s=this.ttl,start:n,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:l=this.sizeCalculation,status:r}=i,{noUpdateTTL:g=this.noUpdateTTL}=i,b=this.#U(t,e,i.size||0,l);if(this.maxEntrySize&&b>this.maxEntrySize)return r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this.delete(t),this;let f=this.#n===0?void 0:this.#s.get(t);if(f===void 0)f=this.#n===0?this.#h:this.#_.length!==0?this.#_.pop():this.#n===this.#g?this.#R(!1):this.#n,this.#i[f]=t,this.#t[f]=e,this.#s.set(t,f),this.#l[this.#h]=f,this.#c[f]=this.#h,this.#h=f,this.#n++,this.#W(f,b,r),r&&(r.set="add"),g=!1;else{this.#v(f);let u=this.#t[f];if(e!==u){if(this.#O&&this.#e(u)){u.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:c}=u;c!==void 0&&!h&&(this.#m&&this.#p?.(c,t,"set"),this.#a&&this.#r?.push([c,t,"set"]))}else h||(this.#m&&this.#p?.(u,t,"set"),this.#a&&this.#r?.push([u,t,"set"]));if(this.#E(f),this.#W(f,b,r),this.#t[f]=e,r){r.set="replace";let c=u&&this.#e(u)?u.__staleWhileFetching:u;c!==void 0&&(r.oldValue=c)}}else r&&(r.set="update")}if(s!==0&&!this.#u&&this.#L(),this.#u&&(g||this.#x(f,s,n),r&&this.#T(r,f)),!h&&this.#a&&this.#r){let u=this.#r,c;for(;c=u?.shift();)this.#w?.(...c)}return this}pop(){try{for(;this.#n;){let t=this.#t[this.#o];if(this.#R(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#a&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#w?.(...e)}}}#R(t){let e=this.#o,i=this.#i[e],s=this.#t[e];return this.#O&&this.#e(s)?s.__abortController.abort(new Error("evicted")):(this.#m||this.#a)&&(this.#m&&this.#p?.(s,i,"evict"),this.#a&&this.#r?.push([s,i,"evict"])),this.#E(e),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#_.push(e)),this.#n===1?(this.#o=this.#h=0,this.#_.length=0):this.#o=this.#l[e],this.#s.delete(i),this.#n--,e}has(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#s.get(t);if(n!==void 0){let h=this.#t[n];if(this.#e(h)&&h.__staleWhileFetching===void 0)return!1;if(this.#d(n))s&&(s.has="stale",this.#T(s,n));else return i&&this.#z(n),s&&(s.has="hit",this.#T(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{allowStale:i=this.allowStale}=e,s=this.#s.get(t);if(s===void 0||!i&&this.#d(s))return;let n=this.#t[s];return this.#e(n)?n.__staleWhileFetching:n}#D(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let h=new W,{signal:l}=i;l?.addEventListener("abort",()=>h.abort(l.reason),{signal:h.signal});let r={signal:h.signal,options:i,context:s},g=(d,S=!1)=>{let{aborted:a}=h.signal,w=i.ignoreFetchAbort&&d!==void 0;if(i.status&&(a&&!S?(i.status.fetchAborted=!0,i.status.fetchError=h.signal.reason,w&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),a&&!w&&!S)return f(h.signal.reason);let y=c;return this.#t[e]===c&&(d===void 0?y.__staleWhileFetching?this.#t[e]=y.__staleWhileFetching:this.delete(t):(i.status&&(i.status.fetchUpdated=!0),this.set(t,d,r.options))),d},b=d=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=d),f(d)),f=d=>{let{aborted:S}=h.signal,a=S&&i.allowStaleOnFetchAbort,w=a||i.allowStaleOnFetchRejection,y=w||i.noDeleteOnFetchRejection,p=c;if(this.#t[e]===c&&(!y||p.__staleWhileFetching===void 0?this.delete(t):a||(this.#t[e]=p.__staleWhileFetching)),w)return i.status&&p.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),p.__staleWhileFetching;if(p.__returned===p)throw d},u=(d,S)=>{let a=this.#C?.(t,n,r);a&&a instanceof Promise&&a.then(w=>d(w===void 0?void 0:w),S),h.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(d(void 0),i.allowStaleOnFetchAbort&&(d=w=>g(w,!0)))})};i.status&&(i.status.fetchDispatched=!0);let c=new Promise(u).then(g,b),F=Object.assign(c,{__abortController:h,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.set(t,F,{...r.options,status:void 0}),e=this.#s.get(t)):this.#t[e]=F,F}#e(t){if(!this.#O)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof W}async fetch(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:h=this.ttl,noDisposeOnSet:l=this.noDisposeOnSet,size:r=0,sizeCalculation:g=this.sizeCalculation,noUpdateTTL:b=this.noUpdateTTL,noDeleteOnFetchRejection:f=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:u=this.allowStaleOnFetchRejection,ignoreFetchAbort:c=this.ignoreFetchAbort,allowStaleOnFetchAbort:F=this.allowStaleOnFetchAbort,context:d,forceRefresh:S=!1,status:a,signal:w}=e;if(!this.#O)return a&&(a.fetch="get"),this.get(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:a});let y={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:h,noDisposeOnSet:l,size:r,sizeCalculation:g,noUpdateTTL:b,noDeleteOnFetchRejection:f,allowStaleOnFetchRejection:u,allowStaleOnFetchAbort:F,ignoreFetchAbort:c,status:a,signal:w},p=this.#s.get(t);if(p===void 0){a&&(a.fetch="miss");let _=this.#D(t,p,y,d);return _.__returned=_}else{let _=this.#t[p];if(this.#e(_)){let U=i&&_.__staleWhileFetching!==void 0;return a&&(a.fetch="inflight",U&&(a.returnedStale=!0)),U?_.__staleWhileFetching:_.__returned=_}let T=this.#d(p);if(!S&&!T)return a&&(a.fetch="hit"),this.#v(p),s&&this.#z(p),a&&this.#T(a,p),_;let m=this.#D(t,p,y,d),x=m.__staleWhileFetching!==void 0&&i;return a&&(a.fetch=T?"stale":"refresh",x&&T&&(a.returnedStale=!0)),x?m.__staleWhileFetching:m.__returned=m}}get(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:h}=e,l=this.#s.get(t);if(l!==void 0){let r=this.#t[l],g=this.#e(r);return h&&this.#T(h,l),this.#d(l)?(h&&(h.get="stale"),g?(h&&i&&r.__staleWhileFetching!==void 0&&(h.returnedStale=!0),i?r.__staleWhileFetching:void 0):(n||this.delete(t),h&&i&&(h.returnedStale=!0),i?r:void 0)):(h&&(h.get="hit"),g?r.__staleWhileFetching:(this.#v(l),s&&this.#z(l),r))}else h&&(h.get="miss")}#I(t,e){this.#c[e]=t,this.#l[t]=e}#v(t){t!==this.#h&&(t===this.#o?this.#o=this.#l[t]:this.#I(this.#c[t],this.#l[t]),this.#I(this.#h,t),this.#h=t)}delete(t){let e=!1;if(this.#n!==0){let i=this.#s.get(t);if(i!==void 0)if(e=!0,this.#n===1)this.clear();else{this.#E(i);let s=this.#t[i];if(this.#e(s)?s.__abortController.abort(new Error("deleted")):(this.#m||this.#a)&&(this.#m&&this.#p?.(s,t,"delete"),this.#a&&this.#r?.push([s,t,"delete"])),this.#s.delete(t),this.#i[i]=void 0,this.#t[i]=void 0,i===this.#h)this.#h=this.#c[i];else if(i===this.#o)this.#o=this.#l[i];else{let n=this.#c[i];this.#l[n]=this.#l[i];let h=this.#l[i];this.#c[h]=this.#c[i]}this.#n--,this.#_.push(i)}}if(this.#a&&this.#r?.length){let i=this.#r,s;for(;s=i?.shift();)this.#w?.(...s)}return e}clear(){for(let t of this.#F({allowStale:!0})){let e=this.#t[t];if(this.#e(e))e.__abortController.abort(new Error("deleted"));else{let i=this.#i[t];this.#m&&this.#p?.(e,i,"delete"),this.#a&&this.#r?.push([e,i,"delete"])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#u&&this.#y&&(this.#u.fill(0),this.#y.fill(0)),this.#b&&this.#b.fill(0),this.#o=0,this.#h=0,this.#_.length=0,this.#S=0,this.#n=0,this.#a&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#w?.(...e)}}};export{R as LRUCache}; +//# sourceMappingURL=index.min.js.map diff --git a/deps/npm/node_modules/lru-cache/package.json b/deps/npm/node_modules/lru-cache/package.json index 348e2118a7c25c..ef118623196112 100644 --- a/deps/npm/node_modules/lru-cache/package.json +++ b/deps/npm/node_modules/lru-cache/package.json @@ -1,7 +1,7 @@ { "name": "lru-cache", "description": "A cache object that deletes the least-recently-used items.", - "version": "10.2.0", + "version": "10.2.2", "author": "Isaac Z. Schlueter ", "keywords": [ "mru", @@ -11,8 +11,7 @@ "sideEffects": false, "scripts": { "build": "npm run prepare", - "prepare": "tshy", - "postprepare": "bash fixup.sh", + "prepare": "tshy && bash fixup.sh", "pretest": "npm run prepare", "presnap": "npm run prepare", "test": "tap", @@ -35,8 +34,8 @@ ".": "./src/index.ts", "./min": { "import": { - "types": "./dist/mjs/index.d.ts", - "default": "./dist/mjs/index.min.js" + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.min.js" }, "require": { "types": "./dist/commonjs/index.d.ts", @@ -105,8 +104,8 @@ }, "./min": { "import": { - "types": "./dist/mjs/index.d.ts", - "default": "./dist/mjs/index.min.js" + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.min.js" }, "require": { "types": "./dist/commonjs/index.d.ts", diff --git a/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js b/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js index 45141095074ecb..bfcfacbcc95e18 100644 --- a/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js +++ b/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js @@ -274,6 +274,8 @@ class CacheEntry { const cacheWritePromise = new Promise((resolve, reject) => { cacheWriteResolve = resolve cacheWriteReject = reject + }).catch((err) => { + body.emit('error', err) }) body = new CachingMinipassPipeline({ events: ['integrity', 'size'] }, new MinipassFlush({ diff --git a/deps/npm/node_modules/make-fetch-happen/lib/remote.js b/deps/npm/node_modules/make-fetch-happen/lib/remote.js index 2aef9f8f969b00..8554564074de6e 100644 --- a/deps/npm/node_modules/make-fetch-happen/lib/remote.js +++ b/deps/npm/node_modules/make-fetch-happen/lib/remote.js @@ -2,6 +2,7 @@ const { Minipass } = require('minipass') const fetch = require('minipass-fetch') const promiseRetry = require('promise-retry') const ssri = require('ssri') +const { log } = require('proc-log') const CachingMinipassPipeline = require('./pipeline.js') const { getAgent } = require('@npmcli/agent') @@ -89,6 +90,8 @@ const remoteFetch = (request, options) => { options.onRetry(res) } + /* eslint-disable-next-line max-len */ + log.http('fetch', `${req.method} ${req.url} attempt ${attemptNum} failed with ${res.status}`) return retryHandler(res) } @@ -112,6 +115,7 @@ const remoteFetch = (request, options) => { options.onRetry(err) } + log.http('fetch', `${req.method} ${req.url} attempt ${attemptNum} failed with ${err.code}`) return retryHandler(err) } }, options.retry).catch((err) => { diff --git a/deps/npm/node_modules/make-fetch-happen/package.json b/deps/npm/node_modules/make-fetch-happen/package.json index a874ace6d1d472..7adb4d1e7f9719 100644 --- a/deps/npm/node_modules/make-fetch-happen/package.json +++ b/deps/npm/node_modules/make-fetch-happen/package.json @@ -1,6 +1,6 @@ { "name": "make-fetch-happen", - "version": "13.0.0", + "version": "13.0.1", "description": "Opinionated, caching, retrying fetch client", "main": "lib/index.js", "files": [ @@ -11,7 +11,7 @@ "test": "tap", "posttest": "npm run lint", "eslint": "eslint", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "lintfix": "npm run lint -- --fix", "postlint": "template-oss-check", "snap": "tap", @@ -42,12 +42,13 @@ "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", + "proc-log": "^4.2.0", "promise-retry": "^2.0.1", "ssri": "^10.0.0" }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.18.0", + "@npmcli/template-oss": "4.21.4", "nock": "^13.2.4", "safe-buffer": "^5.2.1", "standard-version": "^9.3.2", @@ -68,13 +69,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "ciVersions": [ - "16.14.0", - "16.x", - "18.0.0", - "18.x" - ], - "version": "4.18.0", + "version": "4.21.4", "publish": "true" } } diff --git a/deps/npm/node_modules/minimatch/dist/cjs/assert-valid-pattern.js b/deps/npm/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js similarity index 100% rename from deps/npm/node_modules/minimatch/dist/cjs/assert-valid-pattern.js rename to deps/npm/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js diff --git a/deps/npm/node_modules/minimatch/dist/cjs/ast.js b/deps/npm/node_modules/minimatch/dist/commonjs/ast.js similarity index 99% rename from deps/npm/node_modules/minimatch/dist/cjs/ast.js rename to deps/npm/node_modules/minimatch/dist/commonjs/ast.js index 0b0cc8f3c50b3d..9e1f9e765c597e 100644 --- a/deps/npm/node_modules/minimatch/dist/cjs/ast.js +++ b/deps/npm/node_modules/minimatch/dist/commonjs/ast.js @@ -338,6 +338,9 @@ class AST { _glob: glob, }); } + get options() { + return this.#options; + } // returns the string match, the regexp source, whether there's magic // in the regexp (so a regular expression is required) and whether or // not the uflag is needed for the regular expression (for posix classes) diff --git a/deps/npm/node_modules/minimatch/dist/cjs/brace-expressions.js b/deps/npm/node_modules/minimatch/dist/commonjs/brace-expressions.js similarity index 100% rename from deps/npm/node_modules/minimatch/dist/cjs/brace-expressions.js rename to deps/npm/node_modules/minimatch/dist/commonjs/brace-expressions.js diff --git a/deps/npm/node_modules/minimatch/dist/cjs/escape.js b/deps/npm/node_modules/minimatch/dist/commonjs/escape.js similarity index 100% rename from deps/npm/node_modules/minimatch/dist/cjs/escape.js rename to deps/npm/node_modules/minimatch/dist/commonjs/escape.js diff --git a/deps/npm/node_modules/minimatch/dist/cjs/index.js b/deps/npm/node_modules/minimatch/dist/commonjs/index.js similarity index 99% rename from deps/npm/node_modules/minimatch/dist/cjs/index.js rename to deps/npm/node_modules/minimatch/dist/commonjs/index.js index d70e681fef5d7d..d05f8b47f1efb4 100644 --- a/deps/npm/node_modules/minimatch/dist/cjs/index.js +++ b/deps/npm/node_modules/minimatch/dist/commonjs/index.js @@ -344,6 +344,7 @@ class Minimatch { globParts = this.levelOneOptimize(globParts); } else { + // just collapse multiple ** portions into one globParts = this.adjascentGlobstarOptimize(globParts); } return globParts; @@ -833,7 +834,11 @@ class Minimatch { fastTest = dotStarTest; } const re = ast_js_1.AST.fromGlob(pattern, this.options).toMMPattern(); - return fastTest ? Object.assign(re, { test: fastTest }) : re; + if (fastTest && typeof re === 'object') { + // Avoids overriding in frozen environments + Reflect.defineProperty(re, 'test', { value: fastTest }); + } + return re; } makeRe() { if (this.regexp || this.regexp === false) diff --git a/deps/npm/node_modules/minimatch/dist/cjs/package.json b/deps/npm/node_modules/minimatch/dist/commonjs/package.json similarity index 100% rename from deps/npm/node_modules/minimatch/dist/cjs/package.json rename to deps/npm/node_modules/minimatch/dist/commonjs/package.json diff --git a/deps/npm/node_modules/minimatch/dist/cjs/unescape.js b/deps/npm/node_modules/minimatch/dist/commonjs/unescape.js similarity index 100% rename from deps/npm/node_modules/minimatch/dist/cjs/unescape.js rename to deps/npm/node_modules/minimatch/dist/commonjs/unescape.js diff --git a/deps/npm/node_modules/minimatch/dist/mjs/assert-valid-pattern.js b/deps/npm/node_modules/minimatch/dist/esm/assert-valid-pattern.js similarity index 100% rename from deps/npm/node_modules/minimatch/dist/mjs/assert-valid-pattern.js rename to deps/npm/node_modules/minimatch/dist/esm/assert-valid-pattern.js diff --git a/deps/npm/node_modules/minimatch/dist/mjs/ast.js b/deps/npm/node_modules/minimatch/dist/esm/ast.js similarity index 99% rename from deps/npm/node_modules/minimatch/dist/mjs/ast.js rename to deps/npm/node_modules/minimatch/dist/esm/ast.js index 7fb1f83e6182a0..02c6bda68427fc 100644 --- a/deps/npm/node_modules/minimatch/dist/mjs/ast.js +++ b/deps/npm/node_modules/minimatch/dist/esm/ast.js @@ -335,6 +335,9 @@ export class AST { _glob: glob, }); } + get options() { + return this.#options; + } // returns the string match, the regexp source, whether there's magic // in the regexp (so a regular expression is required) and whether or // not the uflag is needed for the regular expression (for posix classes) diff --git a/deps/npm/node_modules/minimatch/dist/mjs/brace-expressions.js b/deps/npm/node_modules/minimatch/dist/esm/brace-expressions.js similarity index 100% rename from deps/npm/node_modules/minimatch/dist/mjs/brace-expressions.js rename to deps/npm/node_modules/minimatch/dist/esm/brace-expressions.js diff --git a/deps/npm/node_modules/minimatch/dist/mjs/escape.js b/deps/npm/node_modules/minimatch/dist/esm/escape.js similarity index 100% rename from deps/npm/node_modules/minimatch/dist/mjs/escape.js rename to deps/npm/node_modules/minimatch/dist/esm/escape.js diff --git a/deps/npm/node_modules/minimatch/dist/mjs/index.js b/deps/npm/node_modules/minimatch/dist/esm/index.js similarity index 99% rename from deps/npm/node_modules/minimatch/dist/mjs/index.js rename to deps/npm/node_modules/minimatch/dist/esm/index.js index 831b6a67f63fb4..ff6319369ccd01 100644 --- a/deps/npm/node_modules/minimatch/dist/mjs/index.js +++ b/deps/npm/node_modules/minimatch/dist/esm/index.js @@ -332,6 +332,7 @@ export class Minimatch { globParts = this.levelOneOptimize(globParts); } else { + // just collapse multiple ** portions into one globParts = this.adjascentGlobstarOptimize(globParts); } return globParts; @@ -821,7 +822,11 @@ export class Minimatch { fastTest = dotStarTest; } const re = AST.fromGlob(pattern, this.options).toMMPattern(); - return fastTest ? Object.assign(re, { test: fastTest }) : re; + if (fastTest && typeof re === 'object') { + // Avoids overriding in frozen environments + Reflect.defineProperty(re, 'test', { value: fastTest }); + } + return re; } makeRe() { if (this.regexp || this.regexp === false) diff --git a/deps/npm/node_modules/minimatch/dist/mjs/package.json b/deps/npm/node_modules/minimatch/dist/esm/package.json similarity index 100% rename from deps/npm/node_modules/minimatch/dist/mjs/package.json rename to deps/npm/node_modules/minimatch/dist/esm/package.json diff --git a/deps/npm/node_modules/minimatch/dist/mjs/unescape.js b/deps/npm/node_modules/minimatch/dist/esm/unescape.js similarity index 100% rename from deps/npm/node_modules/minimatch/dist/mjs/unescape.js rename to deps/npm/node_modules/minimatch/dist/esm/unescape.js diff --git a/deps/npm/node_modules/minimatch/package.json b/deps/npm/node_modules/minimatch/package.json index 061c3b9f343306..2c82c03981152f 100644 --- a/deps/npm/node_modules/minimatch/package.json +++ b/deps/npm/node_modules/minimatch/package.json @@ -2,23 +2,23 @@ "author": "Isaac Z. Schlueter (http://blog.izs.me)", "name": "minimatch", "description": "a glob matcher in javascript", - "version": "9.0.3", + "version": "9.0.4", "repository": { "type": "git", "url": "git://github.com/isaacs/minimatch.git" }, - "main": "./dist/cjs/index.js", - "module": "./dist/mjs/index.js", - "types": "./dist/cjs/index.d.ts", + "main": "./dist/commonjs/index.js", + "types": "./dist/commonjs/index.d.ts", "exports": { + "./package.json": "./package.json", ".": { "import": { - "types": "./dist/mjs/index.d.ts", - "default": "./dist/mjs/index.js" + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" }, "require": { - "types": "./dist/cjs/index.d.ts", - "default": "./dist/cjs/index.js" + "types": "./dist/commonjs/index.d.ts", + "default": "./dist/commonjs/index.js" } } }, @@ -29,13 +29,11 @@ "preversion": "npm test", "postversion": "npm publish", "prepublishOnly": "git push origin --follow-tags", - "preprepare": "rm -rf dist", - "prepare": "tsc -p tsconfig.json && tsc -p tsconfig-esm.json", - "postprepare": "bash fixup.sh", + "prepare": "tshy", "pretest": "npm run prepare", "presnap": "npm run prepare", - "test": "c8 tap", - "snap": "c8 tap", + "test": "tap", + "snap": "tap", "format": "prettier --write . --loglevel warn", "benchmark": "node benchmark/index.js", "typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts" @@ -61,26 +59,24 @@ "@types/brace-expansion": "^1.1.0", "@types/node": "^18.15.11", "@types/tap": "^15.0.8", - "c8": "^7.12.0", "eslint-config-prettier": "^8.6.0", "mkdirp": "1", "prettier": "^2.8.2", - "tap": "^16.3.7", + "tap": "^18.7.2", "ts-node": "^10.9.1", + "tshy": "^1.12.0", "typedoc": "^0.23.21", "typescript": "^4.9.3" }, - "tap": { - "coverage": false, - "node-arg": [ - "--no-warnings", - "--loader", - "ts-node/esm" - ], - "ts": false - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, - "license": "ISC" + "license": "ISC", + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + } + }, + "type": "module" } diff --git a/deps/npm/node_modules/node-gyp/.release-please-manifest.json b/deps/npm/node_modules/node-gyp/.release-please-manifest.json new file mode 100644 index 00000000000000..1842506cfa97f8 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "10.1.0" +} diff --git a/deps/npm/node_modules/node-gyp/CHANGELOG.md b/deps/npm/node_modules/node-gyp/CHANGELOG.md index 98315add5e0d46..9db4f9f95288fd 100644 --- a/deps/npm/node_modules/node-gyp/CHANGELOG.md +++ b/deps/npm/node_modules/node-gyp/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## [10.1.0](https://github.com/nodejs/node-gyp/compare/v10.0.1...v10.1.0) (2024-03-13) + + +### Features + +* improve visual studio detection ([#2957](https://github.com/nodejs/node-gyp/issues/2957)) ([109e3d4](https://github.com/nodejs/node-gyp/commit/109e3d4245504a7b75c99f578e1203c0ef4b518e)) + + +### Core + +* add support for locally installed headers ([#2964](https://github.com/nodejs/node-gyp/issues/2964)) ([3298731](https://github.com/nodejs/node-gyp/commit/329873141f0d3e3787d3c006801431da04e4ed0c)) +* **deps:** bump actions/setup-python from 4 to 5 ([#2960](https://github.com/nodejs/node-gyp/issues/2960)) ([3f0df7e](https://github.com/nodejs/node-gyp/commit/3f0df7e9334e49e8c7f6fdbbb9e1e6c5a8cca53b)) +* **deps:** bump google-github-actions/release-please-action ([#2961](https://github.com/nodejs/node-gyp/issues/2961)) ([b1f1808](https://github.com/nodejs/node-gyp/commit/b1f1808bfff0d51e6d3eb696ab6a5b89b7b9630c)) +* print Python executable path using UTF-8 ([#2995](https://github.com/nodejs/node-gyp/issues/2995)) ([c472912](https://github.com/nodejs/node-gyp/commit/c4729129daa9bb5204246b857826fb391ac961e1)) +* update supported vs versions ([#2959](https://github.com/nodejs/node-gyp/issues/2959)) ([391cc5b](https://github.com/nodejs/node-gyp/commit/391cc5b9b25cffe0cb2edcba3583414a771b4a15)) + + +### Doc + +* npm is currently v10 ([#2970](https://github.com/nodejs/node-gyp/issues/2970)) ([7705a22](https://github.com/nodejs/node-gyp/commit/7705a22f31a62076e9f8429780a459f4ad71ea4c)) +* remove outdated Node versions from readme ([#2955](https://github.com/nodejs/node-gyp/issues/2955)) ([ae8478e](https://github.com/nodejs/node-gyp/commit/ae8478ec32d9b2fa71b591ac22cdf867ef2e9a7d)) +* remove outdated update engines.node reference in 10.0.0 changelog ([b42e796](https://github.com/nodejs/node-gyp/commit/b42e7966177f006f3d1aab1d27885d8372c8ed01)) + + +### Miscellaneous + +* only run release please on push ([cff9ac2](https://github.com/nodejs/node-gyp/commit/cff9ac2c3083769a383e00bc60b91562f03116e3)) +* upgrade release please action from v2 to v4 ([#2982](https://github.com/nodejs/node-gyp/issues/2982)) ([0035d8e](https://github.com/nodejs/node-gyp/commit/0035d8e9dc98b94f0bc8cd9023a6fa635003703e)) + ### [10.0.1](https://www.github.com/nodejs/node-gyp/compare/v10.0.0...v10.0.1) (2023-11-02) @@ -23,7 +52,6 @@ * the `Gyp` class exported is now created using ECMAScript classes and therefore might have small differences to classes that were previously created with `util.inherits`. * All internal functions have been coverted to return promises and no longer accept callbacks. This is not a breaking change for users but may be breaking to consumers of `node-gyp` if you are requiring internal functions directly. * `node-gyp` now supports node `^16.14.0 || >=18.0.0` -* update engines.node to ^14.17.0 || ^16.13.0 || >=18.0.0 ### Features @@ -706,11 +734,11 @@ Republish of v5.0.6 with unnecessary tarball removed from pack file. * [[`94c39c604e`](https://github.com/nodejs/node-gyp/commit/94c39c604e)] - **gyp**: fix ninja build failure (GYP patch) (Daniel Bevenius) [nodejs/node#12484](https://github.com/nodejs/node/pull/12484) * [[`e8ea74e0fa`](https://github.com/nodejs/node-gyp/commit/e8ea74e0fa)] - **tools**: patch gyp to avoid xcrun errors (Ujjwal Sharma) [nodejs/node#21520](https://github.com/nodejs/node/pull/21520) * [[`ea9aff44f2`](https://github.com/nodejs/node-gyp/commit/ea9aff44f2)] - **tools**: fix "the the" typos in comments (Masashi Hirano) [nodejs/node#20716](https://github.com/nodejs/node/pull/20716) -* [[`207e5aa4fd`](https://github.com/nodejs/node-gyp/commit/207e5aa4fd)] - **gyp**: implement LD/LDXX for ninja and FIPS (Sam Roberts) +* [[`207e5aa4fd`](https://github.com/nodejs/node-gyp/commit/207e5aa4fd)] - **gyp**: implement LD/LDXX for ninja and FIPS (Sam Roberts) * [[`b416c5f4b7`](https://github.com/nodejs/node-gyp/commit/b416c5f4b7)] - **gyp**: enable cctest to use objects (gyp part) (Daniel Bevenius) [nodejs/node#12450](https://github.com/nodejs/node/pull/12450) * [[`40692d016b`](https://github.com/nodejs/node-gyp/commit/40692d016b)] - **gyp**: add compile\_commands.json gyp generator (Ben Noordhuis) [nodejs/node#12450](https://github.com/nodejs/node/pull/12450) * [[`fc3c4e2b10`](https://github.com/nodejs/node-gyp/commit/fc3c4e2b10)] - **gyp**: float gyp patch for long filenames (Anna Henningsen) [nodejs/node#7963](https://github.com/nodejs/node/pull/7963) -* [[`8aedbfdef6`](https://github.com/nodejs/node-gyp/commit/8aedbfdef6)] - **gyp**: backport GYP fix to fix AIX shared suffix (Stewart Addison) +* [[`8aedbfdef6`](https://github.com/nodejs/node-gyp/commit/8aedbfdef6)] - **gyp**: backport GYP fix to fix AIX shared suffix (Stewart Addison) * [[`6cd84b84fc`](https://github.com/nodejs/node-gyp/commit/6cd84b84fc)] - **test**: formatting and minor fixes for execFileSync replacement (Rod Vagg) [#1521](https://github.com/nodejs/node-gyp/pull/1521) * [[`60e421363f`](https://github.com/nodejs/node-gyp/commit/60e421363f)] - **test**: added test/processExecSync.js for when execFileSync is not available. (Rohit Hazra) [#1492](https://github.com/nodejs/node-gyp/pull/1492) * [[`969447c5bd`](https://github.com/nodejs/node-gyp/commit/969447c5bd)] - **deps**: bump request to 2.8.7, fixes heok/hawk issues (Rohit Hazra) [#1492](https://github.com/nodejs/node-gyp/pull/1492) @@ -772,7 +800,7 @@ Republish of v5.0.6 with unnecessary tarball removed from pack file. ## v3.5.0 2017-01-10 -* [[`762d19a39e`](https://github.com/nodejs/node-gyp/commit/762d19a39e)] - \[doc\] merge History.md and CHANGELOG.md (Rod Vagg) +* [[`762d19a39e`](https://github.com/nodejs/node-gyp/commit/762d19a39e)] - \[doc\] merge History.md and CHANGELOG.md (Rod Vagg) * [[`80fc5c3d31`](https://github.com/nodejs/node-gyp/commit/80fc5c3d31)] - Fix deprecated dependency warning (Simone Primarosa) [#1069](https://github.com/nodejs/node-gyp/pull/1069) * [[`05c44944fd`](https://github.com/nodejs/node-gyp/commit/05c44944fd)] - Open the build file with universal-newlines mode (Guy Margalit) [#1053](https://github.com/nodejs/node-gyp/pull/1053) * [[`37ae7be114`](https://github.com/nodejs/node-gyp/commit/37ae7be114)] - Try python launcher when stock python is python 3. (Ben Noordhuis) [#992](https://github.com/nodejs/node-gyp/pull/992) @@ -829,7 +857,7 @@ Republish of v5.0.6 with unnecessary tarball removed from pack file. * [[`0e2dfda1f3`](https://github.com/nodejs/node-gyp/commit/0e2dfda1f3)] - Fix test/test-options when run through `npm test`. (Ben Noordhuis) [#755](https://github.com/nodejs/node-gyp/pull/755) * [[`9bfa0876b4`](https://github.com/nodejs/node-gyp/commit/9bfa0876b4)] - Add support for AIX (Michael Dawson) [#753](https://github.com/nodejs/node-gyp/pull/753) * [[`a8d441a0a2`](https://github.com/nodejs/node-gyp/commit/a8d441a0a2)] - Update README for Windows 10 support. (Jason Williams) [#766](https://github.com/nodejs/node-gyp/pull/766) -* [[`d1d6015276`](https://github.com/nodejs/node-gyp/commit/d1d6015276)] - Update broken links and switch to HTTPS. (andrew morton) +* [[`d1d6015276`](https://github.com/nodejs/node-gyp/commit/d1d6015276)] - Update broken links and switch to HTTPS. (andrew morton) ## v3.1.0 2015-11-14 diff --git a/deps/npm/node_modules/node-gyp/README.md b/deps/npm/node_modules/node-gyp/README.md index f46ee06308db1e..9e4c608e20a73f 100644 --- a/deps/npm/node_modules/node-gyp/README.md +++ b/deps/npm/node_modules/node-gyp/README.md @@ -11,9 +11,8 @@ addons. Note that `node-gyp` is _not_ used to build Node.js itself. -Multiple target versions of Node.js are supported (i.e. `0.8`, ..., `4`, `5`, `6`, -etc.), regardless of what version of Node.js is actually installed on your system -(`node-gyp` downloads the necessary development files or headers for the target version). +All current and LTS target versions of Node.js are supported. Depending on what version of Node.js is actually installed on your system +`node-gyp` downloads the necessary development files or headers for the target version. List of stable Node.js versions can be found on [Node.js website](https://nodejs.org/en/about/previous-releases). ## Features @@ -50,9 +49,7 @@ Install the current [version of Python](https://devguide.python.org/versions/) f [Microsoft Store](https://apps.microsoft.com/store/search?publisher=Python+Software+Foundation). Install tools and configuration manually: - * Install Visual C++ Build Environment: [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) - (using "Visual C++ build tools" if using a version older than VS2019, otherwise use "Desktop development with C++" workload) or [Visual Studio Community](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community) - (using the "Desktop development with C++" workload) + * Install Visual C++ Build Environment: For Visual Studio 2019 or later, use the `Desktop development with C++` workload from [Visual Studio Community](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community). For a version older than Visual Studio 2019, install [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) with the `Visual C++ build tools` option. If the above steps didn't work for you, please visit [Microsoft's Node.js Guidelines for Windows](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules) for additional tips. @@ -60,6 +57,9 @@ Install tools and configuration manually: To use the native ARM64 C++ compiler on Windows on ARM, ensure that you have Visual Studio 2022 [17.4 or later](https://devblogs.microsoft.com/visualstudio/arm64-visual-studio-is-officially-here/) installed. +It's advised to install following Powershell module: [VSSetup](https://github.com/microsoft/vssetup.powershell) using `Install-Module VSSetup -Scope CurrentUser`. +This will make Visual Studio detection logic to use more flexible and accessible method, avoiding Powershell's `ConstrainedLanguage` mode. + ### Configuring Python Dependency `node-gyp` requires that you have installed a [supported version of Python](https://devguide.python.org/versions/). diff --git a/deps/npm/node_modules/node-gyp/gyp/README.md b/deps/npm/node_modules/node-gyp/gyp/README.md deleted file mode 100644 index be1d7b9ebf6611..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/README.md +++ /dev/null @@ -1,30 +0,0 @@ -GYP can Generate Your Projects. -=================================== - -Documents are available at [gyp.gsrc.io](https://gyp.gsrc.io), or you can check out ```md-pages``` branch to read those documents offline. - -__gyp-next__ is [released](https://github.com/nodejs/gyp-next/releases) to the [__Python Packaging Index__](https://pypi.org/project/gyp-next) (PyPI) and can be installed with the command: -* `python3 -m pip install gyp-next` - -When used as a command line utility, __gyp-next__ can also be installed with [pipx](https://pypa.github.io/pipx): -* `pipx install gyp-next` -``` -Installing to a new venv 'gyp-next' - installed package gyp-next 0.13.0, installed using Python 3.10.6 - These apps are now globally available - - gyp -done! ✨ 🌟 ✨ -``` - -Or to run __gyp-next__ directly without installing it: -* `pipx run gyp-next --help` -``` -NOTE: running app 'gyp' from 'gyp-next' -usage: usage: gyp [options ...] [build_file ...] - -options: - -h, --help show this help message and exit - --build CONFIGS configuration for build after project generation - --check check format of gyp files - [ ... ] -``` diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py index d3c97c666db077..9a796702142e34 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py @@ -739,9 +739,9 @@ def ComputeOutput(self, spec): % (self.android_class, self.android_module) ) else: - path = "$(call intermediates-dir-for,{},{},,,$(GYP_VAR_PREFIX))".format( - self.android_class, - self.android_module, + path = ( + "$(call intermediates-dir-for," + f"{self.android_class},{self.android_module},,,$(GYP_VAR_PREFIX))" ) assert spec.get("product_dir") is None # TODO: not supported? diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py index 82a07ddc6577be..625b6d65ca1a6d 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py @@ -49,10 +49,9 @@ def GenerateOutput(target_list, target_dicts, data, params): # Use a banner that looks like the stock Python one and like what # code.interact uses by default, but tack on something to indicate what # locals are available, and identify gypsh. - banner = "Python {} on {}\nlocals.keys() = {}\ngypsh".format( - sys.version, - sys.platform, - repr(sorted(locals.keys())), + banner = ( + f"Python {sys.version} on {sys.platform}\nlocals.keys() = " + f"{repr(sorted(locals.keys()))}\ngypsh" ) code.interact(banner, local=locals) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py index 13b0794b4dccc3..6f0f8c1ab64c9c 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py @@ -1778,11 +1778,9 @@ def _GetCopies(spec): outer_dir = posixpath.split(src_bare)[1] fixed_dst = _FixPath(dst) full_dst = f'"{fixed_dst}\\{outer_dir}\\"' - cmd = 'mkdir {} 2>nul & cd "{}" && xcopy /e /f /y "{}" {}'.format( - full_dst, - _FixPath(base_dir), - outer_dir, - full_dst, + cmd = ( + f'mkdir {full_dst} 2>nul & cd "{_FixPath(base_dir)}" && ' + f'xcopy /e /f /y "{outer_dir}" {full_dst}' ) copies.append( ( @@ -1794,10 +1792,9 @@ def _GetCopies(spec): ) else: fix_dst = _FixPath(cpy["destination"]) - cmd = 'mkdir "{}" 2>nul & set ERRORLEVEL=0 & copy /Y "{}" "{}"'.format( - fix_dst, - _FixPath(src), - _FixPath(dst), + cmd = ( + f'mkdir "{fix_dst}" 2>nul & set ERRORLEVEL=0 & ' + f'copy /Y "{_FixPath(src)}" "{_FixPath(dst)}"' ) copies.append(([src], [dst], cmd, f"Copying {src} to {fix_dst}")) return copies @@ -1899,9 +1896,8 @@ def _GetPlatformOverridesOfProject(spec): for config_name, c in spec["configurations"].items(): config_fullname = _ConfigFullName(config_name, c) platform = c.get("msvs_target_platform", _ConfigPlatform(c)) - fixed_config_fullname = "{}|{}".format( - _ConfigBaseName(config_name, _ConfigPlatform(c)), - platform, + fixed_config_fullname = ( + f"{_ConfigBaseName(config_name, _ConfigPlatform(c))}|{platform}" ) if spec["toolset"] == "host" and generator_supports_multiple_toolsets: fixed_config_fullname = f"{config_name}|x64" diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py index 8f39519dee51fb..0b56c72750e6cd 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py @@ -1135,18 +1135,16 @@ def EvalCondition(condition, conditions_key, phase, variables, build_file): true_dict = condition[i + 1] if type(true_dict) is not dict: raise GypError( - "{} {} must be followed by a dictionary, not {}".format( - conditions_key, cond_expr, type(true_dict) - ) + f"{conditions_key} {cond_expr} must be followed by a dictionary, not " + f"{type(true_dict)}" ) if len(condition) > i + 2 and type(condition[i + 2]) is dict: false_dict = condition[i + 2] i = i + 3 if i != len(condition): raise GypError( - "{} {} has {} unexpected trailing items".format( - conditions_key, cond_expr, len(condition) - i - ) + f"{conditions_key} {cond_expr} has {len(condition) - i} " + "unexpected trailing items" ) else: false_dict = None diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py index 38fa21dd666697..847d1b8dc1d4da 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py @@ -830,17 +830,14 @@ def _GetLdManifestFlags( ("VCLinkerTool", "UACUIAccess"), config, default="false" ) - inner = """ + inner = f""" - + -""".format( - execution_level_map[execution_level], - ui_access, - ) +""" # noqa: E501 else: inner = "" diff --git a/deps/npm/node_modules/node-gyp/gyp/pyproject.toml b/deps/npm/node_modules/node-gyp/gyp/pyproject.toml index 0c25d0b3c1a065..7183e07d3c2cd0 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pyproject.toml +++ b/deps/npm/node_modules/node-gyp/gyp/pyproject.toml @@ -38,7 +38,7 @@ gyp = "gyp:script_main" "Homepage" = "https://github.com/nodejs/gyp-next" [tool.ruff] -select = [ +lint.select = [ "C4", # flake8-comprehensions "C90", # McCabe cyclomatic complexity "DTZ", # flake8-datetimez @@ -87,7 +87,7 @@ select = [ # "T20", # flake8-print # "TRY", # tryceratops ] -ignore = [ +lint.ignore = [ "E721", "PLC1901", "PLR0402", @@ -105,10 +105,10 @@ extend-exclude = ["pylib/packaging"] line-length = 88 target-version = "py37" -[tool.ruff.mccabe] +[tool.ruff.lint.mccabe] max-complexity = 101 -[tool.ruff.pylint] +[tool.ruff.lint.pylint] max-args = 11 max-branches = 108 max-returns = 10 diff --git a/deps/npm/node_modules/node-gyp/lib/configure.js b/deps/npm/node_modules/node-gyp/lib/configure.js index 8da41a849dfcf6..e4b8c94e3d2599 100644 --- a/deps/npm/node_modules/node-gyp/lib/configure.js +++ b/deps/npm/node_modules/node-gyp/lib/configure.js @@ -1,6 +1,6 @@ 'use strict' -const { promises: fs } = require('graceful-fs') +const { promises: fs, readFileSync } = require('graceful-fs') const path = require('path') const log = require('./log') const os = require('os') @@ -13,6 +13,10 @@ const { findAccessibleSync } = require('./util') const { findPython } = require('./find-python') const { findVisualStudio } = win ? require('./find-visualstudio') : {} +const majorRe = /^#define NODE_MAJOR_VERSION (\d+)/m +const minorRe = /^#define NODE_MINOR_VERSION (\d+)/m +const patchRe = /^#define NODE_PATCH_VERSION (\d+)/m + async function configure (gyp, argv) { const buildDir = path.resolve('build') const configNames = ['config.gypi', 'common.gypi'] @@ -27,6 +31,28 @@ async function configure (gyp, argv) { // 'python' should be set by now process.env.PYTHON = python + if (!gyp.opts.nodedir && + process.config.variables.use_prefix_to_find_headers) { + // check if the headers can be found using the prefix specified + // at build time. Use them if they match the version expected + const prefix = process.config.variables.node_prefix + let availVersion + try { + const nodeVersionH = readFileSync(path.join(prefix, + 'include', 'node', 'node_version.h'), { encoding: 'utf8' }) + const major = nodeVersionH.match(majorRe)[1] + const minor = nodeVersionH.match(minorRe)[1] + const patch = nodeVersionH.match(patchRe)[1] + availVersion = major + '.' + minor + '.' + patch + } catch {} + if (availVersion === release.version) { + // ok version matches, use the headers + gyp.opts.nodedir = prefix + log.verbose('using local node headers based on prefix', + 'setting nodedir to ' + gyp.opts.nodedir) + } + } + if (gyp.opts.nodedir) { // --nodedir was specified. use that for the dev files nodeDir = gyp.opts.nodedir.replace(/^~/, os.homedir()) diff --git a/deps/npm/node_modules/node-gyp/lib/find-python.js b/deps/npm/node_modules/node-gyp/lib/find-python.js index 615da57bb85723..a71c00c2b65bc1 100644 --- a/deps/npm/node_modules/node-gyp/lib/find-python.js +++ b/deps/npm/node_modules/node-gyp/lib/find-python.js @@ -41,7 +41,7 @@ class PythonFinder { static findPython = (...args) => new PythonFinder(...args).findPython() log = log.withPrefix('find Python') - argsExecutable = ['-c', 'import sys; print(sys.executable);'] + argsExecutable = ['-c', 'import sys; sys.stdout.buffer.write(sys.executable.encode(\'utf-8\'));'] argsVersion = ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);'] semverRange = '>=3.6.0' diff --git a/deps/npm/node_modules/node-gyp/lib/find-visualstudio.js b/deps/npm/node_modules/node-gyp/lib/find-visualstudio.js index b57770259abde3..8c5ae96127504c 100644 --- a/deps/npm/node_modules/node-gyp/lib/find-visualstudio.js +++ b/deps/npm/node_modules/node-gyp/lib/find-visualstudio.js @@ -54,7 +54,10 @@ class VisualStudioFinder { } const checks = [ - () => this.findVisualStudio2017OrNewer(), + () => this.findVisualStudio2019OrNewerUsingSetupModule(), + () => this.findVisualStudio2019OrNewer(), + () => this.findVisualStudio2017UsingSetupModule(), + () => this.findVisualStudio2017(), () => this.findVisualStudio2015(), () => this.findVisualStudio2013() ] @@ -113,9 +116,84 @@ class VisualStudioFinder { throw new Error('Could not find any Visual Studio installation to use') } + async findVisualStudio2019OrNewerUsingSetupModule () { + return this.findNewVSUsingSetupModule([2019, 2022]) + } + + async findVisualStudio2017UsingSetupModule () { + if (this.nodeSemver.major >= 22) { + this.addLog( + 'not looking for VS2017 as it is only supported up to Node.js 21') + return null + } + return this.findNewVSUsingSetupModule([2017]) + } + + async findNewVSUsingSetupModule (supportedYears) { + const ps = path.join(process.env.SystemRoot, 'System32', + 'WindowsPowerShell', 'v1.0', 'powershell.exe') + const vcInstallDir = this.envVcInstallDir + + const checkModuleArgs = [ + '-NoProfile', + '-Command', + '&{@(Get-Module -ListAvailable -Name VSSetup).Version.ToString()}' + ] + this.log.silly('Running', ps, checkModuleArgs) + const [cErr] = await this.execFile(ps, checkModuleArgs) + if (cErr) { + this.addLog('VSSetup module doesn\'t seem to exist. You can install it via: "Install-Module VSSetup -Scope CurrentUser"') + this.log.silly('VSSetup error = %j', cErr && (cErr.stack || cErr)) + return null + } + const filterArg = vcInstallDir !== undefined ? `| where {$_.InstallationPath -eq '${vcInstallDir}' }` : '' + const psArgs = [ + '-NoProfile', + '-Command', + `&{Get-VSSetupInstance ${filterArg} | ConvertTo-Json -Depth 3}` + ] + + this.log.silly('Running', ps, psArgs) + const [err, stdout, stderr] = await this.execFile(ps, psArgs) + let parsedData = this.parseData(err, stdout, stderr) + if (parsedData === null) { + return null + } + this.log.silly('Parsed data', parsedData) + if (!Array.isArray(parsedData)) { + // if there are only 1 result, then Powershell will output non-array + parsedData = [parsedData] + } + // normalize output + parsedData = parsedData.map((info) => { + info.path = info.InstallationPath + info.version = `${info.InstallationVersion.Major}.${info.InstallationVersion.Minor}.${info.InstallationVersion.Build}.${info.InstallationVersion.Revision}` + info.packages = info.Packages.map((p) => p.Id) + return info + }) + // pass for further processing + return this.processData(parsedData, supportedYears) + } + + // Invoke the PowerShell script to get information about Visual Studio 2019 + // or newer installations + async findVisualStudio2019OrNewer () { + return this.findNewVS([2019, 2022]) + } + + // Invoke the PowerShell script to get information about Visual Studio 2017 + async findVisualStudio2017 () { + if (this.nodeSemver.major >= 22) { + this.addLog( + 'not looking for VS2017 as it is only supported up to Node.js 21') + return null + } + return this.findNewVS([2017]) + } + // Invoke the PowerShell script to get information about Visual Studio 2017 // or newer installations - async findVisualStudio2017OrNewer () { + async findNewVS (supportedYears) { const ps = path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe') const csFile = path.join(__dirname, 'Find-VisualStudio.cs') @@ -128,24 +206,35 @@ class VisualStudioFinder { ] this.log.silly('Running', ps, psArgs) - const [err, stdout, stderr] = await execFile(ps, psArgs, { encoding: 'utf8' }) - return this.parseData(err, stdout, stderr) + const [err, stdout, stderr] = await this.execFile(ps, psArgs) + const parsedData = this.parseData(err, stdout, stderr, { checkIsArray: true }) + if (parsedData === null) { + return null + } + return this.processData(parsedData, supportedYears) } - // Parse the output of the PowerShell script and look for an installation - // of Visual Studio 2017 or newer to use - parseData (err, stdout, stderr) { + // Parse the output of the PowerShell script, make sanity checks + parseData (err, stdout, stderr, sanityCheckOptions) { + const defaultOptions = { + checkIsArray: false + } + + // Merging provided options with the default options + const sanityOptions = { ...defaultOptions, ...sanityCheckOptions } + this.log.silly('PS stderr = %j', stderr) - const failPowershell = () => { + const failPowershell = (failureDetails) => { this.addLog( - 'could not use PowerShell to find Visual Studio 2017 or newer, try re-running with \'--loglevel silly\' for more details') + `could not use PowerShell to find Visual Studio 2017 or newer, try re-running with '--loglevel silly' for more details. \n + Failure details: ${failureDetails}`) return null } if (err) { this.log.silly('PS err = %j', err && (err.stack || err)) - return failPowershell() + return failPowershell(`${err}`.substring(0, 40)) } let vsInfo @@ -157,11 +246,16 @@ class VisualStudioFinder { return failPowershell() } - if (!Array.isArray(vsInfo)) { + if (sanityOptions.checkIsArray && !Array.isArray(vsInfo)) { this.log.silly('PS stdout = %j', stdout) - return failPowershell() + return failPowershell('Expected array as output of the PS script') } + return vsInfo + } + // Process parsed data containing information about VS installations + // Look for the required parts, extract and output them back + processData (vsInfo, supportedYears) { vsInfo = vsInfo.map((info) => { this.log.silly(`processing installation: "${info.path}"`) info.path = path.resolve(info.path) @@ -175,11 +269,12 @@ class VisualStudioFinder { this.log.silly('vsInfo:', vsInfo) // Remove future versions or errors parsing version number + // Also remove any unsupported versions vsInfo = vsInfo.filter((info) => { - if (info.versionYear) { + if (info.versionYear && supportedYears.indexOf(info.versionYear) !== -1) { return true } - this.addLog(`unknown version "${info.version}" found at "${info.path}"`) + this.addLog(`${info.versionYear ? 'unsupported' : 'unknown'} version "${info.version}" found at "${info.path}"`) return false }) @@ -438,6 +533,10 @@ class VisualStudioFinder { return true } + + async execFile (exec, args) { + return await execFile(exec, args, { encoding: 'utf8' }) + } } module.exports = VisualStudioFinder diff --git a/deps/npm/node_modules/@npmcli/disparity-colors/LICENSE b/deps/npm/node_modules/node-gyp/node_modules/proc-log/LICENSE similarity index 96% rename from deps/npm/node_modules/@npmcli/disparity-colors/LICENSE rename to deps/npm/node_modules/node-gyp/node_modules/proc-log/LICENSE index dedcd7d2f9daec..83837797202b70 100644 --- a/deps/npm/node_modules/@npmcli/disparity-colors/LICENSE +++ b/deps/npm/node_modules/node-gyp/node_modules/proc-log/LICENSE @@ -1,6 +1,6 @@ The ISC License -Copyright (c) npm Inc. +Copyright (c) GitHub, Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/deps/npm/node_modules/node-gyp/node_modules/proc-log/lib/index.js b/deps/npm/node_modules/node-gyp/node_modules/proc-log/lib/index.js new file mode 100644 index 00000000000000..7c5dfad3b7ba3f --- /dev/null +++ b/deps/npm/node_modules/node-gyp/node_modules/proc-log/lib/index.js @@ -0,0 +1,23 @@ +// emits 'log' events on the process +const LEVELS = [ + 'notice', + 'error', + 'warn', + 'info', + 'verbose', + 'http', + 'silly', + 'pause', + 'resume', +] + +const log = level => (...args) => process.emit('log', level, ...args) + +const logger = {} +for (const level of LEVELS) { + logger[level] = log(level) +} + +logger.LEVELS = LEVELS + +module.exports = logger diff --git a/deps/npm/node_modules/npmlog/package.json b/deps/npm/node_modules/node-gyp/node_modules/proc-log/package.json similarity index 59% rename from deps/npm/node_modules/npmlog/package.json rename to deps/npm/node_modules/node-gyp/node_modules/proc-log/package.json index dbcc772d37ab7a..d335fa965ace51 100644 --- a/deps/npm/node_modules/npmlog/package.json +++ b/deps/npm/node_modules/node-gyp/node_modules/proc-log/package.json @@ -1,52 +1,44 @@ { - "author": "GitHub Inc.", - "name": "npmlog", - "description": "logger for npm", - "version": "7.0.1", - "repository": { - "type": "git", - "url": "https://github.com/npm/npmlog.git" - }, - "main": "lib/log.js", + "name": "proc-log", + "version": "3.0.0", "files": [ "bin/", "lib/" ], + "main": "lib/index.js", + "description": "just emit 'log' events on the process object", + "repository": { + "type": "git", + "url": "https://github.com/npm/proc-log.git" + }, + "author": "GitHub Inc.", + "license": "ISC", "scripts": { "test": "tap", - "npmclilint": "npmcli-lint", - "lint": "eslint \"**/*.js\"", - "lintfix": "npm run lint -- --fix", + "snap": "tap", "posttest": "npm run lint", - "postsnap": "npm run lintfix --", + "postsnap": "eslint index.js test/*.js --fix", + "lint": "eslint \"**/*.js\"", "postlint": "template-oss-check", - "snap": "tap", + "lintfix": "npm run lint -- --fix", "template-oss-apply": "template-oss-apply --force" }, - "dependencies": { - "are-we-there-yet": "^4.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^5.0.0", - "set-blocking": "^2.0.0" - }, "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.6.1", + "@npmcli/eslint-config": "^3.0.1", + "@npmcli/template-oss": "4.5.1", "tap": "^16.0.1" }, - "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" }, + "templateOSS": { + "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", + "version": "4.5.1" + }, "tap": { - "branches": 95, "nyc-arg": [ "--exclude", "tap-snapshots/**" ] - }, - "templateOSS": { - "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.6.1" } } diff --git a/deps/npm/node_modules/node-gyp/package.json b/deps/npm/node_modules/node-gyp/package.json index 80c63f2e72c3d9..95f012fa5daf79 100644 --- a/deps/npm/node_modules/node-gyp/package.json +++ b/deps/npm/node_modules/node-gyp/package.json @@ -11,7 +11,7 @@ "bindings", "gyp" ], - "version": "10.0.1", + "version": "10.1.0", "installVersion": 11, "author": "Nathan Rajlich (http://tootallnate.net)", "repository": { diff --git a/deps/npm/node_modules/node-gyp/release-please-config.json b/deps/npm/node_modules/node-gyp/release-please-config.json new file mode 100644 index 00000000000000..94b8f8110e881a --- /dev/null +++ b/deps/npm/node_modules/node-gyp/release-please-config.json @@ -0,0 +1,40 @@ +{ + "packages": { + ".": { + "include-component-in-tag": false, + "release-type": "node", + "changelog-sections": [ + { "type": "feat", "section": "Features", "hidden": false }, + { "type": "fix", "section": "Bug Fixes", "hidden": false }, + { "type": "bin", "section": "Core", "hidden": false }, + { "type": "gyp", "section": "Core", "hidden": false }, + { "type": "lib", "section": "Core", "hidden": false }, + { "type": "src", "section": "Core", "hidden": false }, + { "type": "test", "section": "Tests", "hidden": false }, + { "type": "build", "section": "Core", "hidden": false }, + { "type": "clean", "section": "Core", "hidden": false }, + { "type": "configure", "section": "Core", "hidden": false }, + { "type": "install", "section": "Core", "hidden": false }, + { "type": "list", "section": "Core", "hidden": false }, + { "type": "rebuild", "section": "Core", "hidden": false }, + { "type": "remove", "section": "Core", "hidden": false }, + { "type": "deps", "section": "Core", "hidden": false }, + { "type": "python", "section": "Core", "hidden": false }, + { "type": "lin", "section": "Core", "hidden": false }, + { "type": "linux", "section": "Core", "hidden": false }, + { "type": "mac", "section": "Core", "hidden": false }, + { "type": "macos", "section": "Core", "hidden": false }, + { "type": "win", "section": "Core", "hidden": false }, + { "type": "windows", "section": "Core", "hidden": false }, + { "type": "zos", "section": "Core", "hidden": false }, + { "type": "doc", "section": "Doc", "hidden": false }, + { "type": "docs", "section": "Doc", "hidden": false }, + { "type": "readme", "section": "Doc", "hidden": false }, + { "type": "chore", "section": "Miscellaneous", "hidden": false }, + { "type": "refactor", "section": "Miscellaneous", "hidden": false }, + { "type": "ci", "section": "Miscellaneous", "hidden": false }, + { "type": "meta", "section": "Miscellaneous", "hidden": false } + ] + } + } +} diff --git a/deps/npm/node_modules/npm-package-arg/lib/npa.js b/deps/npm/node_modules/npm-package-arg/lib/npa.js index 23bf68d2e04a39..6a3f07da929d87 100644 --- a/deps/npm/node_modules/npm-package-arg/lib/npa.js +++ b/deps/npm/node_modules/npm-package-arg/lib/npa.js @@ -10,7 +10,7 @@ const semver = require('semver') const path = global.FAKE_WINDOWS ? require('path').win32 : require('path') const validatePackageName = require('validate-npm-package-name') const { homedir } = require('os') -const log = require('proc-log') +const { log } = require('proc-log') const isWindows = process.platform === 'win32' || global.FAKE_WINDOWS const hasSlashes = isWindows ? /\\|[/]/ : /[/]/ diff --git a/deps/npm/node_modules/npm-package-arg/package.json b/deps/npm/node_modules/npm-package-arg/package.json index f7965d5a007c9d..c4cee1f928e89d 100644 --- a/deps/npm/node_modules/npm-package-arg/package.json +++ b/deps/npm/node_modules/npm-package-arg/package.json @@ -1,6 +1,6 @@ { "name": "npm-package-arg", - "version": "11.0.1", + "version": "11.0.2", "description": "Parse the things that can be arguments to `npm install`", "main": "./lib/npa.js", "directories": { @@ -12,20 +12,20 @@ ], "dependencies": { "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^5.0.0" }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.18.0", + "@npmcli/template-oss": "4.21.3", "tap": "^16.0.1" }, "scripts": { "test": "tap", "snap": "tap", "npmclilint": "npmcli-lint", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "lintfix": "npm run lint -- --fix", "posttest": "npm run lint", "postsnap": "npm run lintfix --", @@ -54,14 +54,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.18.0", - "publish": true, - "ciVersions": [ - "16.14.0", - "16.x", - "18.0.0", - "18.x" - ], - "npmSpec": "next-9" + "version": "4.21.3", + "publish": true } } diff --git a/deps/npm/node_modules/npm-profile/lib/index.js b/deps/npm/node_modules/npm-profile/lib/index.js index ce78882a55438d..e5b5dd046baf2e 100644 --- a/deps/npm/node_modules/npm-profile/lib/index.js +++ b/deps/npm/node_modules/npm-profile/lib/index.js @@ -5,7 +5,7 @@ const { HttpErrorBase } = require('npm-registry-fetch/lib/errors') const EventEmitter = require('events') const os = require('os') const { URL } = require('url') -const log = require('proc-log') +const { log } = require('proc-log') // try loginWeb, catch the "not supported" message and fall back to couch const login = (opener, prompter, opts = {}) => { @@ -276,8 +276,7 @@ class WebLoginNotSupported extends HttpErrorBase { } } -const sleep = (ms) => - new Promise((resolve, reject) => setTimeout(resolve, ms)) +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) module.exports = { adduserCouch, diff --git a/deps/npm/node_modules/npm-profile/package.json b/deps/npm/node_modules/npm-profile/package.json index af57e9e73509c3..acdf4d6baf2ee3 100644 --- a/deps/npm/node_modules/npm-profile/package.json +++ b/deps/npm/node_modules/npm-profile/package.json @@ -1,13 +1,13 @@ { "name": "npm-profile", - "version": "9.0.0", + "version": "9.0.2", "description": "Library for updating an npmjs.com profile", "keywords": [], "author": "GitHub Inc.", "license": "ISC", "dependencies": { - "npm-registry-fetch": "^16.0.0", - "proc-log": "^3.0.0" + "npm-registry-fetch": "^17.0.0", + "proc-log": "^4.0.0" }, "main": "./lib/index.js", "repository": { @@ -20,7 +20,7 @@ ], "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.18.0", + "@npmcli/template-oss": "4.21.4", "nock": "^13.2.4", "tap": "^16.0.1" }, @@ -28,7 +28,7 @@ "posttest": "npm run lint", "test": "tap", "snap": "tap", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "postlint": "template-oss-check", "lintfix": "npm run lint -- --fix", "template-oss-apply": "template-oss-apply --force" @@ -45,13 +45,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.18.0", - "ciVersions": [ - "16.14.0", - "16.x", - "18.0.0", - "18.x" - ], + "version": "4.21.4", "publish": true } } diff --git a/deps/npm/node_modules/npm-registry-fetch/lib/check-response.js b/deps/npm/node_modules/npm-registry-fetch/lib/check-response.js index 066ac3c32420f2..65eea2963b0b4c 100644 --- a/deps/npm/node_modules/npm-registry-fetch/lib/check-response.js +++ b/deps/npm/node_modules/npm-registry-fetch/lib/check-response.js @@ -3,8 +3,8 @@ const errors = require('./errors.js') const { Response } = require('minipass-fetch') const defaultOpts = require('./default-opts.js') -const log = require('proc-log') -const cleanUrl = require('./clean-url.js') +const { log } = require('proc-log') +const { redact: cleanUrl } = require('@npmcli/redact') /* eslint-disable-next-line max-len */ const moreInfoUrl = 'https://github.com/npm/cli/wiki/No-auth-for-URI,-but-auth-present-for-scoped-registry' diff --git a/deps/npm/node_modules/npm-registry-fetch/lib/clean-url.js b/deps/npm/node_modules/npm-registry-fetch/lib/clean-url.js deleted file mode 100644 index 0c2656b5653a00..00000000000000 --- a/deps/npm/node_modules/npm-registry-fetch/lib/clean-url.js +++ /dev/null @@ -1,27 +0,0 @@ -const { URL } = require('url') - -const replace = '***' -const tokenRegex = /\bnpm_[a-zA-Z0-9]{36}\b/g -const guidRegex = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/g - -const cleanUrl = (str) => { - if (typeof str !== 'string' || !str) { - return str - } - - try { - const url = new URL(str) - if (url.password) { - url.password = replace - str = url.toString() - } - } catch { - // ignore errors - } - - return str - .replace(tokenRegex, `npm_${replace}`) - .replace(guidRegex, `npm_${replace}`) -} - -module.exports = cleanUrl diff --git a/deps/npm/node_modules/npm-registry-fetch/lib/index.js b/deps/npm/node_modules/npm-registry-fetch/lib/index.js index bb413f862d92d0..bce6e6b1aae0ac 100644 --- a/deps/npm/node_modules/npm-registry-fetch/lib/index.js +++ b/deps/npm/node_modules/npm-registry-fetch/lib/index.js @@ -245,5 +245,3 @@ function getHeaders (uri, auth, opts) { return headers } - -module.exports.cleanUrl = require('./clean-url.js') diff --git a/deps/npm/node_modules/npm-registry-fetch/package.json b/deps/npm/node_modules/npm-registry-fetch/package.json index b715d52391a933..52820a6a206ecb 100644 --- a/deps/npm/node_modules/npm-registry-fetch/package.json +++ b/deps/npm/node_modules/npm-registry-fetch/package.json @@ -1,6 +1,6 @@ { "name": "npm-registry-fetch", - "version": "16.1.0", + "version": "17.0.0", "description": "Fetch-based http client for use with npm registry APIs", "main": "lib", "files": [ @@ -9,7 +9,7 @@ ], "scripts": { "eslint": "eslint", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "lintfix": "npm run lint -- --fix", "test": "tap", "posttest": "npm run lint", @@ -31,17 +31,18 @@ "author": "GitHub Inc.", "license": "ISC", "dependencies": { + "@npmcli/redact": "^2.0.0", "make-fetch-happen": "^13.0.0", "minipass": "^7.0.2", "minipass-fetch": "^3.0.0", "minipass-json-stream": "^1.0.1", "minizlib": "^2.1.2", "npm-package-arg": "^11.0.0", - "proc-log": "^3.0.0" + "proc-log": "^4.0.0" }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.19.0", + "@npmcli/template-oss": "4.21.4", "cacache": "^18.0.0", "nock": "^13.2.4", "require-inject": "^1.4.4", @@ -61,7 +62,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.19.0", + "version": "4.21.4", "publish": "true" } } diff --git a/deps/npm/node_modules/npmlog/LICENSE.md b/deps/npm/node_modules/npmlog/LICENSE.md deleted file mode 100644 index 5fc208ff122e08..00000000000000 --- a/deps/npm/node_modules/npmlog/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ - - -ISC License - -Copyright npm, Inc. - -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 NPM DISCLAIMS ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO -EVENT SHALL NPM 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. diff --git a/deps/npm/node_modules/npmlog/lib/log.js b/deps/npm/node_modules/npmlog/lib/log.js deleted file mode 100644 index 38106ea34ae08d..00000000000000 --- a/deps/npm/node_modules/npmlog/lib/log.js +++ /dev/null @@ -1,400 +0,0 @@ -'use strict' -var Progress = require('are-we-there-yet') -var Gauge = require('gauge') -var EE = require('events').EventEmitter -var log = exports = module.exports = new EE() -var util = require('util') - -var setBlocking = require('set-blocking') -var consoleControl = require('console-control-strings') - -setBlocking(true) -var stream = process.stderr -Object.defineProperty(log, 'stream', { - set: function (newStream) { - stream = newStream - if (this.gauge) { - this.gauge.setWriteTo(stream, stream) - } - }, - get: function () { - return stream - }, -}) - -// by default, decide based on tty-ness. -var colorEnabled -log.useColor = function () { - return colorEnabled != null ? colorEnabled : stream.isTTY -} - -log.enableColor = function () { - colorEnabled = true - this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled }) -} -log.disableColor = function () { - colorEnabled = false - this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled }) -} - -// default level -log.level = 'info' - -log.gauge = new Gauge(stream, { - enabled: false, // no progress bars unless asked - theme: { hasColor: log.useColor() }, - template: [ - { type: 'progressbar', length: 20 }, - { type: 'activityIndicator', kerning: 1, length: 1 }, - { type: 'section', default: '' }, - ':', - { type: 'logline', kerning: 1, default: '' }, - ], -}) - -log.tracker = new Progress.TrackerGroup() - -// we track this separately as we may need to temporarily disable the -// display of the status bar for our own loggy purposes. -log.progressEnabled = log.gauge.isEnabled() - -var unicodeEnabled - -log.enableUnicode = function () { - unicodeEnabled = true - this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled }) -} - -log.disableUnicode = function () { - unicodeEnabled = false - this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled }) -} - -log.setGaugeThemeset = function (themes) { - this.gauge.setThemeset(themes) -} - -log.setGaugeTemplate = function (template) { - this.gauge.setTemplate(template) -} - -log.enableProgress = function () { - if (this.progressEnabled || this._paused) { - return - } - - this.progressEnabled = true - this.tracker.on('change', this.showProgress) - this.gauge.enable() -} - -log.disableProgress = function () { - if (!this.progressEnabled) { - return - } - this.progressEnabled = false - this.tracker.removeListener('change', this.showProgress) - this.gauge.disable() -} - -var trackerConstructors = ['newGroup', 'newItem', 'newStream'] - -var mixinLog = function (tracker) { - // mixin the public methods from log into the tracker - // (except: conflicts and one's we handle specially) - Object.keys(log).forEach(function (P) { - if (P[0] === '_') { - return - } - - if (trackerConstructors.filter(function (C) { - return C === P - }).length) { - return - } - - if (tracker[P]) { - return - } - - if (typeof log[P] !== 'function') { - return - } - - var func = log[P] - tracker[P] = function () { - return func.apply(log, arguments) - } - }) - // if the new tracker is a group, make sure any subtrackers get - // mixed in too - if (tracker instanceof Progress.TrackerGroup) { - trackerConstructors.forEach(function (C) { - var func = tracker[C] - tracker[C] = function () { - return mixinLog(func.apply(tracker, arguments)) - } - }) - } - return tracker -} - -// Add tracker constructors to the top level log object -trackerConstructors.forEach(function (C) { - log[C] = function () { - return mixinLog(this.tracker[C].apply(this.tracker, arguments)) - } -}) - -log.clearProgress = function (cb) { - if (!this.progressEnabled) { - return cb && process.nextTick(cb) - } - - this.gauge.hide(cb) -} - -log.showProgress = function (name, completed) { - if (!this.progressEnabled) { - return - } - - var values = {} - if (name) { - values.section = name - } - - var last = log.record[log.record.length - 1] - if (last) { - values.subsection = last.prefix - var disp = log.disp[last.level] || last.level - var logline = this._format(disp, log.style[last.level]) - if (last.prefix) { - logline += ' ' + this._format(last.prefix, this.prefixStyle) - } - - logline += ' ' + last.message.split(/\r?\n/)[0] - values.logline = logline - } - values.completed = completed || this.tracker.completed() - this.gauge.show(values) -}.bind(log) // bind for use in tracker's on-change listener - -// temporarily stop emitting, but don't drop -log.pause = function () { - this._paused = true - if (this.progressEnabled) { - this.gauge.disable() - } -} - -log.resume = function () { - if (!this._paused) { - return - } - - this._paused = false - - var b = this._buffer - this._buffer = [] - b.forEach(function (m) { - this.emitLog(m) - }, this) - if (this.progressEnabled) { - this.gauge.enable() - } -} - -log._buffer = [] - -var id = 0 -log.record = [] -log.maxRecordSize = 10000 -log.log = function (lvl, prefix, message) { - var l = this.levels[lvl] - if (l === undefined) { - return this.emit('error', new Error(util.format( - 'Undefined log level: %j', lvl))) - } - - var a = new Array(arguments.length - 2) - var stack = null - for (var i = 2; i < arguments.length; i++) { - var arg = a[i - 2] = arguments[i] - - // resolve stack traces to a plain string. - if (typeof arg === 'object' && arg instanceof Error && arg.stack) { - Object.defineProperty(arg, 'stack', { - value: stack = arg.stack + '', - enumerable: true, - writable: true, - }) - } - } - if (stack) { - a.unshift(stack + '\n') - } - message = util.format.apply(util, a) - - var m = { - id: id++, - level: lvl, - prefix: String(prefix || ''), - message: message, - messageRaw: a, - } - - this.emit('log', m) - this.emit('log.' + lvl, m) - if (m.prefix) { - this.emit(m.prefix, m) - } - - this.record.push(m) - var mrs = this.maxRecordSize - var n = this.record.length - mrs - if (n > mrs / 10) { - var newSize = Math.floor(mrs * 0.9) - this.record = this.record.slice(-1 * newSize) - } - - this.emitLog(m) -}.bind(log) - -log.emitLog = function (m) { - if (this._paused) { - this._buffer.push(m) - return - } - if (this.progressEnabled) { - this.gauge.pulse(m.prefix) - } - - var l = this.levels[m.level] - if (l === undefined) { - return - } - - if (l < this.levels[this.level]) { - return - } - - if (l > 0 && !isFinite(l)) { - return - } - - // If 'disp' is null or undefined, use the lvl as a default - // Allows: '', 0 as valid disp - var disp = log.disp[m.level] != null ? log.disp[m.level] : m.level - this.clearProgress() - m.message.split(/\r?\n/).forEach(function (line) { - var heading = this.heading - if (heading) { - this.write(heading, this.headingStyle) - this.write(' ') - } - this.write(disp, log.style[m.level]) - var p = m.prefix || '' - if (p) { - this.write(' ') - } - - this.write(p, this.prefixStyle) - this.write(' ' + line + '\n') - }, this) - this.showProgress() -} - -log._format = function (msg, style) { - if (!stream) { - return - } - - var output = '' - if (this.useColor()) { - style = style || {} - var settings = [] - if (style.fg) { - settings.push(style.fg) - } - - if (style.bg) { - settings.push('bg' + style.bg[0].toUpperCase() + style.bg.slice(1)) - } - - if (style.bold) { - settings.push('bold') - } - - if (style.underline) { - settings.push('underline') - } - - if (style.inverse) { - settings.push('inverse') - } - - if (settings.length) { - output += consoleControl.color(settings) - } - - if (style.beep) { - output += consoleControl.beep() - } - } - output += msg - if (this.useColor()) { - output += consoleControl.color('reset') - } - - return output -} - -log.write = function (msg, style) { - if (!stream) { - return - } - - stream.write(this._format(msg, style)) -} - -log.addLevel = function (lvl, n, style, disp) { - // If 'disp' is null or undefined, use the lvl as a default - if (disp == null) { - disp = lvl - } - - this.levels[lvl] = n - this.style[lvl] = style - if (!this[lvl]) { - this[lvl] = function () { - var a = new Array(arguments.length + 1) - a[0] = lvl - for (var i = 0; i < arguments.length; i++) { - a[i + 1] = arguments[i] - } - - return this.log.apply(this, a) - }.bind(this) - } - this.disp[lvl] = disp -} - -log.prefixStyle = { fg: 'magenta' } -log.headingStyle = { fg: 'white', bg: 'black' } - -log.style = {} -log.levels = {} -log.disp = {} -log.addLevel('silly', -Infinity, { inverse: true }, 'sill') -log.addLevel('verbose', 1000, { fg: 'cyan', bg: 'black' }, 'verb') -log.addLevel('info', 2000, { fg: 'green' }) -log.addLevel('timing', 2500, { fg: 'green', bg: 'black' }) -log.addLevel('http', 3000, { fg: 'green', bg: 'black' }) -log.addLevel('notice', 3500, { fg: 'cyan', bg: 'black' }) -log.addLevel('warn', 4000, { fg: 'black', bg: 'yellow' }, 'WARN') -log.addLevel('error', 5000, { fg: 'red', bg: 'black' }, 'ERR!') -log.addLevel('silent', Infinity) - -// allow 'error' prefix -log.on('error', function () {}) diff --git a/deps/npm/node_modules/pacote/README.md b/deps/npm/node_modules/pacote/README.md index 17c027dfa048f3..dbb0051de23a4d 100644 --- a/deps/npm/node_modules/pacote/README.md +++ b/deps/npm/node_modules/pacote/README.md @@ -166,8 +166,6 @@ resolved, and other properties, as they are determined. calls. This allows you to easily avoid hitting the registry multiple times (even just to validate the cache) for a given packument, since it is unlikely to change in the span of a single command. -* `silent` A boolean that determines whether the banner is displayed - when calling `@npmcli/run-script`. * `verifySignatures` A boolean that will make pacote verify the integrity signature of a manifest, if present. There must be a configured `_keys` entry in the config that is scoped to the diff --git a/deps/npm/node_modules/pacote/lib/dir.js b/deps/npm/node_modules/pacote/lib/dir.js index 420afc5802cb2f..135be8e6cba833 100644 --- a/deps/npm/node_modules/pacote/lib/dir.js +++ b/deps/npm/node_modules/pacote/lib/dir.js @@ -41,16 +41,11 @@ class DirFetcher extends Fetcher { // but this function is *also* run when installing git deps const stdio = this.opts.foregroundScripts ? 'inherit' : 'pipe' - // hide the banner if silent opt is passed in, or if prepare running - // in the background. - const banner = this.opts.silent ? false : stdio === 'inherit' - return runScript({ pkg: mani, event: 'prepare', path: this.resolved, stdio, - banner, env: { npm_package_resolved: this.resolved, npm_package_integrity: this.integrity, @@ -92,7 +87,7 @@ class DirFetcher extends Fetcher { return Promise.resolve(this.package) } - return this[_readPackageJson](this.resolved + '/package.json') + return this[_readPackageJson](this.resolved) .then(mani => this.package = { ...mani, _integrity: this.integrity && String(this.integrity), diff --git a/deps/npm/node_modules/pacote/lib/fetcher.js b/deps/npm/node_modules/pacote/lib/fetcher.js index f961a45c7d3461..c4a707e7ef81ef 100644 --- a/deps/npm/node_modules/pacote/lib/fetcher.js +++ b/deps/npm/node_modules/pacote/lib/fetcher.js @@ -5,10 +5,9 @@ const npa = require('npm-package-arg') const ssri = require('ssri') -const { promisify } = require('util') const { basename, dirname } = require('path') const tar = require('tar') -const log = require('proc-log') +const { log } = require('proc-log') const retry = require('promise-retry') const fs = require('fs/promises') const fsm = require('fs-minipass') @@ -16,12 +15,14 @@ const cacache = require('cacache') const isPackageBin = require('./util/is-package-bin.js') const removeTrailingSlashes = require('./util/trailing-slashes.js') const getContents = require('@npmcli/installed-package-contents') -const readPackageJsonFast = require('read-package-json-fast') -const readPackageJson = promisify(require('read-package-json')) +const PackageJson = require('@npmcli/package-json') const { Minipass } = require('minipass') - const cacheDir = require('./util/cache-dir.js') +// Pacote is only concerned with the package.json contents +const packageJsonPrepare = (p) => PackageJson.prepare(p).then(pkg => pkg.content) +const packageJsonNormalize = (p) => PackageJson.normalize(p).then(pkg => pkg.content) + // Private methods. // Child classes should not have to override these. // Users should never call them. @@ -93,9 +94,9 @@ class FetcherBase { this.fullMetadata = this.before ? true : !!opts.fullMetadata this.fullReadJson = !!opts.fullReadJson if (this.fullReadJson) { - this[_readPackageJson] = readPackageJson + this[_readPackageJson] = packageJsonPrepare } else { - this[_readPackageJson] = readPackageJsonFast + this[_readPackageJson] = packageJsonNormalize } // rrh is a registry hostname or 'never' or 'always' diff --git a/deps/npm/node_modules/pacote/lib/file.js b/deps/npm/node_modules/pacote/lib/file.js index bf99bb86e359ed..95769de1374c97 100644 --- a/deps/npm/node_modules/pacote/lib/file.js +++ b/deps/npm/node_modules/pacote/lib/file.js @@ -1,10 +1,11 @@ -const Fetcher = require('./fetcher.js') const fsm = require('fs-minipass') const cacache = require('cacache') -const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved') -const _exeBins = Symbol('_exeBins') const { resolve } = require('path') -const fs = require('fs') +const { stat, chmod } = require('fs/promises') +const Fetcher = require('./fetcher.js') + +const _exeBins = Symbol('_exeBins') +const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved') const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson') class FileFetcher extends Fetcher { @@ -26,7 +27,7 @@ class FileFetcher extends Fetcher { // have to unpack the tarball for this. return cacache.tmp.withTmp(this.cache, this.opts, dir => this.extract(dir) - .then(() => this[_readPackageJson](dir + '/package.json')) + .then(() => this[_readPackageJson](dir)) .then(mani => this.package = { ...mani, _integrity: this.integrity && String(this.integrity), @@ -40,23 +41,23 @@ class FileFetcher extends Fetcher { return Promise.resolve() } - return Promise.all(Object.keys(pkg.bin).map(k => new Promise(res => { + return Promise.all(Object.keys(pkg.bin).map(async k => { const script = resolve(dest, pkg.bin[k]) // Best effort. Ignore errors here, the only result is that // a bin script is not executable. But if it's missing or // something, we just leave it for a later stage to trip over // when we can provide a more useful contextual error. - fs.stat(script, (er, st) => { - if (er) { - return res() - } + try { + const st = await stat(script) const mode = st.mode | 0o111 if (mode === st.mode) { - return res() + return } - fs.chmod(script, mode, res) - }) - }))) + await chmod(script, mode) + } catch { + // Ignore errors here + } + })) } extract (dest) { @@ -64,7 +65,7 @@ class FileFetcher extends Fetcher { // but if not, read the unpacked manifest and chmod properly. return super.extract(dest) .then(result => this.package ? result - : this[_readPackageJson](dest + '/package.json').then(pkg => + : this[_readPackageJson](dest).then(pkg => this[_exeBins](pkg, dest)).then(() => result)) } diff --git a/deps/npm/node_modules/pacote/lib/git.js b/deps/npm/node_modules/pacote/lib/git.js index 5d24f72497ec9e..2cac44ae528e6e 100644 --- a/deps/npm/node_modules/pacote/lib/git.js +++ b/deps/npm/node_modules/pacote/lib/git.js @@ -8,7 +8,7 @@ const pickManifest = require('npm-pick-manifest') const npa = require('npm-package-arg') const { Minipass } = require('minipass') const cacache = require('cacache') -const log = require('proc-log') +const { log } = require('proc-log') const npm = require('./util/npm.js') const _resolvedFromRepo = Symbol('_resolvedFromRepo') @@ -156,11 +156,11 @@ class GitFetcher extends Fetcher { [_resolvedFromClone] () { // do a full or shallow clone, then look at the HEAD // kind of wasteful, but no other option, really - return this[_clone](dir => this.resolved) + return this[_clone](() => this.resolved) } [_prepareDir] (dir) { - return this[_readPackageJson](dir + '/package.json').then(mani => { + return this[_readPackageJson](dir).then(mani => { // no need if we aren't going to do any preparation. const scripts = mani.scripts if (!mani.workspaces && (!scripts || !( @@ -312,7 +312,7 @@ class GitFetcher extends Fetcher { return this.spec.hosted && this.resolved ? FileFetcher.prototype.manifest.apply(this) : this[_clone](dir => - this[_readPackageJson](dir + '/package.json') + this[_readPackageJson](dir) .then(mani => this.package = { ...mani, _resolved: this.resolved, diff --git a/deps/npm/node_modules/pacote/lib/registry.js b/deps/npm/node_modules/pacote/lib/registry.js index de25a11af46672..b6a8d49b84f321 100644 --- a/deps/npm/node_modules/pacote/lib/registry.js +++ b/deps/npm/node_modules/pacote/lib/registry.js @@ -3,7 +3,7 @@ const RemoteFetcher = require('./remote.js') const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved') const pacoteVersion = require('../package.json').version const removeTrailingSlashes = require('./util/trailing-slashes.js') -const rpj = require('read-package-json-fast') +const PackageJson = require('@npmcli/package-json') const pickManifest = require('npm-pick-manifest') const ssri = require('ssri') const crypto = require('crypto') @@ -127,12 +127,13 @@ class RegistryFetcher extends Fetcher { } const packument = await this.packument() - let mani = await pickManifest(packument, this.spec.fetchSpec, { + const steps = PackageJson.normalizeSteps.filter(s => s !== '_attributes') + const mani = await new PackageJson().fromContent(pickManifest(packument, this.spec.fetchSpec, { ...this.opts, defaultTag: this.defaultTag, before: this.before, - }) - mani = rpj.normalize(mani) + })).normalize({ steps }).then(p => p.content) + /* XXX add ETARGET and E403 revalidation of cached packuments here */ // add _time from packument if fetched with fullMetadata diff --git a/deps/npm/node_modules/pacote/package.json b/deps/npm/node_modules/pacote/package.json index 8fc0bb707f1e52..4c1751644cd57a 100644 --- a/deps/npm/node_modules/pacote/package.json +++ b/deps/npm/node_modules/pacote/package.json @@ -1,6 +1,6 @@ { "name": "pacote", - "version": "17.0.6", + "version": "18.0.3", "description": "JavaScript package downloader", "author": "GitHub Inc.", "bin": { @@ -27,7 +27,7 @@ "devDependencies": { "@npmcli/arborist": "^7.1.0", "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.21.3", + "@npmcli/template-oss": "4.21.4", "hosted-git-info": "^7.0.0", "mutate-fs": "^2.1.1", "nock": "^13.2.4", @@ -46,19 +46,18 @@ "dependencies": { "@npmcli/git": "^5.0.0", "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.0", - "@npmcli/run-script": "^7.0.0", + "@npmcli/run-script": "^8.0.0", "cacache": "^18.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^11.0.0", "npm-packlist": "^8.0.0", "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^16.0.0", - "proc-log": "^3.0.0", + "npm-registry-fetch": "^17.0.0", + "proc-log": "^4.0.0", "promise-retry": "^2.0.1", - "read-package-json": "^7.0.0", - "read-package-json-fast": "^3.0.0", "sigstore": "^2.2.0", "ssri": "^10.0.0", "tar": "^6.1.11" @@ -72,7 +71,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.21.3", + "version": "4.21.4", "windowsCI": false, "publish": "true" } diff --git a/deps/npm/node_modules/path-scurry/dist/cjs/index.js b/deps/npm/node_modules/path-scurry/dist/commonjs/index.js similarity index 99% rename from deps/npm/node_modules/path-scurry/dist/cjs/index.js rename to deps/npm/node_modules/path-scurry/dist/commonjs/index.js index 23eb5b0853ff28..6e330d400d2ac9 100644 --- a/deps/npm/node_modules/path-scurry/dist/cjs/index.js +++ b/deps/npm/node_modules/path-scurry/dist/commonjs/index.js @@ -75,21 +75,21 @@ const IFMT = 0b1111; // mask to unset low 4 bits const IFMT_UNKNOWN = ~IFMT; // set after successfully calling readdir() and getting entries. -const READDIR_CALLED = 16; +const READDIR_CALLED = 0b0000_0001_0000; // set after a successful lstat() -const LSTAT_CALLED = 32; +const LSTAT_CALLED = 0b0000_0010_0000; // set if an entry (or one of its parents) is definitely not a dir -const ENOTDIR = 64; +const ENOTDIR = 0b0000_0100_0000; // set if an entry (or one of its parents) does not exist // (can also be set on lstat errors like EACCES or ENAMETOOLONG) -const ENOENT = 128; +const ENOENT = 0b0000_1000_0000; // cannot have child entries -- also verify &IFMT is either IFDIR or IFLNK // set if we fail to readlink -const ENOREADLINK = 256; +const ENOREADLINK = 0b0001_0000_0000; // set if we know realpath() will fail -const ENOREALPATH = 512; +const ENOREALPATH = 0b0010_0000_0000; const ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH; -const TYPEMASK = 1023; +const TYPEMASK = 0b0011_1111_1111; const entToType = (s) => s.isFile() ? IFREG : s.isDirectory() @@ -703,7 +703,7 @@ class PathBase { /* c8 ignore stop */ try { const read = await this.#fs.promises.readlink(this.fullpath()); - const linkTarget = this.parent.resolve(read); + const linkTarget = (await this.parent.realpath())?.resolve(read); if (linkTarget) { return (this.#linkTarget = linkTarget); } @@ -732,7 +732,7 @@ class PathBase { /* c8 ignore stop */ try { const read = this.#fs.readlinkSync(this.fullpath()); - const linkTarget = this.parent.resolve(read); + const linkTarget = (this.parent.realpathSync())?.resolve(read); if (linkTarget) { return (this.#linkTarget = linkTarget); } @@ -747,7 +747,9 @@ class PathBase { this.#type |= READDIR_CALLED; // mark all remaining provisional children as ENOENT for (let p = children.provisional; p < children.length; p++) { - children[p].#markENOENT(); + const c = children[p]; + if (c) + c.#markENOENT(); } } #markENOENT() { diff --git a/deps/npm/node_modules/path-scurry/dist/cjs/package.json b/deps/npm/node_modules/path-scurry/dist/commonjs/package.json similarity index 100% rename from deps/npm/node_modules/path-scurry/dist/cjs/package.json rename to deps/npm/node_modules/path-scurry/dist/commonjs/package.json diff --git a/deps/npm/node_modules/path-scurry/dist/mjs/index.js b/deps/npm/node_modules/path-scurry/dist/esm/index.js similarity index 99% rename from deps/npm/node_modules/path-scurry/dist/mjs/index.js rename to deps/npm/node_modules/path-scurry/dist/esm/index.js index 079253a6aee967..2ce978e64bb117 100644 --- a/deps/npm/node_modules/path-scurry/dist/mjs/index.js +++ b/deps/npm/node_modules/path-scurry/dist/esm/index.js @@ -49,21 +49,21 @@ const IFMT = 0b1111; // mask to unset low 4 bits const IFMT_UNKNOWN = ~IFMT; // set after successfully calling readdir() and getting entries. -const READDIR_CALLED = 16; +const READDIR_CALLED = 0b0000_0001_0000; // set after a successful lstat() -const LSTAT_CALLED = 32; +const LSTAT_CALLED = 0b0000_0010_0000; // set if an entry (or one of its parents) is definitely not a dir -const ENOTDIR = 64; +const ENOTDIR = 0b0000_0100_0000; // set if an entry (or one of its parents) does not exist // (can also be set on lstat errors like EACCES or ENAMETOOLONG) -const ENOENT = 128; +const ENOENT = 0b0000_1000_0000; // cannot have child entries -- also verify &IFMT is either IFDIR or IFLNK // set if we fail to readlink -const ENOREADLINK = 256; +const ENOREADLINK = 0b0001_0000_0000; // set if we know realpath() will fail -const ENOREALPATH = 512; +const ENOREALPATH = 0b0010_0000_0000; const ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH; -const TYPEMASK = 1023; +const TYPEMASK = 0b0011_1111_1111; const entToType = (s) => s.isFile() ? IFREG : s.isDirectory() @@ -675,7 +675,7 @@ export class PathBase { /* c8 ignore stop */ try { const read = await this.#fs.promises.readlink(this.fullpath()); - const linkTarget = this.parent.resolve(read); + const linkTarget = (await this.parent.realpath())?.resolve(read); if (linkTarget) { return (this.#linkTarget = linkTarget); } @@ -704,7 +704,7 @@ export class PathBase { /* c8 ignore stop */ try { const read = this.#fs.readlinkSync(this.fullpath()); - const linkTarget = this.parent.resolve(read); + const linkTarget = (this.parent.realpathSync())?.resolve(read); if (linkTarget) { return (this.#linkTarget = linkTarget); } @@ -719,7 +719,9 @@ export class PathBase { this.#type |= READDIR_CALLED; // mark all remaining provisional children as ENOENT for (let p = children.provisional; p < children.length; p++) { - children[p].#markENOENT(); + const c = children[p]; + if (c) + c.#markENOENT(); } } #markENOENT() { diff --git a/deps/npm/node_modules/path-scurry/dist/mjs/package.json b/deps/npm/node_modules/path-scurry/dist/esm/package.json similarity index 100% rename from deps/npm/node_modules/path-scurry/dist/mjs/package.json rename to deps/npm/node_modules/path-scurry/dist/esm/package.json diff --git a/deps/npm/node_modules/path-scurry/package.json b/deps/npm/node_modules/path-scurry/package.json index af04f807fed2bc..90a4b468f04618 100644 --- a/deps/npm/node_modules/path-scurry/package.json +++ b/deps/npm/node_modules/path-scurry/package.json @@ -1,19 +1,20 @@ { "name": "path-scurry", - "version": "1.10.1", + "version": "1.10.2", "description": "walk paths fast and efficiently", "author": "Isaac Z. Schlueter (https://blog.izs.me)", - "main": "./dist/cjs/index.js", - "module": "./dist/mjs/index.js", + "main": "./dist/commonjs/index.js", + "type": "module", "exports": { + "./package.json": "./package.json", ".": { "import": { - "types": "./dist/mjs/index.d.ts", - "default": "./dist/mjs/index.js" + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" }, "require": { - "types": "./dist/cjs/index.d.ts", - "default": "./dist/cjs/index.js" + "types": "./dist/commonjs/index.d.ts", + "default": "./dist/commonjs/index.js" } } }, @@ -26,12 +27,11 @@ "postversion": "npm publish", "prepublishOnly": "git push origin --follow-tags", "preprepare": "rm -rf dist", - "prepare": "tsc -p tsconfig.json && tsc -p tsconfig-esm.json", - "postprepare": "bash ./scripts/fixup.sh", + "prepare": "tshy", "pretest": "npm run prepare", "presnap": "npm run prepare", - "test": "c8 tap", - "snap": "c8 tap", + "test": "tap", + "snap": "tap", "format": "prettier --write . --loglevel warn", "typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts", "bench": "bash ./scripts/bench.sh" @@ -47,28 +47,19 @@ "arrowParens": "avoid", "endOfLine": "lf" }, - "tap": { - "coverage": false, - "node-arg": [ - "--no-warnings", - "--loader", - "ts-node/esm" - ], - "ts": false - }, "devDependencies": { "@nodelib/fs.walk": "^1.2.8", - "@types/node": "^20.1.4", - "@types/tap": "^15.0.7", + "@types/node": "^20.11.30", "c8": "^7.12.0", "eslint-config-prettier": "^8.6.0", "mkdirp": "^3.0.0", "prettier": "^2.8.3", "rimraf": "^5.0.1", - "tap": "^16.3.4", - "ts-node": "^10.9.1", - "typedoc": "^0.23.24", - "typescript": "^5.0.4" + "tap": "^18.7.2", + "ts-node": "^10.9.2", + "tshy": "^1.12.0", + "typedoc": "^0.25.12", + "typescript": "^5.4.3" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -81,7 +72,14 @@ "url": "git+https://github.com/isaacs/path-scurry" }, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - } + }, + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts" + } + }, + "types": "./dist/commonjs/index.d.ts" } diff --git a/deps/npm/node_modules/postcss-selector-parser/package.json b/deps/npm/node_modules/postcss-selector-parser/package.json index d1f6be84cc5c77..0d1af5d373f20e 100644 --- a/deps/npm/node_modules/postcss-selector-parser/package.json +++ b/deps/npm/node_modules/postcss-selector-parser/package.json @@ -1,6 +1,6 @@ { "name": "postcss-selector-parser", - "version": "6.0.15", + "version": "6.0.16", "devDependencies": { "@babel/cli": "^7.11.6", "@babel/core": "^7.11.6", @@ -33,7 +33,8 @@ "!**/__tests__" ], "scripts": { - "pretest": "eslint src && tsc --noEmit postcss-selector-parser.d.ts", + "typecheck": "tsc --noEmit --strict postcss-selector-parser.d.ts postcss-selector-parser.test.ts", + "pretest": "eslint src && npm run typecheck", "prepare": "del-cli dist && BABEL_ENV=publish babel src --out-dir dist --ignore /__tests__/", "lintfix": "eslint --fix src", "report": "nyc report --reporter=html", diff --git a/deps/npm/node_modules/proc-log/lib/index.js b/deps/npm/node_modules/proc-log/lib/index.js index 7c5dfad3b7ba3f..86d90861078dab 100644 --- a/deps/npm/node_modules/proc-log/lib/index.js +++ b/deps/npm/node_modules/proc-log/lib/index.js @@ -1,23 +1,153 @@ -// emits 'log' events on the process -const LEVELS = [ - 'notice', - 'error', - 'warn', - 'info', - 'verbose', - 'http', - 'silly', - 'pause', - 'resume', -] - -const log = level => (...args) => process.emit('log', level, ...args) - -const logger = {} -for (const level of LEVELS) { - logger[level] = log(level) +const META = Symbol('proc-log.meta') +module.exports = { + META: META, + output: { + LEVELS: [ + 'standard', + 'error', + 'buffer', + 'flush', + ], + KEYS: { + standard: 'standard', + error: 'error', + buffer: 'buffer', + flush: 'flush', + }, + standard: function (...args) { + return process.emit('output', 'standard', ...args) + }, + error: function (...args) { + return process.emit('output', 'error', ...args) + }, + buffer: function (...args) { + return process.emit('output', 'buffer', ...args) + }, + flush: function (...args) { + return process.emit('output', 'flush', ...args) + }, + }, + log: { + LEVELS: [ + 'notice', + 'error', + 'warn', + 'info', + 'verbose', + 'http', + 'silly', + 'timing', + 'pause', + 'resume', + ], + KEYS: { + notice: 'notice', + error: 'error', + warn: 'warn', + info: 'info', + verbose: 'verbose', + http: 'http', + silly: 'silly', + timing: 'timing', + pause: 'pause', + resume: 'resume', + }, + error: function (...args) { + return process.emit('log', 'error', ...args) + }, + notice: function (...args) { + return process.emit('log', 'notice', ...args) + }, + warn: function (...args) { + return process.emit('log', 'warn', ...args) + }, + info: function (...args) { + return process.emit('log', 'info', ...args) + }, + verbose: function (...args) { + return process.emit('log', 'verbose', ...args) + }, + http: function (...args) { + return process.emit('log', 'http', ...args) + }, + silly: function (...args) { + return process.emit('log', 'silly', ...args) + }, + timing: function (...args) { + return process.emit('log', 'timing', ...args) + }, + pause: function () { + return process.emit('log', 'pause') + }, + resume: function () { + return process.emit('log', 'resume') + }, + }, + time: { + LEVELS: [ + 'start', + 'end', + ], + KEYS: { + start: 'start', + end: 'end', + }, + start: function (name, fn) { + process.emit('time', 'start', name) + function end () { + return process.emit('time', 'end', name) + } + if (typeof fn === 'function') { + const res = fn() + if (res && res.finally) { + return res.finally(end) + } + end() + return res + } + return end + }, + end: function (name) { + return process.emit('time', 'end', name) + }, + }, + input: { + LEVELS: [ + 'start', + 'end', + 'read', + ], + KEYS: { + start: 'start', + end: 'end', + read: 'read', + }, + start: function (fn) { + process.emit('input', 'start') + function end () { + return process.emit('input', 'end') + } + if (typeof fn === 'function') { + const res = fn() + if (res && res.finally) { + return res.finally(end) + } + end() + return res + } + return end + }, + end: function () { + return process.emit('input', 'end') + }, + read: function (...args) { + let resolve, reject + const promise = new Promise((_resolve, _reject) => { + resolve = _resolve + reject = _reject + }) + process.emit('input', 'read', resolve, reject, ...args) + return promise + }, + }, } - -logger.LEVELS = LEVELS - -module.exports = logger diff --git a/deps/npm/node_modules/proc-log/package.json b/deps/npm/node_modules/proc-log/package.json index d335fa965ace51..4ab89102ecc9b5 100644 --- a/deps/npm/node_modules/proc-log/package.json +++ b/deps/npm/node_modules/proc-log/package.json @@ -1,6 +1,6 @@ { "name": "proc-log", - "version": "3.0.0", + "version": "4.2.0", "files": [ "bin/", "lib/" @@ -18,14 +18,14 @@ "snap": "tap", "posttest": "npm run lint", "postsnap": "eslint index.js test/*.js --fix", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "postlint": "template-oss-check", "lintfix": "npm run lint -- --fix", "template-oss-apply": "template-oss-apply --force" }, "devDependencies": { - "@npmcli/eslint-config": "^3.0.1", - "@npmcli/template-oss": "4.5.1", + "@npmcli/eslint-config": "^4.0.0", + "@npmcli/template-oss": "4.21.3", "tap": "^16.0.1" }, "engines": { @@ -33,7 +33,8 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.5.1" + "version": "4.21.3", + "publish": true }, "tap": { "nyc-arg": [ diff --git a/deps/npm/node_modules/color-support/LICENSE b/deps/npm/node_modules/proggy/LICENSE similarity index 93% rename from deps/npm/node_modules/color-support/LICENSE rename to deps/npm/node_modules/proggy/LICENSE index 19129e315fe593..83837797202b70 100644 --- a/deps/npm/node_modules/color-support/LICENSE +++ b/deps/npm/node_modules/proggy/LICENSE @@ -1,6 +1,6 @@ The ISC License -Copyright (c) Isaac Z. Schlueter and Contributors +Copyright (c) GitHub, Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/deps/npm/node_modules/proggy/lib/client.js b/deps/npm/node_modules/proggy/lib/client.js new file mode 100644 index 00000000000000..2eafb9c75addc2 --- /dev/null +++ b/deps/npm/node_modules/proggy/lib/client.js @@ -0,0 +1,114 @@ +const EE = require('events') +const onProgress = Symbol('onProgress') +const bars = Symbol('bars') +const listener = Symbol('listener') +const normData = Symbol('normData') +class Client extends EE { + constructor ({ normalize = false, stopOnDone = false } = {}) { + super() + this.normalize = !!normalize + this.stopOnDone = !!stopOnDone + this[bars] = new Map() + this[listener] = null + } + + get size () { + return this[bars].size + } + + get listening () { + return !!this[listener] + } + + addListener (...args) { + return this.on(...args) + } + + on (ev, ...args) { + if (ev === 'progress' && !this[listener]) { + this.start() + } + return super.on(ev, ...args) + } + + off (ev, ...args) { + return this.removeListener(ev, ...args) + } + + removeListener (ev, ...args) { + const ret = super.removeListener(ev, ...args) + if (ev === 'progress' && this.listeners(ev).length === 0) { + this.stop() + } + return ret + } + + stop () { + if (this[listener]) { + process.removeListener('progress', this[listener]) + this[listener] = null + } + } + + start () { + if (!this[listener]) { + this[listener] = (...args) => this[onProgress](...args) + process.on('progress', this[listener]) + } + } + + [onProgress] (key, data) { + data = this[normData](key, data) + if (!this[bars].has(key)) { + this.emit('bar', key, data) + } + this[bars].set(key, data) + this.emit('progress', key, data) + if (data.done) { + this[bars].delete(key) + this.emit('barDone', key, data) + if (this.size === 0) { + if (this.stopOnDone) { + this.stop() + } + this.emit('done') + } + } + } + + [normData] (key, data) { + const actualValue = data.value + const actualTotal = data.total + let value = actualValue + let total = actualTotal + const done = data.done || value >= total + if (this.normalize) { + const bar = this[bars].get(key) + total = 100 + if (done) { + value = 100 + } else { + // show value as a portion of 100 + const pct = 100 * actualValue / actualTotal + if (bar) { + // don't ever go backwards, and don't stand still + // move at least 1% of the remaining value if it wouldn't move. + value = (pct > bar.value) ? pct + : (100 - bar.value) / 100 + bar.value + } + } + } + // include the key + return { + ...data, + key, + name: data.name || key, + value, + total, + actualValue, + actualTotal, + done, + } + } +} +module.exports = Client diff --git a/deps/npm/node_modules/proggy/lib/index.js b/deps/npm/node_modules/proggy/lib/index.js new file mode 100644 index 00000000000000..834948b4ff8603 --- /dev/null +++ b/deps/npm/node_modules/proggy/lib/index.js @@ -0,0 +1,15 @@ +exports.Client = require('./client.js') +exports.Tracker = require('./tracker.js') + +const trackers = new Map() +exports.createTracker = (name, key, total) => { + const tracker = new exports.Tracker(name, key, total) + if (trackers.has(tracker.key)) { + const msg = `proggy: duplicate progress id ${JSON.stringify(tracker.key)}` + throw new Error(msg) + } + trackers.set(tracker.key, tracker) + tracker.on('done', () => trackers.delete(tracker.key)) + return tracker +} +exports.createClient = (options = {}) => new exports.Client(options) diff --git a/deps/npm/node_modules/proggy/lib/tracker.js b/deps/npm/node_modules/proggy/lib/tracker.js new file mode 100644 index 00000000000000..56c78d9434dc7c --- /dev/null +++ b/deps/npm/node_modules/proggy/lib/tracker.js @@ -0,0 +1,68 @@ +// The tracker class is intentionally as naive as possible. it is just +// an ergonomic wrapper around process.emit('progress', ...) +const EE = require('events') +class Tracker extends EE { + constructor (name, key, total) { + super() + if (!name) { + throw new Error('proggy: Tracker needs a name') + } + + if (typeof key === 'number' && !total) { + total = key + key = null + } + + if (!total) { + total = 100 + } + + if (!key) { + key = name + } + + this.done = false + this.name = name + this.key = key + this.value = 0 + this.total = total + } + + finish (metadata = {}) { + this.update(this.total, this.total, metadata) + } + + update (value, total, metadata) { + if (!metadata) { + if (total && typeof total === 'object') { + metadata = total + } else { + metadata = {} + } + } + if (typeof total !== 'number') { + total = this.total + } + + if (this.done) { + const msg = `proggy: updating completed tracker: ${JSON.stringify(this.key)}` + throw new Error(msg) + } + this.value = value + this.total = total + const done = this.value >= this.total + process.emit('progress', this.key, { + ...metadata, + name: this.name, + key: this.key, + value, + total, + done, + }) + if (done) { + this.done = true + this.emit('done') + } + } +} +module.exports = Tracker diff --git a/deps/npm/node_modules/are-we-there-yet/package.json b/deps/npm/node_modules/proggy/package.json similarity index 53% rename from deps/npm/node_modules/are-we-there-yet/package.json rename to deps/npm/node_modules/proggy/package.json index f072a21abb444b..4940fc9d002a64 100644 --- a/deps/npm/node_modules/are-we-there-yet/package.json +++ b/deps/npm/node_modules/proggy/package.json @@ -1,53 +1,48 @@ { - "name": "are-we-there-yet", - "version": "4.0.2", - "description": "Keep track of the overall completion of many disparate processes", + "name": "proggy", + "version": "2.0.0", + "files": [ + "bin/", + "lib/" + ], "main": "lib/index.js", + "description": "Progress bar updates at a distance", + "repository": { + "type": "git", + "url": "https://github.com/npm/proggy.git" + }, + "author": "GitHub Inc.", + "license": "ISC", "scripts": { "test": "tap", - "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", - "lintfix": "npm run lint -- --fix", "posttest": "npm run lint", - "postsnap": "npm run lintfix --", "snap": "tap", + "postsnap": "eslint lib test --fix", + "lint": "eslint \"**/*.js\"", "postlint": "template-oss-check", + "lintfix": "npm run lint -- --fix", "template-oss-apply": "template-oss-apply --force" }, - "repository": { - "type": "git", - "url": "https://github.com/npm/are-we-there-yet.git" - }, - "author": "GitHub Inc.", - "license": "ISC", - "bugs": { - "url": "https://github.com/npm/are-we-there-yet/issues" - }, - "homepage": "https://github.com/npm/are-we-there-yet", "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.21.3", + "@npmcli/eslint-config": "^3.0.1", + "@npmcli/template-oss": "4.5.1", + "chalk": "^4.1.2", + "cli-progress": "^3.10.0", + "npmlog": "^6.0.1", "tap": "^16.0.1" }, - "files": [ - "bin/", - "lib/" - ], - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, "tap": { - "branches": 68, - "statements": 92, - "functions": 86, - "lines": 92, + "coverage-map": "map.js", "nyc-arg": [ "--exclude", "tap-snapshots/**" ] }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.21.3", - "publish": true + "version": "4.5.1" } } diff --git a/deps/npm/node_modules/promzard/lib/index.js b/deps/npm/node_modules/promzard/lib/index.js index 2244cbbbacdb02..52c8a3c828313d 100644 --- a/deps/npm/node_modules/promzard/lib/index.js +++ b/deps/npm/node_modules/promzard/lib/index.js @@ -4,7 +4,7 @@ const { promisify } = require('util') const { randomBytes } = require('crypto') const { Module } = require('module') const { dirname, basename } = require('path') -const read = require('read') +const { read } = require('read') const files = {} diff --git a/deps/npm/node_modules/promzard/package.json b/deps/npm/node_modules/promzard/package.json index a48764dd5441b8..a4253193232b87 100644 --- a/deps/npm/node_modules/promzard/package.json +++ b/deps/npm/node_modules/promzard/package.json @@ -2,23 +2,23 @@ "author": "GitHub Inc.", "name": "promzard", "description": "prompting wizardly", - "version": "1.0.0", + "version": "1.0.1", "repository": { "url": "https://github.com/npm/promzard.git", "type": "git" }, "dependencies": { - "read": "^2.0.0" + "read": "^3.0.1" }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.11.0", + "@npmcli/template-oss": "4.21.3", "tap": "^16.3.0" }, "main": "lib/index.js", "scripts": { "test": "tap", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "postlint": "template-oss-check", "template-oss-apply": "template-oss-apply --force", "lintfix": "npm run lint -- --fix", @@ -35,7 +35,8 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.11.0" + "version": "4.21.3", + "publish": true }, "tap": { "jobs": 1, diff --git a/deps/npm/node_modules/read-package-json/LICENSE b/deps/npm/node_modules/read-package-json/LICENSE deleted file mode 100644 index 052085c436514a..00000000000000 --- a/deps/npm/node_modules/read-package-json/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) Isaac Z. Schlueter - -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. diff --git a/deps/npm/node_modules/read-package-json/lib/read-json.js b/deps/npm/node_modules/read-package-json/lib/read-json.js deleted file mode 100644 index d35f09ebd208f9..00000000000000 --- a/deps/npm/node_modules/read-package-json/lib/read-json.js +++ /dev/null @@ -1,589 +0,0 @@ -var fs = require('fs') - -var path = require('path') - -var { glob } = require('glob') -var normalizeData = require('normalize-package-data') -var safeJSON = require('json-parse-even-better-errors') -var util = require('util') -var normalizePackageBin = require('npm-normalize-package-bin') - -module.exports = readJson - -// put more stuff on here to customize. -readJson.extraSet = [ - bundleDependencies, - gypfile, - serverjs, - scriptpath, - authors, - readme, - mans, - bins, - githead, - fillTypes, -] - -var typoWarned = {} -var cache = {} - -function readJson (file, log_, strict_, cb_) { - var log, strict, cb - for (var i = 1; i < arguments.length - 1; i++) { - if (typeof arguments[i] === 'boolean') { - strict = arguments[i] - } else if (typeof arguments[i] === 'function') { - log = arguments[i] - } - } - - if (!log) { - log = function () {} - } - cb = arguments[arguments.length - 1] - - readJson_(file, log, strict, cb) -} - -function readJson_ (file, log, strict, cb) { - fs.readFile(file, 'utf8', function (er, d) { - parseJson(file, er, d, log, strict, cb) - }) -} - -function stripBOM (content) { - // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) - // because the buffer-to-string conversion in `fs.readFileSync()` - // translates it to FEFF, the UTF-16 BOM. - if (content.charCodeAt(0) === 0xFEFF) { - content = content.slice(1) - } - return content -} - -function jsonClone (obj) { - if (obj == null) { - return obj - } else if (Array.isArray(obj)) { - var newarr = new Array(obj.length) - for (var ii in obj) { - newarr[ii] = jsonClone(obj[ii]) - } - return newarr - } else if (typeof obj === 'object') { - var newobj = {} - for (var kk in obj) { - newobj[kk] = jsonClone(obj[kk]) - } - return newobj - } else { - return obj - } -} - -function parseJson (file, er, d, log, strict, cb) { - if (er && er.code === 'ENOENT') { - return fs.stat(path.dirname(file), function (err, stat) { - if (!err && stat && !stat.isDirectory()) { - // ENOTDIR isn't used on Windows, but npm expects it. - er = Object.create(er) - er.code = 'ENOTDIR' - return cb(er) - } else { - return indexjs(file, er, log, strict, cb) - } - }) - } - if (er) { - return cb(er) - } - - if (cache[d]) { - return cb(null, jsonClone(cache[d])) - } - - var data - - try { - data = safeJSON(stripBOM(d)) - for (var key in data) { - if (/^_/.test(key)) { - delete data[key] - } - } - } catch (jsonErr) { - data = parseIndex(d) - if (!data) { - return cb(parseError(jsonErr, file)) - } - } - extrasCached(file, d, data, log, strict, cb) -} - -function extrasCached (file, d, data, log, strict, cb) { - extras(file, data, log, strict, function (err, extrasData) { - if (!err) { - cache[d] = jsonClone(extrasData) - } - cb(err, extrasData) - }) -} - -function indexjs (file, er, log, strict, cb) { - if (path.basename(file) === 'index.js') { - return cb(er) - } - - var index = path.resolve(path.dirname(file), 'index.js') - fs.readFile(index, 'utf8', function (er2, d) { - if (er2) { - return cb(er) - } - - if (cache[d]) { - return cb(null, cache[d]) - } - - var data = parseIndex(d) - if (!data) { - return cb(er) - } - - extrasCached(file, d, data, log, strict, cb) - }) -} - -readJson.extras = extras -function extras (file, data, log_, strict_, cb_) { - var log, strict, cb - for (var i = 2; i < arguments.length - 1; i++) { - if (typeof arguments[i] === 'boolean') { - strict = arguments[i] - } else if (typeof arguments[i] === 'function') { - log = arguments[i] - } - } - - if (!log) { - log = function () {} - } - cb = arguments[i] - - var set = readJson.extraSet - var n = set.length - var errState = null - set.forEach(function (fn) { - fn(file, data, then) - }) - - function then (er) { - if (errState) { - return - } - if (er) { - return cb(errState = er) - } - if (--n > 0) { - return - } - final(file, data, log, strict, cb) - } -} - -function scriptpath (file, data, cb) { - if (!data.scripts) { - return cb(null, data) - } - var k = Object.keys(data.scripts) - k.forEach(scriptpath_, data.scripts) - cb(null, data) -} - -function scriptpath_ (key) { - var s = this[key] - // This is never allowed, and only causes problems - if (typeof s !== 'string') { - return delete this[key] - } - - var spre = /^(\.[/\\])?node_modules[/\\].bin[\\/]/ - if (s.match(spre)) { - this[key] = this[key].replace(spre, '') - } -} - -function gypfile (file, data, cb) { - var dir = path.dirname(file) - var s = data.scripts || {} - if (s.install || s.preinstall) { - return cb(null, data) - } - - if (data.gypfile === false) { - return cb(null, data) - } - glob('*.gyp', { cwd: dir }) - .then(files => gypfile_(file, data, files, cb)) - .catch(er => cb(er)) -} - -function gypfile_ (file, data, files, cb) { - if (!files.length) { - return cb(null, data) - } - var s = data.scripts || {} - s.install = 'node-gyp rebuild' - data.scripts = s - data.gypfile = true - return cb(null, data) -} - -function serverjs (file, data, cb) { - var dir = path.dirname(file) - var s = data.scripts || {} - if (s.start) { - return cb(null, data) - } - fs.access(path.join(dir, 'server.js'), (err) => { - if (!err) { - s.start = 'node server.js' - data.scripts = s - } - return cb(null, data) - }) -} - -function authors (file, data, cb) { - if (data.contributors) { - return cb(null, data) - } - var af = path.resolve(path.dirname(file), 'AUTHORS') - fs.readFile(af, 'utf8', function (er, ad) { - // ignore error. just checking it. - if (er) { - return cb(null, data) - } - authors_(file, data, ad, cb) - }) -} - -function authors_ (file, data, ad, cb) { - ad = ad.split(/\r?\n/g).map(function (line) { - return line.replace(/^\s*#.*$/, '').trim() - }).filter(function (line) { - return line - }) - data.contributors = ad - return cb(null, data) -} - -function readme (file, data, cb) { - if (data.readme) { - return cb(null, data) - } - var dir = path.dirname(file) - var globOpts = { cwd: dir, nocase: true, mark: true } - glob('{README,README.*}', globOpts) - .then(files => { - // don't accept directories. - files = files.filter(function (filtered) { - return !filtered.match(/\/$/) - }) - if (!files.length) { - return cb() - } - var fn = preferMarkdownReadme(files) - var rm = path.resolve(dir, fn) - return readme_(file, data, rm, cb) - }) - .catch(er => cb(er)) -} - -function preferMarkdownReadme (files) { - var fallback = 0 - var re = /\.m?a?r?k?d?o?w?n?$/i - for (var i = 0; i < files.length; i++) { - if (files[i].match(re)) { - return files[i] - } else if (files[i].match(/README$/)) { - fallback = i - } - } - // prefer README.md, followed by README; otherwise, return - // the first filename (which could be README) - return files[fallback] -} - -function readme_ (file, data, rm, cb) { - var rmfn = path.basename(rm) - fs.readFile(rm, 'utf8', function (er, rmData) { - // maybe not readable, or something. - if (er) { - return cb() - } - data.readme = rmData - data.readmeFilename = rmfn - return cb(er, data) - }) -} - -function mans (file, data, cb) { - let cwd = data.directories && data.directories.man - if (data.man || !cwd) { - return cb(null, data) - } - const dirname = path.dirname(file) - cwd = path.resolve(path.dirname(file), cwd) - glob('**/*.[0-9]', { cwd }) - .then(mansGlob => { - data.man = mansGlob.map(man => - path.relative(dirname, path.join(cwd, man)).split(path.sep).join('/') - ) - return cb(null, data) - }) - .catch(er => cb(er)) -} - -function bins (file, data, cb) { - data = normalizePackageBin(data) - - var m = data.directories && data.directories.bin - if (data.bin || !m) { - return cb(null, data) - } - - m = path.resolve(path.dirname(file), path.join('.', path.join('/', m))) - glob('**', { cwd: m }) - .then(binsGlob => bins_(file, data, binsGlob, cb)) - .catch(er => cb(er)) -} - -function bins_ (file, data, binsGlob, cb) { - var m = (data.directories && data.directories.bin) || '.' - data.bin = binsGlob.reduce(function (acc, mf) { - if (mf && mf.charAt(0) !== '.') { - var f = path.basename(mf) - acc[f] = path.join(m, mf) - } - return acc - }, {}) - return cb(null, normalizePackageBin(data)) -} - -function bundleDependencies (file, data, cb) { - var bd = 'bundleDependencies' - var bdd = 'bundledDependencies' - // normalize key name - if (data[bdd] !== undefined) { - if (data[bd] === undefined) { - data[bd] = data[bdd] - } - delete data[bdd] - } - if (data[bd] === false) { - delete data[bd] - } else if (data[bd] === true) { - data[bd] = Object.keys(data.dependencies || {}) - } else if (data[bd] !== undefined && !Array.isArray(data[bd])) { - delete data[bd] - } - return cb(null, data) -} - -function githead (file, data, cb) { - if (data.gitHead) { - return cb(null, data) - } - var dir = path.dirname(file) - var head = path.resolve(dir, '.git/HEAD') - fs.readFile(head, 'utf8', function (er, headData) { - if (er) { - var parent = path.dirname(dir) - if (parent === dir) { - return cb(null, data) - } - return githead(dir, data, cb) - } - githead_(data, dir, headData, cb) - }) -} - -function githead_ (data, dir, head, cb) { - if (!head.match(/^ref: /)) { - data.gitHead = head.trim() - return cb(null, data) - } - var headRef = head.replace(/^ref: /, '').trim() - var headFile = path.resolve(dir, '.git', headRef) - fs.readFile(headFile, 'utf8', function (er, headData) { - if (er || !headData) { - var packFile = path.resolve(dir, '.git/packed-refs') - return fs.readFile(packFile, 'utf8', function (readFileErr, refs) { - if (readFileErr || !refs) { - return cb(null, data) - } - refs = refs.split('\n') - for (var i = 0; i < refs.length; i++) { - var match = refs[i].match(/^([0-9a-f]{40}) (.+)$/) - if (match && match[2].trim() === headRef) { - data.gitHead = match[1] - break - } - } - return cb(null, data) - }) - } - headData = headData.replace(/^ref: /, '').trim() - data.gitHead = headData - return cb(null, data) - }) -} - -/** - * Warn if the bin references don't point to anything. This might be better in - * normalize-package-data if it had access to the file path. - */ -function checkBinReferences_ (file, data, warn, cb) { - if (!(data.bin instanceof Object)) { - return cb() - } - - var keys = Object.keys(data.bin) - var keysLeft = keys.length - if (!keysLeft) { - return cb() - } - - function handleExists (relName, result) { - keysLeft-- - if (!result) { - warn('No bin file found at ' + relName) - } - if (!keysLeft) { - cb() - } - } - - keys.forEach(function (key) { - var dirName = path.dirname(file) - var relName = data.bin[key] - /* istanbul ignore if - impossible, bins have been normalized */ - if (typeof relName !== 'string') { - var msg = 'Bin filename for ' + key + - ' is not a string: ' + util.inspect(relName) - warn(msg) - delete data.bin[key] - handleExists(relName, true) - return - } - var binPath = path.resolve(dirName, relName) - fs.stat(binPath, (err) => handleExists(relName, !err)) - }) -} - -function final (file, data, log, strict, cb) { - var pId = makePackageId(data) - - function warn (msg) { - if (typoWarned[pId]) { - return - } - if (log) { - log('package.json', pId, msg) - } - } - - try { - normalizeData(data, warn, strict) - } catch (error) { - return cb(error) - } - - checkBinReferences_(file, data, warn, function () { - typoWarned[pId] = true - cb(null, data) - }) -} - -function fillTypes (file, data, cb) { - var index = data.main || 'index.js' - - if (typeof index !== 'string') { - return cb(new TypeError('The "main" attribute must be of type string.')) - } - - // TODO exports is much more complicated than this in verbose format - // We need to support for instance - - // "exports": { - // ".": [ - // { - // "default": "./lib/npm.js" - // }, - // "./lib/npm.js" - // ], - // "./package.json": "./package.json" - // }, - // as well as conditional exports - - // if (data.exports && typeof data.exports === 'string') { - // index = data.exports - // } - - // if (data.exports && data.exports['.']) { - // index = data.exports['.'] - // if (typeof index !== 'string') { - // } - // } - - var extless = - path.join(path.dirname(index), path.basename(index, path.extname(index))) - var dts = `./${extless}.d.ts` - var dtsPath = path.join(path.dirname(file), dts) - var hasDTSFields = 'types' in data || 'typings' in data - if (!hasDTSFields && fs.existsSync(dtsPath)) { - data.types = dts.split(path.sep).join('/') - } - - cb(null, data) -} - -function makePackageId (data) { - var name = cleanString(data.name) - var ver = cleanString(data.version) - return name + '@' + ver -} - -function cleanString (str) { - return (!str || typeof (str) !== 'string') ? '' : str.trim() -} - -// /**package { "name": "foo", "version": "1.2.3", ... } **/ -function parseIndex (data) { - data = data.split(/^\/\*\*package(?:\s|$)/m) - - if (data.length < 2) { - return null - } - data = data[1] - data = data.split(/\*\*\/$/m) - - if (data.length < 2) { - return null - } - data = data[0] - data = data.replace(/^\s*\*/mg, '') - - try { - return safeJSON(data) - } catch (er) { - return null - } -} - -function parseError (ex, file) { - var e = new Error('Failed to parse json\n' + ex.message) - e.code = 'EJSONPARSE' - e.path = file - return e -} diff --git a/deps/npm/node_modules/read-package-json/package.json b/deps/npm/node_modules/read-package-json/package.json deleted file mode 100644 index 01061f2bc27921..00000000000000 --- a/deps/npm/node_modules/read-package-json/package.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "name": "read-package-json", - "version": "7.0.0", - "author": "GitHub Inc.", - "description": "The thing npm uses to read package.json files with semantics and defaults and validation", - "repository": { - "type": "git", - "url": "https://github.com/npm/read-package-json.git" - }, - "main": "lib/read-json.js", - "scripts": { - "prerelease": "npm t", - "postrelease": "npm publish && git push --follow-tags", - "release": "standard-version -s", - "test": "tap", - "npmclilint": "npmcli-lint", - "lint": "eslint \"**/*.js\"", - "lintfix": "npm run lint -- --fix", - "posttest": "npm run lint", - "postsnap": "npm run lintfix --", - "postlint": "template-oss-check", - "snap": "tap", - "template-oss-apply": "template-oss-apply --force" - }, - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.18.0", - "tap": "^16.0.1" - }, - "license": "ISC", - "files": [ - "bin/", - "lib/" - ], - "engines": { - "node": "^16.14.0 || >=18.0.0" - }, - "tap": { - "branches": 73, - "functions": 77, - "lines": 77, - "statements": 77, - "nyc-arg": [ - "--exclude", - "tap-snapshots/**" - ] - }, - "templateOSS": { - "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.18.0", - "publish": "true", - "ciVersions": [ - "16.14.0", - "16.x", - "18.0.0", - "18.x" - ] - } -} diff --git a/deps/npm/node_modules/read/dist/commonjs/package.json b/deps/npm/node_modules/read/dist/commonjs/package.json new file mode 100644 index 00000000000000..5bbefffbabee39 --- /dev/null +++ b/deps/npm/node_modules/read/dist/commonjs/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/deps/npm/node_modules/read/dist/commonjs/read.js b/deps/npm/node_modules/read/dist/commonjs/read.js new file mode 100644 index 00000000000000..bab433d8a1155f --- /dev/null +++ b/deps/npm/node_modules/read/dist/commonjs/read.js @@ -0,0 +1,95 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.read = void 0; +const mute_stream_1 = __importDefault(require("mute-stream")); +const readline_1 = require("readline"); +async function read({ default: def, input = process.stdin, output = process.stdout, completer, prompt = '', silent, timeout, edit, terminal, replace, }) { + if (typeof def !== 'undefined' && + typeof def !== 'string' && + typeof def !== 'number') { + throw new Error('default value must be string or number'); + } + let editDef = false; + const defString = def?.toString(); + prompt = prompt.trim() + ' '; + terminal = !!(terminal || output.isTTY); + if (defString) { + if (silent) { + prompt += '(