d</code>.
         * @experimental
         */
        post(method: 'Debugger.getStackTrace', params?: Debugger.GetStackTraceParameterType, callback?: (err: Error | null, params: Debugger.GetStackTraceReturnType) => void): void;
        post(method: 'Debugger.getStackTrace', callback?: (err: Error | null, params: Debugger.GetStackTraceReturnType) => void): void;
        /**
         * Searches for given string in script content.
         */
        post(method: 'Debugger.searchInContent', params?: Debugger.SearchInContentParameterType, callback?: (err: Error | null, params: Debugger.SearchInContentReturnType) => void): void;
        post(method: 'Debugger.searchInContent', callback?: (err: Error | null, params: Debugger.SearchInContentReturnType) => void): void;
        /**
         * Edits JavaScript source live.
         */
        post(method: 'Debugger.setScriptSource', params?: Debugger.SetScriptSourceParameterType, callback?: (err: Error | null, params: Debugger.SetScriptSourceReturnType) => void): void;
        post(method: 'Debugger.setScriptSource', callback?: (err: Error | null, params: Debugger.SetScriptSourceReturnType) => void): void;
        /**
         * Restarts particular call frame from the beginning.
         */
        post(method: 'Debugger.restartFrame', params?: Debugger.RestartFrameParameterType, callback?: (err: Error | null, params: Debugger.RestartFrameReturnType) => void): void;
        post(method: 'Debugger.restartFrame', callback?: (err: Error | null, params: Debugger.RestartFrameReturnType) => void): void;
        /**
         * Returns source for the script with given id.
         */
        post(method: 'Debugger.getScriptSource', params?: Debugger.GetScriptSourceParameterType, callback?: (err: Error | null, params: Debugger.GetScriptSourceReturnType) => void): void;
        post(method: 'Debugger.getScriptSource', callback?: (err: Error | null, params: Debugger.GetScriptSourceReturnType) => void): void;
        /**
         * Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is <code>none</code>.
         */
        post(method: 'Debugger.setPauseOnExceptions', params?: Debugger.SetPauseOnExceptionsParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'Debugger.setPauseOnExceptions', callback?: (err: Error | null) => void): void;
        /**
         * Evaluates expression on a given call frame.
         */
        post(method: 'Debugger.evaluateOnCallFrame', params?: Debugger.EvaluateOnCallFrameParameterType, callback?: (err: Error | null, params: Debugger.EvaluateOnCallFrameReturnType) => void): void;
        post(method: 'Debugger.evaluateOnCallFrame', callback?: (err: Error | null, params: Debugger.EvaluateOnCallFrameReturnType) => void): void;
        /**
         * Changes value of variable in a callframe. Object-based scopes are not supported and must be mutated manually.
         */
        post(method: 'Debugger.setVariableValue', params?: Debugger.SetVariableValueParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'Debugger.setVariableValue', callback?: (err: Error | null) => void): void;
        /**
         * Changes return value in top frame. Available only at return break position.
         * @experimental
         */
        post(method: 'Debugger.setReturnValue', params?: Debugger.SetReturnValueParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'Debugger.setReturnValue', callback?: (err: Error | null) => void): void;
        /**
         * Enables or disables async call stacks tracking.
         */
        post(method: 'Debugger.setAsyncCallStackDepth', params?: Debugger.SetAsyncCallStackDepthParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'Debugger.setAsyncCallStackDepth', callback?: (err: Error | null) => void): void;
        /**
         * Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in scripts with url matching one of the patterns. VM will try to leave blackboxed script by performing 'step in' several times, finally resorting to 'step out' if unsuccessful.
         * @experimental
         */
        post(method: 'Debugger.setBlackboxPatterns', params?: Debugger.SetBlackboxPatternsParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'Debugger.setBlackboxPatterns', callback?: (err: Error | null) => void): void;
        /**
         * Makes backend skip steps in the script in blackboxed ranges. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. Positions array contains positions where blackbox state is changed. First interval isn't blackboxed. Array should be sorted.
         * @experimental
         */
        post(method: 'Debugger.setBlackboxedRanges', params?: Debugger.SetBlackboxedRangesParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'Debugger.setBlackboxedRanges', callback?: (err: Error | null) => void): void;
        /**
         * Enables console domain, sends the messages collected so far to the client by means of the <code>messageAdded</code> notification.
         */
        post(method: 'Console.enable', callback?: (err: Error | null) => void): void;
        /**
         * Disables console domain, prevents further console messages from being reported to the client.
         */
        post(method: 'Console.disable', callback?: (err: Error | null) => void): void;
        /**
         * Does nothing.
         */
        post(method: 'Console.clearMessages', callback?: (err: Error | null) => void): void;
        post(method: 'Profiler.enable', callback?: (err: Error | null) => void): void;
        post(method: 'Profiler.disable', callback?: (err: Error | null) => void): void;
        /**
         * Changes CPU profiler sampling interval. Must be called before CPU profiles recording started.
         */
        post(method: 'Profiler.setSamplingInterval', params?: Profiler.SetSamplingIntervalParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'Profiler.setSamplingInterval', callback?: (err: Error | null) => void): void;
        post(method: 'Profiler.start', callback?: (err: Error | null) => void): void;
        post(method: 'Profiler.stop', callback?: (err: Error | null, params: Profiler.StopReturnType) => void): void;
        /**
         * Enable precise code coverage. Coverage data for JavaScript executed before enabling precise code coverage may be incomplete. Enabling prevents running optimized code and resets execution counters.
         */
        post(method: 'Profiler.startPreciseCoverage', params?: Profiler.StartPreciseCoverageParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'Profiler.startPreciseCoverage', callback?: (err: Error | null) => void): void;
        /**
         * Disable precise code coverage. Disabling releases unnecessary execution count records and allows executing optimized code.
         */
        post(method: 'Profiler.stopPreciseCoverage', callback?: (err: Error | null) => void): void;
        /**
         * Collect coverage data for the current isolate, and resets execution counters. Precise code coverage needs to have started.
         */
        post(method: 'Profiler.takePreciseCoverage', callback?: (err: Error | null, params: Profiler.TakePreciseCoverageReturnType) => void): void;
        /**
         * Collect coverage data for the current isolate. The coverage data may be incomplete due to garbage collection.
         */
        post(method: 'Profiler.getBestEffortCoverage', callback?: (err: Error | null, params: Profiler.GetBestEffortCoverageReturnType) => void): void;
        post(method: 'HeapProfiler.enable', callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.disable', callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.startTrackingHeapObjects', params?: HeapProfiler.StartTrackingHeapObjectsParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.startTrackingHeapObjects', callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.stopTrackingHeapObjects', params?: HeapProfiler.StopTrackingHeapObjectsParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.stopTrackingHeapObjects', callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.takeHeapSnapshot', params?: HeapProfiler.TakeHeapSnapshotParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.takeHeapSnapshot', callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.collectGarbage', callback?: (err: Error | null) => void): void;
        post(
            method: 'HeapProfiler.getObjectByHeapObjectId',
            params?: HeapProfiler.GetObjectByHeapObjectIdParameterType,
            callback?: (err: Error | null, params: HeapProfiler.GetObjectByHeapObjectIdReturnType) => void
        ): void;
        post(method: 'HeapProfiler.getObjectByHeapObjectId', callback?: (err: Error | null, params: HeapProfiler.GetObjectByHeapObjectIdReturnType) => void): void;
        /**
         * Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions).
         */
        post(method: 'HeapProfiler.addInspectedHeapObject', params?: HeapProfiler.AddInspectedHeapObjectParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.addInspectedHeapObject', callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.getHeapObjectId', params?: HeapProfiler.GetHeapObjectIdParameterType, callback?: (err: Error | null, params: HeapProfiler.GetHeapObjectIdReturnType) => void): void;
        post(method: 'HeapProfiler.getHeapObjectId', callback?: (err: Error | null, params: HeapProfiler.GetHeapObjectIdReturnType) => void): void;
        post(method: 'HeapProfiler.startSampling', params?: HeapProfiler.StartSamplingParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.startSampling', callback?: (err: Error | null) => void): void;
        post(method: 'HeapProfiler.stopSampling', callback?: (err: Error | null, params: HeapProfiler.StopSamplingReturnType) => void): void;
        post(method: 'HeapProfiler.getSamplingProfile', callback?: (err: Error | null, params: HeapProfiler.GetSamplingProfileReturnType) => void): void;
        /**
         * Gets supported tracing categories.
         */
        post(method: 'NodeTracing.getCategories', callback?: (err: Error | null, params: NodeTracing.GetCategoriesReturnType) => void): void;
        /**
         * Start trace events collection.
         */
        post(method: 'NodeTracing.start', params?: NodeTracing.StartParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'NodeTracing.start', callback?: (err: Error | null) => void): void;
        /**
         * Stop trace events collection. Remaining collected events will be sent as a sequence of
         * dataCollected events followed by tracingComplete event.
         */
        post(method: 'NodeTracing.stop', callback?: (err: Error | null) => void): void;
        /**
         * Sends protocol message over session with given id.
         */
        post(method: 'NodeWorker.sendMessageToWorker', params?: NodeWorker.SendMessageToWorkerParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'NodeWorker.sendMessageToWorker', callback?: (err: Error | null) => void): void;
        /**
         * Instructs the inspector to attach to running workers. Will also attach to new workers
         * as they start
         */
        post(method: 'NodeWorker.enable', params?: NodeWorker.EnableParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'NodeWorker.enable', callback?: (err: Error | null) => void): void;
        /**
         * Detaches from all running workers and disables attaching to new workers as they are started.
         */
        post(method: 'NodeWorker.disable', callback?: (err: Error | null) => void): void;
        /**
         * Detached from the worker with given sessionId.
         */
        post(method: 'NodeWorker.detach', params?: NodeWorker.DetachParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'NodeWorker.detach', callback?: (err: Error | null) => void): void;
        /**
         * Disables network tracking, prevents network events from being sent to the client.
         */
        post(method: 'Network.disable', callback?: (err: Error | null) => void): void;
        /**
         * Enables network tracking, network events will now be delivered to the client.
         */
        post(method: 'Network.enable', callback?: (err: Error | null) => void): void;
        /**
         * Enable the NodeRuntime events except by `NodeRuntime.waitingForDisconnect`.
         */
        post(method: 'NodeRuntime.enable', callback?: (err: Error | null) => void): void;
        /**
         * Disable NodeRuntime events
         */
        post(method: 'NodeRuntime.disable', callback?: (err: Error | null) => void): void;
        /**
         * Enable the `NodeRuntime.waitingForDisconnect`.
         */
        post(method: 'NodeRuntime.notifyWhenWaitingForDisconnect', params?: NodeRuntime.NotifyWhenWaitingForDisconnectParameterType, callback?: (err: Error | null) => void): void;
        post(method: 'NodeRuntime.notifyWhenWaitingForDisconnect', callback?: (err: Error | null) => void): void;

        addListener(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        addListener(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        addListener(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        addListener(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        addListener(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        addListener(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        addListener(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        addListener(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        addListener(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        addListener(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        addListener(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        addListener(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        addListener(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        addListener(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        addListener(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        addListener(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        addListener(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        addListener(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        addListener(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        addListener(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        addListener(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        addListener(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        addListener(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        addListener(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        addListener(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        addListener(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        addListener(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        addListener(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        addListener(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        addListener(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        addListener(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        addListener(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        addListener(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
        emit(event: string | symbol, ...args: any[]): boolean;
        emit(event: 'inspectorNotification', message: InspectorNotification<object>): boolean;
        emit(event: 'Runtime.executionContextCreated', message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>): boolean;
        emit(event: 'Runtime.executionContextDestroyed', message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>): boolean;
        emit(event: 'Runtime.executionContextsCleared'): boolean;
        emit(event: 'Runtime.exceptionThrown', message: InspectorNotification<Runtime.ExceptionThrownEventDataType>): boolean;
        emit(event: 'Runtime.exceptionRevoked', message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>): boolean;
        emit(event: 'Runtime.consoleAPICalled', message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>): boolean;
        emit(event: 'Runtime.inspectRequested', message: InspectorNotification<Runtime.InspectRequestedEventDataType>): boolean;
        emit(event: 'Debugger.scriptParsed', message: InspectorNotification<Debugger.ScriptParsedEventDataType>): boolean;
        emit(event: 'Debugger.scriptFailedToParse', message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>): boolean;
        emit(event: 'Debugger.breakpointResolved', message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>): boolean;
        emit(event: 'Debugger.paused', message: InspectorNotification<Debugger.PausedEventDataType>): boolean;
        emit(event: 'Debugger.resumed'): boolean;
        emit(event: 'Console.messageAdded', message: InspectorNotification<Console.MessageAddedEventDataType>): boolean;
        emit(event: 'Profiler.consoleProfileStarted', message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>): boolean;
        emit(event: 'Profiler.consoleProfileFinished', message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>): boolean;
        emit(event: 'HeapProfiler.addHeapSnapshotChunk', message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>): boolean;
        emit(event: 'HeapProfiler.resetProfiles'): boolean;
        emit(event: 'HeapProfiler.reportHeapSnapshotProgress', message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>): boolean;
        emit(event: 'HeapProfiler.lastSeenObjectId', message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>): boolean;
        emit(event: 'HeapProfiler.heapStatsUpdate', message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>): boolean;
        emit(event: 'NodeTracing.dataCollected', message: InspectorNotification<NodeTracing.DataCollectedEventDataType>): boolean;
        emit(event: 'NodeTracing.tracingComplete'): boolean;
        emit(event: 'NodeWorker.attachedToWorker', message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>): boolean;
        emit(event: 'NodeWorker.detachedFromWorker', message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>): boolean;
        emit(event: 'NodeWorker.receivedMessageFromWorker', message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>): boolean;
        emit(event: 'Network.requestWillBeSent', message: InspectorNotification<Network.RequestWillBeSentEventDataType>): boolean;
        emit(event: 'Network.responseReceived', message: InspectorNotification<Network.ResponseReceivedEventDataType>): boolean;
        emit(event: 'Network.loadingFailed', message: InspectorNotification<Network.LoadingFailedEventDataType>): boolean;
        emit(event: 'Network.loadingFinished', message: InspectorNotification<Network.LoadingFinishedEventDataType>): boolean;
        emit(event: 'NodeRuntime.waitingForDisconnect'): boolean;
        emit(event: 'NodeRuntime.waitingForDebugger'): boolean;
        on(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        on(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        on(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        on(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        on(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        on(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        on(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        on(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        on(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        on(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        on(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        on(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        on(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        on(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        on(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        on(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        on(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        on(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        on(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        on(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        on(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        on(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        on(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        on(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        on(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        on(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        on(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        on(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        on(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        on(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        on(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        on(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        on(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
        once(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        once(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        once(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        once(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        once(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        once(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        once(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        once(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        once(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        once(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        once(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        once(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        once(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        once(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        once(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        once(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        once(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        once(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        once(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        once(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        once(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        once(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        once(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        once(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        once(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        once(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        once(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        once(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        once(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        once(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        once(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        once(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        once(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
        prependListener(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        prependListener(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        prependListener(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        prependListener(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        prependListener(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        prependListener(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        prependListener(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        prependListener(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        prependListener(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        prependListener(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        prependListener(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        prependListener(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        prependListener(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        prependListener(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        prependListener(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        prependListener(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        prependListener(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        prependListener(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        prependListener(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        prependListener(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        prependListener(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        prependListener(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        prependListener(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        prependListener(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        prependListener(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        prependListener(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        prependListener(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        prependListener(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        prependListener(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        prependListener(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        prependListener(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        prependListener(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        prependListener(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
        prependOnceListener(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        prependOnceListener(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        prependOnceListener(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        prependOnceListener(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        prependOnceListener(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        prependOnceListener(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        prependOnceListener(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        prependOnceListener(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        prependOnceListener(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        prependOnceListener(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        prependOnceListener(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        prependOnceListener(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        prependOnceListener(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        prependOnceListener(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        prependOnceListener(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        prependOnceListener(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        prependOnceListener(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        prependOnceListener(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        prependOnceListener(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        prependOnceListener(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        prependOnceListener(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        prependOnceListener(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        prependOnceListener(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        prependOnceListener(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        prependOnceListener(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        prependOnceListener(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        prependOnceListener(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        prependOnceListener(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        prependOnceListener(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        prependOnceListener(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        prependOnceListener(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        prependOnceListener(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        prependOnceListener(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
    }

    /**
     * Activate inspector on host and port. Equivalent to `node --inspect=[[host:]port]`, but can be done programmatically after node has
     * started.
     *
     * If wait is `true`, will block until a client has connected to the inspect port
     * and flow control has been passed to the debugger client.
     *
     * See the [security warning](https://nodejs.org/docs/latest-v22.x/api/cli.html#warning-binding-inspector-to-a-public-ipport-combination-is-insecure)
     * regarding the `host` parameter usage.
     * @param port Port to listen on for inspector connections. Defaults to what was specified on the CLI.
     * @param host Host to listen on for inspector connections. Defaults to what was specified on the CLI.
     * @param wait Block until a client has connected. Defaults to what was specified on the CLI.
     * @returns Disposable that calls `inspector.close()`.
     */
    function open(port?: number, host?: string, wait?: boolean): Disposable;

    /**
     * Deactivate the inspector. Blocks until there are no active connections.
     */
    function close(): void;

    /**
     * Return the URL of the active inspector, or `undefined` if there is none.
     *
     * ```console
     * $ node --inspect -p 'inspector.url()'
     * Debugger listening on ws://127.0.0.1:9229/166e272e-7a30-4d09-97ce-f1c012b43c34
     * For help, see: https://nodejs.org/en/docs/inspector
     * ws://127.0.0.1:9229/166e272e-7a30-4d09-97ce-f1c012b43c34
     *
     * $ node --inspect=localhost:3000 -p 'inspector.url()'
     * Debugger listening on ws://localhost:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a
     * For help, see: https://nodejs.org/en/docs/inspector
     * ws://localhost:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a
     *
     * $ node -p 'inspector.url()'
     * undefined
     * ```
     */
    function url(): string | undefined;

    /**
     * Blocks until a client (existing or connected later) has sent `Runtime.runIfWaitingForDebugger` command.
     *
     * An exception will be thrown if there is no active inspector.
     * @since v12.7.0
     */
    function waitForDebugger(): void;

    // These methods are exposed by the V8 inspector console API (inspector/v8-console.h).
    // The method signatures differ from those of the Node.js console, and are deliberately
    // typed permissively.
    interface InspectorConsole {
        debug(...data: any[]): void;
        error(...data: any[]): void;
        info(...data: any[]): void;
        log(...data: any[]): void;
        warn(...data: any[]): void;
        dir(...data: any[]): void;
        dirxml(...data: any[]): void;
        table(...data: any[]): void;
        trace(...data: any[]): void;
        group(...data: any[]): void;
        groupCollapsed(...data: any[]): void;
        groupEnd(...data: any[]): void;
        clear(...data: any[]): void;
        count(label?: any): void;
        countReset(label?: any): void;
        assert(value?: any, ...data: any[]): void;
        profile(label?: any): void;
        profileEnd(label?: any): void;
        time(label?: any): void;
        timeLog(label?: any): void;
        timeStamp(label?: any): void;
    }

    /**
     * An object to send messages to the remote inspector console.
     * @since v11.0.0
     */
    const console: InspectorConsole;

    // DevTools protocol event broadcast methods
    namespace Network {
        /**
         * This feature is only available with the `--experimental-network-inspection` flag enabled.
         *
         * Broadcasts the `Network.requestWillBeSent` event to connected frontends. This event indicates that
         * the application is about to send an HTTP request.
         * @since v22.6.0
         * @experimental
         */
        function requestWillBeSent(params: RequestWillBeSentEventDataType): void;
        /**
         * This feature is only available with the `--experimental-network-inspection` flag enabled.
         *
         * Broadcasts the `Network.responseReceived` event to connected frontends. This event indicates that
         * HTTP response is available.
         * @since v22.6.0
         * @experimental
         */
        function responseReceived(params: ResponseReceivedEventDataType): void;
        /**
         * This feature is only available with the `--experimental-network-inspection` flag enabled.
         *
         * Broadcasts the `Network.loadingFinished` event to connected frontends. This event indicates that
         * HTTP request has finished loading.
         * @since v22.6.0
         * @experimental
         */
        function loadingFinished(params: LoadingFinishedEventDataType): void;
        /**
         * This feature is only available with the `--experimental-network-inspection` flag enabled.
         *
         * Broadcasts the `Network.loadingFailed` event to connected frontends. This event indicates that
         * HTTP request has failed to load.
         * @since v22.7.0
         * @experimental
         */
        function loadingFailed(params: LoadingFailedEventDataType): void;
    }
}

/**
 * The `node:inspector` module provides an API for interacting with the V8
 * inspector.
 */
declare module 'node:inspector' {
    export * from 'inspector';
}

/**
 * The `node:inspector/promises` module provides an API for interacting with the V8
 * inspector.
 * @see [source](https://github.com/nodejs/node/blob/v22.x/lib/inspector/promises.js)
 * @since v19.0.0
 */
declare module 'inspector/promises' {
    import EventEmitter = require('node:events');
    import {
        open,
        close,
        url,
        waitForDebugger,
        console,
        InspectorNotification,
        Schema,
        Runtime,
        Debugger,
        Console,
        Profiler,
        HeapProfiler,
        NodeTracing,
        NodeWorker,
        Network,
        NodeRuntime,
    } from 'inspector';

    /**
     * The `inspector.Session` is used for dispatching messages to the V8 inspector
     * back-end and receiving message responses and notifications.
     * @since v19.0.0
     */
    class Session extends EventEmitter {
        /**
         * Create a new instance of the `inspector.Session` class.
         * The inspector session needs to be connected through `session.connect()` before the messages can be dispatched to the inspector backend.
         */
        constructor();

        /**
         * Connects a session to the inspector back-end.
         */
        connect(): void;

        /**
         * Connects a session to the inspector back-end.
         * An exception will be thrown if this API was not called on a Worker thread.
         */
        connectToMainThread(): void;

        /**
         * Immediately close the session. All pending message callbacks will be called with an error.
         * `session.connect()` will need to be called to be able to send messages again.
         * Reconnected session will lose all inspector state, such as enabled agents or configured breakpoints.
         */
        disconnect(): void;

        /**
         * Posts a message to the inspector back-end.
         *
         * ```js
         * import { Session } from 'node:inspector/promises';
         * try {
         *   const session = new Session();
         *   session.connect();
         *   const result = await session.post('Runtime.evaluate', { expression: '2 + 2' });
         *   console.log(result);
         * } catch (error) {
         *   console.error(error);
         * }
         * // Output: { result: { type: 'number', value: 4, description: '4' } }
         * ```
         *
         * The latest version of the V8 inspector protocol is published on the
         * [Chrome DevTools Protocol Viewer](https://chromedevtools.github.io/devtools-protocol/v8/).
         *
         * Node.js inspector supports all the Chrome DevTools Protocol domains declared
         * by V8. Chrome DevTools Protocol domain provides an interface for interacting
         * with one of the runtime agents used to inspect the application state and listen
         * to the run-time events.
         */
        post(method: string, params?: object): Promise<void>;
        /**
         * Returns supported domains.
         */
        post(method: 'Schema.getDomains'): Promise<Schema.GetDomainsReturnType>;
        /**
         * Evaluates expression on global object.
         */
        post(method: 'Runtime.evaluate', params?: Runtime.EvaluateParameterType): Promise<Runtime.EvaluateReturnType>;
        /**
         * Add handler to promise with given promise object id.
         */
        post(method: 'Runtime.awaitPromise', params?: Runtime.AwaitPromiseParameterType): Promise<Runtime.AwaitPromiseReturnType>;
        /**
         * Calls function with given declaration on the given object. Object group of the result is inherited from the target object.
         */
        post(method: 'Runtime.callFunctionOn', params?: Runtime.CallFunctionOnParameterType): Promise<Runtime.CallFunctionOnReturnType>;
        /**
         * Returns properties of a given object. Object group of the result is inherited from the target object.
         */
        post(method: 'Runtime.getProperties', params?: Runtime.GetPropertiesParameterType): Promise<Runtime.GetPropertiesReturnType>;
        /**
         * Releases remote object with given id.
         */
        post(method: 'Runtime.releaseObject', params?: Runtime.ReleaseObjectParameterType): Promise<void>;
        /**
         * Releases all remote objects that belong to a given group.
         */
        post(method: 'Runtime.releaseObjectGroup', params?: Runtime.ReleaseObjectGroupParameterType): Promise<void>;
        /**
         * Tells inspected instance to run if it was waiting for debugger to attach.
         */
        post(method: 'Runtime.runIfWaitingForDebugger'): Promise<void>;
        /**
         * Enables reporting of execution contexts creation by means of <code>executionContextCreated</code> event. When the reporting gets enabled the event will be sent immediately for each existing execution context.
         */
        post(method: 'Runtime.enable'): Promise<void>;
        /**
         * Disables reporting of execution contexts creation.
         */
        post(method: 'Runtime.disable'): Promise<void>;
        /**
         * Discards collected exceptions and console API calls.
         */
        post(method: 'Runtime.discardConsoleEntries'): Promise<void>;
        /**
         * @experimental
         */
        post(method: 'Runtime.setCustomObjectFormatterEnabled', params?: Runtime.SetCustomObjectFormatterEnabledParameterType): Promise<void>;
        /**
         * Compiles expression.
         */
        post(method: 'Runtime.compileScript', params?: Runtime.CompileScriptParameterType): Promise<Runtime.CompileScriptReturnType>;
        /**
         * Runs script with given id in a given context.
         */
        post(method: 'Runtime.runScript', params?: Runtime.RunScriptParameterType): Promise<Runtime.RunScriptReturnType>;
        post(method: 'Runtime.queryObjects', params?: Runtime.QueryObjectsParameterType): Promise<Runtime.QueryObjectsReturnType>;
        /**
         * Returns all let, const and class variables from global scope.
         */
        post(method: 'Runtime.globalLexicalScopeNames', params?: Runtime.GlobalLexicalScopeNamesParameterType): Promise<Runtime.GlobalLexicalScopeNamesReturnType>;
        /**
         * Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received.
         */
        post(method: 'Debugger.enable'): Promise<Debugger.EnableReturnType>;
        /**
         * Disables debugger for given page.
         */
        post(method: 'Debugger.disable'): Promise<void>;
        /**
         * Activates / deactivates all breakpoints on the page.
         */
        post(method: 'Debugger.setBreakpointsActive', params?: Debugger.SetBreakpointsActiveParameterType): Promise<void>;
        /**
         * Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc).
         */
        post(method: 'Debugger.setSkipAllPauses', params?: Debugger.SetSkipAllPausesParameterType): Promise<void>;
        /**
         * Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in <code>locations</code> property. Further matching script parsing will result in subsequent <code>breakpointResolved</code> events issued. This logical breakpoint will survive page reloads.
         */
        post(method: 'Debugger.setBreakpointByUrl', params?: Debugger.SetBreakpointByUrlParameterType): Promise<Debugger.SetBreakpointByUrlReturnType>;
        /**
         * Sets JavaScript breakpoint at a given location.
         */
        post(method: 'Debugger.setBreakpoint', params?: Debugger.SetBreakpointParameterType): Promise<Debugger.SetBreakpointReturnType>;
        /**
         * Removes JavaScript breakpoint.
         */
        post(method: 'Debugger.removeBreakpoint', params?: Debugger.RemoveBreakpointParameterType): Promise<void>;
        /**
         * Returns possible locations for breakpoint. scriptId in start and end range locations should be the same.
         */
        post(method: 'Debugger.getPossibleBreakpoints', params?: Debugger.GetPossibleBreakpointsParameterType): Promise<Debugger.GetPossibleBreakpointsReturnType>;
        /**
         * Continues execution until specific location is reached.
         */
        post(method: 'Debugger.continueToLocation', params?: Debugger.ContinueToLocationParameterType): Promise<void>;
        /**
         * @experimental
         */
        post(method: 'Debugger.pauseOnAsyncCall', params?: Debugger.PauseOnAsyncCallParameterType): Promise<void>;
        /**
         * Steps over the statement.
         */
        post(method: 'Debugger.stepOver'): Promise<void>;
        /**
         * Steps into the function call.
         */
        post(method: 'Debugger.stepInto', params?: Debugger.StepIntoParameterType): Promise<void>;
        /**
         * Steps out of the function call.
         */
        post(method: 'Debugger.stepOut'): Promise<void>;
        /**
         * Stops on the next JavaScript statement.
         */
        post(method: 'Debugger.pause'): Promise<void>;
        /**
         * This method is deprecated - use Debugger.stepInto with breakOnAsyncCall and Debugger.pauseOnAsyncTask instead. Steps into next scheduled async task if any is scheduled before next pause. Returns success when async task is actually scheduled, returns error if no task were scheduled or another scheduleStepIntoAsync was called.
         * @experimental
         */
        post(method: 'Debugger.scheduleStepIntoAsync'): Promise<void>;
        /**
         * Resumes JavaScript execution.
         */
        post(method: 'Debugger.resume'): Promise<void>;
        /**
         * Returns stack trace with given <code>stackTraceId</code>.
         * @experimental
         */
        post(method: 'Debugger.getStackTrace', params?: Debugger.GetStackTraceParameterType): Promise<Debugger.GetStackTraceReturnType>;
        /**
         * Searches for given string in script content.
         */
        post(method: 'Debugger.searchInContent', params?: Debugger.SearchInContentParameterType): Promise<Debugger.SearchInContentReturnType>;
        /**
         * Edits JavaScript source live.
         */
        post(method: 'Debugger.setScriptSource', params?: Debugger.SetScriptSourceParameterType): Promise<Debugger.SetScriptSourceReturnType>;
        /**
         * Restarts particular call frame from the beginning.
         */
        post(method: 'Debugger.restartFrame', params?: Debugger.RestartFrameParameterType): Promise<Debugger.RestartFrameReturnType>;
        /**
         * Returns source for the script with given id.
         */
        post(method: 'Debugger.getScriptSource', params?: Debugger.GetScriptSourceParameterType): Promise<Debugger.GetScriptSourceReturnType>;
        /**
         * Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is <code>none</code>.
         */
        post(method: 'Debugger.setPauseOnExceptions', params?: Debugger.SetPauseOnExceptionsParameterType): Promise<void>;
        /**
         * Evaluates expression on a given call frame.
         */
        post(method: 'Debugger.evaluateOnCallFrame', params?: Debugger.EvaluateOnCallFrameParameterType): Promise<Debugger.EvaluateOnCallFrameReturnType>;
        /**
         * Changes value of variable in a callframe. Object-based scopes are not supported and must be mutated manually.
         */
        post(method: 'Debugger.setVariableValue', params?: Debugger.SetVariableValueParameterType): Promise<void>;
        /**
         * Changes return value in top frame. Available only at return break position.
         * @experimental
         */
        post(method: 'Debugger.setReturnValue', params?: Debugger.SetReturnValueParameterType): Promise<void>;
        /**
         * Enables or disables async call stacks tracking.
         */
        post(method: 'Debugger.setAsyncCallStackDepth', params?: Debugger.SetAsyncCallStackDepthParameterType): Promise<void>;
        /**
         * Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in scripts with url matching one of the patterns. VM will try to leave blackboxed script by performing 'step in' several times, finally resorting to 'step out' if unsuccessful.
         * @experimental
         */
        post(method: 'Debugger.setBlackboxPatterns', params?: Debugger.SetBlackboxPatternsParameterType): Promise<void>;
        /**
         * Makes backend skip steps in the script in blackboxed ranges. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. Positions array contains positions where blackbox state is changed. First interval isn't blackboxed. Array should be sorted.
         * @experimental
         */
        post(method: 'Debugger.setBlackboxedRanges', params?: Debugger.SetBlackboxedRangesParameterType): Promise<void>;
        /**
         * Enables console domain, sends the messages collected so far to the client by means of the <code>messageAdded</code> notification.
         */
        post(method: 'Console.enable'): Promise<void>;
        /**
         * Disables console domain, prevents further console messages from being reported to the client.
         */
        post(method: 'Console.disable'): Promise<void>;
        /**
         * Does nothing.
         */
        post(method: 'Console.clearMessages'): Promise<void>;
        post(method: 'Profiler.enable'): Promise<void>;
        post(method: 'Profiler.disable'): Promise<void>;
        /**
         * Changes CPU profiler sampling interval. Must be called before CPU profiles recording started.
         */
        post(method: 'Profiler.setSamplingInterval', params?: Profiler.SetSamplingIntervalParameterType): Promise<void>;
        post(method: 'Profiler.start'): Promise<void>;
        post(method: 'Profiler.stop'): Promise<Profiler.StopReturnType>;
        /**
         * Enable precise code coverage. Coverage data for JavaScript executed before enabling precise code coverage may be incomplete. Enabling prevents running optimized code and resets execution counters.
         */
        post(method: 'Profiler.startPreciseCoverage', params?: Profiler.StartPreciseCoverageParameterType): Promise<void>;
        /**
         * Disable precise code coverage. Disabling releases unnecessary execution count records and allows executing optimized code.
         */
        post(method: 'Profiler.stopPreciseCoverage'): Promise<void>;
        /**
         * Collect coverage data for the current isolate, and resets execution counters. Precise code coverage needs to have started.
         */
        post(method: 'Profiler.takePreciseCoverage'): Promise<Profiler.TakePreciseCoverageReturnType>;
        /**
         * Collect coverage data for the current isolate. The coverage data may be incomplete due to garbage collection.
         */
        post(method: 'Profiler.getBestEffortCoverage'): Promise<Profiler.GetBestEffortCoverageReturnType>;
        post(method: 'HeapProfiler.enable'): Promise<void>;
        post(method: 'HeapProfiler.disable'): Promise<void>;
        post(method: 'HeapProfiler.startTrackingHeapObjects', params?: HeapProfiler.StartTrackingHeapObjectsParameterType): Promise<void>;
        post(method: 'HeapProfiler.stopTrackingHeapObjects', params?: HeapProfiler.StopTrackingHeapObjectsParameterType): Promise<void>;
        post(method: 'HeapProfiler.takeHeapSnapshot', params?: HeapProfiler.TakeHeapSnapshotParameterType): Promise<void>;
        post(method: 'HeapProfiler.collectGarbage'): Promise<void>;
        post(method: 'HeapProfiler.getObjectByHeapObjectId', params?: HeapProfiler.GetObjectByHeapObjectIdParameterType): Promise<HeapProfiler.GetObjectByHeapObjectIdReturnType>;
        /**
         * Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions).
         */
        post(method: 'HeapProfiler.addInspectedHeapObject', params?: HeapProfiler.AddInspectedHeapObjectParameterType): Promise<void>;
        post(method: 'HeapProfiler.getHeapObjectId', params?: HeapProfiler.GetHeapObjectIdParameterType): Promise<HeapProfiler.GetHeapObjectIdReturnType>;
        post(method: 'HeapProfiler.startSampling', params?: HeapProfiler.StartSamplingParameterType): Promise<void>;
        post(method: 'HeapProfiler.stopSampling'): Promise<HeapProfiler.StopSamplingReturnType>;
        post(method: 'HeapProfiler.getSamplingProfile'): Promise<HeapProfiler.GetSamplingProfileReturnType>;
        /**
         * Gets supported tracing categories.
         */
        post(method: 'NodeTracing.getCategories'): Promise<NodeTracing.GetCategoriesReturnType>;
        /**
         * Start trace events collection.
         */
        post(method: 'NodeTracing.start', params?: NodeTracing.StartParameterType): Promise<void>;
        /**
         * Stop trace events collection. Remaining collected events will be sent as a sequence of
         * dataCollected events followed by tracingComplete event.
         */
        post(method: 'NodeTracing.stop'): Promise<void>;
        /**
         * Sends protocol message over session with given id.
         */
        post(method: 'NodeWorker.sendMessageToWorker', params?: NodeWorker.SendMessageToWorkerParameterType): Promise<void>;
        /**
         * Instructs the inspector to attach to running workers. Will also attach to new workers
         * as they start
         */
        post(method: 'NodeWorker.enable', params?: NodeWorker.EnableParameterType): Promise<void>;
        /**
         * Detaches from all running workers and disables attaching to new workers as they are started.
         */
        post(method: 'NodeWorker.disable'): Promise<void>;
        /**
         * Detached from the worker with given sessionId.
         */
        post(method: 'NodeWorker.detach', params?: NodeWorker.DetachParameterType): Promise<void>;
        /**
         * Disables network tracking, prevents network events from being sent to the client.
         */
        post(method: 'Network.disable'): Promise<void>;
        /**
         * Enables network tracking, network events will now be delivered to the client.
         */
        post(method: 'Network.enable'): Promise<void>;
        /**
         * Enable the NodeRuntime events except by `NodeRuntime.waitingForDisconnect`.
         */
        post(method: 'NodeRuntime.enable'): Promise<void>;
        /**
         * Disable NodeRuntime events
         */
        post(method: 'NodeRuntime.disable'): Promise<void>;
        /**
         * Enable the `NodeRuntime.waitingForDisconnect`.
         */
        post(method: 'NodeRuntime.notifyWhenWaitingForDisconnect', params?: NodeRuntime.NotifyWhenWaitingForDisconnectParameterType): Promise<void>;

        addListener(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        addListener(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        addListener(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        addListener(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        addListener(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        addListener(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        addListener(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        addListener(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        addListener(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        addListener(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        addListener(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        addListener(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        addListener(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        addListener(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        addListener(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        addListener(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        addListener(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        addListener(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        addListener(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        addListener(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        addListener(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        addListener(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        addListener(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        addListener(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        addListener(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        addListener(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        addListener(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        addListener(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        addListener(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        addListener(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        addListener(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        addListener(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        addListener(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
        emit(event: string | symbol, ...args: any[]): boolean;
        emit(event: 'inspectorNotification', message: InspectorNotification<object>): boolean;
        emit(event: 'Runtime.executionContextCreated', message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>): boolean;
        emit(event: 'Runtime.executionContextDestroyed', message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>): boolean;
        emit(event: 'Runtime.executionContextsCleared'): boolean;
        emit(event: 'Runtime.exceptionThrown', message: InspectorNotification<Runtime.ExceptionThrownEventDataType>): boolean;
        emit(event: 'Runtime.exceptionRevoked', message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>): boolean;
        emit(event: 'Runtime.consoleAPICalled', message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>): boolean;
        emit(event: 'Runtime.inspectRequested', message: InspectorNotification<Runtime.InspectRequestedEventDataType>): boolean;
        emit(event: 'Debugger.scriptParsed', message: InspectorNotification<Debugger.ScriptParsedEventDataType>): boolean;
        emit(event: 'Debugger.scriptFailedToParse', message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>): boolean;
        emit(event: 'Debugger.breakpointResolved', message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>): boolean;
        emit(event: 'Debugger.paused', message: InspectorNotification<Debugger.PausedEventDataType>): boolean;
        emit(event: 'Debugger.resumed'): boolean;
        emit(event: 'Console.messageAdded', message: InspectorNotification<Console.MessageAddedEventDataType>): boolean;
        emit(event: 'Profiler.consoleProfileStarted', message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>): boolean;
        emit(event: 'Profiler.consoleProfileFinished', message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>): boolean;
        emit(event: 'HeapProfiler.addHeapSnapshotChunk', message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>): boolean;
        emit(event: 'HeapProfiler.resetProfiles'): boolean;
        emit(event: 'HeapProfiler.reportHeapSnapshotProgress', message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>): boolean;
        emit(event: 'HeapProfiler.lastSeenObjectId', message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>): boolean;
        emit(event: 'HeapProfiler.heapStatsUpdate', message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>): boolean;
        emit(event: 'NodeTracing.dataCollected', message: InspectorNotification<NodeTracing.DataCollectedEventDataType>): boolean;
        emit(event: 'NodeTracing.tracingComplete'): boolean;
        emit(event: 'NodeWorker.attachedToWorker', message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>): boolean;
        emit(event: 'NodeWorker.detachedFromWorker', message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>): boolean;
        emit(event: 'NodeWorker.receivedMessageFromWorker', message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>): boolean;
        emit(event: 'Network.requestWillBeSent', message: InspectorNotification<Network.RequestWillBeSentEventDataType>): boolean;
        emit(event: 'Network.responseReceived', message: InspectorNotification<Network.ResponseReceivedEventDataType>): boolean;
        emit(event: 'Network.loadingFailed', message: InspectorNotification<Network.LoadingFailedEventDataType>): boolean;
        emit(event: 'Network.loadingFinished', message: InspectorNotification<Network.LoadingFinishedEventDataType>): boolean;
        emit(event: 'NodeRuntime.waitingForDisconnect'): boolean;
        emit(event: 'NodeRuntime.waitingForDebugger'): boolean;
        on(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        on(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        on(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        on(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        on(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        on(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        on(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        on(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        on(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        on(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        on(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        on(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        on(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        on(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        on(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        on(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        on(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        on(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        on(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        on(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        on(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        on(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        on(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        on(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        on(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        on(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        on(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        on(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        on(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        on(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        on(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        on(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        on(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
        once(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        once(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        once(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        once(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        once(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        once(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        once(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        once(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        once(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        once(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        once(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        once(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        once(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        once(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        once(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        once(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        once(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        once(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        once(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        once(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        once(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        once(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        once(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        once(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        once(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        once(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        once(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        once(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        once(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        once(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        once(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        once(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        once(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
        prependListener(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        prependListener(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        prependListener(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        prependListener(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        prependListener(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        prependListener(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        prependListener(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        prependListener(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        prependListener(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        prependListener(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        prependListener(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        prependListener(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        prependListener(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        prependListener(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        prependListener(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        prependListener(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        prependListener(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        prependListener(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        prependListener(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        prependListener(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        prependListener(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        prependListener(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        prependListener(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        prependListener(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        prependListener(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        prependListener(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        prependListener(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        prependListener(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        prependListener(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        prependListener(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        prependListener(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        prependListener(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        prependListener(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
        prependOnceListener(event: string, listener: (...args: any[]) => void): this;
        /**
         * Emitted when any notification from the V8 Inspector is received.
         */
        prependOnceListener(event: 'inspectorNotification', listener: (message: InspectorNotification<object>) => void): this;
        /**
         * Issued when new execution context is created.
         */
        prependOnceListener(event: 'Runtime.executionContextCreated', listener: (message: InspectorNotification<Runtime.ExecutionContextCreatedEventDataType>) => void): this;
        /**
         * Issued when execution context is destroyed.
         */
        prependOnceListener(event: 'Runtime.executionContextDestroyed', listener: (message: InspectorNotification<Runtime.ExecutionContextDestroyedEventDataType>) => void): this;
        /**
         * Issued when all executionContexts were cleared in browser
         */
        prependOnceListener(event: 'Runtime.executionContextsCleared', listener: () => void): this;
        /**
         * Issued when exception was thrown and unhandled.
         */
        prependOnceListener(event: 'Runtime.exceptionThrown', listener: (message: InspectorNotification<Runtime.ExceptionThrownEventDataType>) => void): this;
        /**
         * Issued when unhandled exception was revoked.
         */
        prependOnceListener(event: 'Runtime.exceptionRevoked', listener: (message: InspectorNotification<Runtime.ExceptionRevokedEventDataType>) => void): this;
        /**
         * Issued when console API was called.
         */
        prependOnceListener(event: 'Runtime.consoleAPICalled', listener: (message: InspectorNotification<Runtime.ConsoleAPICalledEventDataType>) => void): this;
        /**
         * Issued when object should be inspected (for example, as a result of inspect() command line API call).
         */
        prependOnceListener(event: 'Runtime.inspectRequested', listener: (message: InspectorNotification<Runtime.InspectRequestedEventDataType>) => void): this;
        /**
         * Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.
         */
        prependOnceListener(event: 'Debugger.scriptParsed', listener: (message: InspectorNotification<Debugger.ScriptParsedEventDataType>) => void): this;
        /**
         * Fired when virtual machine fails to parse the script.
         */
        prependOnceListener(event: 'Debugger.scriptFailedToParse', listener: (message: InspectorNotification<Debugger.ScriptFailedToParseEventDataType>) => void): this;
        /**
         * Fired when breakpoint is resolved to an actual script and location.
         */
        prependOnceListener(event: 'Debugger.breakpointResolved', listener: (message: InspectorNotification<Debugger.BreakpointResolvedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.
         */
        prependOnceListener(event: 'Debugger.paused', listener: (message: InspectorNotification<Debugger.PausedEventDataType>) => void): this;
        /**
         * Fired when the virtual machine resumed execution.
         */
        prependOnceListener(event: 'Debugger.resumed', listener: () => void): this;
        /**
         * Issued when new console message is added.
         */
        prependOnceListener(event: 'Console.messageAdded', listener: (message: InspectorNotification<Console.MessageAddedEventDataType>) => void): this;
        /**
         * Sent when new profile recording is started using console.profile() call.
         */
        prependOnceListener(event: 'Profiler.consoleProfileStarted', listener: (message: InspectorNotification<Profiler.ConsoleProfileStartedEventDataType>) => void): this;
        prependOnceListener(event: 'Profiler.consoleProfileFinished', listener: (message: InspectorNotification<Profiler.ConsoleProfileFinishedEventDataType>) => void): this;
        prependOnceListener(event: 'HeapProfiler.addHeapSnapshotChunk', listener: (message: InspectorNotification<HeapProfiler.AddHeapSnapshotChunkEventDataType>) => void): this;
        prependOnceListener(event: 'HeapProfiler.resetProfiles', listener: () => void): this;
        prependOnceListener(event: 'HeapProfiler.reportHeapSnapshotProgress', listener: (message: InspectorNotification<HeapProfiler.ReportHeapSnapshotProgressEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.
         */
        prependOnceListener(event: 'HeapProfiler.lastSeenObjectId', listener: (message: InspectorNotification<HeapProfiler.LastSeenObjectIdEventDataType>) => void): this;
        /**
         * If heap objects tracking has been started then backend may send update for one or more fragments
         */
        prependOnceListener(event: 'HeapProfiler.heapStatsUpdate', listener: (message: InspectorNotification<HeapProfiler.HeapStatsUpdateEventDataType>) => void): this;
        /**
         * Contains an bucket of collected trace events.
         */
        prependOnceListener(event: 'NodeTracing.dataCollected', listener: (message: InspectorNotification<NodeTracing.DataCollectedEventDataType>) => void): this;
        /**
         * Signals that tracing is stopped and there is no trace buffers pending flush, all data were
         * delivered via dataCollected events.
         */
        prependOnceListener(event: 'NodeTracing.tracingComplete', listener: () => void): this;
        /**
         * Issued when attached to a worker.
         */
        prependOnceListener(event: 'NodeWorker.attachedToWorker', listener: (message: InspectorNotification<NodeWorker.AttachedToWorkerEventDataType>) => void): this;
        /**
         * Issued when detached from the worker.
         */
        prependOnceListener(event: 'NodeWorker.detachedFromWorker', listener: (message: InspectorNotification<NodeWorker.DetachedFromWorkerEventDataType>) => void): this;
        /**
         * Notifies about a new protocol message received from the session
         * (session ID is provided in attachedToWorker notification).
         */
        prependOnceListener(event: 'NodeWorker.receivedMessageFromWorker', listener: (message: InspectorNotification<NodeWorker.ReceivedMessageFromWorkerEventDataType>) => void): this;
        /**
         * Fired when page is about to send HTTP request.
         */
        prependOnceListener(event: 'Network.requestWillBeSent', listener: (message: InspectorNotification<Network.RequestWillBeSentEventDataType>) => void): this;
        /**
         * Fired when HTTP response is available.
         */
        prependOnceListener(event: 'Network.responseReceived', listener: (message: InspectorNotification<Network.ResponseReceivedEventDataType>) => void): this;
        prependOnceListener(event: 'Network.loadingFailed', listener: (message: InspectorNotification<Network.LoadingFailedEventDataType>) => void): this;
        prependOnceListener(event: 'Network.loadingFinished', listener: (message: InspectorNotification<Network.LoadingFinishedEventDataType>) => void): this;
        /**
         * This event is fired instead of `Runtime.executionContextDestroyed` when
         * enabled.
         * It is fired when the Node process finished all code execution and is
         * waiting for all frontends to disconnect.
         */
        prependOnceListener(event: 'NodeRuntime.waitingForDisconnect', listener: () => void): this;
        /**
         * This event is fired when the runtime is waiting for the debugger. For
         * example, when inspector.waitingForDebugger is called
         */
        prependOnceListener(event: 'NodeRuntime.waitingForDebugger', listener: () => void): this;
    }

    export {
        Session,
        open,
        close,
        url,
        waitForDebugger,
        console,
        InspectorNotification,
        Schema,
        Runtime,
        Debugger,
        Console,
        Profiler,
        HeapProfiler,
        NodeTracing,
        NodeWorker,
        Network,
        NodeRuntime,
    };
}

/**
 * The `node:inspector/promises` module provides an API for interacting with the V8
 * inspector.
 * @since v19.0.0
 */
declare module 'node:inspector/promises' {
    export * from 'inspector/promises';
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                M	 P      j  @ JHn4"Z|	J	  PF @PF  <Ba![I	  PF @PF  }GP&}E1x1	  PF @PF  |M.ĆZ7	  PF @PF  E/Jqz<#{	  PF @PF  W1I5p	&	  PF @PF  "
k9GRV4Y	  PF @PF  jmI_JK:"$JL	  PF @PF  qZ9H?E̦p|	  PF @PF  3NpMS`_c	  PF @PF  WMx F1խ	  PF @PF  沵JVИ	  PF @PF  JCˏ	  PF @PF  	&"Hn	  PF @PF  :B37	  PF @PF  SWr/@ a	  PF @PF  
֛˧FCס{	  PF @PF  o^Cȝ
07	  PF @PF  גbG䪜Zk	  PF @PF  #KO'߉	  PF @PF  (4/A/Ή	  PF @PF  ?}HNiK I	  PF @PF  3UIcŷ?Y	  PF @PF  -L@0eaB	  PF @PF  aeF#͇/%{A	  PF @PF  Rn!	$JT%xTi	  PF @PF  `|O
Y	  PF @PF  /8#oK1&	  PF @PF  eAJ@Wn	  PF @PF  #}LJ6͡q	  PF @PF  LCpEx"<	  PF @PF  ERv*@06WYM	  PF @PF  DΌD%J	  PF @PF  F YKM#/]	  PF @PF  J"NMl͆ZVM	  PF @PF  ]\J̋*li\a	  PF @PF  WoN_
	  PF  rPF  &fL)C`
cv	  PF  rPF  aJ\|hkv	  PF  rPF  ~ND~ɆXnݾ	  PF  rPF  1M~	  PF  rPF  "nM4A#3a	  PF  rPF  SmH$sٷ	  PF  rPF  %/EI]n~	  PF  rPF  ?uEW>k	  PF  rPF  r
DPꏊL	  PF  rPF  79BɃ	  PF  rPF  ܿ`BA;|nS	  PF  rPF  @nTK@"BR	  PF  rPF  TIA{%	  PF  rPF  HE~,	  PF  rPF   ;wgCl	  PF  rPF  lwA|	  PF  rPF  ԸD|ƻ@	  PF  rPF  hEe(Ĺ	  PF  rPF  &vkD\b`z	  PF  rPF  )2APϘ p	  PF  rPF  {ײ@Hse 	  PF  rPF  XֹQϳB'4	  PF  rPF  	vDEé	  PF  rPF  =Lʆƍ	  PF  rPF   .qIG`	  PF  rPF  xRH;gp	  PF  rPF  +f@^$	  PF  rPF W                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
       M	 `     #  @ PNb1'	   Y+PF  rPF  9ϼOQ)]Y	   Y+PF  rPF  Q@pPȃ	   Y+PF  rPF  i/K`	   Y+PF  rPF  ILL1If!^S	   Y+PF  rPF  ,KNfAa㖲	   Y+PF  rPF  {I.5	   Y+PF  rPF  !ӔL~֟[	   Y+PF  rPF  ͓D,J.6z	   Y+PF  rPF  M2<-	   Y+PF  rPF  .BNn7n	   Y+PF  rPF  0KDiQ%	   Y+PF  rPF  wzun*DJ	   Y+PF  rPF  r02K'z4	   Y+PF  rPF  =C":\T5e	   Y+PF  rPF  8\+)@ڄ0f	   Y+PF  rPF  (@vG>|	   Y+PF  rPF  -;IL^|!	   Y+PF  rPF  rU{Hթw\9	   Y+PF  rPF  1j@CCΛE.Q8	   Y+PF  rPF  lNmU!	   Y+PF  rPF  ߖB%I"	   Y+PF  rPF  ?w1CwuNc	   Y+PF  rPF  ޤOIL=ĮDR9	   Y+PF  rPF  vDv<Uһ	   Y+PF  rPF  Mn;<IЫ	   Y+PF  rPF  =1
MNyʻ	   Y+PF  rPF  +7WDj	   Y+PF  rPF  [y\BR-	   Y+PF  rPF  ?2,EGE.	   Y+PF  rPF  *H#ɇ	   Y+PF  rPF  ?[IG<-E	   Y+PF  rPF  4ޱCƥIi.	   Y+PF  rPF  ~%yF1)@	   Y+PF  rPF  
2'KSg8v	   Y+PF  rPF  NFU	   Y+PF  rPF  ð8P@ݠR4ȫ	   Y+PF  rPF  uaXD9	   Y+PF  rPF  m1y8NcD%T:W	   Y+PF  rPF  KIN#\	   Y+PF  rPF  ޺G}9A>L؁O	   Y+PF  rPF  .2hF_VƓjK	   Y+PF  rPF  &DWm:L	   Y+PF  rPF  2)J`W	   Y+PF  rPF  0
%1NXz	   Y+PF  rPF  ƄΣOP	   Y+PF  rPF  _WBʢ	   Y+PF  rPF  Fi*@O'קa	   Y+PF  rPF  naF
Px(R	   Y+PF  rPF  Y*E*s3pS	   Y+PF  rPF  NDȇD4	   Y+PF  rPF  <	I
#/s	   Y+PF  rPF  mFX/nҠ	   Y+PF  rPF  <C8ý	   Y+PF  rPF  ggz'mA篲LD	   Y+PF  rPF  iòL!H	   Y+PF  rPF  `RnF'	   Y+PF  rPF  OKƓHе9	   Y+PF  rPF  NcsG@=V%	   Y+PF  rPF  L
E4KW	   Y+PF  rPF   8GQy\}S	   Y+PF  rPF  ҂Fo>cj	   Y+PF  rPF  P(E[	   Y+PF  rPF  
o$ChT|{F	   Y+PF  rPF G                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           M	 p     b7 @ İLΕU%bý	  PF  rPF  ϪJB:1"'	Y	  PF  rPF  +/Eư>p	  PF  rPF  z5~RIN 3	  PF  rPF  ?2L &C	  PF  rPF  <YCqc	  PF  rPF  rzQ@#	  PF  rPF  C?$EǯTQ#S	  PF  rPF  > 1EB%	  PF  rPF  .`J[uX	  PF  rPF  KRGO@Ǟ 	  PF  rPF   ",N8	  PF  rPF  C=6	  PF  rPF  =0HIӥ~&~:	  PF  rPF  CP#/	  PF  rPF  ZX|Ow[RT<	  PF  rPF  %6C)E|cw`N%	  PF  rPF  ̾p]K`kӰ	  PF  rPF  V ,#x+@gH}/	  PF  rPF  Ms/L@zk[	  PF  rPF  	~	%IL	  PF  rPF  LGfmI΃7\\\	  PF  rPF  _k\I+/@	  PF  rPF  >n:lLZ	  PF  rPF  ~AMؤG7fIK	  PF  rPF  Å?EZ(tj	  PF  rPF  sFK#=w-	  PF  rPF  u/={dN6@	  PF  rPF  椸>LC{		  PF  rPF  8=nGuĔ	  PF  rPF  e<+Kxq@	  PF  rPF  sJ|,mh	  PF  rPF  *El&s	  PF  rPF  hh"O'	  PF  rPF  oM)HQ1E.	  PF  rPF  SvL}CRt	  PF  rPF  ]!3L,/_	  PF  rPF  atL^:KW4.	  PF  rPF  &|Jmwn	  PF  rPF  P}HKFܘdZ	  PF  rPF  U}4Jќߌ]
	  PF  rPF  'Lu)FF;'e		  PF  rPF  
o~JʴJ	  PF  rPF  ߵEŁV	  PF  rPF  vP%D6Cqb	  PF  rPF  iEJBCL	  PF  rPF  xaCBHLY	  PF  rPF  =BKW'- 	  PF  rPF  vKҵqV8	  PF  rPF  YGl9mu	  PF  rPF  	LC[ʔai	  PF  rPF  
/ZOC	  PF  rPF  A&zA.L	  PF  rPF  OOTxY@	  PF  rPF  quMGM	  PF  rPF  P
sA֝TO	  PF  rPF  ^xHF壟a0	  PF  rPF  =7GB!Y	  PF  rPF  ǔ7HBgP	  PF  rPF  +.H)<,<	  PF  rPF  uv8N4	  PF  rPF  >6, @J=EB	  PF  rPF  1dNoZp	  PF  rPF  ]Nݢ	  PF  rPF 8f                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
  @JHn4"Z|	J    PPF  iPF <Ba![I    PPF  iPF }GP&}E1x1    PPF  iPF |M.ĆZ7    PPF  iPF E/Jqz<#{    PPF  iPF W1I5p	&ߠ    PPF  iPF "
k9GRV4Y    PPF  iPF jmI_JK:"$JL    PPF  iPF qZ9H?E̦p|    PPF  iPF 3NpMS`_c    PPF  iPF WMx F1խ    PPF  iPF 沵JVИ    PPF  iPF JCˏ    PPF  iPF 	&"Hn    PPF  iPF :B37    PPF  iPF SWr/@ a    PPF  iPF 
֛˧FCס{    PPF  iPF o^Cȝ
07    PPF  iPF גbG䪜Zk    PPF  iPF #KO'߉    PPF  iPF (4/A/Ή    PPF  iPF ?}HNiK I    PPF  iPF 3UIcŷ?Y    PPF  iPF -L@0eaB    PPF  iPF aeF#͇/%{A    PPF  iPF Rn!	$JT%xTi    PPF  iPF `|O
YѠ    PPF  iPF /8#oK1&    PPF  iPF eAJ@Wn    PPF  iPF #}LJ6͡q    PPF  iPF LCpEx"<    PPF  iPF ERv*@06WYM    PPF  iPF DΌD%J۠    PPF  iPF F YKM#/]    PPF  iPF J"NMl͆ZVM    PPF  iPF ]\J̋*li\a    PPF  iPF WoN_
    PPF  iPF &fL)C`
cv    PPF  iPF aJ\|hkv    PPF  iPF ~ND~ɆXnݾ    PPF  iPF 1M~    PPF  iPF "nM4A#3a     PPF  iPF SmH$sٷ    PPF  iPF %/EI]n~    PPF  iPF ?uEW>k    PPF  iPF r
DPꏊL    PPF  iPF 79BɃ    PPF  iPF ܿ`BA;|nS    PPF  iPF @nTK@"BR    PPF  iPF TIA{%    PPF  iPF HE~,    PPF  iPF  ;wgCl    PPF  iPF lwA|    PPF  iPF ԸD|ƻ@    PPF  iPF hEe(Ĺ    PPF  iPF &vkD\b`z    PPF  iPF )2APϘ pР    PPF  iPF {ײ@Hse     PPF  iPF XֹQϳB'4    PPF  iPF 	vDEé    PPF  iPF =Lʆƍ    PPF  iPF  .qIG`    PPF  iPF xRH;gp    PPF  iPF +f@^$    PPF  iPF а
A  ; L{>'   *A > ><   FA 1  @XA 1  @A   0  ,23P !` `h\@  ; t= 0Z5A = C  @@7A 1 D @(8A 1 lE @@9A      -#DP !F` Gd@ @; oʠ D;A 1=	J  @pU>A 1K @N?A 1 yL @p?A      -#`P !M`  pE  `B  OC@A pF 0zDp  F  B  QC E   B  U F  4B  S LF  |B  T  F  B  [ F  B  e @ RlB  a e F  hP G  C ]F G  0C {E @@HL @ 
F VH  PC `  H  mC ~ H [D    H SD 0 @@B H 1 0 @< H  WC @ @ G " 0  F  2C @E G  C @@2G  GC   9G  (C  JG  HC ` "21 "  ;=G C   1_BGp @ ,G  %C   "` P VF    g4@0  A @@0@  pB BkB    ?" OY?      C" 3pp `{x~ @ @    QbGn??G B?aoA tD?q/pB~?E boB߆? xB?#?oBv?A0  pBx?0 oBku?G  D?p 1  1 @C 1`D?Y < Cn?C  @C " @5 C 1٬  @C 	0 @ C "0 C? 1 "8p  ;k%n@C@n3W < Cn  C߆  5 xS 	Cv  C²x ßC¯ ;X  H P.E v @gI 1 vP@ZhI 1 w @@mhI      #po    o qhI  #0 !Tzp .ʀ
 R@t2 Eǀǀ DC \   #@V !\   fYʀb  "X\    @  
u H0 gK G I @L @`
 IP @zuL "p @~L       "  "  @%L    0  
"p0 10! G D )0QH    P  ^m !`*`D     @       aOI @>E G @JJ     24 ! GJ  F#` !p    v
        B       =p KI @rD |`@@I     2@J !gI  F#` !p @ E&BD@ @ $  *3     *0 *~ $ 01= 1   Ok~A s$_ϰ       aFjC0E !FC;zpFCL{: ZóF:Ch(  оFy5C 7Fm*Ca  yFCt  F&CRu ōF%C 趷FCCNuOp Cm?woB?/CoB}?Q>  `	S~?	loB4?& pB>?'0  `	bDs?8B@  pBx?3F oBs?wH |sB?F	1  `O?.C@"p GcD}V*G j3DM`W*G /DlN S*G|3D *G<0Dx #)Gt/DbW *G3Dx *G\3D *G/D  n(G/D8Jp @ GF1I 1    BA  2i@  $3  0 0   *0 *~ # 0De %p      R! 1  @@@F! p #_P!%  0 .+p    2!p $@p :@4u@ p 3폐     3p "vp / E]?  Cy? D?#Z pB~?eo y pB.?/ Sr?@  `Sx?v  `Ss?P ?
Dւ?Up 1  1`` @1v0     3Lp "p fuK 4G0b[TL0bI  p 1[U 1pc@qUL       ="` 1`Dfp %^L IJ`nMsJ   2l{ !o Mo F"` 1 p HLI7 w+M`6J   1D, 170 @vU,M       ="h` 19p   @     m P <   `n       <            <            <          <   KI @rD |F'   @I |F |F<   @JI |F F<   gI F F<   gI F F<   gI F F<   gI F F<   gI F F<   gI F F<   I F F<    E    D'     @    ?<     @    ?<     @    3?<     @    ?<     @    ?<     @    ?<     @    ~?<     @    ?<     0A    =@<     A    k~A'     @    ?<     @    ?<     @    3?<     @    ?<     @    ?<     @    ?<     @    ~?<     @    ?<     @    _?<               '               <               <               <               <               <               <               <               <               <   FjC0EE'   !FC;zC<   FCL{:D<   ZóF:Ch(C<   оFy5CC<   7Fm*CaC<   yFCtC<    F&CRuC<   ōF%CC<   趷FCCNuOD<   Cm?wC'   oB?/C?<   oB}?Q>?<   pB~?G?<   loB4?&G?<   pB>?'>?<   oBDs?8B?<    pBx?3F?<   oBs?wH?<   |sB?F?<     `A    ?'               <     ?    ?<               <               <               <               <               <               <     @@    ?<   GcD}E'   V*G j3DMD<   W*G /DlND<   S*G|3DND<   *G<0DxND<   #)Gt/DbWND<   *G3DxND<   *G\3DxND<   *G/DND<   n(G/D8JD<    G    IF'      C    A<     C    iC<      C    3A<      C    A<      C    A<      C    A<      C    ~A<      C    A<    D    iC<               '               <               <               <               <               <               <               <               <               <    D    C'      C    A<     C    A<      C    3A<      C    A<      C    A<      C    A<      C    ~A<      C    A<     C    _A<    G    F'               <     C    +iC<               <               <               <               <               <               <    C    @iC<     :D    uC'               <     A    A<               <               <               <               <               <               <     A    vA<   / E]?C'   oBy?C?<   D?#ZC<   pB~?eH?<   ooB}?yG?<   pB.?/>?<   oBr?@B?<    pBx?vF?<   oBs?H?<   ?
Dւ?UC<    E    `E'               <     B    vB<               <               <               <               <               <               <     LB    B<   fuK 4G0bI'   [TL0bI0bI<   [UL0bIpcI<   qULpcIpcI<   qULpcIpcI<   qULpcIpcI<   qULpcIpcI<   qULpcIpcI<   qULpcIpcI<   ULpcI`DfI<   %^L IJ'   nMsJsJ<   l{MsJoJ<   MoJoJ<   MoJoJ<   MoJoJ<   MoJoJ<   MoJoJ<   MoJoJ<   MoJ J<   HLI7J'   w+M`6J`6J<   D,M`6J7J<   vU,M7J7J<   vU,M7J7J<   vU,M7J7J<   vU,M7J7J<   vU,M7J7J<   vU,M7J7J<   h,M7J9J<               '               <               <                        M	        H  @JHn4"Z|	J    PPF  iPF <Ba![I    PPF  iPF }GP&}E1x1    PPF  iPF |M.ĆZ7    PPF  iPF E/Jqz<#{    PPF  iPF W1I5p	&ߠ    PPF  iPF "
k9GRV4Y    PPF  iPF jmI_JK:"$JL    PPF  iPF qZ9H?E̦p|    PPF  iPF 3NpMS`_c    PPF  iPF WMx F1խ    PPF  iPF 沵JVИ    PPF  iPF JCˏ    PPF  iPF 	&"Hn    PPF  iPF :B37    PPF  iPF SWr/@ a    PPF  iPF 
֛˧FCס{    PPF  iPF o^Cȝ
07    PPF  iPF גbG䪜Zk    PPF  iPF #KO'߉    PPF  iPF (4/A/Ή    PPF  iPF ?}HNiK I    PPF  iPF 3UIcŷ?Y    PPF  iPF -L@0eaB    PPF  iPF aeF#͇/%{A    PPF  iPF Rn!	$JT%xTi    PPF  iPF `|O
YѠ    PPF  iPF /8#oK1&    PPF  iPF eAJ@Wn    PPF  iPF #}LJ6͡q    PPF  iPF LCpEx"<    PPF  iPF ERv*@06WYM    PPF  iPF DΌD%J۠    PPF  iPF F YKM#/]    PPF  iPF J"NMl͆ZVM    PPF  iPF ]\J̋*li\a    PPF  iPF WoN_
    PPF  iPF &fL)C`
cv    PPF  iPF aJ\|hkv    PPF  iPF ~ND~ɆXnݾ    PPF  iPF 1M~    PPF  iPF "nM4A#3a     PPF  iPF SmH$sٷ    PPF  iPF %/EI]n~    PPF  iPF ?uEW>k    PPF  iPF r
DPꏊL    PPF  iPF 79BɃ    PPF  iPF ܿ`BA;|nS    PPF  iPF @nTK@"BR    PPF  iPF TIA{%    PPF  iPF HE~,    PPF  iPF  ;wgCl    PPF  iPF lwA|    PPF  iPF ԸD|ƻ@    PPF  iPF hEe(Ĺ    PPF  iPF &vkD\b`z    PPF  iPF )2APϘ pР    PPF  iPF {ײ@Hse     PPF  iPF XֹQϳB'4    PPF  iPF 	vDEé    PPF  iPF =Lʆƍ    PPF  iPF  .qIG`    PPF  iPF xRH;gp    PPF  iPF +f@^$    PPF  iPF c5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           M	       Z  @GqN\^b    PPF  iPF lBBwЋǴ    PPF  iPF _VLe0    PPF  iPF t	G1dhɷ    PPF  iPF HxE~
    PPF  iPF -kJZ9gD٠    PPF  iPF ovo$aHHnsX    PPF  iPF R!u;J˟,2	`     PPF  iPF 5M"Ja5qT    PPF  iPF )DXOp(    PPF  iPF $~D+KQ     PPF  iPF 1`Kh .    PPF  iPF "cA{NR6    PPF  iPF i/FeQ     PPF  iPF 3& iF8Y"\b    PPF  iPF CBӃ@    PPF  iPF GJW[    PPF  iPF '91@f}iL5    PPF  iPF /џg$@{fe)s    PPF  iPF v7`KiΠ    PPF  iPF *ڳS@٧//8    PPF  iPF ,I׊r0禥    PPF  iPF 2|.kJ-c    PPF  iPF :T{Ić    PPF  iPF 
tA^L
    PPF  iPF 뇽~-Nߓ,A    PPF  iPF LX^B+Q0ՠ    PPF  iPF c5bDuKM"7l    PPF  iPF xOuZS    PPF  iPF qL%OFSp    PPF  iPF ٕ)ğiO[?OR    PPF  iPF e˼M'8@s    PPF  iPF gH#7zР    PPF  iPF gNA#Ej
N    PPF  iPF IԻ=Lg肺hv_    PPF  iPF ǳgM3G|x*    PPF  iPF ꑛgLc,1i    PPF  iPF *!IԾ))΢|    PPF  iPF |8C#AVysq(    PPF  iPF lgKȗ    PPF  iPF _7EFHWMݨ    PPF  iPF qII>=    PPF  iPF L֚19    PPF  iPF n$VHт4^ˠ    PPF  iPF ͗BNCˎ    PPF  iPF N BPdj}ؕ    PPF  iPF J{^Cnw譾    PPF  iPF hpE{'p5    PPF  iPF Sn~A'#' w    PPF  iPF VGMM    PPF  iPF hLpDje    PPF  iPF 6N~zP    PPF  iPF HiC*#Ӳ    PPF  iPF 8N=a@3-Ç    PPF  iPF  B,+<>#    PPF  iPF pHC(@CƸ1fm    PPF  iPF [XḢk F8_    PPF  iPF mnB䦂a[    PPF  iPF 3j@b))U    PPF  iPF ם@۫y    PPF  iPF U_A/K>t    PPF  iPF @#tK(JVu    PPF  iPF Hq~B{v    PPF  iPF ϚCKR7Y^Nz    PPF  iPF զj                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           M	 `        @*H#ɇΠ    PPF  iPF ?[IG<-E    PPF  iPF 4ޱCƥIi.Ҡ    PPF  iPF ~%yF1)@    PPF  iPF 
2'KSg8v    PPF  iPF NFU    PPF  iPF ð8P@ݠR4ȫ    PPF  iPF uaXD9ؠ    PPF  iPF m1y8NcD%T:WƠ    PPF  iPF KIN#\󱈠    PPF  iPF ޺G}9A>L؁O    PPF  iPF .2hF_VƓjK    PPF  iPF &DWm:L    PPF  iPF 2)J`W    PPF  iPF 0
%1NXz    PPF  iPF ƄΣOP    PPF  iPF _WBʢܠ    PPF  iPF Fi*@O'קa    PPF  iPF naF
Px(R    PPF  iPF Y*E*s3pS    PPF  iPF NDȇD4    PPF  iPF <	I
#/s    PPF  iPF mFX/nҠ    PPF  iPF <C8ý    PPF  iPF ggz'mA篲LD    PPF  iPF iòL!H    PPF  iPF `RnF'髠    PPF  iPF OKƓHе9    PPF  iPF NcsG@=V%    PPF  iPF L
E4KWܠ    PPF  iPF  8GQy\}S    PPF  iPF ҂Fo>cj    PPF  iPF P(E[    PPF  iPF 
o$ChT|{F    PPF  iPF coEtKrhihͭx    PPF  iPF ZSJ)+N3w@    PPF  iPF X@ͤO6ܗk    PPF  iPF 1L%sCDW    PPF  iPF *bntLy    PPF  iPF M}b(@N)    PPF  iPF & H\iΠ    PPF  iPF xe,Ns#H    PPF  iPF /xKA"\WZ֠    PPF  iPF :zHˠ    PPF  iPF dd
ISdT
+    PPF  iPF ڛ܊XHITB    PPF  iPF KйFsŌ]J    PPF  iPF "tAU@ؠ    PPF  iPF /	B˶A*5П`    PPF  iPF ^=iMBߒ    PPF  iPF .FJqmv    PPF  iPF 7$<Y
&Fl{g|Ԡ    PPF  iPF "OHϰ<    PPF  iPF aMm(4(<i    PPF  iPF Q2Kj[P    PPF  iPF YRMEU,8    PPF  iPF W3VtLBN    PPF  iPF #lIRT- `    PPF  iPF ^awKg=筠    PPF  iPF 'jI"2~C    PPF  iPF ![vFPLˊv    PPF  iPF 2}J~	A#7    PPF  iPF xO2dHi    PPF  iPF 4f9O37&X    PPF  iPF {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           M	      >  @BnEވJҠ    PPF  iPF Gܮ=gF6!˗    PPF  iPF e1\A74uwv    PPF  iPF $BG`jt    PPF  iPF i'ٌF[[)W5:    PPF  iPF '\yzXGY[0$
@    PPF  iPF {I[BzB    PPF  iPF %+Lg	H\_    PPF  iPF C`K3,    PPF  iPF 3BEư~R    PPF  iPF {3IʜC3B    PPF  iPF 9dVC{V    PPF  iPF hI!ɻN    PPF  iPF 9
#K;j?0    PPF  iPF +?I%篠    PPF  iPF @KO/688    PPF  iPF ^@OOb    PPF  iPF $>HhȫL)@#    PPF  iPF LjL!k8ؠ    PPF  iPF \bg[zOw+iEb    PPF  iPF ZOd>hd    PPF  iPF L;B\@/    PPF  iPF E<Sr@cMjvѭ    PPF  iPF 
3׎O'oY]
    PPF  iPF "|Eu$_F    PPF  iPF ;×7r@"Ƈ'    PPF  iPF Z@/hGR    PPF  iPF *26EL$*C-*m    PPF  iPF -{QK퐖N蝠    PPF  iPF -FÝlk    PPF  iPF WbKߵXM    PPF  iPF }=N`;n    PPF  iPF U<@B*K    PPF  iPF 5CRID[6Ys    PPF  iPF #
=DҢُǠ    PPF  iPF 4Mnf
4    PPF  iPF 40M`u    PPF  iPF 
)[IF@RY    PPF  iPF ۣJMX9©t    PPF  iPF 'PGt-\    PPF  iPF !bM샪KĠ    PPF  iPF JLcAGCyŠ    PPF  iPF ZGW]O?
qU	    PPF  iPF 
Ruu>@Qƞz    PPF  iPF бDcŠ    PPF  iPF ЁYKG=5/g    PPF  iPF Cc@&Er5+ޠ    PPF  iPF `s@eT4*    PPF  iPF `YLJY
;    PPF  iPF 6jSM1٦	    PPF  iPF AOVaig:H    PPF  iPF 8[KMvԢf    PPF  iPF n@kw%    PPF  iPF )طoHǬS ~    PPF  iPF 䯣NtJ&p[    PPF  iPF yrYN<KRwI    PPF  iPF "m'MFa"ʠ    PPF  iPF )>:g8Ag8W    PPF  iPF y
|K~"\M    PPF  iPF 28PHKJ+4    PPF  iPF ߇iGJhAZ    PPF  iPF =y@PB9xf    PPF  iPF <&je>G    PPF  iPF 0M[cfU&4    PPF  iPF :tG                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                NT NOT NULL, title TEXT NOT NULL, chart_type TEXT NOT NULL, unit TEXT NOT NULL, priority INT NOT NULL, first_time_t INT NOT NULL, last_time_t INT NOT NULL, deleted INT NOT NULL, family TEXT, PRIMARY KEY (host_id, id))-A indexsqlite_autoindex_context_1context             A)ϙ۴f*SQLite format 3   @                                                                  .[5
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     3=tablecontextcontextCREATE TABLE context (host_id BLOB, id 8  .   8  ..  8  
.npmignore  8  LICENSE 9  	clone.iml   A<  clone.jsgD  package.jsonI 	README.md                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     {8  .   8  ..  8  readable-stream 8 string_decoder                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ޼8  .   8  ..  8  
.npmignore   9  LICENSE ;  lib 9=  	duplex.js   JA  passthrough.js  A  readable.js fC  transform.jsD  writable.js D  package.jsonI  	README.md   YJ float.patch                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ލ֛8  .   8  ..  8  
.npmignore  9  LICENSE >  index.jsD  package.jsonI 	README.md                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         _8  .   8  ..  8  
.npmignore  69  LICENSE ;  test>  index.js@  mode.js C  
windows.js  D  package.json J d	README.md                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ޒProot:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin
messagebus:x:100:107::/nonexistent:/usr/sbin/nologin
sshd:x:101:65534::/run/sshd:/usr/sbin/nologin
xoa:x:1000:27:xoa,,,:/home/xoa:/bin/bash
_rpc:x:102:65534::/run/rpcbind:/usr/sbin/nologin
netdata:x:999:996::/var/lib/netdata:/bin/sh
statd:x:103:65534::/var/lib/nfs:/usr/sbin/nologin
redis:x:104:109::/var/lib/redis:/usr/sbin/nologin
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin
messagebus:x:100:107::/nonexistent:/usr/sbin/nologin
sshd:x:101:65534::/run/sshd:/usr/sbin/nologin
xoa:x:1000:27:xoa,,,:/home/xoa:/bin/bash
_rpc:x:102:65534::/run/rpcbind:/usr/sbin/nologin
netdata:x:999:996::/var/lib/netdata:/bin/sh
statd:x:103:65534::/var/lib/nfs:/usr/sbin/nologin
redis:x:104:109::/var/lib/redis:/usr/sbin/nologin
xoa-support:x:1001:1001:XOA SSH Support User:/home/xoa-support:/bin/bash
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              8  .   8  ..  8  
.npmignore  79  LICENSE 9  example.htmlk=  test=  
example.js  >  index.jsD  package.jsonwI  CHANGELOG.mdJ L	README.md                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ތ28  .   8  ..  8  
.npmignore  k9  LICENSE  ?  index.js	C  test.js D  package.json$J  	README.md   CM p.travis.yml                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   X^root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:netdata
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:xoa
floppy:x:25:xoa
tape:x:26:
sudo:x:27:
audio:x:29:xoa
dip:x:30:xoa
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
shadow:x:42:
utmp:x:43:
video:x:44:xoa
sasl:x:45:
plugdev:x:46:xoa
staff:x:50:
games:x:60:
users:x:100:xoa
nogroup:x:65534:
systemd-journal:x:999:
systemd-network:x:998:
crontab:x:101:
input:x:102:
sgx:x:103:
kvm:x:104:
render:x:105:
netdev:x:106:xoa
systemd-timesync:x:997:
messagebus:x:107:
_ssh:x:108:
xoa:x:1000:
netdata:x:996:
redis:x:109:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:netdata
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:xoa
floppy:x:25:xoa
tape:x:26:
sudo:x:27:
audio:x:29:xoa
dip:x:30:xoa
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
shadow:x:42:
utmp:x:43:
video:x:44:xoa
sasl:x:45:
plugdev:x:46:xoa
staff:x:50:
games:x:60:
users:x:100:xoa
nogroup:x:65534:
systemd-journal:x:999:
systemd-network:x:998:
crontab:x:101:
input:x:102:
sgx:x:103:
kvm:x:104:
render:x:105:
netdev:x:106:xoa
systemd-timesync:x:997:
messagebus:x:107:
_ssh:x:108:
xoa:x:1000:
netdata:x:996:
redis:x:109:
xoa-support:x:1001:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 root:*::
daemon:*::
bin:*::
sys:*::
adm:*::netdata
tty:*::
disk:*::
lp:*::
mail:*::
news:*::
uucp:*::
man:*::
proxy:*::
kmem:*::
dialout:*::
fax:*::
voice:*::
cdrom:*::xoa
floppy:*::xoa
tape:*::
sudo:*::
audio:*::xoa
dip:*::xoa
www-data:*::
backup:*::
operator:*::
list:*::
irc:*::
src:*::
shadow:*::
utmp:*::
video:*::xoa
sasl:*::
plugdev:*::xoa
staff:*::
games:*::
users:*::xoa
nogroup:*::
systemd-journal:!*::
systemd-network:!*::
crontab:!::
input:!::
sgx:!::
kvm:!::
render:!::
netdev:!::xoa
systemd-timesync:!*::
messagebus:!::
_ssh:!::
xoa:!::
netdata:!::
redis:!::
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   root:*::
daemon:*::
bin:*::
sys:*::
adm:*::netdata
tty:*::
disk:*::
lp:*::
mail:*::
news:*::
uucp:*::
man:*::
proxy:*::
kmem:*::
dialout:*::
fax:*::
voice:*::
cdrom:*::xoa
floppy:*::xoa
tape:*::
sudo:*::
audio:*::xoa
dip:*::xoa
www-data:*::
backup:*::
operator:*::
list:*::
irc:*::
src:*::
shadow:*::
utmp:*::
video:*::xoa
sasl:*::
plugdev:*::xoa
staff:*::
games:*::
users:*::xoa
nogroup:*::
systemd-journal:!*::
systemd-network:!*::
crontab:!::
input:!::
sgx:!::
kvm:!::
render:!::
netdev:!::xoa
systemd-timesync:!*::
messagebus:!::
_ssh:!::
xoa:!::
netdata:!::
redis:!::
xoa-support:!::
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   xoa:100000:65536
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               xoa:100000:65536
xoa-support:165536:65536
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      xoa:100000:65536
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               xoa:100000:65536
xoa-support:165536:65536
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      const Definition = require('./definition.js')

const ciInfo = require('ci-info')
const querystring = require('node:querystring')
const { join } = require('node:path')

const isWindows = process.platform === 'win32'

// used by cafile flattening to flatOptions.ca
const { readFileSync } = require('node:fs')
const maybeReadFile = file => {
  try {
    return readFileSync(file, 'utf8')
  } catch (er) {
    if (er.code !== 'ENOENT') {
      throw er
    }
    return null
  }
}

const buildOmitList = obj => {
  const include = obj.include || []
  const omit = obj.omit || []

  const only = obj.only
  if (/^prod(uction)?$/.test(only) || obj.production) {
    omit.push('dev')
  } else if (obj.production === false) {
    include.push('dev')
  }

  if (/^dev/.test(obj.also)) {
    include.push('dev')
  }

  if (obj.dev) {
    include.push('dev')
  }

  if (obj.optional === false) {
    omit.push('optional')
  } else if (obj.optional === true) {
    include.push('optional')
  }

  obj.omit = [...new Set(omit)].filter(type => !include.includes(type))
  obj.include = [...new Set(include)]

  if (obj.omit.includes('dev')) {
    process.env.NODE_ENV = 'production'
  }

  return obj.omit
}

const editor = process.env.EDITOR ||
  process.env.VISUAL ||
  (isWindows ? `${process.env.SYSTEMROOT}\\notepad.exe` : 'vi')

const shell = isWindows ? process.env.ComSpec || 'cmd'
  : process.env.SHELL || 'sh'

const { networkInterfaces } = require('node:os')
const getLocalAddresses = () => {
  try {
    return Object.values(networkInterfaces()).map(
      int => int.map(({ address }) => address)
    ).reduce((set, addrs) => set.concat(addrs), [null])
  } catch (e) {
    return [null]
  }
}

const unicode = /UTF-?8$/i.test(
  process.env.LC_ALL ||
  process.env.LC_CTYPE ||
  process.env.LANG
)

// use LOCALAPPDATA on Windows, if set
// https://github.com/npm/cli/pull/899
const cacheRoot = (isWindows && process.env.LOCALAPPDATA) || '~'
const cacheExtra = isWindows ? 'npm-cache' : '.npm'
const cache = `${cacheRoot}/${cacheExtra}`

// TODO: refactor these type definitions so that they are less
// weird to pull out of the config module.
// TODO: use better type definition/validation API, nopt's is so weird.
const {
  semver: { type: Semver },
  Umask: { type: Umask },
  url: { type: url },
  path: { type: path },
} = require('../type-defs.js')

// basic flattening function, just copy it over camelCase
const flatten = (key, obj, flatOptions) => {
  const camel = key.replace(/-([a-z])/g, (_0, _1) => _1.toUpperCase())
  flatOptions[camel] = obj[key]
}

// TODO:
// Instead of having each definition provide a flatten method,
// provide the (?list of?) flat option field(s?) that it impacts.
// When that config is set, we mark the relevant flatOption fields
// dirty.  Then, a getter for that field defines how we actually
// set it.
//
// So, `save-dev`, `save-optional`, `save-prod`, et al would indicate
// that they affect the `saveType` flat option.  Then the config.flat
// object has a `get saveType () { ... }` that looks at the "real"
// config settings from files etc and returns the appropriate value.
//
// Getters will also (maybe?) give us a hook to audit flat option
// usage, so we can document and group these more appropriately.
//
// This will be a problem with cases where we currently do:
// const opts = { ...npm.flatOptions, foo: 'bar' }, but we can maybe
// instead do `npm.config.set('foo', 'bar')` prior to passing the
// config object down where it needs to go.
//
// This way, when we go hunting for "where does saveType come from anyway!?"
// while fixing some Arborist bug, we won't have to hunt through too
// many places.

// 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.

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"

    Warning: This should generally not be set via a command-line option.  It
    is safer to use a registry-provided authentication bearer token stored in
    the ~/.npmrc file by running \`npm login\`.
  `,
    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: `
    If you do not want your scoped package to be publicly viewable (and
    installable) set \`--access=restricted\`.

    Unscoped packages can not be set to \`restricted\`.

    Note: This defaults to not changing the current access level for existing
    packages.  Specifying a value of \`restricted\` or \`public\` during
    publish will change the access for an existing package the same way that
    \`npm access set status\` would.
  `,
    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,
  }),
  '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,
  }),
  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,
  }),
  '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: `
    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,
  }),
  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
    string "\\n". For example:

    \`\`\`ini
    ca="-----BEGIN CERTIFICATE-----\\nXXXX\\nXXXX\\n-----END CERTIFICATE-----"
    \`\`\`

    Set to \`null\` to only allow "known" registrars, or to a specific CA
    cert to trust only that specific signing authority.

    Multiple CAs can be trusted by specifying an array of certificates:

    \`\`\`ini
    ca[]="..."
    ca[]="..."
    \`\`\`

    See also the \`strict-ssl\` config.
  `,
    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
      }

      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)
    },
  }),
  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: '<package-spec>',
    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: '<path>',
    type: String,
    description: `
      Destination prefix to be used in \`npm diff\` output.
    `,
    flatten,
  }),
  'diff-src-prefix': new Definition('diff-src-prefix', {
    default: 'a/',
    hint: '<path>',
    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: '<count>',
    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=<type>\`.

      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: '<email>',
    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: '<name>',
    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: '<url>',
    description: `
      The value \`npm init\` should use by default for the package author's homepage.
    `,
  }),
  'init-license': new Definition('init-license', {
    default: 'ISC',
    hint: '<license>',
    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: '<module>',
    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: '<version>',
    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: '<package-spec>',
    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\` and \`process.stdout\` are a TTY.

      Set to \`false\` to suppress the progress bar.
    `,
    flatten (key, obj, flatOptions) {
      flatOptions.progress = !obj.progress ? false
        // progress is only written to stderr but we disable it unless stdout is a tty
        // also. This prevents the progress from appearing when piping output to another
        // command which doesn't break anything, but does look very odd to users.
        : !!process.stderr.isTTY && !!process.stdout.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: '<file>',
    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: '<npmjs|never|always> | 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
      }

      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
      }

      if (flatOptions.saveType === 'peerOptional') {
        return
      }

      if (flatOptions.saveType === 'peer') {
        flatOptions.saveType = 'peerOptional'
      } else {
        flatOptions.saveType = 'optional'
      }
    },
  }),
  '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
      }

      if (flatOptions.saveType === 'peerOptional') {
        return
      }

      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
      }

      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 <package-spec>\` 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.

      It is the tag added to the package@version specified in the
      \`npm dist-tag add\` 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.

      If used in the \`npm publish\` command, this is the tag that will be
      added to the package submitted to the registry.
    `,
    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: '<fundingSourceNumber>',
    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: '<workspace-name>',
    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.
    `,
  }),
}

module.exports = definitions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               # Copyright (c) 2012 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
This module contains classes that help to emulate xcodebuild behavior on top of
other build systems, such as make and ninja.
"""


import copy
import gyp.common
import os
import os.path
import re
import shlex
import subprocess
import sys
from gyp.common import GypError

# Populated lazily by XcodeVersion, for efficiency, and to fix an issue when
# "xcodebuild" is called too quickly (it has been found to return incorrect
# version number).
XCODE_VERSION_CACHE = None

# Populated lazily by GetXcodeArchsDefault, to an |XcodeArchsDefault| instance
# corresponding to the installed version of Xcode.
XCODE_ARCHS_DEFAULT_CACHE = None


def XcodeArchsVariableMapping(archs, archs_including_64_bit=None):
    """Constructs a dictionary with expansion for $(ARCHS_STANDARD) variable,
  and optionally for $(ARCHS_STANDARD_INCLUDING_64_BIT)."""
    mapping = {"$(ARCHS_STANDARD)": archs}
    if archs_including_64_bit:
        mapping["$(ARCHS_STANDARD_INCLUDING_64_BIT)"] = archs_including_64_bit
    return mapping


class XcodeArchsDefault:
    """A class to resolve ARCHS variable from xcode_settings, resolving Xcode
  macros and implementing filtering by VALID_ARCHS. The expansion of macros
  depends on the SDKROOT used ("macosx", "iphoneos", "iphonesimulator") and
  on the version of Xcode.
  """

    # Match variable like $(ARCHS_STANDARD).
    variable_pattern = re.compile(r"\$\([a-zA-Z_][a-zA-Z0-9_]*\)$")

    def __init__(self, default, mac, iphonesimulator, iphoneos):
        self._default = (default,)
        self._archs = {"mac": mac, "ios": iphoneos, "iossim": iphonesimulator}

    def _VariableMapping(self, sdkroot):
        """Returns the dictionary of variable mapping depending on the SDKROOT."""
        sdkroot = sdkroot.lower()
        if "iphoneos" in sdkroot:
            return self._archs["ios"]
        elif "iphonesimulator" in sdkroot:
            return self._archs["iossim"]
        else:
            return self._archs["mac"]

    def _ExpandArchs(self, archs, sdkroot):
        """Expands variables references in ARCHS, and remove duplicates."""
        variable_mapping = self._VariableMapping(sdkroot)
        expanded_archs = []
        for arch in archs:
            if self.variable_pattern.match(arch):
                variable = arch
                try:
                    variable_expansion = variable_mapping[variable]
                    for arch in variable_expansion:
                        if arch not in expanded_archs:
                            expanded_archs.append(arch)
                except KeyError:
                    print('Warning: Ignoring unsupported variable "%s".' % variable)
            elif arch not in expanded_archs:
                expanded_archs.append(arch)
        return expanded_archs

    def ActiveArchs(self, archs, valid_archs, sdkroot):
        """Expands variables references in ARCHS, and filter by VALID_ARCHS if it
    is defined (if not set, Xcode accept any value in ARCHS, otherwise, only
    values present in VALID_ARCHS are kept)."""
        expanded_archs = self._ExpandArchs(archs or self._default, sdkroot or "")
        if valid_archs:
            filtered_archs = []
            for arch in expanded_archs:
                if arch in valid_archs:
                    filtered_archs.append(arch)
            expanded_archs = filtered_archs
        return expanded_archs


def GetXcodeArchsDefault():
    """Returns the |XcodeArchsDefault| object to use to expand ARCHS for the
  installed version of Xcode. The default values used by Xcode for ARCHS
  and the expansion of the variables depends on the version of Xcode used.

  For all version anterior to Xcode 5.0 or posterior to Xcode 5.1 included
  uses $(ARCHS_STANDARD) if ARCHS is unset, while Xcode 5.0 to 5.0.2 uses
  $(ARCHS_STANDARD_INCLUDING_64_BIT). This variable was added to Xcode 5.0
  and deprecated with Xcode 5.1.

  For "macosx" SDKROOT, all version starting with Xcode 5.0 includes 64-bit
  architecture as part of $(ARCHS_STANDARD) and default to only building it.

  For "iphoneos" and "iphonesimulator" SDKROOT, 64-bit architectures are part
  of $(ARCHS_STANDARD_INCLUDING_64_BIT) from Xcode 5.0. From Xcode 5.1, they
  are also part of $(ARCHS_STANDARD).

  All these rules are coded in the construction of the |XcodeArchsDefault|
  object to use depending on the version of Xcode detected. The object is
  for performance reason."""
    global XCODE_ARCHS_DEFAULT_CACHE
    if XCODE_ARCHS_DEFAULT_CACHE:
        return XCODE_ARCHS_DEFAULT_CACHE
    xcode_version, _ = XcodeVersion()
    if xcode_version < "0500":
        XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault(
            "$(ARCHS_STANDARD)",
            XcodeArchsVariableMapping(["i386"]),
            XcodeArchsVariableMapping(["i386"]),
            XcodeArchsVariableMapping(["armv7"]),
        )
    elif xcode_version < "0510":
        XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault(
            "$(ARCHS_STANDARD_INCLUDING_64_BIT)",
            XcodeArchsVariableMapping(["x86_64"], ["x86_64"]),
            XcodeArchsVariableMapping(["i386"], ["i386", "x86_64"]),
            XcodeArchsVariableMapping(
                ["armv7", "armv7s"], ["armv7", "armv7s", "arm64"]
            ),
        )
    else:
        XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault(
            "$(ARCHS_STANDARD)",
            XcodeArchsVariableMapping(["x86_64"], ["x86_64"]),
            XcodeArchsVariableMapping(["i386", "x86_64"], ["i386", "x86_64"]),
            XcodeArchsVariableMapping(
                ["armv7", "armv7s", "arm64"], ["armv7", "armv7s", "arm64"]
            ),
        )
    return XCODE_ARCHS_DEFAULT_CACHE


class XcodeSettings:
    """A class that understands the gyp 'xcode_settings' object."""

    # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached
    # at class-level for efficiency.
    _sdk_path_cache = {}
    _platform_path_cache = {}
    _sdk_root_cache = {}

    # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so
    # cached at class-level for efficiency.
    _plist_cache = {}

    # Populated lazily by GetIOSPostbuilds.  Shared by all XcodeSettings, so
    # cached at class-level for efficiency.
    _codesigning_key_cache = {}

    def __init__(self, spec):
        self.spec = spec

        self.isIOS = False
        self.mac_toolchain_dir = None
        self.header_map_path = None

        # Per-target 'xcode_settings' are pushed down into configs earlier by gyp.
        # This means self.xcode_settings[config] always contains all settings
        # for that config -- the per-target settings as well. Settings that are
        # the same for all configs are implicitly per-target settings.
        self.xcode_settings = {}
        configs = spec["configurations"]
        for configname, config in configs.items():
            self.xcode_settings[configname] = config.get("xcode_settings", {})
            self._ConvertConditionalKeys(configname)
            if self.xcode_settings[configname].get("IPHONEOS_DEPLOYMENT_TARGET", None):
                self.isIOS = True

        # This is only non-None temporarily during the execution of some methods.
        self.configname = None

        # Used by _AdjustLibrary to match .a and .dylib entries in libraries.
        self.library_re = re.compile(r"^lib([^/]+)\.(a|dylib)$")

    def _ConvertConditionalKeys(self, configname):
        """Converts or warns on conditional keys.  Xcode supports conditional keys,
    such as CODE_SIGN_IDENTITY[sdk=iphoneos*].  This is a partial implementation
    with some keys converted while the rest force a warning."""
        settings = self.xcode_settings[configname]
        conditional_keys = [key for key in settings if key.endswith("]")]
        for key in conditional_keys:
            # If you need more, speak up at http://crbug.com/122592
            if key.endswith("[sdk=iphoneos*]"):
                if configname.endswith("iphoneos"):
                    new_key = key.split("[")[0]
                    settings[new_key] = settings[key]
            else:
                print(
                    "Warning: Conditional keys not implemented, ignoring:",
                    " ".join(conditional_keys),
                )
            del settings[key]

    def _Settings(self):
        assert self.configname
        return self.xcode_settings[self.configname]

    def _Test(self, test_key, cond_key, default):
        return self._Settings().get(test_key, default) == cond_key

    def _Appendf(self, lst, test_key, format_str, default=None):
        if test_key in self._Settings():
            lst.append(format_str % str(self._Settings()[test_key]))
        elif default:
            lst.append(format_str % str(default))

    def _WarnUnimplemented(self, test_key):
        if test_key in self._Settings():
            print('Warning: Ignoring not yet implemented key "%s".' % test_key)

    def IsBinaryOutputFormat(self, configname):
        default = "binary" if self.isIOS else "xml"
        format = self.xcode_settings[configname].get("INFOPLIST_OUTPUT_FORMAT", default)
        return format == "binary"

    def IsIosFramework(self):
        return self.spec["type"] == "shared_library" and self._IsBundle() and self.isIOS

    def _IsBundle(self):
        return (
            int(self.spec.get("mac_bundle", 0)) != 0
            or self._IsXCTest()
            or self._IsXCUiTest()
        )

    def _IsXCTest(self):
        return int(self.spec.get("mac_xctest_bundle", 0)) != 0

    def _IsXCUiTest(self):
        return int(self.spec.get("mac_xcuitest_bundle", 0)) != 0

    def _IsIosAppExtension(self):
        return int(self.spec.get("ios_app_extension", 0)) != 0

    def _IsIosWatchKitExtension(self):
        return int(self.spec.get("ios_watchkit_extension", 0)) != 0

    def _IsIosWatchApp(self):
        return int(self.spec.get("ios_watch_app", 0)) != 0

    def GetFrameworkVersion(self):
        """Returns the framework version of the current target. Only valid for
    bundles."""
        assert self._IsBundle()
        return self.GetPerTargetSetting("FRAMEWORK_VERSION", default="A")

    def GetWrapperExtension(self):
        """Returns the bundle extension (.app, .framework, .plugin, etc).  Only
    valid for bundles."""
        assert self._IsBundle()
        if self.spec["type"] in ("loadable_module", "shared_library"):
            default_wrapper_extension = {
                "loadable_module": "bundle",
                "shared_library": "framework",
            }[self.spec["type"]]
            wrapper_extension = self.GetPerTargetSetting(
                "WRAPPER_EXTENSION", default=default_wrapper_extension
            )
            return "." + self.spec.get("product_extension", wrapper_extension)
        elif self.spec["type"] == "executable":
            if self._IsIosAppExtension() or self._IsIosWatchKitExtension():
                return "." + self.spec.get("product_extension", "appex")
            else:
                return "." + self.spec.get("product_extension", "app")
        else:
            assert False, "Don't know extension for '{}', target '{}'".format(
                self.spec["type"],
                self.spec["target_name"],
            )

    def GetProductName(self):
        """Returns PRODUCT_NAME."""
        return self.spec.get("product_name", self.spec["target_name"])

    def GetFullProductName(self):
        """Returns FULL_PRODUCT_NAME."""
        if self._IsBundle():
            return self.GetWrapperName()
        else:
            return self._GetStandaloneBinaryPath()

    def GetWrapperName(self):
        """Returns the directory name of the bundle represented by this target.
    Only valid for bundles."""
        assert self._IsBundle()
        return self.GetProductName() + self.GetWrapperExtension()

    def GetBundleContentsFolderPath(self):
        """Returns the qualified path to the bundle's contents folder. E.g.
    Chromium.app/Contents or Foo.bundle/Versions/A. Only valid for bundles."""
        if self.isIOS:
            return self.GetWrapperName()
        assert self._IsBundle()
        if self.spec["type"] == "shared_library":
            return os.path.join(
                self.GetWrapperName(), "Versions", self.GetFrameworkVersion()
            )
        else:
            # loadable_modules have a 'Contents' folder like executables.
            return os.path.join(self.GetWrapperName(), "Contents")

    def GetBundleResourceFolder(self):
        """Returns the qualified path to the bundle's resource folder. E.g.
    Chromium.app/Contents/Resources. Only valid for bundles."""
        assert self._IsBundle()
        if self.isIOS:
            return self.GetBundleContentsFolderPath()
        return os.path.join(self.GetBundleContentsFolderPath(), "Resources")

    def GetBundleExecutableFolderPath(self):
        """Returns the qualified path to the bundle's executables folder. E.g.
    Chromium.app/Contents/MacOS. Only valid for bundles."""
        assert self._IsBundle()
        if self.spec["type"] in ("shared_library") or self.isIOS:
            return self.GetBundleContentsFolderPath()
        elif self.spec["type"] in ("executable", "loadable_module"):
            return os.path.join(self.GetBundleContentsFolderPath(), "MacOS")

    def GetBundleJavaFolderPath(self):
        """Returns the qualified path to the bundle's Java resource folder.
    E.g. Chromium.app/Contents/Resources/Java. Only valid for bundles."""
        assert self._IsBundle()
        return os.path.join(self.GetBundleResourceFolder(), "Java")

    def GetBundleFrameworksFolderPath(self):
        """Returns the qualified path to the bundle's frameworks folder. E.g,
    Chromium.app/Contents/Frameworks. Only valid for bundles."""
        assert self._IsBundle()
        return os.path.join(self.GetBundleContentsFolderPath(), "Frameworks")

    def GetBundleSharedFrameworksFolderPath(self):
        """Returns the qualified path to the bundle's frameworks folder. E.g,
    Chromium.app/Contents/SharedFrameworks. Only valid for bundles."""
        assert self._IsBundle()
        return os.path.join(self.GetBundleContentsFolderPath(), "SharedFrameworks")

    def GetBundleSharedSupportFolderPath(self):
        """Returns the qualified path to the bundle's shared support folder. E.g,
    Chromium.app/Contents/SharedSupport. Only valid for bundles."""
        assert self._IsBundle()
        if self.spec["type"] == "shared_library":
            return self.GetBundleResourceFolder()
        else:
            return os.path.join(self.GetBundleContentsFolderPath(), "SharedSupport")

    def GetBundlePlugInsFolderPath(self):
        """Returns the qualified path to the bundle's plugins folder. E.g,
    Chromium.app/Contents/PlugIns. Only valid for bundles."""
        assert self._IsBundle()
        return os.path.join(self.GetBundleContentsFolderPath(), "PlugIns")

    def GetBundleXPCServicesFolderPath(self):
        """Returns the qualified path to the bundle's XPC services folder. E.g,
    Chromium.app/Contents/XPCServices. Only valid for bundles."""
        assert self._IsBundle()
        return os.path.join(self.GetBundleContentsFolderPath(), "XPCServices")

    def GetBundlePlistPath(self):
        """Returns the qualified path to the bundle's plist file. E.g.
    Chromium.app/Contents/Info.plist. Only valid for bundles."""
        assert self._IsBundle()
        if (
            self.spec["type"] in ("executable", "loadable_module")
            or self.IsIosFramework()
        ):
            return os.path.join(self.GetBundleContentsFolderPath(), "Info.plist")
        else:
            return os.path.join(
                self.GetBundleContentsFolderPath(), "Resources", "Info.plist"
            )

    def GetProductType(self):
        """Returns the PRODUCT_TYPE of this target."""
        if self._IsIosAppExtension():
            assert self._IsBundle(), (
                "ios_app_extension flag requires mac_bundle "
                "(target %s)" % self.spec["target_name"]
            )
            return "com.apple.product-type.app-extension"
        if self._IsIosWatchKitExtension():
            assert self._IsBundle(), (
                "ios_watchkit_extension flag requires "
                "mac_bundle (target %s)" % self.spec["target_name"]
            )
            return "com.apple.product-type.watchkit-extension"
        if self._IsIosWatchApp():
            assert self._IsBundle(), (
                "ios_watch_app flag requires mac_bundle "
                "(target %s)" % self.spec["target_name"]
            )
            return "com.apple.product-type.application.watchapp"
        if self._IsXCUiTest():
            assert self._IsBundle(), (
                "mac_xcuitest_bundle flag requires mac_bundle "
                "(target %s)" % self.spec["target_name"]
            )
            return "com.apple.product-type.bundle.ui-testing"
        if self._IsBundle():
            return {
                "executable": "com.apple.product-type.application",
                "loadable_module": "com.apple.product-type.bundle",
                "shared_library": "com.apple.product-type.framework",
            }[self.spec["type"]]
        else:
            return {
                "executable": "com.apple.product-type.tool",
                "loadable_module": "com.apple.product-type.library.dynamic",
                "shared_library": "com.apple.product-type.library.dynamic",
                "static_library": "com.apple.product-type.library.static",
            }[self.spec["type"]]

    def GetMachOType(self):
        """Returns the MACH_O_TYPE of this target."""
        # Weird, but matches Xcode.
        if not self._IsBundle() and self.spec["type"] == "executable":
            return ""
        return {
            "executable": "mh_execute",
            "static_library": "staticlib",
            "shared_library": "mh_dylib",
            "loadable_module": "mh_bundle",
        }[self.spec["type"]]

    def _GetBundleBinaryPath(self):
        """Returns the name of the bundle binary of by this target.
    E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles."""
        assert self._IsBundle()
        return os.path.join(
            self.GetBundleExecutableFolderPath(), self.GetExecutableName()
        )

    def _GetStandaloneExecutableSuffix(self):
        if "product_extension" in self.spec:
            return "." + self.spec["product_extension"]
        return {
            "executable": "",
            "static_library": ".a",
            "shared_library": ".dylib",
            "loadable_module": ".so",
        }[self.spec["type"]]

    def _GetStandaloneExecutablePrefix(self):
        return self.spec.get(
            "product_prefix",
            {
                "executable": "",
                "static_library": "lib",
                "shared_library": "lib",
                # Non-bundled loadable_modules are called foo.so for some reason
                # (that is, .so and no prefix) with the xcode build -- match that.
                "loadable_module": "",
            }[self.spec["type"]],
        )

    def _GetStandaloneBinaryPath(self):
        """Returns the name of the non-bundle binary represented by this target.
    E.g. hello_world. Only valid for non-bundles."""
        assert not self._IsBundle()
        assert self.spec["type"] in (
            "executable",
            "shared_library",
            "static_library",
            "loadable_module",
        ), ("Unexpected type %s" % self.spec["type"])
        target = self.spec["target_name"]
        if self.spec["type"] == "static_library":
            if target[:3] == "lib":
                target = target[3:]
        elif self.spec["type"] in ("loadable_module", "shared_library"):
            if target[:3] == "lib":
                target = target[3:]

        target_prefix = self._GetStandaloneExecutablePrefix()
        target = self.spec.get("product_name", target)
        target_ext = self._GetStandaloneExecutableSuffix()
        return target_prefix + target + target_ext

    def GetExecutableName(self):
        """Returns the executable name of the bundle represented by this target.
    E.g. Chromium."""
        if self._IsBundle():
            return self.spec.get("product_name", self.spec["target_name"])
        else:
            return self._GetStandaloneBinaryPath()

    def GetExecutablePath(self):
        """Returns the qualified path to the primary executable of the bundle
    represented by this target. E.g. Chromium.app/Contents/MacOS/Chromium."""
        if self._IsBundle():
            return self._GetBundleBinaryPath()
        else:
            return self._GetStandaloneBinaryPath()

    def GetActiveArchs(self, configname):
        """Returns the architectures this target should be built for."""
        config_settings = self.xcode_settings[configname]
        xcode_archs_default = GetXcodeArchsDefault()
        return xcode_archs_default.ActiveArchs(
            config_settings.get("ARCHS"),
            config_settings.get("VALID_ARCHS"),
            config_settings.get("SDKROOT"),
        )

    def _GetSdkVersionInfoItem(self, sdk, infoitem):
        # xcodebuild requires Xcode and can't run on Command Line Tools-only
        # systems from 10.7 onward.
        # Since the CLT has no SDK paths anyway, returning None is the
        # most sensible route and should still do the right thing.
        try:
            return GetStdoutQuiet(["xcrun", "--sdk", sdk, infoitem])
        except GypError:
            pass

    def _SdkRoot(self, configname):
        if configname is None:
            configname = self.configname
        return self.GetPerConfigSetting("SDKROOT", configname, default="")

    def _XcodePlatformPath(self, configname=None):
        sdk_root = self._SdkRoot(configname)
        if sdk_root not in XcodeSettings._platform_path_cache:
            platform_path = self._GetSdkVersionInfoItem(
                sdk_root, "--show-sdk-platform-path"
            )
            XcodeSettings._platform_path_cache[sdk_root] = platform_path
        return XcodeSettings._platform_path_cache[sdk_root]

    def _SdkPath(self, configname=None):
        sdk_root = self._SdkRoot(configname)
        if sdk_root.startswith("/"):
            return sdk_root
        return self._XcodeSdkPath(sdk_root)

    def _XcodeSdkPath(self, sdk_root):
        if sdk_root not in XcodeSettings._sdk_path_cache:
            sdk_path = self._GetSdkVersionInfoItem(sdk_root, "--show-sdk-path")
            XcodeSettings._sdk_path_cache[sdk_root] = sdk_path
            if sdk_root:
                XcodeSettings._sdk_root_cache[sdk_path] = sdk_root
        return XcodeSettings._sdk_path_cache[sdk_root]

    def _AppendPlatformVersionMinFlags(self, lst):
        self._Appendf(lst, "MACOSX_DEPLOYMENT_TARGET", "-mmacosx-version-min=%s")
        if "IPHONEOS_DEPLOYMENT_TARGET" in self._Settings():
            # TODO: Implement this better?
            sdk_path_basename = os.path.basename(self._SdkPath())
            if sdk_path_basename.lower().startswith("iphonesimulator"):
                self._Appendf(
                    lst, "IPHONEOS_DEPLOYMENT_TARGET", "-mios-simulator-version-min=%s"
                )
            else:
                self._Appendf(
                    lst, "IPHONEOS_DEPLOYMENT_TARGET", "-miphoneos-version-min=%s"
                )

    def GetCflags(self, configname, arch=None):
        """Returns flags that need to be added to .c, .cc, .m, and .mm
    compilations."""
        # This functions (and the similar ones below) do not offer complete
        # emulation of all xcode_settings keys. They're implemented on demand.

        self.configname = configname
        cflags = []

        sdk_root = self._SdkPath()
        if "SDKROOT" in self._Settings() and sdk_root:
            cflags.append("-isysroot %s" % sdk_root)

        if self.header_map_path:
            cflags.append("-I%s" % self.header_map_path)

        if self._Test("CLANG_WARN_CONSTANT_CONVERSION", "YES", default="NO"):
            cflags.append("-Wconstant-conversion")

        if self._Test("GCC_CHAR_IS_UNSIGNED_CHAR", "YES", default="NO"):
            cflags.append("-funsigned-char")

        if self._Test("GCC_CW_ASM_SYNTAX", "YES", default="YES"):
            cflags.append("-fasm-blocks")

        if "GCC_DYNAMIC_NO_PIC" in self._Settings():
            if self._Settings()["GCC_DYNAMIC_NO_PIC"] == "YES":
                cflags.append("-mdynamic-no-pic")
        else:
            pass
            # TODO: In this case, it depends on the target. xcode passes
            # mdynamic-no-pic by default for executable and possibly static lib
            # according to mento

        if self._Test("GCC_ENABLE_PASCAL_STRINGS", "YES", default="YES"):
            cflags.append("-mpascal-strings")

        self._Appendf(cflags, "GCC_OPTIMIZATION_LEVEL", "-O%s", default="s")

        if self._Test("GCC_GENERATE_DEBUGGING_SYMBOLS", "YES", default="YES"):
            dbg_format = self._Settings().get("DEBUG_INFORMATION_FORMAT", "dwarf")
            if dbg_format == "dwarf":
                cflags.append("-gdwarf-2")
            elif dbg_format == "stabs":
                raise NotImplementedError("stabs debug format is not supported yet.")
            elif dbg_format == "dwarf-with-dsym":
                cflags.append("-gdwarf-2")
            else:
                raise NotImplementedError("Unknown debug format %s" % dbg_format)

        if self._Settings().get("GCC_STRICT_ALIASING") == "YES":
            cflags.append("-fstrict-aliasing")
        elif self._Settings().get("GCC_STRICT_ALIASING") == "NO":
            cflags.append("-fno-strict-aliasing")

        if self._Test("GCC_SYMBOLS_PRIVATE_EXTERN", "YES", default="NO"):
            cflags.append("-fvisibility=hidden")

        if self._Test("GCC_TREAT_WARNINGS_AS_ERRORS", "YES", default="NO"):
            cflags.append("-Werror")

        if self._Test("GCC_WARN_ABOUT_MISSING_NEWLINE", "YES", default="NO"):
            cflags.append("-Wnewline-eof")

        # In Xcode, this is only activated when GCC_COMPILER_VERSION is clang or
        # llvm-gcc. It also requires a fairly recent libtool, and
        # if the system clang isn't used, DYLD_LIBRARY_PATH needs to contain the
        # path to the libLTO.dylib that matches the used clang.
        if self._Test("LLVM_LTO", "YES", default="NO"):
            cflags.append("-flto")

        self._AppendPlatformVersionMinFlags(cflags)

        # TODO:
        if self._Test("COPY_PHASE_STRIP", "YES", default="NO"):
            self._WarnUnimplemented("COPY_PHASE_STRIP")
        self._WarnUnimplemented("GCC_DEBUGGING_SYMBOLS")
        self._WarnUnimplemented("GCC_ENABLE_OBJC_EXCEPTIONS")

        # TODO: This is exported correctly, but assigning to it is not supported.
        self._WarnUnimplemented("MACH_O_TYPE")
        self._WarnUnimplemented("PRODUCT_TYPE")

        # If GYP_CROSSCOMPILE (--cross-compiling), disable architecture-specific
        # additions and assume these will be provided as required via CC_host,
        # CXX_host, CC_target and CXX_target.
        if not gyp.common.CrossCompileRequested():
            if arch is not None:
                archs = [arch]
            else:
                assert self.configname
                archs = self.GetActiveArchs(self.configname)
            if len(archs) != 1:
                # TODO: Supporting fat binaries will be annoying.
                self._WarnUnimplemented("ARCHS")
                archs = ["i386"]
            cflags.append("-arch " + archs[0])

            if archs[0] in ("i386", "x86_64"):
                if self._Test("GCC_ENABLE_SSE3_EXTENSIONS", "YES", default="NO"):
                    cflags.append("-msse3")
                if self._Test(
                    "GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS", "YES", default="NO"
                ):
                    cflags.append("-mssse3")  # Note 3rd 's'.
                if self._Test("GCC_ENABLE_SSE41_EXTENSIONS", "YES", default="NO"):
                    cflags.append("-msse4.1")
                if self._Test("GCC_ENABLE_SSE42_EXTENSIONS", "YES", default="NO"):
                    cflags.append("-msse4.2")

        cflags += self._Settings().get("WARNING_CFLAGS", [])

        if self._IsXCTest():
            platform_root = self._XcodePlatformPath(configname)
            if platform_root:
                cflags.append("-F" + platform_root + "/Developer/Library/Frameworks/")

        framework_root = sdk_root if sdk_root else ""
        config = self.spec["configurations"][self.configname]
        framework_dirs = config.get("mac_framework_dirs", [])
        for directory in framework_dirs:
            cflags.append("-F" + directory.replace("$(SDKROOT)", framework_root))

        self.configname = None
        return cflags

    def GetCflagsC(self, configname):
        """Returns flags that need to be added to .c, and .m compilations."""
        self.configname = configname
        cflags_c = []
        if self._Settings().get("GCC_C_LANGUAGE_STANDARD", "") == "ansi":
            cflags_c.append("-ansi")
        else:
            self._Appendf(cflags_c, "GCC_C_LANGUAGE_STANDARD", "-std=%s")
        cflags_c += self._Settings().get("OTHER_CFLAGS", [])
        self.configname = None
        return cflags_c

    def GetCflagsCC(self, configname):
        """Returns flags that need to be added to .cc, and .mm compilations."""
        self.configname = configname
        cflags_cc = []

        clang_cxx_language_standard = self._Settings().get(
            "CLANG_CXX_LANGUAGE_STANDARD"
        )
        # Note: Don't make c++0x to c++11 so that c++0x can be used with older
        # clangs that don't understand c++11 yet (like Xcode 4.2's).
        if clang_cxx_language_standard:
            cflags_cc.append("-std=%s" % clang_cxx_language_standard)

        self._Appendf(cflags_cc, "CLANG_CXX_LIBRARY", "-stdlib=%s")

        if self._Test("GCC_ENABLE_CPP_RTTI", "NO", default="YES"):
            cflags_cc.append("-fno-rtti")
        if self._Test("GCC_ENABLE_CPP_EXCEPTIONS", "NO", default="YES"):
            cflags_cc.append("-fno-exceptions")
        if self._Test("GCC_INLINES_ARE_PRIVATE_EXTERN", "YES", default="NO"):
            cflags_cc.append("-fvisibility-inlines-hidden")
        if self._Test("GCC_THREADSAFE_STATICS", "NO", default="YES"):
            cflags_cc.append("-fno-threadsafe-statics")
        # Note: This flag is a no-op for clang, it only has an effect for gcc.
        if self._Test("GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO", "NO", default="YES"):
            cflags_cc.append("-Wno-invalid-offsetof")

        other_ccflags = []

        for flag in self._Settings().get("OTHER_CPLUSPLUSFLAGS", ["$(inherited)"]):
            # TODO: More general variable expansion. Missing in many other places too.
            if flag in ("$inherited", "$(inherited)", "${inherited}"):
                flag = "$OTHER_CFLAGS"
            if flag in ("$OTHER_CFLAGS", "$(OTHER_CFLAGS)", "${OTHER_CFLAGS}"):
                other_ccflags += self._Settings().get("OTHER_CFLAGS", [])
            else:
                other_ccflags.append(flag)
        cflags_cc += other_ccflags

        self.configname = None
        return cflags_cc

    def _AddObjectiveCGarbageCollectionFlags(self, flags):
        gc_policy = self._Settings().get("GCC_ENABLE_OBJC_GC", "unsupported")
        if gc_policy == "supported":
            flags.append("-fobjc-gc")
        elif gc_policy == "required":
            flags.append("-fobjc-gc-only")

    def _AddObjectiveCARCFlags(self, flags):
        if self._Test("CLANG_ENABLE_OBJC_ARC", "YES", default="NO"):
            flags.append("-fobjc-arc")

    def _AddObjectiveCMissingPropertySynthesisFlags(self, flags):
        if self._Test(
            "CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS", "YES", default="NO"
        ):
            flags.append("-Wobjc-missing-property-synthesis")

    def GetCflagsObjC(self, configname):
        """Returns flags that need to be added to .m compilations."""
        self.configname = configname
        cflags_objc = []
        self._AddObjectiveCGarbageCollectionFlags(cflags_objc)
        self._AddObjectiveCARCFlags(cflags_objc)
        self._AddObjectiveCMissingPropertySynthesisFlags(cflags_objc)
        self.configname = None
        return cflags_objc

    def GetCflagsObjCC(self, configname):
        """Returns flags that need to be added to .mm compilations."""
        self.configname = configname
        cflags_objcc = []
        self._AddObjectiveCGarbageCollectionFlags(cflags_objcc)
        self._AddObjectiveCARCFlags(cflags_objcc)
        self._AddObjectiveCMissingPropertySynthesisFlags(cflags_objcc)
        if self._Test("GCC_OBJC_CALL_CXX_CDTORS", "YES", default="NO"):
            cflags_objcc.append("-fobjc-call-cxx-cdtors")
        self.configname = None
        return cflags_objcc

    def GetInstallNameBase(self):
        """Return DYLIB_INSTALL_NAME_BASE for this target."""
        # Xcode sets this for shared_libraries, and for nonbundled loadable_modules.
        if self.spec["type"] != "shared_library" and (
            self.spec["type"] != "loadable_module" or self._IsBundle()
        ):
            return None
        install_base = self.GetPerTargetSetting(
            "DYLIB_INSTALL_NAME_BASE",
            default="/Library/Frameworks" if self._IsBundle() else "/usr/local/lib",
        )
        return install_base

    def _StandardizePath(self, path):
        """Do :standardizepath processing for path."""
        # I'm not quite sure what :standardizepath does. Just call normpath(),
        # but don't let @executable_path/../foo collapse to foo.
        if "/" in path:
            prefix, rest = "", path
            if path.startswith("@"):
                prefix, rest = path.split("/", 1)
            rest = os.path.normpath(rest)  # :standardizepath
            path = os.path.join(prefix, rest)
        return path

    def GetInstallName(self):
        """Return LD_DYLIB_INSTALL_NAME for this target."""
        # Xcode sets this for shared_libraries, and for nonbundled loadable_modules.
        if self.spec["type"] != "shared_library" and (
            self.spec["type"] != "loadable_module" or self._IsBundle()
        ):
            return None

        default_install_name = (
            "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)"
        )
        install_name = self.GetPerTargetSetting(
            "LD_DYLIB_INSTALL_NAME", default=default_install_name
        )

        # Hardcode support for the variables used in chromium for now, to
        # unblock people using the make build.
        if "$" in install_name:
            assert install_name in (
                "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/"
                "$(WRAPPER_NAME)/$(PRODUCT_NAME)",
                default_install_name,
            ), (
                "Variables in LD_DYLIB_INSTALL_NAME are not generally supported "
                "yet in target '%s' (got '%s')"
                % (self.spec["target_name"], install_name)
            )

            install_name = install_name.replace(
                "$(DYLIB_INSTALL_NAME_BASE:standardizepath)",
                self._StandardizePath(self.GetInstallNameBase()),
            )
            if self._IsBundle():
                # These are only valid for bundles, hence the |if|.
                install_name = install_name.replace(
                    "$(WRAPPER_NAME)", self.GetWrapperName()
                )
                install_name = install_name.replace(
                    "$(PRODUCT_NAME)", self.GetProductName()
                )
            else:
                assert "$(WRAPPER_NAME)" not in install_name
                assert "$(PRODUCT_NAME)" not in install_name

            install_name = install_name.replace(
                "$(EXECUTABLE_PATH)", self.GetExecutablePath()
            )
        return install_name

    def _MapLinkerFlagFilename(self, ldflag, gyp_to_build_path):
        """Checks if ldflag contains a filename and if so remaps it from
    gyp-directory-relative to build-directory-relative."""
        # This list is expanded on demand.
        # They get matched as:
        #   -exported_symbols_list file
        #   -Wl,exported_symbols_list file
        #   -Wl,exported_symbols_list,file
        LINKER_FILE = r"(\S+)"
        WORD = r"\S+"
        linker_flags = [
            ["-exported_symbols_list", LINKER_FILE],  # Needed for NaCl.
            ["-unexported_symbols_list", LINKER_FILE],
            ["-reexported_symbols_list", LINKER_FILE],
            ["-sectcreate", WORD, WORD, LINKER_FILE],  # Needed for remoting.
        ]
        for flag_pattern in linker_flags:
            regex = re.compile("(?:-Wl,)?" + "[ ,]".join(flag_pattern))
            m = regex.match(ldflag)
            if m:
                ldflag = (
                    ldflag[: m.start(1)]
                    + gyp_to_build_path(m.group(1))
                    + ldflag[m.end(1) :]
                )
        # Required for ffmpeg (no idea why they don't use LIBRARY_SEARCH_PATHS,
        # TODO(thakis): Update ffmpeg.gyp):
        if ldflag.startswith("-L"):
            ldflag = "-L" + gyp_to_build_path(ldflag[len("-L") :])
        return ldflag

    def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None):
        """Returns flags that need to be passed to the linker.

    Args:
        configname: The name of the configuration to get ld flags for.
        product_dir: The directory where products such static and dynamic
            libraries are placed. This is added to the library search path.
        gyp_to_build_path: A function that converts paths relative to the
            current gyp file to paths relative to the build directory.
    """
        self.configname = configname
        ldflags = []

        # The xcode build is relative to a gyp file's directory, and OTHER_LDFLAGS
        # can contain entries that depend on this. Explicitly absolutify these.
        for ldflag in self._Settings().get("OTHER_LDFLAGS", []):
            ldflags.append(self._MapLinkerFlagFilename(ldflag, gyp_to_build_path))

        if self._Test("DEAD_CODE_STRIPPING", "YES", default="NO"):
            ldflags.append("-Wl,-dead_strip")

        if self._Test("PREBINDING", "YES", default="NO"):
            ldflags.append("-Wl,-prebind")

        self._Appendf(
            ldflags, "DYLIB_COMPATIBILITY_VERSION", "-compatibility_version %s"
        )
        self._Appendf(ldflags, "DYLIB_CURRENT_VERSION", "-current_version %s")

        self._AppendPlatformVersionMinFlags(ldflags)

        if "SDKROOT" in self._Settings() and self._SdkPath():
            ldflags.append("-isysroot " + self._SdkPath())

        for library_path in self._Settings().get("LIBRARY_SEARCH_PATHS", []):
            ldflags.append("-L" + gyp_to_build_path(library_path))

        if "ORDER_FILE" in self._Settings():
            ldflags.append(
                "-Wl,-order_file "
                + "-Wl,"
                + gyp_to_build_path(self._Settings()["ORDER_FILE"])
            )

        if not gyp.common.CrossCompileRequested():
            if arch is not None:
                archs = [arch]
            else:
                assert self.configname
                archs = self.GetActiveArchs(self.configname)
            if len(archs) != 1:
                # TODO: Supporting fat binaries will be annoying.
                self._WarnUnimplemented("ARCHS")
                archs = ["i386"]
            ldflags.append("-arch " + archs[0])

        # Xcode adds the product directory by default.
        # Rewrite -L. to -L./ to work around http://www.openradar.me/25313838
        ldflags.append("-L" + (product_dir if product_dir != "." else "./"))

        install_name = self.GetInstallName()
        if install_name and self.spec["type"] != "loadable_module":
            ldflags.append("-install_name " + install_name.replace(" ", r"\ "))

        for rpath in self._Settings().get("LD_RUNPATH_SEARCH_PATHS", []):
            ldflags.append("-Wl,-rpath," + rpath)

        sdk_root = self._SdkPath()
        if not sdk_root:
            sdk_root = ""
        config = self.spec["configurations"][self.configname]
        framework_dirs = config.get("mac_framework_dirs", [])
        for directory in framework_dirs:
            ldflags.append("-F" + directory.replace("$(SDKROOT)", sdk_root))

        if self._IsXCTest():
            platform_root = self._XcodePlatformPath(configname)
            if sdk_root and platform_root:
                ldflags.append("-F" + platform_root + "/Developer/Library/Frameworks/")
                ldflags.append("-framework XCTest")

        is_extension = self._IsIosAppExtension() or self._IsIosWatchKitExtension()
        if sdk_root and is_extension:
            # Adds the link flags for extensions. These flags are common for all
            # extensions and provide loader and main function.
            # These flags reflect the compilation options used by xcode to compile
            # extensions.
            xcode_version, _ = XcodeVersion()
            if xcode_version < "0900":
                ldflags.append("-lpkstart")
                ldflags.append(
                    sdk_root
                    + "/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit"
                )
            else:
                ldflags.append("-e _NSExtensionMain")
            ldflags.append("-fapplication-extension")

        self._Appendf(ldflags, "CLANG_CXX_LIBRARY", "-stdlib=%s")

        self.configname = None
        return ldflags

    def GetLibtoolflags(self, configname):
        """Returns flags that need to be passed to the static linker.

    Args:
        configname: The name of the configuration to get ld flags for.
    """
        self.configname = configname
        libtoolflags = []

        for libtoolflag in self._Settings().get("OTHER_LDFLAGS", []):
            libtoolflags.append(libtoolflag)
        # TODO(thakis): ARCHS?

        self.configname = None
        return libtoolflags

    def GetPerTargetSettings(self):
        """Gets a list of all the per-target settings. This will only fetch keys
    whose values are the same across all configurations."""
        first_pass = True
        result = {}
        for configname in sorted(self.xcode_settings.keys()):
            if first_pass:
                result = dict(self.xcode_settings[configname])
                first_pass = False
            else:
                for key, value in self.xcode_settings[configname].items():
                    if key not in result:
                        continue
                    elif result[key] != value:
                        del result[key]
        return result

    def GetPerConfigSetting(self, setting, configname, default=None):
        if configname in self.xcode_settings:
            return self.xcode_settings[configname].get(setting, default)
        else:
            return self.GetPerTargetSetting(setting, default)

    def GetPerTargetSetting(self, setting, default=None):
        """Tries to get xcode_settings.setting from spec. Assumes that the setting
       has the same value in all configurations and throws otherwise."""
        is_first_pass = True
        result = None
        for configname in sorted(self.xcode_settings.keys()):
            if is_first_pass:
                result = self.xcode_settings[configname].get(setting, None)
                is_first_pass = False
            else:
                assert result == self.xcode_settings[configname].get(setting, None), (
                    "Expected per-target setting for '%s', got per-config setting "
                    "(target %s)" % (setting, self.spec["target_name"])
                )
        if result is None:
            return default
        return result

    def _GetStripPostbuilds(self, configname, output_binary, quiet):
        """Returns a list of shell commands that contain the shell commands
    necessary to strip this target's binary. These should be run as postbuilds
    before the actual postbuilds run."""
        self.configname = configname

        result = []
        if self._Test("DEPLOYMENT_POSTPROCESSING", "YES", default="NO") and self._Test(
            "STRIP_INSTALLED_PRODUCT", "YES", default="NO"
        ):

            default_strip_style = "debugging"
            if (
                self.spec["type"] == "loadable_module" or self._IsIosAppExtension()
            ) and self._IsBundle():
                default_strip_style = "non-global"
            elif self.spec["type"] == "executable":
                default_strip_style = "all"

            strip_style = self._Settings().get("STRIP_STYLE", default_strip_style)
            strip_flags = {"all": "", "non-global": "-x", "debugging": "-S"}[
                strip_style
            ]

            explicit_strip_flags = self._Settings().get("STRIPFLAGS", "")
            if explicit_strip_flags:
                strip_flags += " " + _NormalizeEnvVarReferences(explicit_strip_flags)

            if not quiet:
                result.append("echo STRIP\\(%s\\)" % self.spec["target_name"])
            result.append(f"strip {strip_flags} {output_binary}")

        self.configname = None
        return result

    def _GetDebugInfoPostbuilds(self, configname, output, output_binary, quiet):
        """Returns a list of shell commands that contain the shell commands
    necessary to massage this target's debug information. These should be run
    as postbuilds before the actual postbuilds run."""
        self.configname = configname

        # For static libraries, no dSYMs are created.
        result = []
        if (
            self._Test("GCC_GENERATE_DEBUGGING_SYMBOLS", "YES", default="YES")
            and self._Test(
                "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym", default="dwarf"
            )
            and self.spec["type"] != "static_library"
        ):
            if not quiet:
                result.append("echo DSYMUTIL\\(%s\\)" % self.spec["target_name"])
            result.append("dsymutil {} -o {}".format(output_binary, output + ".dSYM"))

        self.configname = None
        return result

    def _GetTargetPostbuilds(self, configname, output, output_binary, quiet=False):
        """Returns a list of shell commands that contain the shell commands
    to run as postbuilds for this target, before the actual postbuilds."""
        # dSYMs need to build before stripping happens.
        return self._GetDebugInfoPostbuilds(
            configname, output, output_binary, quiet
        ) + self._GetStripPostbuilds(configname, output_binary, quiet)

    def _GetIOSPostbuilds(self, configname, output_binary):
        """Return a shell command to codesign the iOS output binary so it can
    be deployed to a device.  This should be run as the very last step of the
    build."""
        if not (
            self.isIOS
            and (self.spec["type"] == "executable" or self._IsXCTest())
            or self.IsIosFramework()
        ):
            return []

        postbuilds = []
        product_name = self.GetFullProductName()
        settings = self.xcode_settings[configname]

        # Xcode expects XCTests to be copied into the TEST_HOST dir.
        if self._IsXCTest():
            source = os.path.join("${BUILT_PRODUCTS_DIR}", product_name)
            test_host = os.path.dirname(settings.get("TEST_HOST"))
            xctest_destination = os.path.join(test_host, "PlugIns", product_name)
            postbuilds.extend([f"ditto {source} {xctest_destination}"])

        key = self._GetIOSCodeSignIdentityKey(settings)
        if not key:
            return postbuilds

        # Warn for any unimplemented signing xcode keys.
        unimpl = ["OTHER_CODE_SIGN_FLAGS"]
        unimpl = set(unimpl) & set(self.xcode_settings[configname].keys())
        if unimpl:
            print(
                "Warning: Some codesign keys not implemented, ignoring: %s"
                % ", ".join(sorted(unimpl))
            )

        if self._IsXCTest():
            # For device xctests, Xcode copies two extra frameworks into $TEST_HOST.
            test_host = os.path.dirname(settings.get("TEST_HOST"))
            frameworks_dir = os.path.join(test_host, "Frameworks")
            platform_root = self._XcodePlatformPath(configname)
            frameworks = [
                "Developer/Library/PrivateFrameworks/IDEBundleInjection.framework",
                "Developer/Library/Frameworks/XCTest.framework",
            ]
            for framework in frameworks:
                source = os.path.join(platform_root, framework)
                destination = os.path.join(frameworks_dir, os.path.basename(framework))
                postbuilds.extend([f"ditto {source} {destination}"])

                # Then re-sign everything with 'preserve=True'
                postbuilds.extend(
                    [
                        '%s code-sign-bundle "%s" "%s" "%s" "%s" %s'
                        % (
                            os.path.join("${TARGET_BUILD_DIR}", "gyp-mac-tool"),
                            key,
                            settings.get("CODE_SIGN_ENTITLEMENTS", ""),
                            settings.get("PROVISIONING_PROFILE", ""),
                            destination,
                            True,
                        )
                    ]
                )
            plugin_dir = os.path.join(test_host, "PlugIns")
            targets = [os.path.join(plugin_dir, product_name), test_host]
            for target in targets:
                postbuilds.extend(
                    [
                        '%s code-sign-bundle "%s" "%s" "%s" "%s" %s'
                        % (
                            os.path.join("${TARGET_BUILD_DIR}", "gyp-mac-tool"),
                            key,
                            settings.get("CODE_SIGN_ENTITLEMENTS", ""),
                            settings.get("PROVISIONING_PROFILE", ""),
                            target,
                            True,
                        )
                    ]
                )

        postbuilds.extend(
            [
                '%s code-sign-bundle "%s" "%s" "%s" "%s" %s'
                % (
                    os.path.join("${TARGET_BUILD_DIR}", "gyp-mac-tool"),
                    key,
                    settings.get("CODE_SIGN_ENTITLEMENTS", ""),
                    settings.get("PROVISIONING_PROFILE", ""),
                    os.path.join("${BUILT_PRODUCTS_DIR}", product_name),
                    False,
                )
            ]
        )
        return postbuilds

    def _GetIOSCodeSignIdentityKey(self, settings):
        identity = settings.get("CODE_SIGN_IDENTITY")
        if not identity:
            return None
        if identity not in XcodeSettings._codesigning_key_cache:
            output = subprocess.check_output(
                ["security", "find-identity", "-p", "codesigning", "-v"]
            )
            for line in output.splitlines():
                if identity in line:
                    fingerprint = line.split()[1]
                    cache = XcodeSettings._codesigning_key_cache
                    assert identity not in cache or fingerprint == cache[identity], (
                        "Multiple codesigning fingerprints for identity: %s" % identity
                    )
                    XcodeSettings._codesigning_key_cache[identity] = fingerprint
        return XcodeSettings._codesigning_key_cache.get(identity, "")

    def AddImplicitPostbuilds(
        self, configname, output, output_binary, postbuilds=[], quiet=False
    ):
        """Returns a list of shell commands that should run before and after
    |postbuilds|."""
        assert output_binary is not None
        pre = self._GetTargetPostbuilds(configname, output, output_binary, quiet)
        post = self._GetIOSPostbuilds(configname, output_binary)
        return pre + postbuilds + post

    def _AdjustLibrary(self, library, config_name=None):
        if library.endswith(".framework"):
            l_flag = "-framework " + os.path.splitext(os.path.basename(library))[0]
        else:
            m = self.library_re.match(library)
            l_flag = "-l" + m.group(1) if m else library

        sdk_root = self._SdkPath(config_name)
        if not sdk_root:
            sdk_root = ""
        # Xcode 7 started shipping with ".tbd" (text based stubs) files instead of
        # ".dylib" without providing a real support for them. What it does, for
        # "/usr/lib" libraries, is do "-L/usr/lib -lname" which is dependent on the
        # library order and cause collision when building Chrome.
        #
        # Instead substitute ".tbd" to ".dylib" in the generated project when the
        # following conditions are both true:
        # - library is referenced in the gyp file as "$(SDKROOT)/**/*.dylib",
        # - the ".dylib" file does not exists but a ".tbd" file do.
        library = l_flag.replace("$(SDKROOT)", sdk_root)
        if l_flag.startswith("$(SDKROOT)"):
            basename, ext = os.path.splitext(library)
            if ext == ".dylib" and not os.path.exists(library):
                tbd_library = basename + ".tbd"
                if os.path.exists(tbd_library):
                    library = tbd_library
        return library

    def AdjustLibraries(self, libraries, config_name=None):
        """Transforms entries like 'Cocoa.framework' in libraries into entries like
    '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc.
    """
        libraries = [self._AdjustLibrary(library, config_name) for library in libraries]
        return libraries

    def _BuildMachineOSBuild(self):
        return GetStdout(["sw_vers", "-buildVersion"])

    def _XcodeIOSDeviceFamily(self, configname):
        family = self.xcode_settings[configname].get("TARGETED_DEVICE_FAMILY", "1")
        return [int(x) for x in family.split(",")]

    def GetExtraPlistItems(self, configname=None):
        """Returns a dictionary with extra items to insert into Info.plist."""
        if configname not in XcodeSettings._plist_cache:
            cache = {}
            cache["BuildMachineOSBuild"] = self._BuildMachineOSBuild()

            xcode_version, xcode_build = XcodeVersion()
            cache["DTXcode"] = xcode_version
            cache["DTXcodeBuild"] = xcode_build
            compiler = self.xcode_settings[configname].get("GCC_VERSION")
            if compiler is not None:
                cache["DTCompiler"] = compiler

            sdk_root = self._SdkRoot(configname)
            if not sdk_root:
                sdk_root = self._DefaultSdkRoot()
            sdk_version = self._GetSdkVersionInfoItem(sdk_root, "--show-sdk-version")
            cache["DTSDKName"] = sdk_root + (sdk_version or "")
            if xcode_version >= "0720":
                cache["DTSDKBuild"] = self._GetSdkVersionInfoItem(
                    sdk_root, "--show-sdk-build-version"
                )
            elif xcode_version >= "0430":
                cache["DTSDKBuild"] = sdk_version
            else:
                cache["DTSDKBuild"] = cache["BuildMachineOSBuild"]

            if self.isIOS:
                cache["MinimumOSVersion"] = self.xcode_settings[configname].get(
                    "IPHONEOS_DEPLOYMENT_TARGET"
                )
                cache["DTPlatformName"] = sdk_root
                cache["DTPlatformVersion"] = sdk_version

                if configname.endswith("iphoneos"):
                    cache["CFBundleSupportedPlatforms"] = ["iPhoneOS"]
                    cache["DTPlatformBuild"] = cache["DTSDKBuild"]
                else:
                    cache["CFBundleSupportedPlatforms"] = ["iPhoneSimulator"]
                    # This is weird, but Xcode sets DTPlatformBuild to an empty field
                    # for simulator builds.
                    cache["DTPlatformBuild"] = ""
            XcodeSettings._plist_cache[configname] = cache

        # Include extra plist items that are per-target, not per global
        # XcodeSettings.
        items = dict(XcodeSettings._plist_cache[configname])
        if self.isIOS:
            items["UIDeviceFamily"] = self._XcodeIOSDeviceFamily(configname)
        return items

    def _DefaultSdkRoot(self):
        """Returns the default SDKROOT to use.

    Prior to version 5.0.0, if SDKROOT was not explicitly set in the Xcode
    project, then the environment variable was empty. Starting with this
    version, Xcode uses the name of the newest SDK installed.
    """
        xcode_version, _ = XcodeVersion()
        if xcode_version < "0500":
            return ""
        default_sdk_path = self._XcodeSdkPath("")
        default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path)
        if default_sdk_root:
            return default_sdk_root
        try:
            all_sdks = GetStdout(["xcodebuild", "-showsdks"])
        except GypError:
            # If xcodebuild fails, there will be no valid SDKs
            return ""
        for line in all_sdks.splitlines():
            items = line.split()
            if len(items) >= 3 and items[-2] == "-sdk":
                sdk_root = items[-1]
                sdk_path = self._XcodeSdkPath(sdk_root)
                if sdk_path == default_sdk_path:
                    return sdk_root
        return ""


class MacPrefixHeader:
    """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature.

  This feature consists of several pieces:
  * If GCC_PREFIX_HEADER is present, all compilations in that project get an
    additional |-include path_to_prefix_header| cflag.
  * If GCC_PRECOMPILE_PREFIX_HEADER is present too, then the prefix header is
    instead compiled, and all other compilations in the project get an
    additional |-include path_to_compiled_header| instead.
    + Compiled prefix headers have the extension gch. There is one gch file for
      every language used in the project (c, cc, m, mm), since gch files for
      different languages aren't compatible.
    + gch files themselves are built with the target's normal cflags, but they
      obviously don't get the |-include| flag. Instead, they need a -x flag that
      describes their language.
    + All o files in the target need to depend on the gch file, to make sure
      it's built before any o file is built.

  This class helps with some of these tasks, but it needs help from the build
  system for writing dependencies to the gch files, for writing build commands
  for the gch files, and for figuring out the location of the gch files.
  """

    def __init__(
        self, xcode_settings, gyp_path_to_build_path, gyp_path_to_build_output
    ):
        """If xcode_settings is None, all methods on this class are no-ops.

    Args:
        gyp_path_to_build_path: A function that takes a gyp-relative path,
            and returns a path relative to the build directory.
        gyp_path_to_build_output: A function that takes a gyp-relative path and
            a language code ('c', 'cc', 'm', or 'mm'), and that returns a path
            to where the output of precompiling that path for that language
            should be placed (without the trailing '.gch').
    """
        # This doesn't support per-configuration prefix headers. Good enough
        # for now.
        self.header = None
        self.compile_headers = False
        if xcode_settings:
            self.header = xcode_settings.GetPerTargetSetting("GCC_PREFIX_HEADER")
            self.compile_headers = (
                xcode_settings.GetPerTargetSetting(
                    "GCC_PRECOMPILE_PREFIX_HEADER", default="NO"
                )
                != "NO"
            )
        self.compiled_headers = {}
        if self.header:
            if self.compile_headers:
                for lang in ["c", "cc", "m", "mm"]:
                    self.compiled_headers[lang] = gyp_path_to_build_output(
                        self.header, lang
                    )
            self.header = gyp_path_to_build_path(self.header)

    def _CompiledHeader(self, lang, arch):
        assert self.compile_headers
        h = self.compiled_headers[lang]
        if arch:
            h += "." + arch
        return h

    def GetInclude(self, lang, arch=None):
        """Gets the cflags to include the prefix header for language |lang|."""
        if self.compile_headers and lang in self.compiled_headers:
            return "-include %s" % self._CompiledHeader(lang, arch)
        elif self.header:
            return "-include %s" % self.header
        else:
            return ""

    def _Gch(self, lang, arch):
        """Returns the actual file name of the prefix header for language |lang|."""
        assert self.compile_headers
        return self._CompiledHeader(lang, arch) + ".gch"

    def GetObjDependencies(self, sources, objs, arch=None):
        """Given a list of source files and the corresponding object files, returns
    a list of (source, object, gch) tuples, where |gch| is the build-directory
    relative path to the gch file each object file depends on.  |compilable[i]|
    has to be the source file belonging to |objs[i]|."""
        if not self.header or not self.compile_headers:
            return []

        result = []
        for source, obj in zip(sources, objs):
            ext = os.path.splitext(source)[1]
            lang = {
                ".c": "c",
                ".cpp": "cc",
                ".cc": "cc",
                ".cxx": "cc",
                ".m": "m",
                ".mm": "mm",
            }.get(ext, None)
            if lang:
                result.append((source, obj, self._Gch(lang, arch)))
        return result

    def GetPchBuildCommands(self, arch=None):
        """Returns [(path_to_gch, language_flag, language, header)].
    |path_to_gch| and |header| are relative to the build directory.
    """
        if not self.header or not self.compile_headers:
            return []
        return [
            (self._Gch("c", arch), "-x c-header", "c", self.header),
            (self._Gch("cc", arch), "-x c++-header", "cc", self.header),
            (self._Gch("m", arch), "-x objective-c-header", "m", self.header),
            (self._Gch("mm", arch), "-x objective-c++-header", "mm", self.header),
        ]


def XcodeVersion():
    """Returns a tuple of version and build version of installed Xcode."""
    # `xcodebuild -version` output looks like
    #    Xcode 4.6.3
    #    Build version 4H1503
    # or like
    #    Xcode 3.2.6
    #    Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0
    #    BuildVersion: 10M2518
    # Convert that to ('0463', '4H1503') or ('0326', '10M2518').
    global XCODE_VERSION_CACHE
    if XCODE_VERSION_CACHE:
        return XCODE_VERSION_CACHE
    version = ""
    build = ""
    try:
        version_list = GetStdoutQuiet(["xcodebuild", "-version"]).splitlines()
        # In some circumstances xcodebuild exits 0 but doesn't return
        # the right results; for example, a user on 10.7 or 10.8 with
        # a bogus path set via xcode-select
        # In that case this may be a CLT-only install so fall back to
        # checking that version.
        if len(version_list) < 2:
            raise GypError("xcodebuild returned unexpected results")
        version = version_list[0].split()[-1]  # Last word on first line
        build = version_list[-1].split()[-1]  # Last word on last line
    except GypError:  # Xcode not installed so look for XCode Command Line Tools
        version = CLTVersion()  # macOS Catalina returns 11.0.0.0.1.1567737322
        if not version:
            raise GypError("No Xcode or CLT version detected!")
    # Be careful to convert "4.2.3" to "0423" and "11.0.0" to "1100":
    version = version.split(".")[:3]  # Just major, minor, micro
    version[0] = version[0].zfill(2)  # Add a leading zero if major is one digit
    version = ("".join(version) + "00")[:4]  # Limit to exactly four characters
    XCODE_VERSION_CACHE = (version, build)
    return XCODE_VERSION_CACHE


# This function ported from the logic in Homebrew's CLT version check
def CLTVersion():
    """Returns the version of command-line tools from pkgutil."""
    # pkgutil output looks like
    #   package-id: com.apple.pkg.CLTools_Executables
    #   version: 5.0.1.0.1.1382131676
    #   volume: /
    #   location: /
    #   install-time: 1382544035
    #   groups: com.apple.FindSystemFiles.pkg-group
    #           com.apple.DevToolsBoth.pkg-group
    #           com.apple.DevToolsNonRelocatableShared.pkg-group
    STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo"
    FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI"
    MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables"

    regex = re.compile("version: (?P<version>.+)")
    for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]:
        try:
            output = GetStdout(["/usr/sbin/pkgutil", "--pkg-info", key])
            return re.search(regex, output).groupdict()["version"]
        except GypError:
            continue

    regex = re.compile(r"Command Line Tools for Xcode\s+(?P<version>\S+)")
    try:
        output = GetStdout(["/usr/sbin/softwareupdate", "--history"])
        return re.search(regex, output).groupdict()["version"]
    except GypError:
        return None


def GetStdoutQuiet(cmdlist):
    """Returns the content of standard output returned by invoking |cmdlist|.
  Ignores the stderr.
  Raises |GypError| if the command return with a non-zero return code."""
    job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out = job.communicate()[0].decode("utf-8")
    if job.returncode != 0:
        raise GypError("Error %d running %s" % (job.returncode, cmdlist[0]))
    return out.rstrip("\n")


def GetStdout(cmdlist):
    """Returns the content of standard output returned by invoking |cmdlist|.
  Raises |GypError| if the command return with a non-zero return code."""
    job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE)
    out = job.communicate()[0].decode("utf-8")
    if job.returncode != 0:
        sys.stderr.write(out + "\n")
        raise GypError("Error %d running %s" % (job.returncode, cmdlist[0]))
    return out.rstrip("\n")


def MergeGlobalXcodeSettingsToSpec(global_dict, spec):
    """Merges the global xcode_settings dictionary into each configuration of the
  target represented by spec. For keys that are both in the global and the local
  xcode_settings dict, the local key gets precedence.
  """
    # The xcode generator special-cases global xcode_settings and does something
    # that amounts to merging in the global xcode_settings into each local
    # xcode_settings dict.
    global_xcode_settings = global_dict.get("xcode_settings", {})
    for config in spec["configurations"].values():
        if "xcode_settings" in config:
            new_settings = global_xcode_settings.copy()
            new_settings.update(config["xcode_settings"])
            config["xcode_settings"] = new_settings


def IsMacBundle(flavor, spec):
    """Returns if |spec| should be treated as a bundle.

  Bundles are directories with a certain subdirectory structure, instead of
  just a single file. Bundle rules do not produce a binary but also package
  resources into that directory."""
    is_mac_bundle = (
        int(spec.get("mac_xctest_bundle", 0)) != 0
        or int(spec.get("mac_xcuitest_bundle", 0)) != 0
        or (int(spec.get("mac_bundle", 0)) != 0 and flavor == "mac")
    )

    if is_mac_bundle:
        assert spec["type"] != "none", (
            'mac_bundle targets cannot have type none (target "%s")'
            % spec["target_name"]
        )
    return is_mac_bundle


def GetMacBundleResources(product_dir, xcode_settings, resources):
    """Yields (output, resource) pairs for every resource in |resources|.
  Only call this for mac bundle targets.

  Args:
      product_dir: Path to the directory containing the output bundle,
          relative to the build directory.
      xcode_settings: The XcodeSettings of the current target.
      resources: A list of bundle resources, relative to the build directory.
  """
    dest = os.path.join(product_dir, xcode_settings.GetBundleResourceFolder())
    for res in resources:
        output = dest

        # The make generator doesn't support it, so forbid it everywhere
        # to keep the generators more interchangeable.
        assert " " not in res, "Spaces in resource filenames not supported (%s)" % res

        # Split into (path,file).
        res_parts = os.path.split(res)

        # Now split the path into (prefix,maybe.lproj).
        lproj_parts = os.path.split(res_parts[0])
        # If the resource lives in a .lproj bundle, add that to the destination.
        if lproj_parts[1].endswith(".lproj"):
            output = os.path.join(output, lproj_parts[1])

        output = os.path.join(output, res_parts[1])
        # Compiled XIB files are referred to by .nib.
        if output.endswith(".xib"):
            output = os.path.splitext(output)[0] + ".nib"
        # Compiled storyboard files are referred to by .storyboardc.
        if output.endswith(".storyboard"):
            output = os.path.splitext(output)[0] + ".storyboardc"

        yield output, res


def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path):
    """Returns (info_plist, dest_plist, defines, extra_env), where:
  * |info_plist| is the source plist path, relative to the
    build directory,
  * |dest_plist| is the destination plist path, relative to the
    build directory,
  * |defines| is a list of preprocessor defines (empty if the plist
    shouldn't be preprocessed,
  * |extra_env| is a dict of env variables that should be exported when
    invoking |mac_tool copy-info-plist|.

  Only call this for mac bundle targets.

  Args:
      product_dir: Path to the directory containing the output bundle,
          relative to the build directory.
      xcode_settings: The XcodeSettings of the current target.
      gyp_to_build_path: A function that converts paths relative to the
          current gyp file to paths relative to the build directory.
  """
    info_plist = xcode_settings.GetPerTargetSetting("INFOPLIST_FILE")
    if not info_plist:
        return None, None, [], {}

    # The make generator doesn't support it, so forbid it everywhere
    # to keep the generators more interchangeable.
    assert " " not in info_plist, (
        "Spaces in Info.plist filenames not supported (%s)" % info_plist
    )

    info_plist = gyp_path_to_build_path(info_plist)

    # If explicitly set to preprocess the plist, invoke the C preprocessor and
    # specify any defines as -D flags.
    if (
        xcode_settings.GetPerTargetSetting("INFOPLIST_PREPROCESS", default="NO")
        == "YES"
    ):
        # Create an intermediate file based on the path.
        defines = shlex.split(
            xcode_settings.GetPerTargetSetting(
                "INFOPLIST_PREPROCESSOR_DEFINITIONS", default=""
            )
        )
    else:
        defines = []

    dest_plist = os.path.join(product_dir, xcode_settings.GetBundlePlistPath())
    extra_env = xcode_settings.GetPerTargetSettings()

    return info_plist, dest_plist, defines, extra_env


def _GetXcodeEnv(
    xcode_settings, built_products_dir, srcroot, configuration, additional_settings=None
):
    """Return the environment variables that Xcode would set. See
  http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW153
  for a full list.

  Args:
      xcode_settings: An XcodeSettings object. If this is None, this function
          returns an empty dict.
      built_products_dir: Absolute path to the built products dir.
      srcroot: Absolute path to the source root.
      configuration: The build configuration name.
      additional_settings: An optional dict with more values to add to the
          result.
  """

    if not xcode_settings:
        return {}

    # This function is considered a friend of XcodeSettings, so let it reach into
    # its implementation details.
    spec = xcode_settings.spec

    # These are filled in on an as-needed basis.
    env = {
        "BUILT_FRAMEWORKS_DIR": built_products_dir,
        "BUILT_PRODUCTS_DIR": built_products_dir,
        "CONFIGURATION": configuration,
        "PRODUCT_NAME": xcode_settings.GetProductName(),
        # For FULL_PRODUCT_NAME see:
        # /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec  # noqa: E501
        "SRCROOT": srcroot,
        "SOURCE_ROOT": "${SRCROOT}",
        # This is not true for static libraries, but currently the env is only
        # written for bundles:
        "TARGET_BUILD_DIR": built_products_dir,
        "TEMP_DIR": "${TMPDIR}",
        "XCODE_VERSION_ACTUAL": XcodeVersion()[0],
    }
    if xcode_settings.GetPerConfigSetting("SDKROOT", configuration):
        env["SDKROOT"] = xcode_settings._SdkPath(configuration)
    else:
        env["SDKROOT"] = ""

    if xcode_settings.mac_toolchain_dir:
        env["DEVELOPER_DIR"] = xcode_settings.mac_toolchain_dir

    if spec["type"] in (
        "executable",
        "static_library",
        "shared_library",
        "loadable_module",
    ):
        env["EXECUTABLE_NAME"] = xcode_settings.GetExecutableName()
        env["EXECUTABLE_PATH"] = xcode_settings.GetExecutablePath()
        env["FULL_PRODUCT_NAME"] = xcode_settings.GetFullProductName()
        mach_o_type = xcode_settings.GetMachOType()
        if mach_o_type:
            env["MACH_O_TYPE"] = mach_o_type
        env["PRODUCT_TYPE"] = xcode_settings.GetProductType()
    if xcode_settings._IsBundle():
        # xcodeproj_file.py sets the same Xcode subfolder value for this as for
        # FRAMEWORKS_FOLDER_PATH so Xcode builds will actually use FFP's value.
        env["BUILT_FRAMEWORKS_DIR"] = os.path.join(
            built_products_dir + os.sep + xcode_settings.GetBundleFrameworksFolderPath()
        )
        env["CONTENTS_FOLDER_PATH"] = xcode_settings.GetBundleContentsFolderPath()
        env["EXECUTABLE_FOLDER_PATH"] = xcode_settings.GetBundleExecutableFolderPath()
        env[
            "UNLOCALIZED_RESOURCES_FOLDER_PATH"
        ] = xcode_settings.GetBundleResourceFolder()
        env["JAVA_FOLDER_PATH"] = xcode_settings.GetBundleJavaFolderPath()
        env["FRAMEWORKS_FOLDER_PATH"] = xcode_settings.GetBundleFrameworksFolderPath()
        env[
            "SHARED_FRAMEWORKS_FOLDER_PATH"
        ] = xcode_settings.GetBundleSharedFrameworksFolderPath()
        env[
            "SHARED_SUPPORT_FOLDER_PATH"
        ] = xcode_settings.GetBundleSharedSupportFolderPath()
        env["PLUGINS_FOLDER_PATH"] = xcode_settings.GetBundlePlugInsFolderPath()
        env["XPCSERVICES_FOLDER_PATH"] = xcode_settings.GetBundleXPCServicesFolderPath()
        env["INFOPLIST_PATH"] = xcode_settings.GetBundlePlistPath()
        env["WRAPPER_NAME"] = xcode_settings.GetWrapperName()

    install_name = xcode_settings.GetInstallName()
    if install_name:
        env["LD_DYLIB_INSTALL_NAME"] = install_name
    install_name_base = xcode_settings.GetInstallNameBase()
    if install_name_base:
        env["DYLIB_INSTALL_NAME_BASE"] = install_name_base
    xcode_version, _ = XcodeVersion()
    if xcode_version >= "0500" and not env.get("SDKROOT"):
        sdk_root = xcode_settings._SdkRoot(configuration)
        if not sdk_root:
            sdk_root = xcode_settings._XcodeSdkPath("")
        if sdk_root is None:
            sdk_root = ""
        env["SDKROOT"] = sdk_root

    if not additional_settings:
        additional_settings = {}
    else:
        # Flatten lists to strings.
        for k in additional_settings:
            if not isinstance(additional_settings[k], str):
                additional_settings[k] = " ".join(additional_settings[k])
    additional_settings.update(env)

    for k in additional_settings:
        additional_settings[k] = _NormalizeEnvVarReferences(additional_settings[k])

    return additional_settings


def _NormalizeEnvVarReferences(str):
    """Takes a string containing variable references in the form ${FOO}, $(FOO),
  or $FOO, and returns a string with all variable references in the form ${FOO}.
  """
    # $FOO -> ${FOO}
    str = re.sub(r"\$([a-zA-Z_][a-zA-Z0-9_]*)", r"${\1}", str)

    # $(FOO) -> ${FOO}
    matches = re.findall(r"(\$\(([a-zA-Z0-9\-_]+)\))", str)
    for match in matches:
        to_replace, variable = match
        assert "$(" not in match, "$($(FOO)) variables not supported: " + match
        str = str.replace(to_replace, "${" + variable + "}")

    return str


def ExpandEnvVars(string, expansions):
    """Expands ${VARIABLES}, $(VARIABLES), and $VARIABLES in string per the
  expansions list. If the variable expands to something that references
  another variable, this variable is expanded as well if it's in env --
  until no variables present in env are left."""
    for k, v in reversed(expansions):
        string = string.replace("${" + k + "}", v)
        string = string.replace("$(" + k + ")", v)
        string = string.replace("$" + k, v)
    return string


def _TopologicallySortedEnvVarKeys(env):
    """Takes a dict |env| whose values are strings that can refer to other keys,
  for example env['foo'] = '$(bar) and $(baz)'. Returns a list L of all keys of
  env such that key2 is after key1 in L if env[key2] refers to env[key1].

  Throws an Exception in case of dependency cycles.
  """
    # Since environment variables can refer to other variables, the evaluation
    # order is important. Below is the logic to compute the dependency graph
    # and sort it.
    regex = re.compile(r"\$\{([a-zA-Z0-9\-_]+)\}")

    def GetEdges(node):
        # Use a definition of edges such that user_of_variable -> used_varible.
        # This happens to be easier in this case, since a variable's
        # definition contains all variables it references in a single string.
        # We can then reverse the result of the topological sort at the end.
        # Since: reverse(topsort(DAG)) = topsort(reverse_edges(DAG))
        matches = {v for v in regex.findall(env[node]) if v in env}
        for dependee in matches:
            assert "${" not in dependee, "Nested variables not supported: " + dependee
        return matches

    try:
        # Topologically sort, and then reverse, because we used an edge definition
        # that's inverted from the expected result of this function (see comment
        # above).
        order = gyp.common.TopologicallySorted(env.keys(), GetEdges)
        order.reverse()
        return order
    except gyp.common.CycleError as e:
        raise GypError(
            "Xcode environment variables are cyclically dependent: " + str(e.nodes)
        )


def GetSortedXcodeEnv(
    xcode_settings, built_products_dir, srcroot, configuration, additional_settings=None
):
    env = _GetXcodeEnv(
        xcode_settings, built_products_dir, srcroot, configuration, additional_settings
    )
    return [(key, env[key]) for key in _TopologicallySortedEnvVarKeys(env)]


def GetSpecPostbuildCommands(spec, quiet=False):
    """Returns the list of postbuilds explicitly defined on |spec|, in a form
  executable by a shell."""
    postbuilds = []
    for postbuild in spec.get("postbuilds", []):
        if not quiet:
            postbuilds.append(
                "echo POSTBUILD\\(%s\\) %s"
                % (spec["target_name"], postbuild["postbuild_name"])
            )
        postbuilds.append(gyp.common.EncodePOSIXShellList(postbuild["action"]))
    return postbuilds


def _HasIOSTarget(targets):
    """Returns true if any target contains the iOS specific key
  IPHONEOS_DEPLOYMENT_TARGET."""
    for target_dict in targets.values():
        for config in target_dict["configurations"].values():
            if config.get("xcode_settings", {}).get("IPHONEOS_DEPLOYMENT_TARGET"):
                return True
    return False


def _AddIOSDeviceConfigurations(targets):
    """Clone all targets and append -iphoneos to the name. Configure these targets
  to build for iOS devices and use correct architectures for those builds."""
    for target_dict in targets.values():
        toolset = target_dict["toolset"]
        configs = target_dict["configurations"]
        for config_name, simulator_config_dict in dict(configs).items():
            iphoneos_config_dict = copy.deepcopy(simulator_config_dict)
            configs[config_name + "-iphoneos"] = iphoneos_config_dict
            configs[config_name + "-iphonesimulator"] = simulator_config_dict
            if toolset == "target":
                simulator_config_dict["xcode_settings"]["SDKROOT"] = "iphonesimulator"
                iphoneos_config_dict["xcode_settings"]["SDKROOT"] = "iphoneos"
    return targets


def CloneConfigurationForDeviceAndEmulator(target_dicts):
    """If |target_dicts| contains any iOS targets, automatically create -iphoneos
  targets for iOS device builds."""
    if _HasIOSTarget(target_dicts):
        return _AddIOSDeviceConfigurations(target_dicts)
    return target_dicts
                                                                                                                                                                                                #!/usr/bin/env python3

# Copyright (c) 2012 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Unit tests for the MSVSSettings.py file."""

import unittest
import gyp.MSVSSettings as MSVSSettings

from io import StringIO


class TestSequenceFunctions(unittest.TestCase):
    def setUp(self):
        self.stderr = StringIO()

    def _ExpectedWarnings(self, expected):
        """Compares recorded lines to expected warnings."""
        self.stderr.seek(0)
        actual = self.stderr.read().split("\n")
        actual = [line for line in actual if line]
        self.assertEqual(sorted(expected), sorted(actual))

    def testValidateMSVSSettings_tool_names(self):
        """Tests that only MSVS tool names are allowed."""
        MSVSSettings.ValidateMSVSSettings(
            {
                "VCCLCompilerTool": {},
                "VCLinkerTool": {},
                "VCMIDLTool": {},
                "foo": {},
                "VCResourceCompilerTool": {},
                "VCLibrarianTool": {},
                "VCManifestTool": {},
                "ClCompile": {},
            },
            self.stderr,
        )
        self._ExpectedWarnings(
            ["Warning: unrecognized tool foo", "Warning: unrecognized tool ClCompile"]
        )

    def testValidateMSVSSettings_settings(self):
        """Tests that for invalid MSVS settings."""
        MSVSSettings.ValidateMSVSSettings(
            {
                "VCCLCompilerTool": {
                    "AdditionalIncludeDirectories": "folder1;folder2",
                    "AdditionalOptions": ["string1", "string2"],
                    "AdditionalUsingDirectories": "folder1;folder2",
                    "AssemblerListingLocation": "a_file_name",
                    "AssemblerOutput": "0",
                    "BasicRuntimeChecks": "5",
                    "BrowseInformation": "fdkslj",
                    "BrowseInformationFile": "a_file_name",
                    "BufferSecurityCheck": "true",
                    "CallingConvention": "-1",
                    "CompileAs": "1",
                    "DebugInformationFormat": "2",
                    "DefaultCharIsUnsigned": "true",
                    "Detect64BitPortabilityProblems": "true",
                    "DisableLanguageExtensions": "true",
                    "DisableSpecificWarnings": "string1;string2",
                    "EnableEnhancedInstructionSet": "1",
                    "EnableFiberSafeOptimizations": "true",
                    "EnableFunctionLevelLinking": "true",
                    "EnableIntrinsicFunctions": "true",
                    "EnablePREfast": "true",
                    "Enableprefast": "bogus",
                    "ErrorReporting": "1",
                    "ExceptionHandling": "1",
                    "ExpandAttributedSource": "true",
                    "FavorSizeOrSpeed": "1",
                    "FloatingPointExceptions": "true",
                    "FloatingPointModel": "1",
                    "ForceConformanceInForLoopScope": "true",
                    "ForcedIncludeFiles": "file1;file2",
                    "ForcedUsingFiles": "file1;file2",
                    "GeneratePreprocessedFile": "1",
                    "GenerateXMLDocumentationFiles": "true",
                    "IgnoreStandardIncludePath": "true",
                    "InlineFunctionExpansion": "1",
                    "KeepComments": "true",
                    "MinimalRebuild": "true",
                    "ObjectFile": "a_file_name",
                    "OmitDefaultLibName": "true",
                    "OmitFramePointers": "true",
                    "OpenMP": "true",
                    "Optimization": "1",
                    "PrecompiledHeaderFile": "a_file_name",
                    "PrecompiledHeaderThrough": "a_file_name",
                    "PreprocessorDefinitions": "string1;string2",
                    "ProgramDataBaseFileName": "a_file_name",
                    "RuntimeLibrary": "1",
                    "RuntimeTypeInfo": "true",
                    "ShowIncludes": "true",
                    "SmallerTypeCheck": "true",
                    "StringPooling": "true",
                    "StructMemberAlignment": "1",
                    "SuppressStartupBanner": "true",
                    "TreatWChar_tAsBuiltInType": "true",
                    "UndefineAllPreprocessorDefinitions": "true",
                    "UndefinePreprocessorDefinitions": "string1;string2",
                    "UseFullPaths": "true",
                    "UsePrecompiledHeader": "1",
                    "UseUnicodeResponseFiles": "true",
                    "WarnAsError": "true",
                    "WarningLevel": "1",
                    "WholeProgramOptimization": "true",
                    "XMLDocumentationFileName": "a_file_name",
                    "ZZXYZ": "bogus",
                },
                "VCLinkerTool": {
                    "AdditionalDependencies": "file1;file2",
                    "AdditionalDependencies_excluded": "file3",
                    "AdditionalLibraryDirectories": "folder1;folder2",
                    "AdditionalManifestDependencies": "file1;file2",
                    "AdditionalOptions": "a string1",
                    "AddModuleNamesToAssembly": "file1;file2",
                    "AllowIsolation": "true",
                    "AssemblyDebug": "2",
                    "AssemblyLinkResource": "file1;file2",
                    "BaseAddress": "a string1",
                    "CLRImageType": "2",
                    "CLRThreadAttribute": "2",
                    "CLRUnmanagedCodeCheck": "true",
                    "DataExecutionPrevention": "2",
                    "DelayLoadDLLs": "file1;file2",
                    "DelaySign": "true",
                    "Driver": "2",
                    "EmbedManagedResourceFile": "file1;file2",
                    "EnableCOMDATFolding": "2",
                    "EnableUAC": "true",
                    "EntryPointSymbol": "a string1",
                    "ErrorReporting": "2",
                    "FixedBaseAddress": "2",
                    "ForceSymbolReferences": "file1;file2",
                    "FunctionOrder": "a_file_name",
                    "GenerateDebugInformation": "true",
                    "GenerateManifest": "true",
                    "GenerateMapFile": "true",
                    "HeapCommitSize": "a string1",
                    "HeapReserveSize": "a string1",
                    "IgnoreAllDefaultLibraries": "true",
                    "IgnoreDefaultLibraryNames": "file1;file2",
                    "IgnoreEmbeddedIDL": "true",
                    "IgnoreImportLibrary": "true",
                    "ImportLibrary": "a_file_name",
                    "KeyContainer": "a_file_name",
                    "KeyFile": "a_file_name",
                    "LargeAddressAware": "2",
                    "LinkIncremental": "2",
                    "LinkLibraryDependencies": "true",
                    "LinkTimeCodeGeneration": "2",
                    "ManifestFile": "a_file_name",
                    "MapExports": "true",
                    "MapFileName": "a_file_name",
                    "MergedIDLBaseFileName": "a_file_name",
                    "MergeSections": "a string1",
                    "MidlCommandFile": "a_file_name",
                    "ModuleDefinitionFile": "a_file_name",
                    "OptimizeForWindows98": "1",
                    "OptimizeReferences": "2",
                    "OutputFile": "a_file_name",
                    "PerUserRedirection": "true",
                    "Profile": "true",
                    "ProfileGuidedDatabase": "a_file_name",
                    "ProgramDatabaseFile": "a_file_name",
                    "RandomizedBaseAddress": "2",
                    "RegisterOutput": "true",
                    "ResourceOnlyDLL": "true",
                    "SetChecksum": "true",
                    "ShowProgress": "2",
                    "StackCommitSize": "a string1",
                    "StackReserveSize": "a string1",
                    "StripPrivateSymbols": "a_file_name",
                    "SubSystem": "2",
                    "SupportUnloadOfDelayLoadedDLL": "true",
                    "SuppressStartupBanner": "true",
                    "SwapRunFromCD": "true",
                    "SwapRunFromNet": "true",
                    "TargetMachine": "2",
                    "TerminalServerAware": "2",
                    "TurnOffAssemblyGeneration": "true",
                    "TypeLibraryFile": "a_file_name",
                    "TypeLibraryResourceID": "33",
                    "UACExecutionLevel": "2",
                    "UACUIAccess": "true",
                    "UseLibraryDependencyInputs": "true",
                    "UseUnicodeResponseFiles": "true",
                    "Version": "a string1",
                },
                "VCMIDLTool": {
                    "AdditionalIncludeDirectories": "folder1;folder2",
                    "AdditionalOptions": "a string1",
                    "CPreprocessOptions": "a string1",
                    "DefaultCharType": "1",
                    "DLLDataFileName": "a_file_name",
                    "EnableErrorChecks": "1",
                    "ErrorCheckAllocations": "true",
                    "ErrorCheckBounds": "true",
                    "ErrorCheckEnumRange": "true",
                    "ErrorCheckRefPointers": "true",
                    "ErrorCheckStubData": "true",
                    "GenerateStublessProxies": "true",
                    "GenerateTypeLibrary": "true",
                    "HeaderFileName": "a_file_name",
                    "IgnoreStandardIncludePath": "true",
                    "InterfaceIdentifierFileName": "a_file_name",
                    "MkTypLibCompatible": "true",
                    "notgood": "bogus",
                    "OutputDirectory": "a string1",
                    "PreprocessorDefinitions": "string1;string2",
                    "ProxyFileName": "a_file_name",
                    "RedirectOutputAndErrors": "a_file_name",
                    "StructMemberAlignment": "1",
                    "SuppressStartupBanner": "true",
                    "TargetEnvironment": "1",
                    "TypeLibraryName": "a_file_name",
                    "UndefinePreprocessorDefinitions": "string1;string2",
                    "ValidateParameters": "true",
                    "WarnAsError": "true",
                    "WarningLevel": "1",
                },
                "VCResourceCompilerTool": {
                    "AdditionalOptions": "a string1",
                    "AdditionalIncludeDirectories": "folder1;folder2",
                    "Culture": "1003",
                    "IgnoreStandardIncludePath": "true",
                    "notgood2": "bogus",
                    "PreprocessorDefinitions": "string1;string2",
                    "ResourceOutputFileName": "a string1",
                    "ShowProgress": "true",
                    "SuppressStartupBanner": "true",
                    "UndefinePreprocessorDefinitions": "string1;string2",
                },
                "VCLibrarianTool": {
                    "AdditionalDependencies": "file1;file2",
                    "AdditionalLibraryDirectories": "folder1;folder2",
                    "AdditionalOptions": "a string1",
                    "ExportNamedFunctions": "string1;string2",
                    "ForceSymbolReferences": "a string1",
                    "IgnoreAllDefaultLibraries": "true",
                    "IgnoreSpecificDefaultLibraries": "file1;file2",
                    "LinkLibraryDependencies": "true",
                    "ModuleDefinitionFile": "a_file_name",
                    "OutputFile": "a_file_name",
                    "SuppressStartupBanner": "true",
                    "UseUnicodeResponseFiles": "true",
                },
                "VCManifestTool": {
                    "AdditionalManifestFiles": "file1;file2",
                    "AdditionalOptions": "a string1",
                    "AssemblyIdentity": "a string1",
                    "ComponentFileName": "a_file_name",
                    "DependencyInformationFile": "a_file_name",
                    "GenerateCatalogFiles": "true",
                    "InputResourceManifests": "a string1",
                    "ManifestResourceFile": "a_file_name",
                    "OutputManifestFile": "a_file_name",
                    "RegistrarScriptFile": "a_file_name",
                    "ReplacementsFile": "a_file_name",
                    "SuppressStartupBanner": "true",
                    "TypeLibraryFile": "a_file_name",
                    "UpdateFileHashes": "truel",
                    "UpdateFileHashesSearchPath": "a_file_name",
                    "UseFAT32Workaround": "true",
                    "UseUnicodeResponseFiles": "true",
                    "VerboseOutput": "true",
                },
            },
            self.stderr,
        )
        self._ExpectedWarnings(
            [
                "Warning: for VCCLCompilerTool/BasicRuntimeChecks, "
                "index value (5) not in expected range [0, 4)",
                "Warning: for VCCLCompilerTool/BrowseInformation, "
                "invalid literal for int() with base 10: 'fdkslj'",
                "Warning: for VCCLCompilerTool/CallingConvention, "
                "index value (-1) not in expected range [0, 4)",
                "Warning: for VCCLCompilerTool/DebugInformationFormat, "
                "converted value for 2 not specified.",
                "Warning: unrecognized setting VCCLCompilerTool/Enableprefast",
                "Warning: unrecognized setting VCCLCompilerTool/ZZXYZ",
                "Warning: for VCLinkerTool/TargetMachine, "
                "converted value for 2 not specified.",
                "Warning: unrecognized setting VCMIDLTool/notgood",
                "Warning: unrecognized setting VCResourceCompilerTool/notgood2",
                "Warning: for VCManifestTool/UpdateFileHashes, "
                "expected bool; got 'truel'"
                "",
            ]
        )

    def testValidateMSBuildSettings_settings(self):
        """Tests that for invalid MSBuild settings."""
        MSVSSettings.ValidateMSBuildSettings(
            {
                "ClCompile": {
                    "AdditionalIncludeDirectories": "folder1;folder2",
                    "AdditionalOptions": ["string1", "string2"],
                    "AdditionalUsingDirectories": "folder1;folder2",
                    "AssemblerListingLocation": "a_file_name",
                    "AssemblerOutput": "NoListing",
                    "BasicRuntimeChecks": "StackFrameRuntimeCheck",
                    "BrowseInformation": "false",
                    "BrowseInformationFile": "a_file_name",
                    "BufferSecurityCheck": "true",
                    "BuildingInIDE": "true",
                    "CallingConvention": "Cdecl",
                    "CompileAs": "CompileAsC",
                    "CompileAsManaged": "true",
                    "CreateHotpatchableImage": "true",
                    "DebugInformationFormat": "ProgramDatabase",
                    "DisableLanguageExtensions": "true",
                    "DisableSpecificWarnings": "string1;string2",
                    "EnableEnhancedInstructionSet": "StreamingSIMDExtensions",
                    "EnableFiberSafeOptimizations": "true",
                    "EnablePREfast": "true",
                    "Enableprefast": "bogus",
                    "ErrorReporting": "Prompt",
                    "ExceptionHandling": "SyncCThrow",
                    "ExpandAttributedSource": "true",
                    "FavorSizeOrSpeed": "Neither",
                    "FloatingPointExceptions": "true",
                    "FloatingPointModel": "Precise",
                    "ForceConformanceInForLoopScope": "true",
                    "ForcedIncludeFiles": "file1;file2",
                    "ForcedUsingFiles": "file1;file2",
                    "FunctionLevelLinking": "false",
                    "GenerateXMLDocumentationFiles": "true",
                    "IgnoreStandardIncludePath": "true",
                    "InlineFunctionExpansion": "OnlyExplicitInline",
                    "IntrinsicFunctions": "false",
                    "MinimalRebuild": "true",
                    "MultiProcessorCompilation": "true",
                    "ObjectFileName": "a_file_name",
                    "OmitDefaultLibName": "true",
                    "OmitFramePointers": "true",
                    "OpenMPSupport": "true",
                    "Optimization": "Disabled",
                    "PrecompiledHeader": "NotUsing",
                    "PrecompiledHeaderFile": "a_file_name",
                    "PrecompiledHeaderOutputFile": "a_file_name",
                    "PreprocessKeepComments": "true",
                    "PreprocessorDefinitions": "string1;string2",
                    "PreprocessOutputPath": "a string1",
                    "PreprocessSuppressLineNumbers": "false",
                    "PreprocessToFile": "false",
                    "ProcessorNumber": "33",
                    "ProgramDataBaseFileName": "a_file_name",
                    "RuntimeLibrary": "MultiThreaded",
                    "RuntimeTypeInfo": "true",
                    "ShowIncludes": "true",
                    "SmallerTypeCheck": "true",
                    "StringPooling": "true",
                    "StructMemberAlignment": "1Byte",
                    "SuppressStartupBanner": "true",
                    "TrackerLogDirectory": "a_folder",
                    "TreatSpecificWarningsAsErrors": "string1;string2",
                    "TreatWarningAsError": "true",
                    "TreatWChar_tAsBuiltInType": "true",
                    "UndefineAllPreprocessorDefinitions": "true",
                    "UndefinePreprocessorDefinitions": "string1;string2",
                    "UseFullPaths": "true",
                    "UseUnicodeForAssemblerListing": "true",
                    "WarningLevel": "TurnOffAllWarnings",
                    "WholeProgramOptimization": "true",
                    "XMLDocumentationFileName": "a_file_name",
                    "ZZXYZ": "bogus",
                },
                "Link": {
                    "AdditionalDependencies": "file1;file2",
                    "AdditionalLibraryDirectories": "folder1;folder2",
                    "AdditionalManifestDependencies": "file1;file2",
                    "AdditionalOptions": "a string1",
                    "AddModuleNamesToAssembly": "file1;file2",
                    "AllowIsolation": "true",
                    "AssemblyDebug": "",
                    "AssemblyLinkResource": "file1;file2",
                    "BaseAddress": "a string1",
                    "BuildingInIDE": "true",
                    "CLRImageType": "ForceIJWImage",
                    "CLRSupportLastError": "Enabled",
                    "CLRThreadAttribute": "MTAThreadingAttribute",
                    "CLRUnmanagedCodeCheck": "true",
                    "CreateHotPatchableImage": "X86Image",
                    "DataExecutionPrevention": "false",
                    "DelayLoadDLLs": "file1;file2",
                    "DelaySign": "true",
                    "Driver": "NotSet",
                    "EmbedManagedResourceFile": "file1;file2",
                    "EnableCOMDATFolding": "false",
                    "EnableUAC": "true",
                    "EntryPointSymbol": "a string1",
                    "FixedBaseAddress": "false",
                    "ForceFileOutput": "Enabled",
                    "ForceSymbolReferences": "file1;file2",
                    "FunctionOrder": "a_file_name",
                    "GenerateDebugInformation": "true",
                    "GenerateMapFile": "true",
                    "HeapCommitSize": "a string1",
                    "HeapReserveSize": "a string1",
                    "IgnoreAllDefaultLibraries": "true",
                    "IgnoreEmbeddedIDL": "true",
                    "IgnoreSpecificDefaultLibraries": "a_file_list",
                    "ImageHasSafeExceptionHandlers": "true",
                    "ImportLibrary": "a_file_name",
                    "KeyContainer": "a_file_name",
                    "KeyFile": "a_file_name",
                    "LargeAddressAware": "false",
                    "LinkDLL": "true",
                    "LinkErrorReporting": "SendErrorReport",
                    "LinkStatus": "true",
                    "LinkTimeCodeGeneration": "UseLinkTimeCodeGeneration",
                    "ManifestFile": "a_file_name",
                    "MapExports": "true",
                    "MapFileName": "a_file_name",
                    "MergedIDLBaseFileName": "a_file_name",
                    "MergeSections": "a string1",
                    "MidlCommandFile": "a_file_name",
                    "MinimumRequiredVersion": "a string1",
                    "ModuleDefinitionFile": "a_file_name",
                    "MSDOSStubFileName": "a_file_name",
                    "NoEntryPoint": "true",
                    "OptimizeReferences": "false",
                    "OutputFile": "a_file_name",
                    "PerUserRedirection": "true",
                    "PreventDllBinding": "true",
                    "Profile": "true",
                    "ProfileGuidedDatabase": "a_file_name",
                    "ProgramDatabaseFile": "a_file_name",
                    "RandomizedBaseAddress": "false",
                    "RegisterOutput": "true",
                    "SectionAlignment": "33",
                    "SetChecksum": "true",
                    "ShowProgress": "LinkVerboseREF",
                    "SpecifySectionAttributes": "a string1",
                    "StackCommitSize": "a string1",
                    "StackReserveSize": "a string1",
                    "StripPrivateSymbols": "a_file_name",
                    "SubSystem": "Console",
                    "SupportNobindOfDelayLoadedDLL": "true",
                    "SupportUnloadOfDelayLoadedDLL": "true",
                    "SuppressStartupBanner": "true",
                    "SwapRunFromCD": "true",
                    "SwapRunFromNET": "true",
                    "TargetMachine": "MachineX86",
                    "TerminalServerAware": "false",
                    "TrackerLogDirectory": "a_folder",
                    "TreatLinkerWarningAsErrors": "true",
                    "TurnOffAssemblyGeneration": "true",
                    "TypeLibraryFile": "a_file_name",
                    "TypeLibraryResourceID": "33",
                    "UACExecutionLevel": "AsInvoker",
                    "UACUIAccess": "true",
                    "Version": "a string1",
                },
                "ResourceCompile": {
                    "AdditionalIncludeDirectories": "folder1;folder2",
                    "AdditionalOptions": "a string1",
                    "Culture": "0x236",
                    "IgnoreStandardIncludePath": "true",
                    "NullTerminateStrings": "true",
                    "PreprocessorDefinitions": "string1;string2",
                    "ResourceOutputFileName": "a string1",
                    "ShowProgress": "true",
                    "SuppressStartupBanner": "true",
                    "TrackerLogDirectory": "a_folder",
                    "UndefinePreprocessorDefinitions": "string1;string2",
                },
                "Midl": {
                    "AdditionalIncludeDirectories": "folder1;folder2",
                    "AdditionalOptions": "a string1",
                    "ApplicationConfigurationMode": "true",
                    "ClientStubFile": "a_file_name",
                    "CPreprocessOptions": "a string1",
                    "DefaultCharType": "Signed",
                    "DllDataFileName": "a_file_name",
                    "EnableErrorChecks": "EnableCustom",
                    "ErrorCheckAllocations": "true",
                    "ErrorCheckBounds": "true",
                    "ErrorCheckEnumRange": "true",
                    "ErrorCheckRefPointers": "true",
                    "ErrorCheckStubData": "true",
                    "GenerateClientFiles": "Stub",
                    "GenerateServerFiles": "None",
                    "GenerateStublessProxies": "true",
                    "GenerateTypeLibrary": "true",
                    "HeaderFileName": "a_file_name",
                    "IgnoreStandardIncludePath": "true",
                    "InterfaceIdentifierFileName": "a_file_name",
                    "LocaleID": "33",
                    "MkTypLibCompatible": "true",
                    "OutputDirectory": "a string1",
                    "PreprocessorDefinitions": "string1;string2",
                    "ProxyFileName": "a_file_name",
                    "RedirectOutputAndErrors": "a_file_name",
                    "ServerStubFile": "a_file_name",
                    "StructMemberAlignment": "NotSet",
                    "SuppressCompilerWarnings": "true",
                    "SuppressStartupBanner": "true",
                    "TargetEnvironment": "Itanium",
                    "TrackerLogDirectory": "a_folder",
                    "TypeLibFormat": "NewFormat",
                    "TypeLibraryName": "a_file_name",
                    "UndefinePreprocessorDefinitions": "string1;string2",
                    "ValidateAllParameters": "true",
                    "WarnAsError": "true",
                    "WarningLevel": "1",
                },
                "Lib": {
                    "AdditionalDependencies": "file1;file2",
                    "AdditionalLibraryDirectories": "folder1;folder2",
                    "AdditionalOptions": "a string1",
                    "DisplayLibrary": "a string1",
                    "ErrorReporting": "PromptImmediately",
                    "ExportNamedFunctions": "string1;string2",
                    "ForceSymbolReferences": "a string1",
                    "IgnoreAllDefaultLibraries": "true",
                    "IgnoreSpecificDefaultLibraries": "file1;file2",
                    "LinkTimeCodeGeneration": "true",
                    "MinimumRequiredVersion": "a string1",
                    "ModuleDefinitionFile": "a_file_name",
                    "Name": "a_file_name",
                    "OutputFile": "a_file_name",
                    "RemoveObjects": "file1;file2",
                    "SubSystem": "Console",
                    "SuppressStartupBanner": "true",
                    "TargetMachine": "MachineX86i",
                    "TrackerLogDirectory": "a_folder",
                    "TreatLibWarningAsErrors": "true",
                    "UseUnicodeResponseFiles": "true",
                    "Verbose": "true",
                },
                "Manifest": {
                    "AdditionalManifestFiles": "file1;file2",
                    "AdditionalOptions": "a string1",
                    "AssemblyIdentity": "a string1",
                    "ComponentFileName": "a_file_name",
                    "EnableDPIAwareness": "fal",
                    "GenerateCatalogFiles": "truel",
                    "GenerateCategoryTags": "true",
                    "InputResourceManifests": "a string1",
                    "ManifestFromManagedAssembly": "a_file_name",
                    "notgood3": "bogus",
                    "OutputManifestFile": "a_file_name",
                    "OutputResourceManifests": "a string1",
                    "RegistrarScriptFile": "a_file_name",
                    "ReplacementsFile": "a_file_name",
                    "SuppressDependencyElement": "true",
                    "SuppressStartupBanner": "true",
                    "TrackerLogDirectory": "a_folder",
                    "TypeLibraryFile": "a_file_name",
                    "UpdateFileHashes": "true",
                    "UpdateFileHashesSearchPath": "a_file_name",
                    "VerboseOutput": "true",
                },
                "ProjectReference": {
                    "LinkLibraryDependencies": "true",
                    "UseLibraryDependencyInputs": "true",
                },
                "ManifestResourceCompile": {"ResourceOutputFileName": "a_file_name"},
                "": {
                    "EmbedManifest": "true",
                    "GenerateManifest": "true",
                    "IgnoreImportLibrary": "true",
                    "LinkIncremental": "false",
                },
            },
            self.stderr,
        )
        self._ExpectedWarnings(
            [
                "Warning: unrecognized setting ClCompile/Enableprefast",
                "Warning: unrecognized setting ClCompile/ZZXYZ",
                "Warning: unrecognized setting Manifest/notgood3",
                "Warning: for Manifest/GenerateCatalogFiles, "
                "expected bool; got 'truel'",
                "Warning: for Lib/TargetMachine, unrecognized enumerated value "
                "MachineX86i",
                "Warning: for Manifest/EnableDPIAwareness, expected bool; got 'fal'",
            ]
        )

    def testConvertToMSBuildSettings_empty(self):
        """Tests an empty conversion."""
        msvs_settings = {}
        expected_msbuild_settings = {}
        actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
            msvs_settings, self.stderr
        )
        self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
        self._ExpectedWarnings([])

    def testConvertToMSBuildSettings_minimal(self):
        """Tests a minimal conversion."""
        msvs_settings = {
            "VCCLCompilerTool": {
                "AdditionalIncludeDirectories": "dir1",
                "AdditionalOptions": "/foo",
                "BasicRuntimeChecks": "0",
            },
            "VCLinkerTool": {
                "LinkTimeCodeGeneration": "1",
                "ErrorReporting": "1",
                "DataExecutionPrevention": "2",
            },
        }
        expected_msbuild_settings = {
            "ClCompile": {
                "AdditionalIncludeDirectories": "dir1",
                "AdditionalOptions": "/foo",
                "BasicRuntimeChecks": "Default",
            },
            "Link": {
                "LinkTimeCodeGeneration": "UseLinkTimeCodeGeneration",
                "LinkErrorReporting": "PromptImmediately",
                "DataExecutionPrevention": "true",
            },
        }
        actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
            msvs_settings, self.stderr
        )
        self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
        self._ExpectedWarnings([])

    def testConvertToMSBuildSettings_warnings(self):
        """Tests conversion that generates warnings."""
        msvs_settings = {
            "VCCLCompilerTool": {
                "AdditionalIncludeDirectories": "1",
                "AdditionalOptions": "2",
                # These are incorrect values:
                "BasicRuntimeChecks": "12",
                "BrowseInformation": "21",
                "UsePrecompiledHeader": "13",
                "GeneratePreprocessedFile": "14",
            },
            "VCLinkerTool": {
                # These are incorrect values:
                "Driver": "10",
                "LinkTimeCodeGeneration": "31",
                "ErrorReporting": "21",
                "FixedBaseAddress": "6",
            },
            "VCResourceCompilerTool": {
                # Custom
                "Culture": "1003"
            },
        }
        expected_msbuild_settings = {
            "ClCompile": {
                "AdditionalIncludeDirectories": "1",
                "AdditionalOptions": "2",
            },
            "Link": {},
            "ResourceCompile": {
                # Custom
                "Culture": "0x03eb"
            },
        }
        actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
            msvs_settings, self.stderr
        )
        self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
        self._ExpectedWarnings(
            [
                "Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to "
                "MSBuild, index value (12) not in expected range [0, 4)",
                "Warning: while converting VCCLCompilerTool/BrowseInformation to "
                "MSBuild, index value (21) not in expected range [0, 3)",
                "Warning: while converting VCCLCompilerTool/UsePrecompiledHeader to "
                "MSBuild, index value (13) not in expected range [0, 3)",
                "Warning: while converting "
                "VCCLCompilerTool/GeneratePreprocessedFile to "
                "MSBuild, value must be one of [0, 1, 2]; got 14",
                "Warning: while converting VCLinkerTool/Driver to "
                "MSBuild, index value (10) not in expected range [0, 4)",
                "Warning: while converting VCLinkerTool/LinkTimeCodeGeneration to "
                "MSBuild, index value (31) not in expected range [0, 5)",
                "Warning: while converting VCLinkerTool/ErrorReporting to "
                "MSBuild, index value (21) not in expected range [0, 3)",
                "Warning: while converting VCLinkerTool/FixedBaseAddress to "
                "MSBuild, index value (6) not in expected range [0, 3)",
            ]
        )

    def testConvertToMSBuildSettings_full_synthetic(self):
        """Tests conversion of all the MSBuild settings."""
        msvs_settings = {
            "VCCLCompilerTool": {
                "AdditionalIncludeDirectories": "folder1;folder2;folder3",
                "AdditionalOptions": "a_string",
                "AdditionalUsingDirectories": "folder1;folder2;folder3",
                "AssemblerListingLocation": "a_file_name",
                "AssemblerOutput": "0",
                "BasicRuntimeChecks": "1",
                "BrowseInformation": "2",
                "BrowseInformationFile": "a_file_name",
                "BufferSecurityCheck": "true",
                "CallingConvention": "0",
                "CompileAs": "1",
                "DebugInformationFormat": "4",
                "DefaultCharIsUnsigned": "true",
                "Detect64BitPortabilityProblems": "true",
                "DisableLanguageExtensions": "true",
                "DisableSpecificWarnings": "d1;d2;d3",
                "EnableEnhancedInstructionSet": "0",
                "EnableFiberSafeOptimizations": "true",
                "EnableFunctionLevelLinking": "true",
                "EnableIntrinsicFunctions": "true",
                "EnablePREfast": "true",
                "ErrorReporting": "1",
                "ExceptionHandling": "2",
                "ExpandAttributedSource": "true",
                "FavorSizeOrSpeed": "0",
                "FloatingPointExceptions": "true",
                "FloatingPointModel": "1",
                "ForceConformanceInForLoopScope": "true",
                "ForcedIncludeFiles": "file1;file2;file3",
                "ForcedUsingFiles": "file1;file2;file3",
                "GeneratePreprocessedFile": "1",
                "GenerateXMLDocumentationFiles": "true",
                "IgnoreStandardIncludePath": "true",
                "InlineFunctionExpansion": "2",
                "KeepComments": "true",
                "MinimalRebuild": "true",
                "ObjectFile": "a_file_name",
                "OmitDefaultLibName": "true",
                "OmitFramePointers": "true",
                "OpenMP": "true",
                "Optimization": "3",
                "PrecompiledHeaderFile": "a_file_name",
                "PrecompiledHeaderThrough": "a_file_name",
                "PreprocessorDefinitions": "d1;d2;d3",
                "ProgramDataBaseFileName": "a_file_name",
                "RuntimeLibrary": "0",
                "RuntimeTypeInfo": "true",
                "ShowIncludes": "true",
                "SmallerTypeCheck": "true",
                "StringPooling": "true",
                "StructMemberAlignment": "1",
                "SuppressStartupBanner": "true",
                "TreatWChar_tAsBuiltInType": "true",
                "UndefineAllPreprocessorDefinitions": "true",
                "UndefinePreprocessorDefinitions": "d1;d2;d3",
                "UseFullPaths": "true",
                "UsePrecompiledHeader": "1",
                "UseUnicodeResponseFiles": "true",
                "WarnAsError": "true",
                "WarningLevel": "2",
                "WholeProgramOptimization": "true",
                "XMLDocumentationFileName": "a_file_name",
            },
            "VCLinkerTool": {
                "AdditionalDependencies": "file1;file2;file3",
                "AdditionalLibraryDirectories": "folder1;folder2;folder3",
                "AdditionalLibraryDirectories_excluded": "folder1;folder2;folder3",
                "AdditionalManifestDependencies": "file1;file2;file3",
                "AdditionalOptions": "a_string",
                "AddModuleNamesToAssembly": "file1;file2;file3",
                "AllowIsolation": "true",
                "AssemblyDebug": "0",
                "AssemblyLinkResource": "file1;file2;file3",
                "BaseAddress": "a_string",
                "CLRImageType": "1",
                "CLRThreadAttribute": "2",
                "CLRUnmanagedCodeCheck": "true",
                "DataExecutionPrevention": "0",
                "DelayLoadDLLs": "file1;file2;file3",
                "DelaySign": "true",
                "Driver": "1",
                "EmbedManagedResourceFile": "file1;file2;file3",
                "EnableCOMDATFolding": "0",
                "EnableUAC": "true",
                "EntryPointSymbol": "a_string",
                "ErrorReporting": "0",
                "FixedBaseAddress": "1",
                "ForceSymbolReferences": "file1;file2;file3",
                "FunctionOrder": "a_file_name",
                "GenerateDebugInformation": "true",
                "GenerateManifest": "true",
                "GenerateMapFile": "true",
                "HeapCommitSize": "a_string",
                "HeapReserveSize": "a_string",
                "IgnoreAllDefaultLibraries": "true",
                "IgnoreDefaultLibraryNames": "file1;file2;file3",
                "IgnoreEmbeddedIDL": "true",
                "IgnoreImportLibrary": "true",
                "ImportLibrary": "a_file_name",
                "KeyContainer": "a_file_name",
                "KeyFile": "a_file_name",
                "LargeAddressAware": "2",
                "LinkIncremental": "1",
                "LinkLibraryDependencies": "true",
                "LinkTimeCodeGeneration": "2",
                "ManifestFile": "a_file_name",
                "MapExports": "true",
                "MapFileName": "a_file_name",
                "MergedIDLBaseFileName": "a_file_name",
                "MergeSections": "a_string",
                "MidlCommandFile": "a_file_name",
                "ModuleDefinitionFile": "a_file_name",
                "OptimizeForWindows98": "1",
                "OptimizeReferences": "0",
                "OutputFile": "a_file_name",
                "PerUserRedirection": "true",
                "Profile": "true",
                "ProfileGuidedDatabase": "a_file_name",
                "ProgramDatabaseFile": "a_file_name",
                "RandomizedBaseAddress": "1",
                "RegisterOutput": "true",
                "ResourceOnlyDLL": "true",
                "SetChecksum": "true",
                "ShowProgress": "0",
                "StackCommitSize": "a_string",
                "StackReserveSize": "a_string",
                "StripPrivateSymbols": "a_file_name",
                "SubSystem": "2",
                "SupportUnloadOfDelayLoadedDLL": "true",
                "SuppressStartupBanner": "true",
                "SwapRunFromCD": "true",
                "SwapRunFromNet": "true",
                "TargetMachine": "3",
                "TerminalServerAware": "2",
                "TurnOffAssemblyGeneration": "true",
                "TypeLibraryFile": "a_file_name",
                "TypeLibraryResourceID": "33",
                "UACExecutionLevel": "1",
                "UACUIAccess": "true",
                "UseLibraryDependencyInputs": "false",
                "UseUnicodeResponseFiles": "true",
                "Version": "a_string",
            },
            "VCResourceCompilerTool": {
                "AdditionalIncludeDirectories": "folder1;folder2;folder3",
                "AdditionalOptions": "a_string",
                "Culture": "1003",
                "IgnoreStandardIncludePath": "true",
                "PreprocessorDefinitions": "d1;d2;d3",
                "ResourceOutputFileName": "a_string",
                "ShowProgress": "true",
                "SuppressStartupBanner": "true",
                "UndefinePreprocessorDefinitions": "d1;d2;d3",
            },
            "VCMIDLTool": {
                "AdditionalIncludeDirectories": "folder1;folder2;folder3",
                "AdditionalOptions": "a_string",
                "CPreprocessOptions": "a_string",
                "DefaultCharType": "0",
                "DLLDataFileName": "a_file_name",
                "EnableErrorChecks": "2",
                "ErrorCheckAllocations": "true",
                "ErrorCheckBounds": "true",
                "ErrorCheckEnumRange": "true",
                "ErrorCheckRefPointers": "true",
                "ErrorCheckStubData": "true",
                "GenerateStublessProxies": "true",
                "GenerateTypeLibrary": "true",
                "HeaderFileName": "a_file_name",
                "IgnoreStandardIncludePath": "true",
                "InterfaceIdentifierFileName": "a_file_name",
                "MkTypLibCompatible": "true",
                "OutputDirectory": "a_string",
                "PreprocessorDefinitions": "d1;d2;d3",
                "ProxyFileName": "a_file_name",
                "RedirectOutputAndErrors": "a_file_name",
                "StructMemberAlignment": "3",
                "SuppressStartupBanner": "true",
                "TargetEnvironment": "1",
                "TypeLibraryName": "a_file_name",
                "UndefinePreprocessorDefinitions": "d1;d2;d3",
                "ValidateParameters": "true",
                "WarnAsError": "true",
                "WarningLevel": "4",
            },
            "VCLibrarianTool": {
                "AdditionalDependencies": "file1;file2;file3",
                "AdditionalLibraryDirectories": "folder1;folder2;folder3",
                "AdditionalLibraryDirectories_excluded": "folder1;folder2;folder3",
                "AdditionalOptions": "a_string",
                "ExportNamedFunctions": "d1;d2;d3",
                "ForceSymbolReferences": "a_string",
                "IgnoreAllDefaultLibraries": "true",
                "IgnoreSpecificDefaultLibraries": "file1;file2;file3",
                "LinkLibraryDependencies": "true",
                "ModuleDefinitionFile": "a_file_name",
                "OutputFile": "a_file_name",
                "SuppressStartupBanner": "true",
                "UseUnicodeResponseFiles": "true",
            },
            "VCManifestTool": {
                "AdditionalManifestFiles": "file1;file2;file3",
                "AdditionalOptions": "a_string",
                "AssemblyIdentity": "a_string",
                "ComponentFileName": "a_file_name",
                "DependencyInformationFile": "a_file_name",
                "EmbedManifest": "true",
                "GenerateCatalogFiles": "true",
                "InputResourceManifests": "a_string",
                "ManifestResourceFile": "my_name",
                "OutputManifestFile": "a_file_name",
                "RegistrarScriptFile": "a_file_name",
                "ReplacementsFile": "a_file_name",
                "SuppressStartupBanner": "true",
                "TypeLibraryFile": "a_file_name",
                "UpdateFileHashes": "true",
                "UpdateFileHashesSearchPath": "a_file_name",
                "UseFAT32Workaround": "true",
                "UseUnicodeResponseFiles": "true",
                "VerboseOutput": "true",
            },
        }
        expected_msbuild_settings = {
            "ClCompile": {
                "AdditionalIncludeDirectories": "folder1;folder2;folder3",
                "AdditionalOptions": "a_string /J",
                "AdditionalUsingDirectories": "folder1;folder2;folder3",
                "AssemblerListingLocation": "a_file_name",
                "AssemblerOutput": "NoListing",
                "BasicRuntimeChecks": "StackFrameRuntimeCheck",
                "BrowseInformation": "true",
                "BrowseInformationFile": "a_file_name",
                "BufferSecurityCheck": "true",
                "CallingConvention": "Cdecl",
                "CompileAs": "CompileAsC",
                "DebugInformationFormat": "EditAndContinue",
                "DisableLanguageExtensions": "true",
                "DisableSpecificWarnings": "d1;d2;d3",
                "EnableEnhancedInstructionSet": "NotSet",
                "EnableFiberSafeOptimizations": "true",
                "EnablePREfast": "true",
                "ErrorReporting": "Prompt",
                "ExceptionHandling": "Async",
                "ExpandAttributedSource": "true",
                "FavorSizeOrSpeed": "Neither",
                "FloatingPointExceptions": "true",
                "FloatingPointModel": "Strict",
                "ForceConformanceInForLoopScope": "true",
                "ForcedIncludeFiles": "file1;file2;file3",
                "ForcedUsingFiles": "file1;file2;file3",
                "FunctionLevelLinking": "true",
                "GenerateXMLDocumentationFiles": "true",
                "IgnoreStandardIncludePath": "true",
                "InlineFunctionExpansion": "AnySuitable",
                "IntrinsicFunctions": "true",
                "MinimalRebuild": "true",
                "ObjectFileName": "a_file_name",
                "OmitDefaultLibName": "true",
                "OmitFramePointers": "true",
                "OpenMPSupport": "true",
                "Optimization": "Full",
                "PrecompiledHeader": "Create",
                "PrecompiledHeaderFile": "a_file_name",
                "PrecompiledHeaderOutputFile": "a_file_name",
                "PreprocessKeepComments": "true",
                "PreprocessorDefinitions": "d1;d2;d3",
                "PreprocessSuppressLineNumbers": "false",
                "PreprocessToFile": "true",
                "ProgramDataBaseFileName": "a_file_name",
                "RuntimeLibrary": "MultiThreaded",
                "RuntimeTypeInfo": "true",
                "ShowIncludes": "true",
                "SmallerTypeCheck": "true",
                "StringPooling": "true",
                "StructMemberAlignment": "1Byte",
                "SuppressStartupBanner": "true",
                "TreatWarningAsError": "true",
                "TreatWChar_tAsBuiltInType": "true",
                "UndefineAllPreprocessorDefinitions": "true",
                "UndefinePreprocessorDefinitions": "d1;d2;d3",
                "UseFullPaths": "true",
                "WarningLevel": "Level2",
                "WholeProgramOptimization": "true",
                "XMLDocumentationFileName": "a_file_name",
            },
            "Link": {
                "AdditionalDependencies": "file1;file2;file3",
                "AdditionalLibraryDirectories": "folder1;folder2;folder3",
                "AdditionalManifestDependencies": "file1;file2;file3",
                "AdditionalOptions": "a_string",
                "AddModuleNamesToAssembly": "file1;file2;file3",
                "AllowIsolation": "true",
                "AssemblyDebug": "",
                "AssemblyLinkResource": "file1;file2;file3",
                "BaseAddress": "a_string",
                "CLRImageType": "ForceIJWImage",
                "CLRThreadAttribute": "STAThreadingAttribute",
                "CLRUnmanagedCodeCheck": "true",
                "DataExecutionPrevention": "",
                "DelayLoadDLLs": "file1;file2;file3",
                "DelaySign": "true",
                "Driver": "Driver",
                "EmbedManagedResourceFile": "file1;file2;file3",
                "EnableCOMDATFolding": "",
                "EnableUAC": "true",
                "EntryPointSymbol": "a_string",
                "FixedBaseAddress": "false",
                "ForceSymbolReferences": "file1;file2;file3",
                "FunctionOrder": "a_file_name",
                "GenerateDebugInformation": "true",
                "GenerateMapFile": "true",
                "HeapCommitSize": "a_string",
                "HeapReserveSize": "a_string",
                "IgnoreAllDefaultLibraries": "true",
                "IgnoreEmbeddedIDL": "true",
                "IgnoreSpecificDefaultLibraries": "file1;file2;file3",
                "ImportLibrary": "a_file_name",
                "KeyContainer": "a_file_name",
                "KeyFile": "a_file_name",
                "LargeAddressAware": "true",
                "LinkErrorReporting": "NoErrorReport",
                "LinkTimeCodeGeneration": "PGInstrument",
                "ManifestFile": "a_file_name",
                "MapExports": "true",
                "MapFileName": "a_file_name",
                "MergedIDLBaseFileName": "a_file_name",
                "MergeSections": "a_string",
                "MidlCommandFile": "a_file_name",
                "ModuleDefinitionFile": "a_file_name",
                "NoEntryPoint": "true",
                "OptimizeReferences": "",
                "OutputFile": "a_file_name",
                "PerUserRedirection": "true",
                "Profile": "true",
                "ProfileGuidedDatabase": "a_file_name",
                "ProgramDatabaseFile": "a_file_name",
                "RandomizedBaseAddress": "false",
                "RegisterOutput": "true",
                "SetChecksum": "true",
                "ShowProgress": "NotSet",
                "StackCommitSize": "a_string",
                "StackReserveSize": "a_string",
                "StripPrivateSymbols": "a_file_name",
                "SubSystem": "Windows",
                "SupportUnloadOfDelayLoadedDLL": "true",
                "SuppressStartupBanner": "true",
                "SwapRunFromCD": "true",
                "SwapRunFromNET": "true",
                "TargetMachine": "MachineARM",
                "TerminalServerAware": "true",
                "TurnOffAssemblyGeneration": "true",
                "TypeLibraryFile": "a_file_name",
                "TypeLibraryResourceID": "33",
                "UACExecutionLevel": "HighestAvailable",
                "UACUIAccess": "true",
                "Version": "a_string",
            },
            "ResourceCompile": {
                "AdditionalIncludeDirectories": "folder1;folder2;folder3",
                "AdditionalOptions": "a_string",
                "Culture": "0x03eb",
                "IgnoreStandardIncludePath": "true",
                "PreprocessorDefinitions": "d1;d2;d3",
                "ResourceOutputFileName": "a_string",
                "ShowProgress": "true",
                "SuppressStartupBanner": "true",
                "UndefinePreprocessorDefinitions": "d1;d2;d3",
            },
            "Midl": {
                "AdditionalIncludeDirectories": "folder1;folder2;folder3",
                "AdditionalOptions": "a_string",
                "CPreprocessOptions": "a_string",
                "DefaultCharType": "Unsigned",
                "DllDataFileName": "a_file_name",
                "EnableErrorChecks": "All",
                "ErrorCheckAllocations": "true",
                "ErrorCheckBounds": "true",
                "ErrorCheckEnumRange": "true",
                "ErrorCheckRefPointers": "true",
                "ErrorCheckStubData": "true",
                "GenerateStublessProxies": "true",
                "GenerateTypeLibrary": "true",
                "HeaderFileName": "a_file_name",
                "IgnoreStandardIncludePath": "true",
                "InterfaceIdentifierFileName": "a_file_name",
                "MkTypLibCompatible": "true",
                "OutputDirectory": "a_string",
                "PreprocessorDefinitions": "d1;d2;d3",
                "ProxyFileName": "a_file_name",
                "RedirectOutputAndErrors": "a_file_name",
                "StructMemberAlignment": "4",
                "SuppressStartupBanner": "true",
                "TargetEnvironment": "Win32",
                "TypeLibraryName": "a_file_name",
                "UndefinePreprocessorDefinitions": "d1;d2;d3",
                "ValidateAllParameters": "true",
                "WarnAsError": "true",
                "WarningLevel": "4",
            },
            "Lib": {
                "AdditionalDependencies": "file1;file2;file3",
                "AdditionalLibraryDirectories": "folder1;folder2;folder3",
                "AdditionalOptions": "a_string",
                "ExportNamedFunctions": "d1;d2;d3",
                "ForceSymbolReferences": "a_string",
                "IgnoreAllDefaultLibraries": "true",
                "IgnoreSpecificDefaultLibraries": "file1;file2;file3",
                "ModuleDefinitionFile": "a_file_name",
                "OutputFile": "a_file_name",
                "SuppressStartupBanner": "true",
                "UseUnicodeResponseFiles": "true",
            },
            "Manifest": {
                "AdditionalManifestFiles": "file1;file2;file3",
                "AdditionalOptions": "a_string",
                "AssemblyIdentity": "a_string",
                "ComponentFileName": "a_file_name",
                "GenerateCatalogFiles": "true",
                "InputResourceManifests": "a_string",
                "OutputManifestFile": "a_file_name",
                "RegistrarScriptFile": "a_file_name",
                "ReplacementsFile": "a_file_name",
                "SuppressStartupBanner": "true",
                "TypeLibraryFile": "a_file_name",
                "UpdateFileHashes": "true",
                "UpdateFileHashesSearchPath": "a_file_name",
                "VerboseOutput": "true",
            },
            "ManifestResourceCompile": {"ResourceOutputFileName": "my_name"},
            "ProjectReference": {
                "LinkLibraryDependencies": "true",
                "UseLibraryDependencyInputs": "false",
            },
            "": {
                "EmbedManifest": "true",
                "GenerateManifest": "true",
                "IgnoreImportLibrary": "true",
                "LinkIncremental": "false",
            },
        }
        self.maxDiff = 9999  # on failure display a long diff
        actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
            msvs_settings, self.stderr
        )
        self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
        self._ExpectedWarnings([])

    def testConvertToMSBuildSettings_actual(self):
        """Tests the conversion of an actual project.

    A VS2008 project with most of the options defined was created through the
    VS2008 IDE.  It was then converted to VS2010.  The tool settings found in
    the .vcproj and .vcxproj files were converted to the two dictionaries
    msvs_settings and expected_msbuild_settings.

    Note that for many settings, the VS2010 converter adds macros like
    %(AdditionalIncludeDirectories) to make sure than inherited values are
    included.  Since the Gyp projects we generate do not use inheritance,
    we removed these macros.  They were:
        ClCompile:
            AdditionalIncludeDirectories:  ';%(AdditionalIncludeDirectories)'
            AdditionalOptions:  ' %(AdditionalOptions)'
            AdditionalUsingDirectories:  ';%(AdditionalUsingDirectories)'
            DisableSpecificWarnings: ';%(DisableSpecificWarnings)',
            ForcedIncludeFiles:  ';%(ForcedIncludeFiles)',
            ForcedUsingFiles:  ';%(ForcedUsingFiles)',
            PreprocessorDefinitions:  ';%(PreprocessorDefinitions)',
            UndefinePreprocessorDefinitions:
                ';%(UndefinePreprocessorDefinitions)',
        Link:
            AdditionalDependencies:  ';%(AdditionalDependencies)',
            AdditionalLibraryDirectories:  ';%(AdditionalLibraryDirectories)',
            AdditionalManifestDependencies:
                ';%(AdditionalManifestDependencies)',
            AdditionalOptions:  ' %(AdditionalOptions)',
            AddModuleNamesToAssembly:  ';%(AddModuleNamesToAssembly)',
            AssemblyLinkResource:  ';%(AssemblyLinkResource)',
            DelayLoadDLLs:  ';%(DelayLoadDLLs)',
            EmbedManagedResourceFile:  ';%(EmbedManagedResourceFile)',
            ForceSymbolReferences:  ';%(ForceSymbolReferences)',
            IgnoreSpecificDefaultLibraries:
                ';%(IgnoreSpecificDefaultLibraries)',
        ResourceCompile:
            AdditionalIncludeDirectories:  ';%(AdditionalIncludeDirectories)',
            AdditionalOptions:  ' %(AdditionalOptions)',
            PreprocessorDefinitions:  ';%(PreprocessorDefinitions)',
        Manifest:
            AdditionalManifestFiles:  ';%(AdditionalManifestFiles)',
            AdditionalOptions:  ' %(AdditionalOptions)',
            InputResourceManifests:  ';%(InputResourceManifests)',
    """
        msvs_settings = {
            "VCCLCompilerTool": {
                "AdditionalIncludeDirectories": "dir1",
                "AdditionalOptions": "/more",
                "AdditionalUsingDirectories": "test",
                "AssemblerListingLocation": "$(IntDir)\\a",
                "AssemblerOutput": "1",
                "BasicRuntimeChecks": "3",
                "BrowseInformation": "1",
                "BrowseInformationFile": "$(IntDir)\\e",
                "BufferSecurityCheck": "false",
                "CallingConvention": "1",
                "CompileAs": "1",
                "DebugInformationFormat": "4",
                "DefaultCharIsUnsigned": "true",
                "Detect64BitPortabilityProblems": "true",
                "DisableLanguageExtensions": "true",
                "DisableSpecificWarnings": "abc",
                "EnableEnhancedInstructionSet": "1",
                "EnableFiberSafeOptimizations": "true",
                "EnableFunctionLevelLinking": "true",
                "EnableIntrinsicFunctions": "true",
                "EnablePREfast": "true",
                "ErrorReporting": "2",
                "ExceptionHandling": "2",
                "ExpandAttributedSource": "true",
                "FavorSizeOrSpeed": "2",
                "FloatingPointExceptions": "true",
                "FloatingPointModel": "1",
                "ForceConformanceInForLoopScope": "false",
                "ForcedIncludeFiles": "def",
                "ForcedUsingFiles": "ge",
                "GeneratePreprocessedFile": "2",
                "GenerateXMLDocumentationFiles": "true",
                "IgnoreStandardIncludePath": "true",
                "InlineFunctionExpansion": "1",
                "KeepComments": "true",
                "MinimalRebuild": "true",
                "ObjectFile": "$(IntDir)\\b",
                "OmitDefaultLibName": "true",
                "OmitFramePointers": "true",
                "OpenMP": "true",
                "Optimization": "3",
                "PrecompiledHeaderFile": "$(IntDir)\\$(TargetName).pche",
                "PrecompiledHeaderThrough": "StdAfx.hd",
                "PreprocessorDefinitions": "WIN32;_DEBUG;_CONSOLE",
                "ProgramDataBaseFileName": "$(IntDir)\\vc90b.pdb",
                "RuntimeLibrary": "3",
                "RuntimeTypeInfo": "false",
                "ShowIncludes": "true",
                "SmallerTypeCheck": "true",
                "StringPooling": "true",
                "StructMemberAlignment": "3",
                "SuppressStartupBanner": "false",
                "TreatWChar_tAsBuiltInType": "false",
                "UndefineAllPreprocessorDefinitions": "true",
                "UndefinePreprocessorDefinitions": "wer",
                "UseFullPaths": "true",
                "UsePrecompiledHeader": "0",
                "UseUnicodeResponseFiles": "false",
                "WarnAsError": "true",
                "WarningLevel": "3",
                "WholeProgramOptimization": "true",
                "XMLDocumentationFileName": "$(IntDir)\\c",
            },
            "VCLinkerTool": {
                "AdditionalDependencies": "zx",
                "AdditionalLibraryDirectories": "asd",
                "AdditionalManifestDependencies": "s2",
                "AdditionalOptions": "/mor2",
                "AddModuleNamesToAssembly": "d1",
                "AllowIsolation": "false",
                "AssemblyDebug": "1",
                "AssemblyLinkResource": "d5",
                "BaseAddress": "23423",
                "CLRImageType": "3",
                "CLRThreadAttribute": "1",
                "CLRUnmanagedCodeCheck": "true",
                "DataExecutionPrevention": "0",
                "DelayLoadDLLs": "d4",
                "DelaySign": "true",
                "Driver": "2",
                "EmbedManagedResourceFile": "d2",
                "EnableCOMDATFolding": "1",
                "EnableUAC": "false",
                "EntryPointSymbol": "f5",
                "ErrorReporting": "2",
                "FixedBaseAddress": "1",
                "ForceSymbolReferences": "d3",
                "FunctionOrder": "fssdfsd",
                "GenerateDebugInformation": "true",
                "GenerateManifest": "false",
                "GenerateMapFile": "true",
                "HeapCommitSize": "13",
                "HeapReserveSize": "12",
                "IgnoreAllDefaultLibraries": "true",
                "IgnoreDefaultLibraryNames": "flob;flok",
                "IgnoreEmbeddedIDL": "true",
                "IgnoreImportLibrary": "true",
                "ImportLibrary": "f4",
                "KeyContainer": "f7",
                "KeyFile": "f6",
                "LargeAddressAware": "2",
                "LinkIncremental": "0",
                "LinkLibraryDependencies": "false",
                "LinkTimeCodeGeneration": "1",
                "ManifestFile": "$(IntDir)\\$(TargetFileName).2intermediate.manifest",
                "MapExports": "true",
                "MapFileName": "d5",
                "MergedIDLBaseFileName": "f2",
                "MergeSections": "f5",
                "MidlCommandFile": "f1",
                "ModuleDefinitionFile": "sdsd",
                "OptimizeForWindows98": "2",
                "OptimizeReferences": "2",
                "OutputFile": "$(OutDir)\\$(ProjectName)2.exe",
                "PerUserRedirection": "true",
                "Profile": "true",
                "ProfileGuidedDatabase": "$(TargetDir)$(TargetName).pgdd",
                "ProgramDatabaseFile": "Flob.pdb",
                "RandomizedBaseAddress": "1",
                "RegisterOutput": "true",
                "ResourceOnlyDLL": "true",
                "SetChecksum": "false",
                "ShowProgress": "1",
                "StackCommitSize": "15",
                "StackReserveSize": "14",
                "StripPrivateSymbols": "d3",
                "SubSystem": "1",
                "SupportUnloadOfDelayLoadedDLL": "true",
                "SuppressStartupBanner": "false",
                "SwapRunFromCD": "true",
                "SwapRunFromNet": "true",
                "TargetMachine": "1",
                "TerminalServerAware": "1",
                "TurnOffAssemblyGeneration": "true",
                "TypeLibraryFile": "f3",
                "TypeLibraryResourceID": "12",
                "UACExecutionLevel": "2",
                "UACUIAccess": "true",
                "UseLibraryDependencyInputs": "true",
                "UseUnicodeResponseFiles": "false",
                "Version": "333",
            },
            "VCResourceCompilerTool": {
                "AdditionalIncludeDirectories": "f3",
                "AdditionalOptions": "/more3",
                "Culture": "3084",
                "IgnoreStandardIncludePath": "true",
                "PreprocessorDefinitions": "_UNICODE;UNICODE2",
                "ResourceOutputFileName": "$(IntDir)/$(InputName)3.res",
                "ShowProgress": "true",
            },
            "VCManifestTool": {
                "AdditionalManifestFiles": "sfsdfsd",
                "AdditionalOptions": "afdsdafsd",
                "AssemblyIdentity": "sddfdsadfsa",
                "ComponentFileName": "fsdfds",
                "DependencyInformationFile": "$(IntDir)\\mt.depdfd",
                "EmbedManifest": "false",
                "GenerateCatalogFiles": "true",
                "InputResourceManifests": "asfsfdafs",
                "ManifestResourceFile":
                    "$(IntDir)\\$(TargetFileName).embed.manifest.resfdsf",
                "OutputManifestFile": "$(TargetPath).manifestdfs",
                "RegistrarScriptFile": "sdfsfd",
                "ReplacementsFile": "sdffsd",
                "SuppressStartupBanner": "false",
                "TypeLibraryFile": "sfsd",
                "UpdateFileHashes": "true",
                "UpdateFileHashesSearchPath": "sfsd",
                "UseFAT32Workaround": "true",
                "UseUnicodeResponseFiles": "false",
                "VerboseOutput": "true",
            },
        }
        expected_msbuild_settings = {
            "ClCompile": {
                "AdditionalIncludeDirectories": "dir1",
                "AdditionalOptions": "/more /J",
                "AdditionalUsingDirectories": "test",
                "AssemblerListingLocation": "$(IntDir)a",
                "AssemblerOutput": "AssemblyCode",
                "BasicRuntimeChecks": "EnableFastChecks",
                "BrowseInformation": "true",
                "BrowseInformationFile": "$(IntDir)e",
                "BufferSecurityCheck": "false",
                "CallingConvention": "FastCall",
                "CompileAs": "CompileAsC",
                "DebugInformationFormat": "EditAndContinue",
                "DisableLanguageExtensions": "true",
                "DisableSpecificWarnings": "abc",
                "EnableEnhancedInstructionSet": "StreamingSIMDExtensions",
                "EnableFiberSafeOptimizations": "true",
                "EnablePREfast": "true",
                "ErrorReporting": "Queue",
                "ExceptionHandling": "Async",
                "ExpandAttributedSource": "true",
                "FavorSizeOrSpeed": "Size",
                "FloatingPointExceptions": "true",
                "FloatingPointModel": "Strict",
                "ForceConformanceInForLoopScope": "false",
                "ForcedIncludeFiles": "def",
                "ForcedUsingFiles": "ge",
                "FunctionLevelLinking": "true",
                "GenerateXMLDocumentationFiles": "true",
                "IgnoreStandardIncludePath": "true",
                "InlineFunctionExpansion": "OnlyExplicitInline",
                "IntrinsicFunctions": "true",
                "MinimalRebuild": "true",
                "ObjectFileName": "$(IntDir)b",
                "OmitDefaultLibName": "true",
                "OmitFramePointers": "true",
                "OpenMPSupport": "true",
                "Optimization": "Full",
                "PrecompiledHeader": "NotUsing",  # Actual conversion gives ''
                "PrecompiledHeaderFile": "StdAfx.hd",
                "PrecompiledHeaderOutputFile": "$(IntDir)$(TargetName).pche",
                "PreprocessKeepComments": "true",
                "PreprocessorDefinitions": "WIN32;_DEBUG;_CONSOLE",
                "PreprocessSuppressLineNumbers": "true",
                "PreprocessToFile": "true",
                "ProgramDataBaseFileName": "$(IntDir)vc90b.pdb",
                "RuntimeLibrary": "MultiThreadedDebugDLL",
                "RuntimeTypeInfo": "false",
                "ShowIncludes": "true",
                "SmallerTypeCheck": "true",
                "StringPooling": "true",
                "StructMemberAlignment": "4Bytes",
                "SuppressStartupBanner": "false",
                "TreatWarningAsError": "true",
                "TreatWChar_tAsBuiltInType": "false",
                "UndefineAllPreprocessorDefinitions": "true",
                "UndefinePreprocessorDefinitions": "wer",
                "UseFullPaths": "true",
                "WarningLevel": "Level3",
                "WholeProgramOptimization": "true",
                "XMLDocumentationFileName": "$(IntDir)c",
            },
            "Link": {
                "AdditionalDependencies": "zx",
                "AdditionalLibraryDirectories": "asd",
                "AdditionalManifestDependencies": "s2",
                "AdditionalOptions": "/mor2",
                "AddModuleNamesToAssembly": "d1",
                "AllowIsolation": "false",
                "AssemblyDebug": "true",
                "AssemblyLinkResource": "d5",
                "BaseAddress": "23423",
                "CLRImageType": "ForceSafeILImage",
                "CLRThreadAttribute": "MTAThreadingAttribute",
                "CLRUnmanagedCodeCheck": "true",
                "DataExecutionPrevention": "",
                "DelayLoadDLLs": "d4",
                "DelaySign": "true",
                "Driver": "UpOnly",
                "EmbedManagedResourceFile": "d2",
                "EnableCOMDATFolding": "false",
                "EnableUAC": "false",
                "EntryPointSymbol": "f5",
                "FixedBaseAddress": "false",
                "ForceSymbolReferences": "d3",
                "FunctionOrder": "fssdfsd",
                "GenerateDebugInformation": "true",
                "GenerateMapFile": "true",
                "HeapCommitSize": "13",
                "HeapReserveSize": "12",
                "IgnoreAllDefaultLibraries": "true",
                "IgnoreEmbeddedIDL": "true",
                "IgnoreSpecificDefaultLibraries": "flob;flok",
                "ImportLibrary": "f4",
                "KeyContainer": "f7",
                "KeyFile": "f6",
                "LargeAddressAware": "true",
                "LinkErrorReporting": "QueueForNextLogin",
                "LinkTimeCodeGeneration": "UseLinkTimeCodeGeneration",
                "ManifestFile": "$(IntDir)$(TargetFileName).2intermediate.manifest",
                "MapExports": "true",
                "MapFileName": "d5",
                "MergedIDLBaseFileName": "f2",
                "MergeSections": "f5",
                "MidlCommandFile": "f1",
                "ModuleDefinitionFile": "sdsd",
                "NoEntryPoint": "true",
                "OptimizeReferences": "true",
                "OutputFile": "$(OutDir)$(ProjectName)2.exe",
                "PerUserRedirection": "true",
                "Profile": "true",
                "ProfileGuidedDatabase": "$(TargetDir)$(TargetName).pgdd",
                "ProgramDatabaseFile": "Flob.pdb",
                "RandomizedBaseAddress": "false",
                "RegisterOutput": "true",
                "SetChecksum": "false",
                "ShowProgress": "LinkVerbose",
                "StackCommitSize": "15",
                "StackReserveSize": "14",
                "StripPrivateSymbols": "d3",
                "SubSystem": "Console",
                "SupportUnloadOfDelayLoadedDLL": "true",
                "SuppressStartupBanner": "false",
                "SwapRunFromCD": "true",
                "SwapRunFromNET": "true",
                "TargetMachine": "MachineX86",
                "TerminalServerAware": "false",
                "TurnOffAssemblyGeneration": "true",
                "TypeLibraryFile": "f3",
                "TypeLibraryResourceID": "12",
                "UACExecutionLevel": "RequireAdministrator",
                "UACUIAccess": "true",
                "Version": "333",
            },
            "ResourceCompile": {
                "AdditionalIncludeDirectories": "f3",
                "AdditionalOptions": "/more3",
                "Culture": "0x0c0c",
                "IgnoreStandardIncludePath": "true",
                "PreprocessorDefinitions": "_UNICODE;UNICODE2",
                "ResourceOutputFileName": "$(IntDir)%(Filename)3.res",
                "ShowProgress": "true",
            },
            "Manifest": {
                "AdditionalManifestFiles": "sfsdfsd",
                "AdditionalOptions": "afdsdafsd",
                "AssemblyIdentity": "sddfdsadfsa",
                "ComponentFileName": "fsdfds",
                "GenerateCatalogFiles": "true",
                "InputResourceManifests": "asfsfdafs",
                "OutputManifestFile": "$(TargetPath).manifestdfs",
                "RegistrarScriptFile": "sdfsfd",
                "ReplacementsFile": "sdffsd",
                "SuppressStartupBanner": "false",
                "TypeLibraryFile": "sfsd",
                "UpdateFileHashes": "true",
                "UpdateFileHashesSearchPath": "sfsd",
                "VerboseOutput": "true",
            },
            "ProjectReference": {
                "LinkLibraryDependencies": "false",
                "UseLibraryDependencyInputs": "true",
            },
            "": {
                "EmbedManifest": "false",
                "GenerateManifest": "false",
                "IgnoreImportLibrary": "true",
                "LinkIncremental": "",
            },
            "ManifestResourceCompile": {
                "ResourceOutputFileName":
                    "$(IntDir)$(TargetFileName).embed.manifest.resfdsf"
            },
        }
        self.maxDiff = 9999  # on failure display a long diff
        actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
            msvs_settings, self.stderr
        )
        self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
        self._ExpectedWarnings([])


if __name__ == "__main__":
    unittest.main()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/* See https://github.com/libuv/libuv#documentation for documentation. */

#ifndef UV_H
#define UV_H
#ifdef __cplusplus
extern "C" {
#endif

#if defined(BUILDING_UV_SHARED) && defined(USING_UV_SHARED)
#error "Define either BUILDING_UV_SHARED or USING_UV_SHARED, not both."
#endif

#ifndef UV_EXTERN
#ifdef _WIN32
  /* Windows - set up dll import/export decorators. */
# if defined(BUILDING_UV_SHARED)
    /* Building shared library. */
#   define UV_EXTERN __declspec(dllexport)
# elif defined(USING_UV_SHARED)
    /* Using shared library. */
#   define UV_EXTERN __declspec(dllimport)
# else
    /* Building static library. */
#   define UV_EXTERN /* nothing */
# endif
#elif __GNUC__ >= 4
# define UV_EXTERN __attribute__((visibility("default")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) /* Sun Studio >= 8 */
# define UV_EXTERN __global
#else
# define UV_EXTERN /* nothing */
#endif
#endif /* UV_EXTERN */

#include "uv/errno.h"
#include "uv/version.h"
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>

/* Internal type, do not use. */
struct uv__queue {
  struct uv__queue* next;
  struct uv__queue* prev;
};

#if defined(_WIN32)
# include "uv/win.h"
#else
# include "uv/unix.h"
#endif

/* Expand this list if necessary. */
#define UV_ERRNO_MAP(XX)                                                      \
  XX(E2BIG, "argument list too long")                                         \
  XX(EACCES, "permission denied")                                             \
  XX(EADDRINUSE, "address already in use")                                    \
  XX(EADDRNOTAVAIL, "address not available")                                  \
  XX(EAFNOSUPPORT, "address family not supported")                            \
  XX(EAGAIN, "resource temporarily unavailable")                              \
  XX(EAI_ADDRFAMILY, "address family not supported")                          \
  XX(EAI_AGAIN, "temporary failure")                                          \
  XX(EAI_BADFLAGS, "bad ai_flags value")                                      \
  XX(EAI_BADHINTS, "invalid value for hints")                                 \
  XX(EAI_CANCELED, "request canceled")                                        \
  XX(EAI_FAIL, "permanent failure")                                           \
  XX(EAI_FAMILY, "ai_family not supported")                                   \
  XX(EAI_MEMORY, "out of memory")                                             \
  XX(EAI_NODATA, "no address")                                                \
  XX(EAI_NONAME, "unknown node or service")                                   \
  XX(EAI_OVERFLOW, "argument buffer overflow")                                \
  XX(EAI_PROTOCOL, "resolved protocol is unknown")                            \
  XX(EAI_SERVICE, "service not available for socket type")                    \
  XX(EAI_SOCKTYPE, "socket type not supported")                               \
  XX(EALREADY, "connection already in progress")                              \
  XX(EBADF, "bad file descriptor")                                            \
  XX(EBUSY, "resource busy or locked")                                        \
  XX(ECANCELED, "operation canceled")                                         \
  XX(ECHARSET, "invalid Unicode character")                                   \
  XX(ECONNABORTED, "software caused connection abort")                        \
  XX(ECONNREFUSED, "connection refused")                                      \
  XX(ECONNRESET, "connection reset by peer")                                  \
  XX(EDESTADDRREQ, "destination address required")                            \
  XX(EEXIST, "file already exists")                                           \
  XX(EFAULT, "bad address in system call argument")                           \
  XX(EFBIG, "file too large")                                                 \
  XX(EHOSTUNREACH, "host is unreachable")                                     \
  XX(EINTR, "interrupted system call")                                        \
  XX(EINVAL, "invalid argument")                                              \
  XX(EIO, "i/o error")                                                        \
  XX(EISCONN, "socket is already connected")                                  \
  XX(EISDIR, "illegal operation on a directory")                              \
  XX(ELOOP, "too many symbolic links encountered")                            \
  XX(EMFILE, "too many open files")                                           \
  XX(EMSGSIZE, "message too long")                                            \
  XX(ENAMETOOLONG, "name too long")                                           \
  XX(ENETDOWN, "network is down")                                             \
  XX(ENETUNREACH, "network is unreachable")                                   \
  XX(ENFILE, "file table overflow")                                           \
  XX(ENOBUFS, "no buffer space available")                                    \
  XX(ENODEV, "no such device")                                                \
  XX(ENOENT, "no such file or directory")                                     \
  XX(ENOMEM, "not enough memory")                                             \
  XX(ENONET, "machine is not on the network")                                 \
  XX(ENOPROTOOPT, "protocol not available")                                   \
  XX(ENOSPC, "no space left on device")                                       \
  XX(ENOSYS, "function not implemented")                                      \
  XX(ENOTCONN, "socket is not connected")                                     \
  XX(ENOTDIR, "not a directory")                                              \
  XX(ENOTEMPTY, "directory not empty")                                        \
  XX(ENOTSOCK, "socket operation on non-socket")                              \
  XX(ENOTSUP, "operation not supported on socket")                            \
  XX(EOVERFLOW, "value too large for defined data type")                      \
  XX(EPERM, "operation not permitted")                                        \
  XX(EPIPE, "broken pipe")                                                    \
  XX(EPROTO, "protocol error")                                                \
  XX(EPROTONOSUPPORT, "protocol not supported")                               \
  XX(EPROTOTYPE, "protocol wrong type for socket")                            \
  XX(ERANGE, "result too large")                                              \
  XX(EROFS, "read-only file system")                                          \
  XX(ESHUTDOWN, "cannot send after transport endpoint shutdown")              \
  XX(ESPIPE, "invalid seek")                                                  \
  XX(ESRCH, "no such process")                                                \
  XX(ETIMEDOUT, "connection timed out")                                       \
  XX(ETXTBSY, "text file is busy")                                            \
  XX(EXDEV, "cross-device link not permitted")                                \
  XX(UNKNOWN, "unknown error")                                                \
  XX(EOF, "end of file")                                                      \
  XX(ENXIO, "no such device or address")                                      \
  XX(EMLINK, "too many links")                                                \
  XX(EHOSTDOWN, "host is down")                                               \
  XX(EREMOTEIO, "remote I/O error")                                           \
  XX(ENOTTY, "inappropriate ioctl for device")                                \
  XX(EFTYPE, "inappropriate file type or format")                             \
  XX(EILSEQ, "illegal byte sequence")                                         \
  XX(ESOCKTNOSUPPORT, "socket type not supported")                            \
  XX(ENODATA, "no data available")                                            \
  XX(EUNATCH, "protocol driver not attached")                                 \

#define UV_HANDLE_TYPE_MAP(XX)                                                \
  XX(ASYNC, async)                                                            \
  XX(CHECK, check)                                                            \
  XX(FS_EVENT, fs_event)                                                      \
  XX(FS_POLL, fs_poll)                                                        \
  XX(HANDLE, handle)                                                          \
  XX(IDLE, idle)                                                              \
  XX(NAMED_PIPE, pipe)                                                        \
  XX(POLL, poll)                                                              \
  XX(PREPARE, prepare)                                                        \
  XX(PROCESS, process)                                                        \
  XX(STREAM, stream)                                                          \
  XX(TCP, tcp)                                                                \
  XX(TIMER, timer)                                                            \
  XX(TTY, tty)                                                                \
  XX(UDP, udp)                                                                \
  XX(SIGNAL, signal)                                                          \

#define UV_REQ_TYPE_MAP(XX)                                                   \
  XX(REQ, req)                                                                \
  XX(CONNECT, connect)                                                        \
  XX(WRITE, write)                                                            \
  XX(SHUTDOWN, shutdown)                                                      \
  XX(UDP_SEND, udp_send)                                                      \
  XX(FS, fs)                                                                  \
  XX(WORK, work)                                                              \
  XX(GETADDRINFO, getaddrinfo)                                                \
  XX(GETNAMEINFO, getnameinfo)                                                \
  XX(RANDOM, random)                                                          \

typedef enum {
#define XX(code, _) UV_ ## code = UV__ ## code,
  UV_ERRNO_MAP(XX)
#undef XX
  UV_ERRNO_MAX = UV__EOF - 1
} uv_errno_t;

typedef enum {
  UV_UNKNOWN_HANDLE = 0,
#define XX(uc, lc) UV_##uc,
  UV_HANDLE_TYPE_MAP(XX)
#undef XX
  UV_FILE,
  UV_HANDLE_TYPE_MAX
} uv_handle_type;

typedef enum {
  UV_UNKNOWN_REQ = 0,
#define XX(uc, lc) UV_##uc,
  UV_REQ_TYPE_MAP(XX)
#undef XX
  UV_REQ_TYPE_PRIVATE
  UV_REQ_TYPE_MAX
} uv_req_type;


/* Handle types. */
typedef struct uv_loop_s uv_loop_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_dir_s uv_dir_t;
typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_udp_s uv_udp_t;
typedef struct uv_pipe_s uv_pipe_t;
typedef struct uv_tty_s uv_tty_t;
typedef struct uv_poll_s uv_poll_t;
typedef struct uv_timer_s uv_timer_t;
typedef struct uv_prepare_s uv_prepare_t;
typedef struct uv_check_s uv_check_t;
typedef struct uv_idle_s uv_idle_t;
typedef struct uv_async_s uv_async_t;
typedef struct uv_process_s uv_process_t;
typedef struct uv_fs_event_s uv_fs_event_t;
typedef struct uv_fs_poll_s uv_fs_poll_t;
typedef struct uv_signal_s uv_signal_t;

/* Request types. */
typedef struct uv_req_s uv_req_t;
typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
typedef struct uv_getnameinfo_s uv_getnameinfo_t;
typedef struct uv_shutdown_s uv_shutdown_t;
typedef struct uv_write_s uv_write_t;
typedef struct uv_connect_s uv_connect_t;
typedef struct uv_udp_send_s uv_udp_send_t;
typedef struct uv_fs_s uv_fs_t;
typedef struct uv_work_s uv_work_t;
typedef struct uv_random_s uv_random_t;

/* None of the above. */
typedef struct uv_env_item_s uv_env_item_t;
typedef struct uv_cpu_info_s uv_cpu_info_t;
typedef struct uv_interface_address_s uv_interface_address_t;
typedef struct uv_dirent_s uv_dirent_t;
typedef struct uv_passwd_s uv_passwd_t;
typedef struct uv_group_s uv_group_t;
typedef struct uv_utsname_s uv_utsname_t;
typedef struct uv_statfs_s uv_statfs_t;

typedef struct uv_metrics_s uv_metrics_t;

typedef enum {
  UV_LOOP_BLOCK_SIGNAL = 0,
  UV_METRICS_IDLE_TIME
} uv_loop_option;

typedef enum {
  UV_RUN_DEFAULT = 0,
  UV_RUN_ONCE,
  UV_RUN_NOWAIT
} uv_run_mode;


UV_EXTERN unsigned int uv_version(void);
UV_EXTERN const char* uv_version_string(void);

typedef void* (*uv_malloc_func)(size_t size);
typedef void* (*uv_realloc_func)(void* ptr, size_t size);
typedef void* (*uv_calloc_func)(size_t count, size_t size);
typedef void (*uv_free_func)(void* ptr);

UV_EXTERN void uv_library_shutdown(void);

UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func,
                                   uv_realloc_func realloc_func,
                                   uv_calloc_func calloc_func,
                                   uv_free_func free_func);

UV_EXTERN uv_loop_t* uv_default_loop(void);
UV_EXTERN int uv_loop_init(uv_loop_t* loop);
UV_EXTERN int uv_loop_close(uv_loop_t* loop);
/*
 * NOTE:
 *  This function is DEPRECATED, users should
 *  allocate the loop manually and use uv_loop_init instead.
 */
UV_EXTERN uv_loop_t* uv_loop_new(void);
/*
 * NOTE:
 *  This function is DEPRECATED. Users should use
 *  uv_loop_close and free the memory manually instead.
 */
UV_EXTERN void uv_loop_delete(uv_loop_t*);
UV_EXTERN size_t uv_loop_size(void);
UV_EXTERN int uv_loop_alive(const uv_loop_t* loop);
UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...);
UV_EXTERN int uv_loop_fork(uv_loop_t* loop);

UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);
UV_EXTERN void uv_stop(uv_loop_t*);

UV_EXTERN void uv_ref(uv_handle_t*);
UV_EXTERN void uv_unref(uv_handle_t*);
UV_EXTERN int uv_has_ref(const uv_handle_t*);

UV_EXTERN void uv_update_time(uv_loop_t*);
UV_EXTERN uint64_t uv_now(const uv_loop_t*);

UV_EXTERN int uv_backend_fd(const uv_loop_t*);
UV_EXTERN int uv_backend_timeout(const uv_loop_t*);

typedef void (*uv_alloc_cb)(uv_handle_t* handle,
                            size_t suggested_size,
                            uv_buf_t* buf);
typedef void (*uv_read_cb)(uv_stream_t* stream,
                           ssize_t nread,
                           const uv_buf_t* buf);
typedef void (*uv_write_cb)(uv_write_t* req, int status);
typedef void (*uv_connect_cb)(uv_connect_t* req, int status);
typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);
typedef void (*uv_connection_cb)(uv_stream_t* server, int status);
typedef void (*uv_close_cb)(uv_handle_t* handle);
typedef void (*uv_poll_cb)(uv_poll_t* handle, int status, int events);
typedef void (*uv_timer_cb)(uv_timer_t* handle);
typedef void (*uv_async_cb)(uv_async_t* handle);
typedef void (*uv_prepare_cb)(uv_prepare_t* handle);
typedef void (*uv_check_cb)(uv_check_t* handle);
typedef void (*uv_idle_cb)(uv_idle_t* handle);
typedef void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal);
typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg);
typedef void (*uv_fs_cb)(uv_fs_t* req);
typedef void (*uv_work_cb)(uv_work_t* req);
typedef void (*uv_after_work_cb)(uv_work_t* req, int status);
typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req,
                                  int status,
                                  struct addrinfo* res);
typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req,
                                  int status,
                                  const char* hostname,
                                  const char* service);
typedef void (*uv_random_cb)(uv_random_t* req,
                             int status,
                             void* buf,
                             size_t buflen);

typedef enum {
  UV_CLOCK_MONOTONIC,
  UV_CLOCK_REALTIME
} uv_clock_id;

/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */
typedef struct {
  long tv_sec;
  long tv_nsec;
} uv_timespec_t;

typedef struct {
  int64_t tv_sec;
  int32_t tv_nsec;
} uv_timespec64_t;

/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */
typedef struct {
  long tv_sec;
  long tv_usec;
} uv_timeval_t;

typedef struct {
  int64_t tv_sec;
  int32_t tv_usec;
} uv_timeval64_t;

typedef struct {
  uint64_t st_dev;
  uint64_t st_mode;
  uint64_t st_nlink;
  uint64_t st_uid;
  uint64_t st_gid;
  uint64_t st_rdev;
  uint64_t st_ino;
  uint64_t st_size;
  uint64_t st_blksize;
  uint64_t st_blocks;
  uint64_t st_flags;
  uint64_t st_gen;
  uv_timespec_t st_atim;
  uv_timespec_t st_mtim;
  uv_timespec_t st_ctim;
  uv_timespec_t st_birthtim;
} uv_stat_t;


typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle,
                               const char* filename,
                               int events,
                               int status);

typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle,
                              int status,
                              const uv_stat_t* prev,
                              const uv_stat_t* curr);

typedef void (*uv_signal_cb)(uv_signal_t* handle, int signum);


typedef enum {
  UV_LEAVE_GROUP = 0,
  UV_JOIN_GROUP
} uv_membership;


UV_EXTERN int uv_translate_sys_error(int sys_errno);

UV_EXTERN const char* uv_strerror(int err);
UV_EXTERN char* uv_strerror_r(int err, char* buf, size_t buflen);

UV_EXTERN const char* uv_err_name(int err);
UV_EXTERN char* uv_err_name_r(int err, char* buf, size_t buflen);


#define UV_REQ_FIELDS                                                         \
  /* public */                                                                \
  void* data;                                                                 \
  /* read-only */                                                             \
  uv_req_type type;                                                           \
  /* private */                                                               \
  void* reserved[6];                                                          \
  UV_REQ_PRIVATE_FIELDS                                                       \

/* Abstract base class of all requests. */
struct uv_req_s {
  UV_REQ_FIELDS
};


/* Platform-specific request types. */
UV_PRIVATE_REQ_TYPES


UV_EXTERN int uv_shutdown(uv_shutdown_t* req,
                          uv_stream_t* handle,
                          uv_shutdown_cb cb);

struct uv_shutdown_s {
  UV_REQ_FIELDS
  uv_stream_t* handle;
  uv_shutdown_cb cb;
  UV_SHUTDOWN_PRIVATE_FIELDS
};


#define UV_HANDLE_FIELDS                                                      \
  /* public */                                                                \
  void* data;                                                                 \
  /* read-only */                                                             \
  uv_loop_t* loop;                                                            \
  uv_handle_type type;                                                        \
  /* private */                                                               \
  uv_close_cb close_cb;                                                       \
  struct uv__queue handle_queue;                                              \
  union {                                                                     \
    int fd;                                                                   \
    void* reserved[4];                                                        \
  } u;                                                                        \
  UV_HANDLE_PRIVATE_FIELDS                                                    \

/* The abstract base class of all handles. */
struct uv_handle_s {
  UV_HANDLE_FIELDS
};

UV_EXTERN size_t uv_handle_size(uv_handle_type type);
UV_EXTERN uv_handle_type uv_handle_get_type(const uv_handle_t* handle);
UV_EXTERN const char* uv_handle_type_name(uv_handle_type type);
UV_EXTERN void* uv_handle_get_data(const uv_handle_t* handle);
UV_EXTERN uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle);
UV_EXTERN void uv_handle_set_data(uv_handle_t* handle, void* data);

UV_EXTERN size_t uv_req_size(uv_req_type type);
UV_EXTERN void* uv_req_get_data(const uv_req_t* req);
UV_EXTERN void uv_req_set_data(uv_req_t* req, void* data);
UV_EXTERN uv_req_type uv_req_get_type(const uv_req_t* req);
UV_EXTERN const char* uv_req_type_name(uv_req_type type);

UV_EXTERN int uv_is_active(const uv_handle_t* handle);

UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);

/* Helpers for ad hoc debugging, no API/ABI stability guaranteed. */
UV_EXTERN void uv_print_all_handles(uv_loop_t* loop, FILE* stream);
UV_EXTERN void uv_print_active_handles(uv_loop_t* loop, FILE* stream);

UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);

UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value);
UV_EXTERN int uv_recv_buffer_size(uv_handle_t* handle, int* value);

UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd);

UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len);

UV_EXTERN int uv_pipe(uv_file fds[2], int read_flags, int write_flags);
UV_EXTERN int uv_socketpair(int type,
                            int protocol,
                            uv_os_sock_t socket_vector[2],
                            int flags0,
                            int flags1);

#define UV_STREAM_FIELDS                                                      \
  /* number of bytes queued for writing */                                    \
  size_t write_queue_size;                                                    \
  uv_alloc_cb alloc_cb;                                                       \
  uv_read_cb read_cb;                                                         \
  /* private */                                                               \
  UV_STREAM_PRIVATE_FIELDS

/*
 * uv_stream_t is a subclass of uv_handle_t.
 *
 * uv_stream is an abstract class.
 *
 * uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t and uv_tty_t.
 */
struct uv_stream_s {
  UV_HANDLE_FIELDS
  UV_STREAM_FIELDS
};

UV_EXTERN size_t uv_stream_get_write_queue_size(const uv_stream_t* stream);

UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client);

UV_EXTERN int uv_read_start(uv_stream_t*,
                            uv_alloc_cb alloc_cb,
                            uv_read_cb read_cb);
UV_EXTERN int uv_read_stop(uv_stream_t*);

UV_EXTERN int uv_write(uv_write_t* req,
                       uv_stream_t* handle,
                       const uv_buf_t bufs[],
                       unsigned int nbufs,
                       uv_write_cb cb);
UV_EXTERN int uv_write2(uv_write_t* req,
                        uv_stream_t* handle,
                        const uv_buf_t bufs[],
                        unsigned int nbufs,
                        uv_stream_t* send_handle,
                        uv_write_cb cb);
UV_EXTERN int uv_try_write(uv_stream_t* handle,
                           const uv_buf_t bufs[],
                           unsigned int nbufs);
UV_EXTERN int uv_try_write2(uv_stream_t* handle,
                            const uv_buf_t bufs[],
                            unsigned int nbufs,
                            uv_stream_t* send_handle);

/* uv_write_t is a subclass of uv_req_t. */
struct uv_write_s {
  UV_REQ_FIELDS
  uv_write_cb cb;
  uv_stream_t* send_handle; /* TODO: make private and unix-only in v2.x. */
  uv_stream_t* handle;
  UV_WRITE_PRIVATE_FIELDS
};


UV_EXTERN int uv_is_readable(const uv_stream_t* handle);
UV_EXTERN int uv_is_writable(const uv_stream_t* handle);

UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking);

UV_EXTERN int uv_is_closing(const uv_handle_t* handle);


/*
 * uv_tcp_t is a subclass of uv_stream_t.
 *
 * Represents a TCP stream or TCP server.
 */
struct uv_tcp_s {
  UV_HANDLE_FIELDS
  UV_STREAM_FIELDS
  UV_TCP_PRIVATE_FIELDS
};

UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle);
UV_EXTERN int uv_tcp_init_ex(uv_loop_t*, uv_tcp_t* handle, unsigned int flags);
UV_EXTERN int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock);
UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
                               int enable,
                               unsigned int delay);
UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);

enum uv_tcp_flags {
  /* Used with uv_tcp_bind, when an IPv6 address is used. */
  UV_TCP_IPV6ONLY = 1
};

UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle,
                          const struct sockaddr* addr,
                          unsigned int flags);
UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle,
                                 struct sockaddr* name,
                                 int* namelen);
UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle,
                                 struct sockaddr* name,
                                 int* namelen);
UV_EXTERN int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb);
UV_EXTERN int uv_tcp_connect(uv_connect_t* req,
                             uv_tcp_t* handle,
                             const struct sockaddr* addr,
                             uv_connect_cb cb);

/* uv_connect_t is a subclass of uv_req_t. */
struct uv_connect_s {
  UV_REQ_FIELDS
  uv_connect_cb cb;
  uv_stream_t* handle;
  UV_CONNECT_PRIVATE_FIELDS
};


/*
 * UDP support.
 */

enum uv_udp_flags {
  /* Disables dual stack mode. */
  UV_UDP_IPV6ONLY = 1,
  /*
   * Indicates message was truncated because read buffer was too small. The
   * remainder was discarded by the OS. Used in uv_udp_recv_cb.
   */
  UV_UDP_PARTIAL = 2,
  /*
   * Indicates if SO_REUSEADDR will be set when binding the handle.
   * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
   * Unix platforms, it sets the SO_REUSEADDR flag.  What that means is that
   * multiple threads or processes can bind to the same address without error
   * (provided they all set the flag) but only the last one to bind will receive
   * any traffic, in effect "stealing" the port from the previous listener.
   */
  UV_UDP_REUSEADDR = 4,
  /*
   * Indicates that the message was received by recvmmsg, so the buffer provided
   * must not be freed by the recv_cb callback.
   */
  UV_UDP_MMSG_CHUNK = 8,
  /*
   * Indicates that the buffer provided has been fully utilized by recvmmsg and
   * that it should now be freed by the recv_cb callback. When this flag is set
   * in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL.
   */
  UV_UDP_MMSG_FREE = 16,
  /*
   * Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
   * This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
   * Linux. This stops the Linux kernel from suppressing some ICMP error
   * messages and enables full ICMP error reporting for faster failover.
   * This flag is no-op on platforms other than Linux.
   */
  UV_UDP_LINUX_RECVERR = 32,
  /*
   * Indicates that recvmmsg should be used, if available.
   */
  UV_UDP_RECVMMSG = 256
};

typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
typedef void (*uv_udp_recv_cb)(uv_udp_t* handle,
                               ssize_t nread,
                               const uv_buf_t* buf,
                               const struct sockaddr* addr,
                               unsigned flags);

/* uv_udp_t is a subclass of uv_handle_t. */
struct uv_udp_s {
  UV_HANDLE_FIELDS
  /* read-only */
  /*
   * Number of bytes queued for sending. This field strictly shows how much
   * information is currently queued.
   */
  size_t send_queue_size;
  /*
   * Number of send requests currently in the queue awaiting to be processed.
   */
  size_t send_queue_count;
  UV_UDP_PRIVATE_FIELDS
};

/* uv_udp_send_t is a subclass of uv_req_t. */
struct uv_udp_send_s {
  UV_REQ_FIELDS
  uv_udp_t* handle;
  uv_udp_send_cb cb;
  UV_UDP_SEND_PRIVATE_FIELDS
};

UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
UV_EXTERN int uv_udp_init_ex(uv_loop_t*, uv_udp_t* handle, unsigned int flags);
UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
                          const struct sockaddr* addr,
                          unsigned int flags);
UV_EXTERN int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr);

UV_EXTERN int uv_udp_getpeername(const uv_udp_t* handle,
                                 struct sockaddr* name,
                                 int* namelen);
UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,
                                 struct sockaddr* name,
                                 int* namelen);
UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle,
                                    const char* multicast_addr,
                                    const char* interface_addr,
                                    uv_membership membership);
UV_EXTERN int uv_udp_set_source_membership(uv_udp_t* handle,
                                           const char* multicast_addr,
                                           const char* interface_addr,
                                           const char* source_addr,
                                           uv_membership membership);
UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on);
UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl);
UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle,
                                             const char* interface_addr);
UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on);
UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl);
UV_EXTERN int uv_udp_send(uv_udp_send_t* req,
                          uv_udp_t* handle,
                          const uv_buf_t bufs[],
                          unsigned int nbufs,
                          const struct sockaddr* addr,
                          uv_udp_send_cb send_cb);
UV_EXTERN int uv_udp_try_send(uv_udp_t* handle,
                              const uv_buf_t bufs[],
                              unsigned int nbufs,
                              const struct sockaddr* addr);
UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
                                uv_alloc_cb alloc_cb,
                                uv_udp_recv_cb recv_cb);
UV_EXTERN int uv_udp_using_recvmmsg(const uv_udp_t* handle);
UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);
UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);


/*
 * uv_tty_t is a subclass of uv_stream_t.
 *
 * Representing a stream for the console.
 */
struct uv_tty_s {
  UV_HANDLE_FIELDS
  UV_STREAM_FIELDS
  UV_TTY_PRIVATE_FIELDS
};

typedef enum {
  /* Initial/normal terminal mode */
  UV_TTY_MODE_NORMAL,
  /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
  UV_TTY_MODE_RAW,
  /* Binary-safe I/O mode for IPC (Unix-only) */
  UV_TTY_MODE_IO
} uv_tty_mode_t;

typedef enum {
  /*
   * The console supports handling of virtual terminal sequences
   * (Windows10 new console, ConEmu)
   */
  UV_TTY_SUPPORTED,
  /* The console cannot process the virtual terminal sequence.  (Legacy
   * console)
   */
  UV_TTY_UNSUPPORTED
} uv_tty_vtermstate_t;


UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable);
UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode);
UV_EXTERN int uv_tty_reset_mode(void);
UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);
UV_EXTERN void uv_tty_set_vterm_state(uv_tty_vtermstate_t state);
UV_EXTERN int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state);

#ifdef __cplusplus
extern "C++" {

inline int uv_tty_set_mode(uv_tty_t* handle, int mode) {
  return uv_tty_set_mode(handle, static_cast<uv_tty_mode_t>(mode));
}

}
#endif

UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);

enum {
  UV_PIPE_NO_TRUNCATE = 1u << 0
};

/*
 * uv_pipe_t is a subclass of uv_stream_t.
 *
 * Representing a pipe stream or pipe server. On Windows this is a Named
 * Pipe. On Unix this is a Unix domain socket.
 */
struct uv_pipe_s {
  UV_HANDLE_FIELDS
  UV_STREAM_FIELDS
  int ipc; /* non-zero if this pipe is used for passing handles */
  UV_PIPE_PRIVATE_FIELDS
};

UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);
UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file);
UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);
UV_EXTERN int uv_pipe_bind2(uv_pipe_t* handle,
                            const char* name,
                            size_t namelen,
                            unsigned int flags);
UV_EXTERN void uv_pipe_connect(uv_connect_t* req,
                               uv_pipe_t* handle,
                               const char* name,
                               uv_connect_cb cb);
UV_EXTERN int uv_pipe_connect2(uv_connect_t* req,
                               uv_pipe_t* handle,
                               const char* name,
                               size_t namelen,
                               unsigned int flags,
                               uv_connect_cb cb);
UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,
                                  char* buffer,
                                  size_t* size);
UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle,
                                  char* buffer,
                                  size_t* size);
UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count);
UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle);
UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
UV_EXTERN int uv_pipe_chmod(uv_pipe_t* handle, int flags);


struct uv_poll_s {
  UV_HANDLE_FIELDS
  uv_poll_cb poll_cb;
  UV_POLL_PRIVATE_FIELDS
};

enum uv_poll_event {
  UV_READABLE = 1,
  UV_WRITABLE = 2,
  UV_DISCONNECT = 4,
  UV_PRIORITIZED = 8
};

UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd);
UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop,
                                  uv_poll_t* handle,
                                  uv_os_sock_t socket);
UV_EXTERN int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb);
UV_EXTERN int uv_poll_stop(uv_poll_t* handle);


struct uv_prepare_s {
  UV_HANDLE_FIELDS
  UV_PREPARE_PRIVATE_FIELDS
};

UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare);
UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb);
UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare);


struct uv_check_s {
  UV_HANDLE_FIELDS
  UV_CHECK_PRIVATE_FIELDS
};

UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check);
UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb);
UV_EXTERN int uv_check_stop(uv_check_t* check);


struct uv_idle_s {
  UV_HANDLE_FIELDS
  UV_IDLE_PRIVATE_FIELDS
};

UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle);
UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb);
UV_EXTERN int uv_idle_stop(uv_idle_t* idle);


struct uv_async_s {
  UV_HANDLE_FIELDS
  UV_ASYNC_PRIVATE_FIELDS
};

UV_EXTERN int uv_async_init(uv_loop_t*,
                            uv_async_t* async,
                            uv_async_cb async_cb);
UV_EXTERN int uv_async_send(uv_async_t* async);


/*
 * uv_timer_t is a subclass of uv_handle_t.
 *
 * Used to get woken up at a specified time in the future.
 */
struct uv_timer_s {
  UV_HANDLE_FIELDS
  UV_TIMER_PRIVATE_FIELDS
};

UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* handle);
UV_EXTERN int uv_timer_start(uv_timer_t* handle,
                             uv_timer_cb cb,
                             uint64_t timeout,
                             uint64_t repeat);
UV_EXTERN int uv_timer_stop(uv_timer_t* handle);
UV_EXTERN int uv_timer_again(uv_timer_t* handle);
UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat);
UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle);
UV_EXTERN uint64_t uv_timer_get_due_in(const uv_timer_t* handle);


/*
 * uv_getaddrinfo_t is a subclass of uv_req_t.
 *
 * Request object for uv_getaddrinfo.
 */
struct uv_getaddrinfo_s {
  UV_REQ_FIELDS
  /* read-only */
  uv_loop_t* loop;
  /* struct addrinfo* addrinfo is marked as private, but it really isn't. */
  UV_GETADDRINFO_PRIVATE_FIELDS
};


UV_EXTERN int uv_getaddrinfo(uv_loop_t* loop,
                             uv_getaddrinfo_t* req,
                             uv_getaddrinfo_cb getaddrinfo_cb,
                             const char* node,
                             const char* service,
                             const struct addrinfo* hints);
UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai);


/*
* uv_getnameinfo_t is a subclass of uv_req_t.
*
* Request object for uv_getnameinfo.
*/
struct uv_getnameinfo_s {
  UV_REQ_FIELDS
  /* read-only */
  uv_loop_t* loop;
  /* host and service are marked as private, but they really aren't. */
  UV_GETNAMEINFO_PRIVATE_FIELDS
};

UV_EXTERN int uv_getnameinfo(uv_loop_t* loop,
                             uv_getnameinfo_t* req,
                             uv_getnameinfo_cb getnameinfo_cb,
                             const struct sockaddr* addr,
                             int flags);


/* uv_spawn() options. */
typedef enum {
  UV_IGNORE         = 0x00,
  UV_CREATE_PIPE    = 0x01,
  UV_INHERIT_FD     = 0x02,
  UV_INHERIT_STREAM = 0x04,

  /*
   * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE
   * determine the direction of flow, from the child process' perspective. Both
   * flags may be specified to create a duplex data stream.
   */
  UV_READABLE_PIPE  = 0x10,
  UV_WRITABLE_PIPE  = 0x20,

  /*
   * When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the
   * handle in non-blocking mode in the child. This may cause loss of data,
   * if the child is not designed to handle to encounter this mode,
   * but can also be significantly more efficient.
   */
  UV_NONBLOCK_PIPE  = 0x40,
  UV_OVERLAPPED_PIPE = 0x40 /* old name, for compatibility */
} uv_stdio_flags;

typedef struct uv_stdio_container_s {
  uv_stdio_flags flags;

  union {
    uv_stream_t* stream;
    int fd;
  } data;
} uv_stdio_container_t;

typedef struct uv_process_options_s {
  uv_exit_cb exit_cb; /* Called after the process exits. */
  const char* file;   /* Path to program to execute. */
  /*
   * Command line arguments. args[0] should be the path to the program. On
   * Windows this uses CreateProcess which concatenates the arguments into a
   * string this can cause some strange errors. See the note at
   * windows_verbatim_arguments.
   */
  char** args;
  /*
   * This will be set as the environ variable in the subprocess. If this is
   * NULL then the parents environ will be used.
   */
  char** env;
  /*
   * If non-null this represents a directory the subprocess should execute
   * in. Stands for current working directory.
   */
  const char* cwd;
  /*
   * Various flags that control how uv_spawn() behaves. See the definition of
   * `enum uv_process_flags` below.
   */
  unsigned int flags;
  /*
   * The `stdio` field points to an array of uv_stdio_container_t structs that
   * describe the file descriptors that will be made available to the child
   * process. The convention is that stdio[0] points to stdin, fd 1 is used for
   * stdout, and fd 2 is stderr.
   *
   * Note that on windows file descriptors greater than 2 are available to the
   * child process only if the child processes uses the MSVCRT runtime.
   */
  int stdio_count;
  uv_stdio_container_t* stdio;
  /*
   * Libuv can change the child process' user/group id. This happens only when
   * the appropriate bits are set in the flags fields. This is not supported on
   * windows; uv_spawn() will fail and set the error to UV_ENOTSUP.
   */
  uv_uid_t uid;
  uv_gid_t gid;
} uv_process_options_t;

/*
 * These are the flags that can be used for the uv_process_options.flags field.
 */
enum uv_process_flags {
  /*
   * Set the child process' user id. The user id is supplied in the `uid` field
   * of the options struct. This does not work on windows; setting this flag
   * will cause uv_spawn() to fail.
   */
  UV_PROCESS_SETUID = (1 << 0),
  /*
   * Set the child process' group id. The user id is supplied in the `gid`
   * field of the options struct. This does not work on windows; setting this
   * flag will cause uv_spawn() to fail.
   */
  UV_PROCESS_SETGID = (1 << 1),
  /*
   * Do not wrap any arguments in quotes, or perform any other escaping, when
   * converting the argument list into a command line string. This option is
   * only meaningful on Windows systems. On Unix it is silently ignored.
   */
  UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2),
  /*
   * Spawn the child process in a detached state - this will make it a process
   * group leader, and will effectively enable the child to keep running after
   * the parent exits.  Note that the child process will still keep the
   * parent's event loop alive unless the parent process calls uv_unref() on
   * the child's process handle.
   */
  UV_PROCESS_DETACHED = (1 << 3),
  /*
   * Hide the subprocess window that would normally be created. This option is
   * only meaningful on Windows systems. On Unix it is silently ignored.
   */
  UV_PROCESS_WINDOWS_HIDE = (1 << 4),
  /*
   * Hide the subprocess console window that would normally be created. This
   * option is only meaningful on Windows systems. On Unix it is silently
   * ignored.
   */
  UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5),
  /*
   * Hide the subprocess GUI window that would normally be created. This
   * option is only meaningful on Windows systems. On Unix it is silently
   * ignored.
   */
  UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6)
};

/*
 * uv_process_t is a subclass of uv_handle_t.
 */
struct uv_process_s {
  UV_HANDLE_FIELDS
  uv_exit_cb exit_cb;
  int pid;
  UV_PROCESS_PRIVATE_FIELDS
};

UV_EXTERN int uv_spawn(uv_loop_t* loop,
                       uv_process_t* handle,
                       const uv_process_options_t* options);
UV_EXTERN int uv_process_kill(uv_process_t*, int signum);
UV_EXTERN int uv_kill(int pid, int signum);
UV_EXTERN uv_pid_t uv_process_get_pid(const uv_process_t*);


/*
 * uv_work_t is a subclass of uv_req_t.
 */
struct uv_work_s {
  UV_REQ_FIELDS
  uv_loop_t* loop;
  uv_work_cb work_cb;
  uv_after_work_cb after_work_cb;
  UV_WORK_PRIVATE_FIELDS
};

UV_EXTERN int uv_queue_work(uv_loop_t* loop,
                            uv_work_t* req,
                            uv_work_cb work_cb,
                            uv_after_work_cb after_work_cb);

UV_EXTERN int uv_cancel(uv_req_t* req);


struct uv_cpu_times_s {
  uint64_t user; /* milliseconds */
  uint64_t nice; /* milliseconds */
  uint64_t sys; /* milliseconds */
  uint64_t idle; /* milliseconds */
  uint64_t irq; /* milliseconds */
};

struct uv_cpu_info_s {
  char* model;
  int speed;
  struct uv_cpu_times_s cpu_times;
};

struct uv_interface_address_s {
  char* name;
  char phys_addr[6];
  int is_internal;
  union {
    struct sockaddr_in address4;
    struct sockaddr_in6 address6;
  } address;
  union {
    struct sockaddr_in netmask4;
    struct sockaddr_in6 netmask6;
  } netmask;
};

struct uv_passwd_s {
  char* username;
  unsigned long uid;
  unsigned long gid;
  char* shell;
  char* homedir;
};

struct uv_group_s {
  char* groupname;
  unsigned long gid;
  char** members;
};

struct uv_utsname_s {
  char sysname[256];
  char release[256];
  char version[256];
  char machine[256];
  /* This struct does not contain the nodename and domainname fields present in
     the utsname type. domainname is a GNU extension. Both fields are referred
     to as meaningless in the docs. */
};

struct uv_statfs_s {
  uint64_t f_type;
  uint64_t f_bsize;
  uint64_t f_blocks;
  uint64_t f_bfree;
  uint64_t f_bavail;
  uint64_t f_files;
  uint64_t f_ffree;
  uint64_t f_spare[4];
};

typedef enum {
  UV_DIRENT_UNKNOWN,
  UV_DIRENT_FILE,
  UV_DIRENT_DIR,
  UV_DIRENT_LINK,
  UV_DIRENT_FIFO,
  UV_DIRENT_SOCKET,
  UV_DIRENT_CHAR,
  UV_DIRENT_BLOCK
} uv_dirent_type_t;

struct uv_dirent_s {
  const char* name;
  uv_dirent_type_t type;
};

UV_EXTERN char** uv_setup_args(int argc, char** argv);
UV_EXTERN int uv_get_process_title(char* buffer, size_t size);
UV_EXTERN int uv_set_process_title(const char* title);
UV_EXTERN int uv_resident_set_memory(size_t* rss);
UV_EXTERN int uv_uptime(double* uptime);
UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd);

typedef struct {
   uv_timeval_t ru_utime; /* user CPU time used */
   uv_timeval_t ru_stime; /* system CPU time used */
   uint64_t ru_maxrss;    /* maximum resident set size */
   uint64_t ru_ixrss;     /* integral shared memory size */
   uint64_t ru_idrss;     /* integral unshared data size */
   uint64_t ru_isrss;     /* integral unshared stack size */
   uint64_t ru_minflt;    /* page reclaims (soft page faults) */
   uint64_t ru_majflt;    /* page faults (hard page faults) */
   uint64_t ru_nswap;     /* swaps */
   uint64_t ru_inblock;   /* block input operations */
   uint64_t ru_oublock;   /* block output operations */
   uint64_t ru_msgsnd;    /* IPC messages sent */
   uint64_t ru_msgrcv;    /* IPC messages received */
   uint64_t ru_nsignals;  /* signals received */
   uint64_t ru_nvcsw;     /* voluntary context switches */
   uint64_t ru_nivcsw;    /* involuntary context switches */
} uv_rusage_t;

UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);

UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);
UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd);
UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
UV_EXTERN int uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid);
UV_EXTERN int uv_os_get_group(uv_group_t* grp, uv_uid_t gid);
UV_EXTERN void uv_os_free_group(uv_group_t* grp);
UV_EXTERN uv_pid_t uv_os_getpid(void);
UV_EXTERN uv_pid_t uv_os_getppid(void);

#if defined(__PASE__)
/* On IBM i PASE, the highest process priority is -10 */
# define UV_PRIORITY_LOW 39          /* RUNPTY(99) */
# define UV_PRIORITY_BELOW_NORMAL 15 /* RUNPTY(50) */
# define UV_PRIORITY_NORMAL 0        /* RUNPTY(20) */
# define UV_PRIORITY_ABOVE_NORMAL -4 /* RUNTY(12) */
# define UV_PRIORITY_HIGH -7         /* RUNPTY(6) */
# define UV_PRIORITY_HIGHEST -10     /* RUNPTY(1) */
#else
# define UV_PRIORITY_LOW 19
# define UV_PRIORITY_BELOW_NORMAL 10
# define UV_PRIORITY_NORMAL 0
# define UV_PRIORITY_ABOVE_NORMAL -7
# define UV_PRIORITY_HIGH -14
# define UV_PRIORITY_HIGHEST -20
#endif

UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);

UV_EXTERN unsigned int uv_available_parallelism(void);
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
UV_EXTERN int uv_cpumask_size(void);

UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
                                     int* count);
UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
                                           int count);

struct uv_env_item_s {
  char* name;
  char* value;
};

UV_EXTERN int uv_os_environ(uv_env_item_t** envitems, int* count);
UV_EXTERN void uv_os_free_environ(uv_env_item_t* envitems, int count);
UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
UV_EXTERN int uv_os_setenv(const char* name, const char* value);
UV_EXTERN int uv_os_unsetenv(const char* name);

#ifdef MAXHOSTNAMELEN
# define UV_MAXHOSTNAMESIZE (MAXHOSTNAMELEN + 1)
#else
  /*
    Fallback for the maximum hostname size, including the null terminator. The
    Windows gethostname() documentation states that 256 bytes will always be
    large enough to hold the null-terminated hostname.
  */
# define UV_MAXHOSTNAMESIZE 256
#endif

UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);

UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);

struct uv_metrics_s {
  uint64_t loop_count;
  uint64_t events;
  uint64_t events_waiting;
  /* private */
  uint64_t* reserved[13];
};

UV_EXTERN int uv_metrics_info(uv_loop_t* loop, uv_metrics_t* metrics);
UV_EXTERN uint64_t uv_metrics_idle_time(uv_loop_t* loop);

typedef enum {
  UV_FS_UNKNOWN = -1,
  UV_FS_CUSTOM,
  UV_FS_OPEN,
  UV_FS_CLOSE,
  UV_FS_READ,
  UV_FS_WRITE,
  UV_FS_SENDFILE,
  UV_FS_STAT,
  UV_FS_LSTAT,
  UV_FS_FSTAT,
  UV_FS_FTRUNCATE,
  UV_FS_UTIME,
  UV_FS_FUTIME,
  UV_FS_ACCESS,
  UV_FS_CHMOD,
  UV_FS_FCHMOD,
  UV_FS_FSYNC,
  UV_FS_FDATASYNC,
  UV_FS_UNLINK,
  UV_FS_RMDIR,
  UV_FS_MKDIR,
  UV_FS_MKDTEMP,
  UV_FS_RENAME,
  UV_FS_SCANDIR,
  UV_FS_LINK,
  UV_FS_SYMLINK,
  UV_FS_READLINK,
  UV_FS_CHOWN,
  UV_FS_FCHOWN,
  UV_FS_REALPATH,
  UV_FS_COPYFILE,
  UV_FS_LCHOWN,
  UV_FS_OPENDIR,
  UV_FS_READDIR,
  UV_FS_CLOSEDIR,
  UV_FS_STATFS,
  UV_FS_MKSTEMP,
  UV_FS_LUTIME
} uv_fs_type;

struct uv_dir_s {
  uv_dirent_t* dirents;
  size_t nentries;
  void* reserved[4];
  UV_DIR_PRIVATE_FIELDS
};

/* uv_fs_t is a subclass of uv_req_t. */
struct uv_fs_s {
  UV_REQ_FIELDS
  uv_fs_type fs_type;
  uv_loop_t* loop;
  uv_fs_cb cb;
  ssize_t result;
  void* ptr;
  const char* path;
  uv_stat_t statbuf;  /* Stores the result of uv_fs_stat() and uv_fs_fstat(). */
  UV_FS_PRIVATE_FIELDS
};

UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*);
UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*);
UV_EXTERN int uv_fs_get_system_error(const uv_fs_t*);
UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*);
UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*);
UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*);

UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req);
UV_EXTERN int uv_fs_close(uv_loop_t* loop,
                          uv_fs_t* req,
                          uv_file file,
                          uv_fs_cb cb);
UV_EXTERN int uv_fs_open(uv_loop_t* loop,
                         uv_fs_t* req,
                         const char* path,
                         int flags,
                         int mode,
                         uv_fs_cb cb);
UV_EXTERN int uv_fs_read(uv_loop_t* loop,
                         uv_fs_t* req,
                         uv_file file,
                         const uv_buf_t bufs[],
                         unsigned int nbufs,
                         int64_t offset,
                         uv_fs_cb cb);
UV_EXTERN int uv_fs_unlink(uv_loop_t* loop,
                           uv_fs_t* req,
                           const char* path,
                           uv_fs_cb cb);
UV_EXTERN int uv_fs_write(uv_loop_t* loop,
                          uv_fs_t* req,
                          uv_file file,
                          const uv_buf_t bufs[],
                          unsigned int nbufs,
                          int64_t offset,
                          uv_fs_cb cb);
/*
 * This flag can be used with uv_fs_copyfile() to return an error if the
 * destination already exists.
 */
#define UV_FS_COPYFILE_EXCL   0x0001

/*
 * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
 * If copy-on-write is not supported, a fallback copy mechanism is used.
 */
#define UV_FS_COPYFILE_FICLONE 0x0002

/*
 * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
 * If copy-on-write is not supported, an error is returned.
 */
#define UV_FS_COPYFILE_FICLONE_FORCE 0x0004

UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
                             uv_fs_t* req,
                             const char* path,
                             const char* new_path,
                             int flags,
                             uv_fs_cb cb);
UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop,
                          uv_fs_t* req,
                          const char* path,
                          int mode,
                          uv_fs_cb cb);
UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop,
                            uv_fs_t* req,
                            const char* tpl,
                            uv_fs_cb cb);
UV_EXTERN int uv_fs_mkstemp(uv_loop_t* loop,
                            uv_fs_t* req,
                            const char* tpl,
                            uv_fs_cb cb);
UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop,
                          uv_fs_t* req,
                          const char* path,
                          uv_fs_cb cb);
UV_EXTERN int uv_fs_scandir(uv_loop_t* loop,
                            uv_fs_t* req,
                            const char* path,
                            int flags,
                            uv_fs_cb cb);
UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req,
                                 uv_dirent_t* ent);
UV_EXTERN int uv_fs_opendir(uv_loop_t* loop,
                            uv_fs_t* req,
                            const char* path,
                            uv_fs_cb cb);
UV_EXTERN int uv_fs_readdir(uv_loop_t* loop,
                            uv_fs_t* req,
                            uv_dir_t* dir,
                            uv_fs_cb cb);
UV_EXTERN int uv_fs_closedir(uv_loop_t* loop,
                             uv_fs_t* req,
                             uv_dir_t* dir,
                             uv_fs_cb cb);
UV_EXTERN int uv_fs_stat(uv_loop_t* loop,
                         uv_fs_t* req,
                         const char* path,
                         uv_fs_cb cb);
UV_EXTERN int uv_fs_fstat(uv_loop_t* loop,
                          uv_fs_t* req,
                          uv_file file,
                          uv_fs_cb cb);
UV_EXTERN int uv_fs_rename(uv_loop_t* loop,
                           uv_fs_t* req,
                           const char* path,
                           const char* new_path,
                           uv_fs_cb cb);
UV_EXTERN int uv_fs_fsync(uv_loop_t* loop,
                          uv_fs_t* req,
                          uv_file file,
                          uv_fs_cb cb);
UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop,
                              uv_fs_t* req,
                              uv_file file,
                              uv_fs_cb cb);
UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop,
                              uv_fs_t* req,
                              uv_file file,
                              int64_t offset,
                              uv_fs_cb cb);
UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop,
                             uv_fs_t* req,
                             uv_file out_fd,
                             uv_file in_fd,
                             int64_t in_offset,
                             size_t length,
                             uv_fs_cb cb);
UV_EXTERN int uv_fs_access(uv_loop_t* loop,
                           uv_fs_t* req,
                           const char* path,
                           int mode,
                           uv_fs_cb cb);
UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
                          uv_fs_t* req,
                          const char* path,
                          int mode,
                          uv_fs_cb cb);
UV_EXTERN int uv_fs_utime(uv_loop_t* loop,
                          uv_fs_t* req,
                          const char* path,
                          double atime,
                          double mtime,
                          uv_fs_cb cb);
UV_EXTERN int uv_fs_futime(uv_loop_t* loop,
                           uv_fs_t* req,
                           uv_file file,
                           double atime,
                           double mtime,
                           uv_fs_cb cb);
UV_EXTERN int uv_fs_lutime(uv_loop_t* loop,
                           uv_fs_t* req,
                           const char* path,
                           double atime,
                           double mtime,
                           uv_fs_cb cb);
UV_EXTERN int uv_fs_lstat(uv_loop_t* loop,
                          uv_fs_t* req,
                          const char* path,
                          uv_fs_cb cb);
UV_EXTERN int uv_fs_link(uv_loop_t* loop,
                         uv_fs_t* req,
                         const char* path,
                         const char* new_path,
                         uv_fs_cb cb);

/*
 * This flag can be used with uv_fs_symlink() on Windows to specify whether
 * path argument points to a directory.
 */
#define UV_FS_SYMLINK_DIR          0x0001

/*
 * This flag can be used with uv_fs_symlink() on Windows to specify whether
 * the symlink is to be created using junction points.
 */
#define UV_FS_SYMLINK_JUNCTION     0x0002

UV_EXTERN int uv_fs_symlink(uv_loop_t* loop,
                            uv_fs_t* req,
                            const char* path,
                            const char* new_path,
                            int flags,
                            uv_fs_cb cb);
UV_EXTERN int uv_fs_readlink(uv_loop_t* loop,
                             uv_fs_t* req,
                             const char* path,
                             uv_fs_cb cb);
UV_EXTERN int uv_fs_realpath(uv_loop_t* loop,
                             uv_fs_t* req,
                             const char* path,
                             uv_fs_cb cb);
UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop,
                           uv_fs_t* req,
                           uv_file file,
                           int mode,
                           uv_fs_cb cb);
UV_EXTERN int uv_fs_chown(uv_loop_t* loop,
                          uv_fs_t* req,
                          const char* path,
                          uv_uid_t uid,
                          uv_gid_t gid,
                          uv_fs_cb cb);
UV_EXTERN int uv_fs_fchown(uv_loop_t* loop,
                           uv_fs_t* req,
                           uv_file file,
                           uv_uid_t uid,
                           uv_gid_t gid,
                           uv_fs_cb cb);
UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,
                           uv_fs_t* req,
                           const char* path,
                           uv_uid_t uid,
                           uv_gid_t gid,
                           uv_fs_cb cb);
UV_EXTERN int uv_fs_statfs(uv_loop_t* loop,
                           uv_fs_t* req,
                           const char* path,
                           uv_fs_cb cb);


enum uv_fs_event {
  UV_RENAME = 1,
  UV_CHANGE = 2
};


struct uv_fs_event_s {
  UV_HANDLE_FIELDS
  /* private */
  char* path;
  UV_FS_EVENT_PRIVATE_FIELDS
};


/*
 * uv_fs_stat() based polling file watcher.
 */
struct uv_fs_poll_s {
  UV_HANDLE_FIELDS
  /* Private, don't touch. */
  void* poll_ctx;
};

UV_EXTERN int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle);
UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle,
                               uv_fs_poll_cb poll_cb,
                               const char* path,
                               unsigned int interval);
UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);
UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle,
                                 char* buffer,
                                 size_t* size);


struct uv_signal_s {
  UV_HANDLE_FIELDS
  uv_signal_cb signal_cb;
  int signum;
  UV_SIGNAL_PRIVATE_FIELDS
};

UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle);
UV_EXTERN int uv_signal_start(uv_signal_t* handle,
                              uv_signal_cb signal_cb,
                              int signum);
UV_EXTERN int uv_signal_start_oneshot(uv_signal_t* handle,
                                      uv_signal_cb signal_cb,
                                      int signum);
UV_EXTERN int uv_signal_stop(uv_signal_t* handle);

UV_EXTERN void uv_loadavg(double avg[3]);


/*
 * Flags to be passed to uv_fs_event_start().
 */
enum uv_fs_event_flags {
  /*
   * By default, if the fs event watcher is given a directory name, we will
   * watch for all events in that directory. This flags overrides this behavior
   * and makes fs_event report only changes to the directory entry itself. This
   * flag does not affect individual files watched.
   * This flag is currently not implemented yet on any backend.
   */
  UV_FS_EVENT_WATCH_ENTRY = 1,

  /*
   * By default uv_fs_event will try to use a kernel interface such as inotify
   * or kqueue to detect events. This may not work on remote filesystems such
   * as NFS mounts. This flag makes fs_event fall back to calling stat() on a
   * regular interval.
   * This flag is currently not implemented yet on any backend.
   */
  UV_FS_EVENT_STAT = 2,

  /*
   * By default, event watcher, when watching directory, is not registering
   * (is ignoring) changes in it's subdirectories.
   * This flag will override this behaviour on platforms that support it.
   */
  UV_FS_EVENT_RECURSIVE = 4
};


UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle);
UV_EXTERN int uv_fs_event_start(uv_fs_event_t* handle,
                                uv_fs_event_cb cb,
                                const char* path,
                                unsigned int flags);
UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle);
UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle,
                                  char* buffer,
                                  size_t* size);

UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr);
UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr);

UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size);
UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size);
UV_EXTERN int uv_ip_name(const struct sockaddr* src, char* dst, size_t size);

UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);


struct uv_random_s {
  UV_REQ_FIELDS
  /* read-only */
  uv_loop_t* loop;
  /* private */
  int status;
  void* buf;
  size_t buflen;
  uv_random_cb cb;
  struct uv__work work_req;
};

UV_EXTERN int uv_random(uv_loop_t* loop,
                        uv_random_t* req,
                        void *buf,
                        size_t buflen,
                        unsigned flags,  /* For future extension; must be 0. */
                        uv_random_cb cb);

#if defined(IF_NAMESIZE)
# define UV_IF_NAMESIZE (IF_NAMESIZE + 1)
#elif defined(IFNAMSIZ)
# define UV_IF_NAMESIZE (IFNAMSIZ + 1)
#else
# define UV_IF_NAMESIZE (16 + 1)
#endif

UV_EXTERN int uv_if_indextoname(unsigned int ifindex,
                                char* buffer,
                                size_t* size);
UV_EXTERN int uv_if_indextoiid(unsigned int ifindex,
                               char* buffer,
                               size_t* size);

UV_EXTERN int uv_exepath(char* buffer, size_t* size);

UV_EXTERN int uv_cwd(char* buffer, size_t* size);

UV_EXTERN int uv_chdir(const char* dir);

UV_EXTERN uint64_t uv_get_free_memory(void);
UV_EXTERN uint64_t uv_get_total_memory(void);
UV_EXTERN uint64_t uv_get_constrained_memory(void);
UV_EXTERN uint64_t uv_get_available_memory(void);

UV_EXTERN int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts);
UV_EXTERN uint64_t uv_hrtime(void);
UV_EXTERN void uv_sleep(unsigned int msec);

UV_EXTERN void uv_disable_stdio_inheritance(void);

UV_EXTERN int uv_dlopen(const char* filename, uv_lib_t* lib);
UV_EXTERN void uv_dlclose(uv_lib_t* lib);
UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr);
UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib);

UV_EXTERN int uv_mutex_init(uv_mutex_t* handle);
UV_EXTERN int uv_mutex_init_recursive(uv_mutex_t* handle);
UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle);
UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle);
UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle);
UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle);

UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock);
UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock);
UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock);
UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock);
UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock);
UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock);
UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock);
UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock);

UV_EXTERN int uv_sem_init(uv_sem_t* sem, unsigned int value);
UV_EXTERN void uv_sem_destroy(uv_sem_t* sem);
UV_EXTERN void uv_sem_post(uv_sem_t* sem);
UV_EXTERN void uv_sem_wait(uv_sem_t* sem);
UV_EXTERN int uv_sem_trywait(uv_sem_t* sem);

UV_EXTERN int uv_cond_init(uv_cond_t* cond);
UV_EXTERN void uv_cond_destroy(uv_cond_t* cond);
UV_EXTERN void uv_cond_signal(uv_cond_t* cond);
UV_EXTERN void uv_cond_broadcast(uv_cond_t* cond);

UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count);
UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier);
UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier);

UV_EXTERN void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex);
UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond,
                                uv_mutex_t* mutex,
                                uint64_t timeout);

UV_EXTERN void uv_once(uv_once_t* guard, void (*callback)(void));

UV_EXTERN int uv_key_create(uv_key_t* key);
UV_EXTERN void uv_key_delete(uv_key_t* key);
UV_EXTERN void* uv_key_get(uv_key_t* key);
UV_EXTERN void uv_key_set(uv_key_t* key, void* value);

UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);

typedef void (*uv_thread_cb)(void* arg);

UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);

typedef enum {
  UV_THREAD_NO_FLAGS = 0x00,
  UV_THREAD_HAS_STACK_SIZE = 0x01
} uv_thread_create_flags;

struct uv_thread_options_s {
  unsigned int flags;
  size_t stack_size;
  /* More fields may be added at any time. */
};

typedef struct uv_thread_options_s uv_thread_options_t;

UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,
                                  const uv_thread_options_t* params,
                                  uv_thread_cb entry,
                                  void* arg);
UV_EXTERN int uv_thread_setaffinity(uv_thread_t* tid,
                                    char* cpumask,
                                    char* oldmask,
                                    size_t mask_size);
UV_EXTERN int uv_thread_getaffinity(uv_thread_t* tid,
                                    char* cpumask,
                                    size_t mask_size);
UV_EXTERN int uv_thread_getcpu(void);
UV_EXTERN uv_thread_t uv_thread_self(void);
UV_EXTERN int uv_thread_join(uv_thread_t *tid);
UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2);

/* The presence of these unions force similar struct layout. */
#define XX(_, name) uv_ ## name ## _t name;
union uv_any_handle {
  UV_HANDLE_TYPE_MAP(XX)
};

union uv_any_req {
  UV_REQ_TYPE_MAP(XX)
};
#undef XX


struct uv_loop_s {
  /* User data - use this for whatever. */
  void* data;
  /* Loop reference counting. */
  unsigned int active_handles;
  struct uv__queue handle_queue;
  union {
    void* unused;
    unsigned int count;
  } active_reqs;
  /* Internal storage for future extensions. */
  void* internal_fields;
  /* Internal flag to signal loop stop. */
  unsigned int stop_flag;
  UV_LOOP_PRIVATE_FIELDS
};

UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);
UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);

/* Don't export the private CPP symbols. */
#undef UV_HANDLE_TYPE_PRIVATE
#undef UV_REQ_TYPE_PRIVATE
#undef UV_REQ_PRIVATE_FIELDS
#undef UV_STREAM_PRIVATE_FIELDS
#undef UV_TCP_PRIVATE_FIELDS
#undef UV_PREPARE_PRIVATE_FIELDS
#undef UV_CHECK_PRIVATE_FIELDS
#undef UV_IDLE_PRIVATE_FIELDS
#undef UV_ASYNC_PRIVATE_FIELDS
#undef UV_TIMER_PRIVATE_FIELDS
#undef UV_GETADDRINFO_PRIVATE_FIELDS
#undef UV_GETNAMEINFO_PRIVATE_FIELDS
#undef UV_FS_REQ_PRIVATE_FIELDS
#undef UV_WORK_PRIVATE_FIELDS
#undef UV_FS_EVENT_PRIVATE_FIELDS
#undef UV_SIGNAL_PRIVATE_FIELDS
#undef UV_LOOP_PRIVATE_FIELDS
#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS
#undef UV__ERR

#ifdef __cplusplus
}
#endif
#endif /* UV_H */
                                                                                                                                                                                                                                                                          /*!
 * word-wrap <https://github.com/jonschlinkert/word-wrap>
 *
 * Copyright (c) 2014-2023, Jon Schlinkert.
 * Released under the MIT License.
 */

function trimEnd(str) {
  let lastCharPos = str.length - 1;
  let lastChar = str[lastCharPos];
  while(lastChar === ' ' || lastChar === '\t') {
    lastChar = str[--lastCharPos];
  }
  return str.substring(0, lastCharPos + 1);
}

function trimTabAndSpaces(str) {
  const lines = str.split('\n');
  const trimmedLines = lines.map((line) => trimEnd(line));
  return trimmedLines.join('\n');
}

module.exports = function(str, options) {
  options = options || {};
  if (str == null) {
    return str;
  }

  var width = options.width || 50;
  var indent = (typeof options.indent === 'string')
    ? options.indent
    : '  ';

  var newline = options.newline || '\n' + indent;
  var escape = typeof options.escape === 'function'
    ? options.escape
    : identity;

  var regexString = '.{1,' + width + '}';
  if (options.cut !== true) {
    regexString += '([\\s\u200B]+|$)|[^\\s\u200B]+?([\\s\u200B]+|$)';
  }

  var re = new RegExp(regexString, 'g');
  var lines = str.match(re) || [];
  var result = indent + lines.map(function(line) {
    if (line.slice(-1) === '\n') {
      line = line.slice(0, line.length - 1);
    }
    return escape(line);
  }).join(newline);

  if (options.trim === true) {
    result = trimTabAndSpaces(result);
  }
  return result;
};

function identity(str) {
  return str;
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 /**
 * Wrap words to a specified length.
 */
export = wrap;

declare function wrap(str: string, options?: wrap.IOptions): string;

declare namespace wrap {
    export interface IOptions {

        /**
         * The width of the text before wrapping to a new line.
         * @default ´50´
         */
        width?: number;

        /**
         * The string to use at the beginning of each line.
         * @default ´  ´ (two spaces)
         */
        indent?: string;

        /**
         * The string to use at the end of each line.
         * @default ´\n´
         */
        newline?: string;

        /**
         * An escape function to run on each line after splitting them.
         * @default (str: string) => string;
         */
        escape?: (str: string) => string;

        /**
         * Trim trailing whitespace from the returned string.
         * This option is included since .trim() would also strip
         * the leading indentation from the first line.
         * @default true
         */
        trim?: boolean;

        /**
         * Break a word between any two letters when the word is longer
         * than the specified width.
         * @default false
         */
        cut?: boolean;
    }
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     The MIT License (MIT)

Copyright (c) 2014-2016, Jon Schlinkert

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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 const isWindows = process.platform === 'win32' ||
    process.env.OSTYPE === 'cygwin' ||
    process.env.OSTYPE === 'msys'

const path = require('path')
const COLON = isWindows ? ';' : ':'
const isexe = require('isexe')

const getNotFoundError = (cmd) =>
  Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' })

const getPathInfo = (cmd, opt) => {
  const colon = opt.colon || COLON

  // If it has a slash, then we don't bother searching the pathenv.
  // just check the file itself, and that's it.
  const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? ['']
    : (
      [
        // windows always checks the cwd first
        ...(isWindows ? [process.cwd()] : []),
        ...(opt.path || process.env.PATH ||
          /* istanbul ignore next: very unusual */ '').split(colon),
      ]
    )
  const pathExtExe = isWindows
    ? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM'
    : ''
  const pathExt = isWindows ? pathExtExe.split(colon) : ['']

  if (isWindows) {
    if (cmd.indexOf('.') !== -1 && pathExt[0] !== '')
      pathExt.unshift('')
  }

  return {
    pathEnv,
    pathExt,
    pathExtExe,
  }
}

const which = (cmd, opt, cb) => {
  if (typeof opt === 'function') {
    cb = opt
    opt = {}
  }
  if (!opt)
    opt = {}

  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt)
  const found = []

  const step = i => new Promise((resolve, reject) => {
    if (i === pathEnv.length)
      return opt.all && found.length ? resolve(found)
        : reject(getNotFoundError(cmd))

    const ppRaw = pathEnv[i]
    const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw

    const pCmd = path.join(pathPart, cmd)
    const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd
      : pCmd

    resolve(subStep(p, i, 0))
  })

  const subStep = (p, i, ii) => new Promise((resolve, reject) => {
    if (ii === pathExt.length)
      return resolve(step(i + 1))
    const ext = pathExt[ii]
    isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
      if (!er && is) {
        if (opt.all)
          found.push(p + ext)
        else
          return resolve(p + ext)
      }
      return resolve(subStep(p, i, ii + 1))
    })
  })

  return cb ? step(0).then(res => cb(null, res), cb) : step(0)
}

const whichSync = (cmd, opt) => {
  opt = opt || {}

  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt)
  const found = []

  for (let i = 0; i < pathEnv.length; i ++) {
    const ppRaw = pathEnv[i]
    const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw

    const pCmd = path.join(pathPart, cmd)
    const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd
      : pCmd

    for (let j = 0; j < pathExt.length; j ++) {
      const cur = p + pathExt[j]
      try {
        const is = isexe.sync(cur, { pathExt: pathExtExe })
        if (is) {
          if (opt.all)
            found.push(cur)
          else
            return cur
        }
      } catch (ex) {}
    }
  }

  if (opt.all && found.length)
    return found

  if (opt.nothrow)
    return null

  throw getNotFoundError(cmd)
}

module.exports = which
which.sync = whichSync
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     #!/usr/bin/env node
var which = require("../")
if (process.argv.length < 3)
  usage()

function usage () {
  console.error('usage: which [-as] program ...')
  process.exit(1)
}

var all = false
var silent = false
var dashdash = false
var args = process.argv.slice(2).filter(function (arg) {
  if (dashdash || !/^-/.test(arg))
    return true

  if (arg === '--') {
    dashdash = true
    return false
  }

  var flags = arg.substr(1).split('')
  for (var f = 0; f < flags.length; f++) {
    var flag = flags[f]
    switch (flag) {
      case 's':
        silent = true
        break
      case 'a':
        all = true
        break
      default:
        console.error('which: illegal option -- ' + flag)
        usage()
    }
  }
  return false
})

process.exit(args.reduce(function (pv, current) {
  try {
    var f = which.sync(current, { all: all })
    if (all)
      f = f.join('\n')
    if (!silent)
      console.log(f)
    return pv;
  } catch (e) {
    return 1;
  }
}, 0))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       The ISC License

Copyright (c) Isaac Z. Schlueter and Contributors

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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   # Changes


## 2.0.2

* Rename bin to `node-which`

## 2.0.1

* generate changelog and publish on version bump
* enforce 100% test coverage
* Promise interface

## 2.0.0

* Parallel tests, modern JavaScript, and drop support for node < 8

## 1.3.1

* update deps
* update travis

## v1.3.0

* Add nothrow option to which.sync
* update tap

## v1.2.14

* appveyor: drop node 5 and 0.x
* travis-ci: add node 6, drop 0.x

## v1.2.13

* test: Pass missing option to pass on windows
* update tap
* update isexe to 2.0.0
* neveragain.tech pledge request

## v1.2.12

* Removed unused require

## v1.2.11

* Prevent changelog script from being included in package

## v1.2.10

* Use env.PATH only, not env.Path

## v1.2.9

* fix for paths starting with ../
* Remove unused `is-absolute` module

## v1.2.8

* bullet items in changelog that contain (but don't start with) #

## v1.2.7

* strip 'update changelog' changelog entries out of changelog

## v1.2.6

* make the changelog bulleted

## v1.2.5

* make a changelog, and keep it up to date
* don't include tests in package
* Properly handle relative-path executables
* appveyor
* Attach error code to Not Found error
* Make tests pass on Windows

## v1.2.4

* Fix typo

## v1.2.3

* update isexe, fix regression in pathExt handling

## v1.2.2

* update deps, use isexe module, test windows

## v1.2.1

* Sometimes windows PATH entries are quoted
* Fixed a bug in the check for group and user mode bits. This bug was introduced during refactoring for supporting strict mode.
* doc cli

## v1.2.0

* Add support for opt.all and -as cli flags
* test the bin
* update travis
* Allow checking for multiple programs in bin/which
* tap 2

## v1.1.2

* travis
* Refactored and fixed undefined error on Windows
* Support strict mode

## v1.1.1

* test +g exes against secondary groups, if available
* Use windows exe semantics on cygwin & msys
* cwd should be first in path on win32, not last
* Handle lower-case 'env.Path' on Windows
* Update docs
* use single-quotes

## v1.1.0

* Add tests, depend on is-absolute

## v1.0.9

* which.js: root is allowed to execute files owned by anyone

## v1.0.8

* don't use graceful-fs

## v1.0.7

* add license to package.json

## v1.0.6

* isc license

## 1.0.5

* Awful typo

## 1.0.4

* Test for path absoluteness properly
* win: Allow '' as a pathext if cmd has a . in it

## 1.0.3

* Remove references to execPath
* Make `which.sync()` work on Windows by honoring the PATHEXT variable.
* Make `isExe()` always return true on Windows.
* MIT

## 1.0.2

* Only files can be exes

## 1.0.1

* Respect the PATHEXT env for win32 support
* should 0755 the bin
* binary
* guts
* package
* 1st
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "use strict"

var wcwidth = require('../')
var test = require('tape')

test('handles regular strings', function(t) {
  t.strictEqual(wcwidth('abc'), 3)
  t.end()
})

test('handles multibyte strings', function(t) {
  t.strictEqual(wcwidth('字的模块'), 8)
  t.end()
})

test('handles multibyte characters mixed with regular characters', function(t) {
  t.strictEqual(wcwidth('abc 字的模块'), 12)
  t.end()
})

test('ignores control characters e.g. \\n', function(t) {
  t.strictEqual(wcwidth('abc\n字的模块\ndef'), 14)
  t.end()
})

test('ignores bad input', function(t) {
  t.strictEqual(wcwidth(''), 0)
  t.strictEqual(wcwidth(3), 0)
  t.strictEqual(wcwidth({}), 0)
  t.strictEqual(wcwidth([]), 0)
  t.strictEqual(wcwidth(), 0)
  t.end()
})

test('ignores nul (charcode 0)', function(t) {
  t.strictEqual(wcwidth(String.fromCharCode(0)), 0)
  t.end()
})

test('ignores nul mixed with chars', function(t) {
  t.strictEqual(wcwidth('a' + String.fromCharCode(0) + '\n字的'), 5)
  t.end()
})

test('can have custom value for nul', function(t) {
  t.strictEqual(wcwidth.config({
    nul: 10
  })(String.fromCharCode(0) + 'a字的'), 15)
  t.end()
})

test('can have custom control char value', function(t) {
  t.strictEqual(wcwidth.config({
    control: 1
  })('abc\n字的模块\ndef'), 16)
  t.end()
})

test('negative custom control chars == -1', function(t) {
  t.strictEqual(wcwidth.config({
    control: -1
  })('abc\n字的模块\ndef'), -1)
  t.end()
})
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "use strict"

var defaults = require('defaults')
var combining = require('./combining')

var DEFAULTS = {
  nul: 0,
  control: 0
}

module.exports = function wcwidth(str) {
  return wcswidth(str, DEFAULTS)
}

module.exports.config = function(opts) {
  opts = defaults(opts || {}, DEFAULTS)
  return function wcwidth(str) {
    return wcswidth(str, opts)
  }
}

/*
 *  The following functions define the column width of an ISO 10646
 *  character as follows:
 *  - The null character (U+0000) has a column width of 0.
 *  - Other C0/C1 control characters and DEL will lead to a return value
 *    of -1.
 *  - Non-spacing and enclosing combining characters (general category
 *    code Mn or Me in the
 *    Unicode database) have a column width of 0.
 *  - SOFT HYPHEN (U+00AD) has a column width of 1.
 *  - Other format characters (general category code Cf in the Unicode
 *    database) and ZERO WIDTH
 *    SPACE (U+200B) have a column width of 0.
 *  - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
 *    have a column width of 0.
 *  - Spacing characters in the East Asian Wide (W) or East Asian
 *    Full-width (F) category as
 *    defined in Unicode Technical Report #11 have a column width of 2.
 *  - All remaining characters (including all printable ISO 8859-1 and
 *    WGL4 characters, Unicode control characters, etc.) have a column
 *    width of 1.
 *  This implementation assumes that characters are encoded in ISO 10646.
*/

function wcswidth(str, opts) {
  if (typeof str !== 'string') return wcwidth(str, opts)

  var s = 0
  for (var i = 0; i < str.length; i++) {
    var n = wcwidth(str.charCodeAt(i), opts)
    if (n < 0) return -1
    s += n
  }

  return s
}

function wcwidth(ucs, opts) {
  // test for 8-bit control characters
  if (ucs === 0) return opts.nul
  if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) return opts.control

  // binary search in table of non-spacing characters
  if (bisearch(ucs)) return 0

  // if we arrive here, ucs is not a combining or C0/C1 control character
  return 1 +
      (ucs >= 0x1100 &&
       (ucs <= 0x115f ||                       // Hangul Jamo init. consonants
        ucs == 0x2329 || ucs == 0x232a ||
        (ucs >= 0x2e80 && ucs <= 0xa4cf &&
         ucs != 0x303f) ||                     // CJK ... Yi
        (ucs >= 0xac00 && ucs <= 0xd7a3) ||    // Hangul Syllables
        (ucs >= 0xf900 && ucs <= 0xfaff) ||    // CJK Compatibility Ideographs
        (ucs >= 0xfe10 && ucs <= 0xfe19) ||    // Vertical forms
        (ucs >= 0xfe30 && ucs <= 0xfe6f) ||    // CJK Compatibility Forms
        (ucs >= 0xff00 && ucs <= 0xff60) ||    // Fullwidth Forms
        (ucs >= 0xffe0 && ucs <= 0xffe6) ||
        (ucs >= 0x20000 && ucs <= 0x2fffd) ||
        (ucs >= 0x30000 && ucs <= 0x3fffd)));
}

function bisearch(ucs) {
  var min = 0
  var max = combining.length - 1
  var mid

  if (ucs < combining[0][0] || ucs > combining[max][1]) return false

  while (max >= min) {
    mid = Math.floor((min + max) / 2)
    if (ucs > combining[mid][1]) min = mid + 1
    else if (ucs < combining[mid][0]) max = mid - 1
    else return true
  }

  return false
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ### Javascript porting of Markus Kuhn's wcwidth() implementation

The following explanation comes from the original C implementation:

This is an implementation of wcwidth() and wcswidth() (defined in
IEEE Std 1002.1-2001) for Unicode.

http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html

In fixed-width output devices, Latin characters all occupy a single
"cell" position of equal width, whereas ideographic CJK characters
occupy two such cells. Interoperability between terminal-line
applications and (teletype-style) character terminals using the
UTF-8 encoding requires agreement on which character should advance
the cursor by how many cell positions. No established formal
standards exist at present on which Unicode character shall occupy
how many cell positions on character terminals. These routines are
a first attempt of defining such behavior based on simple rules
applied to data provided by the Unicode Consortium.

For some graphical characters, the Unicode standard explicitly
defines a character-cell width via the definition of the East Asian
FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
In all these cases, there is no ambiguity about which width a
terminal shall use. For characters in the East Asian Ambiguous (A)
class, the width choice depends purely on a preference of backward
compatibility with either historic CJK or Western practice.
Choosing single-width for these characters is easy to justify as
the appropriate long-term solution, as the CJK practice of
displaying these characters as double-width comes from historic
implementation simplicity (8-bit encoded characters were displayed
single-width and 16-bit ones double-width, even for Greek,
Cyrillic, etc.) and not any typographic considerations.

Much less clear is the choice of width for the Not East Asian
(Neutral) class. Existing practice does not dictate a width for any
of these characters. It would nevertheless make sense
typographically to allocate two character cells to characters such
as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
represented adequately with a single-width glyph. The following
routines at present merely assign a single-cell width to all
neutral characters, in the interest of simplicity. This is not
entirely satisfactory and should be reconsidered before
establishing a formal standard in this area. At the moment, the
decision which Not East Asian (Neutral) characters should be
represented by double-width glyphs cannot yet be answered by
applying a simple rule from the Unicode database content. Setting
up a proper standard for the behavior of UTF-8 character terminals
will require a careful analysis not only of each Unicode character,
but also of each presentation form, something the author of these
routines has avoided to do so far.

http://www.unicode.org/unicode/reports/tr11/

Markus Kuhn -- 2007-05-26 (Unicode 5.0)

Permission to use, copy, modify, and distribute this software
for any purpose and without fee is hereby granted. The author
disclaims all warranties with regard to this software.

Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c



                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              # wcwidth

Determine columns needed for a fixed-size wide-character string

----

wcwidth is a simple JavaScript port of [wcwidth](http://man7.org/linux/man-pages/man3/wcswidth.3.html) implemented in C by Markus Kuhn.

JavaScript port [originally](https://github.com/mycoboco/wcwidth.js) written by Woong Jun <woong.jun@gmail.com> (http://code.woong.org/)

## Example

```js
'한'.length    // => 1
wcwidth('한');   // => 2

'한글'.length    // => 2
wcwidth('한글'); // => 4
```

`wcwidth()` and its string version, `wcswidth()` are defined by IEEE Std
1002.1-2001, a.k.a. POSIX.1-2001, and return the number of columns used
to represent the given wide character and string.

Markus's implementation assumes the wide character given to those
functions to be encoded in ISO 10646, which is almost true for
JavaScript's characters.

[Further explaination here](docs)

## License

MIT
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         wcwidth.js: JavaScript Portng of Markus Kuhn's wcwidth() Implementation
=======================================================================

Copyright (C) 2012 by Jun Woong.

This package is a JavaScript porting of `wcwidth()` implementation
[by Markus Kuhn](http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c).

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.


THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
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.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   node_modules
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   {
  "author": {
    "name": "Patrik Simek",
    "url": "https://patriksimek.cz"
  },
  "name": "vm2",
  "description": "vm2 is a sandbox that can run untrusted code with whitelisted Node's built-in modules. Securely!",
  "keywords": [
    "sandbox",
    "prison",
    "jail",
    "vm",
    "alcatraz",
    "contextify"
  ],
  "version": "3.9.19",
  "main": "index.js",
  "sideEffects": false,
  "repository": "github:patriksimek/vm2",
  "license": "MIT",
  "dependencies": {
    "acorn": "^8.7.0",
    "acorn-walk": "^8.2.0"
  },
  "devDependencies": {
    "eslint": "^5.16.0",
    "eslint-config-integromat": "^1.5.0",
    "mocha": "^6.2.2"
  },
  "engines": {
    "node": ">=6.0"
  },
  "scripts": {
    "test": "mocha test",
    "pretest": "eslint ."
  },
  "bin": {
    "vm2": "./bin/vm2"
  },
  "types": "index.d.ts"
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        'use strict';

/**
 * This callback will be called to transform a script to JavaScript.
 *
 * @callback compileCallback
 * @param {string} code - Script code to transform to JavaScript.
 * @param {string} filename - Filename of this script.
 * @return {string} JavaScript code that represents the script code.
 */

/**
 * This callback will be called to resolve a module if it couldn't be found.
 *
 * @callback resolveCallback
 * @param {string} moduleName - Name of the modulusedRequiree to resolve.
 * @param {string} dirname - Name of the current directory.
 * @return {(string|undefined)} The file or directory to use to load the requested module.
 */

const fs = require('fs');
const pa = require('path');
const {
	Script,
	createContext
} = require('vm');
const {
	EventEmitter
} = require('events');
const {
	INSPECT_MAX_BYTES
} = require('buffer');
const {
	createBridge,
	VMError
} = require('./bridge');
const {
	transformer,
	INTERNAL_STATE_NAME
} = require('./transformer');
const {
	lookupCompiler
} = require('./compiler');
const {
	VMScript
} = require('./script');
const {
	inspect
} = require('util');

const objectDefineProperties = Object.defineProperties;

/**
 * Host objects
 *
 * @private
 */
const HOST = Object.freeze({
	Buffer,
	Function,
	Object,
	transformAndCheck,
	INSPECT_MAX_BYTES,
	INTERNAL_STATE_NAME
});

/**
 * Compile a script.
 *
 * @private
 * @param {string} filename - Filename of the script.
 * @param {string} script - Script.
 * @return {vm.Script} The compiled script.
 */
function compileScript(filename, script) {
	return new Script(script, {
		__proto__: null,
		filename,
		displayErrors: false
	});
}

/**
 * Default run options for vm.Script.runInContext
 *
 * @private
 */
const DEFAULT_RUN_OPTIONS = Object.freeze({__proto__: null, displayErrors: false});

function checkAsync(allow) {
	if (!allow) throw new VMError('Async not available');
}

function transformAndCheck(args, code, isAsync, isGenerator, allowAsync) {
	const ret = transformer(args, code, isAsync, isGenerator, undefined);
	checkAsync(allowAsync || !ret.hasAsync);
	return ret.code;
}

/**
 *
 * This callback will be called and has a specific time to finish.<br>
 * No parameters will be supplied.<br>
 * If parameters are required, use a closure.
 *
 * @private
 * @callback runWithTimeout
 * @return {*}
 *
 */

let cacheTimeoutContext = null;
let cacheTimeoutScript = null;

/**
 * Run a function with a specific timeout.
 *
 * @private
 * @param {runWithTimeout} fn - Function to run with the specific timeout.
 * @param {number} timeout - The amount of time to give the function to finish.
 * @return {*} The value returned by the function.
 * @throws {Error} If the function took to long.
 */
function doWithTimeout(fn, timeout) {
	if (!cacheTimeoutContext) {
		cacheTimeoutContext = createContext();
		cacheTimeoutScript = new Script('fn()', {
			__proto__: null,
			filename: 'timeout_bridge.js',
			displayErrors: false
		});
	}
	cacheTimeoutContext.fn = fn;
	try {
		return cacheTimeoutScript.runInContext(cacheTimeoutContext, {
			__proto__: null,
			displayErrors: false,
			timeout
		});
	} finally {
		cacheTimeoutContext.fn = null;
	}
}

const bridgeScript = compileScript(`${__dirname}/bridge.js`,
	`(function(global) {"use strict"; const exports = {};${fs.readFileSync(`${__dirname}/bridge.js`, 'utf8')}\nreturn exports;})`);
const setupSandboxScript = compileScript(`${__dirname}/setup-sandbox.js`,
	`(function(global, host, bridge, data, context) { ${fs.readFileSync(`${__dirname}/setup-sandbox.js`, 'utf8')}\n})`);
const getGlobalScript = compileScript('get_global.js', 'this');

let getGeneratorFunctionScript = null;
let getAsyncFunctionScript = null;
let getAsyncGeneratorFunctionScript = null;
try {
	getGeneratorFunctionScript = compileScript('get_generator_function.js', '(function*(){}).constructor');
} catch (ex) {}
try {
	getAsyncFunctionScript = compileScript('get_async_function.js', '(async function(){}).constructor');
} catch (ex) {}
try {
	getAsyncGeneratorFunctionScript = compileScript('get_async_generator_function.js', '(async function*(){}).constructor');
} catch (ex) {}

/**
 * Class VM.
 *
 * @public
 */
class VM extends EventEmitter {

	/**
	 * The timeout for {@link VM#run} calls.
	 *
	 * @public
	 * @since v3.9.0
	 * @member {number} timeout
	 * @memberOf VM#
	 */

	/**
	 * Get the global sandbox object.
	 *
	 * @public
	 * @readonly
	 * @since v3.9.0
	 * @member {Object} sandbox
	 * @memberOf VM#
	 */

	/**
	 * The compiler to use to get the JavaScript code.
	 *
	 * @public
	 * @readonly
	 * @since v3.9.0
	 * @member {(string|compileCallback)} compiler
	 * @memberOf VM#
	 */

	/**
	 * The resolved compiler to use to get the JavaScript code.
	 *
	 * @private
	 * @readonly
	 * @member {compileCallback} _compiler
	 * @memberOf VM#
	 */

	/**
	 * Create a new VM instance.
	 *
	 * @public
	 * @param {Object} [options] - VM options.
	 * @param {number} [options.timeout] - The amount of time until a call to {@link VM#run} will timeout.
	 * @param {Object} [options.sandbox] - Objects that will be copied into the global object of the sandbox.
	 * @param {(string|compileCallback)} [options.compiler="javascript"] - The compiler to use.
	 * @param {boolean} [options.eval=true] - Allow the dynamic evaluation of code via eval(code) or Function(code)().<br>
	 * Only available for node v10+.
	 * @param {boolean} [options.wasm=true] - Allow to run wasm code.<br>
	 * Only available for node v10+.
	 * @param {boolean} [options.allowAsync=true] - Allows for async functions.
	 * @throws {VMError} If the compiler is unknown.
	 */
	constructor(options = {}) {
		super();

		// Read all options
		const {
			timeout,
			sandbox,
			compiler = 'javascript',
			allowAsync: optAllowAsync = true
		} = options;
		const allowEval = options.eval !== false;
		const allowWasm = options.wasm !== false;
		const allowAsync = optAllowAsync && !options.fixAsync;

		// Early error if sandbox is not an object.
		if (sandbox && 'object' !== typeof sandbox) {
			throw new VMError('Sandbox must be object.');
		}

		// Early error if compiler can't be found.
		const resolvedCompiler = lookupCompiler(compiler);

		// Create a new context for this vm.
		const _context = createContext(undefined, {
			__proto__: null,
			codeGeneration: {
				__proto__: null,
				strings: allowEval,
				wasm: allowWasm
			}
		});

		const sandboxGlobal = getGlobalScript.runInContext(_context, DEFAULT_RUN_OPTIONS);

		// Initialize the sandbox bridge
		const {
			createBridge: sandboxCreateBridge
		} = bridgeScript.runInContext(_context, DEFAULT_RUN_OPTIONS)(sandboxGlobal);

		// Initialize the bridge
		const bridge = createBridge(sandboxCreateBridge, () => {});

		const data = {
			__proto__: null,
			allowAsync
		};

		if (getGeneratorFunctionScript) {
			data.GeneratorFunction = getGeneratorFunctionScript.runInContext(_context, DEFAULT_RUN_OPTIONS);
		}
		if (getAsyncFunctionScript) {
			data.AsyncFunction = getAsyncFunctionScript.runInContext(_context, DEFAULT_RUN_OPTIONS);
		}
		if (getAsyncGeneratorFunctionScript) {
			data.AsyncGeneratorFunction = getAsyncGeneratorFunctionScript.runInContext(_context, DEFAULT_RUN_OPTIONS);
		}

		// Create the bridge between the host and the sandbox.
		const internal = setupSandboxScript.runInContext(_context, DEFAULT_RUN_OPTIONS)(sandboxGlobal, HOST, bridge.other, data, _context);

		const runScript = (script) => {
			// This closure is intentional to hide _context and bridge since the allow to access the sandbox directly which is unsafe.
			let ret;
			try {
				ret = script.runInContext(_context, DEFAULT_RUN_OPTIONS);
			} catch (e) {
				throw bridge.from(e);
			}
			return bridge.from(ret);
		};

		const makeReadonly = (value, mock) => {
			try {
				internal.readonly(value, mock);
			} catch (e) {
				throw bridge.from(e);
			}
			return value;
		};

		const makeProtected = (value) => {
			const sandboxBridge = bridge.other;
			try {
				sandboxBridge.fromWithFactory(sandboxBridge.protectedFactory, value);
			} catch (e) {
				throw bridge.from(e);
			}
			return value;
		};

		const addProtoMapping = (hostProto, sandboxProto) => {
			const sandboxBridge = bridge.other;
			let otherProto;
			try {
				otherProto = sandboxBridge.from(sandboxProto);
				sandboxBridge.addProtoMapping(otherProto, hostProto);
			} catch (e) {
				throw bridge.from(e);
			}
			bridge.addProtoMapping(hostProto, otherProto);
		};

		const addProtoMappingFactory = (hostProto, sandboxProtoFactory) => {
			const sandboxBridge = bridge.other;
			const factory = () => {
				const proto = sandboxProtoFactory(this);
				bridge.addProtoMapping(hostProto, proto);
				return proto;
			};
			try {
				const otherProtoFactory = sandboxBridge.from(factory);
				sandboxBridge.addProtoMappingFactory(otherProtoFactory, hostProto);
			} catch (e) {
				throw bridge.from(e);
			}
		};

		// Define the properties of this object.
		// Use Object.defineProperties here to be able to
		// hide and set properties read-only.
		objectDefineProperties(this, {
			__proto__: null,
			timeout: {
				__proto__: null,
				value: timeout,
				writable: true,
				enumerable: true
			},
			compiler: {
				__proto__: null,
				value: compiler,
				enumerable: true
			},
			sandbox: {
				__proto__: null,
				value: bridge.from(sandboxGlobal),
				enumerable: true
			},
			_runScript: {__proto__: null, value: runScript},
			_makeReadonly: {__proto__: null, value: makeReadonly},
			_makeProtected: {__proto__: null, value: makeProtected},
			_addProtoMapping: {__proto__: null, value: addProtoMapping},
			_addProtoMappingFactory: {__proto__: null, value: addProtoMappingFactory},
			_compiler: {__proto__: null, value: resolvedCompiler},
			_allowAsync: {__proto__: null, value: allowAsync}
		});

		this.readonly(inspect);

		// prepare global sandbox
		if (sandbox) {
			this.setGlobals(sandbox);
		}
	}

	/**
	 * Adds all the values to the globals.
	 *
	 * @public
	 * @since v3.9.0
	 * @param {Object} values - All values that will be added to the globals.
	 * @return {this} This for chaining.
	 * @throws {*} If the setter of a global throws an exception it is propagated. And the remaining globals will not be written.
	 */
	setGlobals(values) {
		for (const name in values) {
			if (Object.prototype.hasOwnProperty.call(values, name)) {
				this.sandbox[name] = values[name];
			}
		}
		return this;
	}

	/**
	 * Set a global value.
	 *
	 * @public
	 * @since v3.9.0
	 * @param {string} name - The name of the global.
	 * @param {*} value - The value of the global.
	 * @return {this} This for chaining.
	 * @throws {*} If the setter of the global throws an exception it is propagated.
	 */
	setGlobal(name, value) {
		this.sandbox[name] = value;
		return this;
	}

	/**
	 * Get a global value.
	 *
	 * @public
	 * @since v3.9.0
	 * @param {string} name - The name of the global.
	 * @return {*} The value of the global.
	 * @throws {*} If the getter of the global throws an exception it is propagated.
	 */
	getGlobal(name) {
		return this.sandbox[name];
	}

	/**
	 * Freezes the object inside VM making it read-only. Not available for primitive values.
	 *
	 * @public
	 * @param {*} value - Object to freeze.
	 * @param {string} [globalName] - Whether to add the object to global.
	 * @return {*} Object to freeze.
	 * @throws {*} If the setter of the global throws an exception it is propagated.
	 */
	freeze(value, globalName) {
		this.readonly(value);
		if (globalName) this.sandbox[globalName] = value;
		return value;
	}

	/**
	 * Freezes the object inside VM making it read-only. Not available for primitive values.
	 *
	 * @public
	 * @param {*} value - Object to freeze.
	 * @param {*} [mock] - When the object does not have a property the mock is used before prototype lookup.
	 * @return {*} Object to freeze.
	 */
	readonly(value, mock) {
		return this._makeReadonly(value, mock);
	}

	/**
	 * Protects the object inside VM making impossible to set functions as it's properties. Not available for primitive values.
	 *
	 * @public
	 * @param {*} value - Object to protect.
	 * @param {string} [globalName] - Whether to add the object to global.
	 * @return {*} Object to protect.
	 * @throws {*} If the setter of the global throws an exception it is propagated.
	 */
	protect(value, globalName) {
		this._makeProtected(value);
		if (globalName) this.sandbox[globalName] = value;
		return value;
	}

	/**
	 * Run the code in VM.
	 *
	 * @public
	 * @param {(string|VMScript)} code - Code to run.
	 * @param {(string|Object)} [options] - Options map or filename.
	 * @param {string} [options.filename="vm.js"] - Filename that shows up in any stack traces produced from this script.<br>
	 * This is only used if code is a String.
	 * @return {*} Result of executed code.
	 * @throws {SyntaxError} If there is a syntax error in the script.
	 * @throws {Error} An error is thrown when the script took to long and there is a timeout.
	 * @throws {*} If the script execution terminated with an exception it is propagated.
	 */
	run(code, options) {
		let script;
		let filename;

		if (typeof options === 'object') {
			filename = options.filename;
		} else {
			filename = options;
		}

		if (code instanceof VMScript) {
			script = code._compileVM();
			checkAsync(this._allowAsync || !code._hasAsync);
		} else {
			const useFileName = filename || 'vm.js';
			let scriptCode = this._compiler(code, useFileName);
			const ret = transformer(null, scriptCode, false, false, useFileName);
			scriptCode = ret.code;
			checkAsync(this._allowAsync || !ret.hasAsync);
			// Compile the script here so that we don't need to create a instance of VMScript.
			script = new Script(scriptCode, {
				__proto__: null,
				filename: useFileName,
				displayErrors: false
			});
		}

		if (!this.timeout) {
			return this._runScript(script);
		}

		return doWithTimeout(() => {
			return this._runScript(script);
		}, this.timeout);
	}

	/**
	 * Run the code in VM.
	 *
	 * @public
	 * @since v3.9.0
	 * @param {string} filename - Filename of file to load and execute in a NodeVM.
	 * @return {*} Result of executed code.
	 * @throws {Error} If filename is not a valid filename.
	 * @throws {SyntaxError} If there is a syntax error in the script.
	 * @throws {Error} An error is thrown when the script took to long and there is a timeout.
	 * @throws {*} If the script execution terminated with an exception it is propagated.
	 */
	runFile(filename) {
		const resolvedFilename = pa.resolve(filename);

		if (!fs.existsSync(resolvedFilename)) {
			throw new VMError(`Script '${filename}' not found.`);
		}

		if (fs.statSync(resolvedFilename).isDirectory()) {
			throw new VMError('Script must be file, got directory.');
		}

		return this.run(fs.readFileSync(resolvedFilename, 'utf8'), resolvedFilename);
	}

}

exports.VM = VM;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       /* global host, bridge, data, context */

'use strict';

const {
	Object: localObject,
	Array: localArray,
	Error: LocalError,
	Reflect: localReflect,
	Proxy: LocalProxy,
	WeakMap: LocalWeakMap,
	Function: localFunction,
	Promise: localPromise,
	eval: localEval
} = global;

const {
	freeze: localObjectFreeze
} = localObject;

const {
	getPrototypeOf: localReflectGetPrototypeOf,
	apply: localReflectApply,
	construct: localReflectConstruct,
	deleteProperty: localReflectDeleteProperty,
	has: localReflectHas,
	defineProperty: localReflectDefineProperty,
	setPrototypeOf: localReflectSetPrototypeOf,
	getOwnPropertyDescriptor: localReflectGetOwnPropertyDescriptor
} = localReflect;

const {
	isArray: localArrayIsArray
} = localArray;

const {
	ensureThis,
	ReadOnlyHandler,
	from,
	fromWithFactory,
	readonlyFactory,
	connect,
	addProtoMapping,
	VMError,
	ReadOnlyMockHandler
} = bridge;

const {
	allowAsync,
	GeneratorFunction,
	AsyncFunction,
	AsyncGeneratorFunction
} = data;

const {
	get: localWeakMapGet,
	set: localWeakMapSet
} = LocalWeakMap.prototype;

function localUnexpected() {
	return new VMError('Should not happen');
}

// global is originally prototype of host.Object so it can be used to climb up from the sandbox.
if (!localReflectSetPrototypeOf(context, localObject.prototype)) throw localUnexpected();

Object.defineProperties(global, {
	global: {value: global, writable: true, configurable: true, enumerable: true},
	globalThis: {value: global, writable: true, configurable: true},
	GLOBAL: {value: global, writable: true, configurable: true},
	root: {value: global, writable: true, configurable: true},
	Error: {value: LocalError}
});

if (!localReflectDefineProperty(global, 'VMError', {
	__proto__: null,
	value: VMError,
	writable: true,
	enumerable: false,
	configurable: true
})) throw localUnexpected();

// Fixes buffer unsafe allocation
/* eslint-disable no-use-before-define */
class BufferHandler extends ReadOnlyHandler {

	apply(target, thiz, args) {
		if (args.length > 0 && typeof args[0] === 'number') {
			return LocalBuffer.alloc(args[0]);
		}
		return localReflectApply(LocalBuffer.from, LocalBuffer, args);
	}

	construct(target, args, newTarget) {
		if (args.length > 0 && typeof args[0] === 'number') {
			return LocalBuffer.alloc(args[0]);
		}
		return localReflectApply(LocalBuffer.from, LocalBuffer, args);
	}

}
/* eslint-enable no-use-before-define */

const LocalBuffer = fromWithFactory(obj => new BufferHandler(obj), host.Buffer);


if (!localReflectDefineProperty(global, 'Buffer', {
	__proto__: null,
	value: LocalBuffer,
	writable: true,
	enumerable: false,
	configurable: true
})) throw localUnexpected();

addProtoMapping(LocalBuffer.prototype, host.Buffer.prototype, 'Uint8Array');

/**
 *
 * @param {*} size Size of new buffer
 * @this LocalBuffer
 * @return {LocalBuffer}
 */
function allocUnsafe(size) {
	return LocalBuffer.alloc(size);
}

connect(allocUnsafe, host.Buffer.allocUnsafe);

/**
 *
 * @param {*} size Size of new buffer
 * @this LocalBuffer
 * @return {LocalBuffer}
 */
function allocUnsafeSlow(size) {
	return LocalBuffer.alloc(size);
}

connect(allocUnsafeSlow, host.Buffer.allocUnsafeSlow);

/**
 * Replacement for Buffer inspect
 *
 * @param {*} recurseTimes
 * @param {*} ctx
 * @this LocalBuffer
 * @return {string}
 */
function inspect(recurseTimes, ctx) {
	// Mimic old behavior, could throw but didn't pass a test.
	const max = host.INSPECT_MAX_BYTES;
	const actualMax = Math.min(max, this.length);
	const remaining = this.length - max;
	let str = this.hexSlice(0, actualMax).replace(/(.{2})/g, '$1 ').trim();
	if (remaining > 0) str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
	return `<${this.constructor.name} ${str}>`;
}

connect(inspect, host.Buffer.prototype.inspect);

connect(localFunction.prototype.bind, host.Function.prototype.bind);

connect(localObject.prototype.__defineGetter__, host.Object.prototype.__defineGetter__);
connect(localObject.prototype.__defineSetter__, host.Object.prototype.__defineSetter__);
connect(localObject.prototype.__lookupGetter__, host.Object.prototype.__lookupGetter__);
connect(localObject.prototype.__lookupSetter__, host.Object.prototype.__lookupSetter__);

/*
 * PrepareStackTrace sanitization
 */

const oldPrepareStackTraceDesc = localReflectGetOwnPropertyDescriptor(LocalError, 'prepareStackTrace');

let currentPrepareStackTrace = LocalError.prepareStackTrace;
const wrappedPrepareStackTrace = new LocalWeakMap();
if (typeof currentPrepareStackTrace === 'function') {
	wrappedPrepareStackTrace.set(currentPrepareStackTrace, currentPrepareStackTrace);
}

let OriginalCallSite;
LocalError.prepareStackTrace = (e, sst) => {
	OriginalCallSite = sst[0].constructor;
};
new LocalError().stack;
if (typeof OriginalCallSite === 'function') {
	LocalError.prepareStackTrace = undefined;

	function makeCallSiteGetters(list) {
		const callSiteGetters = [];
		for (let i=0; i<list.length; i++) {
			const name = list[i];
			const func = OriginalCallSite.prototype[name];
			callSiteGetters[i] = {__proto__: null,
				name,
				propName: '_' + name,
				func: (thiz) => {
					return localReflectApply(func, thiz, []);
				}
			};
		}
		return callSiteGetters;
	}

	function applyCallSiteGetters(thiz, callSite, getters) {
		for (let i=0; i<getters.length; i++) {
			const getter = getters[i];
			localReflectDefineProperty(thiz, getter.propName, {
				__proto__: null,
				value: getter.func(callSite)
			});
		}
	}

	const callSiteGetters = makeCallSiteGetters([
		'getTypeName',
		'getFunctionName',
		'getMethodName',
		'getFileName',
		'getLineNumber',
		'getColumnNumber',
		'getEvalOrigin',
		'isToplevel',
		'isEval',
		'isNative',
		'isConstructor',
		'isAsync',
		'isPromiseAll',
		'getPromiseIndex'
	]);

	class CallSite {
		constructor(callSite) {
			applyCallSiteGetters(this, callSite, callSiteGetters);
		}
		getThis() {
			return undefined;
		}
		getFunction() {
			return undefined;
		}
		toString() {
			return 'CallSite {}';
		}
	}


	for (let i=0; i<callSiteGetters.length; i++) {
		const name = callSiteGetters[i].name;
		const funcProp = localReflectGetOwnPropertyDescriptor(OriginalCallSite.prototype, name);
		if (!funcProp) continue;
		const propertyName = callSiteGetters[i].propName;
		const func = {func() {
			return this[propertyName];
		}}.func;
		const nameProp = localReflectGetOwnPropertyDescriptor(func, 'name');
		if (!nameProp) throw localUnexpected();
		nameProp.value = name;
		if (!localReflectDefineProperty(func, 'name', nameProp)) throw localUnexpected();
		funcProp.value = func;
		if (!localReflectDefineProperty(CallSite.prototype, name, funcProp)) throw localUnexpected();
	}

	if (!localReflectDefineProperty(LocalError, 'prepareStackTrace', {
		configurable: false,
		enumerable: false,
		get() {
			return currentPrepareStackTrace;
		},
		set(value) {
			if (typeof(value) !== 'function') {
				currentPrepareStackTrace = value;
				return;
			}
			const wrapped = localReflectApply(localWeakMapGet, wrappedPrepareStackTrace, [value]);
			if (wrapped) {
				currentPrepareStackTrace = wrapped;
				return;
			}
			const newWrapped = (error, sst) => {
				const sandboxSst = ensureThis(sst);
				if (localArrayIsArray(sst)) {
					if (sst === sandboxSst) {
						for (let i=0; i < sst.length; i++) {
							const cs = sst[i];
							if (typeof cs === 'object' && localReflectGetPrototypeOf(cs) === OriginalCallSite.prototype) {
								sst[i] = new CallSite(cs);
							}
						}
					} else {
						sst = [];
						for (let i=0; i < sandboxSst.length; i++) {
							const cs = sandboxSst[i];
							localReflectDefineProperty(sst, i, {
								__proto__: null,
								value: new CallSite(cs),
								enumerable: true,
								configurable: true,
								writable: true
							});
						}
					}
				} else {
					sst = sandboxSst;
				}
				return value(error, sst);
			};
			localReflectApply(localWeakMapSet, wrappedPrepareStackTrace, [value, newWrapped]);
			localReflectApply(localWeakMapSet, wrappedPrepareStackTrace, [newWrapped, newWrapped]);
			currentPrepareStackTrace = newWrapped;
		}
	})) throw localUnexpected();
} else if (oldPrepareStackTraceDesc) {
	localReflectDefineProperty(LocalError, 'prepareStackTrace', oldPrepareStackTraceDesc);
} else {
	localReflectDeleteProperty(LocalError, 'prepareStackTrace');
}

/*
 * Exception sanitization
 */

const withProxy = localObjectFreeze({
	__proto__: null,
	has(target, key) {
		if (key === host.INTERNAL_STATE_NAME) return false;
		return localReflectHas(target, key);
	}
});

const interanState = localObjectFreeze({
	__proto__: null,
	wrapWith(x) {
		if (x === null || x === undefined) return x;
		return new LocalProxy(localObject(x), withProxy);
	},
	handleException: ensureThis,
	import(what) {
		throw new VMError('Dynamic Import not supported');
	}
});

if (!localReflectDefineProperty(global, host.INTERNAL_STATE_NAME, {
	__proto__: null,
	configurable: false,
	enumerable: false,
	writable: false,
	value: interanState
})) throw localUnexpected();

/*
 * Eval sanitization
 */

function throwAsync() {
	return new VMError('Async not available');
}

function makeFunction(inputArgs, isAsync, isGenerator) {
	const lastArgs = inputArgs.length - 1;
	let code = lastArgs >= 0 ? `${inputArgs[lastArgs]}` : '';
	let args = lastArgs > 0 ? `${inputArgs[0]}` : '';
	for (let i = 1; i < lastArgs; i++) {
		args += `,${inputArgs[i]}`;
	}
	try {
		code = host.transformAndCheck(args, code, isAsync, isGenerator, allowAsync);
	} catch (e) {
		throw bridge.from(e);
	}
	return localEval(code);
}

const FunctionHandler = {
	__proto__: null,
	apply(target, thiz, args) {
		return makeFunction(args, this.isAsync, this.isGenerator);
	},
	construct(target, args, newTarget) {
		return makeFunction(args, this.isAsync, this.isGenerator);
	}
};

const EvalHandler = {
	__proto__: null,
	apply(target, thiz, args) {
		if (args.length === 0) return undefined;
		let code = `${args[0]}`;
		try {
			code = host.transformAndCheck(null, code, false, false, allowAsync);
		} catch (e) {
			throw bridge.from(e);
		}
		return localEval(code);
	}
};

const AsyncErrorHandler = {
	__proto__: null,
	apply(target, thiz, args) {
		throw throwAsync();
	},
	construct(target, args, newTarget) {
		throw throwAsync();
	}
};

function makeCheckFunction(isAsync, isGenerator) {
	if (isAsync && !allowAsync) return AsyncErrorHandler;
	return {
		__proto__: FunctionHandler,
		isAsync,
		isGenerator
	};
}

function overrideWithProxy(obj, prop, value, handler) {
	const proxy = new LocalProxy(value, handler);
	if (!localReflectDefineProperty(obj, prop, {__proto__: null, value: proxy})) throw localUnexpected();
	return proxy;
}

const proxiedFunction = overrideWithProxy(localFunction.prototype, 'constructor', localFunction, makeCheckFunction(false, false));
if (GeneratorFunction) {
	if (!localReflectSetPrototypeOf(GeneratorFunction, proxiedFunction)) throw localUnexpected();
	overrideWithProxy(GeneratorFunction.prototype, 'constructor', GeneratorFunction, makeCheckFunction(false, true));
}
if (AsyncFunction) {
	if (!localReflectSetPrototypeOf(AsyncFunction, proxiedFunction)) throw localUnexpected();
	overrideWithProxy(AsyncFunction.prototype, 'constructor', AsyncFunction, makeCheckFunction(true, false));
}
if (AsyncGeneratorFunction) {
	if (!localReflectSetPrototypeOf(AsyncGeneratorFunction, proxiedFunction)) throw localUnexpected();
	overrideWithProxy(AsyncGeneratorFunction.prototype, 'constructor', AsyncGeneratorFunction, makeCheckFunction(true, true));
}

function makeSafeHandlerArgs(args) {
	const sArgs = ensureThis(args);
	if (sArgs === args) return args;
	const a = [];
	for (let i=0; i < sArgs.length; i++) {
		localReflectDefineProperty(a, i, {
			__proto__: null,
			value: sArgs[i],
			enumerable: true,
			configurable: true,
			writable: true
		});
	}
	return a;
}

const makeSafeArgs = Object.freeze({
	__proto__: null,
	apply(target, thiz, args) {
		return localReflectApply(target, thiz, makeSafeHandlerArgs(args));
	},
	construct(target, args, newTarget) {
		return localReflectConstruct(target, makeSafeHandlerArgs(args), newTarget);
	}
});

const proxyHandlerHandler = Object.freeze({
	__proto__: null,
	get(target, name, receiver) {
		const value = target.handler[name];
		if (typeof value !== 'function') return value;
		return new LocalProxy(value, makeSafeArgs);
	}
});

function wrapProxyHandler(args) {
	if (args.length < 2) return args;
	const handler = args[1];
	args[1] = new LocalProxy({__proto__: null, handler}, proxyHandlerHandler);
	return args;
}

const proxyHandler = Object.freeze({
	__proto__: null,
	apply(target, thiz, args) {
		return localReflectApply(target, thiz, wrapProxyHandler(args));
	},
	construct(target, args, newTarget) {
		return localReflectConstruct(target, wrapProxyHandler(args), newTarget);
	}
});

const proxiedProxy = new LocalProxy(LocalProxy, proxyHandler);

overrideWithProxy(LocalProxy, 'revocable', LocalProxy.revocable, proxyHandler);

global.Proxy = proxiedProxy;
global.Function = proxiedFunction;
global.eval = new LocalProxy(localEval, EvalHandler);

/*
 * Promise sanitization
 */

if (localPromise) {

	const PromisePrototype = localPromise.prototype;

	if (!allowAsync) {

		overrideWithProxy(PromisePrototype, 'then', PromisePrototype.then, AsyncErrorHandler);
		// This seems not to work, and will produce
		// UnhandledPromiseRejectionWarning: TypeError: Method Promise.prototype.then called on incompatible receiver [object Object].
		// This is likely caused since the host.Promise.prototype.then cannot use the VM Proxy object.
		// Contextify.connect(host.Promise.prototype.then, Promise.prototype.then);

	} else {

		overrideWithProxy(PromisePrototype, 'then', PromisePrototype.then, {
			__proto__: null,
			apply(target, thiz, args) {
				if (args.length > 1) {
					const onRejected = args[1];
					if (typeof onRejected === 'function') {
						args[1] = function wrapper(error) {
							error = ensureThis(error);
							return localReflectApply(onRejected, this, [error]);
						};
					}
				}
				return localReflectApply(target, thiz, args);
			}
		});

	}

}

function readonly(other, mock) {
	// Note: other@other(unsafe) mock@other(unsafe) returns@this(unsafe) throws@this(unsafe)
	if (!mock) return fromWithFactory(readonlyFactory, other);
	const tmock = from(mock);
	return fromWithFactory(obj=>new ReadOnlyMockHandler(obj, tmock), other);
}

return {
	__proto__: null,
	readonly,
	global
};
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 /* global host, data, VMError */

'use strict';

const LocalError = Error;
const LocalTypeError = TypeError;
const LocalWeakMap = WeakMap;

const {
	apply: localReflectApply,
	defineProperty: localReflectDefineProperty
} = Reflect;

const {
	set: localWeakMapSet,
	get: localWeakMapGet
} = LocalWeakMap.prototype;

const {
	isArray: localArrayIsArray
} = Array;

function uncurryThis(func) {
	return (thiz, ...args) => localReflectApply(func, thiz, args);
}

const localArrayPrototypeSlice = uncurryThis(Array.prototype.slice);
const localArrayPrototypeIncludes = uncurryThis(Array.prototype.includes);
const localArrayPrototypePush = uncurryThis(Array.prototype.push);
const localArrayPrototypeIndexOf = uncurryThis(Array.prototype.indexOf);
const localArrayPrototypeSplice = uncurryThis(Array.prototype.splice);
const localStringPrototypeStartsWith = uncurryThis(String.prototype.startsWith);
const localStringPrototypeSlice = uncurryThis(String.prototype.slice);
const localStringPrototypeIndexOf = uncurryThis(String.prototype.indexOf);

const {
	argv: optionArgv,
	env: optionEnv,
	console: optionConsole,
	extensions,
	emitArgs,
	globalPaths,
	getLookupPathsFor,
	resolve: resolve0,
	lookupPaths,
	loadBuiltinModule,
	registerModule,
	builtinModules,
	dirname,
	basename
} = data;

function ensureSandboxArray(a) {
	return localArrayPrototypeSlice(a);
}

class Module {

	constructor(id, path, parent) {
		this.id = id;
		this.filename = id;
		this.path = path;
		this.parent = parent;
		this.loaded = false;
		this.paths = path ? ensureSandboxArray(getLookupPathsFor(path)) : [];
		this.children = [];
		this.exports = {};
	}

	_updateChildren(child, isNew) {
		const children = this.children;
		if (children && (isNew || !localArrayPrototypeIncludes(children, child))) {
			localArrayPrototypePush(children, child);
		}
	}

	require(id) {
		return requireImpl(this, id, false);
	}

}

const originalRequire = Module.prototype.require;
const cacheBuiltins = {__proto__: null};

function requireImpl(mod, id, direct) {
	if (direct && mod.require !== originalRequire) {
		return mod.require(id);
	}
	const filename = resolve0(mod, id, undefined, Module._extensions, direct);
	if (localStringPrototypeStartsWith(filename, 'node:')) {
		id = localStringPrototypeSlice(filename, 5);
		let nmod = cacheBuiltins[id];
		if (!nmod) {
			nmod = loadBuiltinModule(id);
			if (!nmod) throw new VMError(`Cannot find module '${filename}'`, 'ENOTFOUND');
			cacheBuiltins[id] = nmod;
		}
		return nmod;
	}

	const cachedModule = Module._cache[filename];
	if (cachedModule !== undefined) {
		mod._updateChildren(cachedModule, false);
		return cachedModule.exports;
	}

	let nmod = cacheBuiltins[id];
	if (nmod) return nmod;
	nmod = loadBuiltinModule(id);
	if (nmod) {
		cacheBuiltins[id] = nmod;
		return nmod;
	}

	const path = dirname(filename);
	const module = new Module(filename, path, mod);
	registerModule(module, filename, path, mod, direct);
	mod._updateChildren(module, true);
	try {
		Module._cache[filename] = module;
		const handler = findBestExtensionHandler(filename);
		handler(module, filename);
		module.loaded = true;
	} catch (e) {
		delete Module._cache[filename];
		const children = mod.children;
		if (localArrayIsArray(children)) {
			const index = localArrayPrototypeIndexOf(children, module);
			if (index !== -1) {
				localArrayPrototypeSplice(children, index, 1);
			}
		}
		throw e;
	}

	return module.exports;
}

Module.builtinModules = ensureSandboxArray(builtinModules);
Module.globalPaths = ensureSandboxArray(globalPaths);
Module._extensions = {__proto__: null};
Module._cache = {__proto__: null};

{
	const keys = Object.getOwnPropertyNames(extensions);
	for (let i = 0; i < keys.length; i++) {
		const key = keys[i];
		const handler = extensions[key];
		Module._extensions[key] = (mod, filename) => handler(mod, filename);
	}
}

function findBestExtensionHandler(filename) {
	const name = basename(filename);
	for (let i = 0; (i = localStringPrototypeIndexOf(name, '.', i + 1)) !== -1;) {
		const ext = localStringPrototypeSlice(name, i);
		const handler = Module._extensions[ext];
		if (handler) return handler;
	}
	const js = Module._extensions['.js'];
	if (js) return js;
	const keys = Object.getOwnPropertyNames(Module._extensions);
	if (keys.length === 0) throw new VMError(`Failed to load '${filename}': Unknown type.`, 'ELOADFAIL');
	return Module._extensions[keys[0]];
}

function createRequireForModule(mod) {
	// eslint-disable-next-line no-shadow
	function require(id) {
		return requireImpl(mod, id, true);
	}
	function resolve(id, options) {
		return resolve0(mod, id, options, Module._extensions, true);
	}
	require.resolve = resolve;
	function paths(id) {
		return ensureSandboxArray(lookupPaths(mod, id));
	}
	resolve.paths = paths;

	require.extensions = Module._extensions;

	require.cache = Module._cache;

	return require;
}

/**
 * Prepare sandbox.
 */

const TIMERS = new LocalWeakMap();

class Timeout {
}

class Interval {
}

class Immediate {
}

function clearTimer(timer) {
	const obj = localReflectApply(localWeakMapGet, TIMERS, [timer]);
	if (obj) {
		obj.clear(obj.value);
	}
}

// This is a function and not an arrow function, since the original is also a function
// eslint-disable-next-line no-shadow
global.setTimeout = function setTimeout(callback, delay, ...args) {
	if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function');
	const obj = new Timeout(callback, args);
	const cb = () => {
		localReflectApply(callback, null, args);
	};
	const tmr = host.setTimeout(cb, delay);

	const ref = {
		__proto__: null,
		clear: host.clearTimeout,
		value: tmr
	};

	localReflectApply(localWeakMapSet, TIMERS, [obj, ref]);
	return obj;
};

// eslint-disable-next-line no-shadow
global.setInterval = function setInterval(callback, interval, ...args) {
	if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function');
	const obj = new Interval();
	const cb = () => {
		localReflectApply(callback, null, args);
	};
	const tmr = host.setInterval(cb, interval);

	const ref = {
		__proto__: null,
		clear: host.clearInterval,
		value: tmr
	};

	localReflectApply(localWeakMapSet, TIMERS, [obj, ref]);
	return obj;
};

// eslint-disable-next-line no-shadow
global.setImmediate = function setImmediate(callback, ...args) {
	if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function');
	const obj = new Immediate();
	const cb = () => {
		localReflectApply(callback, null, args);
	};
	const tmr = host.setImmediate(cb);

	const ref = {
		__proto__: null,
		clear: host.clearImmediate,
		value: tmr
	};

	localReflectApply(localWeakMapSet, TIMERS, [obj, ref]);
	return obj;
};

// eslint-disable-next-line no-shadow
global.clearTimeout = function clearTimeout(timeout) {
	clearTimer(timeout);
};

// eslint-disable-next-line no-shadow
global.clearInterval = function clearInterval(interval) {
	clearTimer(interval);
};

// eslint-disable-next-line no-shadow
global.clearImmediate = function clearImmediate(immediate) {
	clearTimer(immediate);
};

const localProcess = host.process;

const LISTENERS = new LocalWeakMap();
const LISTENER_HANDLER = new LocalWeakMap();

/**
 *
 * @param {*} name
 * @param {*} handler
 * @this process
 * @return {this}
 */
function addListener(name, handler) {
	if (name !== 'beforeExit' && name !== 'exit') {
		throw new LocalError(`Access denied to listen for '${name}' event.`);
	}

	let cb = localReflectApply(localWeakMapGet, LISTENERS, [handler]);
	if (!cb) {
		cb = () => {
			handler();
		};
		localReflectApply(localWeakMapSet, LISTENER_HANDLER, [cb, handler]);
		localReflectApply(localWeakMapSet, LISTENERS, [handler, cb]);
	}

	localProcess.on(name, cb);

	return this;
}

/**
 *
 * @this process
 * @return {this}
 */
// eslint-disable-next-line no-shadow
function process() {
	return this;
}

const baseUptime = localProcess.uptime();

// FIXME wrong class structure
global.process = {
	__proto__: process.prototype,
	argv: optionArgv !== undefined ? optionArgv : [],
	title: localProcess.title,
	version: localProcess.version,
	versions: localProcess.versions,
	arch: localProcess.arch,
	platform: localProcess.platform,
	env: optionEnv !== undefined ? optionEnv : {},
	pid: localProcess.pid,
	features: localProcess.features,
	nextTick: function nextTick(callback, ...args) {
		if (typeof callback !== 'function') {
			throw new LocalError('Callback must be a function.');
		}

		localProcess.nextTick(()=>{
			localReflectApply(callback, null, args);
		});
	},
	hrtime: function hrtime(time) {
		return localProcess.hrtime(time);
	},
	uptime: function uptime() {
		return localProcess.uptime() - baseUptime;
	},
	cwd: function cwd() {
		return localProcess.cwd();
	},
	addListener,
	on: addListener,

	once: function once(name, handler) {
		if (name !== 'beforeExit' && name !== 'exit') {
			throw new LocalError(`Access denied to listen for '${name}' event.`);
		}

		let triggered = false;
		const cb = () => {
			if (triggered) return;
			triggered = true;
			localProcess.removeListener(name, cb);
			handler();
		};
		localReflectApply(localWeakMapSet, LISTENER_HANDLER, [cb, handler]);

		localProcess.on(name, cb);

		return this;
	},

	listeners: function listeners(name) {
		if (name !== 'beforeExit' && name !== 'exit') {
			// Maybe add ({__proto__:null})[name] to throw when name fails in https://tc39.es/ecma262/#sec-topropertykey.
			return [];
		}

		// Filter out listeners, which were not created in this sandbox
		const all = localProcess.listeners(name);
		const filtered = [];
		let j = 0;
		for (let i = 0; i < all.length; i++) {
			const h = localReflectApply(localWeakMapGet, LISTENER_HANDLER, [all[i]]);
			if (h) {
				if (!localReflectDefineProperty(filtered, j, {
					__proto__: null,
					value: h,
					writable: true,
					enumerable: true,
					configurable: true
				})) throw new LocalError('Unexpected');
				j++;
			}
		}
		return filtered;
	},

	removeListener: function removeListener(name, handler) {
		if (name !== 'beforeExit' && name !== 'exit') {
			return this;
		}

		const cb = localReflectApply(localWeakMapGet, LISTENERS, [handler]);
		if (cb) localProcess.removeListener(name, cb);

		return this;
	},

	umask: function umask() {
		if (arguments.length) {
			throw new LocalError('Access denied to set umask.');
		}

		return localProcess.umask();
	}
};

if (optionConsole === 'inherit') {
	global.console = host.console;
} else if (optionConsole === 'redirect') {
	global.console = {
		debug(...args) {
			emitArgs('console.debug', args);
		},
		log(...args) {
			emitArgs('console.log', args);
		},
		info(...args) {
			emitArgs('console.info', args);
		},
		warn(...args) {
			emitArgs('console.warn', args);
		},
		error(...args) {
			emitArgs('console.error', args);
		},
		dir(...args) {
			emitArgs('console.dir', args);
		},
		time() {},
		timeEnd() {},
		trace(...args) {
			emitArgs('console.trace', args);
		}
	};
}

return {
	__proto__: null,
	Module,
	jsonParse: JSON.parse,
	createRequireForModule,
	requireImpl
};
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      'use strict';

const {Script} = require('vm');
const {
	lookupCompiler,
	removeShebang
} = require('./compiler');
const {
	transformer
} = require('./transformer');

const objectDefineProperties = Object.defineProperties;

const MODULE_PREFIX = '(function (exports, require, module, __filename, __dirname) { ';
const STRICT_MODULE_PREFIX = MODULE_PREFIX + '"use strict"; ';
const MODULE_SUFFIX = '\n});';

/**
 * Class Script
 *
 * @public
 */
class VMScript {

	/**
	 * The script code with wrapping. If set will invalidate the cache.<br>
	 * Writable only for backwards compatibility.
	 *
	 * @public
	 * @readonly
	 * @member {string} code
	 * @memberOf VMScript#
	 */

	/**
	 * The filename used for this script.
	 *
	 * @public
	 * @readonly
	 * @since v3.9.0
	 * @member {string} filename
	 * @memberOf VMScript#
	 */

	/**
	 * The line offset use for stack traces.
	 *
	 * @public
	 * @readonly
	 * @since v3.9.0
	 * @member {number} lineOffset
	 * @memberOf VMScript#
	 */

	/**
	 * The column offset use for stack traces.
	 *
	 * @public
	 * @readonly
	 * @since v3.9.0
	 * @member {number} columnOffset
	 * @memberOf VMScript#
	 */

	/**
	 * The compiler to use to get the JavaScript code.
	 *
	 * @public
	 * @readonly
	 * @since v3.9.0
	 * @member {(string|compileCallback)} compiler
	 * @memberOf VMScript#
	 */

	/**
	 * The prefix for the script.
	 *
	 * @private
	 * @member {string} _prefix
	 * @memberOf VMScript#
	 */

	/**
	 * The suffix for the script.
	 *
	 * @private
	 * @member {string} _suffix
	 * @memberOf VMScript#
	 */

	/**
	 * The compiled vm.Script for the VM or if not compiled <code>null</code>.
	 *
	 * @private
	 * @member {?vm.Script} _compiledVM
	 * @memberOf VMScript#
	 */

	/**
	 * The compiled vm.Script for the NodeVM or if not compiled <code>null</code>.
	 *
	 * @private
	 * @member {?vm.Script} _compiledNodeVM
	 * @memberOf VMScript#
	 */

	/**
	 * The compiled vm.Script for the NodeVM in strict mode or if not compiled <code>null</code>.
	 *
	 * @private
	 * @member {?vm.Script} _compiledNodeVMStrict
	 * @memberOf VMScript#
	 */

	/**
	 * The resolved compiler to use to get the JavaScript code.
	 *
	 * @private
	 * @readonly
	 * @member {compileCallback} _compiler
	 * @memberOf VMScript#
	 */

	/**
	 * The script to run without wrapping.
	 *
	 * @private
	 * @member {string} _code
	 * @memberOf VMScript#
	 */

	/**
	 * Whether or not the script contains async functions.
	 *
	 * @private
	 * @member {boolean} _hasAsync
	 * @memberOf VMScript#
	 */

	/**
	 * Create VMScript instance.
	 *
	 * @public
	 * @param {string} code - Code to run.
	 * @param {(string|Object)} [options] - Options map or filename.
	 * @param {string} [options.filename="vm.js"] - Filename that shows up in any stack traces produced from this script.
	 * @param {number} [options.lineOffset=0] - Passed to vm.Script options.
	 * @param {number} [options.columnOffset=0] - Passed to vm.Script options.
	 * @param {(string|compileCallback)} [options.compiler="javascript"] - The compiler to use.
	 * @throws {VMError} If the compiler is unknown or if coffee-script was requested but the module not found.
	 */
	constructor(code, options) {
		const sCode = `${code}`;
		let useFileName;
		let useOptions;
		if (arguments.length === 2) {
			if (typeof options === 'object') {
				useOptions = options || {__proto__: null};
				useFileName = useOptions.filename;
			} else {
				useOptions = {__proto__: null};
				useFileName = options;
			}
		} else if (arguments.length > 2) {
			// We do it this way so that there are no more arguments in the function.
			// eslint-disable-next-line prefer-rest-params
			useOptions = arguments[2] || {__proto__: null};
			useFileName = options || useOptions.filename;
		} else {
			useOptions = {__proto__: null};
		}

		const {
			compiler = 'javascript',
			lineOffset = 0,
			columnOffset = 0
		} = useOptions;

		// Throw if the compiler is unknown.
		const resolvedCompiler = lookupCompiler(compiler);

		objectDefineProperties(this, {
			__proto__: null,
			code: {
				__proto__: null,
				// Put this here so that it is enumerable, and looks like a property.
				get() {
					return this._prefix + this._code + this._suffix;
				},
				set(value) {
					const strNewCode = String(value);
					if (strNewCode === this._code && this._prefix === '' && this._suffix === '') return;
					this._code = strNewCode;
					this._prefix = '';
					this._suffix = '';
					this._compiledVM = null;
					this._compiledNodeVM = null;
					this._compiledCode = null;
				},
				enumerable: true
			},
			filename: {
				__proto__: null,
				value: useFileName || 'vm.js',
				enumerable: true
			},
			lineOffset: {
				__proto__: null,
				value: lineOffset,
				enumerable: true
			},
			columnOffset: {
				__proto__: null,
				value: columnOffset,
				enumerable: true
			},
			compiler: {
				__proto__: null,
				value: compiler,
				enumerable: true
			},
			_code: {
				__proto__: null,
				value: sCode,
				writable: true
			},
			_prefix: {
				__proto__: null,
				value: '',
				writable: true
			},
			_suffix: {
				__proto__: null,
				value: '',
				writable: true
			},
			_compiledVM: {
				__proto__: null,
				value: null,
				writable: true
			},
			_compiledNodeVM: {
				__proto__: null,
				value: null,
				writable: true
			},
			_compiledNodeVMStrict: {
				__proto__: null,
				value: null,
				writable: true
			},
			_compiledCode: {
				__proto__: null,
				value: null,
				writable: true
			},
			_hasAsync: {
				__proto__: null,
				value: false,
				writable: true
			},
			_compiler: {__proto__: null, value: resolvedCompiler}
		});
	}

	/**
	 * Wraps the code.<br>
	 * This will replace the old wrapping.<br>
	 * Will invalidate the code cache.
	 *
	 * @public
	 * @deprecated Since v3.9.0. Wrap your code before passing it into the VMScript object.
	 * @param {string} prefix - String that will be appended before the script code.
	 * @param {script} suffix - String that will be appended behind the script code.
	 * @return {this} This for chaining.
	 * @throws {TypeError} If prefix or suffix is a Symbol.
	 */
	wrap(prefix, suffix) {
		const strPrefix = `${prefix}`;
		const strSuffix = `${suffix}`;
		if (this._prefix === strPrefix && this._suffix === strSuffix) return this;
		this._prefix = strPrefix;
		this._suffix = strSuffix;
		this._compiledVM = null;
		this._compiledNodeVM = null;
		this._compiledNodeVMStrict = null;
		return this;
	}

	/**
	 * Compile this script. <br>
	 * This is useful to detect syntax errors in the script.
	 *
	 * @public
	 * @return {this} This for chaining.
	 * @throws {SyntaxError} If there is a syntax error in the script.
	 */
	compile() {
		this._compileVM();
		return this;
	}

	/**
	 * Get the compiled code.
	 *
	 * @private
	 * @return {string} The code.
	 */
	getCompiledCode() {
		if (!this._compiledCode) {
			const comp = this._compiler(this._prefix + removeShebang(this._code) + this._suffix, this.filename);
			const res = transformer(null, comp, false, false, this.filename);
			this._compiledCode = res.code;
			this._hasAsync = res.hasAsync;
		}
		return this._compiledCode;
	}

	/**
	 * Compiles this script to a vm.Script.
	 *
	 * @private
	 * @param {string} prefix - JavaScript code that will be used as prefix.
	 * @param {string} suffix - JavaScript code that will be used as suffix.
	 * @return {vm.Script} The compiled vm.Script.
	 * @throws {SyntaxError} If there is a syntax error in the script.
	 */
	_compile(prefix, suffix) {
		return new Script(prefix + this.getCompiledCode() + suffix, {
			__proto__: null,
			filename: this.filename,
			displayErrors: false,
			lineOffset: this.lineOffset,
			columnOffset: this.columnOffset
		});
	}

	/**
	 * Will return the cached version of the script intended for VM or compile it.
	 *
	 * @private
	 * @return {vm.Script} The compiled script
	 * @throws {SyntaxError} If there is a syntax error in the script.
	 */
	_compileVM() {
		let script = this._compiledVM;
		if (!script) {
			this._compiledVM = script = this._compile('', '');
		}
		return script;
	}

	/**
	 * Will return the cached version of the script intended for NodeVM or compile it.
	 *
	 * @private
	 * @return/*
 * WARNING: do not edit!
 * Generated by makefile from include/openssl/ssl.h.in
 *
 * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
 * Copyright 2005 Nokia. All rights reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */



#ifndef OPENSSL_SSL_H
# define OPENSSL_SSL_H
# pragma once

# include <openssl/macros.h>
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define HEADER_SSL_H
# endif

# include <openssl/e_os2.h>
# include <openssl/opensslconf.h>
# include <openssl/comp.h>
# include <openssl/bio.h>
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  include <openssl/x509.h>
#  include <openssl/crypto.h>
#  include <openssl/buffer.h>
# endif
# include <openssl/lhash.h>
# include <openssl/pem.h>
# include <openssl/hmac.h>
# include <openssl/async.h>

# include <openssl/safestack.h>
# include <openssl/symhacks.h>
# include <openssl/ct.h>
# include <openssl/sslerr.h>
# include <openssl/prov_ssl.h>

#ifdef  __cplusplus
extern "C" {
#endif

/* OpenSSL version number for ASN.1 encoding of the session information */
/*-
 * Version 0 - initial version
 * Version 1 - added the optional peer certificate
 */
# define SSL_SESSION_ASN1_VERSION 0x0001

# define SSL_MAX_SSL_SESSION_ID_LENGTH           32
# define SSL_MAX_SID_CTX_LENGTH                  32

# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES     (512/8)
# define SSL_MAX_KEY_ARG_LENGTH                  8
/* SSL_MAX_MASTER_KEY_LENGTH is defined in prov_ssl.h */

/* The maximum number of encrypt/decrypt pipelines we can support */
# define SSL_MAX_PIPELINES  32

/* text strings for the ciphers */

/* These are used to specify which ciphers to use and not to use */

# define SSL_TXT_LOW             "LOW"
# define SSL_TXT_MEDIUM          "MEDIUM"
# define SSL_TXT_HIGH            "HIGH"
# define SSL_TXT_FIPS            "FIPS"

# define SSL_TXT_aNULL           "aNULL"
# define SSL_TXT_eNULL           "eNULL"
# define SSL_TXT_NULL            "NULL"

# define SSL_TXT_kRSA            "kRSA"
# define SSL_TXT_kDHr            "kDHr"/* this cipher class has been removed */
# define SSL_TXT_kDHd            "kDHd"/* this cipher class has been removed */
# define SSL_TXT_kDH             "kDH"/* this cipher class has been removed */
# define SSL_TXT_kEDH            "kEDH"/* alias for kDHE */
# define SSL_TXT_kDHE            "kDHE"
# define SSL_TXT_kECDHr          "kECDHr"/* this cipher class has been removed */
# define SSL_TXT_kECDHe          "kECDHe"/* this cipher class has been removed */
# define SSL_TXT_kECDH           "kECDH"/* this cipher class has been removed */
# define SSL_TXT_kEECDH          "kEECDH"/* alias for kECDHE */
# define SSL_TXT_kECDHE          "kECDHE"
# define SSL_TXT_kPSK            "kPSK"
# define SSL_TXT_kRSAPSK         "kRSAPSK"
# define SSL_TXT_kECDHEPSK       "kECDHEPSK"
# define SSL_TXT_kDHEPSK         "kDHEPSK"
# define SSL_TXT_kGOST           "kGOST"
# define SSL_TXT_kGOST18         "kGOST18"
# define SSL_TXT_kSRP            "kSRP"

# define SSL_TXT_aRSA            "aRSA"
# define SSL_TXT_aDSS            "aDSS"
# define SSL_TXT_aDH             "aDH"/* this cipher class has been removed */
# define SSL_TXT_aECDH           "aECDH"/* this cipher class has been removed */
# define SSL_TXT_aECDSA          "aECDSA"
# define SSL_TXT_aPSK            "aPSK"
# define SSL_TXT_aGOST94         "aGOST94"
# define SSL_TXT_aGOST01         "aGOST01"
# define SSL_TXT_aGOST12         "aGOST12"
# define SSL_TXT_aGOST           "aGOST"
# define SSL_TXT_aSRP            "aSRP"

# define SSL_TXT_DSS             "DSS"
# define SSL_TXT_DH              "DH"
# define SSL_TXT_DHE             "DHE"/* same as "kDHE:-ADH" */
# define SSL_TXT_EDH             "EDH"/* alias for DHE */
# define SSL_TXT_ADH             "ADH"
# define SSL_TXT_RSA             "RSA"
# define SSL_TXT_ECDH            "ECDH"
# define SSL_TXT_EECDH           "EECDH"/* alias for ECDHE" */
# define SSL_TXT_ECDHE           "ECDHE"/* same as "kECDHE:-AECDH" */
# define SSL_TXT_AECDH           "AECDH"
# define SSL_TXT_ECDSA           "ECDSA"
# define SSL_TXT_PSK             "PSK"
# define SSL_TXT_SRP             "SRP"

# define SSL_TXT_DES             "DES"
# define SSL_TXT_3DES            "3DES"
# define SSL_TXT_RC4             "RC4"
# define SSL_TXT_RC2             "RC2"
# define SSL_TXT_IDEA            "IDEA"
# define SSL_TXT_SEED            "SEED"
# define SSL_TXT_AES128          "AES128"
# define SSL_TXT_AES256          "AES256"
# define SSL_TXT_AES             "AES"
# define SSL_TXT_AES_GCM         "AESGCM"
# define SSL_TXT_AES_CCM         "AESCCM"
# define SSL_TXT_AES_CCM_8       "AESCCM8"
# define SSL_TXT_CAMELLIA128     "CAMELLIA128"
# define SSL_TXT_CAMELLIA256     "CAMELLIA256"
# define SSL_TXT_CAMELLIA        "CAMELLIA"
# define SSL_TXT_CHACHA20        "CHACHA20"
# define SSL_TXT_GOST            "GOST89"
# define SSL_TXT_ARIA            "ARIA"
# define SSL_TXT_ARIA_GCM        "ARIAGCM"
# define SSL_TXT_ARIA128         "ARIA128"
# define SSL_TXT_ARIA256         "ARIA256"
# define SSL_TXT_GOST2012_GOST8912_GOST8912 "GOST2012-GOST8912-GOST8912"
# define SSL_TXT_CBC             "CBC"

# define SSL_TXT_MD5             "MD5"
# define SSL_TXT_SHA1            "SHA1"
# define SSL_TXT_SHA             "SHA"/* same as "SHA1" */
# define SSL_TXT_GOST94          "GOST94"
# define SSL_TXT_GOST89MAC       "GOST89MAC"
# define SSL_TXT_GOST12          "GOST12"
# define SSL_TXT_GOST89MAC12     "GOST89MAC12"
# define SSL_TXT_SHA256          "SHA256"
# define SSL_TXT_SHA384          "SHA384"

# define SSL_TXT_SSLV3           "SSLv3"
# define SSL_TXT_TLSV1           "TLSv1"
# define SSL_TXT_TLSV1_1         "TLSv1.1"
# define SSL_TXT_TLSV1_2         "TLSv1.2"

# define SSL_TXT_ALL             "ALL"

/*-
 * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
 * ciphers normally not being used.
 * Example: "RC4" will activate all ciphers using RC4 including ciphers
 * without authentication, which would normally disabled by DEFAULT (due
 * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
 * will make sure that it is also disabled in the specific selection.
 * COMPLEMENTOF* identifiers are portable between version, as adjustments
 * to the default cipher setup will also be included here.
 *
 * COMPLEMENTOFDEFAULT does not experience the same special treatment that
 * DEFAULT gets, as only selection is being done and no sorting as needed
 * for DEFAULT.
 */
# define SSL_TXT_CMPALL          "COMPLEMENTOFALL"
# define SSL_TXT_CMPDEF          "COMPLEMENTOFDEFAULT"

/*
 * The following cipher list is used by default. It also is substituted when
 * an application-defined cipher list string starts with 'DEFAULT'.
 * This applies to ciphersuites for TLSv1.2 and below.
 * DEPRECATED IN 3.0.0, in favor of OSSL_default_cipher_list()
 * Update both macro and function simultaneously
 */
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL"
/*
 * This is the default set of TLSv1.3 ciphersuites
 * DEPRECATED IN 3.0.0, in favor of OSSL_default_ciphersuites()
 * Update both macro and function simultaneously
 */
#  define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
                                   "TLS_CHACHA20_POLY1305_SHA256:" \
                                   "TLS_AES_128_GCM_SHA256"
# endif
/*
 * As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always
 * starts with a reasonable order, and all we have to do for DEFAULT is
 * throwing out anonymous and unencrypted ciphersuites! (The latter are not
 * actually enabled by ALL, but "ALL:RSA" would enable some of them.)
 */

/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
# define SSL_SENT_SHUTDOWN       1
# define SSL_RECEIVED_SHUTDOWN   2

#ifdef __cplusplus
}
#endif

#ifdef  __cplusplus
extern "C" {
#endif

# define SSL_FILETYPE_ASN1       X509_FILETYPE_ASN1
# define SSL_FILETYPE_PEM        X509_FILETYPE_PEM

/*
 * This is needed to stop compilers complaining about the 'struct ssl_st *'
 * function parameters used to prototype callbacks in SSL_CTX.
 */
typedef struct ssl_st *ssl_crock_st;
typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
typedef struct ssl_method_st SSL_METHOD;
typedef struct ssl_cipher_st SSL_CIPHER;
typedef struct ssl_session_st SSL_SESSION;
typedef struct tls_sigalgs_st TLS_SIGALGS;
typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
typedef struct ssl_comp_st SSL_COMP;

STACK_OF(SSL_CIPHER);
STACK_OF(SSL_COMP);

/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/
typedef struct srtp_protection_profile_st {
    const char *name;
    unsigned long id;
} SRTP_PROTECTION_PROFILE;
SKM_DEFINE_STACK_OF_INTERNAL(SRTP_PROTECTION_PROFILE, SRTP_PROTECTION_PROFILE, SRTP_PROTECTION_PROFILE)
#define sk_SRTP_PROTECTION_PROFILE_num(sk) OPENSSL_sk_num(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_value(sk, idx) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_value(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk), (idx)))
#define sk_SRTP_PROTECTION_PROFILE_new(cmp) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_new(ossl_check_SRTP_PROTECTION_PROFILE_compfunc_type(cmp)))
#define sk_SRTP_PROTECTION_PROFILE_new_null() ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_new_null())
#define sk_SRTP_PROTECTION_PROFILE_new_reserve(cmp, n) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_new_reserve(ossl_check_SRTP_PROTECTION_PROFILE_compfunc_type(cmp), (n)))
#define sk_SRTP_PROTECTION_PROFILE_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), (n))
#define sk_SRTP_PROTECTION_PROFILE_free(sk) OPENSSL_sk_free(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_zero(sk) OPENSSL_sk_zero(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_delete(sk, i) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_delete(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), (i)))
#define sk_SRTP_PROTECTION_PROFILE_delete_ptr(sk, ptr) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_delete_ptr(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr)))
#define sk_SRTP_PROTECTION_PROFILE_push(sk, ptr) OPENSSL_sk_push(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_pop(sk) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_pop(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk)))
#define sk_SRTP_PROTECTION_PROFILE_shift(sk) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_shift(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk)))
#define sk_SRTP_PROTECTION_PROFILE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk),ossl_check_SRTP_PROTECTION_PROFILE_freefunc_type(freefunc))
#define sk_SRTP_PROTECTION_PROFILE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr), (idx))
#define sk_SRTP_PROTECTION_PROFILE_set(sk, idx, ptr) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_set(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), (idx), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr)))
#define sk_SRTP_PROTECTION_PROFILE_find(sk, ptr) OPENSSL_sk_find(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr), pnum)
#define sk_SRTP_PROTECTION_PROFILE_sort(sk) OPENSSL_sk_sort(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_dup(sk) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_dup(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk)))
#define sk_SRTP_PROTECTION_PROFILE_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_deep_copy(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_copyfunc_type(copyfunc), ossl_check_SRTP_PROTECTION_PROFILE_freefunc_type(freefunc)))
#define sk_SRTP_PROTECTION_PROFILE_set_cmp_func(sk, cmp) ((sk_SRTP_PROTECTION_PROFILE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_compfunc_type(cmp)))



typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data,
                                            int len, void *arg);
typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len,
                                        STACK_OF(SSL_CIPHER) *peer_ciphers,
                                        const SSL_CIPHER **cipher, void *arg);

/* Extension context codes */
/* This extension is only allowed in TLS */
#define SSL_EXT_TLS_ONLY                        0x0001
/* This extension is only allowed in DTLS */
#define SSL_EXT_DTLS_ONLY                       0x0002
/* Some extensions may be allowed in DTLS but we don't implement them for it */
#define SSL_EXT_TLS_IMPLEMENTATION_ONLY         0x0004
/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */
#define SSL_EXT_SSL3_ALLOWED                    0x0008
/* Extension is only defined for TLS1.2 and below */
#define SSL_EXT_TLS1_2_AND_BELOW_ONLY           0x0010
/* Extension is only defined for TLS1.3 and above */
#define SSL_EXT_TLS1_3_ONLY                     0x0020
/* Ignore this extension during parsing if we are resuming */
#define SSL_EXT_IGNORE_ON_RESUMPTION            0x0040
#define SSL_EXT_CLIENT_HELLO                    0x0080
/* Really means TLS1.2 or below */
#define SSL_EXT_TLS1_2_SERVER_HELLO             0x0100
#define SSL_EXT_TLS1_3_SERVER_HELLO             0x0200
#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS     0x0400
#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST      0x0800
#define SSL_EXT_TLS1_3_CERTIFICATE              0x1000
#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET       0x2000
#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST      0x4000

/* Typedefs for handling custom extensions */

typedef int (*custom_ext_add_cb)(SSL *s, unsigned int ext_type,
                                 const unsigned char **out, size_t *outlen,
                                 int *al, void *add_arg);

typedef void (*custom_ext_free_cb)(SSL *s, unsigned int ext_type,
                                   const unsigned char *out, void *add_arg);

typedef int (*custom_ext_parse_cb)(SSL *s, unsigned int ext_type,
                                   const unsigned char *in, size_t inlen,
                                   int *al, void *parse_arg);


typedef int (*SSL_custom_ext_add_cb_ex)(SSL *s, unsigned int ext_type,
                                        unsigned int context,
                                        const unsigned char **out,
                                        size_t *outlen, X509 *x,
                                        size_t chainidx,
                                        int *al, void *add_arg);

typedef void (*SSL_custom_ext_free_cb_ex)(SSL *s, unsigned int ext_type,
                                          unsigned int context,
                                          const unsigned char *out,
                                          void *add_arg);

typedef int (*SSL_custom_ext_parse_cb_ex)(SSL *s, unsigned int ext_type,
                                          unsigned int context,
                                          const unsigned char *in,
                                          size_t inlen, X509 *x,
                                          size_t chainidx,
                                          int *al, void *parse_arg);

/* Typedef for verification callback */
typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);

/* Typedef for SSL async callback */
typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);

#define SSL_OP_BIT(n)  ((uint64_t)1 << (uint64_t)n)

/*
 * SSL/TLS connection options.
 */
    /* Disable Extended master secret */
# define SSL_OP_NO_EXTENDED_MASTER_SECRET                SSL_OP_BIT(0)
    /* Cleanse plaintext copies of data delivered to the application */
# define SSL_OP_CLEANSE_PLAINTEXT                        SSL_OP_BIT(1)
    /* Allow initial connection to servers that don't support RI */
# define SSL_OP_LEGACY_SERVER_CONNECT                    SSL_OP_BIT(2)
    /* Enable support for Kernel TLS */
# define SSL_OP_ENABLE_KTLS                              SSL_OP_BIT(3)
# define SSL_OP_TLSEXT_PADDING                           SSL_OP_BIT(4)
# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG                   SSL_OP_BIT(6)
# define SSL_OP_IGNORE_UNEXPECTED_EOF                    SSL_OP_BIT(7)
# define SSL_OP_ALLOW_CLIENT_RENEGOTIATION               SSL_OP_BIT(8)
# define SSL_OP_DISABLE_TLSEXT_CA_NAMES                  SSL_OP_BIT(9)
    /* In TLSv1.3 allow a non-(ec)dhe based kex_mode */
# define SSL_OP_ALLOW_NO_DHE_KEX                         SSL_OP_BIT(10)
    /*
     * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
     * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
     * the workaround is not needed.  Unfortunately some broken SSL/TLS
     * implementations cannot handle it at all, which is why we include it
     * in SSL_OP_ALL. Added in 0.9.6e
     */
# define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              SSL_OP_BIT(11)
    /* DTLS options */
# define SSL_OP_NO_QUERY_MTU                             SSL_OP_BIT(12)
    /* Turn on Cookie Exchange (on relevant for servers) */
# define SSL_OP_COOKIE_EXCHANGE                          SSL_OP_BIT(13)
    /* Don't use RFC4507 ticket extension */
# define SSL_OP_NO_TICKET                                SSL_OP_BIT(14)
# ifndef OPENSSL_NO_DTLS1_METHOD
    /*
     * Use Cisco's version identifier of DTLS_BAD_VER
     * (only with deprecated DTLSv1_client_method())
     */
#  define SSL_OP_CISCO_ANYCONNECT                        SSL_OP_BIT(15)
# endif
    /* As server, disallow session resumption on renegotiation */
# define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION   SSL_OP_BIT(16)
    /* Don't use compression even if supported */
# define SSL_OP_NO_COMPRESSION                           SSL_OP_BIT(17)
    /* Permit unsafe legacy renegotiation */
# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION        SSL_OP_BIT(18)
    /* Disable encrypt-then-mac */
# define SSL_OP_NO_ENCRYPT_THEN_MAC                      SSL_OP_BIT(19)
    /*
     * Enable TLSv1.3 Compatibility mode. This is on by default. A future
     * version of OpenSSL may have this disabled by default.
     */
# define SSL_OP_ENABLE_MIDDLEBOX_COMPAT                  SSL_OP_BIT(20)
    /*
     * Prioritize Chacha20Poly1305 when client does.
     * Modifies SSL_OP_CIPHER_SERVER_PREFERENCE
     */
# define SSL_OP_PRIORITIZE_CHACHA                        SSL_OP_BIT(21)
    /*
     * Set on servers to choose the cipher according to server's preferences.
     */
# define SSL_OP_CIPHER_SERVER_PREFERENCE                 SSL_OP_BIT(22)
    /*
     * If set, a server will allow a client to issue a SSLv3.0 version
     * number as latest version supported in the premaster secret, even when
     * TLSv1.0 (version 3.1) was announced in the client hello. Normally
     * this is forbidden to prevent version rollback attacks.
     */
# define SSL_OP_TLS_ROLLBACK_BUG                         SSL_OP_BIT(23)
    /*
     * Switches off automatic TLSv1.3 anti-replay protection for early data.
     * This is a server-side option only (no effect on the client).
     */
# define SSL_OP_NO_ANTI_REPLAY                           SSL_OP_BIT(24)
# define SSL_OP_NO_SSLv3                                 SSL_OP_BIT(25)
# define SSL_OP_NO_TLSv1                                 SSL_OP_BIT(26)
# define SSL_OP_NO_TLSv1_2                               SSL_OP_BIT(27)
# define SSL_OP_NO_TLSv1_1                               SSL_OP_BIT(28)
# define SSL_OP_NO_TLSv1_3                               SSL_OP_BIT(29)
# define SSL_OP_NO_DTLSv1                                SSL_OP_BIT(26)
# define SSL_OP_NO_DTLSv1_2                              SSL_OP_BIT(27)
    /* Disallow all renegotiation */
# define SSL_OP_NO_RENEGOTIATION                         SSL_OP_BIT(30)
    /*
     * Make server add server-hello extension from early version of
     * cryptopro draft, when GOST ciphersuite is negotiated. Required for
     * interoperability with CryptoPro CSP 3.x
     */
# define SSL_OP_CRYPTOPRO_TLSEXT_BUG                     SSL_OP_BIT(31)

/*
 * Option "collections."
 */
# define SSL_OP_NO_SSL_MASK \
        ( SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 \
          | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3 )
# define SSL_OP_NO_DTLS_MASK \
        ( SSL_OP_NO_DTLSv1 | SSL_OP_NO_DTLSv1_2 )

/* Various bug workarounds that should be rather harmless. */
# define SSL_OP_ALL \
        ( SSL_OP_CRYPTOPRO_TLSEXT_BUG | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS \
          | SSL_OP_TLSEXT_PADDING | SSL_OP_SAFARI_ECDHE_ECDSA_BUG )

/*
 * OBSOLETE OPTIONS retained for compatibility
 */

# define SSL_OP_MICROSOFT_SESS_ID_BUG                    0x0
# define SSL_OP_NETSCAPE_CHALLENGE_BUG                   0x0
# define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG         0x0
# define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG              0x0
# define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER               0x0
# define SSL_OP_MSIE_SSLV2_RSA_PADDING                   0x0
# define SSL_OP_SSLEAY_080_CLIENT_DH_BUG                 0x0
# define SSL_OP_TLS_D5_BUG                               0x0
# define SSL_OP_TLS_BLOCK_PADDING_BUG                    0x0
# define SSL_OP_SINGLE_ECDH_USE                          0x0
# define SSL_OP_SINGLE_DH_USE                            0x0
# define SSL_OP_EPHEMERAL_RSA                            0x0
# define SSL_OP_NO_SSLv2                                 0x0
# define SSL_OP_PKCS1_CHECK_1                            0x0
# define SSL_OP_PKCS1_CHECK_2                            0x0
# define SSL_OP_NETSCAPE_CA_DN_BUG                       0x0
# define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG          0x0

/*
 * Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
 * when just a single record has been written):
 */
# define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001U
/*
 * Make it possible to retry SSL_write() with changed buffer location (buffer
 * contents must stay the same!); this is not the default to avoid the
 * misconception that non-blocking SSL_write() behaves like non-blocking
 * write():
 */
# define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002U
/*
 * Never bother the application with retries if the transport is blocking:
 */
# define SSL_MODE_AUTO_RETRY 0x00000004U
/* Don't attempt to automatically build certificate chain */
# define SSL_MODE_NO_AUTO_CHAIN 0x00000008U
/*
 * Save RAM by releasing read and write buffers when they're empty. (SSL3 and
 * TLS only.) Released buffers are freed.
 */
# define SSL_MODE_RELEASE_BUFFERS 0x00000010U
/*
 * Send the current time in the Random fields of the ClientHello and
 * ServerHello records for compatibility with hypothetical implementations
 * that require it.
 */
# define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020U
# define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040U
/*
 * Send TLS_FALLBACK_SCSV in the ClientHello. To be set only by applications
 * that reconnect with a downgraded protocol version; see
 * draft-ietf-tls-downgrade-scsv-00 for details. DO NOT ENABLE THIS if your
 * application attempts a normal handshake. Only use this in explicit
 * fallback retries, following the guidance in
 * draft-ietf-tls-downgrade-scsv-00.
 */
# define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080U
/*
 * Support Asynchronous operation
 */
# define SSL_MODE_ASYNC 0x00000100U

/*
 * When using DTLS/SCTP, include the terminating zero in the label
 * used for computing the endpoint-pair shared secret. Required for
 * interoperability with implementations having this bug like these
 * older version of OpenSSL:
 * - OpenSSL 1.0.0 series
 * - OpenSSL 1.0.1 series
 * - OpenSSL 1.0.2 series
 * - OpenSSL 1.1.0 series
 * - OpenSSL 1.1.1 and 1.1.1a
 */
# define SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG 0x00000400U

/* Cert related flags */
/*
 * Many implementations ignore some aspects of the TLS standards such as
 * enforcing certificate chain algorithms. When this is set we enforce them.
 */
# define SSL_CERT_FLAG_TLS_STRICT                0x00000001U

/* Suite B modes, takes same values as certificate verify flags */
# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY       0x10000
/* Suite B 192 bit only mode */
# define SSL_CERT_FLAG_SUITEB_192_LOS            0x20000
/* Suite B 128 bit mode allowing 192 bit algorithms */
# define SSL_CERT_FLAG_SUITEB_128_LOS            0x30000

/* Perform all sorts of protocol violations for testing purposes */
# define SSL_CERT_FLAG_BROKEN_PROTOCOL           0x10000000

/* Flags for building certificate chains */
/* Treat any existing certificates as untrusted CAs */
# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED          0x1
/* Don't include root CA in chain */
# define SSL_BUILD_CHAIN_FLAG_NO_ROOT            0x2
/* Just check certificates already there */
# define SSL_BUILD_CHAIN_FLAG_CHECK              0x4
/* Ignore verification errors */
# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR       0x8
/* Clear verification errors from queue */
# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR        0x10

/* Flags returned by SSL_check_chain */
/* Certificate can be used with this session */
# define CERT_PKEY_VALID         0x1
/* Certificate can also be used for signing */
# define CERT_PKEY_SIGN          0x2
/* EE certificate signing algorithm OK */
# define CERT_PKEY_EE_SIGNATURE  0x10
/* CA signature algorithms OK */
# define CERT_PKEY_CA_SIGNATURE  0x20
/* EE certificate parameters OK */
# define CERT_PKEY_EE_PARAM      0x40
/* CA certificate parameters OK */
# define CERT_PKEY_CA_PARAM      0x80
/* Signing explicitly allowed as opposed to SHA1 fallback */
# define CERT_PKEY_EXPLICIT_SIGN 0x100
/* Client CA issuer names match (always set for server cert) */
# define CERT_PKEY_ISSUER_NAME   0x200
/* Cert type matches client types (always set for server cert) */
# define CERT_PKEY_CERT_TYPE     0x400
/* Cert chain suitable to Suite B */
# define CERT_PKEY_SUITEB        0x800

# define SSL_CONF_FLAG_CMDLINE           0x1
# define SSL_CONF_FLAG_FILE              0x2
# define SSL_CONF_FLAG_CLIENT            0x4
# define SSL_CONF_FLAG_SERVER            0x8
# define SSL_CONF_FLAG_SHOW_ERRORS       0x10
# define SSL_CONF_FLAG_CERTIFICATE       0x20
# define SSL_CONF_FLAG_REQUIRE_PRIVATE   0x40
/* Configuration value types */
# define SSL_CONF_TYPE_UNKNOWN           0x0
# define SSL_CONF_TYPE_STRING            0x1
# define SSL_CONF_TYPE_FILE              0x2
# define SSL_CONF_TYPE_DIR               0x3
# define SSL_CONF_TYPE_NONE              0x4
# define SSL_CONF_TYPE_STORE             0x5

/* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */
# define SSL_COOKIE_LENGTH                       4096

/*
 * Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they
 * cannot be used to clear bits.
 */

uint64_t SSL_CTX_get_options(const SSL_CTX *ctx);
uint64_t SSL_get_options(const SSL *s);
uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op);
uint64_t SSL_clear_options(SSL *s, uint64_t op);
uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op);
uint64_t SSL_set_options(SSL *s, uint64_t op);

# define SSL_CTX_set_mode(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
# define SSL_CTX_clear_mode(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
# define SSL_CTX_get_mode(ctx) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
# define SSL_clear_mode(ssl,op) \
        SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
# define SSL_set_mode(ssl,op) \
        SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
# define SSL_get_mode(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
# define SSL_set_mtu(ssl, mtu) \
        SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
# define DTLS_set_link_mtu(ssl, mtu) \
        SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL)
# define DTLS_get_link_min_mtu(ssl) \
        SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL)

# define SSL_get_secure_renegotiation_support(ssl) \
        SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)

# define SSL_CTX_set_cert_flags(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL)
# define SSL_set_cert_flags(s,op) \
        SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL)
# define SSL_CTX_clear_cert_flags(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
# define SSL_clear_cert_flags(s,op) \
        SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)

void SSL_CTX_set_msg_callback(SSL_CTX *ctx,
                              void (*cb) (int write_p, int version,
                                          int content_type, const void *buf,
                                          size_t len, SSL *ssl, void *arg));
void SSL_set_msg_callback(SSL *ssl,
                          void (*cb) (int write_p, int version,
                                      int content_type, const void *buf,
                                      size_t len, SSL *ssl, void *arg));
# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))

# define SSL_get_extms_support(s) \
        SSL_ctrl((s),SSL_CTRL_GET_EXTMS_SUPPORT,0,NULL)

# ifndef OPENSSL_NO_SRP
/* see tls_srp.c */
#  ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 __owur int SSL_SRP_CTX_init(SSL *s);
OSSL_DEPRECATEDIN_3_0 __owur int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx);
OSSL_DEPRECATEDIN_3_0 int SSL_SRP_CTX_free(SSL *ctx);
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx);
OSSL_DEPRECATEDIN_3_0 __owur int SSL_srp_server_param_with_username(SSL *s,
                                                                    int *ad);
OSSL_DEPRECATEDIN_3_0 __owur int SRP_Calc_A_param(SSL *s);
#  endif
# endif

/* 100k max cert list */
# define SSL_MAX_CERT_LIST_DEFAULT (1024*100)

# define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT      (1024*20)

/*
 * This callback type is used inside SSL_CTX, SSL, and in the functions that
 * set them. It is used to override the generation of SSL/TLS session IDs in
 * a server. Return value should be zero on an error, non-zero to proceed.
 * Also, callbacks should themselves check if the id they generate is unique
 * otherwise the SSL handshake will fail with an error - callbacks can do
 * this using the 'ssl' value they're passed by;
 * SSL_has_matching_session_id(ssl, id, *id_len) The length value passed in
 * is set at the maximum size the session ID can be. In SSLv3/TLSv1 it is 32
 * bytes. The callback can alter this length to be less if desired. It is
 * also an error for the callback to set the size to zero.
 */
typedef int (*GEN_SESSION_CB) (SSL *ssl, unsigned char *id,
                               unsigned int *id_len);

# define SSL_SESS_CACHE_OFF                      0x0000
# define SSL_SESS_CACHE_CLIENT                   0x0001
# define SSL_SESS_CACHE_SERVER                   0x0002
# define SSL_SESS_CACHE_BOTH     (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
# define SSL_SESS_CACHE_NO_AUTO_CLEAR            0x0080
/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
# define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP       0x0100
# define SSL_SESS_CACHE_NO_INTERNAL_STORE        0x0200
# define SSL_SESS_CACHE_NO_INTERNAL \
        (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
# define SSL_SESS_CACHE_UPDATE_TIME              0x0400

LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
# define SSL_CTX_sess_number(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
# define SSL_CTX_sess_connect(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
# define SSL_CTX_sess_connect_good(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
# define SSL_CTX_sess_connect_renegotiate(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
# define SSL_CTX_sess_accept(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
# define SSL_CTX_sess_accept_renegotiate(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
# define SSL_CTX_sess_accept_good(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
# define SSL_CTX_sess_hits(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
# define SSL_CTX_sess_cb_hits(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
# define SSL_CTX_sess_misses(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
# define SSL_CTX_sess_timeouts(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
# define SSL_CTX_sess_cache_full(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)

void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
                             int (*new_session_cb) (struct ssl_st *ssl,
                                                    SSL_SESSION *sess));
int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
                                              SSL_SESSION *sess);
void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
                                void (*remove_session_cb) (struct ssl_ctx_st
                                                           *ctx,
                                                           SSL_SESSION *sess));
void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (struct ssl_ctx_st *ctx,
                                                  SSL_SESSION *sess);
void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
                             SSL_SESSION *(*get_session_cb) (struct ssl_st
                                                             *ssl,
                                                             const unsigned char
                                                             *data, int len,
                                                             int *copy));
SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
                                                       const unsigned char *data,
                                                       int len, int *copy);
void SSL_CTX_set_info_callback(SSL_CTX *ctx,
                               void (*cb) (const SSL *ssl, int type, int val));
void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type,
                                                 int val);
void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
                                int (*client_cert_cb) (SSL *ssl, X509 **x509,
                                                       EVP_PKEY **pkey));
int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
                                                 EVP_PKEY **pkey);
# ifndef OPENSSL_NO_ENGINE
__owur int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
# endif
void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
                                    int (*app_gen_cookie_cb) (SSL *ssl,
                                                              unsigned char
                                                              *cookie,
                                                              unsigned int
                                                              *cookie_len));
void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
                                  int (*app_verify_cookie_cb) (SSL *ssl,
                                                               const unsigned
                                                               char *cookie,
                                                               unsigned int
                                                               cookie_len));

void SSL_CTX_set_stateless_cookie_generate_cb(
    SSL_CTX *ctx,
    int (*gen_stateless_cookie_cb) (SSL *ssl,
                                    unsigned char *cookie,
                                    size_t *cookie_len));
void SSL_CTX_set_stateless_cookie_verify_cb(
    SSL_CTX *ctx,
    int (*verify_stateless_cookie_cb) (SSL *ssl,
                                       const unsigned char *cookie,
                                       size_t cookie_len));
# ifndef OPENSSL_NO_NEXTPROTONEG

typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl,
                                              const unsigned char **out,
                                              unsigned int *outlen,
                                              void *arg);
void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s,
                                           SSL_CTX_npn_advertised_cb_func cb,
                                           void *arg);
#  define SSL_CTX_set_npn_advertised_cb SSL_CTX_set_next_protos_advertised_cb

typedef int (*SSL_CTX_npn_select_cb_func)(SSL *s,
                                          unsigned char **out,
                                          unsigned char *outlen,
                                          const unsigned char *in,
                                          unsigned int inlen,
                                          void *arg);
void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
                                      SSL_CTX_npn_select_cb_func cb,
                                      void *arg);
#  define SSL_CTX_set_npn_select_cb SSL_CTX_set_next_proto_select_cb

void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
                                    unsigned *len);
#  define SSL_get0_npn_negotiated SSL_get0_next_proto_negotiated
# endif

__owur int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
                                 const unsigned char *in, unsigned int inlen,
                                 const unsigned char *client,
                                 unsigned int client_len);

# define OPENSSL_NPN_UNSUPPORTED 0
# define OPENSSL_NPN_NEGOTIATED  1
# define OPENSSL_NPN_NO_OVERLAP  2

__owur int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
                                   unsigned int protos_len);
__owur int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
                               unsigned int protos_len);
typedef int (*SSL_CTX_alpn_select_cb_func)(SSL *ssl,
                                           const unsigned char **out,
                                           unsigned char *outlen,
                                           const unsigned char *in,
                                           unsigned int inlen,
                                           void *arg);
void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
                                SSL_CTX_alpn_select_cb_func cb,
                                void *arg);
void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
                            unsigned int *len);

# ifndef OPENSSL_NO_PSK
/*
 * the maximum length of the buffer given to callbacks containing the
 * resulting identity/psk
 */
#  define PSK_MAX_IDENTITY_LEN 256
#  define PSK_MAX_PSK_LEN 512
typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl,
                                               const char *hint,
                                               char *identity,
                                               unsigned int max_identity_len,
                                               unsigned char *psk,
                                               unsigned int max_psk_len);
void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb);
void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb);

typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl,
                                               const char *identity,
                                               unsigned char *psk,
                                               unsigned int max_psk_len);
void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb);
void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb);

__owur int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
__owur int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
const char *SSL_get_psk_identity_hint(const SSL *s);
const char *SSL_get_psk_identity(const SSL *s);
# endif

typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl,
                                            const unsigned char *identity,
                                            size_t identity_len,
                                            SSL_SESSION **sess);
typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md,
                                           const unsigned char **id,
                                           size_t *idlen,
                                           SSL_SESSION **sess);

void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb);
void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx,
                                           SSL_psk_find_session_cb_func cb);
void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb);
void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx,
                                          SSL_psk_use_session_cb_func cb);

/* Register callbacks to handle custom TLS Extensions for client or server. */

__owur int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx,
                                         unsigned int ext_type);

__owur int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx,
                                         unsigned int ext_type,
                                         custom_ext_add_cb add_cb,
                                         custom_ext_free_cb free_cb,
                                         void *add_arg,
                                         custom_ext_parse_cb parse_cb,
                                         void *parse_arg);

__owur int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx,
                                         unsigned int ext_type,
                                         custom_ext_add_cb add_cb,
                                         custom_ext_free_cb free_cb,
                                         void *add_arg,
                                         custom_ext_parse_cb parse_cb,
                                         void *parse_arg);

__owur int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
                                  unsigned int context,
                                  SSL_custom_ext_add_cb_ex add_cb,
                                  SSL_custom_ext_free_cb_ex free_cb,
                                  void *add_arg,
                                  SSL_custom_ext_parse_cb_ex parse_cb,
                                  void *parse_arg);

__owur int SSL_extension_supported(unsigned int ext_type);

# define SSL_NOTHING            1
# define SSL_WRITING            2
# define SSL_READING            3
# define SSL_X509_LOOKUP        4
# define SSL_ASYNC_PAUSED       5
# define SSL_ASYNC_NO_JOBS      6
# define SSL_CLIENT_HELLO_CB    7
# define SSL_RETRY_VERIFY       8

/* These will only be used when doing non-blocking IO */
# define SSL_want_nothing(s)         (SSL_want(s) == SSL_NOTHING)
# define SSL_want_read(s)            (SSL_want(s) == SSL_READING)
# define SSL_want_write(s)           (SSL_want(s) == SSL_WRITING)
# define SSL_want_x509_lookup(s)     (SSL_want(s) == SSL_X509_LOOKUP)
# define SSL_want_retry_verify(s)    (SSL_want(s) == SSL_RETRY_VERIFY)
# define SSL_want_async(s)           (SSL_want(s) == SSL_ASYNC_PAUSED)
# define SSL_want_async_job(s)       (SSL_want(s) == SSL_ASYNC_NO_JOBS)
# define SSL_want_client_hello_cb(s) (SSL_want(s) == SSL_CLIENT_HELLO_CB)

# define SSL_MAC_FLAG_READ_MAC_STREAM 1
# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
# define SSL_MAC_FLAG_READ_MAC_TLSTREE 4
# define SSL_MAC_FLAG_WRITE_MAC_TLSTREE 8

/*
 * A callback for logging out TLS key material. This callback should log out
 * |line| followed by a newline.
 */
typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line);

/*
 * SSL_CTX_set_keylog_callback configures a callback to log key material. This
 * is intended for debugging use with tools like Wireshark. The cb function
 * should log line followed by a newline.
 */
void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb);

/*
 * SSL_CTX_get_keylog_callback returns the callback configured by
 * SSL_CTX_set_keylog_callback.
 */
SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx);

int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data);
uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
uint32_t SSL_get_max_early_data(const SSL *s);
int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data);
uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx);
int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data);
uint32_t SSL_get_recv_max_early_data(const SSL *s);

#ifdef __cplusplus
}
#endif

# include <openssl/ssl2.h>
# include <openssl/ssl3.h>
# include <openssl/tls1.h>      /* This is mostly sslv3 with a few tweaks */
# include <openssl/dtls1.h>     /* Datagram TLS */
# include <openssl/srtp.h>      /* Support for the use_srtp extension */

#ifdef  __cplusplus
extern "C" {
#endif

/*
 * These need to be after the above set of includes due to a compiler bug
 * in VisualStudio 2015
 */
SKM_DEFINE_STACK_OF_INTERNAL(SSL_CIPHER, const SSL_CIPHER, SSL_CIPHER)
#define sk_SSL_CIPHER_num(sk) OPENSSL_sk_num(ossl_check_const_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_value(sk, idx) ((const SSL_CIPHER *)OPENSSL_sk_value(ossl_check_const_SSL_CIPHER_sk_type(sk), (idx)))
#define sk_SSL_CIPHER_new(cmp) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_new(ossl_check_SSL_CIPHER_compfunc_type(cmp)))
#define sk_SSL_CIPHER_new_null() ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_new_null())
#define sk_SSL_CIPHER_new_reserve(cmp, n) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_new_reserve(ossl_check_SSL_CIPHER_compfunc_type(cmp), (n)))
#define sk_SSL_CIPHER_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_SSL_CIPHER_sk_type(sk), (n))
#define sk_SSL_CIPHER_free(sk) OPENSSL_sk_free(ossl_check_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_zero(sk) OPENSSL_sk_zero(ossl_check_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_delete(sk, i) ((const SSL_CIPHER *)OPENSSL_sk_delete(ossl_check_SSL_CIPHER_sk_type(sk), (i)))
#define sk_SSL_CIPHER_delete_ptr(sk, ptr) ((const SSL_CIPHER *)OPENSSL_sk_delete_ptr(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr)))
#define sk_SSL_CIPHER_push(sk, ptr) OPENSSL_sk_push(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_pop(sk) ((const SSL_CIPHER *)OPENSSL_sk_pop(ossl_check_SSL_CIPHER_sk_type(sk)))
#define sk_SSL_CIPHER_shift(sk) ((const SSL_CIPHER *)OPENSSL_sk_shift(ossl_check_SSL_CIPHER_sk_type(sk)))
#define sk_SSL_CIPHER_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SSL_CIPHER_sk_type(sk),ossl_check_SSL_CIPHER_freefunc_type(freefunc))
#define sk_SSL_CIPHER_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr), (idx))
#define sk_SSL_CIPHER_set(sk, idx, ptr) ((const SSL_CIPHER *)OPENSSL_sk_set(ossl_check_SSL_CIPHER_sk_type(sk), (idx), ossl_check_SSL_CIPHER_type(ptr)))
#define sk_SSL_CIPHER_find(sk, ptr) OPENSSL_sk_find(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr), pnum)
#define sk_SSL_CIPHER_sort(sk) OPENSSL_sk_sort(ossl_check_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_dup(sk) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_dup(ossl_check_const_SSL_CIPHER_sk_type(sk)))
#define sk_SSL_CIPHER_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_deep_copy(ossl_check_const_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_copyfunc_type(copyfunc), ossl_check_SSL_CIPHER_freefunc_type(freefunc)))
#define sk_SSL_CIPHER_set_cmp_func(sk, cmp) ((sk_SSL_CIPHER_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_compfunc_type(cmp)))
SKM_DEFINE_STACK_OF_INTERNAL(SSL_COMP, SSL_COMP, SSL_COMP)
#define sk_SSL_COMP_num(sk) OPENSSL_sk_num(ossl_check_const_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_value(sk, idx) ((SSL_COMP *)OPENSSL_sk_value(ossl_check_const_SSL_COMP_sk_type(sk), (idx)))
#define sk_SSL_COMP_new(cmp) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_new(ossl_check_SSL_COMP_compfunc_type(cmp)))
#define sk_SSL_COMP_new_null() ((STACK_OF(SSL_COMP) *)OPENSSL_sk_new_null())
#define sk_SSL_COMP_new_reserve(cmp, n) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_new_reserve(ossl_check_SSL_COMP_compfunc_type(cmp), (n)))
#define sk_SSL_COMP_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_SSL_COMP_sk_type(sk), (n))
#define sk_SSL_COMP_free(sk) OPENSSL_sk_free(ossl_check_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_zero(sk) OPENSSL_sk_zero(ossl_check_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_delete(sk, i) ((SSL_COMP *)OPENSSL_sk_delete(ossl_check_SSL_COMP_sk_type(sk), (i)))
#define sk_SSL_COMP_delete_ptr(sk, ptr) ((SSL_COMP *)OPENSSL_sk_delete_ptr(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr)))
#define sk_SSL_COMP_push(sk, ptr) OPENSSL_sk_push(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_pop(sk) ((SSL_COMP *)OPENSSL_sk_pop(ossl_check_SSL_COMP_sk_type(sk)))
#define sk_SSL_COMP_shift(sk) ((SSL_COMP *)OPENSSL_sk_shift(ossl_check_SSL_COMP_sk_type(sk)))
#define sk_SSL_COMP_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SSL_COMP_sk_type(sk),ossl_check_SSL_COMP_freefunc_type(freefunc))
#define sk_SSL_COMP_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr), (idx))
#define sk_SSL_COMP_set(sk, idx, ptr) ((SSL_COMP *)OPENSSL_sk_set(ossl_check_SSL_COMP_sk_type(sk), (idx), ossl_check_SSL_COMP_type(ptr)))
#define sk_SSL_COMP_find(sk, ptr) OPENSSL_sk_find(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr), pnum)
#define sk_SSL_COMP_sort(sk) OPENSSL_sk_sort(ossl_check_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_dup(sk) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_dup(ossl_check_const_SSL_COMP_sk_type(sk)))
#define sk_SSL_COMP_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_deep_copy(ossl_check_const_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_copyfunc_type(copyfunc), ossl_check_SSL_COMP_freefunc_type(freefunc)))
#define sk_SSL_COMP_set_cmp_func(sk, cmp) ((sk_SSL_COMP_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_compfunc_type(cmp)))


/* compatibility */
# define SSL_set_app_data(s,arg)         (SSL_set_ex_data(s,0,(char *)(arg)))
# define SSL_get_app_data(s)             (SSL_get_ex_data(s,0))
# define SSL_SESSION_set_app_data(s,a)   (SSL_SESSION_set_ex_data(s,0, \
                                                                  (char *)(a)))
# define SSL_SESSION_get_app_data(s)     (SSL_SESSION_get_ex_data(s,0))
# define SSL_CTX_get_app_data(ctx)       (SSL_CTX_get_ex_data(ctx,0))
# define SSL_CTX_set_app_data(ctx,arg)   (SSL_CTX_set_ex_data(ctx,0, \
                                                              (char *)(arg)))
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 void SSL_set_debug(SSL *s, int debug);
# endif

/* TLSv1.3 KeyUpdate message types */
/* -1 used so that this is an invalid value for the on-the-wire protocol */
#define SSL_KEY_UPDATE_NONE             -1
/* Values as defined for the on-the-wire protocol */
#define SSL_KEY_UPDATE_NOT_REQUESTED     0
#define SSL_KEY_UPDATE_REQUESTED         1

/*
 * The valid handshake states (one for each type message sent and one for each
 * type of message received). There are also two "special" states:
 * TLS = TLS or DTLS state
 * DTLS = DTLS specific state
 * CR/SR = Client Read/Server Read
 * CW/SW = Client Write/Server Write
 *
 * The "special" states are:
 * TLS_ST_BEFORE = No handshake has been initiated yet
 * TLS_ST_OK = A handshake has been successfully completed
 */
typedef enum {
    TLS_ST_BEFORE,
    TLS_ST_OK,
    DTLS_ST_CR_HELLO_VERIFY_REQUEST,
    TLS_ST_CR_SRVR_HELLO,
    TLS_ST_CR_CERT,
    TLS_ST_CR_CERT_STATUS,
    TLS_ST_CR_KEY_EXCH,
    TLS_ST_CR_CERT_REQ,
    TLS_ST_CR_SRVR_DONE,
    TLS_ST_CR_SESSION_TICKET,
    TLS_ST_CR_CHANGE,
    TLS_ST_CR_FINISHED,
    TLS_ST_CW_CLNT_HELLO,
    TLS_ST_CW_CERT,
    TLS_ST_CW_KEY_EXCH,
    TLS_ST_CW_CERT_VRFY,
    TLS_ST_CW_CHANGE,
    TLS_ST_CW_NEXT_PROTO,
    TLS_ST_CW_FINISHED,
    TLS_ST_SW_HELLO_REQ,
    TLS_ST_SR_CLNT_HELLO,
    DTLS_ST_SW_HELLO_VERIFY_REQUEST,
    TLS_ST_SW_SRVR_HELLO,
    TLS_ST_SW_CERT,
    TLS_ST_SW_KEY_EXCH,
    TLS_ST_SW_CERT_REQ,
    TLS_ST_SW_SRVR_DONE,
    TLS_ST_SR_CERT,
    TLS_ST_SR_KEY_EXCH,
    TLS_ST_SR_CERT_VRFY,
    TLS_ST_SR_NEXT_PROTO,
    TLS_ST_SR_CHANGE,
    TLS_ST_SR_FINISHED,
    TLS_ST_SW_SESSION_TICKET,
    TLS_ST_SW_CERT_STATUS,
    TLS_ST_SW_CHANGE,
    TLS_ST_SW_FINISHED,
    TLS_ST_SW_ENCRYPTED_EXTENSIONS,
    TLS_ST_CR_ENCRYPTED_EXTENSIONS,
    TLS_ST_CR_CERT_VRFY,
    TLS_ST_SW_CERT_VRFY,
    TLS_ST_CR_HELLO_REQ,
    TLS_ST_SW_KEY_UPDATE,
    TLS_ST_CW_KEY_UPDATE,
    TLS_ST_SR_KEY_UPDATE,
    TLS_ST_CR_KEY_UPDATE,
    TLS_ST_EARLY_DATA,
    TLS_ST_PENDING_EARLY_DATA_END,
    TLS_ST_CW_END_OF_EARLY_DATA,
    TLS_ST_SR_END_OF_EARLY_DATA
} OSSL_HANDSHAKE_STATE;

/*
 * Most of the following state values are no longer used and are defined to be
 * the closest equivalent value in the current state machine code. Not all
 * defines have an equivalent and are set to a dummy value (-1). SSL_ST_CONNECT
 * and SSL_ST_ACCEPT are still in use in the definition of SSL_CB_ACCEPT_LOOP,
 * SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP and SSL_CB_CONNECT_EXIT.
 */

# define SSL_ST_CONNECT                  0x1000
# define SSL_ST_ACCEPT                   0x2000

# define SSL_ST_MASK                     0x0FFF

# define SSL_CB_LOOP                     0x01
# define SSL_CB_EXIT                     0x02
# define SSL_CB_READ                     0x04
# define SSL_CB_WRITE                    0x08
# define SSL_CB_ALERT                    0x4000/* used in callback */
# define SSL_CB_READ_ALERT               (SSL_CB_ALERT|SSL_CB_READ)
# define SSL_CB_WRITE_ALERT              (SSL_CB_ALERT|SSL_CB_WRITE)
# define SSL_CB_ACCEPT_LOOP              (SSL_ST_ACCEPT|SSL_CB_LOOP)
# define SSL_CB_ACCEPT_EXIT              (SSL_ST_ACCEPT|SSL_CB_EXIT)
# define SSL_CB_CONNECT_LOOP             (SSL_ST_CONNECT|SSL_CB_LOOP)
# define SSL_CB_CONNECT_EXIT             (SSL_ST_CONNECT|SSL_CB_EXIT)
# define SSL_CB_HANDSHAKE_START          0x10
# define SSL_CB_HANDSHAKE_DONE           0x20

/* Is the SSL_connection established? */
# define SSL_in_connect_init(a)          (SSL_in_init(a) && !SSL_is_server(a))
# define SSL_in_accept_init(a)           (SSL_in_init(a) && SSL_is_server(a))
int SSL_in_init(const SSL *s);
int SSL_in_before(const SSL *s);
int SSL_is_init_finished(const SSL *s);

/*
 * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you
 * should not need these
 */
# define SSL_ST_READ_HEADER                      0xF0
# define SSL_ST_READ_BODY                        0xF1
# define SSL_ST_READ_DONE                        0xF2

/*-
 * Obtain latest Finished message
 *   -- that we sent (SSL_get_finished)
 *   -- that we expected from peer (SSL_get_peer_finished).
 * Returns length (0 == no Finished so far), copies up to 'count' bytes.
 */
size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);

/*
 * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options are
 * 'ored' with SSL_VERIFY_PEER if they are desired
 */
# define SSL_VERIFY_NONE                 0x00
# define SSL_VERIFY_PEER                 0x01
# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
# define SSL_VERIFY_CLIENT_ONCE          0x04
# define SSL_VERIFY_POST_HANDSHAKE       0x08

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define OpenSSL_add_ssl_algorithms()   SSL_library_init()
#  define SSLeay_add_ssl_algorithms()    SSL_library_init()
# endif

/* More backward compatibility */
# define SSL_get_cipher(s) \
                SSL_CIPHER_get_name(SSL_get_current_cipher(s))
# define SSL_get_cipher_bits(s,np) \
                SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
# define SSL_get_cipher_version(s) \
                SSL_CIPHER_get_version(SSL_get_current_cipher(s))
# define SSL_get_cipher_name(s) \
                SSL_CIPHER_get_name(SSL_get_current_cipher(s))
# define SSL_get_time(a)         SSL_SESSION_get_time(a)
# define SSL_set_time(a,b)       SSL_SESSION_set_time((a),(b))
# define SSL_get_timeout(a)      SSL_SESSION_get_timeout(a)
# define SSL_set_timeout(a,b)    SSL_SESSION_set_timeout((a),(b))

# define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
# define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)

DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_AD_REASON_OFFSET            1000/* offset to get SSL_R_... value
                                              * from SSL_AD_... */
/* These alert types are for SSLv3 and TLSv1 */
# define SSL_AD_CLOSE_NOTIFY             SSL3_AD_CLOSE_NOTIFY
/* fatal */
# define SSL_AD_UNEXPECTED_MESSAGE       SSL3_AD_UNEXPECTED_MESSAGE
/* fatal */
# define SSL_AD_BAD_RECORD_MAC           SSL3_AD_BAD_RECORD_MAC
# define SSL_AD_DECRYPTION_FAILED        TLS1_AD_DECRYPTION_FAILED
# define SSL_AD_RECORD_OVERFLOW          TLS1_AD_RECORD_OVERFLOW
/* fatal */
# define SSL_AD_DECOMPRESSION_FAILURE    SSL3_AD_DECOMPRESSION_FAILURE
/* fatal */
# define SSL_AD_HANDSHAKE_FAILURE        SSL3_AD_HANDSHAKE_FAILURE
/* Not for TLS */
# define SSL_AD_NO_CERTIFICATE           SSL3_AD_NO_CERTIFICATE
# define SSL_AD_BAD_CERTIFICATE          SSL3_AD_BAD_CERTIFICATE
# define SSL_AD_UNSUPPORTED_CERTIFICATE  SSL3_AD_UNSUPPORTED_CERTIFICATE
# define SSL_AD_CERTIFICATE_REVOKED      SSL3_AD_CERTIFICATE_REVOKED
# define SSL_AD_CERTIFICATE_EXPIRED      SSL3_AD_CERTIFICATE_EXPIRED
# define SSL_AD_CERTIFICATE_UNKNOWN      SSL3_AD_CERTIFICATE_UNKNOWN
/* fatal */
# define SSL_AD_ILLEGAL_PARAMETER        SSL3_AD_ILLEGAL_PARAMETER
/* fatal */
# define SSL_AD_UNKNOWN_CA               TLS1_AD_UNKNOWN_CA
/* fatal */
# define SSL_AD_ACCESS_DENIED            TLS1_AD_ACCESS_DENIED
/* fatal */
# define SSL_AD_DECODE_ERROR             TLS1_AD_DECODE_ERROR
# define SSL_AD_DECRYPT_ERROR            TLS1_AD_DECRYPT_ERROR
/* fatal */
# define SSL_AD_EXPORT_RESTRICTION       TLS1_AD_EXPORT_RESTRICTION
/* fatal */
# define SSL_AD_PROTOCOL_VERSION         TLS1_AD_PROTOCOL_VERSION
/* fatal */
# define SSL_AD_INSUFFICIENT_SECURITY    TLS1_AD_INSUFFICIENT_SECURITY
/* fatal */
# define SSL_AD_INTERNAL_ERROR           TLS1_AD_INTERNAL_ERROR
# define SSL_AD_USER_CANCELLED           TLS1_AD_USER_CANCELLED
# define SSL_AD_NO_RENEGOTIATION         TLS1_AD_NO_RENEGOTIATION
# define SSL_AD_MISSING_EXTENSION        TLS13_AD_MISSING_EXTENSION
# define SSL_AD_CERTIFICATE_REQUIRED     TLS13_AD_CERTIFICATE_REQUIRED
# define SSL_AD_UNSUPPORTED_EXTENSION    TLS1_AD_UNSUPPORTED_EXTENSION
# define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
# define SSL_AD_UNRECOGNIZED_NAME        TLS1_AD_UNRECOGNIZED_NAME
# define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
# define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
/* fatal */
# define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY
/* fatal */
# define SSL_AD_INAPPROPRIATE_FALLBACK   TLS1_AD_INAPPROPRIATE_FALLBACK
# define SSL_AD_NO_APPLICATION_PROTOCOL  TLS1_AD_NO_APPLICATION_PROTOCOL
# define SSL_ERROR_NONE                  0
# define SSL_ERROR_SSL                   1
# define SSL_ERROR_WANT_READ             2
# define SSL_ERROR_WANT_WRITE            3
# define SSL_ERROR_WANT_X509_LOOKUP      4
# define SSL_ERROR_SYSCALL               5/* look at error stack/return
                                           * value/errno */
# define SSL_ERROR_ZERO_RETURN           6
# define SSL_ERROR_WANT_CONNECT          7
# define SSL_ERROR_WANT_ACCEPT           8
# define SSL_ERROR_WANT_ASYNC            9
# define SSL_ERROR_WANT_ASYNC_JOB       10
# define SSL_ERROR_WANT_CLIENT_HELLO_CB 11
# define SSL_ERROR_WANT_RETRY_VERIFY    12

# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTRL_SET_TMP_DH                    3
#  define SSL_CTRL_SET_TMP_ECDH                  4
#  define SSL_CTRL_SET_TMP_DH_CB                 6
# endif

# define SSL_CTRL_GET_CLIENT_CERT_REQUEST        9
# define SSL_CTRL_GET_NUM_RENEGOTIATIONS         10
# define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS       11
# define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS       12
# define SSL_CTRL_GET_FLAGS                      13
# define SSL_CTRL_EXTRA_CHAIN_CERT               14
# define SSL_CTRL_SET_MSG_CALLBACK               15
# define SSL_CTRL_SET_MSG_CALLBACK_ARG           16
/* only applies to datagram connections */
# define SSL_CTRL_SET_MTU                17
/* Stats */
# define SSL_CTRL_SESS_NUMBER                    20
# define SSL_CTRL_SESS_CONNECT                   21
# define SSL_CTRL_SESS_CONNECT_GOOD              22
# define SSL_CTRL_SESS_CONNECT_RENEGOTIATE       23
# define SSL_CTRL_SESS_ACCEPT                    24
# define SSL_CTRL_SESS_ACCEPT_GOOD               25
# define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE        26
# define SSL_CTRL_SESS_HIT                       27
# define SSL_CTRL_SESS_CB_HIT                    28
# define SSL_CTRL_SESS_MISSES                    29
# define SSL_CTRL_SESS_TIMEOUTS                  30
# define SSL_CTRL_SESS_CACHE_FULL                31
# define SSL_CTRL_MODE                           33
# define SSL_CTRL_GET_READ_AHEAD                 40
# define SSL_CTRL_SET_READ_AHEAD                 41
# define SSL_CTRL_SET_SESS_CACHE_SIZE            42
# define SSL_CTRL_GET_SESS_CACHE_SIZE            43
# define SSL_CTRL_SET_SESS_CACHE_MODE            44
# define SSL_CTRL_GET_SESS_CACHE_MODE            45
# define SSL_CTRL_GET_MAX_CERT_LIST              50
# define SSL_CTRL_SET_MAX_CERT_LIST              51
# define SSL_CTRL_SET_MAX_SEND_FRAGMENT          52
/* see tls1.h for macros based on these */
# define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB       53
# define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG      54
# define SSL_CTRL_SET_TLSEXT_HOSTNAME            55
# define SSL_CTRL_SET_TLSEXT_DEBUG_CB            56
# define SSL_CTRL_SET_TLSEXT_DEBUG_ARG           57
# define SSL_CTRL_GET_TLSEXT_TICKET_KEYS         58
# define SSL_CTRL_SET_TLSEXT_TICKET_KEYS         59
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT    60 */
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 61 */
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 */
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB       63
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG   64
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE     65
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS     66
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS     67
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS      68
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS      69
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP        70
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP        71
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB      72
# endif
# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB    75
# define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB                76
# define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB             77
# define SSL_CTRL_SET_SRP_ARG            78
# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME               79
# define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH               80
# define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD               81
# define DTLS_CTRL_GET_TIMEOUT           73
# define DTLS_CTRL_HANDLE_TIMEOUT        74
# define SSL_CTRL_GET_RI_SUPPORT                 76
# define SSL_CTRL_CLEAR_MODE                     78
# define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB      79
# define SSL_CTRL_GET_EXTRA_CHAIN_CERTS          82
# define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS        83
# define SSL_CTRL_CHAIN                          88
# define SSL_CTRL_CHAIN_CERT                     89
# define SSL_CTRL_GET_GROUPS                     90
# define SSL_CTRL_SET_GROUPS                     91
# define SSL_CTRL_SET_GROUPS_LIST                92
# define SSL_CTRL_GET_SHARED_GROUP               93
# define SSL_CTRL_SET_SIGALGS                    97
# define SSL_CTRL_SET_SIGALGS_LIST               98
# define SSL_CTRL_CERT_FLAGS                     99
# define SSL_CTRL_CLEAR_CERT_FLAGS               100
# define SSL_CTRL_SET_CLIENT_SIGALGS             101
# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST        102
# define SSL_CTRL_GET_CLIENT_CERT_TYPES          103
# define SSL_CTRL_SET_CLIENT_CERT_TYPES          104
# define SSL_CTRL_BUILD_CERT_CHAIN               105
# define SSL_CTRL_SET_VERIFY_CERT_STORE          106
# define SSL_CTRL_SET_CHAIN_CERT_STORE           107
# define SSL_CTRL_GET_PEER_SIGNATURE_NID         108
# define SSL_CTRL_GET_PEER_TMP_KEY               109
# define SSL_CTRL_GET_RAW_CIPHERLIST             110
# define SSL_CTRL_GET_EC_POINT_FORMATS           111
# define SSL_CTRL_GET_CHAIN_CERTS                115
# define SSL_CTRL_SELECT_CURRENT_CERT            116
# define SSL_CTRL_SET_CURRENT_CERT               117
# define SSL_CTRL_SET_DH_AUTO                    118
# define DTLS_CTRL_SET_LINK_MTU                  120
# define DTLS_CTRL_GET_LINK_MIN_MTU              121
# define SSL_CTRL_GET_EXTMS_SUPPORT              122
# define SSL_CTRL_SET_MIN_PROTO_VERSION          123
# define SSL_CTRL_SET_MAX_PROTO_VERSION          124
# define SSL_CTRL_SET_SPLIT_SEND_FRAGMENT        125
# define SSL_CTRL_SET_MAX_PIPELINES              126
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE     127
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB       128
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG   129
# define SSL_CTRL_GET_MIN_PROTO_VERSION          130
# define SSL_CTRL_GET_MAX_PROTO_VERSION          131
# define SSL_CTRL_GET_SIGNATURE_NID              132
# define SSL_CTRL_GET_TMP_KEY                    133
# define SSL_CTRL_GET_NEGOTIATED_GROUP           134
# define SSL_CTRL_SET_RETRY_VERIFY               136
# define SSL_CTRL_GET_VERIFY_CERT_STORE          137
# define SSL_CTRL_GET_CHAIN_CERT_STORE           138
# define SSL_CERT_SET_FIRST                      1
# define SSL_CERT_SET_NEXT                       2
# define SSL_CERT_SET_SERVER                     3
# define DTLSv1_get_timeout(ssl, arg) \
        SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)(arg))
# define DTLSv1_handle_timeout(ssl) \
        SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
# define SSL_num_renegotiations(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
# define SSL_clear_num_renegotiations(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
# define SSL_total_renegotiations(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTX_set_tmp_dh(ctx,dh) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
# endif
# define SSL_CTX_set_dh_auto(ctx, onoff) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
# define SSL_set_dh_auto(s, onoff) \
        SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_set_tmp_dh(ssl,dh) \
        SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
# endif
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
#  define SSL_set_tmp_ecdh(ssl,ecdh) \
        SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
# endif
# define SSL_CTX_add_extra_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)(x509))
# define SSL_CTX_get_extra_chain_certs(ctx,px509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509)
# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509)
# define SSL_CTX_clear_extra_chain_certs(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL)
# define SSL_CTX_set0_chain(ctx,sk) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk))
# define SSL_CTX_set1_chain(ctx,sk) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk))
# define SSL_CTX_add0_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
# define SSL_CTX_add1_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
# define SSL_CTX_get0_chain_certs(ctx,px509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
# define SSL_CTX_clear_chain_certs(ctx) \
        SSL_CTX_set0_chain(ctx,NULL)
# define SSL_CTX_build_cert_chain(ctx, flags) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
# define SSL_CTX_select_current_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
# define SSL_CTX_set_current_cert(ctx, op) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
# define SSL_CTX_set0_verify_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set1_verify_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
# define SSL_CTX_get0_verify_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set0_chain_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set1_chain_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
# define SSL_CTX_get0_chain_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_set0_chain(s,sk) \
        SSL_ctrl(s,SSL_CTRL_CHAIN,0,(char *)(sk))
# define SSL_set1_chain(s,sk) \
        SSL_ctrl(s,SSL_CTRL_CHAIN,1,(char *)(sk))
# define SSL_add0_chain_cert(s,x509) \
        SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
# define SSL_add1_chain_cert(s,x509) \
        SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
# define SSL_get0_chain_certs(s,px509) \
        SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
# define SSL_clear_chain_certs(s) \
        SSL_set0_chain(s,NULL)
# define SSL_build_cert_chain(s, flags) \
        SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
# define SSL_select_current_cert(s,x509) \
        SSL_ctrl(s,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
# define SSL_set_current_cert(s,op) \
        SSL_ctrl(s,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
# define SSL_set0_verify_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_set1_verify_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
#define SSL_get0_verify_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_set0_chain_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_set1_chain_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
#define SSL_get0_chain_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))

# define SSL_get1_groups(s, glist) \
        SSL_ctrl(s,SSL_CTRL_GET_GROUPS,0,(int*)(glist))
# define SSL_CTX_set1_groups(ctx, glist, glistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(int *)(glist))
# define SSL_CTX_set1_groups_list(ctx, s) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s))
# define SSL_set1_groups(s, glist, glistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist))
# define SSL_set1_groups_list(s, str) \
        SSL_ctrl(s,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(str))
# define SSL_get_shared_group(s, n) \
        SSL_ctrl(s,SSL_CTRL_GET_SHARED_GROUP,n,NULL)
# define SSL_get_negotiated_group(s) \
        SSL_ctrl(s,SSL_CTRL_GET_NEGOTIATED_GROUP,0,NULL)
# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
# define SSL_CTX_set1_sigalgs_list(ctx, s) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s))
# define SSL_set1_sigalgs(s, slist, slistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
# define SSL_set1_sigalgs_list(s, str) \
        SSL_ctrl(s,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(str))
# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s))
# define SSL_set1_client_sigalgs(s, slist, slistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
# define SSL_set1_client_sigalgs_list(s, str) \
        SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(str))
# define SSL_get0_certificate_types(s, clist) \
        SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)(clist))
# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen, \
                     (char *)(clist))
# define SSL_set1_client_certificate_types(s, clist, clistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)(clist))
# define SSL_get_signature_nid(s, pn) \
        SSL_ctrl(s,SSL_CTRL_GET_SIGNATURE_NID,0,pn)
# define SSL_get_peer_signature_nid(s, pn) \
        SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn)
# define SSL_get_peer_tmp_key(s, pk) \
        SSL_ctrl(s,SSL_CTRL_GET_PEER_TMP_KEY,0,pk)
# define SSL_get_tmp_key(s, pk) \
        SSL_ctrl(s,SSL_CTRL_GET_TMP_KEY,0,pk)
# define SSL_get0_raw_cipherlist(s, plst) \
        SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,plst)
# define SSL_get0_ec_point_formats(s, plst) \
        SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,plst)
# define SSL_CTX_set_min_proto_version(ctx, version) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
# define SSL_CTX_set_max_proto_version(ctx, version) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
# define SSL_CTX_get_min_proto_version(ctx) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
# define SSL_CTX_get_max_proto_version(ctx) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)
# define SSL_set_min_proto_version(s, version) \
        SSL_ctrl(s, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
# define SSL_set_max_proto_version(s, version) \
        SSL_ctrl(s, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
# define SSL_get_min_proto_version(s) \
        SSL_ctrl(s, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
# define SSL_get_max_proto_version(s) \
        SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)

const char *SSL_group_to_name(SSL *s, int id);

/* Backwards compatibility, original 1.1.0 names */
# define SSL_CTRL_GET_SERVER_TMP_KEY \
         SSL_CTRL_GET_PEER_TMP_KEY
# define SSL_get_server_tmp_key(s, pk) \
         SSL_get_peer_tmp_key(s, pk)

int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey);
int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey);

/*
 * The following symbol names are old and obsolete. They are kept
 * for compatibility reasons only and should not be used anymore.
 */
# define SSL_CTRL_GET_CURVES           SSL_CTRL_GET_GROUPS
# define SSL_CTRL_SET_CURVES           SSL_CTRL_SET_GROUPS
# define SSL_CTRL_SET_CURVES_LIST      SSL_CTRL_SET_GROUPS_LIST
# define SSL_CTRL_GET_SHARED_CURVE     SSL_CTRL_GET_SHARED_GROUP

# define SSL_get1_curves               SSL_get1_groups
# define SSL_CTX_set1_curves           SSL_CTX_set1_groups
# define SSL_CTX_set1_curves_list      SSL_CTX_set1_groups_list
# define SSL_set1_curves               SSL_set1_groups
# define SSL_set1_curves_list          SSL_set1_groups_list
# define SSL_get_shared_curve          SSL_get_shared_group


# ifndef OPENSSL_NO_DEPRECATED_1_1_0
/* Provide some compatibility macros for removed functionality. */
#  define SSL_CTX_need_tmp_RSA(ctx)                0
#  define SSL_CTX_set_tmp_rsa(ctx,rsa)             1
#  define SSL_need_tmp_RSA(ssl)                    0
#  define SSL_set_tmp_rsa(ssl,rsa)                 1
#  define SSL_CTX_set_ecdh_auto(dummy, onoff)      ((onoff) != 0)
#  define SSL_set_ecdh_auto(dummy, onoff)          ((onoff) != 0)
/*
 * We "pretend" to call the callback to avoid warnings about unused static
 * functions.
 */
#  define SSL_CTX_set_tmp_rsa_callback(ctx, cb)    while(0) (cb)(NULL, 0, 0)
#  define SSL_set_tmp_rsa_callback(ssl, cb)        while(0) (cb)(NULL, 0, 0)
# endif
__owur const BIO_METHOD *BIO_f_ssl(void);
__owur BIO *BIO_new_ssl(SSL_CTX *ctx, int client);
__owur BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
__owur BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
__owur int BIO_ssl_copy_session_id(BIO *to, BIO *from);
void BIO_ssl_shutdown(BIO *ssl_bio);

__owur int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str);
__owur SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
__owur SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
                               const SSL_METHOD *meth);
int SSL_CTX_up_ref(SSL_CTX *ctx);
void SSL_CTX_free(SSL_CTX *);
__owur long SSL_CTX_set_timeout(SSL_CTX *ctx, long t);
__owur long SSL_CTX_get_timeout(const SSL_CTX *ctx);
__owur X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
void SSL_CTX_set1_cert_store(SSL_CTX *, X509_STORE *);
__owur int SSL_want(const SSL *s);
__owur int SSL_clear(SSL *s);

void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm);

__owur const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
__owur const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s);
__owur int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits);
__owur const char *SSL_CIPHER_get_version(const SSL_CIPHER *c);
__owur const char *SSL_CIPHER_get_name(const SSL_CIPHER *c);
__owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c);
__owur const char *OPENSSL_cipher_name(const char *rfc_name);
__owur uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c);
__owur uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c);
__owur int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c);
__owur int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c);
__owur const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c);
__owur int SSL_CIPHER_is_aead(const SSL_CIPHER *c);

__owur int SSL_get_fd(const SSL *s);
__owur int SSL_get_rfd(const SSL *s);
__owur int SSL_get_wfd(const SSL *s);
__owur const char *SSL_get_cipher_list(const SSL *s, int n);
__owur char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size);
__owur int SSL_get_read_ahead(const SSL *s);
__owur int SSL_pending(const SSL *s);
__owur int SSL_has_pending(const SSL *s);
# ifndef OPENSSL_NO_SOCK
__owur int SSL_set_fd(SSL *s, int fd);
__owur int SSL_set_rfd(SSL *s, int fd);
__owur int SSL_set_wfd(SSL *s, int fd);
# endif
void SSL_set0_rbio(SSL *s, BIO *rbio);
void SSL_set0_wbio(SSL *s, BIO *wbio);
void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio);
__owur BIO *SSL_get_rbio(const SSL *s);
__owur BIO *SSL_get_wbio(const SSL *s);
__owur int SSL_set_cipher_list(SSL *s, const char *str);
__owur int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
__owur int SSL_set_ciphersuites(SSL *s, const char *str);
void SSL_set_read_ahead(SSL *s, int yes);
__owur int SSL_get_verify_mode(const SSL *s);
__owur int SSL_get_verify_depth(const SSL *s);
__owur SSL_verify_cb SSL_get_verify_callback(const SSL *s);
void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback);
void SSL_set_verify_depth(SSL *s, int depth);
void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg);
# ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 __owur int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
OSSL_DEPRECATEDIN_3_0
__owur int SSL_use_RSAPrivateKey_ASN1(SSL *ssl,
                                      const unsigned char *d, long len);
# endif
__owur int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
__owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d,
                                   long len);
__owur int SSL_use_certificate(SSL *ssl, X509 *x);
__owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
__owur int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey,
                                STACK_OF(X509) *chain, int override);


/* serverinfo file format versions */
# define SSL_SERVERINFOV1   1
# define SSL_SERVERINFOV2   2

/* Set serverinfo data for the current active cert. */
__owur int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
                                  size_t serverinfo_length);
__owur int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
                                     const unsigned char *serverinfo,
                                     size_t serverinfo_length);
__owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file);

#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
#endif

__owur int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
__owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type);

#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file,
                                          int type);
#endif
__owur int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file,
                                       int type);
__owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,
                                        int type);
/* PEM type */
__owur int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
__owur int SSL_use_certificate_chain_file(SSL *ssl, const char *file);
__owur STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
__owur STACK_OF(X509_NAME)
*SSL_load_client_CA_file_ex(const char *file, OSSL_LIB_CTX *libctx,
                            const char *propq);
__owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                               const char *file);
int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                       const char *dir);
int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                       const char *uri);

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_load_error_strings() \
    OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
                     | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
# endif

__owur const char *SSL_state_string(const SSL *s);
__owur const char *SSL_rstate_string(const SSL *s);
__owur const char *SSL_state_string_long(const SSL *s);
__owur const char *SSL_rstate_string_long(const SSL *s);
__owur long SSL_SESSION_get_time(const SSL_SESSION *s);
__owur long SSL_SESSION_set_time(SSL_SESSION *s, long t);
__owur long SSL_SESSION_get_timeout(const SSL_SESSION *s);
__owur long SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
__owur int SSL_SESSION_get_protocol_version(const SSL_SESSION *s);
__owur int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version);

__owur const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s);
__owur int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname);
void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s,
                                    const unsigned char **alpn,
                                    size_t *len);
__owur int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s,
                                          const unsigned char *alpn,
                                          size_t len);
__owur const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s);
__owur int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher);
__owur int SSL_SESSION_has_ticket(const SSL_SESSION *s);
__owur unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s);
void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
                             size_t *len);
__owur uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s);
__owur int SSL_SESSION_set_max_early_data(SSL_SESSION *s,
                                          uint32_t max_early_data);
__owur int SSL_copy_session_id(SSL *to, const SSL *from);
__owur X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
__owur int SSL_SESSION_set1_id_context(SSL_SESSION *s,
                                       const unsigned char *sid_ctx,
                                       unsigned int sid_ctx_len);
__owur int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
                               unsigned int sid_len);
__owur int SSL_SESSION_is_resumable(const SSL_SESSION *s);

__owur SSL_SESSION *SSL_SESSION_new(void);
__owur SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src);
const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
                                        unsigned int *len);
const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s,
                                                 unsigned int *len);
__owur unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s);
# ifndef OPENSSL_NO_STDIO
int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses);
# endif
int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses);
int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x);
int SSL_SESSION_up_ref(SSL_SESSION *ses);
void SSL_SESSION_free(SSL_SESSION *ses);
__owur int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp);
__owur int SSL_set_session(SSL *to, SSL_SESSION *session);
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session);
int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session);
__owur int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb);
__owur int SSL_set_generate_session_id(SSL *s, GEN_SESSION_CB cb);
__owur int SSL_has_matching_session_id(const SSL *s,
                                       const unsigned char *id,
                                       unsigned int id_len);
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
                             long length);

# ifdef OPENSSL_X509_H
__owur X509 *SSL_get0_peer_certificate(const SSL *s);
__owur X509 *SSL_get1_peer_certificate(const SSL *s);
/* Deprecated in 3.0.0 */
#  ifndef OPENSSL_NO_DEPRECATED_3_0
#   define SSL_get_peer_certificate SSL_get1_peer_certificate
#  endif
# endif

__owur STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);

__owur int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
__owur int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
__owur SSL_verify_cb SSL_CTX_get_verify_callback(const SSL_CTX *ctx);
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback);
void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
                                      int (*cb) (X509_STORE_CTX *, void *),
                                      void *arg);
void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg),
                         void *arg);
# ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d,
                                          long len);
# endif
__owur int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
__owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx,
                                       const unsigned char *d, long len);
__owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
__owur int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len,
                                        const unsigned char *d);
__owur int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey,
                                    STACK_OF(X509) *chain, int override);

void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx);
void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx);
void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb);
void SSL_set_default_passwd_cb_userdata(SSL *s, void *u);
pem_password_cb *SSL_get_default_passwd_cb(SSL *s);
void *SSL_get_default_passwd_cb_userdata(SSL *s);

__owur int SSL_CTX_check_private_key(const SSL_CTX *ctx);
__owur int SSL_check_private_key(const SSL *ctx);

__owur int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
                                          const unsigned char *sid_ctx,
                                          unsigned int sid_ctx_len);

SSL *SSL_new(SSL_CTX *ctx);
int SSL_up_ref(SSL *s);
int SSL_is_dtls(const SSL *s);
__owur int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
                                      unsigned int sid_ctx_len);

__owur int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose);
__owur int SSL_set_purpose(SSL *ssl, int purpose);
__owur int SSL_CTX_set_trust(SSL_CTX *ctx, int trust);
__owur int SSL_set_trust(SSL *ssl, int trust);

__owur int SSL_set1_host(SSL *s, const char *hostname);
__owur int SSL_add1_host(SSL *s, const char *hostname);
__owur const char *SSL_get0_peername(SSL *s);
void SSL_set_hostflags(SSL *s, unsigned int flags);

__owur int SSL_CTX_dane_enable(SSL_CTX *ctx);
__owur int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md,
                                  uint8_t mtype, uint8_t ord);
__owur int SSL_dane_enable(SSL *s, const char *basedomain);
__owur int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
                             uint8_t mtype, const unsigned char *data, size_t dlen);
__owur int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki);
__owur int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
                              uint8_t *mtype, const unsigned char **data,
                              size_t *dlen);
/*
 * Bridge opacity barrier between libcrypt and libssl, also needed to support
 * offline testing in test/danetest.c
 */
SSL_DANE *SSL_get0_dane(SSL *ssl);
/*
 * DANE flags
 */
unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags);
unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags);
unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags);
unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags);

__owur int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
__owur int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);

__owur X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx);
__owur X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);

# ifndef OPENSSL_NO_SRP
#  ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name);
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password);
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength);
OSSL_DEPRECATEDIN_3_0
int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
                                        char *(*cb) (SSL *, void *));
OSSL_DEPRECATEDIN_3_0
int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
                                          int (*cb) (SSL *, void *));
OSSL_DEPRECATEDIN_3_0
int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
                                      int (*cb) (SSL *, int *, void *));
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg);

OSSL_DEPRECATEDIN_3_0
int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
                             BIGNUM *sa, BIGNUM *v, char *info);
OSSL_DEPRECATEDIN_3_0
int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
                                const char *grp);

OSSL_DEPRECATEDIN_3_0 __owur BIGNUM *SSL_get_srp_g(SSL *s);
OSSL_DEPRECATEDIN_3_0 __owur BIGNUM *SSL_get_srp_N(SSL *s);

OSSL_DEPRECATEDIN_3_0 __owur char *SSL_get_srp_username(SSL *s);
OSSL_DEPRECATEDIN_3_0 __owur char *SSL_get_srp_userinfo(SSL *s);
#  endif
# endif

/*
 * ClientHello callback and helpers.
 */

# define SSL_CLIENT_HELLO_SUCCESS 1
# define SSL_CLIENT_HELLO_ERROR   0
# define SSL_CLIENT_HELLO_RETRY   (-1)

typedef int (*SSL_client_hello_cb_fn) (SSL *s, int *al, void *arg);
void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb,
                                 void *arg);
int SSL_client_hello_isv2(SSL *s);
unsigned int SSL_client_hello_get0_legacy_version(SSL *s);
size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_compression_methods(SSL *s,
                                                 const unsigned char **out);
int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen);
int SSL_client_hello_get0_ext(SSL *s, unsigned int type,
                              const unsigned char **out, size_t *outlen);

void SSL_certs_clear(SSL *s);
void SSL_free(SSL *ssl);
# ifdef OSSL_ASYNC_FD
/*
 * Windows application developer has to include windows.h to use these.
 */
__owur int SSL_waiting_for_async(SSL *s);
__owur int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds);
__owur int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd,
                                     size_t *numaddfds, OSSL_ASYNC_FD *delfd,
                                     size_t *numdelfds);
__owur int SSL_CTX_set_async_callback(SSL_CTX *ctx, SSL_async_callback_fn callback);
__owur int SSL_CTX_set_async_callback_arg(SSL_CTX *ctx, void *arg);
__owur int SSL_set_async_callback(SSL *s, SSL_async_callback_fn callback);
__owur int SSL_set_async_callback_arg(SSL *s, void *arg);
__owur int SSL_get_async_status(SSL *s, int *status);

# endif
__owur int SSL_accept(SSL *ssl);
__owur int SSL_stateless(SSL *s);
__owur int SSL_connect(SSL *ssl);
__owur int SSL_read(SSL *ssl, void *buf, int num);
__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);

# define SSL_READ_EARLY_DATA_ERROR   0
# define SSL_READ_EARLY_DATA_SUCCESS 1
# define SSL_READ_EARLY_DATA_FINISH  2

__owur int SSL_read_early_data(SSL *s, void *buf, size_t num,
                               size_t *readbytes);
__owur int SSL_peek(SSL *ssl, void *buf, int num);
__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
__owur ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size,
                                 int flags);
__owur int SSL_write(SSL *ssl, const void *buf, int num);
__owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
__owur int SSL_write_early_data(SSL *s, const void *buf, size_t num,
                                size_t *written);
long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg);
long SSL_callback_ctrl(SSL *, int, void (*)(void));
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));

# define SSL_EARLY_DATA_NOT_SENT    0
# define SSL_EARLY_DATA_REJECTED    1
# define SSL_EARLY_DATA_ACCEPTED    2

__owur int SSL_get_early_data_status(const SSL *s);

__owur int SSL_get_error(const SSL *s, int ret_code);
__owur const char *SSL_get_version(const SSL *s);

/* This sets the 'default' SSL version that SSL_new() will create */
# ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
# endif

# ifndef OPENSSL_NO_SSL3_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_method(void); /* SSLv3 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_client_method(void);
#  endif
# endif

#define SSLv23_method           TLS_method
#define SSLv23_server_method    TLS_server_method
#define SSLv23_client_method    TLS_client_method

/* Negotiate highest available SSL/TLS version */
__owur const SSL_METHOD *TLS_method(void);
__owur const SSL_METHOD *TLS_server_method(void);
__owur const SSL_METHOD *TLS_client_method(void);

# ifndef OPENSSL_NO_TLS1_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_TLS1_1_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_method(void); /* TLSv1.1 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_TLS1_2_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_method(void); /* TLSv1.2 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_DTLS1_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_DTLS1_2_METHOD
/* DTLSv1.2 */
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_client_method(void);
#  endif
# endif

__owur const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */
__owur const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */
__owur const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */

__owur size_t DTLS_get_data_mtu(const SSL *s);

__owur STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
__owur STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
__owur STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s);
__owur STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s);

__owur int SSL_do_handshake(SSL *s);
int SSL_key_update(SSL *s, int updatetype);
int SSL_get_key_update_type(const SSL *s);
int SSL_renegotiate(SSL *s);
int SSL_renegotiate_abbreviated(SSL *s);
__owur int SSL_renegotiate_pending(const SSL *s);
int SSL_new_session_ticket(SSL *s);
int SSL_shutdown(SSL *s);
__owur int SSL_verify_client_post_handshake(SSL *s);
void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val);
void SSL_set_post_handshake_auth(SSL *s, int val);

__owur const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx);
__owur const SSL_METHOD *SSL_get_ssl_method(const SSL *s);
__owur int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
__owur const char *SSL_alert_type_string_long(int value);
__owur const char *SSL_alert_type_string(int value);
__owur const char *SSL_alert_desc_string_long(int value);
__owur const char *SSL_alert_desc_string(int value);

void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
__owur const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s);
__owur const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx);
__owur int SSL_add1_to_CA_list(SSL *ssl, const X509 *x);
__owur int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x);
__owur const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s);

void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
__owur STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
__owur STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
__owur int SSL_add_client_CA(SSL *ssl, X509 *x);
__owur int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x);

void SSL_set_connect_state(SSL *s);
void SSL_set_accept_state(SSL *s);

__owur long SSL_get_default_timeout(const SSL *s);

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_library_init() OPENSSL_init_ssl(0, NULL)
# endif

__owur char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size);
__owur STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk);

__owur SSL *SSL_dup(SSL *ssl);

__owur X509 *SSL_get_certificate(const SSL *ssl);
/*
 * EVP_PKEY
 */
struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl);

__owur X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx);
__owur EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx);

void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode);
__owur int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
void SSL_set_quiet_shutdown(SSL *ssl, int mode);
__owur int SSL_get_quiet_shutdown(const SSL *ssl);
void SSL_set_shutdown(SSL *ssl, int mode);
__owur int SSL_get_shutdown(const SSL *ssl);
__owur int SSL_version(const SSL *ssl);
__owur int SSL_client_version(const SSL *s);
__owur int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_store(SSL_CTX *ctx);
__owur int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile);
__owur int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath);
__owur int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore);
__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx,
                                                        const char *CAfile,
                                                        const char *CApath);
# define SSL_get0_session SSL_get_session/* just peek at pointer */
__owur SSL_SESSION *SSL_get_session(const SSL *ssl);
__owur SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
__owur SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
void SSL_set_info_callback(SSL *ssl,
                           void (*cb) (const SSL *ssl, int type, int val));
void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type,
                                               int val);
__owur OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl);

void SSL_set_verify_result(SSL *ssl, long v);
__owur long SSL_get_verify_result(const SSL *ssl);
__owur STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s);

__owur size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
                                    size_t outlen);
__owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
                                    size_t outlen);
__owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *sess,
                                         unsigned char *out, size_t outlen);
__owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess,
                                       const unsigned char *in, size_t len);
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *sess);

#define SSL_get_ex_new_index(l, p, newf, dupf, freef) \
    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef)
__owur int SSL_set_ex_data(SSL *ssl, int idx, void *data);
void *SSL_get_ex_data(const SSL *ssl, int idx);
#define SSL_SESSION_get_ex_new_index(l, p, newf, dupf, freef) \
    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, l, p, newf, dupf, freef)
__owur int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data);
void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx);
#define SSL_CTX_get_ex_new_index(l, p, newf, dupf, freef) \
    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, l, p, newf, dupf, freef)
__owur int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data);
void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx);

__owur int SSL_get_ex_data_X509_STORE_CTX_idx(void);

# define SSL_CTX_sess_set_cache_size(ctx,t) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
# define SSL_CTX_sess_get_cache_size(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
# define SSL_CTX_set_session_cache_mode(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
# define SSL_CTX_get_session_cache_mode(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)

# define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
# define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
# define SSL_CTX_get_read_ahead(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
# define SSL_CTX_set_read_ahead(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
# define SSL_CTX_get_max_cert_list(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
# define SSL_CTX_set_max_cert_list(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
# define SSL_get_max_cert_list(ssl) \
        SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
# define SSL_set_max_cert_list(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)

# define SSL_CTX_set_max_send_fragment(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_set_max_send_fragment(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_split_send_fragment(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_set_split_send_fragment(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_max_pipelines(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
# define SSL_set_max_pipelines(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
# define SSL_set_retry_verify(ssl) \
        (SSL_ctrl(ssl,SSL_CTRL_SET_RETRY_VERIFY,0,NULL) > 0)

void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
void SSL_set_default_read_buffer_len(SSL *s, size_t len);

# ifndef OPENSSL_NO_DH
#  ifndef OPENSSL_NO_DEPRECATED_3_0
/* NB: the |keylength| is only applicable when is_export is true */
OSSL_DEPRECATEDIN_3_0
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
                                 DH *(*dh) (SSL *ssl, int is_export,
                                            int keylength));
OSSL_DEPRECATEDIN_3_0
void SSL_set_tmp_dh_callback(SSL *ssl,
                             DH *(*dh) (SSL *ssl, int is_export,
                                        int keylength));
#  endif
# endif

__owur const COMP_METHOD *SSL_get_current_compression(const SSL *s);
__owur const COMP_METHOD *SSL_get_current_expansion(const SSL *s);
__owur const char *SSL_COMP_get_name(const COMP_METHOD *comp);
__owur const char *SSL_COMP_get0_name(const SSL_COMP *comp);
__owur int SSL_COMP_get_id(const SSL_COMP *comp);
STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
__owur STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
                                                             *meths);
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_COMP_free_compression_methods() while(0) continue
# endif
__owur int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm);

const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c);
int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c);
int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
                             int isv2format, STACK_OF(SSL_CIPHER) **sk,
                             STACK_OF(SSL_CIPHER) **scsvs);

/* TLS extensions functions */
__owur int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);

__owur int SSL_set_session_ticket_ext_cb(SSL *s,
                                         tls_session_ticket_ext_cb_fn cb,
                                         void *arg);

/* Pre-shared secret session resumption functions */
__owur int SSL_set_session_secret_cb(SSL *s,
                                     tls_session_secret_cb_fn session_secret_cb,
                                     void *arg);

void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
                                                int (*cb) (SSL *ssl,
                                                           int
                                                           is_forward_secure));

void SSL_set_not_resumable_session_callback(SSL *ssl,
                                            int (*cb) (SSL *ssl,
                                                       int is_forward_secure));

void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
                                         size_t (*cb) (SSL *ssl, int type,
                                                       size_t len, void *arg));
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx);
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);

int SSL_set_record_padding_callback(SSL *ssl,
                                    size_t (*cb) (SSL *ssl, int type,
                                                  size_t len, void *arg));
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg);
void *SSL_get_record_padding_callback_arg(const SSL *ssl);
int SSL_set_block_padding(SSL *ssl, size_t block_size);

int SSL_set_num_tickets(SSL *s, size_t num_tickets);
size_t SSL_get_num_tickets(const SSL *s);
int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_cache_hit(s) SSL_session_reused(s)
# endif

__owur int SSL_session_reused(const SSL *s);
__owur int SSL_is_server(const SSL *s);

__owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void);
int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx);
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx);
unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags);
__owur unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx,
                                             unsigned int flags);
__owur int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre);

void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl);
void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx);

__owur int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
__owur int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv);
__owur int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);

void SSL_add_ssl_module(void);
int SSL_config(SSL *s, const char *name);
int SSL_CTX_config(SSL_CTX *ctx, const char *name);

# ifndef OPENSSL_NO_SSL_TRACE
void SSL_trace(int write_p, int version, int content_type,
               const void *buf, size_t len, SSL *ssl, void *arg);
# endif

# ifndef OPENSSL_NO_SOCK
int DTLSv1_listen(SSL *s, BIO_ADDR *client);
# endif

# ifndef OPENSSL_NO_CT

/*
 * A callback for verifying that the received SCTs are sufficient.
 * Expected to return 1 if they are sufficient, otherwise 0.
 * May return a negative integer if an error occurs.
 * A connection should be aborted if the SCTs are deemed insufficient.
 */
typedef int (*ssl_ct_validation_cb)(const CT_POLICY_EVAL_CTX *ctx,
                                    const STACK_OF(SCT) *scts, void *arg);

/*
 * Sets a |callback| that is invoked upon receipt of ServerHelloDone to validate
 * the received SCTs.
 * If the callback returns a non-positive result, the connection is terminated.
 * Call this function before beginning a handshake.
 * If a NULL |callback| is provided, SCT validation is disabled.
 * |arg| is arbitrary userdata that will be passed to the callback whenever it
 * is invoked. Ownership of |arg| remains with the caller.
 *
 * NOTE: A side-effect of setting a CT callback is that an OCSP stapled response
 *       will be requested.
 */
int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback,
                                   void *arg);
int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
                                       ssl_ct_validation_cb callback,
                                       void *arg);
#define SSL_disable_ct(s) \
        ((void) SSL_set_validation_callback((s), NULL, NULL))
#define SSL_CTX_disable_ct(ctx) \
        ((void) SSL_CTX_set_validation_callback((ctx), NULL, NULL))

/*
 * The validation type enumerates the available behaviours of the built-in SSL
 * CT validation callback selected via SSL_enable_ct() and SSL_CTX_enable_ct().
 * The underlying callback is a static function in libssl.
 */
enum {
    SSL_CT_VALIDATION_PERMISSIVE = 0,
    SSL_CT_VALIDATION_STRICT
};

/*
 * Enable CT by setting up a callback that implements one of the built-in
 * validation variants.  The SSL_CT_VALIDATION_PERMISSIVE variant always
 * continues the handshake, the application can make appropriate decisions at
 * handshake completion.  The SSL_CT_VALIDATION_STRICT variant requires at
 * least one valid SCT, or else handshake termination will be requested.  The
 * handshake may continue anyway if SSL_VERIFY_NONE is in effect.
 */
int SSL_enable_ct(SSL *s, int validation_mode);
int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode);

/*
 * Report whether a non-NULL callback is enabled.
 */
int SSL_ct_is_enabled(const SSL *s);
int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx);

/* Gets the SCTs received from a connection */
const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s);

/*
 * Loads the CT log list from the default location.
 * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
 * the log information loaded from this file will be appended to the
 * CTLOG_STORE.
 * Returns 1 on success, 0 otherwise.
 */
int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx);

/*
 * Loads the CT log list from the specified file path.
 * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
 * the log information loaded from this file will be appended to the
 * CTLOG_STORE.
 * Returns 1 on success, 0 otherwise.
 */
int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path);

/*
 * Sets the CT log list used by all SSL connections created from this SSL_CTX.
 * Ownership of the CTLOG_STORE is transferred to the SSL_CTX.
 */
void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE *logs);

/*
 * Gets the CT log list used by all SSL connections created from this SSL_CTX.
 * This will be NULL unless one of the following functions has been called:
 * - SSL_CTX_set_default_ctlog_list_file
 * - SSL_CTX_set_ctlog_list_file
 * - SSL_CTX_set_ctlog_store
 */
const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx);

# endif /* OPENSSL_NO_CT */

/* What the "other" parameter contains in security callback */
/* Mask for type */
# define SSL_SECOP_OTHER_TYPE    0xffff0000
# define SSL_SECOP_OTHER_NONE    0
# define SSL_SECOP_OTHER_CIPHER  (1 << 16)
# define SSL_SECOP_OTHER_CURVE   (2 << 16)
# define SSL_SECOP_OTHER_DH      (3 << 16)
# define SSL_SECOP_OTHER_PKEY    (4 << 16)
# define SSL_SECOP_OTHER_SIGALG  (5 << 16)
# define SSL_SECOP_OTHER_CERT    (6 << 16)

/* Indicated operation refers to peer key or certificate */
# define SSL_SECOP_PEER          0x1000

/* Values for "op" parameter in security callback */

/* Called to filter ciphers */
/* Ciphers client supports */
# define SSL_SECOP_CIPHER_SUPPORTED      (1 | SSL_SECOP_OTHER_CIPHER)
/* Cipher shared by client/server */
# define SSL_SECOP_CIPHER_SHARED         (2 | SSL_SECOP_OTHER_CIPHER)
/* Sanity check of cipher server selects */
# define SSL_SECOP_CIPHER_CHECK          (3 | SSL_SECOP_OTHER_CIPHER)
/* Curves supported by client */
# define SSL_SECOP_CURVE_SUPPORTED       (4 | SSL_SECOP_OTHER_CURVE)
/* Curves shared by client/server */
# define SSL_SECOP_CURVE_SHARED          (5 | SSL_SECOP_OTHER_CURVE)
/* Sanity check of curve server selects */
# define SSL_SECOP_CURVE_CHECK           (6 | SSL_SECOP_OTHER_CURVE)
/* Temporary DH key */
# define SSL_SECOP_TMP_DH                (7 | SSL_SECOP_OTHER_PKEY)
/* SSL/TLS version */
# define SSL_SECOP_VERSION               (9 | SSL_SECOP_OTHER_NONE)
/* Session tickets */
# define SSL_SECOP_TICKET                (10 | SSL_SECOP_OTHER_NONE)
/* Supported signature algorithms sent to peer */
# define SSL_SECOP_SIGALG_SUPPORTED      (11 | SSL_SECOP_OTHER_SIGALG)
/* Shared signature algorithm */
# define SSL_SECOP_SIGALG_SHARED         (12 | SSL_SECOP_OTHER_SIGALG)
/* Sanity check signature algorithm allowed */
# define SSL_SECOP_SIGALG_CHECK          (13 | SSL_SECOP_OTHER_SIGALG)
/* Used to get mask of supported public key signature algorithms */
# define SSL_SECOP_SIGALG_MASK           (14 | SSL_SECOP_OTHER_SIGALG)
/* Use to see if compression is allowed */
# define SSL_SECOP_COMPRESSION           (15 | SSL_SECOP_OTHER_NONE)
/* EE key in certificate */
# define SSL_SECOP_EE_KEY                (16 | SSL_SECOP_OTHER_CERT)
/* CA key in certificate */
# define SSL_SECOP_CA_KEY                (17 | SSL_SECOP_OTHER_CERT)
/* CA digest algorithm in certificate */
# define SSL_SECOP_CA_MD                 (18 | SSL_SECOP_OTHER_CERT)
/* Peer EE key in certificate */
# define SSL_SECOP_PEER_EE_KEY           (SSL_SECOP_EE_KEY | SSL_SECOP_PEER)
/* Peer CA key in certificate */
# define SSL_SECOP_PEER_CA_KEY           (SSL_SECOP_CA_KEY | SSL_SECOP_PEER)
/* Peer CA digest algorithm in certificate */
# define SSL_SECOP_PEER_CA_MD            (SSL_SECOP_CA_MD | SSL_SECOP_PEER)

void SSL_set_security_level(SSL *s, int level);
__owur int SSL_get_security_level(const SSL *s);
void SSL_set_security_callback(SSL *s,
                               int (*cb) (const SSL *s, const SSL_CTX *ctx,
                                          int op, int bits, int nid,
                                          void *other, void *ex));
int (*SSL_get_security_callback(const SSL *s)) (const SSL *s,
                                                const SSL_CTX *ctx, int op,
                                                int bits, int nid, void *other,
                                                void *ex);
void SSL_set0_security_ex_data(SSL *s, void *ex);
__owur void *SSL_get0_security_ex_data(const SSL *s);

void SSL_CTX_set_security_level(SSL_CTX *ctx, int level);
__owur int SSL_CTX_get_security_level(const SSL_CTX *ctx);
void SSL_CTX_set_security_callback(SSL_CTX *ctx,
                                   int (*cb) (const SSL *s, const SSL_CTX *ctx,
                                              int op, int bits, int nid,
                                              void *other, void *ex));
int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s,
                                                          const SSL_CTX *ctx,
                                                          int op, int bits,
                                                          int nid,
                                                          void *other,
                                                          void *ex);
void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex);
__owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx);

/* OPENSSL_INIT flag 0x010000 reserved for internal use */
# define OPENSSL_INIT_NO_LOAD_SSL_STRINGS    0x00100000L
# define OPENSSL_INIT_LOAD_SSL_STRINGS       0x00200000L

# define OPENSSL_INIT_SSL_DEFAULT \
        (OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS)

int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);

# ifndef OPENSSL_NO_UNIT_TEST
__owur const struct openssl_ssl_test_functions *SSL_test_functions(void);
# endif

__owur int SSL_free_buffers(SSL *ssl);
__owur int SSL_alloc_buffers(SSL *ssl);

/* Status codes passed to the decrypt session ticket callback. Some of these
 * are for internal use only and are never passed to the callback. */
typedef int SSL_TICKET_STATUS;

/* Support for ticket appdata */
/* fatal error, malloc failure */
# define SSL_TICKET_FATAL_ERR_MALLOC 0
/* fatal error, either from parsing or decrypting the ticket */
# define SSL_TICKET_FATAL_ERR_OTHER  1
/* No ticket present */
# define SSL_TICKET_NONE             2
/* Empty ticket present */
# define SSL_TICKET_EMPTY            3
/* the ticket couldn't be decrypted */
# define SSL_TICKET_NO_DECRYPT       4
/* a ticket was successfully decrypted */
# define SSL_TICKET_SUCCESS          5
/* same as above but the ticket needs to be renewed */
# define SSL_TICKET_SUCCESS_RENEW    6

/* Return codes for the decrypt session ticket callback */
typedef int SSL_TICKET_RETURN;

/* An error occurred */
#define SSL_TICKET_RETURN_ABORT             0
/* Do not use the ticket, do not send a renewed ticket to the client */
#define SSL_TICKET_RETURN_IGNORE            1
/* Do not use the ticket, send a renewed ticket to the client */
#define SSL_TICKET_RETURN_IGNORE_RENEW      2
/* Use the ticket, do not send a renewed ticket to the client */
#define SSL_TICKET_RETURN_USE               3
/* Use the ticket, send a renewed ticket to the client */
#define SSL_TICKET_RETURN_USE_RENEW         4

typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg);
typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss,
                                                               const unsigned char *keyname,
                                                               size_t keyname_length,
                                                               SSL_TICKET_STATUS status,
                                                               void *arg);
int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx,
                                  SSL_CTX_generate_session_ticket_fn gen_cb,
                                  SSL_CTX_decrypt_session_ticket_fn dec_cb,
                                  void *arg);
int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len);
int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len);

typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);

void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);


typedef int (*SSL_allow_early_data_cb_fn)(SSL *s, void *arg);
void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx,
                                     SSL_allow_early_data_cb_fn cb,
                                     void *arg);
void SSL_set_allow_early_data_cb(SSL *s,
                                 SSL_allow_early_data_cb_fn cb,
                                 void *arg);

/* store the default cipher strings inside the library */
const char *OSSL_default_cipher_list(void);
const char *OSSL_default_ciphersuites(void);

#  ifndef OPENSSL_NO_QUIC
/*
 * QUIC integration - The QUIC interface matches BoringSSL
 *
 * ssl_encryption_level_t represents a specific QUIC encryption level used to
 * transmit handshake messages. BoringSSL has this as an 'enum'.
 */
#include <openssl/quic.h>

/* Used by Chromium/QUIC - moved from evp.h to avoid breaking FIPS checksums */
# define X25519_PRIVATE_KEY_LEN          32
# define X25519_PUBLIC_VALUE_LEN         32

/* moved from types.h to avoid breaking FIPS checksums */
typedef struct ssl_quic_method_st SSL_QUIC_METHOD;

typedef enum ssl_encryption_level_t {
    ssl_encryption_initial = 0,
    ssl_encryption_early_data,
    ssl_encryption_handshake,
    ssl_encryption_application
} OSSL_ENCRYPTION_LEVEL;

struct ssl_quic_method_st {
    int (*set_encryption_secrets)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
                                  const uint8_t *read_secret,
                                  const uint8_t *write_secret, size_t secret_len);
    int (*add_handshake_data)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
                              const uint8_t *data, size_t len);
    int (*flush_flight)(SSL *ssl);
    int (*send_alert)(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert);
};

__owur int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method);
__owur int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method);
__owur int SSL_set_quic_transport_params(SSL *ssl,
                                         const uint8_t *params,
                                         size_t params_len);
void SSL_get_peer_quic_transport_params(const SSL *ssl,
                                        const uint8_t **out_params,
                                        size_t *out_params_len);
__owur size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, OSSL_ENCRYPTION_LEVEL level);
__owur OSSL_ENCRYPTION_LEVEL SSL_quic_read_level(const SSL *ssl);
__owur OSSL_ENCRYPTION_LEVEL SSL_quic_write_level(const SSL *ssl);
__owur int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
                                 const uint8_t *data, size_t len);
__owur int SSL_process_quic_post_handshake(SSL *ssl);

__owur int SSL_is_quic(SSL *ssl);

/* BoringSSL API */
void SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy);

/*
 * Set an explicit value that you want to use
 * If 0 (default) the server will use the highest extenstion the client sent
 * If 0 (default) the client will send both extensions
 */
void SSL_set_quic_transport_version(SSL *ssl, int version);
__owur int SSL_get_quic_transport_version(const SSL *ssl);
/* Returns the negotiated version, or -1 on error */
__owur int SSL_get_peer_quic_transport_version(const SSL *ssl);

int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c);

void SSL_set_quic_early_data_enabled(SSL *ssl, int enabled);

#  endif

# ifdef  __cplusplus
}
# endif
#endif
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     /*
 * WARNING: do not edit!
 * Generated by makefile from include/openssl/ssl.h.in
 *
 * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
 * Copyright 2005 Nokia. All rights reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */



#ifndef OPENSSL_SSL_H
# define OPENSSL_SSL_H
# pragma once

# include <openssl/macros.h>
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define HEADER_SSL_H
# endif

# include <openssl/e_os2.h>
# include <openssl/opensslconf.h>
# include <openssl/comp.h>
# include <openssl/bio.h>
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  include <openssl/x509.h>
#  include <openssl/crypto.h>
#  include <openssl/buffer.h>
# endif
# include <openssl/lhash.h>
# include <openssl/pem.h>
# include <openssl/hmac.h>
# include <openssl/async.h>

# include <openssl/safestack.h>
# include <openssl/symhacks.h>
# include <openssl/ct.h>
# include <openssl/sslerr.h>
# include <openssl/prov_ssl.h>

#ifdef  __cplusplus
extern "C" {
#endif

/* OpenSSL version number for ASN.1 encoding of the session information */
/*-
 * Version 0 - initial version
 * Version 1 - added the optional peer certificate
 */
# define SSL_SESSION_ASN1_VERSION 0x0001

# define SSL_MAX_SSL_SESSION_ID_LENGTH           32
# define SSL_MAX_SID_CTX_LENGTH                  32

# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES     (512/8)
# define SSL_MAX_KEY_ARG_LENGTH                  8
/* SSL_MAX_MASTER_KEY_LENGTH is defined in prov_ssl.h */

/* The maximum number of encrypt/decrypt pipelines we can support */
# define SSL_MAX_PIPELINES  32

/* text strings for the ciphers */

/* These are used to specify which ciphers to use and not to use */

# define SSL_TXT_LOW             "LOW"
# define SSL_TXT_MEDIUM          "MEDIUM"
# define SSL_TXT_HIGH            "HIGH"
# define SSL_TXT_FIPS            "FIPS"

# define SSL_TXT_aNULL           "aNULL"
# define SSL_TXT_eNULL           "eNULL"
# define SSL_TXT_NULL            "NULL"

# define SSL_TXT_kRSA            "kRSA"
# define SSL_TXT_kDHr            "kDHr"/* this cipher class has been removed */
# define SSL_TXT_kDHd            "kDHd"/* this cipher class has been removed */
# define SSL_TXT_kDH             "kDH"/* this cipher class has been removed */
# define SSL_TXT_kEDH            "kEDH"/* alias for kDHE */
# define SSL_TXT_kDHE            "kDHE"
# define SSL_TXT_kECDHr          "kECDHr"/* this cipher class has been removed */
# define SSL_TXT_kECDHe          "kECDHe"/* this cipher class has been removed */
# define SSL_TXT_kECDH           "kECDH"/* this cipher class has been removed */
# define SSL_TXT_kEECDH          "kEECDH"/* alias for kECDHE */
# define SSL_TXT_kECDHE          "kECDHE"
# define SSL_TXT_kPSK            "kPSK"
# define SSL_TXT_kRSAPSK         "kRSAPSK"
# define SSL_TXT_kECDHEPSK       "kECDHEPSK"
# define SSL_TXT_kDHEPSK         "kDHEPSK"
# define SSL_TXT_kGOST           "kGOST"
# define SSL_TXT_kGOST18         "kGOST18"
# define SSL_TXT_kSRP            "kSRP"

# define SSL_TXT_aRSA            "aRSA"
# define SSL_TXT_aDSS            "aDSS"
# define SSL_TXT_aDH             "aDH"/* this cipher class has been removed */
# define SSL_TXT_aECDH           "aECDH"/* this cipher class has been removed */
# define SSL_TXT_aECDSA          "aECDSA"
# define SSL_TXT_aPSK            "aPSK"
# define SSL_TXT_aGOST94         "aGOST94"
# define SSL_TXT_aGOST01         "aGOST01"
# define SSL_TXT_aGOST12         "aGOST12"
# define SSL_TXT_aGOST           "aGOST"
# define SSL_TXT_aSRP            "aSRP"

# define SSL_TXT_DSS             "DSS"
# define SSL_TXT_DH              "DH"
# define SSL_TXT_DHE             "DHE"/* same as "kDHE:-ADH" */
# define SSL_TXT_EDH             "EDH"/* alias for DHE */
# define SSL_TXT_ADH             "ADH"
# define SSL_TXT_RSA             "RSA"
# define SSL_TXT_ECDH            "ECDH"
# define SSL_TXT_EECDH           "EECDH"/* alias for ECDHE" */
# define SSL_TXT_ECDHE           "ECDHE"/* same as "kECDHE:-AECDH" */
# define SSL_TXT_AECDH           "AECDH"
# define SSL_TXT_ECDSA           "ECDSA"
# define SSL_TXT_PSK             "PSK"
# define SSL_TXT_SRP             "SRP"

# define SSL_TXT_DES             "DES"
# define SSL_TXT_3DES            "3DES"
# define SSL_TXT_RC4             "RC4"
# define SSL_TXT_RC2             "RC2"
# define SSL_TXT_IDEA            "IDEA"
# define SSL_TXT_SEED            "SEED"
# define SSL_TXT_AES128          "AES128"
# define SSL_TXT_AES256          "AES256"
# define SSL_TXT_AES             "AES"
# define SSL_TXT_AES_GCM         "AESGCM"
# define SSL_TXT_AES_CCM         "AESCCM"
# define SSL_TXT_AES_CCM_8       "AESCCM8"
# define SSL_TXT_CAMELLIA128     "CAMELLIA128"
# define SSL_TXT_CAMELLIA256     "CAMELLIA256"
# define SSL_TXT_CAMELLIA        "CAMELLIA"
# define SSL_TXT_CHACHA20        "CHACHA20"
# define SSL_TXT_GOST            "GOST89"
# define SSL_TXT_ARIA            "ARIA"
# define SSL_TXT_ARIA_GCM        "ARIAGCM"
# define SSL_TXT_ARIA128         "ARIA128"
# define SSL_TXT_ARIA256         "ARIA256"
# define SSL_TXT_GOST2012_GOST8912_GOST8912 "GOST2012-GOST8912-GOST8912"
# define SSL_TXT_CBC             "CBC"

# define SSL_TXT_MD5             "MD5"
# define SSL_TXT_SHA1            "SHA1"
# define SSL_TXT_SHA             "SHA"/* same as "SHA1" */
# define SSL_TXT_GOST94          "GOST94"
# define SSL_TXT_GOST89MAC       "GOST89MAC"
# define SSL_TXT_GOST12          "GOST12"
# define SSL_TXT_GOST89MAC12     "GOST89MAC12"
# define SSL_TXT_SHA256          "SHA256"
# define SSL_TXT_SHA384          "SHA384"

# define SSL_TXT_SSLV3           "SSLv3"
# define SSL_TXT_TLSV1           "TLSv1"
# define SSL_TXT_TLSV1_1         "TLSv1.1"
# define SSL_TXT_TLSV1_2         "TLSv1.2"

# define SSL_TXT_ALL             "ALL"

/*-
 * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
 * ciphers normally not being used.
 * Example: "RC4" will activate all ciphers using RC4 including ciphers
 * without authentication, which would normally disabled by DEFAULT (due
 * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
 * will make sure that it is also disabled in the specific selection.
 * COMPLEMENTOF* identifiers are portable between version, as adjustments
 * to the default cipher setup will also be included here.
 *
 * COMPLEMENTOFDEFAULT does not experience the same special treatment that
 * DEFAULT gets, as only selection is being done and no sorting as needed
 * for DEFAULT.
 */
# define SSL_TXT_CMPALL          "COMPLEMENTOFALL"
# define SSL_TXT_CMPDEF          "COMPLEMENTOFDEFAULT"

/*
 * The following cipher list is used by default. It also is substituted when
 * an application-defined cipher list string starts with 'DEFAULT'.
 * This applies to ciphersuites for TLSv1.2 and below.
 * DEPRECATED IN 3.0.0, in favor of OSSL_default_cipher_list()
 * Update both macro and function simultaneously
 */
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL"
/*
 * This is the default set of TLSv1.3 ciphersuites
 * DEPRECATED IN 3.0.0, in favor of OSSL_default_ciphersuites()
 * Update both macro and function simultaneously
 */
#  define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
                                   "TLS_CHACHA20_POLY1305_SHA256:" \
                                   "TLS_AES_128_GCM_SHA256"
# endif
/*
 * As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always
 * starts with a reasonable order, and all we have to do for DEFAULT is
 * throwing out anonymous and unencrypted ciphersuites! (The latter are not
 * actually enabled by ALL, but "ALL:RSA" would enable some of them.)
 */

/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
# define SSL_SENT_SHUTDOWN       1
# define SSL_RECEIVED_SHUTDOWN   2

#ifdef __cplusplus
}
#endif

#ifdef  __cplusplus
extern "C" {
#endif

# define SSL_FILETYPE_ASN1       X509_FILETYPE_ASN1
# define SSL_FILETYPE_PEM        X509_FILETYPE_PEM

/*
 * This is needed to stop compilers complaining about the 'struct ssl_st *'
 * function parameters used to prototype callbacks in SSL_CTX.
 */
typedef struct ssl_st *ssl_crock_st;
typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
typedef struct ssl_method_st SSL_METHOD;
typedef struct ssl_cipher_st SSL_CIPHER;
typedef struct ssl_session_st SSL_SESSION;
typedef struct tls_sigalgs_st TLS_SIGALGS;
typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
typedef struct ssl_comp_st SSL_COMP;

STACK_OF(SSL_CIPHER);
STACK_OF(SSL_COMP);

/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/
typedef struct srtp_protection_profile_st {
    const char *name;
    unsigned long id;
} SRTP_PROTECTION_PROFILE;
SKM_DEFINE_STACK_OF_INTERNAL(SRTP_PROTECTION_PROFILE, SRTP_PROTECTION_PROFILE, SRTP_PROTECTION_PROFILE)
#define sk_SRTP_PROTECTION_PROFILE_num(sk) OPENSSL_sk_num(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_value(sk, idx) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_value(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk), (idx)))
#define sk_SRTP_PROTECTION_PROFILE_new(cmp) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_new(ossl_check_SRTP_PROTECTION_PROFILE_compfunc_type(cmp)))
#define sk_SRTP_PROTECTION_PROFILE_new_null() ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_new_null())
#define sk_SRTP_PROTECTION_PROFILE_new_reserve(cmp, n) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_new_reserve(ossl_check_SRTP_PROTECTION_PROFILE_compfunc_type(cmp), (n)))
#define sk_SRTP_PROTECTION_PROFILE_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), (n))
#define sk_SRTP_PROTECTION_PROFILE_free(sk) OPENSSL_sk_free(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_zero(sk) OPENSSL_sk_zero(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_delete(sk, i) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_delete(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), (i)))
#define sk_SRTP_PROTECTION_PROFILE_delete_ptr(sk, ptr) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_delete_ptr(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr)))
#define sk_SRTP_PROTECTION_PROFILE_push(sk, ptr) OPENSSL_sk_push(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_pop(sk) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_pop(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk)))
#define sk_SRTP_PROTECTION_PROFILE_shift(sk) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_shift(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk)))
#define sk_SRTP_PROTECTION_PROFILE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk),ossl_check_SRTP_PROTECTION_PROFILE_freefunc_type(freefunc))
#define sk_SRTP_PROTECTION_PROFILE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr), (idx))
#define sk_SRTP_PROTECTION_PROFILE_set(sk, idx, ptr) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_set(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), (idx), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr)))
#define sk_SRTP_PROTECTION_PROFILE_find(sk, ptr) OPENSSL_sk_find(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr), pnum)
#define sk_SRTP_PROTECTION_PROFILE_sort(sk) OPENSSL_sk_sort(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_dup(sk) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_dup(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk)))
#define sk_SRTP_PROTECTION_PROFILE_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_deep_copy(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_copyfunc_type(copyfunc), ossl_check_SRTP_PROTECTION_PROFILE_freefunc_type(freefunc)))
#define sk_SRTP_PROTECTION_PROFILE_set_cmp_func(sk, cmp) ((sk_SRTP_PROTECTION_PROFILE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_compfunc_type(cmp)))



typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data,
                                            int len, void *arg);
typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len,
                                        STACK_OF(SSL_CIPHER) *peer_ciphers,
                                        const SSL_CIPHER **cipher, void *arg);

/* Extension context codes */
/* This extension is only allowed in TLS */
#define SSL_EXT_TLS_ONLY                        0x0001
/* This extension is only allowed in DTLS */
#define SSL_EXT_DTLS_ONLY                       0x0002
/* Some extensions may be allowed in DTLS but we don't implement them for it */
#define SSL_EXT_TLS_IMPLEMENTATION_ONLY         0x0004
/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */
#define SSL_EXT_SSL3_ALLOWED                    0x0008
/* Extension is only defined for TLS1.2 and below */
#define SSL_EXT_TLS1_2_AND_BELOW_ONLY           0x0010
/* Extension is only defined for TLS1.3 and above */
#define SSL_EXT_TLS1_3_ONLY                     0x0020
/* Ignore this extension during parsing if we are resuming */
#define SSL_EXT_IGNORE_ON_RESUMPTION            0x0040
#define SSL_EXT_CLIENT_HELLO                    0x0080
/* Really means TLS1.2 or below */
#define SSL_EXT_TLS1_2_SERVER_HELLO             0x0100
#define SSL_EXT_TLS1_3_SERVER_HELLO             0x0200
#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS     0x0400
#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST      0x0800
#define SSL_EXT_TLS1_3_CERTIFICATE              0x1000
#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET       0x2000
#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST      0x4000

/* Typedefs for handling custom extensions */

typedef int (*custom_ext_add_cb)(SSL *s, unsigned int ext_type,
                                 const unsigned char **out, size_t *outlen,
                                 int *al, void *add_arg);

typedef void (*custom_ext_free_cb)(SSL *s, unsigned int ext_type,
                                   const unsigned char *out, void *add_arg);

typedef int (*custom_ext_parse_cb)(SSL *s, unsigned int ext_type,
                                   const unsigned char *in, size_t inlen,
                                   int *al, void *parse_arg);


typedef int (*SSL_custom_ext_add_cb_ex)(SSL *s, unsigned int ext_type,
                                        unsigned int context,
                                        const unsigned char **out,
                                        size_t *outlen, X509 *x,
                                        size_t chainidx,
                                        int *al, void *add_arg);

typedef void (*SSL_custom_ext_free_cb_ex)(SSL *s, unsigned int ext_type,
                                          unsigned int context,
                                          const unsigned char *out,
                                          void *add_arg);

typedef int (*SSL_custom_ext_parse_cb_ex)(SSL *s, unsigned int ext_type,
                                          unsigned int context,
                                          const unsigned char *in,
                                          size_t inlen, X509 *x,
                                          size_t chainidx,
                                          int *al, void *parse_arg);

/* Typedef for verification callback */
typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);

/* Typedef for SSL async callback */
typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);

#define SSL_OP_BIT(n)  ((uint64_t)1 << (uint64_t)n)

/*
 * SSL/TLS connection options.
 */
    /* Disable Extended master secret */
# define SSL_OP_NO_EXTENDED_MASTER_SECRET                SSL_OP_BIT(0)
    /* Cleanse plaintext copies of data delivered to the application */
# define SSL_OP_CLEANSE_PLAINTEXT                        SSL_OP_BIT(1)
    /* Allow initial connection to servers that don't support RI */
# define SSL_OP_LEGACY_SERVER_CONNECT                    SSL_OP_BIT(2)
    /* Enable support for Kernel TLS */
# define SSL_OP_ENABLE_KTLS                              SSL_OP_BIT(3)
# define SSL_OP_TLSEXT_PADDING                           SSL_OP_BIT(4)
# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG                   SSL_OP_BIT(6)
# define SSL_OP_IGNORE_UNEXPECTED_EOF                    SSL_OP_BIT(7)
# define SSL_OP_ALLOW_CLIENT_RENEGOTIATION               SSL_OP_BIT(8)
# define SSL_OP_DISABLE_TLSEXT_CA_NAMES                  SSL_OP_BIT(9)
    /* In TLSv1.3 allow a non-(ec)dhe based kex_mode */
# define SSL_OP_ALLOW_NO_DHE_KEX                         SSL_OP_BIT(10)
    /*
     * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
     * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
     * the workaround is not needed.  Unfortunately some broken SSL/TLS
     * implementations cannot handle it at all, which is why we include it
     * in SSL_OP_ALL. Added in 0.9.6e
     */
# define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              SSL_OP_BIT(11)
    /* DTLS options */
# define SSL_OP_NO_QUERY_MTU                             SSL_OP_BIT(12)
    /* Turn on Cookie Exchange (on relevant for servers) */
# define SSL_OP_COOKIE_EXCHANGE                          SSL_OP_BIT(13)
    /* Don't use RFC4507 ticket extension */
# define SSL_OP_NO_TICKET                                SSL_OP_BIT(14)
# ifndef OPENSSL_NO_DTLS1_METHOD
    /*
     * Use Cisco's version identifier of DTLS_BAD_VER
     * (only with deprecated DTLSv1_client_method())
     */
#  define SSL_OP_CISCO_ANYCONNECT                        SSL_OP_BIT(15)
# endif
    /* As server, disallow session resumption on renegotiation */
# define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION   SSL_OP_BIT(16)
    /* Don't use compression even if supported */
# define SSL_OP_NO_COMPRESSION                           SSL_OP_BIT(17)
    /* Permit unsafe legacy renegotiation */
# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION        SSL_OP_BIT(18)
    /* Disable encrypt-then-mac */
# define SSL_OP_NO_ENCRYPT_THEN_MAC                      SSL_OP_BIT(19)
    /*
     * Enable TLSv1.3 Compatibility mode. This is on by default. A future
     * version of OpenSSL may have this disabled by default.
     */
# define SSL_OP_ENABLE_MIDDLEBOX_COMPAT                  SSL_OP_BIT(20)
    /*
     * Prioritize Chacha20Poly1305 when client does.
     * Modifies SSL_OP_CIPHER_SERVER_PREFERENCE
     */
# define SSL_OP_PRIORITIZE_CHACHA                        SSL_OP_BIT(21)
    /*
     * Set on servers to choose the cipher according to server's preferences.
     */
# define SSL_OP_CIPHER_SERVER_PREFERENCE                 SSL_OP_BIT(22)
    /*
     * If set, a server will allow a client to issue a SSLv3.0 version
     * number as latest version supported in the premaster secret, even when
     * TLSv1.0 (version 3.1) was announced in the client hello. Normally
     * this is forbidden to prevent version rollback attacks.
     */
# define SSL_OP_TLS_ROLLBACK_BUG                         SSL_OP_BIT(23)
    /*
     * Switches off automatic TLSv1.3 anti-replay protection for early data.
     * This is a server-side option only (no effect on the client).
     */
# define SSL_OP_NO_ANTI_REPLAY                           SSL_OP_BIT(24)
# define SSL_OP_NO_SSLv3                                 SSL_OP_BIT(25)
# define SSL_OP_NO_TLSv1                                 SSL_OP_BIT(26)
# define SSL_OP_NO_TLSv1_2                               SSL_OP_BIT(27)
# define SSL_OP_NO_TLSv1_1                               SSL_OP_BIT(28)
# define SSL_OP_NO_TLSv1_3                               SSL_OP_BIT(29)
# define SSL_OP_NO_DTLSv1                                SSL_OP_BIT(26)
# define SSL_OP_NO_DTLSv1_2                              SSL_OP_BIT(27)
    /* Disallow all renegotiation */
# define SSL_OP_NO_RENEGOTIATION                         SSL_OP_BIT(30)
    /*
     * Make server add server-hello extension from early version of
     * cryptopro draft, when GOST ciphersuite is negotiated. Required for
     * interoperability with CryptoPro CSP 3.x
     */
# define SSL_OP_CRYPTOPRO_TLSEXT_BUG                     SSL_OP_BIT(31)

/*
 * Option "collections."
 */
# define SSL_OP_NO_SSL_MASK \
        ( SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 \
          | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3 )
# define SSL_OP_NO_DTLS_MASK \
        ( SSL_OP_NO_DTLSv1 | SSL_OP_NO_DTLSv1_2 )

/* Various bug workarounds that should be rather harmless. */
# define SSL_OP_ALL \
        ( SSL_OP_CRYPTOPRO_TLSEXT_BUG | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS \
          | SSL_OP_TLSEXT_PADDING | SSL_OP_SAFARI_ECDHE_ECDSA_BUG )

/*
 * OBSOLETE OPTIONS retained for compatibility
 */

# define SSL_OP_MICROSOFT_SESS_ID_BUG                    0x0
# define SSL_OP_NETSCAPE_CHALLENGE_BUG                   0x0
# define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG         0x0
# define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG              0x0
# define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER               0x0
# define SSL_OP_MSIE_SSLV2_RSA_PADDING                   0x0
# define SSL_OP_SSLEAY_080_CLIENT_DH_BUG                 0x0
# define SSL_OP_TLS_D5_BUG                               0x0
# define SSL_OP_TLS_BLOCK_PADDING_BUG                    0x0
# define SSL_OP_SINGLE_ECDH_USE                          0x0
# define SSL_OP_SINGLE_DH_USE                            0x0
# define SSL_OP_EPHEMERAL_RSA                            0x0
# define SSL_OP_NO_SSLv2                                 0x0
# define SSL_OP_PKCS1_CHECK_1                            0x0
# define SSL_OP_PKCS1_CHECK_2                            0x0
# define SSL_OP_NETSCAPE_CA_DN_BUG                       0x0
# define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG          0x0

/*
 * Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
 * when just a single record has been written):
 */
# define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001U
/*
 * Make it possible to retry SSL_write() with changed buffer location (buffer
 * contents must stay the same!); this is not the default to avoid the
 * misconception that non-blocking SSL_write() behaves like non-blocking
 * write():
 */
# define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002U
/*
 * Never bother the application with retries if the transport is blocking:
 */
# define SSL_MODE_AUTO_RETRY 0x00000004U
/* Don't attempt to automatically build certificate chain */
# define SSL_MODE_NO_AUTO_CHAIN 0x00000008U
/*
 * Save RAM by releasing read and write buffers when they're empty. (SSL3 and
 * TLS only.) Released buffers are freed.
 */
# define SSL_MODE_RELEASE_BUFFERS 0x00000010U
/*
 * Send the current time in the Random fields of the ClientHello and
 * ServerHello records for compatibility with hypothetical implementations
 * that require it.
 */
# define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020U
# define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040U
/*
 * Send TLS_FALLBACK_SCSV in the ClientHello. To be set only by applications
 * that reconnect with a downgraded protocol version; see
 * draft-ietf-tls-downgrade-scsv-00 for details. DO NOT ENABLE THIS if your
 * application attempts a normal handshake. Only use this in explicit
 * fallback retries, following the guidance in
 * draft-ietf-tls-downgrade-scsv-00.
 */
# define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080U
/*
 * Support Asynchronous operation
 */
# define SSL_MODE_ASYNC 0x00000100U

/*
 * When using DTLS/SCTP, include the terminating zero in the label
 * used for computing the endpoint-pair shared secret. Required for
 * interoperability with implementations having this bug like these
 * older version of OpenSSL:
 * - OpenSSL 1.0.0 series
 * - OpenSSL 1.0.1 series
 * - OpenSSL 1.0.2 series
 * - OpenSSL 1.1.0 series
 * - OpenSSL 1.1.1 and 1.1.1a
 */
# define SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG 0x00000400U

/* Cert related flags */
/*
 * Many implementations ignore some aspects of the TLS standards such as
 * enforcing certificate chain algorithms. When this is set we enforce them.
 */
# define SSL_CERT_FLAG_TLS_STRICT                0x00000001U

/* Suite B modes, takes same values as certificate verify flags */
# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY       0x10000
/* Suite B 192 bit only mode */
# define SSL_CERT_FLAG_SUITEB_192_LOS            0x20000
/* Suite B 128 bit mode allowing 192 bit algorithms */
# define SSL_CERT_FLAG_SUITEB_128_LOS            0x30000

/* Perform all sorts of protocol violations for testing purposes */
# define SSL_CERT_FLAG_BROKEN_PROTOCOL           0x10000000

/* Flags for building certificate chains */
/* Treat any existing certificates as untrusted CAs */
# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED          0x1
/* Don't include root CA in chain */
# define SSL_BUILD_CHAIN_FLAG_NO_ROOT            0x2
/* Just check certificates already there */
# define SSL_BUILD_CHAIN_FLAG_CHECK              0x4
/* Ignore verification errors */
# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR       0x8
/* Clear verification errors from queue */
# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR        0x10

/* Flags returned by SSL_check_chain */
/* Certificate can be used with this session */
# define CERT_PKEY_VALID         0x1
/* Certificate can also be used for signing */
# define CERT_PKEY_SIGN          0x2
/* EE certificate signing algorithm OK */
# define CERT_PKEY_EE_SIGNATURE  0x10
/* CA signature algorithms OK */
# define CERT_PKEY_CA_SIGNATURE  0x20
/* EE certificate parameters OK */
# define CERT_PKEY_EE_PARAM      0x40
/* CA certificate parameters OK */
# define CERT_PKEY_CA_PARAM      0x80
/* Signing explicitly allowed as opposed to SHA1 fallback */
# define CERT_PKEY_EXPLICIT_SIGN 0x100
/* Client CA issuer names match (always set for server cert) */
# define CERT_PKEY_ISSUER_NAME   0x200
/* Cert type matches client types (always set for server cert) */
# define CERT_PKEY_CERT_TYPE     0x400
/* Cert chain suitable to Suite B */
# define CERT_PKEY_SUITEB        0x800

# define SSL_CONF_FLAG_CMDLINE           0x1
# define SSL_CONF_FLAG_FILE              0x2
# define SSL_CONF_FLAG_CLIENT            0x4
# define SSL_CONF_FLAG_SERVER            0x8
# define SSL_CONF_FLAG_SHOW_ERRORS       0x10
# define SSL_CONF_FLAG_CERTIFICATE       0x20
# define SSL_CONF_FLAG_REQUIRE_PRIVATE   0x40
/* Configuration value types */
# define SSL_CONF_TYPE_UNKNOWN           0x0
# define SSL_CONF_TYPE_STRING            0x1
# define SSL_CONF_TYPE_FILE              0x2
# define SSL_CONF_TYPE_DIR               0x3
# define SSL_CONF_TYPE_NONE              0x4
# define SSL_CONF_TYPE_STORE             0x5

/* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */
# define SSL_COOKIE_LENGTH                       4096

/*
 * Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they
 * cannot be used to clear bits.
 */

uint64_t SSL_CTX_get_options(const SSL_CTX *ctx);
uint64_t SSL_get_options(const SSL *s);
uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op);
uint64_t SSL_clear_options(SSL *s, uint64_t op);
uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op);
uint64_t SSL_set_options(SSL *s, uint64_t op);

# define SSL_CTX_set_mode(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
# define SSL_CTX_clear_mode(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
# define SSL_CTX_get_mode(ctx) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
# define SSL_clear_mode(ssl,op) \
        SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
# define SSL_set_mode(ssl,op) \
        SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
# define SSL_get_mode(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
# define SSL_set_mtu(ssl, mtu) \
        SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
# define DTLS_set_link_mtu(ssl, mtu) \
        SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL)
# define DTLS_get_link_min_mtu(ssl) \
        SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL)

# define SSL_get_secure_renegotiation_support(ssl) \
        SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)

# define SSL_CTX_set_cert_flags(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL)
# define SSL_set_cert_flags(s,op) \
        SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL)
# define SSL_CTX_clear_cert_flags(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
# define SSL_clear_cert_flags(s,op) \
        SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)

void SSL_CTX_set_msg_callback(SSL_CTX *ctx,
                              void (*cb) (int write_p, int version,
                                          int content_type, const void *buf,
                                          size_t len, SSL *ssl, void *arg));
void SSL_set_msg_callback(SSL *ssl,
                          void (*cb) (int write_p, int version,
                                      int content_type, const void *buf,
                                      size_t len, SSL *ssl, void *arg));
# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))

# define SSL_get_extms_support(s) \
        SSL_ctrl((s),SSL_CTRL_GET_EXTMS_SUPPORT,0,NULL)

# ifndef OPENSSL_NO_SRP
/* see tls_srp.c */
#  ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 __owur int SSL_SRP_CTX_init(SSL *s);
OSSL_DEPRECATEDIN_3_0 __owur int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx);
OSSL_DEPRECATEDIN_3_0 int SSL_SRP_CTX_free(SSL *ctx);
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx);
OSSL_DEPRECATEDIN_3_0 __owur int SSL_srp_server_param_with_username(SSL *s,
                                                                    int *ad);
OSSL_DEPRECATEDIN_3_0 __owur int SRP_Calc_A_param(SSL *s);
#  endif
# endif

/* 100k max cert list */
# define SSL_MAX_CERT_LIST_DEFAULT (1024*100)

# define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT      (1024*20)

/*
 * This callback type is used inside SSL_CTX, SSL, and in the functions that
 * set them. It is used to override the generation of SSL/TLS session IDs in
 * a server. Return value should be zero on an error, non-zero to proceed.
 * Also, callbacks should themselves check if the id they generate is unique
 * otherwise the SSL handshake will fail with an error - callbacks can do
 * this using the 'ssl' value they're passed by;
 * SSL_has_matching_session_id(ssl, id, *id_len) The length value passed in
 * is set at the maximum size the session ID can be. In SSLv3/TLSv1 it is 32
 * bytes. The callback can alter this length to be less if desired. It is
 * also an error for the callback to set the size to zero.
 */
typedef int (*GEN_SESSION_CB) (SSL *ssl, unsigned char *id,
                               unsigned int *id_len);

# define SSL_SESS_CACHE_OFF                      0x0000
# define SSL_SESS_CACHE_CLIENT                   0x0001
# define SSL_SESS_CACHE_SERVER                   0x0002
# define SSL_SESS_CACHE_BOTH     (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
# define SSL_SESS_CACHE_NO_AUTO_CLEAR            0x0080
/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
# define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP       0x0100
# define SSL_SESS_CACHE_NO_INTERNAL_STORE        0x0200
# define SSL_SESS_CACHE_NO_INTERNAL \
        (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
# define SSL_SESS_CACHE_UPDATE_TIME              0x0400

LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
# define SSL_CTX_sess_number(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
# define SSL_CTX_sess_connect(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
# define SSL_CTX_sess_connect_good(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
# define SSL_CTX_sess_connect_renegotiate(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
# define SSL_CTX_sess_accept(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
# define SSL_CTX_sess_accept_renegotiate(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
# define SSL_CTX_sess_accept_good(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
# define SSL_CTX_sess_hits(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
# define SSL_CTX_sess_cb_hits(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
# define SSL_CTX_sess_misses(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
# define SSL_CTX_sess_timeouts(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
# define SSL_CTX_sess_cache_full(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)

void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
                             int (*new_session_cb) (struct ssl_st *ssl,
                                                    SSL_SESSION *sess));
int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
                                              SSL_SESSION *sess);
void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
                                void (*remove_session_cb) (struct ssl_ctx_st
                                                           *ctx,
                                                           SSL_SESSION *sess));
void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (struct ssl_ctx_st *ctx,
                                                  SSL_SESSION *sess);
void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
                             SSL_SESSION *(*get_session_cb) (struct ssl_st
                                                             *ssl,
                                                             const unsigned char
                                                             *data, int len,
                                                             int *copy));
SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
                                                       const unsigned char *data,
                                                       int len, int *copy);
void SSL_CTX_set_info_callback(SSL_CTX *ctx,
                               void (*cb) (const SSL *ssl, int type, int val));
void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type,
                                                 int val);
void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
                                int (*client_cert_cb) (SSL *ssl, X509 **x509,
                                                       EVP_PKEY **pkey));
int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
                                                 EVP_PKEY **pkey);
# ifndef OPENSSL_NO_ENGINE
__owur int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
# endif
void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
                                    int (*app_gen_cookie_cb) (SSL *ssl,
                                                              unsigned char
                                                              *cookie,
                                                              unsigned int
                                                              *cookie_len));
void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
                                  int (*app_verify_cookie_cb) (SSL *ssl,
                                                               const unsigned
                                                               char *cookie,
                                                               unsigned int
                                                               cookie_len));

void SSL_CTX_set_stateless_cookie_generate_cb(
    SSL_CTX *ctx,
    int (*gen_stateless_cookie_cb) (SSL *ssl,
                                    unsigned char *cookie,
                                    size_t *cookie_len));
void SSL_CTX_set_stateless_cookie_verify_cb(
    SSL_CTX *ctx,
    int (*verify_stateless_cookie_cb) (SSL *ssl,
                                       const unsigned char *cookie,
                                       size_t cookie_len));
# ifndef OPENSSL_NO_NEXTPROTONEG

typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl,
                                              const unsigned char **out,
                                              unsigned int *outlen,
                                              void *arg);
void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s,
                                           SSL_CTX_npn_advertised_cb_func cb,
                                           void *arg);
#  define SSL_CTX_set_npn_advertised_cb SSL_CTX_set_next_protos_advertised_cb

typedef int (*SSL_CTX_npn_select_cb_func)(SSL *s,
                                          unsigned char **out,
                                          unsigned char *outlen,
                                          const unsigned char *in,
                                          unsigned int inlen,
                                          void *arg);
void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
                                      SSL_CTX_npn_select_cb_func cb,
                                      void *arg);
#  define SSL_CTX_set_npn_select_cb SSL_CTX_set_next_proto_select_cb

void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
                                    unsigned *len);
#  define SSL_get0_npn_negotiated SSL_get0_next_proto_negotiated
# endif

__owur int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
                                 const unsigned char *in, unsigned int inlen,
                                 const unsigned char *client,
                                 unsigned int client_len);

# define OPENSSL_NPN_UNSUPPORTED 0
# define OPENSSL_NPN_NEGOTIATED  1
# define OPENSSL_NPN_NO_OVERLAP  2

__owur int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
                                   unsigned int protos_len);
__owur int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
                               unsigned int protos_len);
typedef int (*SSL_CTX_alpn_select_cb_func)(SSL *ssl,
                                           const unsigned char **out,
                                           unsigned char *outlen,
                                           const unsigned char *in,
                                           unsigned int inlen,
                                           void *arg);
void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
                                SSL_CTX_alpn_select_cb_func cb,
                                void *arg);
void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
                            unsigned int *len);

# ifndef OPENSSL_NO_PSK
/*
 * the maximum length of the buffer given to callbacks containing the
 * resulting identity/psk
 */
#  define PSK_MAX_IDENTITY_LEN 256
#  define PSK_MAX_PSK_LEN 512
typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl,
                                               const char *hint,
                                               char *identity,
                                               unsigned int max_identity_len,
                                               unsigned char *psk,
                                               unsigned int max_psk_len);
void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb);
void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb);

typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl,
                                               const char *identity,
                                               unsigned char *psk,
                                               unsigned int max_psk_len);
void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb);
void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb);

__owur int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
__owur int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
const char *SSL_get_psk_identity_hint(const SSL *s);
const char *SSL_get_psk_identity(const SSL *s);
# endif

typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl,
                                            const unsigned char *identity,
                                            size_t identity_len,
                                            SSL_SESSION **sess);
typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md,
                                           const unsigned char **id,
                                           size_t *idlen,
                                           SSL_SESSION **sess);

void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb);
void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx,
                                           SSL_psk_find_session_cb_func cb);
void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb);
void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx,
                                          SSL_psk_use_session_cb_func cb);

/* Register callbacks to handle custom TLS Extensions for client or server. */

__owur int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx,
                                         unsigned int ext_type);

__owur int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx,
                                         unsigned int ext_type,
                                         custom_ext_add_cb add_cb,
                                         custom_ext_free_cb free_cb,
                                         void *add_arg,
                                         custom_ext_parse_cb parse_cb,
                                         void *parse_arg);

__owur int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx,
                                         unsigned int ext_type,
                                         custom_ext_add_cb add_cb,
                                         custom_ext_free_cb free_cb,
                                         void *add_arg,
                                         custom_ext_parse_cb parse_cb,
                                         void *parse_arg);

__owur int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
                                  unsigned int context,
                                  SSL_custom_ext_add_cb_ex add_cb,
                                  SSL_custom_ext_free_cb_ex free_cb,
                                  void *add_arg,
                                  SSL_custom_ext_parse_cb_ex parse_cb,
                                  void *parse_arg);

__owur int SSL_extension_supported(unsigned int ext_type);

# define SSL_NOTHING            1
# define SSL_WRITING            2
# define SSL_READING            3
# define SSL_X509_LOOKUP        4
# define SSL_ASYNC_PAUSED       5
# define SSL_ASYNC_NO_JOBS      6
# define SSL_CLIENT_HELLO_CB    7
# define SSL_RETRY_VERIFY       8

/* These will only be used when doing non-blocking IO */
# define SSL_want_nothing(s)         (SSL_want(s) == SSL_NOTHING)
# define SSL_want_read(s)            (SSL_want(s) == SSL_READING)
# define SSL_want_write(s)           (SSL_want(s) == SSL_WRITING)
# define SSL_want_x509_lookup(s)     (SSL_want(s) == SSL_X509_LOOKUP)
# define SSL_want_retry_verify(s)    (SSL_want(s) == SSL_RETRY_VERIFY)
# define SSL_want_async(s)           (SSL_want(s) == SSL_ASYNC_PAUSED)
# define SSL_want_async_job(s)       (SSL_want(s) == SSL_ASYNC_NO_JOBS)
# define SSL_want_client_hello_cb(s) (SSL_want(s) == SSL_CLIENT_HELLO_CB)

# define SSL_MAC_FLAG_READ_MAC_STREAM 1
# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
# define SSL_MAC_FLAG_READ_MAC_TLSTREE 4
# define SSL_MAC_FLAG_WRITE_MAC_TLSTREE 8

/*
 * A callback for logging out TLS key material. This callback should log out
 * |line| followed by a newline.
 */
typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line);

/*
 * SSL_CTX_set_keylog_callback configures a callback to log key material. This
 * is intended for debugging use with tools like Wireshark. The cb function
 * should log line followed by a newline.
 */
void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb);

/*
 * SSL_CTX_get_keylog_callback returns the callback configured by
 * SSL_CTX_set_keylog_callback.
 */
SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx);

int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data);
uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
uint32_t SSL_get_max_early_data(const SSL *s);
int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data);
uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx);
int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data);
uint32_t SSL_get_recv_max_early_data(const SSL *s);

#ifdef __cplusplus
}
#endif

# include <openssl/ssl2.h>
# include <openssl/ssl3.h>
# include <openssl/tls1.h>      /* This is mostly sslv3 with a few tweaks */
# include <openssl/dtls1.h>     /* Datagram TLS */
# include <openssl/srtp.h>      /* Support for the use_srtp extension */

#ifdef  __cplusplus
extern "C" {
#endif

/*
 * These need to be after the above set of includes due to a compiler bug
 * in VisualStudio 2015
 */
SKM_DEFINE_STACK_OF_INTERNAL(SSL_CIPHER, const SSL_CIPHER, SSL_CIPHER)
#define sk_SSL_CIPHER_num(sk) OPENSSL_sk_num(ossl_check_const_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_value(sk, idx) ((const SSL_CIPHER *)OPENSSL_sk_value(ossl_check_const_SSL_CIPHER_sk_type(sk), (idx)))
#define sk_SSL_CIPHER_new(cmp) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_new(ossl_check_SSL_CIPHER_compfunc_type(cmp)))
#define sk_SSL_CIPHER_new_null() ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_new_null())
#define sk_SSL_CIPHER_new_reserve(cmp, n) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_new_reserve(ossl_check_SSL_CIPHER_compfunc_type(cmp), (n)))
#define sk_SSL_CIPHER_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_SSL_CIPHER_sk_type(sk), (n))
#define sk_SSL_CIPHER_free(sk) OPENSSL_sk_free(ossl_check_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_zero(sk) OPENSSL_sk_zero(ossl_check_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_delete(sk, i) ((const SSL_CIPHER *)OPENSSL_sk_delete(ossl_check_SSL_CIPHER_sk_type(sk), (i)))
#define sk_SSL_CIPHER_delete_ptr(sk, ptr) ((const SSL_CIPHER *)OPENSSL_sk_delete_ptr(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr)))
#define sk_SSL_CIPHER_push(sk, ptr) OPENSSL_sk_push(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_pop(sk) ((const SSL_CIPHER *)OPENSSL_sk_pop(ossl_check_SSL_CIPHER_sk_type(sk)))
#define sk_SSL_CIPHER_shift(sk) ((const SSL_CIPHER *)OPENSSL_sk_shift(ossl_check_SSL_CIPHER_sk_type(sk)))
#define sk_SSL_CIPHER_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SSL_CIPHER_sk_type(sk),ossl_check_SSL_CIPHER_freefunc_type(freefunc))
#define sk_SSL_CIPHER_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr), (idx))
#define sk_SSL_CIPHER_set(sk, idx, ptr) ((const SSL_CIPHER *)OPENSSL_sk_set(ossl_check_SSL_CIPHER_sk_type(sk), (idx), ossl_check_SSL_CIPHER_type(ptr)))
#define sk_SSL_CIPHER_find(sk, ptr) OPENSSL_sk_find(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr), pnum)
#define sk_SSL_CIPHER_sort(sk) OPENSSL_sk_sort(ossl_check_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_dup(sk) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_dup(ossl_check_const_SSL_CIPHER_sk_type(sk)))
#define sk_SSL_CIPHER_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_deep_copy(ossl_check_const_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_copyfunc_type(copyfunc), ossl_check_SSL_CIPHER_freefunc_type(freefunc)))
#define sk_SSL_CIPHER_set_cmp_func(sk, cmp) ((sk_SSL_CIPHER_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_compfunc_type(cmp)))
SKM_DEFINE_STACK_OF_INTERNAL(SSL_COMP, SSL_COMP, SSL_COMP)
#define sk_SSL_COMP_num(sk) OPENSSL_sk_num(ossl_check_const_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_value(sk, idx) ((SSL_COMP *)OPENSSL_sk_value(ossl_check_const_SSL_COMP_sk_type(sk), (idx)))
#define sk_SSL_COMP_new(cmp) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_new(ossl_check_SSL_COMP_compfunc_type(cmp)))
#define sk_SSL_COMP_new_null() ((STACK_OF(SSL_COMP) *)OPENSSL_sk_new_null())
#define sk_SSL_COMP_new_reserve(cmp, n) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_new_reserve(ossl_check_SSL_COMP_compfunc_type(cmp), (n)))
#define sk_SSL_COMP_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_SSL_COMP_sk_type(sk), (n))
#define sk_SSL_COMP_free(sk) OPENSSL_sk_free(ossl_check_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_zero(sk) OPENSSL_sk_zero(ossl_check_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_delete(sk, i) ((SSL_COMP *)OPENSSL_sk_delete(ossl_check_SSL_COMP_sk_type(sk), (i)))
#define sk_SSL_COMP_delete_ptr(sk, ptr) ((SSL_COMP *)OPENSSL_sk_delete_ptr(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr)))
#define sk_SSL_COMP_push(sk, ptr) OPENSSL_sk_push(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_pop(sk) ((SSL_COMP *)OPENSSL_sk_pop(ossl_check_SSL_COMP_sk_type(sk)))
#define sk_SSL_COMP_shift(sk) ((SSL_COMP *)OPENSSL_sk_shift(ossl_check_SSL_COMP_sk_type(sk)))
#define sk_SSL_COMP_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SSL_COMP_sk_type(sk),ossl_check_SSL_COMP_freefunc_type(freefunc))
#define sk_SSL_COMP_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr), (idx))
#define sk_SSL_COMP_set(sk, idx, ptr) ((SSL_COMP *)OPENSSL_sk_set(ossl_check_SSL_COMP_sk_type(sk), (idx), ossl_check_SSL_COMP_type(ptr)))
#define sk_SSL_COMP_find(sk, ptr) OPENSSL_sk_find(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr), pnum)
#define sk_SSL_COMP_sort(sk) OPENSSL_sk_sort(ossl_check_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_dup(sk) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_dup(ossl_check_const_SSL_COMP_sk_type(sk)))
#define sk_SSL_COMP_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_deep_copy(ossl_check_const_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_copyfunc_type(copyfunc), ossl_check_SSL_COMP_freefunc_type(freefunc)))
#define sk_SSL_COMP_set_cmp_func(sk, cmp) ((sk_SSL_COMP_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_compfunc_type(cmp)))


/* compatibility */
# define SSL_set_app_data(s,arg)         (SSL_set_ex_data(s,0,(char *)(arg)))
# define SSL_get_app_data(s)             (SSL_get_ex_data(s,0))
# define SSL_SESSION_set_app_data(s,a)   (SSL_SESSION_set_ex_data(s,0, \
                                                                  (char *)(a)))
# define SSL_SESSION_get_app_data(s)     (SSL_SESSION_get_ex_data(s,0))
# define SSL_CTX_get_app_data(ctx)       (SSL_CTX_get_ex_data(ctx,0))
# define SSL_CTX_set_app_data(ctx,arg)   (SSL_CTX_set_ex_data(ctx,0, \
                                                              (char *)(arg)))
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 void SSL_set_debug(SSL *s, int debug);
# endif

/* TLSv1.3 KeyUpdate message types */
/* -1 used so that this is an invalid value for the on-the-wire protocol */
#define SSL_KEY_UPDATE_NONE             -1
/* Values as defined for the on-the-wire protocol */
#define SSL_KEY_UPDATE_NOT_REQUESTED     0
#define SSL_KEY_UPDATE_REQUESTED         1

/*
 * The valid handshake states (one for each type message sent and one for each
 * type of message received). There are also two "special" states:
 * TLS = TLS or DTLS state
 * DTLS = DTLS specific state
 * CR/SR = Client Read/Server Read
 * CW/SW = Client Write/Server Write
 *
 * The "special" states are:
 * TLS_ST_BEFORE = No handshake has been initiated yet
 * TLS_ST_OK = A handshake has been successfully completed
 */
typedef enum {
    TLS_ST_BEFORE,
    TLS_ST_OK,
    DTLS_ST_CR_HELLO_VERIFY_REQUEST,
    TLS_ST_CR_SRVR_HELLO,
    TLS_ST_CR_CERT,
    TLS_ST_CR_CERT_STATUS,
    TLS_ST_CR_KEY_EXCH,
    TLS_ST_CR_CERT_REQ,
    TLS_ST_CR_SRVR_DONE,
    TLS_ST_CR_SESSION_TICKET,
    TLS_ST_CR_CHANGE,
    TLS_ST_CR_FINISHED,
    TLS_ST_CW_CLNT_HELLO,
    TLS_ST_CW_CERT,
    TLS_ST_CW_KEY_EXCH,
    TLS_ST_CW_CERT_VRFY,
    TLS_ST_CW_CHANGE,
    TLS_ST_CW_NEXT_PROTO,
    TLS_ST_CW_FINISHED,
    TLS_ST_SW_HELLO_REQ,
    TLS_ST_SR_CLNT_HELLO,
    DTLS_ST_SW_HELLO_VERIFY_REQUEST,
    TLS_ST_SW_SRVR_HELLO,
    TLS_ST_SW_CERT,
    TLS_ST_SW_KEY_EXCH,
    TLS_ST_SW_CERT_REQ,
    TLS_ST_SW_SRVR_DONE,
    TLS_ST_SR_CERT,
    TLS_ST_SR_KEY_EXCH,
    TLS_ST_SR_CERT_VRFY,
    TLS_ST_SR_NEXT_PROTO,
    TLS_ST_SR_CHANGE,
    TLS_ST_SR_FINISHED,
    TLS_ST_SW_SESSION_TICKET,
    TLS_ST_SW_CERT_STATUS,
    TLS_ST_SW_CHANGE,
    TLS_ST_SW_FINISHED,
    TLS_ST_SW_ENCRYPTED_EXTENSIONS,
    TLS_ST_CR_ENCRYPTED_EXTENSIONS,
    TLS_ST_CR_CERT_VRFY,
    TLS_ST_SW_CERT_VRFY,
    TLS_ST_CR_HELLO_REQ,
    TLS_ST_SW_KEY_UPDATE,
    TLS_ST_CW_KEY_UPDATE,
    TLS_ST_SR_KEY_UPDATE,
    TLS_ST_CR_KEY_UPDATE,
    TLS_ST_EARLY_DATA,
    TLS_ST_PENDING_EARLY_DATA_END,
    TLS_ST_CW_END_OF_EARLY_DATA,
    TLS_ST_SR_END_OF_EARLY_DATA
} OSSL_HANDSHAKE_STATE;

/*
 * Most of the following state values are no longer used and are defined to be
 * the closest equivalent value in the current state machine code. Not all
 * defines have an equivalent and are set to a dummy value (-1). SSL_ST_CONNECT
 * and SSL_ST_ACCEPT are still in use in the definition of SSL_CB_ACCEPT_LOOP,
 * SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP and SSL_CB_CONNECT_EXIT.
 */

# define SSL_ST_CONNECT                  0x1000
# define SSL_ST_ACCEPT                   0x2000

# define SSL_ST_MASK                     0x0FFF

# define SSL_CB_LOOP                     0x01
# define SSL_CB_EXIT                     0x02
# define SSL_CB_READ                     0x04
# define SSL_CB_WRITE                    0x08
# define SSL_CB_ALERT                    0x4000/* used in callback */
# define SSL_CB_READ_ALERT               (SSL_CB_ALERT|SSL_CB_READ)
# define SSL_CB_WRITE_ALERT              (SSL_CB_ALERT|SSL_CB_WRITE)
# define SSL_CB_ACCEPT_LOOP              (SSL_ST_ACCEPT|SSL_CB_LOOP)
# define SSL_CB_ACCEPT_EXIT              (SSL_ST_ACCEPT|SSL_CB_EXIT)
# define SSL_CB_CONNECT_LOOP             (SSL_ST_CONNECT|SSL_CB_LOOP)
# define SSL_CB_CONNECT_EXIT             (SSL_ST_CONNECT|SSL_CB_EXIT)
# define SSL_CB_HANDSHAKE_START          0x10
# define SSL_CB_HANDSHAKE_DONE           0x20

/* Is the SSL_connection established? */
# define SSL_in_connect_init(a)          (SSL_in_init(a) && !SSL_is_server(a))
# define SSL_in_accept_init(a)           (SSL_in_init(a) && SSL_is_server(a))
int SSL_in_init(const SSL *s);
int SSL_in_before(const SSL *s);
int SSL_is_init_finished(const SSL *s);

/*
 * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you
 * should not need these
 */
# define SSL_ST_READ_HEADER                      0xF0
# define SSL_ST_READ_BODY                        0xF1
# define SSL_ST_READ_DONE                        0xF2

/*-
 * Obtain latest Finished message
 *   -- that we sent (SSL_get_finished)
 *   -- that we expected from peer (SSL_get_peer_finished).
 * Returns length (0 == no Finished so far), copies up to 'count' bytes.
 */
size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);

/*
 * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options are
 * 'ored' with SSL_VERIFY_PEER if they are desired
 */
# define SSL_VERIFY_NONE                 0x00
# define SSL_VERIFY_PEER                 0x01
# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
# define SSL_VERIFY_CLIENT_ONCE          0x04
# define SSL_VERIFY_POST_HANDSHAKE       0x08

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define OpenSSL_add_ssl_algorithms()   SSL_library_init()
#  define SSLeay_add_ssl_algorithms()    SSL_library_init()
# endif

/* More backward compatibility */
# define SSL_get_cipher(s) \
                SSL_CIPHER_get_name(SSL_get_current_cipher(s))
# define SSL_get_cipher_bits(s,np) \
                SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
# define SSL_get_cipher_version(s) \
                SSL_CIPHER_get_version(SSL_get_current_cipher(s))
# define SSL_get_cipher_name(s) \
                SSL_CIPHER_get_name(SSL_get_current_cipher(s))
# define SSL_get_time(a)         SSL_SESSION_get_time(a)
# define SSL_set_time(a,b)       SSL_SESSION_set_time((a),(b))
# define SSL_get_timeout(a)      SSL_SESSION_get_timeout(a)
# define SSL_set_timeout(a,b)    SSL_SESSION_set_timeout((a),(b))

# define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
# define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)

DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_AD_REASON_OFFSET            1000/* offset to get SSL_R_... value
                                              * from SSL_AD_... */
/* These alert types are for SSLv3 and TLSv1 */
# define SSL_AD_CLOSE_NOTIFY             SSL3_AD_CLOSE_NOTIFY
/* fatal */
# define SSL_AD_UNEXPECTED_MESSAGE       SSL3_AD_UNEXPECTED_MESSAGE
/* fatal */
# define SSL_AD_BAD_RECORD_MAC           SSL3_AD_BAD_RECORD_MAC
# define SSL_AD_DECRYPTION_FAILED        TLS1_AD_DECRYPTION_FAILED
# define SSL_AD_RECORD_OVERFLOW          TLS1_AD_RECORD_OVERFLOW
/* fatal */
# define SSL_AD_DECOMPRESSION_FAILURE    SSL3_AD_DECOMPRESSION_FAILURE
/* fatal */
# define SSL_AD_HANDSHAKE_FAILURE        SSL3_AD_HANDSHAKE_FAILURE
/* Not for TLS */
# define SSL_AD_NO_CERTIFICATE           SSL3_AD_NO_CERTIFICATE
# define SSL_AD_BAD_CERTIFICATE          SSL3_AD_BAD_CERTIFICATE
# define SSL_AD_UNSUPPORTED_CERTIFICATE  SSL3_AD_UNSUPPORTED_CERTIFICATE
# define SSL_AD_CERTIFICATE_REVOKED      SSL3_AD_CERTIFICATE_REVOKED
# define SSL_AD_CERTIFICATE_EXPIRED      SSL3_AD_CERTIFICATE_EXPIRED
# define SSL_AD_CERTIFICATE_UNKNOWN      SSL3_AD_CERTIFICATE_UNKNOWN
/* fatal */
# define SSL_AD_ILLEGAL_PARAMETER        SSL3_AD_ILLEGAL_PARAMETER
/* fatal */
# define SSL_AD_UNKNOWN_CA               TLS1_AD_UNKNOWN_CA
/* fatal */
# define SSL_AD_ACCESS_DENIED            TLS1_AD_ACCESS_DENIED
/* fatal */
# define SSL_AD_DECODE_ERROR             TLS1_AD_DECODE_ERROR
# define SSL_AD_DECRYPT_ERROR            TLS1_AD_DECRYPT_ERROR
/* fatal */
# define SSL_AD_EXPORT_RESTRICTION       TLS1_AD_EXPORT_RESTRICTION
/* fatal */
# define SSL_AD_PROTOCOL_VERSION         TLS1_AD_PROTOCOL_VERSION
/* fatal */
# define SSL_AD_INSUFFICIENT_SECURITY    TLS1_AD_INSUFFICIENT_SECURITY
/* fatal */
# define SSL_AD_INTERNAL_ERROR           TLS1_AD_INTERNAL_ERROR
# define SSL_AD_USER_CANCELLED           TLS1_AD_USER_CANCELLED
# define SSL_AD_NO_RENEGOTIATION         TLS1_AD_NO_RENEGOTIATION
# define SSL_AD_MISSING_EXTENSION        TLS13_AD_MISSING_EXTENSION
# define SSL_AD_CERTIFICATE_REQUIRED     TLS13_AD_CERTIFICATE_REQUIRED
# define SSL_AD_UNSUPPORTED_EXTENSION    TLS1_AD_UNSUPPORTED_EXTENSION
# define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
# define SSL_AD_UNRECOGNIZED_NAME        TLS1_AD_UNRECOGNIZED_NAME
# define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
# define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
/* fatal */
# define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY
/* fatal */
# define SSL_AD_INAPPROPRIATE_FALLBACK   TLS1_AD_INAPPROPRIATE_FALLBACK
# define SSL_AD_NO_APPLICATION_PROTOCOL  TLS1_AD_NO_APPLICATION_PROTOCOL
# define SSL_ERROR_NONE                  0
# define SSL_ERROR_SSL                   1
# define SSL_ERROR_WANT_READ             2
# define SSL_ERROR_WANT_WRITE            3
# define SSL_ERROR_WANT_X509_LOOKUP      4
# define SSL_ERROR_SYSCALL               5/* look at error stack/return
                                           * value/errno */
# define SSL_ERROR_ZERO_RETURN           6
# define SSL_ERROR_WANT_CONNECT          7
# define SSL_ERROR_WANT_ACCEPT           8
# define SSL_ERROR_WANT_ASYNC            9
# define SSL_ERROR_WANT_ASYNC_JOB       10
# define SSL_ERROR_WANT_CLIENT_HELLO_CB 11
# define SSL_ERROR_WANT_RETRY_VERIFY    12

# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTRL_SET_TMP_DH                    3
#  define SSL_CTRL_SET_TMP_ECDH                  4
#  define SSL_CTRL_SET_TMP_DH_CB                 6
# endif

# define SSL_CTRL_GET_CLIENT_CERT_REQUEST        9
# define SSL_CTRL_GET_NUM_RENEGOTIATIONS         10
# define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS       11
# define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS       12
# define SSL_CTRL_GET_FLAGS                      13
# define SSL_CTRL_EXTRA_CHAIN_CERT               14
# define SSL_CTRL_SET_MSG_CALLBACK               15
# define SSL_CTRL_SET_MSG_CALLBACK_ARG           16
/* only applies to datagram connections */
# define SSL_CTRL_SET_MTU                17
/* Stats */
# define SSL_CTRL_SESS_NUMBER                    20
# define SSL_CTRL_SESS_CONNECT                   21
# define SSL_CTRL_SESS_CONNECT_GOOD              22
# define SSL_CTRL_SESS_CONNECT_RENEGOTIATE       23
# define SSL_CTRL_SESS_ACCEPT                    24
# define SSL_CTRL_SESS_ACCEPT_GOOD               25
# define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE        26
# define SSL_CTRL_SESS_HIT                       27
# define SSL_CTRL_SESS_CB_HIT                    28
# define SSL_CTRL_SESS_MISSES                    29
# define SSL_CTRL_SESS_TIMEOUTS                  30
# define SSL_CTRL_SESS_CACHE_FULL                31
# define SSL_CTRL_MODE                           33
# define SSL_CTRL_GET_READ_AHEAD                 40
# define SSL_CTRL_SET_READ_AHEAD                 41
# define SSL_CTRL_SET_SESS_CACHE_SIZE            42
# define SSL_CTRL_GET_SESS_CACHE_SIZE            43
# define SSL_CTRL_SET_SESS_CACHE_MODE            44
# define SSL_CTRL_GET_SESS_CACHE_MODE            45
# define SSL_CTRL_GET_MAX_CERT_LIST              50
# define SSL_CTRL_SET_MAX_CERT_LIST              51
# define SSL_CTRL_SET_MAX_SEND_FRAGMENT          52
/* see tls1.h for macros based on these */
# define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB       53
# define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG      54
# define SSL_CTRL_SET_TLSEXT_HOSTNAME            55
# define SSL_CTRL_SET_TLSEXT_DEBUG_CB            56
# define SSL_CTRL_SET_TLSEXT_DEBUG_ARG           57
# define SSL_CTRL_GET_TLSEXT_TICKET_KEYS         58
# define SSL_CTRL_SET_TLSEXT_TICKET_KEYS         59
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT    60 */
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 61 */
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 */
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB       63
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG   64
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE     65
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS     66
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS     67
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS      68
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS      69
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP        70
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP        71
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB      72
# endif
# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB    75
# define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB                76
# define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB             77
# define SSL_CTRL_SET_SRP_ARG            78
# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME               79
# define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH               80
# define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD               81
# define DTLS_CTRL_GET_TIMEOUT           73
# define DTLS_CTRL_HANDLE_TIMEOUT        74
# define SSL_CTRL_GET_RI_SUPPORT                 76
# define SSL_CTRL_CLEAR_MODE                     78
# define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB      79
# define SSL_CTRL_GET_EXTRA_CHAIN_CERTS          82
# define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS        83
# define SSL_CTRL_CHAIN                          88
# define SSL_CTRL_CHAIN_CERT                     89
# define SSL_CTRL_GET_GROUPS                     90
# define SSL_CTRL_SET_GROUPS                     91
# define SSL_CTRL_SET_GROUPS_LIST                92
# define SSL_CTRL_GET_SHARED_GROUP               93
# define SSL_CTRL_SET_SIGALGS                    97
# define SSL_CTRL_SET_SIGALGS_LIST               98
# define SSL_CTRL_CERT_FLAGS                     99
# define SSL_CTRL_CLEAR_CERT_FLAGS               100
# define SSL_CTRL_SET_CLIENT_SIGALGS             101
# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST        102
# define SSL_CTRL_GET_CLIENT_CERT_TYPES          103
# define SSL_CTRL_SET_CLIENT_CERT_TYPES          104
# define SSL_CTRL_BUILD_CERT_CHAIN               105
# define SSL_CTRL_SET_VERIFY_CERT_STORE          106
# define SSL_CTRL_SET_CHAIN_CERT_STORE           107
# define SSL_CTRL_GET_PEER_SIGNATURE_NID         108
# define SSL_CTRL_GET_PEER_TMP_KEY               109
# define SSL_CTRL_GET_RAW_CIPHERLIST             110
# define SSL_CTRL_GET_EC_POINT_FORMATS           111
# define SSL_CTRL_GET_CHAIN_CERTS                115
# define SSL_CTRL_SELECT_CURRENT_CERT            116
# define SSL_CTRL_SET_CURRENT_CERT               117
# define SSL_CTRL_SET_DH_AUTO                    118
# define DTLS_CTRL_SET_LINK_MTU                  120
# define DTLS_CTRL_GET_LINK_MIN_MTU              121
# define SSL_CTRL_GET_EXTMS_SUPPORT              122
# define SSL_CTRL_SET_MIN_PROTO_VERSION          123
# define SSL_CTRL_SET_MAX_PROTO_VERSION          124
# define SSL_CTRL_SET_SPLIT_SEND_FRAGMENT        125
# define SSL_CTRL_SET_MAX_PIPELINES              126
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE     127
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB       128
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG   129
# define SSL_CTRL_GET_MIN_PROTO_VERSION          130
# define SSL_CTRL_GET_MAX_PROTO_VERSION          131
# define SSL_CTRL_GET_SIGNATURE_NID              132
# define SSL_CTRL_GET_TMP_KEY                    133
# define SSL_CTRL_GET_NEGOTIATED_GROUP           134
# define SSL_CTRL_SET_RETRY_VERIFY               136
# define SSL_CTRL_GET_VERIFY_CERT_STORE          137
# define SSL_CTRL_GET_CHAIN_CERT_STORE           138
# define SSL_CERT_SET_FIRST                      1
# define SSL_CERT_SET_NEXT                       2
# define SSL_CERT_SET_SERVER                     3
# define DTLSv1_get_timeout(ssl, arg) \
        SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)(arg))
# define DTLSv1_handle_timeout(ssl) \
        SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
# define SSL_num_renegotiations(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
# define SSL_clear_num_renegotiations(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
# define SSL_total_renegotiations(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTX_set_tmp_dh(ctx,dh) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
# endif
# define SSL_CTX_set_dh_auto(ctx, onoff) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
# define SSL_set_dh_auto(s, onoff) \
        SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_set_tmp_dh(ssl,dh) \
        SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
# endif
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
#  define SSL_set_tmp_ecdh(ssl,ecdh) \
        SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
# endif
# define SSL_CTX_add_extra_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)(x509))
# define SSL_CTX_get_extra_chain_certs(ctx,px509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509)
# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509)
# define SSL_CTX_clear_extra_chain_certs(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL)
# define SSL_CTX_set0_chain(ctx,sk) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk))
# define SSL_CTX_set1_chain(ctx,sk) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk))
# define SSL_CTX_add0_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
# define SSL_CTX_add1_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
# define SSL_CTX_get0_chain_certs(ctx,px509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
# define SSL_CTX_clear_chain_certs(ctx) \
        SSL_CTX_set0_chain(ctx,NULL)
# define SSL_CTX_build_cert_chain(ctx, flags) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
# define SSL_CTX_select_current_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
# define SSL_CTX_set_current_cert(ctx, op) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
# define SSL_CTX_set0_verify_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set1_verify_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
# define SSL_CTX_get0_verify_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set0_chain_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set1_chain_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
# define SSL_CTX_get0_chain_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_set0_chain(s,sk) \
        SSL_ctrl(s,SSL_CTRL_CHAIN,0,(char *)(sk))
# define SSL_set1_chain(s,sk) \
        SSL_ctrl(s,SSL_CTRL_CHAIN,1,(char *)(sk))
# define SSL_add0_chain_cert(s,x509) \
        SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
# define SSL_add1_chain_cert(s,x509) \
        SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
# define SSL_get0_chain_certs(s,px509) \
        SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
# define SSL_clear_chain_certs(s) \
        SSL_set0_chain(s,NULL)
# define SSL_build_cert_chain(s, flags) \
        SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
# define SSL_select_current_cert(s,x509) \
        SSL_ctrl(s,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
# define SSL_set_current_cert(s,op) \
        SSL_ctrl(s,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
# define SSL_set0_verify_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_set1_verify_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
#define SSL_get0_verify_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_set0_chain_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_set1_chain_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
#define SSL_get0_chain_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))

# define SSL_get1_groups(s, glist) \
        SSL_ctrl(s,SSL_CTRL_GET_GROUPS,0,(int*)(glist))
# define SSL_CTX_set1_groups(ctx, glist, glistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(int *)(glist))
# define SSL_CTX_set1_groups_list(ctx, s) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s))
# define SSL_set1_groups(s, glist, glistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist))
# define SSL_set1_groups_list(s, str) \
        SSL_ctrl(s,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(str))
# define SSL_get_shared_group(s, n) \
        SSL_ctrl(s,SSL_CTRL_GET_SHARED_GROUP,n,NULL)
# define SSL_get_negotiated_group(s) \
        SSL_ctrl(s,SSL_CTRL_GET_NEGOTIATED_GROUP,0,NULL)
# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
# define SSL_CTX_set1_sigalgs_list(ctx, s) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s))
# define SSL_set1_sigalgs(s, slist, slistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
# define SSL_set1_sigalgs_list(s, str) \
        SSL_ctrl(s,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(str))
# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s))
# define SSL_set1_client_sigalgs(s, slist, slistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
# define SSL_set1_client_sigalgs_list(s, str) \
        SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(str))
# define SSL_get0_certificate_types(s, clist) \
        SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)(clist))
# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen, \
                     (char *)(clist))
# define SSL_set1_client_certificate_types(s, clist, clistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)(clist))
# define SSL_get_signature_nid(s, pn) \
        SSL_ctrl(s,SSL_CTRL_GET_SIGNATURE_NID,0,pn)
# define SSL_get_peer_signature_nid(s, pn) \
        SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn)
# define SSL_get_peer_tmp_key(s, pk) \
        SSL_ctrl(s,SSL_CTRL_GET_PEER_TMP_KEY,0,pk)
# define SSL_get_tmp_key(s, pk) \
        SSL_ctrl(s,SSL_CTRL_GET_TMP_KEY,0,pk)
# define SSL_get0_raw_cipherlist(s, plst) \
        SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,plst)
# define SSL_get0_ec_point_formats(s, plst) \
        SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,plst)
# define SSL_CTX_set_min_proto_version(ctx, version) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
# define SSL_CTX_set_max_proto_version(ctx, version) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
# define SSL_CTX_get_min_proto_version(ctx) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
# define SSL_CTX_get_max_proto_version(ctx) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)
# define SSL_set_min_proto_version(s, version) \
        SSL_ctrl(s, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
# define SSL_set_max_proto_version(s, version) \
        SSL_ctrl(s, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
# define SSL_get_min_proto_version(s) \
        SSL_ctrl(s, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
# define SSL_get_max_proto_version(s) \
        SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)

const char *SSL_group_to_name(SSL *s, int id);

/* Backwards compatibility, original 1.1.0 names */
# define SSL_CTRL_GET_SERVER_TMP_KEY \
         SSL_CTRL_GET_PEER_TMP_KEY
# define SSL_get_server_tmp_key(s, pk) \
         SSL_get_peer_tmp_key(s, pk)

int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey);
int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey);

/*
 * The following symbol names are old and obsolete. They are kept
 * for compatibility reasons only and should not be used anymore.
 */
# define SSL_CTRL_GET_CURVES           SSL_CTRL_GET_GROUPS
# define SSL_CTRL_SET_CURVES           SSL_CTRL_SET_GROUPS
# define SSL_CTRL_SET_CURVES_LIST      SSL_CTRL_SET_GROUPS_LIST
# define SSL_CTRL_GET_SHARED_CURVE     SSL_CTRL_GET_SHARED_GROUP

# define SSL_get1_curves               SSL_get1_groups
# define SSL_CTX_set1_curves           SSL_CTX_set1_groups
# define SSL_CTX_set1_curves_list      SSL_CTX_set1_groups_list
# define SSL_set1_curves               SSL_set1_groups
# define SSL_set1_curves_list          SSL_set1_groups_list
# define SSL_get_shared_curve          SSL_get_shared_group


# ifndef OPENSSL_NO_DEPRECATED_1_1_0
/* Provide some compatibility macros for removed functionality. */
#  define SSL_CTX_need_tmp_RSA(ctx)                0
#  define SSL_CTX_set_tmp_rsa(ctx,rsa)             1
#  define SSL_need_tmp_RSA(ssl)                    0
#  define SSL_set_tmp_rsa(ssl,rsa)                 1
#  define SSL_CTX_set_ecdh_auto(dummy, onoff)      ((onoff) != 0)
#  define SSL_set_ecdh_auto(dummy, onoff)          ((onoff) != 0)
/*
 * We "pretend" to call the callback to avoid warnings about unused static
 * functions.
 */
#  define SSL_CTX_set_tmp_rsa_callback(ctx, cb)    while(0) (cb)(NULL, 0, 0)
#  define SSL_set_tmp_rsa_callback(ssl, cb)        while(0) (cb)(NULL, 0, 0)
# endif
__owur const BIO_METHOD *BIO_f_ssl(void);
__owur BIO *BIO_new_ssl(SSL_CTX *ctx, int client);
__owur BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
__owur BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
__owur int BIO_ssl_copy_session_id(BIO *to, BIO *from);
void BIO_ssl_shutdown(BIO *ssl_bio);

__owur int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str);
__owur SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
__owur SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
                               const SSL_METHOD *meth);
int SSL_CTX_up_ref(SSL_CTX *ctx);
void SSL_CTX_free(SSL_CTX *);
__owur long SSL_CTX_set_timeout(SSL_CTX *ctx, long t);
__owur long SSL_CTX_get_timeout(const SSL_CTX *ctx);
__owur X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
void SSL_CTX_set1_cert_store(SSL_CTX *, X509_STORE *);
__owur int SSL_want(const SSL *s);
__owur int SSL_clear(SSL *s);

void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm);

__owur const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
__owur const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s);
__owur int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits);
__owur const char *SSL_CIPHER_get_version(const SSL_CIPHER *c);
__owur const char *SSL_CIPHER_get_name(const SSL_CIPHER *c);
__owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c);
__owur const char *OPENSSL_cipher_name(const char *rfc_name);
__owur uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c);
__owur uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c);
__owur int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c);
__owur int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c);
__owur const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c);
__owur int SSL_CIPHER_is_aead(const SSL_CIPHER *c);

__owur int SSL_get_fd(const SSL *s);
__owur int SSL_get_rfd(const SSL *s);
__owur int SSL_get_wfd(const SSL *s);
__owur const char *SSL_get_cipher_list(const SSL *s, int n);
__owur char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size);
__owur int SSL_get_read_ahead(const SSL *s);
__owur int SSL_pending(const SSL *s);
__owur int SSL_has_pending(const SSL *s);
# ifndef OPENSSL_NO_SOCK
__owur int SSL_set_fd(SSL *s, int fd);
__owur int SSL_set_rfd(SSL *s, int fd);
__owur int SSL_set_wfd(SSL *s, int fd);
# endif
void SSL_set0_rbio(SSL *s, BIO *rbio);
void SSL_set0_wbio(SSL *s, BIO *wbio);
void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio);
__owur BIO *SSL_get_rbio(const SSL *s);
__owur BIO *SSL_get_wbio(const SSL *s);
__owur int SSL_set_cipher_list(SSL *s, const char *str);
__owur int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
__owur int SSL_set_ciphersuites(SSL *s, const char *str);
void SSL_set_read_ahead(SSL *s, int yes);
__owur int SSL_get_verify_mode(const SSL *s);
__owur int SSL_get_verify_depth(const SSL *s);
__owur SSL_verify_cb SSL_get_verify_callback(const SSL *s);
void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback);
void SSL_set_verify_depth(SSL *s, int depth);
void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg);
# ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 __owur int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
OSSL_DEPRECATEDIN_3_0
__owur int SSL_use_RSAPrivateKey_ASN1(SSL *ssl,
                                      const unsigned char *d, long len);
# endif
__owur int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
__owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d,
                                   long len);
__owur int SSL_use_certificate(SSL *ssl, X509 *x);
__owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
__owur int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey,
                                STACK_OF(X509) *chain, int override);


/* serverinfo file format versions */
# define SSL_SERVERINFOV1   1
# define SSL_SERVERINFOV2   2

/* Set serverinfo data for the current active cert. */
__owur int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
                                  size_t serverinfo_length);
__owur int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
                                     const unsigned char *serverinfo,
                                     size_t serverinfo_length);
__owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file);

#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
#endif

__owur int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
__owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type);

#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file,
                                          int type);
#endif
__owur int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file,
                                       int type);
__owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,
                                        int type);
/* PEM type */
__owur int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
__owur int SSL_use_certificate_chain_file(SSL *ssl, const char *file);
__owur STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
__owur STACK_OF(X509_NAME)
*SSL_load_client_CA_file_ex(const char *file, OSSL_LIB_CTX *libctx,
                            const char *propq);
__owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                               const char *file);
int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                       const char *dir);
int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                       const char *uri);

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_load_error_strings() \
    OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
                     | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
# endif

__owur const char *SSL_state_string(const SSL *s);
__owur const char *SSL_rstate_string(const SSL *s);
__owur const char *SSL_state_string_long(const SSL *s);
__owur const char *SSL_rstate_string_long(const SSL *s);
__owur long SSL_SESSION_get_time(const SSL_SESSION *s);
__owur long SSL_SESSION_set_time(SSL_SESSION *s, long t);
__owur long SSL_SESSION_get_timeout(const SSL_SESSION *s);
__owur long SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
__owur int SSL_SESSION_get_protocol_version(const SSL_SESSION *s);
__owur int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version);

__owur const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s);
__owur int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname);
void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s,
                                    const unsigned char **alpn,
                                    size_t *len);
__owur int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s,
                                          const unsigned char *alpn,
                                          size_t len);
__owur const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s);
__owur int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher);
__owur int SSL_SESSION_has_ticket(const SSL_SESSION *s);
__owur unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s);
void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
                             size_t *len);
__owur uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s);
__owur int SSL_SESSION_set_max_early_data(SSL_SESSION *s,
                                          uint32_t max_early_data);
__owur int SSL_copy_session_id(SSL *to, const SSL *from);
__owur X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
__owur int SSL_SESSION_set1_id_context(SSL_SESSION *s,
                                       const unsigned char *sid_ctx,
                                       unsigned int sid_ctx_len);
__owur int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
                               unsigned int sid_len);
__owur int SSL_SESSION_is_resumable(const SSL_SESSION *s);

__owur SSL_SESSION *SSL_SESSION_new(void);
__owur SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src);
const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
                                        unsigned int *len);
const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s,
                                                 unsigned int *len);
__owur unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s);
# ifndef OPENSSL_NO_STDIO
int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses);
# endif
int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses);
int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x);
int SSL_SESSION_up_ref(SSL_SESSION *ses);
void SSL_SESSION_free(SSL_SESSION *ses);
__owur int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp);
__owur int SSL_set_session(SSL *to, SSL_SESSION *session);
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session);
int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session);
__owur int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb);
__owur int SSL_set_generate_session_id(SSL *s, GEN_SESSION_CB cb);
__owur int SSL_has_matching_session_id(const SSL *s,
                                       const unsigned char *id,
                                       unsigned int id_len);
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
                             long length);

# ifdef OPENSSL_X509_H
__owur X509 *SSL_get0_peer_certificate(const SSL *s);
__owur X509 *SSL_get1_peer_certificate(const SSL *s);
/* Deprecated in 3.0.0 */
#  ifndef OPENSSL_NO_DEPRECATED_3_0
#   define SSL_get_peer_certificate SSL_get1_peer_certificate
#  endif
# endif

__owur STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);

__owur int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
__owur int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
__owur SSL_verify_cb SSL_CTX_get_verify_callback(const SSL_CTX *ctx);
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback);
void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
                                      int (*cb) (X509_STORE_CTX *, void *),
                                      void *arg);
void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg),
                         void *arg);
# ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d,
                                          long len);
# endif
__owur int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
__owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx,
                                       const unsigned char *d, long len);
__owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
__owur int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len,
                                        const unsigned char *d);
__owur int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey,
                                    STACK_OF(X509) *chain, int override);

void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx);
void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx);
void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb);
void SSL_set_default_passwd_cb_userdata(SSL *s, void *u);
pem_password_cb *SSL_get_default_passwd_cb(SSL *s);
void *SSL_get_default_passwd_cb_userdata(SSL *s);

__owur int SSL_CTX_check_private_key(const SSL_CTX *ctx);
__owur int SSL_check_private_key(const SSL *ctx);

__owur int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
                                          const unsigned char *sid_ctx,
                                          unsigned int sid_ctx_len);

SSL *SSL_new(SSL_CTX *ctx);
int SSL_up_ref(SSL *s);
int SSL_is_dtls(const SSL *s);
__owur int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
                                      unsigned int sid_ctx_len);

__owur int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose);
__owur int SSL_set_purpose(SSL *ssl, int purpose);
__owur int SSL_CTX_set_trust(SSL_CTX *ctx, int trust);
__owur int SSL_set_trust(SSL *ssl, int trust);

__owur int SSL_set1_host(SSL *s, const char *hostname);
__owur int SSL_add1_host(SSL *s, const char *hostname);
__owur const char *SSL_get0_peername(SSL *s);
void SSL_set_hostflags(SSL *s, unsigned int flags);

__owur int SSL_CTX_dane_enable(SSL_CTX *ctx);
__owur int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md,
                                  uint8_t mtype, uint8_t ord);
__owur int SSL_dane_enable(SSL *s, const char *basedomain);
__owur int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
                             uint8_t mtype, const unsigned char *data, size_t dlen);
__owur int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki);
__owur int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
                              uint8_t *mtype, const unsigned char **data,
                              size_t *dlen);
/*
 * Bridge opacity barrier between libcrypt and libssl, also needed to support
 * offline testing in test/danetest.c
 */
SSL_DANE *SSL_get0_dane(SSL *ssl);
/*
 * DANE flags
 */
unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags);
unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags);
unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags);
unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags);

__owur int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
__owur int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);

__owur X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx);
__owur X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);

# ifndef OPENSSL_NO_SRP
#  ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name);
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password);
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength);
OSSL_DEPRECATEDIN_3_0
int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
                                        char *(*cb) (SSL *, void *));
OSSL_DEPRECATEDIN_3_0
int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
                                          int (*cb) (SSL *, void *));
OSSL_DEPRECATEDIN_3_0
int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
                                      int (*cb) (SSL *, int *, void *));
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg);

OSSL_DEPRECATEDIN_3_0
int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
                             BIGNUM *sa, BIGNUM *v, char *info);
OSSL_DEPRECATEDIN_3_0
int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
                                const char *grp);

OSSL_DEPRECATEDIN_3_0 __owur BIGNUM *SSL_get_srp_g(SSL *s);
OSSL_DEPRECATEDIN_3_0 __owur BIGNUM *SSL_get_srp_N(SSL *s);

OSSL_DEPRECATEDIN_3_0 __owur char *SSL_get_srp_username(SSL *s);
OSSL_DEPRECATEDIN_3_0 __owur char *SSL_get_srp_userinfo(SSL *s);
#  endif
# endif

/*
 * ClientHello callback and helpers.
 */

# define SSL_CLIENT_HELLO_SUCCESS 1
# define SSL_CLIENT_HELLO_ERROR   0
# define SSL_CLIENT_HELLO_RETRY   (-1)

typedef int (*SSL_client_hello_cb_fn) (SSL *s, int *al, void *arg);
void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb,
                                 void *arg);
int SSL_client_hello_isv2(SSL *s);
unsigned int SSL_client_hello_get0_legacy_version(SSL *s);
size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_compression_methods(SSL *s,
                                                 const unsigned char **out);
int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen);
int SSL_client_hello_get0_ext(SSL *s, unsigned int type,
                              const unsigned char **out, size_t *outlen);

void SSL_certs_clear(SSL *s);
void SSL_free(SSL *ssl);
# ifdef OSSL_ASYNC_FD
/*
 * Windows application developer has to include windows.h to use these.
 */
__owur int SSL_waiting_for_async(SSL *s);
__owur int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds);
__owur int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd,
                                     size_t *numaddfds, OSSL_ASYNC_FD *delfd,
                                     size_t *numdelfds);
__owur int SSL_CTX_set_async_callback(SSL_CTX *ctx, SSL_async_callback_fn callback);
__owur int SSL_CTX_set_async_callback_arg(SSL_CTX *ctx, void *arg);
__owur int SSL_set_async_callback(SSL *s, SSL_async_callback_fn callback);
__owur int SSL_set_async_callback_arg(SSL *s, void *arg);
__owur int SSL_get_async_status(SSL *s, int *status);

# endif
__owur int SSL_accept(SSL *ssl);
__owur int SSL_stateless(SSL *s);
__owur int SSL_connect(SSL *ssl);
__owur int SSL_read(SSL *ssl, void *buf, int num);
__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);

# define SSL_READ_EARLY_DATA_ERROR   0
# define SSL_READ_EARLY_DATA_SUCCESS 1
# define SSL_READ_EARLY_DATA_FINISH  2

__owur int SSL_read_early_data(SSL *s, void *buf, size_t num,
                               size_t *readbytes);
__owur int SSL_peek(SSL *ssl, void *buf, int num);
__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
__owur ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size,
                                 int flags);
__owur int SSL_write(SSL *ssl, const void *buf, int num);
__owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
__owur int SSL_write_early_data(SSL *s, const void *buf, size_t num,
                                size_t *written);
long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg);
long SSL_callback_ctrl(SSL *, int, void (*)(void));
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));

# define SSL_EARLY_DATA_NOT_SENT    0
# define SSL_EARLY_DATA_REJECTED    1
# define SSL_EARLY_DATA_ACCEPTED    2

__owur int SSL_get_early_data_status(const SSL *s);

__owur int SSL_get_error(const SSL *s, int ret_code);
__owur const char *SSL_get_version(const SSL *s);

/* This sets the 'default' SSL version that SSL_new() will create */
# ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
# endif

# ifndef OPENSSL_NO_SSL3_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_method(void); /* SSLv3 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_client_method(void);
#  endif
# endif

#define SSLv23_method           TLS_method
#define SSLv23_server_method    TLS_server_method
#define SSLv23_client_method    TLS_client_method

/* Negotiate highest available SSL/TLS version */
__owur const SSL_METHOD *TLS_method(void);
__owur const SSL_METHOD *TLS_server_method(void);
__owur const SSL_METHOD *TLS_client_method(void);

# ifndef OPENSSL_NO_TLS1_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_TLS1_1_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_method(void); /* TLSv1.1 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_TLS1_2_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_method(void); /* TLSv1.2 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_DTLS1_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_DTLS1_2_METHOD
/* DTLSv1.2 */
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_client_method(void);
#  endif
# endif

__owur const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */
__owur const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */
__owur const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */

__owur size_t DTLS_get_data_mtu(const SSL *s);

__owur STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
__owur STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
__owur STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s);
__owur STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s);

__owur int SSL_do_handshake(SSL *s);
int SSL_key_update(SSL *s, int updatetype);
int SSL_get_key_update_type(const SSL *s);
int SSL_renegotiate(SSL *s);
int SSL_renegotiate_abbreviated(SSL *s);
__owur int SSL_renegotiate_pending(const SSL *s);
int SSL_new_session_ticket(SSL *s);
int SSL_shutdown(SSL *s);
__owur int SSL_verify_client_post_handshake(SSL *s);
void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val);
void SSL_set_post_handshake_auth(SSL *s, int val);

__owur const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx);
__owur const SSL_METHOD *SSL_get_ssl_method(const SSL *s);
__owur int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
__owur const char *SSL_alert_type_string_long(int value);
__owur const char *SSL_alert_type_string(int value);
__owur const char *SSL_alert_desc_string_long(int value);
__owur const char *SSL_alert_desc_string(int value);

void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
__owur const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s);
__owur const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx);
__owur int SSL_add1_to_CA_list(SSL *ssl, const X509 *x);
__owur int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x);
__owur const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s);

void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
__owur STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
__owur STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
__owur int SSL_add_client_CA(SSL *ssl, X509 *x);
__owur int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x);

void SSL_set_connect_state(SSL *s);
void SSL_set_accept_state(SSL *s);

__owur long SSL_get_default_timeout(const SSL *s);

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_library_init() OPENSSL_init_ssl(0, NULL)
# endif

__owur char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size);
__owur STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk);

__owur SSL *SSL_dup(SSL *ssl);

__owur X509 *SSL_get_certificate(const SSL *ssl);
/*
 * EVP_PKEY
 */
struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl);

__owur X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx);
__owur EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx);

void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode);
__owur int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
void SSL_set_quiet_shutdown(SSL *ssl, int mode);
__owur int SSL_get_quiet_shutdown(const SSL *ssl);
void SSL_set_shutdown(SSL *ssl, int mode);
__owur int SSL_get_shutdown(const SSL *ssl);
__owur int SSL_version(const SSL *ssl);
__owur int SSL_client_version(const SSL *s);
__owur int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_store(SSL_CTX *ctx);
__owur int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile);
__owur int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath);
__owur int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore);
__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx,
                                                        const char *CAfile,
                                                        const char *CApath);
# define SSL_get0_session SSL_get_session/* just peek at pointer */
__owur SSL_SESSION *SSL_get_session(const SSL *ssl);
__owur SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
__owur SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
void SSL_set_info_callback(SSL *ssl,
                           void (*cb) (const SSL *ssl, int type, int val));
void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type,
                                               int val);
__owur OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl);

void SSL_set_verify_result(SSL *ssl, long v);
__owur long SSL_get_verify_result(const SSL *ssl);
__owur STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s);

__owur size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
                                    size_t outlen);
__owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
                                    size_t outlen);
__owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *sess,
                                         unsigned char *out, size_t outlen);
__owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess,
                                       const unsigned char *in, size_t len);
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *sess);

#define SSL_get_ex_new_index(l, p, newf, dupf, freef) \
    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef)
__owur int SSL_set_ex_data(SSL *ssl, int idx, void *data);
void *SSL_get_ex_data(const SSL *ssl, int idx);
#define SSL_SESSION_get_ex_new_index(l, p, newf, dupf, freef) \
    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, l, p, newf, dupf, freef)
__owur int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data);
void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx);
#define SSL_CTX_get_ex_new_index(l, p, newf, dupf, freef) \
    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, l, p, newf, dupf, freef)
__owur int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data);
void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx);

__owur int SSL_get_ex_data_X509_STORE_CTX_idx(void);

# define SSL_CTX_sess_set_cache_size(ctx,t) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
# define SSL_CTX_sess_get_cache_size(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
# define SSL_CTX_set_session_cache_mode(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
# define SSL_CTX_get_session_cache_mode(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)

# define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
# define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
# define SSL_CTX_get_read_ahead(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
# define SSL_CTX_set_read_ahead(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
# define SSL_CTX_get_max_cert_list(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
# define SSL_CTX_set_max_cert_list(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
# define SSL_get_max_cert_list(ssl) \
        SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
# define SSL_set_max_cert_list(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)

# define SSL_CTX_set_max_send_fragment(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_set_max_send_fragment(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_split_send_fragment(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_set_split_send_fragment(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_max_pipelines(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
# define SSL_set_max_pipelines(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
# define SSL_set_retry_verify(ssl) \
        (SSL_ctrl(ssl,SSL_CTRL_SET_RETRY_VERIFY,0,NULL) > 0)

void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
void SSL_set_default_read_buffer_len(SSL *s, size_t len);

# ifndef OPENSSL_NO_DH
#  ifndef OPENSSL_NO_DEPRECATED_3_0
/* NB: the |keylength| is only applicable when is_export is true */
OSSL_DEPRECATEDIN_3_0
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
                                 DH *(*dh) (SSL *ssl, int is_export,
                                            int keylength));
OSSL_DEPRECATEDIN_3_0
void SSL_set_tmp_dh_callback(SSL *ssl,
                             DH *(*dh) (SSL *ssl, int is_export,
                                        int keylength));
#  endif
# endif

__owur const COMP_METHOD *SSL_get_current_compression(const SSL *s);
__owur const COMP_METHOD *SSL_get_current_expansion(const SSL *s);
__owur const char *SSL_COMP_get_name(const COMP_METHOD *comp);
__owur const char *SSL_COMP_get0_name(const SSL_COMP *comp);
__owur int SSL_COMP_get_id(const SSL_COMP *comp);
STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
__owur STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
                                                             *meths);
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_COMP_free_compression_methods() while(0) continue
# endif
__owur int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm);

const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c);
int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c);
int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
                             int isv2format, STACK_OF(SSL_CIPHER) **sk,
                             STACK_OF(SSL_CIPHER) **scsvs);

/* TLS extensions functions */
__owur int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);

__owur int SSL_set_session_ticket_ext_cb(SSL *s,
                                         tls_session_ticket_ext_cb_fn cb,
                                         void *arg);

/* Pre-shared secret session resumption functions */
__owur int SSL_set_session_secret_cb(SSL *s,
                                     tls_session_secret_cb_fn session_secret_cb,
                                     void *arg);

void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
                                                int (*cb) (SSL *ssl,
                                                           int
                                                           is_forward_secure));

void SSL_set_not_resumable_session_callback(SSL *ssl,
                                            int (*cb) (SSL *ssl,
                                                       int is_forward_secure));

void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
                                         size_t (*cb) (SSL *ssl, int type,
                                                       size_t len, void *arg));
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx);
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);

int SSL_set_record_padding_callback(SSL *ssl,
                                    size_t (*cb) (SSL *ssl, int type,
                                                  size_t len, void *arg));
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg);
void *SSL_get_record_padding_callback_arg(const SSL *ssl);
int SSL_set_block_padding(SSL *ssl, size_t block_size);

int SSL_set_num_tickets(SSL *s, size_t num_tickets);
size_t SSL_get_num_tickets(const SSL *s);
int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_cache_hit(s) SSL_session_reused(s)
# endif

__owur int SSL_session_reused(const SSL *s);
__owur int SSL_is_server(const SSL *s);

__owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void);
int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx);
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx);
unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags);
__owur unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx,
                                             unsigned int flags);
__owur int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre);

void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl);
void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx);

__owur int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
__owur int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv);
__owur int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);

void SSL_add_ssl_module(void);
int SSL_config(SSL *s, const char *name);
int SSL_CTX_config(SSL_CTX *ctx, const char *name);

# ifndef OPENSSL_NO_SSL_TRACE
void SSL_trace(int write_p, int version, int content_type,
               const void *buf, size_t len, SSL *ssl, void *arg);
# endif

# ifndef OPENSSL_NO_SOCK
int DTLSv1_listen(SSL *s, BIO_ADDR *client);
# endif

# ifndef OPENSSL_NO_CT

/*
 * A callback for verifying that the received SCTs are sufficient.
 * Expected to return 1 if they are sufficient, otherwise 0.
 * May return a negative integer if an error occurs.
 * A connection should be aborted if the SCTs are deemed insufficient.
 */
typedef int (*ssl_ct_validation_cb)(const CT_POLICY_EVAL_CTX *ctx,
                                    const STACK_OF(SCT) *scts, void *arg);

/*
 * Sets a |callback| that is invoked upon receipt of ServerHelloDone to validate
 * the received SCTs.
 * If the callback returns a non-positive result, the connection is terminated.
 * Call this function before beginning a handshake.
 * If a NULL |callback| is provided, SCT validation is disabled.
 * |arg| is arbitrary userdata that will be passed to the callback whenever it
 * is invoked. Ownership of |arg| remains with the caller.
 *
 * NOTE: A side-effect of setting a CT callback is that an OCSP stapled response
 *       will be requested.
 */
int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback,
                                   void *arg);
int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
                                       ssl_ct_validation_cb callback,
                                       void *arg);
#define SSL_disable_ct(s) \
        ((void) SSL_set_validation_callback((s), NULL, NULL))
#define SSL_CTX_disable_ct(ctx) \
        ((void) SSL_CTX_set_validation_callback((ctx), NULL, NULL))

/*
 * The validation type enumerates the available behaviours of the built-in SSL
 * CT validation callback selected via SSL_enable_ct() and SSL_CTX_enable_ct().
 * The underlying callback is a static function in libssl.
 */
enum {
    SSL_CT_VALIDATION_PERMISSIVE = 0,
    SSL_CT_VALIDATION_STRICT
};

/*
 * Enable CT by setting up a callback that implements one of the built-in
 * validation variants.  The SSL_CT_VALIDATION_PERMISSIVE variant always
 * continues the handshake, the application can make appropriate decisions at
 * handshake completion.  The SSL_CT_VALIDATION_STRICT variant requires at
 * least one valid SCT, or else handshake termination will be requested.  The
 * handshake may continue anyway if SSL_VERIFY_NONE is in effect.
 */
int SSL_enable_ct(SSL *s, int validation_mode);
int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode);

/*
 * Report whether a non-NULL callback is enabled.
 */
int SSL_ct_is_enabled(const SSL *s);
int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx);

/* Gets the SCTs received from a connection */
const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s);

/*
 * Loads the CT log list from the default location.
 * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
 * the log information loaded from this file will be appended to the
 * CTLOG_STORE.
 * Returns 1 on success, 0 otherwise.
 */
int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx);

/*
 * Loads the CT log list from the specified file path.
 * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
 * the log information loaded from this file will be appended to the
 * CTLOG_STORE.
 * Returns 1 on success, 0 otherwise.
 */
int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path);

/*
 * Sets the CT log list used by all SSL connections created from this SSL_CTX.
 * Ownership of the CTLOG_STORE is transferred to the SSL_CTX.
 */
void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE *logs);

/*
 * Gets the CT log list used by all SSL connections created from this SSL_CTX.
 * This will be NULL unless one of the following functions has been called:
 * - SSL_CTX_set_default_ctlog_list_file
 * - SSL_CTX_set_ctlog_list_file
 * - SSL_CTX_set_ctlog_store
 */
const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx);

# endif /* OPENSSL_NO_CT */

/* What the "other" parameter contains in security callback */
/* Mask for type */
# define SSL_SECOP_OTHER_TYPE    0xffff0000
# define SSL_SECOP_OTHER_NONE    0
# define SSL_SECOP_OTHER_CIPHER  (1 << 16)
# define SSL_SECOP_OTHER_CURVE   (2 << 16)
# define SSL_SECOP_OTHER_DH      (3 << 16)
# define SSL_SECOP_OTHER_PKEY    (4 << 16)
# define SSL_SECOP_OTHER_SIGALG  (5 << 16)
# define SSL_SECOP_OTHER_CERT    (6 << 16)

/* Indicated operation refers to peer key or certificate */
# define SSL_SECOP_PEER          0x1000

/* Values for "op" parameter in security callback */

/* Called to filter ciphers */
/* Ciphers client supports */
# define SSL_SECOP_CIPHER_SUPPORTED      (1 | SSL_SECOP_OTHER_CIPHER)
/* Cipher shared by client/server */
# define SSL_SECOP_CIPHER_SHARED         (2 | SSL_SECOP_OTHER_CIPHER)
/* Sanity check of cipher server selects */
# define SSL_SECOP_CIPHER_CHECK          (3 | SSL_SECOP_OTHER_CIPHER)
/* Curves supported by client */
# define SSL_SECOP_CURVE_SUPPORTED       (4 | SSL_SECOP_OTHER_CURVE)
/* Curves shared by client/server */
# define SSL_SECOP_CURVE_SHARED          (5 | SSL_SECOP_OTHER_CURVE)
/* Sanity check of curve server selects */
# define SSL_SECOP_CURVE_CHECK           (6 | SSL_SECOP_OTHER_CURVE)
/* Temporary DH key */
# define SSL_SECOP_TMP_DH                (7 | SSL_SECOP_OTHER_PKEY)
/* SSL/TLS version */
# define SSL_SECOP_VERSION               (9 | SSL_SECOP_OTHER_NONE)
/* Session tickets */
# define SSL_SECOP_TICKET                (10 | SSL_SECOP_OTHER_NONE)
/* Supported signature algorithms sent to peer */
# define SSL_SECOP_SIGALG_SUPPORTED      (11 | SSL_SECOP_OTHER_SIGALG)
/* Shared signature algorithm */
# define SSL_SECOP_SIGALG_SHARED         (12 | SSL_SECOP_OTHER_SIGALG)
/* Sanity check signature algorithm allowed */
# define SSL_SECOP_SIGALG_CHECK          (13 | SSL_SECOP_OTHER_SIGALG)
/* Used to get mask of supported public key signature algorithms */
# define SSL_SECOP_SIGALG_MASK           (14 | SSL_SECOP_OTHER_SIGALG)
/* Use to see if compression is allowed */
# define SSL_SECOP_COMPRESSION           (15 | SSL_SECOP_OTHER_NONE)
/* EE key in certificate */
# define SSL_SECOP_EE_KEY                (16 | SSL_SECOP_OTHER_CERT)
/* CA key in certificate */
# define SSL_SECOP_CA_KEY                (17 | SSL_SECOP_OTHER_CERT)
/* CA digest algorithm in certificate */
# define SSL_SECOP_CA_MD                 (18 | SSL_SECOP_OTHER_CERT)
/* Peer EE key in certificate */
# define SSL_SECOP_PEER_EE_KEY           (SSL_SECOP_EE_KEY | SSL_SECOP_PEER)
/* Peer CA key in certificate */
# define SSL_SECOP_PEER_CA_KEY           (SSL_SECOP_CA_KEY | SSL_SECOP_PEER)
/* Peer CA digest algorithm in certificate */
# define SSL_SECOP_PEER_CA_MD            (SSL_SECOP_CA_MD | SSL_SECOP_PEER)

void SSL_set_security_level(SSL *s, int level);
__owur int SSL_get_security_level(const SSL *s);
void SSL_set_security_callback(SSL *s,
                               int (*cb) (const SSL *s, const SSL_CTX *ctx,
                                          int op, int bits, int nid,
                                          void *other, void *ex));
int (*SSL_get_security_callback(const SSL *s)) (const SSL *s,
                                                const SSL_CTX *ctx, int op,
                                                int bits, int nid, void *other,
                                                void *ex);
void SSL_set0_security_ex_data(SSL *s, void *ex);
__owur void *SSL_get0_security_ex_data(const SSL *s);

void SSL_CTX_set_security_level(SSL_CTX *ctx, int level);
__owur int SSL_CTX_get_security_level(const SSL_CTX *ctx);
void SSL_CTX_set_security_callback(SSL_CTX *ctx,
                                   int (*cb) (const SSL *s, const SSL_CTX *ctx,
                                              int op, int bits, int nid,
                                              void *other, void *ex));
int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s,
                                                          const SSL_CTX *ctx,
                                                          int op, int bits,
                                                          int nid,
                                                          void *other,
                                                          void *ex);
void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex);
__owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx);

/* OPENSSL_INIT flag 0x010000 reserved for internal use */
# define OPENSSL_INIT_NO_LOAD_SSL_STRINGS    0x00100000L
# define OPENSSL_INIT_LOAD_SSL_STRINGS       0x00200000L

# define OPENSSL_INIT_SSL_DEFAULT \
        (OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS)

int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);

# ifndef OPENSSL_NO_UNIT_TEST
__owur const struct openssl_ssl_test_functions *SSL_test_functions(void);
# endif

__owur int SSL_free_buffers(SSL *ssl);
__owur int SSL_alloc_buffers(SSL *ssl);

/* Status codes passed to the decrypt session ticket callback. Some of these
 * are for internal use only and are never passed to the callback. */
typedef int SSL_TICKET_STATUS;

/* Support for ticket appdata */
/* fatal error, malloc failure */
# define SSL_TICKET_FATAL_ERR_MALLOC 0
/* fatal error, either from parsing or decrypting the ticket */
# define SSL_TICKET_FATAL_ERR_OTHER  1
/* No ticket present */
# define SSL_TICKET_NONE             2
/* Empty ticket present */
# define SSL_TICKET_EMPTY            3
/* the ticket couldn't be decrypted */
# define SSL_TICKET_NO_DECRYPT       4
/* a ticket was successfully decrypted */
# define SSL_TICKET_SUCCESS          5
/* same as above but the ticket needs to be renewed */
# define SSL_TICKET_SUCCESS_RENEW    6

/* Return codes for the decrypt session ticket callback */
typedef int SSL_TICKET_RETURN;

/* An error occurred */
#define SSL_TICKET_RETURN_ABORT             0
/* Do not use the ticket, do not send a renewed ticket to the client */
#define SSL_TICKET_RETURN_IGNORE            1
/* Do not use the ticket, send a renewed ticket to the client */
#define SSL_TICKET_RETURN_IGNORE_RENEW      2
/* Use the ticket, do not send a renewed ticket to the client */
#define SSL_TICKET_RETURN_USE               3
/* Use the ticket, send a renewed ticket to the client */
#define SSL_TICKET_RETURN_USE_RENEW         4

typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg);
typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss,
                                                               const unsigned char *keyname,
                                                               size_t keyname_length,
                                                               SSL_TICKET_STATUS status,
                                                               void *arg);
int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx,
                                  SSL_CTX_generate_session_ticket_fn gen_cb,
                                  SSL_CTX_decrypt_session_ticket_fn dec_cb,
                                  void *arg);
int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len);
int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len);

typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);

void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);


typedef int (*SSL_allow_early_data_cb_fn)(SSL *s, void *arg);
void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx,
                                     SSL_allow_early_data_cb_fn cb,
                                     void *arg);
void SSL_set_allow_early_data_cb(SSL *s,
                                 SSL_allow_early_data_cb_fn cb,
                                 void *arg);

/* store the default cipher strings inside the library */
const char *OSSL_default_cipher_list(void);
const char *OSSL_default_ciphersuites(void);

#  ifndef OPENSSL_NO_QUIC
/*
 * QUIC integration - The QUIC interface matches BoringSSL
 *
 * ssl_encryption_level_t represents a specific QUIC encryption level used to
 * transmit handshake messages. BoringSSL has this as an 'enum'.
 */
#include <openssl/quic.h>

/* Used by Chromium/QUIC - moved from evp.h to avoid breaking FIPS checksums */
# define X25519_PRIVATE_KEY_LEN          32
# define X25519_PUBLIC_VALUE_LEN         32

/* moved from types.h to avoid breaking FIPS checksums */
typedef struct ssl_quic_method_st SSL_QUIC_METHOD;

typedef enum ssl_encryption_level_t {
    ssl_encryption_initial = 0,
    ssl_encryption_early_data,
    ssl_encryption_handshake,
    ssl_encryption_application
} OSSL_ENCRYPTION_LEVEL;

struct ssl_quic_method_st {
    int (*set_encryption_secrets)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
                                  const uint8_t *read_secret,
                                  const uint8_t *write_secret, size_t secret_len);
    int (*add_handshake_data)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
                              const uint8_t *data, size_t len);
    int (*flush_flight)(SSL *ssl);
    int (*send_alert)(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert);
};

__owur int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method);
__owur int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method);
__owur int SSL_set_quic_transport_params(SSL *ssl,
                                         const uint8_t *params,
                                         size_t params_len);
void SSL_get_peer_quic_transport_params(const SSL *ssl,
                                        const uint8_t **out_params,
                                        size_t *out_params_len);
__owur size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, OSSL_ENCRYPTION_LEVEL level);
__owur OSSL_ENCRYPTION_LEVEL SSL_quic_read_level(const SSL *ssl);
__owur OSSL_ENCRYPTION_LEVEL SSL_quic_write_level(const SSL *ssl);
__owur int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
                                 const uint8_t *data, size_t len);
__owur int SSL_process_quic_post_handshake(SSL *ssl);

__owur int SSL_is_quic(SSL *ssl);

/* BoringSSL API */
void SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy);

/*
 * Set an explicit value that you want to use
 * If 0 (default) the server will use the highest extenstion the client sent
 * If 0 (default) the client will send both extensions
 */
void SSL_set_quic_transport_version(SSL *ssl, int version);
__owur int SSL_get_quic_transport_version(const SSL *ssl);
/* Returns the negotiated version, or -1 on error */
__owur int SSL_get_peer_quic_transport_version(const SSL *ssl);

int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c);

void SSL_set_quic_early_data_enabled(SSL *ssl, int enabled);

#  endif

# ifdef  __cplusplus
}
# endif
#endif
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     /*
 * WARNING: do not edit!
 * Generated by makefile from include/openssl/ssl.h.in
 *
 * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
 * Copyright 2005 Nokia. All rights reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */



#ifndef OPENSSL_SSL_H
# define OPENSSL_SSL_H
# pragma once

# include <openssl/macros.h>
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define HEADER_SSL_H
# endif

# include <openssl/e_os2.h>
# include <openssl/opensslconf.h>
# include <openssl/comp.h>
# include <openssl/bio.h>
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  include <openssl/x509.h>
#  include <openssl/crypto.h>
#  include <openssl/buffer.h>
# endif
# include <openssl/lhash.h>
# include <openssl/pem.h>
# include <openssl/hmac.h>
# include <openssl/async.h>

# include <openssl/safestack.h>
# include <openssl/symhacks.h>
# include <openssl/ct.h>
# include <openssl/sslerr.h>
# include <openssl/prov_ssl.h>

#ifdef  __cplusplus
extern "C" {
#endif

/* OpenSSL version number for ASN.1 encoding of the session information */
/*-
 * Version 0 - initial version
 * Version 1 - added the optional peer certificate
 */
# define SSL_SESSION_ASN1_VERSION 0x0001

# define SSL_MAX_SSL_SESSION_ID_LENGTH           32
# define SSL_MAX_SID_CTX_LENGTH                  32

# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES     (512/8)
# define SSL_MAX_KEY_ARG_LENGTH                  8
/* SSL_MAX_MASTER_KEY_LENGTH is defined in prov_ssl.h */

/* The maximum number of encrypt/decrypt pipelines we can support */
# define SSL_MAX_PIPELINES  32

/* text strings for the ciphers */

/* These are used to specify which ciphers to use and not to use */

# define SSL_TXT_LOW             "LOW"
# define SSL_TXT_MEDIUM          "MEDIUM"
# define SSL_TXT_HIGH            "HIGH"
# define SSL_TXT_FIPS            "FIPS"

# define SSL_TXT_aNULL           "aNULL"
# define SSL_TXT_eNULL           "eNULL"
# define SSL_TXT_NULL            "NULL"

# define SSL_TXT_kRSA            "kRSA"
# define SSL_TXT_kDHr            "kDHr"/* this cipher class has been removed */
# define SSL_TXT_kDHd            "kDHd"/* this cipher class has been removed */
# define SSL_TXT_kDH             "kDH"/* this cipher class has been removed */
# define SSL_TXT_kEDH            "kEDH"/* alias for kDHE */
# define SSL_TXT_kDHE            "kDHE"
# define SSL_TXT_kECDHr          "kECDHr"/* this cipher class has been removed */
# define SSL_TXT_kECDHe          "kECDHe"/* this cipher class has been removed */
# define SSL_TXT_kECDH           "kECDH"/* this cipher class has been removed */
# define SSL_TXT_kEECDH          "kEECDH"/* alias for kECDHE */
# define SSL_TXT_kECDHE          "kECDHE"
# define SSL_TXT_kPSK            "kPSK"
# define SSL_TXT_kRSAPSK         "kRSAPSK"
# define SSL_TXT_kECDHEPSK       "kECDHEPSK"
# define SSL_TXT_kDHEPSK         "kDHEPSK"
# define SSL_TXT_kGOST           "kGOST"
# define SSL_TXT_kGOST18         "kGOST18"
# define SSL_TXT_kSRP            "kSRP"

# define SSL_TXT_aRSA            "aRSA"
# define SSL_TXT_aDSS            "aDSS"
# define SSL_TXT_aDH             "aDH"/* this cipher class has been removed */
# define SSL_TXT_aECDH           "aECDH"/* this cipher class has been removed */
# define SSL_TXT_aECDSA          "aECDSA"
# define SSL_TXT_aPSK            "aPSK"
# define SSL_TXT_aGOST94         "aGOST94"
# define SSL_TXT_aGOST01         "aGOST01"
# define SSL_TXT_aGOST12         "aGOST12"
# define SSL_TXT_aGOST           "aGOST"
# define SSL_TXT_aSRP            "aSRP"

# define SSL_TXT_DSS             "DSS"
# define SSL_TXT_DH              "DH"
# define SSL_TXT_DHE             "DHE"/* same as "kDHE:-ADH" */
# define SSL_TXT_EDH             "EDH"/* alias for DHE */
# define SSL_TXT_ADH             "ADH"
# define SSL_TXT_RSA             "RSA"
# define SSL_TXT_ECDH            "ECDH"
# define SSL_TXT_EECDH           "EECDH"/* alias for ECDHE" */
# define SSL_TXT_ECDHE           "ECDHE"/* same as "kECDHE:-AECDH" */
# define SSL_TXT_AECDH           "AECDH"
# define SSL_TXT_ECDSA           "ECDSA"
# define SSL_TXT_PSK             "PSK"
# define SSL_TXT_SRP             "SRP"

# define SSL_TXT_DES             "DES"
# define SSL_TXT_3DES            "3DES"
# define SSL_TXT_RC4             "RC4"
# define SSL_TXT_RC2             "RC2"
# define SSL_TXT_IDEA            "IDEA"
# define SSL_TXT_SEED            "SEED"
# define SSL_TXT_AES128          "AES128"
# define SSL_TXT_AES256          "AES256"
# define SSL_TXT_AES             "AES"
# define SSL_TXT_AES_GCM         "AESGCM"
# define SSL_TXT_AES_CCM         "AESCCM"
# define SSL_TXT_AES_CCM_8       "AESCCM8"
# define SSL_TXT_CAMELLIA128     "CAMELLIA128"
# define SSL_TXT_CAMELLIA256     "CAMELLIA256"
# define SSL_TXT_CAMELLIA        "CAMELLIA"
# define SSL_TXT_CHACHA20        "CHACHA20"
# define SSL_TXT_GOST            "GOST89"
# define SSL_TXT_ARIA            "ARIA"
# define SSL_TXT_ARIA_GCM        "ARIAGCM"
# define SSL_TXT_ARIA128         "ARIA128"
# define SSL_TXT_ARIA256         "ARIA256"
# define SSL_TXT_GOST2012_GOST8912_GOST8912 "GOST2012-GOST8912-GOST8912"
# define SSL_TXT_CBC             "CBC"

# define SSL_TXT_MD5             "MD5"
# define SSL_TXT_SHA1            "SHA1"
# define SSL_TXT_SHA             "SHA"/* same as "SHA1" */
# define SSL_TXT_GOST94          "GOST94"
# define SSL_TXT_GOST89MAC       "GOST89MAC"
# define SSL_TXT_GOST12          "GOST12"
# define SSL_TXT_GOST89MAC12     "GOST89MAC12"
# define SSL_TXT_SHA256          "SHA256"
# define SSL_TXT_SHA384          "SHA384"

# define SSL_TXT_SSLV3           "SSLv3"
# define SSL_TXT_TLSV1           "TLSv1"
# define SSL_TXT_TLSV1_1         "TLSv1.1"
# define SSL_TXT_TLSV1_2         "TLSv1.2"

# define SSL_TXT_ALL             "ALL"

/*-
 * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
 * ciphers normally not being used.
 * Example: "RC4" will activate all ciphers using RC4 including ciphers
 * without authentication, which would normally disabled by DEFAULT (due
 * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
 * will make sure that it is also disabled in the specific selection.
 * COMPLEMENTOF* identifiers are portable between version, as adjustments
 * to the default cipher setup will also be included here.
 *
 * COMPLEMENTOFDEFAULT does not experience the same special treatment that
 * DEFAULT gets, as only selection is being done and no sorting as needed
 * for DEFAULT.
 */
# define SSL_TXT_CMPALL          "COMPLEMENTOFALL"
# define SSL_TXT_CMPDEF          "COMPLEMENTOFDEFAULT"

/*
 * The following cipher list is used by default. It also is substituted when
 * an application-defined cipher list string starts with 'DEFAULT'.
 * This applies to ciphersuites for TLSv1.2 and below.
 * DEPRECATED IN 3.0.0, in favor of OSSL_default_cipher_list()
 * Update both macro and function simultaneously
 */
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL"
/*
 * This is the default set of TLSv1.3 ciphersuites
 * DEPRECATED IN 3.0.0, in favor of OSSL_default_ciphersuites()
 * Update both macro and function simultaneously
 */
#  define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
                                   "TLS_CHACHA20_POLY1305_SHA256:" \
                                   "TLS_AES_128_GCM_SHA256"
# endif
/*
 * As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always
 * starts with a reasonable order, and all we have to do for DEFAULT is
 * throwing out anonymous and unencrypted ciphersuites! (The latter are not
 * actually enabled by ALL, but "ALL:RSA" would enable some of them.)
 */

/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
# define SSL_SENT_SHUTDOWN       1
# define SSL_RECEIVED_SHUTDOWN   2

#ifdef __cplusplus
}
#endif

#ifdef  __cplusplus
extern "C" {
#endif

# define SSL_FILETYPE_ASN1       X509_FILETYPE_ASN1
# define SSL_FILETYPE_PEM        X509_FILETYPE_PEM

/*
 * This is needed to stop compilers complaining about the 'struct ssl_st *'
 * function parameters used to prototype callbacks in SSL_CTX.
 */
typedef struct ssl_st *ssl_crock_st;
typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
typedef struct ssl_method_st SSL_METHOD;
typedef struct ssl_cipher_st SSL_CIPHER;
typedef struct ssl_session_st SSL_SESSION;
typedef struct tls_sigalgs_st TLS_SIGALGS;
typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
typedef struct ssl_comp_st SSL_COMP;

STACK_OF(SSL_CIPHER);
STACK_OF(SSL_COMP);

/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/
typedef struct srtp_protection_profile_st {
    const char *name;
    unsigned long id;
} SRTP_PROTECTION_PROFILE;
SKM_DEFINE_STACK_OF_INTERNAL(SRTP_PROTECTION_PROFILE, SRTP_PROTECTION_PROFILE, SRTP_PROTECTION_PROFILE)
#define sk_SRTP_PROTECTION_PROFILE_num(sk) OPENSSL_sk_num(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_value(sk, idx) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_value(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk), (idx)))
#define sk_SRTP_PROTECTION_PROFILE_new(cmp) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_new(ossl_check_SRTP_PROTECTION_PROFILE_compfunc_type(cmp)))
#define sk_SRTP_PROTECTION_PROFILE_new_null() ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_new_null())
#define sk_SRTP_PROTECTION_PROFILE_new_reserve(cmp, n) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_new_reserve(ossl_check_SRTP_PROTECTION_PROFILE_compfunc_type(cmp), (n)))
#define sk_SRTP_PROTECTION_PROFILE_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), (n))
#define sk_SRTP_PROTECTION_PROFILE_free(sk) OPENSSL_sk_free(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_zero(sk) OPENSSL_sk_zero(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_delete(sk, i) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_delete(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), (i)))
#define sk_SRTP_PROTECTION_PROFILE_delete_ptr(sk, ptr) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_delete_ptr(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr)))
#define sk_SRTP_PROTECTION_PROFILE_push(sk, ptr) OPENSSL_sk_push(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_pop(sk) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_pop(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk)))
#define sk_SRTP_PROTECTION_PROFILE_shift(sk) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_shift(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk)))
#define sk_SRTP_PROTECTION_PROFILE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk),ossl_check_SRTP_PROTECTION_PROFILE_freefunc_type(freefunc))
#define sk_SRTP_PROTECTION_PROFILE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr), (idx))
#define sk_SRTP_PROTECTION_PROFILE_set(sk, idx, ptr) ((SRTP_PROTECTION_PROFILE *)OPENSSL_sk_set(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), (idx), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr)))
#define sk_SRTP_PROTECTION_PROFILE_find(sk, ptr) OPENSSL_sk_find(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr))
#define sk_SRTP_PROTECTION_PROFILE_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_type(ptr), pnum)
#define sk_SRTP_PROTECTION_PROFILE_sort(sk) OPENSSL_sk_sort(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk))
#define sk_SRTP_PROTECTION_PROFILE_dup(sk) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_dup(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk)))
#define sk_SRTP_PROTECTION_PROFILE_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(SRTP_PROTECTION_PROFILE) *)OPENSSL_sk_deep_copy(ossl_check_const_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_copyfunc_type(copyfunc), ossl_check_SRTP_PROTECTION_PROFILE_freefunc_type(freefunc)))
#define sk_SRTP_PROTECTION_PROFILE_set_cmp_func(sk, cmp) ((sk_SRTP_PROTECTION_PROFILE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_SRTP_PROTECTION_PROFILE_sk_type(sk), ossl_check_SRTP_PROTECTION_PROFILE_compfunc_type(cmp)))



typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data,
                                            int len, void *arg);
typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len,
                                        STACK_OF(SSL_CIPHER) *peer_ciphers,
                                        const SSL_CIPHER **cipher, void *arg);

/* Extension context codes */
/* This extension is only allowed in TLS */
#define SSL_EXT_TLS_ONLY                        0x0001
/* This extension is only allowed in DTLS */
#define SSL_EXT_DTLS_ONLY                       0x0002
/* Some extensions may be allowed in DTLS but we don't implement them for it */
#define SSL_EXT_TLS_IMPLEMENTATION_ONLY         0x0004
/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */
#define SSL_EXT_SSL3_ALLOWED                    0x0008
/* Extension is only defined for TLS1.2 and below */
#define SSL_EXT_TLS1_2_AND_BELOW_ONLY           0x0010
/* Extension is only defined for TLS1.3 and above */
#define SSL_EXT_TLS1_3_ONLY                     0x0020
/* Ignore this extension during parsing if we are resuming */
#define SSL_EXT_IGNORE_ON_RESUMPTION            0x0040
#define SSL_EXT_CLIENT_HELLO                    0x0080
/* Really means TLS1.2 or below */
#define SSL_EXT_TLS1_2_SERVER_HELLO             0x0100
#define SSL_EXT_TLS1_3_SERVER_HELLO             0x0200
#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS     0x0400
#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST      0x0800
#define SSL_EXT_TLS1_3_CERTIFICATE              0x1000
#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET       0x2000
#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST      0x4000

/* Typedefs for handling custom extensions */

typedef int (*custom_ext_add_cb)(SSL *s, unsigned int ext_type,
                                 const unsigned char **out, size_t *outlen,
                                 int *al, void *add_arg);

typedef void (*custom_ext_free_cb)(SSL *s, unsigned int ext_type,
                                   const unsigned char *out, void *add_arg);

typedef int (*custom_ext_parse_cb)(SSL *s, unsigned int ext_type,
                                   const unsigned char *in, size_t inlen,
                                   int *al, void *parse_arg);


typedef int (*SSL_custom_ext_add_cb_ex)(SSL *s, unsigned int ext_type,
                                        unsigned int context,
                                        const unsigned char **out,
                                        size_t *outlen, X509 *x,
                                        size_t chainidx,
                                        int *al, void *add_arg);

typedef void (*SSL_custom_ext_free_cb_ex)(SSL *s, unsigned int ext_type,
                                          unsigned int context,
                                          const unsigned char *out,
                                          void *add_arg);

typedef int (*SSL_custom_ext_parse_cb_ex)(SSL *s, unsigned int ext_type,
                                          unsigned int context,
                                          const unsigned char *in,
                                          size_t inlen, X509 *x,
                                          size_t chainidx,
                                          int *al, void *parse_arg);

/* Typedef for verification callback */
typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);

/* Typedef for SSL async callback */
typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);

#define SSL_OP_BIT(n)  ((uint64_t)1 << (uint64_t)n)

/*
 * SSL/TLS connection options.
 */
    /* Disable Extended master secret */
# define SSL_OP_NO_EXTENDED_MASTER_SECRET                SSL_OP_BIT(0)
    /* Cleanse plaintext copies of data delivered to the application */
# define SSL_OP_CLEANSE_PLAINTEXT                        SSL_OP_BIT(1)
    /* Allow initial connection to servers that don't support RI */
# define SSL_OP_LEGACY_SERVER_CONNECT                    SSL_OP_BIT(2)
    /* Enable support for Kernel TLS */
# define SSL_OP_ENABLE_KTLS                              SSL_OP_BIT(3)
# define SSL_OP_TLSEXT_PADDING                           SSL_OP_BIT(4)
# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG                   SSL_OP_BIT(6)
# define SSL_OP_IGNORE_UNEXPECTED_EOF                    SSL_OP_BIT(7)
# define SSL_OP_ALLOW_CLIENT_RENEGOTIATION               SSL_OP_BIT(8)
# define SSL_OP_DISABLE_TLSEXT_CA_NAMES                  SSL_OP_BIT(9)
    /* In TLSv1.3 allow a non-(ec)dhe based kex_mode */
# define SSL_OP_ALLOW_NO_DHE_KEX                         SSL_OP_BIT(10)
    /*
     * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
     * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
     * the workaround is not needed.  Unfortunately some broken SSL/TLS
     * implementations cannot handle it at all, which is why we include it
     * in SSL_OP_ALL. Added in 0.9.6e
     */
# define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              SSL_OP_BIT(11)
    /* DTLS options */
# define SSL_OP_NO_QUERY_MTU                             SSL_OP_BIT(12)
    /* Turn on Cookie Exchange (on relevant for servers) */
# define SSL_OP_COOKIE_EXCHANGE                          SSL_OP_BIT(13)
    /* Don't use RFC4507 ticket extension */
# define SSL_OP_NO_TICKET                                SSL_OP_BIT(14)
# ifndef OPENSSL_NO_DTLS1_METHOD
    /*
     * Use Cisco's version identifier of DTLS_BAD_VER
     * (only with deprecated DTLSv1_client_method())
     */
#  define SSL_OP_CISCO_ANYCONNECT                        SSL_OP_BIT(15)
# endif
    /* As server, disallow session resumption on renegotiation */
# define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION   SSL_OP_BIT(16)
    /* Don't use compression even if supported */
# define SSL_OP_NO_COMPRESSION                           SSL_OP_BIT(17)
    /* Permit unsafe legacy renegotiation */
# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION        SSL_OP_BIT(18)
    /* Disable encrypt-then-mac */
# define SSL_OP_NO_ENCRYPT_THEN_MAC                      SSL_OP_BIT(19)
    /*
     * Enable TLSv1.3 Compatibility mode. This is on by default. A future
     * version of OpenSSL may have this disabled by default.
     */
# define SSL_OP_ENABLE_MIDDLEBOX_COMPAT                  SSL_OP_BIT(20)
    /*
     * Prioritize Chacha20Poly1305 when client does.
     * Modifies SSL_OP_CIPHER_SERVER_PREFERENCE
     */
# define SSL_OP_PRIORITIZE_CHACHA                        SSL_OP_BIT(21)
    /*
     * Set on servers to choose the cipher according to server's preferences.
     */
# define SSL_OP_CIPHER_SERVER_PREFERENCE                 SSL_OP_BIT(22)
    /*
     * If set, a server will allow a client to issue a SSLv3.0 version
     * number as latest version supported in the premaster secret, even when
     * TLSv1.0 (version 3.1) was announced in the client hello. Normally
     * this is forbidden to prevent version rollback attacks.
     */
# define SSL_OP_TLS_ROLLBACK_BUG                         SSL_OP_BIT(23)
    /*
     * Switches off automatic TLSv1.3 anti-replay protection for early data.
     * This is a server-side option only (no effect on the client).
     */
# define SSL_OP_NO_ANTI_REPLAY                           SSL_OP_BIT(24)
# define SSL_OP_NO_SSLv3                                 SSL_OP_BIT(25)
# define SSL_OP_NO_TLSv1                                 SSL_OP_BIT(26)
# define SSL_OP_NO_TLSv1_2                               SSL_OP_BIT(27)
# define SSL_OP_NO_TLSv1_1                               SSL_OP_BIT(28)
# define SSL_OP_NO_TLSv1_3                               SSL_OP_BIT(29)
# define SSL_OP_NO_DTLSv1                                SSL_OP_BIT(26)
# define SSL_OP_NO_DTLSv1_2                              SSL_OP_BIT(27)
    /* Disallow all renegotiation */
# define SSL_OP_NO_RENEGOTIATION                         SSL_OP_BIT(30)
    /*
     * Make server add server-hello extension from early version of
     * cryptopro draft, when GOST ciphersuite is negotiated. Required for
     * interoperability with CryptoPro CSP 3.x
     */
# define SSL_OP_CRYPTOPRO_TLSEXT_BUG                     SSL_OP_BIT(31)

/*
 * Option "collections."
 */
# define SSL_OP_NO_SSL_MASK \
        ( SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 \
          | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3 )
# define SSL_OP_NO_DTLS_MASK \
        ( SSL_OP_NO_DTLSv1 | SSL_OP_NO_DTLSv1_2 )

/* Various bug workarounds that should be rather harmless. */
# define SSL_OP_ALL \
        ( SSL_OP_CRYPTOPRO_TLSEXT_BUG | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS \
          | SSL_OP_TLSEXT_PADDING | SSL_OP_SAFARI_ECDHE_ECDSA_BUG )

/*
 * OBSOLETE OPTIONS retained for compatibility
 */

# define SSL_OP_MICROSOFT_SESS_ID_BUG                    0x0
# define SSL_OP_NETSCAPE_CHALLENGE_BUG                   0x0
# define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG         0x0
# define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG              0x0
# define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER               0x0
# define SSL_OP_MSIE_SSLV2_RSA_PADDING                   0x0
# define SSL_OP_SSLEAY_080_CLIENT_DH_BUG                 0x0
# define SSL_OP_TLS_D5_BUG                               0x0
# define SSL_OP_TLS_BLOCK_PADDING_BUG                    0x0
# define SSL_OP_SINGLE_ECDH_USE                          0x0
# define SSL_OP_SINGLE_DH_USE                            0x0
# define SSL_OP_EPHEMERAL_RSA                            0x0
# define SSL_OP_NO_SSLv2                                 0x0
# define SSL_OP_PKCS1_CHECK_1                            0x0
# define SSL_OP_PKCS1_CHECK_2                            0x0
# define SSL_OP_NETSCAPE_CA_DN_BUG                       0x0
# define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG          0x0

/*
 * Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
 * when just a single record has been written):
 */
# define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001U
/*
 * Make it possible to retry SSL_write() with changed buffer location (buffer
 * contents must stay the same!); this is not the default to avoid the
 * misconception that non-blocking SSL_write() behaves like non-blocking
 * write():
 */
# define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002U
/*
 * Never bother the application with retries if the transport is blocking:
 */
# define SSL_MODE_AUTO_RETRY 0x00000004U
/* Don't attempt to automatically build certificate chain */
# define SSL_MODE_NO_AUTO_CHAIN 0x00000008U
/*
 * Save RAM by releasing read and write buffers when they're empty. (SSL3 and
 * TLS only.) Released buffers are freed.
 */
# define SSL_MODE_RELEASE_BUFFERS 0x00000010U
/*
 * Send the current time in the Random fields of the ClientHello and
 * ServerHello records for compatibility with hypothetical implementations
 * that require it.
 */
# define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020U
# define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040U
/*
 * Send TLS_FALLBACK_SCSV in the ClientHello. To be set only by applications
 * that reconnect with a downgraded protocol version; see
 * draft-ietf-tls-downgrade-scsv-00 for details. DO NOT ENABLE THIS if your
 * application attempts a normal handshake. Only use this in explicit
 * fallback retries, following the guidance in
 * draft-ietf-tls-downgrade-scsv-00.
 */
# define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080U
/*
 * Support Asynchronous operation
 */
# define SSL_MODE_ASYNC 0x00000100U

/*
 * When using DTLS/SCTP, include the terminating zero in the label
 * used for computing the endpoint-pair shared secret. Required for
 * interoperability with implementations having this bug like these
 * older version of OpenSSL:
 * - OpenSSL 1.0.0 series
 * - OpenSSL 1.0.1 series
 * - OpenSSL 1.0.2 series
 * - OpenSSL 1.1.0 series
 * - OpenSSL 1.1.1 and 1.1.1a
 */
# define SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG 0x00000400U

/* Cert related flags */
/*
 * Many implementations ignore some aspects of the TLS standards such as
 * enforcing certificate chain algorithms. When this is set we enforce them.
 */
# define SSL_CERT_FLAG_TLS_STRICT                0x00000001U

/* Suite B modes, takes same values as certificate verify flags */
# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY       0x10000
/* Suite B 192 bit only mode */
# define SSL_CERT_FLAG_SUITEB_192_LOS            0x20000
/* Suite B 128 bit mode allowing 192 bit algorithms */
# define SSL_CERT_FLAG_SUITEB_128_LOS            0x30000

/* Perform all sorts of protocol violations for testing purposes */
# define SSL_CERT_FLAG_BROKEN_PROTOCOL           0x10000000

/* Flags for building certificate chains */
/* Treat any existing certificates as untrusted CAs */
# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED          0x1
/* Don't include root CA in chain */
# define SSL_BUILD_CHAIN_FLAG_NO_ROOT            0x2
/* Just check certificates already there */
# define SSL_BUILD_CHAIN_FLAG_CHECK              0x4
/* Ignore verification errors */
# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR       0x8
/* Clear verification errors from queue */
# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR        0x10

/* Flags returned by SSL_check_chain */
/* Certificate can be used with this session */
# define CERT_PKEY_VALID         0x1
/* Certificate can also be used for signing */
# define CERT_PKEY_SIGN          0x2
/* EE certificate signing algorithm OK */
# define CERT_PKEY_EE_SIGNATURE  0x10
/* CA signature algorithms OK */
# define CERT_PKEY_CA_SIGNATURE  0x20
/* EE certificate parameters OK */
# define CERT_PKEY_EE_PARAM      0x40
/* CA certificate parameters OK */
# define CERT_PKEY_CA_PARAM      0x80
/* Signing explicitly allowed as opposed to SHA1 fallback */
# define CERT_PKEY_EXPLICIT_SIGN 0x100
/* Client CA issuer names match (always set for server cert) */
# define CERT_PKEY_ISSUER_NAME   0x200
/* Cert type matches client types (always set for server cert) */
# define CERT_PKEY_CERT_TYPE     0x400
/* Cert chain suitable to Suite B */
# define CERT_PKEY_SUITEB        0x800

# define SSL_CONF_FLAG_CMDLINE           0x1
# define SSL_CONF_FLAG_FILE              0x2
# define SSL_CONF_FLAG_CLIENT            0x4
# define SSL_CONF_FLAG_SERVER            0x8
# define SSL_CONF_FLAG_SHOW_ERRORS       0x10
# define SSL_CONF_FLAG_CERTIFICATE       0x20
# define SSL_CONF_FLAG_REQUIRE_PRIVATE   0x40
/* Configuration value types */
# define SSL_CONF_TYPE_UNKNOWN           0x0
# define SSL_CONF_TYPE_STRING            0x1
# define SSL_CONF_TYPE_FILE              0x2
# define SSL_CONF_TYPE_DIR               0x3
# define SSL_CONF_TYPE_NONE              0x4
# define SSL_CONF_TYPE_STORE             0x5

/* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */
# define SSL_COOKIE_LENGTH                       4096

/*
 * Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they
 * cannot be used to clear bits.
 */

uint64_t SSL_CTX_get_options(const SSL_CTX *ctx);
uint64_t SSL_get_options(const SSL *s);
uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op);
uint64_t SSL_clear_options(SSL *s, uint64_t op);
uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op);
uint64_t SSL_set_options(SSL *s, uint64_t op);

# define SSL_CTX_set_mode(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
# define SSL_CTX_clear_mode(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
# define SSL_CTX_get_mode(ctx) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
# define SSL_clear_mode(ssl,op) \
        SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
# define SSL_set_mode(ssl,op) \
        SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
# define SSL_get_mode(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
# define SSL_set_mtu(ssl, mtu) \
        SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
# define DTLS_set_link_mtu(ssl, mtu) \
        SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL)
# define DTLS_get_link_min_mtu(ssl) \
        SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL)

# define SSL_get_secure_renegotiation_support(ssl) \
        SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)

# define SSL_CTX_set_cert_flags(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL)
# define SSL_set_cert_flags(s,op) \
        SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL)
# define SSL_CTX_clear_cert_flags(ctx,op) \
        SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
# define SSL_clear_cert_flags(s,op) \
        SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)

void SSL_CTX_set_msg_callback(SSL_CTX *ctx,
                              void (*cb) (int write_p, int version,
                                          int content_type, const void *buf,
                                          size_t len, SSL *ssl, void *arg));
void SSL_set_msg_callback(SSL *ssl,
                          void (*cb) (int write_p, int version,
                                      int content_type, const void *buf,
                                      size_t len, SSL *ssl, void *arg));
# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))

# define SSL_get_extms_support(s) \
        SSL_ctrl((s),SSL_CTRL_GET_EXTMS_SUPPORT,0,NULL)

# ifndef OPENSSL_NO_SRP
/* see tls_srp.c */
#  ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 __owur int SSL_SRP_CTX_init(SSL *s);
OSSL_DEPRECATEDIN_3_0 __owur int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx);
OSSL_DEPRECATEDIN_3_0 int SSL_SRP_CTX_free(SSL *ctx);
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx);
OSSL_DEPRECATEDIN_3_0 __owur int SSL_srp_server_param_with_username(SSL *s,
                                                                    int *ad);
OSSL_DEPRECATEDIN_3_0 __owur int SRP_Calc_A_param(SSL *s);
#  endif
# endif

/* 100k max cert list */
# define SSL_MAX_CERT_LIST_DEFAULT (1024*100)

# define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT      (1024*20)

/*
 * This callback type is used inside SSL_CTX, SSL, and in the functions that
 * set them. It is used to override the generation of SSL/TLS session IDs in
 * a server. Return value should be zero on an error, non-zero to proceed.
 * Also, callbacks should themselves check if the id they generate is unique
 * otherwise the SSL handshake will fail with an error - callbacks can do
 * this using the 'ssl' value they're passed by;
 * SSL_has_matching_session_id(ssl, id, *id_len) The length value passed in
 * is set at the maximum size the session ID can be. In SSLv3/TLSv1 it is 32
 * bytes. The callback can alter this length to be less if desired. It is
 * also an error for the callback to set the size to zero.
 */
typedef int (*GEN_SESSION_CB) (SSL *ssl, unsigned char *id,
                               unsigned int *id_len);

# define SSL_SESS_CACHE_OFF                      0x0000
# define SSL_SESS_CACHE_CLIENT                   0x0001
# define SSL_SESS_CACHE_SERVER                   0x0002
# define SSL_SESS_CACHE_BOTH     (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
# define SSL_SESS_CACHE_NO_AUTO_CLEAR            0x0080
/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
# define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP       0x0100
# define SSL_SESS_CACHE_NO_INTERNAL_STORE        0x0200
# define SSL_SESS_CACHE_NO_INTERNAL \
        (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
# define SSL_SESS_CACHE_UPDATE_TIME              0x0400

LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
# define SSL_CTX_sess_number(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
# define SSL_CTX_sess_connect(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
# define SSL_CTX_sess_connect_good(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
# define SSL_CTX_sess_connect_renegotiate(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
# define SSL_CTX_sess_accept(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
# define SSL_CTX_sess_accept_renegotiate(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
# define SSL_CTX_sess_accept_good(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
# define SSL_CTX_sess_hits(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
# define SSL_CTX_sess_cb_hits(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
# define SSL_CTX_sess_misses(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
# define SSL_CTX_sess_timeouts(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
# define SSL_CTX_sess_cache_full(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)

void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
                             int (*new_session_cb) (struct ssl_st *ssl,
                                                    SSL_SESSION *sess));
int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
                                              SSL_SESSION *sess);
void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
                                void (*remove_session_cb) (struct ssl_ctx_st
                                                           *ctx,
                                                           SSL_SESSION *sess));
void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (struct ssl_ctx_st *ctx,
                                                  SSL_SESSION *sess);
void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
                             SSL_SESSION *(*get_session_cb) (struct ssl_st
                                                             *ssl,
                                                             const unsigned char
                                                             *data, int len,
                                                             int *copy));
SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
                                                       const unsigned char *data,
                                                       int len, int *copy);
void SSL_CTX_set_info_callback(SSL_CTX *ctx,
                               void (*cb) (const SSL *ssl, int type, int val));
void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type,
                                                 int val);
void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
                                int (*client_cert_cb) (SSL *ssl, X509 **x509,
                                                       EVP_PKEY **pkey));
int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
                                                 EVP_PKEY **pkey);
# ifndef OPENSSL_NO_ENGINE
__owur int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
# endif
void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
                                    int (*app_gen_cookie_cb) (SSL *ssl,
                                                              unsigned char
                                                              *cookie,
                                                              unsigned int
                                                              *cookie_len));
void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
                                  int (*app_verify_cookie_cb) (SSL *ssl,
                                                               const unsigned
                                                               char *cookie,
                                                               unsigned int
                                                               cookie_len));

void SSL_CTX_set_stateless_cookie_generate_cb(
    SSL_CTX *ctx,
    int (*gen_stateless_cookie_cb) (SSL *ssl,
                                    unsigned char *cookie,
                                    size_t *cookie_len));
void SSL_CTX_set_stateless_cookie_verify_cb(
    SSL_CTX *ctx,
    int (*verify_stateless_cookie_cb) (SSL *ssl,
                                       const unsigned char *cookie,
                                       size_t cookie_len));
# ifndef OPENSSL_NO_NEXTPROTONEG

typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl,
                                              const unsigned char **out,
                                              unsigned int *outlen,
                                              void *arg);
void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s,
                                           SSL_CTX_npn_advertised_cb_func cb,
                                           void *arg);
#  define SSL_CTX_set_npn_advertised_cb SSL_CTX_set_next_protos_advertised_cb

typedef int (*SSL_CTX_npn_select_cb_func)(SSL *s,
                                          unsigned char **out,
                                          unsigned char *outlen,
                                          const unsigned char *in,
                                          unsigned int inlen,
                                          void *arg);
void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
                                      SSL_CTX_npn_select_cb_func cb,
                                      void *arg);
#  define SSL_CTX_set_npn_select_cb SSL_CTX_set_next_proto_select_cb

void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
                                    unsigned *len);
#  define SSL_get0_npn_negotiated SSL_get0_next_proto_negotiated
# endif

__owur int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
                                 const unsigned char *in, unsigned int inlen,
                                 const unsigned char *client,
                                 unsigned int client_len);

# define OPENSSL_NPN_UNSUPPORTED 0
# define OPENSSL_NPN_NEGOTIATED  1
# define OPENSSL_NPN_NO_OVERLAP  2

__owur int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
                                   unsigned int protos_len);
__owur int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
                               unsigned int protos_len);
typedef int (*SSL_CTX_alpn_select_cb_func)(SSL *ssl,
                                           const unsigned char **out,
                                           unsigned char *outlen,
                                           const unsigned char *in,
                                           unsigned int inlen,
                                           void *arg);
void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
                                SSL_CTX_alpn_select_cb_func cb,
                                void *arg);
void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
                            unsigned int *len);

# ifndef OPENSSL_NO_PSK
/*
 * the maximum length of the buffer given to callbacks containing the
 * resulting identity/psk
 */
#  define PSK_MAX_IDENTITY_LEN 256
#  define PSK_MAX_PSK_LEN 512
typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl,
                                               const char *hint,
                                               char *identity,
                                               unsigned int max_identity_len,
                                               unsigned char *psk,
                                               unsigned int max_psk_len);
void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb);
void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb);

typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl,
                                               const char *identity,
                                               unsigned char *psk,
                                               unsigned int max_psk_len);
void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb);
void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb);

__owur int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
__owur int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
const char *SSL_get_psk_identity_hint(const SSL *s);
const char *SSL_get_psk_identity(const SSL *s);
# endif

typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl,
                                            const unsigned char *identity,
                                            size_t identity_len,
                                            SSL_SESSION **sess);
typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md,
                                           const unsigned char **id,
                                           size_t *idlen,
                                           SSL_SESSION **sess);

void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb);
void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx,
                                           SSL_psk_find_session_cb_func cb);
void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb);
void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx,
                                          SSL_psk_use_session_cb_func cb);

/* Register callbacks to handle custom TLS Extensions for client or server. */

__owur int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx,
                                         unsigned int ext_type);

__owur int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx,
                                         unsigned int ext_type,
                                         custom_ext_add_cb add_cb,
                                         custom_ext_free_cb free_cb,
                                         void *add_arg,
                                         custom_ext_parse_cb parse_cb,
                                         void *parse_arg);

__owur int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx,
                                         unsigned int ext_type,
                                         custom_ext_add_cb add_cb,
                                         custom_ext_free_cb free_cb,
                                         void *add_arg,
                                         custom_ext_parse_cb parse_cb,
                                         void *parse_arg);

__owur int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
                                  unsigned int context,
                                  SSL_custom_ext_add_cb_ex add_cb,
                                  SSL_custom_ext_free_cb_ex free_cb,
                                  void *add_arg,
                                  SSL_custom_ext_parse_cb_ex parse_cb,
                                  void *parse_arg);

__owur int SSL_extension_supported(unsigned int ext_type);

# define SSL_NOTHING            1
# define SSL_WRITING            2
# define SSL_READING            3
# define SSL_X509_LOOKUP        4
# define SSL_ASYNC_PAUSED       5
# define SSL_ASYNC_NO_JOBS      6
# define SSL_CLIENT_HELLO_CB    7
# define SSL_RETRY_VERIFY       8

/* These will only be used when doing non-blocking IO */
# define SSL_want_nothing(s)         (SSL_want(s) == SSL_NOTHING)
# define SSL_want_read(s)            (SSL_want(s) == SSL_READING)
# define SSL_want_write(s)           (SSL_want(s) == SSL_WRITING)
# define SSL_want_x509_lookup(s)     (SSL_want(s) == SSL_X509_LOOKUP)
# define SSL_want_retry_verify(s)    (SSL_want(s) == SSL_RETRY_VERIFY)
# define SSL_want_async(s)           (SSL_want(s) == SSL_ASYNC_PAUSED)
# define SSL_want_async_job(s)       (SSL_want(s) == SSL_ASYNC_NO_JOBS)
# define SSL_want_client_hello_cb(s) (SSL_want(s) == SSL_CLIENT_HELLO_CB)

# define SSL_MAC_FLAG_READ_MAC_STREAM 1
# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
# define SSL_MAC_FLAG_READ_MAC_TLSTREE 4
# define SSL_MAC_FLAG_WRITE_MAC_TLSTREE 8

/*
 * A callback for logging out TLS key material. This callback should log out
 * |line| followed by a newline.
 */
typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line);

/*
 * SSL_CTX_set_keylog_callback configures a callback to log key material. This
 * is intended for debugging use with tools like Wireshark. The cb function
 * should log line followed by a newline.
 */
void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb);

/*
 * SSL_CTX_get_keylog_callback returns the callback configured by
 * SSL_CTX_set_keylog_callback.
 */
SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx);

int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data);
uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
uint32_t SSL_get_max_early_data(const SSL *s);
int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data);
uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx);
int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data);
uint32_t SSL_get_recv_max_early_data(const SSL *s);

#ifdef __cplusplus
}
#endif

# include <openssl/ssl2.h>
# include <openssl/ssl3.h>
# include <openssl/tls1.h>      /* This is mostly sslv3 with a few tweaks */
# include <openssl/dtls1.h>     /* Datagram TLS */
# include <openssl/srtp.h>      /* Support for the use_srtp extension */

#ifdef  __cplusplus
extern "C" {
#endif

/*
 * These need to be after the above set of includes due to a compiler bug
 * in VisualStudio 2015
 */
SKM_DEFINE_STACK_OF_INTERNAL(SSL_CIPHER, const SSL_CIPHER, SSL_CIPHER)
#define sk_SSL_CIPHER_num(sk) OPENSSL_sk_num(ossl_check_const_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_value(sk, idx) ((const SSL_CIPHER *)OPENSSL_sk_value(ossl_check_const_SSL_CIPHER_sk_type(sk), (idx)))
#define sk_SSL_CIPHER_new(cmp) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_new(ossl_check_SSL_CIPHER_compfunc_type(cmp)))
#define sk_SSL_CIPHER_new_null() ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_new_null())
#define sk_SSL_CIPHER_new_reserve(cmp, n) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_new_reserve(ossl_check_SSL_CIPHER_compfunc_type(cmp), (n)))
#define sk_SSL_CIPHER_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_SSL_CIPHER_sk_type(sk), (n))
#define sk_SSL_CIPHER_free(sk) OPENSSL_sk_free(ossl_check_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_zero(sk) OPENSSL_sk_zero(ossl_check_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_delete(sk, i) ((const SSL_CIPHER *)OPENSSL_sk_delete(ossl_check_SSL_CIPHER_sk_type(sk), (i)))
#define sk_SSL_CIPHER_delete_ptr(sk, ptr) ((const SSL_CIPHER *)OPENSSL_sk_delete_ptr(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr)))
#define sk_SSL_CIPHER_push(sk, ptr) OPENSSL_sk_push(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_pop(sk) ((const SSL_CIPHER *)OPENSSL_sk_pop(ossl_check_SSL_CIPHER_sk_type(sk)))
#define sk_SSL_CIPHER_shift(sk) ((const SSL_CIPHER *)OPENSSL_sk_shift(ossl_check_SSL_CIPHER_sk_type(sk)))
#define sk_SSL_CIPHER_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SSL_CIPHER_sk_type(sk),ossl_check_SSL_CIPHER_freefunc_type(freefunc))
#define sk_SSL_CIPHER_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr), (idx))
#define sk_SSL_CIPHER_set(sk, idx, ptr) ((const SSL_CIPHER *)OPENSSL_sk_set(ossl_check_SSL_CIPHER_sk_type(sk), (idx), ossl_check_SSL_CIPHER_type(ptr)))
#define sk_SSL_CIPHER_find(sk, ptr) OPENSSL_sk_find(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr))
#define sk_SSL_CIPHER_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_type(ptr), pnum)
#define sk_SSL_CIPHER_sort(sk) OPENSSL_sk_sort(ossl_check_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_SSL_CIPHER_sk_type(sk))
#define sk_SSL_CIPHER_dup(sk) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_dup(ossl_check_const_SSL_CIPHER_sk_type(sk)))
#define sk_SSL_CIPHER_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(SSL_CIPHER) *)OPENSSL_sk_deep_copy(ossl_check_const_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_copyfunc_type(copyfunc), ossl_check_SSL_CIPHER_freefunc_type(freefunc)))
#define sk_SSL_CIPHER_set_cmp_func(sk, cmp) ((sk_SSL_CIPHER_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_SSL_CIPHER_sk_type(sk), ossl_check_SSL_CIPHER_compfunc_type(cmp)))
SKM_DEFINE_STACK_OF_INTERNAL(SSL_COMP, SSL_COMP, SSL_COMP)
#define sk_SSL_COMP_num(sk) OPENSSL_sk_num(ossl_check_const_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_value(sk, idx) ((SSL_COMP *)OPENSSL_sk_value(ossl_check_const_SSL_COMP_sk_type(sk), (idx)))
#define sk_SSL_COMP_new(cmp) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_new(ossl_check_SSL_COMP_compfunc_type(cmp)))
#define sk_SSL_COMP_new_null() ((STACK_OF(SSL_COMP) *)OPENSSL_sk_new_null())
#define sk_SSL_COMP_new_reserve(cmp, n) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_new_reserve(ossl_check_SSL_COMP_compfunc_type(cmp), (n)))
#define sk_SSL_COMP_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_SSL_COMP_sk_type(sk), (n))
#define sk_SSL_COMP_free(sk) OPENSSL_sk_free(ossl_check_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_zero(sk) OPENSSL_sk_zero(ossl_check_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_delete(sk, i) ((SSL_COMP *)OPENSSL_sk_delete(ossl_check_SSL_COMP_sk_type(sk), (i)))
#define sk_SSL_COMP_delete_ptr(sk, ptr) ((SSL_COMP *)OPENSSL_sk_delete_ptr(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr)))
#define sk_SSL_COMP_push(sk, ptr) OPENSSL_sk_push(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_pop(sk) ((SSL_COMP *)OPENSSL_sk_pop(ossl_check_SSL_COMP_sk_type(sk)))
#define sk_SSL_COMP_shift(sk) ((SSL_COMP *)OPENSSL_sk_shift(ossl_check_SSL_COMP_sk_type(sk)))
#define sk_SSL_COMP_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SSL_COMP_sk_type(sk),ossl_check_SSL_COMP_freefunc_type(freefunc))
#define sk_SSL_COMP_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr), (idx))
#define sk_SSL_COMP_set(sk, idx, ptr) ((SSL_COMP *)OPENSSL_sk_set(ossl_check_SSL_COMP_sk_type(sk), (idx), ossl_check_SSL_COMP_type(ptr)))
#define sk_SSL_COMP_find(sk, ptr) OPENSSL_sk_find(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
#define sk_SSL_COMP_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr), pnum)
#define sk_SSL_COMP_sort(sk) OPENSSL_sk_sort(ossl_check_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_SSL_COMP_sk_type(sk))
#define sk_SSL_COMP_dup(sk) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_dup(ossl_check_const_SSL_COMP_sk_type(sk)))
#define sk_SSL_COMP_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(SSL_COMP) *)OPENSSL_sk_deep_copy(ossl_check_const_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_copyfunc_type(copyfunc), ossl_check_SSL_COMP_freefunc_type(freefunc)))
#define sk_SSL_COMP_set_cmp_func(sk, cmp) ((sk_SSL_COMP_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_compfunc_type(cmp)))


/* compatibility */
# define SSL_set_app_data(s,arg)         (SSL_set_ex_data(s,0,(char *)(arg)))
# define SSL_get_app_data(s)             (SSL_get_ex_data(s,0))
# define SSL_SESSION_set_app_data(s,a)   (SSL_SESSION_set_ex_data(s,0, \
                                                                  (char *)(a)))
# define SSL_SESSION_get_app_data(s)     (SSL_SESSION_get_ex_data(s,0))
# define SSL_CTX_get_app_data(ctx)       (SSL_CTX_get_ex_data(ctx,0))
# define SSL_CTX_set_app_data(ctx,arg)   (SSL_CTX_set_ex_data(ctx,0, \
                                                              (char *)(arg)))
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 void SSL_set_debug(SSL *s, int debug);
# endif

/* TLSv1.3 KeyUpdate message types */
/* -1 used so that this is an invalid value for the on-the-wire protocol */
#define SSL_KEY_UPDATE_NONE             -1
/* Values as defined for the on-the-wire protocol */
#define SSL_KEY_UPDATE_NOT_REQUESTED     0
#define SSL_KEY_UPDATE_REQUESTED         1

/*
 * The valid handshake states (one for each type message sent and one for each
 * type of message received). There are also two "special" states:
 * TLS = TLS or DTLS state
 * DTLS = DTLS specific state
 * CR/SR = Client Read/Server Read
 * CW/SW = Client Write/Server Write
 *
 * The "special" states are:
 * TLS_ST_BEFORE = No handshake has been initiated yet
 * TLS_ST_OK = A handshake has been successfully completed
 */
typedef enum {
    TLS_ST_BEFORE,
    TLS_ST_OK,
    DTLS_ST_CR_HELLO_VERIFY_REQUEST,
    TLS_ST_CR_SRVR_HELLO,
    TLS_ST_CR_CERT,
    TLS_ST_CR_CERT_STATUS,
    TLS_ST_CR_KEY_EXCH,
    TLS_ST_CR_CERT_REQ,
    TLS_ST_CR_SRVR_DONE,
    TLS_ST_CR_SESSION_TICKET,
    TLS_ST_CR_CHANGE,
    TLS_ST_CR_FINISHED,
    TLS_ST_CW_CLNT_HELLO,
    TLS_ST_CW_CERT,
    TLS_ST_CW_KEY_EXCH,
    TLS_ST_CW_CERT_VRFY,
    TLS_ST_CW_CHANGE,
    TLS_ST_CW_NEXT_PROTO,
    TLS_ST_CW_FINISHED,
    TLS_ST_SW_HELLO_REQ,
    TLS_ST_SR_CLNT_HELLO,
    DTLS_ST_SW_HELLO_VERIFY_REQUEST,
    TLS_ST_SW_SRVR_HELLO,
    TLS_ST_SW_CERT,
    TLS_ST_SW_KEY_EXCH,
    TLS_ST_SW_CERT_REQ,
    TLS_ST_SW_SRVR_DONE,
    TLS_ST_SR_CERT,
    TLS_ST_SR_KEY_EXCH,
    TLS_ST_SR_CERT_VRFY,
    TLS_ST_SR_NEXT_PROTO,
    TLS_ST_SR_CHANGE,
    TLS_ST_SR_FINISHED,
    TLS_ST_SW_SESSION_TICKET,
    TLS_ST_SW_CERT_STATUS,
    TLS_ST_SW_CHANGE,
    TLS_ST_SW_FINISHED,
    TLS_ST_SW_ENCRYPTED_EXTENSIONS,
    TLS_ST_CR_ENCRYPTED_EXTENSIONS,
    TLS_ST_CR_CERT_VRFY,
    TLS_ST_SW_CERT_VRFY,
    TLS_ST_CR_HELLO_REQ,
    TLS_ST_SW_KEY_UPDATE,
    TLS_ST_CW_KEY_UPDATE,
    TLS_ST_SR_KEY_UPDATE,
    TLS_ST_CR_KEY_UPDATE,
    TLS_ST_EARLY_DATA,
    TLS_ST_PENDING_EARLY_DATA_END,
    TLS_ST_CW_END_OF_EARLY_DATA,
    TLS_ST_SR_END_OF_EARLY_DATA
} OSSL_HANDSHAKE_STATE;

/*
 * Most of the following state values are no longer used and are defined to be
 * the closest equivalent value in the current state machine code. Not all
 * defines have an equivalent and are set to a dummy value (-1). SSL_ST_CONNECT
 * and SSL_ST_ACCEPT are still in use in the definition of SSL_CB_ACCEPT_LOOP,
 * SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP and SSL_CB_CONNECT_EXIT.
 */

# define SSL_ST_CONNECT                  0x1000
# define SSL_ST_ACCEPT                   0x2000

# define SSL_ST_MASK                     0x0FFF

# define SSL_CB_LOOP                     0x01
# define SSL_CB_EXIT                     0x02
# define SSL_CB_READ                     0x04
# define SSL_CB_WRITE                    0x08
# define SSL_CB_ALERT                    0x4000/* used in callback */
# define SSL_CB_READ_ALERT               (SSL_CB_ALERT|SSL_CB_READ)
# define SSL_CB_WRITE_ALERT              (SSL_CB_ALERT|SSL_CB_WRITE)
# define SSL_CB_ACCEPT_LOOP              (SSL_ST_ACCEPT|SSL_CB_LOOP)
# define SSL_CB_ACCEPT_EXIT              (SSL_ST_ACCEPT|SSL_CB_EXIT)
# define SSL_CB_CONNECT_LOOP             (SSL_ST_CONNECT|SSL_CB_LOOP)
# define SSL_CB_CONNECT_EXIT             (SSL_ST_CONNECT|SSL_CB_EXIT)
# define SSL_CB_HANDSHAKE_START          0x10
# define SSL_CB_HANDSHAKE_DONE           0x20

/* Is the SSL_connection established? */
# define SSL_in_connect_init(a)          (SSL_in_init(a) && !SSL_is_server(a))
# define SSL_in_accept_init(a)           (SSL_in_init(a) && SSL_is_server(a))
int SSL_in_init(const SSL *s);
int SSL_in_before(const SSL *s);
int SSL_is_init_finished(const SSL *s);

/*
 * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you
 * should not need these
 */
# define SSL_ST_READ_HEADER                      0xF0
# define SSL_ST_READ_BODY                        0xF1
# define SSL_ST_READ_DONE                        0xF2

/*-
 * Obtain latest Finished message
 *   -- that we sent (SSL_get_finished)
 *   -- that we expected from peer (SSL_get_peer_finished).
 * Returns length (0 == no Finished so far), copies up to 'count' bytes.
 */
size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);

/*
 * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options are
 * 'ored' with SSL_VERIFY_PEER if they are desired
 */
# define SSL_VERIFY_NONE                 0x00
# define SSL_VERIFY_PEER                 0x01
# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
# define SSL_VERIFY_CLIENT_ONCE          0x04
# define SSL_VERIFY_POST_HANDSHAKE       0x08

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define OpenSSL_add_ssl_algorithms()   SSL_library_init()
#  define SSLeay_add_ssl_algorithms()    SSL_library_init()
# endif

/* More backward compatibility */
# define SSL_get_cipher(s) \
                SSL_CIPHER_get_name(SSL_get_current_cipher(s))
# define SSL_get_cipher_bits(s,np) \
                SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
# define SSL_get_cipher_version(s) \
                SSL_CIPHER_get_version(SSL_get_current_cipher(s))
# define SSL_get_cipher_name(s) \
                SSL_CIPHER_get_name(SSL_get_current_cipher(s))
# define SSL_get_time(a)         SSL_SESSION_get_time(a)
# define SSL_set_time(a,b)       SSL_SESSION_set_time((a),(b))
# define SSL_get_timeout(a)      SSL_SESSION_get_timeout(a)
# define SSL_set_timeout(a,b)    SSL_SESSION_set_timeout((a),(b))

# define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
# define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)

DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_AD_REASON_OFFSET            1000/* offset to get SSL_R_... value
                                              * from SSL_AD_... */
/* These alert types are for SSLv3 and TLSv1 */
# define SSL_AD_CLOSE_NOTIFY             SSL3_AD_CLOSE_NOTIFY
/* fatal */
# define SSL_AD_UNEXPECTED_MESSAGE       SSL3_AD_UNEXPECTED_MESSAGE
/* fatal */
# define SSL_AD_BAD_RECORD_MAC           SSL3_AD_BAD_RECORD_MAC
# define SSL_AD_DECRYPTION_FAILED        TLS1_AD_DECRYPTION_FAILED
# define SSL_AD_RECORD_OVERFLOW          TLS1_AD_RECORD_OVERFLOW
/* fatal */
# define SSL_AD_DECOMPRESSION_FAILURE    SSL3_AD_DECOMPRESSION_FAILURE
/* fatal */
# define SSL_AD_HANDSHAKE_FAILURE        SSL3_AD_HANDSHAKE_FAILURE
/* Not for TLS */
# define SSL_AD_NO_CERTIFICATE           SSL3_AD_NO_CERTIFICATE
# define SSL_AD_BAD_CERTIFICATE          SSL3_AD_BAD_CERTIFICATE
# define SSL_AD_UNSUPPORTED_CERTIFICATE  SSL3_AD_UNSUPPORTED_CERTIFICATE
# define SSL_AD_CERTIFICATE_REVOKED      SSL3_AD_CERTIFICATE_REVOKED
# define SSL_AD_CERTIFICATE_EXPIRED      SSL3_AD_CERTIFICATE_EXPIRED
# define SSL_AD_CERTIFICATE_UNKNOWN      SSL3_AD_CERTIFICATE_UNKNOWN
/* fatal */
# define SSL_AD_ILLEGAL_PARAMETER        SSL3_AD_ILLEGAL_PARAMETER
/* fatal */
# define SSL_AD_UNKNOWN_CA               TLS1_AD_UNKNOWN_CA
/* fatal */
# define SSL_AD_ACCESS_DENIED            TLS1_AD_ACCESS_DENIED
/* fatal */
# define SSL_AD_DECODE_ERROR             TLS1_AD_DECODE_ERROR
# define SSL_AD_DECRYPT_ERROR            TLS1_AD_DECRYPT_ERROR
/* fatal */
# define SSL_AD_EXPORT_RESTRICTION       TLS1_AD_EXPORT_RESTRICTION
/* fatal */
# define SSL_AD_PROTOCOL_VERSION         TLS1_AD_PROTOCOL_VERSION
/* fatal */
# define SSL_AD_INSUFFICIENT_SECURITY    TLS1_AD_INSUFFICIENT_SECURITY
/* fatal */
# define SSL_AD_INTERNAL_ERROR           TLS1_AD_INTERNAL_ERROR
# define SSL_AD_USER_CANCELLED           TLS1_AD_USER_CANCELLED
# define SSL_AD_NO_RENEGOTIATION         TLS1_AD_NO_RENEGOTIATION
# define SSL_AD_MISSING_EXTENSION        TLS13_AD_MISSING_EXTENSION
# define SSL_AD_CERTIFICATE_REQUIRED     TLS13_AD_CERTIFICATE_REQUIRED
# define SSL_AD_UNSUPPORTED_EXTENSION    TLS1_AD_UNSUPPORTED_EXTENSION
# define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
# define SSL_AD_UNRECOGNIZED_NAME        TLS1_AD_UNRECOGNIZED_NAME
# define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
# define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
/* fatal */
# define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY
/* fatal */
# define SSL_AD_INAPPROPRIATE_FALLBACK   TLS1_AD_INAPPROPRIATE_FALLBACK
# define SSL_AD_NO_APPLICATION_PROTOCOL  TLS1_AD_NO_APPLICATION_PROTOCOL
# define SSL_ERROR_NONE                  0
# define SSL_ERROR_SSL                   1
# define SSL_ERROR_WANT_READ             2
# define SSL_ERROR_WANT_WRITE            3
# define SSL_ERROR_WANT_X509_LOOKUP      4
# define SSL_ERROR_SYSCALL               5/* look at error stack/return
                                           * value/errno */
# define SSL_ERROR_ZERO_RETURN           6
# define SSL_ERROR_WANT_CONNECT          7
# define SSL_ERROR_WANT_ACCEPT           8
# define SSL_ERROR_WANT_ASYNC            9
# define SSL_ERROR_WANT_ASYNC_JOB       10
# define SSL_ERROR_WANT_CLIENT_HELLO_CB 11
# define SSL_ERROR_WANT_RETRY_VERIFY    12

# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTRL_SET_TMP_DH                    3
#  define SSL_CTRL_SET_TMP_ECDH                  4
#  define SSL_CTRL_SET_TMP_DH_CB                 6
# endif

# define SSL_CTRL_GET_CLIENT_CERT_REQUEST        9
# define SSL_CTRL_GET_NUM_RENEGOTIATIONS         10
# define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS       11
# define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS       12
# define SSL_CTRL_GET_FLAGS                      13
# define SSL_CTRL_EXTRA_CHAIN_CERT               14
# define SSL_CTRL_SET_MSG_CALLBACK               15
# define SSL_CTRL_SET_MSG_CALLBACK_ARG           16
/* only applies to datagram connections */
# define SSL_CTRL_SET_MTU                17
/* Stats */
# define SSL_CTRL_SESS_NUMBER                    20
# define SSL_CTRL_SESS_CONNECT                   21
# define SSL_CTRL_SESS_CONNECT_GOOD              22
# define SSL_CTRL_SESS_CONNECT_RENEGOTIATE       23
# define SSL_CTRL_SESS_ACCEPT                    24
# define SSL_CTRL_SESS_ACCEPT_GOOD               25
# define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE        26
# define SSL_CTRL_SESS_HIT                       27
# define SSL_CTRL_SESS_CB_HIT                    28
# define SSL_CTRL_SESS_MISSES                    29
# define SSL_CTRL_SESS_TIMEOUTS                  30
# define SSL_CTRL_SESS_CACHE_FULL                31
# define SSL_CTRL_MODE                           33
# define SSL_CTRL_GET_READ_AHEAD                 40
# define SSL_CTRL_SET_READ_AHEAD                 41
# define SSL_CTRL_SET_SESS_CACHE_SIZE            42
# define SSL_CTRL_GET_SESS_CACHE_SIZE            43
# define SSL_CTRL_SET_SESS_CACHE_MODE            44
# define SSL_CTRL_GET_SESS_CACHE_MODE            45
# define SSL_CTRL_GET_MAX_CERT_LIST              50
# define SSL_CTRL_SET_MAX_CERT_LIST              51
# define SSL_CTRL_SET_MAX_SEND_FRAGMENT          52
/* see tls1.h for macros based on these */
# define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB       53
# define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG      54
# define SSL_CTRL_SET_TLSEXT_HOSTNAME            55
# define SSL_CTRL_SET_TLSEXT_DEBUG_CB            56
# define SSL_CTRL_SET_TLSEXT_DEBUG_ARG           57
# define SSL_CTRL_GET_TLSEXT_TICKET_KEYS         58
# define SSL_CTRL_SET_TLSEXT_TICKET_KEYS         59
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT    60 */
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 61 */
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 */
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB       63
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG   64
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE     65
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS     66
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS     67
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS      68
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS      69
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP        70
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP        71
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB      72
# endif
# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB    75
# define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB                76
# define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB             77
# define SSL_CTRL_SET_SRP_ARG            78
# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME               79
# define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH               80
# define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD               81
# define DTLS_CTRL_GET_TIMEOUT           73
# define DTLS_CTRL_HANDLE_TIMEOUT        74
# define SSL_CTRL_GET_RI_SUPPORT                 76
# define SSL_CTRL_CLEAR_MODE                     78
# define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB      79
# define SSL_CTRL_GET_EXTRA_CHAIN_CERTS          82
# define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS        83
# define SSL_CTRL_CHAIN                          88
# define SSL_CTRL_CHAIN_CERT                     89
# define SSL_CTRL_GET_GROUPS                     90
# define SSL_CTRL_SET_GROUPS                     91
# define SSL_CTRL_SET_GROUPS_LIST                92
# define SSL_CTRL_GET_SHARED_GROUP               93
# define SSL_CTRL_SET_SIGALGS                    97
# define SSL_CTRL_SET_SIGALGS_LIST               98
# define SSL_CTRL_CERT_FLAGS                     99
# define SSL_CTRL_CLEAR_CERT_FLAGS               100
# define SSL_CTRL_SET_CLIENT_SIGALGS             101
# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST        102
# define SSL_CTRL_GET_CLIENT_CERT_TYPES          103
# define SSL_CTRL_SET_CLIENT_CERT_TYPES          104
# define SSL_CTRL_BUILD_CERT_CHAIN               105
# define SSL_CTRL_SET_VERIFY_CERT_STORE          106
# define SSL_CTRL_SET_CHAIN_CERT_STORE           107
# define SSL_CTRL_GET_PEER_SIGNATURE_NID         108
# define SSL_CTRL_GET_PEER_TMP_KEY               109
# define SSL_CTRL_GET_RAW_CIPHERLIST             110
# define SSL_CTRL_GET_EC_POINT_FORMATS           111
# define SSL_CTRL_GET_CHAIN_CERTS                115
# define SSL_CTRL_SELECT_CURRENT_CERT            116
# define SSL_CTRL_SET_CURRENT_CERT               117
# define SSL_CTRL_SET_DH_AUTO                    118
# define DTLS_CTRL_SET_LINK_MTU                  120
# define DTLS_CTRL_GET_LINK_MIN_MTU              121
# define SSL_CTRL_GET_EXTMS_SUPPORT              122
# define SSL_CTRL_SET_MIN_PROTO_VERSION          123
# define SSL_CTRL_SET_MAX_PROTO_VERSION          124
# define SSL_CTRL_SET_SPLIT_SEND_FRAGMENT        125
# define SSL_CTRL_SET_MAX_PIPELINES              126
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE     127
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB       128
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG   129
# define SSL_CTRL_GET_MIN_PROTO_VERSION          130
# define SSL_CTRL_GET_MAX_PROTO_VERSION          131
# define SSL_CTRL_GET_SIGNATURE_NID              132
# define SSL_CTRL_GET_TMP_KEY                    133
# define SSL_CTRL_GET_NEGOTIATED_GROUP           134
# define SSL_CTRL_SET_RETRY_VERIFY               136
# define SSL_CTRL_GET_VERIFY_CERT_STORE          137
# define SSL_CTRL_GET_CHAIN_CERT_STORE           138
# define SSL_CERT_SET_FIRST                      1
# define SSL_CERT_SET_NEXT                       2
# define SSL_CERT_SET_SERVER                     3
# define DTLSv1_get_timeout(ssl, arg) \
        SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)(arg))
# define DTLSv1_handle_timeout(ssl) \
        SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
# define SSL_num_renegotiations(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
# define SSL_clear_num_renegotiations(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
# define SSL_total_renegotiations(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTX_set_tmp_dh(ctx,dh) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
# endif
# define SSL_CTX_set_dh_auto(ctx, onoff) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
# define SSL_set_dh_auto(s, onoff) \
        SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_set_tmp_dh(ssl,dh) \
        SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
# endif
# ifndef OPENSSL_NO_DEPRECATED_3_0
#  define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
#  define SSL_set_tmp_ecdh(ssl,ecdh) \
        SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
# endif
# define SSL_CTX_add_extra_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)(x509))
# define SSL_CTX_get_extra_chain_certs(ctx,px509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509)
# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509)
# define SSL_CTX_clear_extra_chain_certs(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL)
# define SSL_CTX_set0_chain(ctx,sk) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk))
# define SSL_CTX_set1_chain(ctx,sk) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk))
# define SSL_CTX_add0_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
# define SSL_CTX_add1_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
# define SSL_CTX_get0_chain_certs(ctx,px509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
# define SSL_CTX_clear_chain_certs(ctx) \
        SSL_CTX_set0_chain(ctx,NULL)
# define SSL_CTX_build_cert_chain(ctx, flags) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
# define SSL_CTX_select_current_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
# define SSL_CTX_set_current_cert(ctx, op) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
# define SSL_CTX_set0_verify_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set1_verify_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
# define SSL_CTX_get0_verify_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set0_chain_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set1_chain_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
# define SSL_CTX_get0_chain_cert_store(ctx,st) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_set0_chain(s,sk) \
        SSL_ctrl(s,SSL_CTRL_CHAIN,0,(char *)(sk))
# define SSL_set1_chain(s,sk) \
        SSL_ctrl(s,SSL_CTRL_CHAIN,1,(char *)(sk))
# define SSL_add0_chain_cert(s,x509) \
        SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
# define SSL_add1_chain_cert(s,x509) \
        SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
# define SSL_get0_chain_certs(s,px509) \
        SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
# define SSL_clear_chain_certs(s) \
        SSL_set0_chain(s,NULL)
# define SSL_build_cert_chain(s, flags) \
        SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
# define SSL_select_current_cert(s,x509) \
        SSL_ctrl(s,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
# define SSL_set_current_cert(s,op) \
        SSL_ctrl(s,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
# define SSL_set0_verify_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_set1_verify_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
#define SSL_get0_verify_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_set0_chain_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_set1_chain_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
#define SSL_get0_chain_cert_store(s,st) \
        SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))

# define SSL_get1_groups(s, glist) \
        SSL_ctrl(s,SSL_CTRL_GET_GROUPS,0,(int*)(glist))
# define SSL_CTX_set1_groups(ctx, glist, glistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(int *)(glist))
# define SSL_CTX_set1_groups_list(ctx, s) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s))
# define SSL_set1_groups(s, glist, glistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist))
# define SSL_set1_groups_list(s, str) \
        SSL_ctrl(s,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(str))
# define SSL_get_shared_group(s, n) \
        SSL_ctrl(s,SSL_CTRL_GET_SHARED_GROUP,n,NULL)
# define SSL_get_negotiated_group(s) \
        SSL_ctrl(s,SSL_CTRL_GET_NEGOTIATED_GROUP,0,NULL)
# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
# define SSL_CTX_set1_sigalgs_list(ctx, s) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s))
# define SSL_set1_sigalgs(s, slist, slistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
# define SSL_set1_sigalgs_list(s, str) \
        SSL_ctrl(s,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(str))
# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s))
# define SSL_set1_client_sigalgs(s, slist, slistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
# define SSL_set1_client_sigalgs_list(s, str) \
        SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(str))
# define SSL_get0_certificate_types(s, clist) \
        SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)(clist))
# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen, \
                     (char *)(clist))
# define SSL_set1_client_certificate_types(s, clist, clistlen) \
        SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)(clist))
# define SSL_get_signature_nid(s, pn) \
        SSL_ctrl(s,SSL_CTRL_GET_SIGNATURE_NID,0,pn)
# define SSL_get_peer_signature_nid(s, pn) \
        SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn)
# define SSL_get_peer_tmp_key(s, pk) \
        SSL_ctrl(s,SSL_CTRL_GET_PEER_TMP_KEY,0,pk)
# define SSL_get_tmp_key(s, pk) \
        SSL_ctrl(s,SSL_CTRL_GET_TMP_KEY,0,pk)
# define SSL_get0_raw_cipherlist(s, plst) \
        SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,plst)
# define SSL_get0_ec_point_formats(s, plst) \
        SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,plst)
# define SSL_CTX_set_min_proto_version(ctx, version) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
# define SSL_CTX_set_max_proto_version(ctx, version) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
# define SSL_CTX_get_min_proto_version(ctx) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
# define SSL_CTX_get_max_proto_version(ctx) \
        SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)
# define SSL_set_min_proto_version(s, version) \
        SSL_ctrl(s, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
# define SSL_set_max_proto_version(s, version) \
        SSL_ctrl(s, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
# define SSL_get_min_proto_version(s) \
        SSL_ctrl(s, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
# define SSL_get_max_proto_version(s) \
        SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)

const char *SSL_group_to_name(SSL *s, int id);

/* Backwards compatibility, original 1.1.0 names */
# define SSL_CTRL_GET_SERVER_TMP_KEY \
         SSL_CTRL_GET_PEER_TMP_KEY
# define SSL_get_server_tmp_key(s, pk) \
         SSL_get_peer_tmp_key(s, pk)

int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey);
int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey);

/*
 * The following symbol names are old and obsolete. They are kept
 * for compatibility reasons only and should not be used anymore.
 */
# define SSL_CTRL_GET_CURVES           SSL_CTRL_GET_GROUPS
# define SSL_CTRL_SET_CURVES           SSL_CTRL_SET_GROUPS
# define SSL_CTRL_SET_CURVES_LIST      SSL_CTRL_SET_GROUPS_LIST
# define SSL_CTRL_GET_SHARED_CURVE     SSL_CTRL_GET_SHARED_GROUP

# define SSL_get1_curves               SSL_get1_groups
# define SSL_CTX_set1_curves           SSL_CTX_set1_groups
# define SSL_CTX_set1_curves_list      SSL_CTX_set1_groups_list
# define SSL_set1_curves               SSL_set1_groups
# define SSL_set1_curves_list          SSL_set1_groups_list
# define SSL_get_shared_curve          SSL_get_shared_group


# ifndef OPENSSL_NO_DEPRECATED_1_1_0
/* Provide some compatibility macros for removed functionality. */
#  define SSL_CTX_need_tmp_RSA(ctx)                0
#  define SSL_CTX_set_tmp_rsa(ctx,rsa)             1
#  define SSL_need_tmp_RSA(ssl)                    0
#  define SSL_set_tmp_rsa(ssl,rsa)                 1
#  define SSL_CTX_set_ecdh_auto(dummy, onoff)      ((onoff) != 0)
#  define SSL_set_ecdh_auto(dummy, onoff)          ((onoff) != 0)
/*
 * We "pretend" to call the callback to avoid warnings about unused static
 * functions.
 */
#  define SSL_CTX_set_tmp_rsa_callback(ctx, cb)    while(0) (cb)(NULL, 0, 0)
#  define SSL_set_tmp_rsa_callback(ssl, cb)        while(0) (cb)(NULL, 0, 0)
# endif
__owur const BIO_METHOD *BIO_f_ssl(void);
__owur BIO *BIO_new_ssl(SSL_CTX *ctx, int client);
__owur BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
__owur BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
__owur int BIO_ssl_copy_session_id(BIO *to, BIO *from);
void BIO_ssl_shutdown(BIO *ssl_bio);

__owur int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str);
__owur SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
__owur SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
                               const SSL_METHOD *meth);
int SSL_CTX_up_ref(SSL_CTX *ctx);
void SSL_CTX_free(SSL_CTX *);
__owur long SSL_CTX_set_timeout(SSL_CTX *ctx, long t);
__owur long SSL_CTX_get_timeout(const SSL_CTX *ctx);
__owur X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
void SSL_CTX_set1_cert_store(SSL_CTX *, X509_STORE *);
__owur int SSL_want(const SSL *s);
__owur int SSL_clear(SSL *s);

void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm);

__owur const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
__owur const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s);
__owur int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits);
__owur const char *SSL_CIPHER_get_version(const SSL_CIPHER *c);
__owur const char *SSL_CIPHER_get_name(const SSL_CIPHER *c);
__owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c);
__owur const char *OPENSSL_cipher_name(const char *rfc_name);
__owur uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c);
__owur uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c);
__owur int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c);
__owur int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c);
__owur const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c);
__owur int SSL_CIPHER_is_aead(const SSL_CIPHER *c);

__owur int SSL_get_fd(const SSL *s);
__owur int SSL_get_rfd(const SSL *s);
__owur int SSL_get_wfd(const SSL *s);
__owur const char *SSL_get_cipher_list(const SSL *s, int n);
__owur char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size);
__owur int SSL_get_read_ahead(const SSL *s);
__owur int SSL_pending(const SSL *s);
__owur int SSL_has_pending(const SSL *s);
# ifndef OPENSSL_NO_SOCK
__owur int SSL_set_fd(SSL *s, int fd);
__owur int SSL_set_rfd(SSL *s, int fd);
__owur int SSL_set_wfd(SSL *s, int fd);
# endif
void SSL_set0_rbio(SSL *s, BIO *rbio);
void SSL_set0_wbio(SSL *s, BIO *wbio);
void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio);
__owur BIO *SSL_get_rbio(const SSL *s);
__owur BIO *SSL_get_wbio(const SSL *s);
__owur int SSL_set_cipher_list(SSL *s, const char *str);
__owur int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
__owur int SSL_set_ciphersuites(SSL *s, const char *str);
void SSL_set_read_ahead(SSL *s, int yes);
__owur int SSL_get_verify_mode(const SSL *s);
__owur int SSL_get_verify_depth(const SSL *s);
__owur SSL_verify_cb SSL_get_verify_callback(const SSL *s);
void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback);
void SSL_set_verify_depth(SSL *s, int depth);
void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg);
# ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 __owur int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
OSSL_DEPRECATEDIN_3_0
__owur int SSL_use_RSAPrivateKey_ASN1(SSL *ssl,
                                      const unsigned char *d, long len);
# endif
__owur int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
__owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d,
                                   long len);
__owur int SSL_use_certificate(SSL *ssl, X509 *x);
__owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
__owur int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey,
                                STACK_OF(X509) *chain, int override);


/* serverinfo file format versions */
# define SSL_SERVERINFOV1   1
# define SSL_SERVERINFOV2   2

/* Set serverinfo data for the current active cert. */
__owur int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
                                  size_t serverinfo_length);
__owur int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
                                     const unsigned char *serverinfo,
                                     size_t serverinfo_length);
__owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file);

#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
#endif

__owur int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
__owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type);

#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file,
                                          int type);
#endif
__owur int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file,
                                       int type);
__owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,
                                        int type);
/* PEM type */
__owur int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
__owur int SSL_use_certificate_chain_file(SSL *ssl, const char *file);
__owur STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
__owur STACK_OF(X509_NAME)
*SSL_load_client_CA_file_ex(const char *file, OSSL_LIB_CTX *libctx,
                            const char *propq);
__owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                               const char *file);
int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                       const char *dir);
int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                       const char *uri);

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_load_error_strings() \
    OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
                     | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
# endif

__owur const char *SSL_state_string(const SSL *s);
__owur const char *SSL_rstate_string(const SSL *s);
__owur const char *SSL_state_string_long(const SSL *s);
__owur const char *SSL_rstate_string_long(const SSL *s);
__owur long SSL_SESSION_get_time(const SSL_SESSION *s);
__owur long SSL_SESSION_set_time(SSL_SESSION *s, long t);
__owur long SSL_SESSION_get_timeout(const SSL_SESSION *s);
__owur long SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
__owur int SSL_SESSION_get_protocol_version(const SSL_SESSION *s);
__owur int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version);

__owur const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s);
__owur int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname);
void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s,
                                    const unsigned char **alpn,
                                    size_t *len);
__owur int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s,
                                          const unsigned char *alpn,
                                          size_t len);
__owur const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s);
__owur int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher);
__owur int SSL_SESSION_has_ticket(const SSL_SESSION *s);
__owur unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s);
void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
                             size_t *len);
__owur uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s);
__owur int SSL_SESSION_set_max_early_data(SSL_SESSION *s,
                                          uint32_t max_early_data);
__owur int SSL_copy_session_id(SSL *to, const SSL *from);
__owur X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
__owur int SSL_SESSION_set1_id_context(SSL_SESSION *s,
                                       const unsigned char *sid_ctx,
                                       unsigned int sid_ctx_len);
__owur int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
                               unsigned int sid_len);
__owur int SSL_SESSION_is_resumable(const SSL_SESSION *s);

__owur SSL_SESSION *SSL_SESSION_new(void);
__owur SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src);
const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
                                        unsigned int *len);
const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s,
                                                 unsigned int *len);
__owur unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s);
# ifndef OPENSSL_NO_STDIO
int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses);
# endif
int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses);
int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x);
int SSL_SESSION_up_ref(SSL_SESSION *ses);
void SSL_SESSION_free(SSL_SESSION *ses);
__owur int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp);
__owur int SSL_set_session(SSL *to, SSL_SESSION *session);
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session);
int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session);
__owur int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb);
__owur int SSL_set_generate_session_id(SSL *s, GEN_SESSION_CB cb);
__owur int SSL_has_matching_session_id(const SSL *s,
                                       const unsigned char *id,
                                       unsigned int id_len);
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
                             long length);

# ifdef OPENSSL_X509_H
__owur X509 *SSL_get0_peer_certificate(const SSL *s);
__owur X509 *SSL_get1_peer_certificate(const SSL *s);
/* Deprecated in 3.0.0 */
#  ifndef OPENSSL_NO_DEPRECATED_3_0
#   define SSL_get_peer_certificate SSL_get1_peer_certificate
#  endif
# endif

__owur STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);

__owur int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
__owur int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
__owur SSL_verify_cb SSL_CTX_get_verify_callback(const SSL_CTX *ctx);
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback);
void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
                                      int (*cb) (X509_STORE_CTX *, void *),
                                      void *arg);
void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg),
                         void *arg);
# ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d,
                                          long len);
# endif
__owur int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
__owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx,
                                       const unsigned char *d, long len);
__owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
__owur int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len,
                                        const unsigned char *d);
__owur int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey,
                                    STACK_OF(X509) *chain, int override);

void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx);
void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx);
void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb);
void SSL_set_default_passwd_cb_userdata(SSL *s, void *u);
pem_password_cb *SSL_get_default_passwd_cb(SSL *s);
void *SSL_get_default_passwd_cb_userdata(SSL *s);

__owur int SSL_CTX_check_private_key(const SSL_CTX *ctx);
__owur int SSL_check_private_key(const SSL *ctx);

__owur int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
                                          const unsigned char *sid_ctx,
                                          unsigned int sid_ctx_len);

SSL *SSL_new(SSL_CTX *ctx);
int SSL_up_ref(SSL *s);
int SSL_is_dtls(const SSL *s);
__owur int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
                                      unsigned int sid_ctx_len);

__owur int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose);
__owur int SSL_set_purpose(SSL *ssl, int purpose);
__owur int SSL_CTX_set_trust(SSL_CTX *ctx, int trust);
__owur int SSL_set_trust(SSL *ssl, int trust);

__owur int SSL_set1_host(SSL *s, const char *hostname);
__owur int SSL_add1_host(SSL *s, const char *hostname);
__owur const char *SSL_get0_peername(SSL *s);
void SSL_set_hostflags(SSL *s, unsigned int flags);

__owur int SSL_CTX_dane_enable(SSL_CTX *ctx);
__owur int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md,
                                  uint8_t mtype, uint8_t ord);
__owur int SSL_dane_enable(SSL *s, const char *basedomain);
__owur int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
                             uint8_t mtype, const unsigned char *data, size_t dlen);
__owur int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki);
__owur int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
                              uint8_t *mtype, const unsigned char **data,
                              size_t *dlen);
/*
 * Bridge opacity barrier between libcrypt and libssl, also needed to support
 * offline testing in test/danetest.c
 */
SSL_DANE *SSL_get0_dane(SSL *ssl);
/*
 * DANE flags
 */
unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags);
unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags);
unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags);
unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags);

__owur int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
__owur int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);

__owur X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx);
__owur X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);

# ifndef OPENSSL_NO_SRP
#  ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name);
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password);
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength);
OSSL_DEPRECATEDIN_3_0
int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
                                        char *(*cb) (SSL *, void *));
OSSL_DEPRECATEDIN_3_0
int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
                                          int (*cb) (SSL *, void *));
OSSL_DEPRECATEDIN_3_0
int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
                                      int (*cb) (SSL *, int *, void *));
OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg);

OSSL_DEPRECATEDIN_3_0
int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
                             BIGNUM *sa, BIGNUM *v, char *info);
OSSL_DEPRECATEDIN_3_0
int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
                                const char *grp);

OSSL_DEPRECATEDIN_3_0 __owur BIGNUM *SSL_get_srp_g(SSL *s);
OSSL_DEPRECATEDIN_3_0 __owur BIGNUM *SSL_get_srp_N(SSL *s);

OSSL_DEPRECATEDIN_3_0 __owur char *SSL_get_srp_username(SSL *s);
OSSL_DEPRECATEDIN_3_0 __owur char *SSL_get_srp_userinfo(SSL *s);
#  endif
# endif

/*
 * ClientHello callback and helpers.
 */

# define SSL_CLIENT_HELLO_SUCCESS 1
# define SSL_CLIENT_HELLO_ERROR   0
# define SSL_CLIENT_HELLO_RETRY   (-1)

typedef int (*SSL_client_hello_cb_fn) (SSL *s, int *al, void *arg);
void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb,
                                 void *arg);
int SSL_client_hello_isv2(SSL *s);
unsigned int SSL_client_hello_get0_legacy_version(SSL *s);
size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_compression_methods(SSL *s,
                                                 const unsigned char **out);
int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen);
int SSL_client_hello_get0_ext(SSL *s, unsigned int type,
                              const unsigned char **out, size_t *outlen);

void SSL_certs_clear(SSL *s);
void SSL_free(SSL *ssl);
# ifdef OSSL_ASYNC_FD
/*
 * Windows application developer has to include windows.h to use these.
 */
__owur int SSL_waiting_for_async(SSL *s);
__owur int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds);
__owur int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd,
                                     size_t *numaddfds, OSSL_ASYNC_FD *delfd,
                                     size_t *numdelfds);
__owur int SSL_CTX_set_async_callback(SSL_CTX *ctx, SSL_async_callback_fn callback);
__owur int SSL_CTX_set_async_callback_arg(SSL_CTX *ctx, void *arg);
__owur int SSL_set_async_callback(SSL *s, SSL_async_callback_fn callback);
__owur int SSL_set_async_callback_arg(SSL *s, void *arg);
__owur int SSL_get_async_status(SSL *s, int *status);

# endif
__owur int SSL_accept(SSL *ssl);
__owur int SSL_stateless(SSL *s);
__owur int SSL_connect(SSL *ssl);
__owur int SSL_read(SSL *ssl, void *buf, int num);
__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);

# define SSL_READ_EARLY_DATA_ERROR   0
# define SSL_READ_EARLY_DATA_SUCCESS 1
# define SSL_READ_EARLY_DATA_FINISH  2

__owur int SSL_read_early_data(SSL *s, void *buf, size_t num,
                               size_t *readbytes);
__owur int SSL_peek(SSL *ssl, void *buf, int num);
__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
__owur ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size,
                                 int flags);
__owur int SSL_write(SSL *ssl, const void *buf, int num);
__owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
__owur int SSL_write_early_data(SSL *s, const void *buf, size_t num,
                                size_t *written);
long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg);
long SSL_callback_ctrl(SSL *, int, void (*)(void));
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));

# define SSL_EARLY_DATA_NOT_SENT    0
# define SSL_EARLY_DATA_REJECTED    1
# define SSL_EARLY_DATA_ACCEPTED    2

__owur int SSL_get_early_data_status(const SSL *s);

__owur int SSL_get_error(const SSL *s, int ret_code);
__owur const char *SSL_get_version(const SSL *s);

/* This sets the 'default' SSL version that SSL_new() will create */
# ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
__owur int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
# endif

# ifndef OPENSSL_NO_SSL3_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_method(void); /* SSLv3 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_client_method(void);
#  endif
# endif

#define SSLv23_method           TLS_method
#define SSLv23_server_method    TLS_server_method
#define SSLv23_client_method    TLS_client_method

/* Negotiate highest available SSL/TLS version */
__owur const SSL_METHOD *TLS_method(void);
__owur const SSL_METHOD *TLS_server_method(void);
__owur const SSL_METHOD *TLS_client_method(void);

# ifndef OPENSSL_NO_TLS1_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_TLS1_1_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_method(void); /* TLSv1.1 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_TLS1_2_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_method(void); /* TLSv1.2 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_DTLS1_METHOD
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_client_method(void);
#  endif
# endif

# ifndef OPENSSL_NO_DTLS1_2_METHOD
/* DTLSv1.2 */
#  ifndef OPENSSL_NO_DEPRECATED_1_1_0
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_server_method(void);
OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_client_method(void);
#  endif
# endif

__owur const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */
__owur const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */
__owur const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */

__owur size_t DTLS_get_data_mtu(const SSL *s);

__owur STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
__owur STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
__owur STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s);
__owur STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s);

__owur int SSL_do_handshake(SSL *s);
int SSL_key_update(SSL *s, int updatetype);
int SSL_get_key_update_type(const SSL *s);
int SSL_renegotiate(SSL *s);
int SSL_renegotiate_abbreviated(SSL *s);
__owur int SSL_renegotiate_pending(const SSL *s);
int SSL_new_session_ticket(SSL *s);
int SSL_shutdown(SSL *s);
__owur int SSL_verify_client_post_handshake(SSL *s);
void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val);
void SSL_set_post_handshake_auth(SSL *s, int val);

__owur const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx);
__owur const SSL_METHOD *SSL_get_ssl_method(const SSL *s);
__owur int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
__owur const char *SSL_alert_type_string_long(int value);
__owur const char *SSL_alert_type_string(int value);
__owur const char *SSL_alert_desc_string_long(int value);
__owur const char *SSL_alert_desc_string(int value);

void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
__owur const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s);
__owur const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx);
__owur int SSL_add1_to_CA_list(SSL *ssl, const X509 *x);
__owur int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x);
__owur const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s);

void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
__owur STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
__owur STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
__owur int SSL_add_client_CA(SSL *ssl, X509 *x);
__owur int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x);

void SSL_set_connect_state(SSL *s);
void SSL_set_accept_state(SSL *s);

__owur long SSL_get_default_timeout(const SSL *s);

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_library_init() OPENSSL_init_ssl(0, NULL)
# endif

__owur char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size);
__owur STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk);

__owur SSL *SSL_dup(SSL *ssl);

__owur X509 *SSL_get_certificate(const SSL *ssl);
/*
 * EVP_PKEY
 */
struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl);

__owur X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx);
__owur EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx);

void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode);
__owur int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
void SSL_set_quiet_shutdown(SSL *ssl, int mode);
__owur int SSL_get_quiet_shutdown(const SSL *ssl);
void SSL_set_shutdown(SSL *ssl, int mode);
__owur int SSL_get_shutdown(const SSL *ssl);
__owur int SSL_version(const SSL *ssl);
__owur int SSL_client_version(const SSL *s);
__owur int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_store(SSL_CTX *ctx);
__owur int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile);
__owur int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath);
__owur int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore);
__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx,
                                                        const char *CAfile,
                                                        const char *CApath);
# define SSL_get0_session SSL_get_session/* just peek at pointer */
__owur SSL_SESSION *SSL_get_session(const SSL *ssl);
__owur SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
__owur SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
void SSL_set_info_callback(SSL *ssl,
                           void (*cb) (const SSL *ssl, int type, int val));
void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type,
                                               int val);
__owur OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl);

void SSL_set_verify_result(SSL *ssl, long v);
__owur long SSL_get_verify_result(const SSL *ssl);
__owur STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s);

__owur size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
                                    size_t outlen);
__owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
                                    size_t outlen);
__owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *sess,
                                         unsigned char *out, size_t outlen);
__owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess,
                                       const unsigned char *in, size_t len);
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *sess);

#define SSL_get_ex_new_index(l, p, newf, dupf, freef) \
    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef)
__owur int SSL_set_ex_data(SSL *ssl, int idx, void *data);
void *SSL_get_ex_data(const SSL *ssl, int idx);
#define SSL_SESSION_get_ex_new_index(l, p, newf, dupf, freef) \
    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, l, p, newf, dupf, freef)
__owur int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data);
void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx);
#define SSL_CTX_get_ex_new_index(l, p, newf, dupf, freef) \
    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, l, p, newf, dupf, freef)
__owur int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data);
void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx);

__owur int SSL_get_ex_data_X509_STORE_CTX_idx(void);

# define SSL_CTX_sess_set_cache_size(ctx,t) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
# define SSL_CTX_sess_get_cache_size(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
# define SSL_CTX_set_session_cache_mode(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
# define SSL_CTX_get_session_cache_mode(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)

# define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
# define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
# define SSL_CTX_get_read_ahead(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
# define SSL_CTX_set_read_ahead(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
# define SSL_CTX_get_max_cert_list(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
# define SSL_CTX_set_max_cert_list(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
# define SSL_get_max_cert_list(ssl) \
        SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
# define SSL_set_max_cert_list(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)

# define SSL_CTX_set_max_send_fragment(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_set_max_send_fragment(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_split_send_fragment(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_set_split_send_fragment(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_max_pipelines(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
# define SSL_set_max_pipelines(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
# define SSL_set_retry_verify(ssl) \
        (SSL_ctrl(ssl,SSL_CTRL_SET_RETRY_VERIFY,0,NULL) > 0)

void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
void SSL_set_default_read_buffer_len(SSL *s, size_t len);

# ifndef OPENSSL_NO_DH
#  ifndef OPENSSL_NO_DEPRECATED_3_0
/* NB: the |keylength| is only applicable when is_export is true */
OSSL_DEPRECATEDIN_3_0
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
                                 DH *(*dh) (SSL *ssl, int is_export,
                                            int keylength));
OSSL_DEPRECATEDIN_3_0
void SSL_set_tmp_dh_callback(SSL *ssl,
                             DH *(*dh) (SSL *ssl, int is_export,
                                        int keylength));
#  endif
# endif

__owur const COMP_METHOD *SSL_get_current_compression(const SSL *s);
__owur const COMP_METHOD *SSL_get_current_expansion(const SSL *s);
__owur const char *SSL_COMP_get_name(const COMP_METHOD *comp);
__owur const char *SSL_COMP_get0_name(const SSL_COMP *comp);
__owur int SSL_COMP_get_id(const SSL_COMP *comp);
STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
__owur STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
                                                             *meths);
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_COMP_free_compression_methods() while(0) continue
# endif
__owur int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm);

const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c);
int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c);
int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
                             int isv2format, STACK_OF(SSL_CIPHER) **sk,
                             STACK_OF(SSL_CIPHER) **scsvs);

/* TLS extensions functions */
__owur int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);

__owur int SSL_set_session_ticket_ext_cb(SSL *s,
                                         tls_session_ticket_ext_cb_fn cb,
                                         void *arg);

/* Pre-shared secret session resumption functions */
__owur int SSL_set_session_secret_cb(SSL *s,
                                     tls_session_secret_cb_fn session_secret_cb,
                                     void *arg);

void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
                                                int (*cb) (SSL *ssl,
                                                           int
                                                           is_forward_secure));

void SSL_set_not_resumable_session_callback(SSL *ssl,
                                            int (*cb) (SSL *ssl,
                                                       int is_forward_secure));

void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
                                         size_t (*cb) (SSL *ssl, int type,
                                                       size_t len, void *arg));
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx);
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);

int SSL_set_record_padding_callback(SSL *ssl,
                                    size_t (*cb) (SSL *ssl, int type,
                                                  size_t len, void *arg));
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg);
void *SSL_get_record_padding_callback_arg(const SSL *ssl);
int SSL_set_block_padding(SSL *ssl, size_t block_size);

int SSL_set_num_tickets(SSL *s, size_t num_tickets);
size_t SSL_get_num_tickets(const SSL *s);
int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);

# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#  define SSL_cache_hit(s) SSL_session_reused(s)
# endif

__owur int SSL_session_reused(const SSL *s);
__owur int SSL_is_server(const SSL *s);

__owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void);
int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx);
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx);
unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags);
__owur unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx,
                                             unsigned int flags);
__owur int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre);

void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl);
void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx);

__owur int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
__owur int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv);
__owur int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);

void SSL_add_ssl_module(void);
int SSL_config(SSL *s, const char *name);
int SSL_CTX_config(SSL_CTX *ctx, const char *name);

# ifndef OPENSSL_NO_SSL_TRACE
void SSL_trace(int write_p, int version, int content_type,
               const void *buf, size_t len, SSL *ssl, void *arg);
# endif

# ifndef OPENSSL_NO_SOCK
int DTLSv1_listen(SSL *s, BIO_ADDR *client);
# endif

# ifndef OPENSSL_NO_CT

/*
 * A callback for verifying that the received SCTs are sufficient.
 * Expected to return 1 if they are sufficient, otherwise 0.
 * May return a negative integer if an error occurs.
 * A connection should be aborted if the SCTs are deemed insufficient.
 */
typedef int (*ssl_ct_validation_cb)(const CT_POLICY_EVAL_CTX *ctx,
                                    const STACK_OF(SCT) *scts, void *arg);

/*
 * Sets a |callback| that is invoked upon receipt of ServerHelloDone to validate
 * the received SCTs.
 * If the callback returns a non-positive result, the connection is terminated.
 * Call this function before beginning a handshake.
 * If a NULL |callback| is provided, SCT validation is disabled.
 * |arg| is arbitrary userdata that will be passed to the callback whenever it
 * is invoked. Ownership of |arg| remains with the caller.
 *
 * NOTE: A side-effect of setting a CT callback is that an OCSP stapled response
 *       will be requested.
 */
int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback,
                                   void *arg);
int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
                                       ssl_ct_validation_cb callback,
                                       void *arg);
#define SSL_disable_ct(s) \
        ((void) SSL_set_validation_callback((s), NULL, NULL))
#define SSL_CTX_disable_ct(ctx) \
        ((void) SSL_CTX_set_validation_callback((ctx), NULL, NULL))

/*
 * The validation type enumerates the available behaviours of the built-in SSL
 * CT validation callback selected via SSL_enable_ct() and SSL_CTX_enable_ct().
 * The underlying callback is a static function in libssl.
 */
enum {
    SSL_CT_VALIDATION_PERMISSIVE = 0,
    SSL_CT_VALIDATION_STRICT
};

/*
 * Enable CT by setting up a callback that implements one of the built-in
 * validation variants.  The SSL_CT_VALIDATION_PERMISSIVE variant always
 * continues the handshake, the application can make appropriate decisions at
 * handshake completion.  The SSL_CT_VALIDATION_STRICT variant requires at
 * least one valid SCT, or else handshake termination will be requested.  The
 * handshake may continue anyway if SSL_VERIFY_NONE is in effect.
 */
int SSL_enable_ct(SSL *s, int validation_mode);
int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode);

/*
 * Report whether a non-NULL callback is enabled.
 */
int SSL_ct_is_enabled(const SSL *s);
int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx);

/* Gets the SCTs received from a connection */
const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s);

/*
 * Loads the CT log list from the default location.
 * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
 * the log information loaded from this file will be appended to the
 * CTLOG_STORE.
 * Returns 1 on success, 0 otherwise.
 */
int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx);

/*
 * Loads the CT log list from the specified file path.
 * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
 * the log information loaded from this file will be appended to the
 * CTLOG_STORE.
 * Returns 1 on success, 0 otherwise.
 */
int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path);

/*
 * Sets the CT log list used by all SSL connections created from this SSL_CTX.
 * Ownership of the CTLOG_STORE is transferred to the SSL_CTX.
 */
void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE *logs);

/*
 * Gets the CT log list used by all SSL connections created from this SSL_CTX.
 * This will be NULL unless one of the following functions has been called:
 * - SSL_CTX_set_default_ctlog_list_file
 * - SSL_CTX_set_ctlog_list_file
 * - SSL_CTX_set_ctlog_store
 */
const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx);

# endif /* OPENSSL_NO_CT */

/* What the "other" parameter contains in security callback */
/* Mask for type */
# define SSL_SECOP_OTHER_TYPE    0xffff0000
# define SSL_SECOP_OTHER_NONE    0
# define SSL_SECOP_OTHER_CIPHER  (1 << 16)
# define SSL_SECOP_OTHER_CURVE   (2 << 16)
# define SSL_SECOP_OTHER_DH      (3 << 16)
# define SSL_SECOP_OTHER_PKEY    (4 << 16)
# define SSL_SECOP_OTHER_SIGALG  (5 << 16)
# define SSL_SECOP_OTHER_CERT    (6 << 16)

/* Indicated operation refers to peer key or certificate */
# define SSL_SECOP_PEER          0x1000

/* Values for "op" parameter in security callback */

/* Called to filter ciphers */
/* Ciphers client supports */
# define SSL_SECOP_CIPHER_SUPPORTED      (1 | SSL_SECOP_OTHER_CIPHER)
/* Cipher shared by client/server */
# define SSL_SECOP_CIPHER_SHARED         (2 | SSL_SECOP_OTHER_CIPHER)
/* Sanity check of cipher server selects */
# define SSL_SECOP_CIPHER_CHECK          (3 | SSL_SECOP_OTHER_CIPHER)
/* Curves supported by client */
# define SSL_SECOP_CURVE_SUPPORTED       (4 | SSL_SECOP_OTHER_CURVE)
/* Curves shared by client/server */
# define SSL_SECOP_CURVE_SHARED          (5 | SSL_SECOP_OTHER_CURVE)
/* Sanity check of curve server selects */
# define SSL_SECOP_CURVE_CHECK           (6 | SSL_SECOP_OTHER_CURVE)
/* Temporary DH key */
# define SSL_SECOP_TMP_DH                (7 | SSL_SECOP_OTHER_PKEY)
/* SSL/TLS version */
# define SSL_SECOP_VERSION               (9 | SSL_SECOP_OTHER_NONE)
/* Session tickets */
# define SSL_SECOP_TICKET                (10 | SSL_SECOP_OTHER_NONE)
/* Supported signature algorithms sent to peer */
# define SSL_SECOP_SIGALG_SUPPORTED      (11 | SSL_SECOP_OTHER_SIGALG)
/* Shared signature algorithm */
# define SSL_SECOP_SIGALG_SHARED         (12 | SSL_SECOP_OTHER_SIGALG)
/* Sanity check signature algorithm allowed */
# define SSL_SECOP_SIGALG_CHECK          (13 | SSL_SECOP_OTHER_SIGALG)
/* Used to get mask of supported public key signature algorithms */
# define SSL_SECOP_SIGALG_MASK           (14 | SSL_SECOP_OTHER_SIGALG)
/* Use to see if compression is allowed */
# define SSL_SECOP_COMPRESSION           (15 | SSL_SECOP_OTHER_NONE)
/* EE key in certificate */
# define SSL_SECOP_EE_KEY                (16 | SSL_SECOP_OTHER_CERT)
/* CA key in certificate */
# define SSL_SECOP_CA_KEY                (17 | SSL_SECOP_OTHER_CERT)
/* CA digest algorithm in certificate */
# define SSL_SECOP_CA_MD                 (18 | SSL_SECOP_OTHER_CERT)
/* Peer EE key in certificate */
# define SSL_SECOP_PEER_EE_KEY           (SSL_SECOP_EE_KEY | SSL_SECOP_PEER)
/* Peer CA key in certificate */
# define SSL_SECOP_PEER_CA_KEY           (SSL_SECOP_CA_KEY | SSL_SECOP_PEER)
/* Peer CA digest algorithm in certificate */
# define SSL_SECOP_PEER_CA_MD            (SSL_SECOP_CA_MD | SSL_SECOP_PEER)

void SSL_set_security_level(SSL *s, int level);
__owur int SSL_get_security_level(const SSL *s);
void SSL_set_security_callback(SSL *s,
                               int (*cb) (const SSL *s, const SSL_CTX *ctx,
                                          int op, int bits, int nid,
                                          void *other, void *ex));
int (*SSL_get_security_callback(const SSL *s)) (const SSL *s,
                                                const SSL_CTX *ctx, int op,
                                                int bits, int nid, void *other,
                                                void *ex);
void SSL_set0_security_ex_data(SSL *s, void *ex);
__owur void *SSL_get0_security_ex_data(const SSL *s);

void SSL_CTX_set_security_level(SSL_CTX *ctx, int level);
__owur int SSL_CTX_get_security_level(const SSL_CTX *ctx);
void SSL_CTX_set_security_callback(SSL_CTX *ctx,
                                   int (*cb) (const SSL *s, const SSL_CTX *ctx,
                                              int op, int bits, int nid,
                                              void *other, void *ex));
int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s,
                                                          const SSL_CTX *ctx,
                                                          int op, int bits,
                                                          int nid,
                                                          void *other,
                                                          void *ex);
void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex);
__owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx);

/* OPENSSL_INIT flag 0x010000 reserved for internal use */
# define OPENSSL_INIT_NO_LOAD_SSL_STRINGS    0x00100000L
# define OPENSSL_INIT_LOAD_SSL_STRINGS       0x00200000L

# define OPENSSL_INIT_SSL_DEFAULT \
        (OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS)

int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);

# ifndef OPENSSL_NO_UNIT_TEST
__owur const struct openssl_ssl_test_functions *SSL_test_functions(void);
# endif

__owur int SSL_free_buffers(SSL *ssl);
__owur int SSL_alloc_buffers(SSL *ssl);

/* Status codes passed to the decrypt session ticket callback. Some of these
 * are for internal use only and are never passed to the callback. */
typedef int SSL_TICKET_STATUS;

/* Support for ticket appdata */
/* fatal error, malloc failure */
# define SSL_TICKET_FATAL_ERR_MALLOC 0
/* fatal error, either from parsing or decrypting the ticket */
# define SSL_TICKET_FATAL_ERR_OTHER  1
/* No ticket present */
# define SSL_TICKET_NONE             2
/* Empty ticket present */
# define SSL_TICKET_EMPTY            3
/* the ticket couldn't be decrypted */
# define SSL_TICKET_NO_DECRYPT       4
/* a ticket was successfully decrypted */
# define SSL_TICKET_SUCCESS          5
/* same as above but the ticket needs to be renewed */
# define SSL_TICKET_SUCCESS_RENEW    6

/* Return codes for the decrypt session ticket callback */
typedef int SSL_TICKET_RETURN;

/* An error occurred */
#define SSL_TICKET_RETURN_ABORT             0
/* Do not use the ticket, do not send a renewed ticket to the client */
#define SSL_TICKET_RETURN_IGNORE            1
/* Do not use the ticket, send a renewed ticket to the client */
#define SSL_TICKET_RETURN_IGNORE_RENEW      2
/* Use the ticket, do not send a renewed ticket to the client */
#define SSL_TICKET_RETURN_USE               3
/* Use the ticket, send a renewed ticket to the client */
#define SSL_TICKET_RETURN_USE_RENEW         4

typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg);
typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss,
                                                               const unsigned char *keyname,
                                                               size_t keyname_length,
                                                               SSL_TICKET_STATUS status,
                                                               void *arg);
int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx,
                                  SSL_CTX_generate_session_ticket_fn gen_cb,
                                  SSL_CTX_decrypt_session_ticket_fn dec_cb,
                                  void *arg);
int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len);
int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len);

typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);

void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);


typedef int (*SSL_allow_early_data_cb_fn)(SSL *s, void *arg);
void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx,
                                     SSL_allow_early_data_cb_fn cb,
                                     void *arg);
void SSL_set_allow_early_data_cb(SSL *s,
                                 SSL_allow_early_data_cb_fn cb,
                                 void *arg);

/* store the default cipher strings inside the library */
const char *OSSL_default_cipher_list(void);
const char *OSSL_default_ciphersuites(void);

#  ifndef OPENSSL_NO_QUIC
/*
 * QUIC integration - The QUIC interface matches BoringSSL
 *
 * ssl_encryption_level_t represents a specific QUIC encryption level used to
 * transmit handshake messages. BoringSSL has this as an 'enum'.
 */
#include <openssl/quic.h>

/* Used by Chromium/QUIC - moved from evp.h to avoid breaking FIPS checksums */
# define X25519_PRIVATE_KEY_LEN          32
# define X25519_PUBLIC_VALUE_LEN         32

/* moved from types.h to avoid breaking FIPS checksums */
typedef struct ssl_quic_method_st SSL_QUIC_METHOD;

typedef enum ssl_encryption_level_t {
    ssl_encryption_initial = 0,
    ssl_encryption_early_data,
    ssl_encryption_handshake,
    ssl_encryption_application
} OSSL_ENCRYPTION_LEVEL;

struct ssl_quic_method_st {
    int (*set_encryption_secrets)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
                                  const uint8_t *read_secret,
                                  const uint8_t *write_secret, size_t secret_len);
    int (*add_handshake_data)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
                              const uint8_t *data, size_t len);
    int (*flush_flight)(SSL *ssl);
    int (*send_alert)(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert);
};

__owur int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method);
__owur int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method);
__owur int SSL_set_quic_transport_params(SSL *ssl,
                                         const uint8_t *params,
                                         size_t params_len);
void SSL_get_peer_quic_transport_params(const SSL *ssl,
                                        const uint8_t **out_params,
                                        size_t *out_params_len);
__owur size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, OSSL_ENCRYPTION_LEVEL level);
__owur OSSL_ENCRYPTION_LEVEL SSL_quic_read_level(const SSL *ssl);
__owur OSSL_ENCRYPTION_LEVEL SSL_quic_write_level(const SSL *ssl);
__owur int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
                                 const uint8_t *data, size_t len);
__owur int SSL_process_quic_post_handshake(SSL *ssl);

__owur int SSL_is_quic(SSL *ssl);

/* BoringSSL API */
void SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy);

/*
 * Set an explicit value that you want to use
 * If 0 (default) the server will use the highest extenstion the client sent
 * If 0 (default) the client will send both extensions
 */
void SSL_set_quic_transport_version(SSL *ssl, int version);
__owur int SSL_get_quic_transport_version(const SSL *ssl);
/* Returns the negotiated version, or -1 on error */
__owur int SSL_get_peer_quic_transport_version(const SSL *ssl);

int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c);

void SSL_set_quic_early_data_enabled(SSL *ssl, int enabled);

#  endif

# ifdef  __cplusplus
}
# endif
#endif
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     