use single backtick (#17133)

This commit is contained in:
flywind
2021-02-21 02:27:39 -06:00
committed by GitHub
parent 69a78c9183
commit 70ec17eede
10 changed files with 103 additions and 103 deletions

View File

@@ -9,7 +9,7 @@
## This module contains code for reading from `stdin`:idx:. On UNIX the
## linenoise library is wrapped and set up to provide default key bindings
## (e.g. you can navigate with the arrow keys). On Windows ``system.readLine``
## (e.g. you can navigate with the arrow keys). On Windows `system.readLine`
## is used. This suffices because Windows' console already provides the
## wanted functionality.
@@ -33,11 +33,11 @@ when defined(windows):
proc readLineFromStdin*(prompt: string, line: var string): bool {.
tags: [ReadIOEffect, WriteIOEffect].} =
## Reads a `line` from stdin. `line` must not be
## ``nil``! May throw an IO exception.
## A line of text may be delimited by ``CR``, ``LF`` or
## ``CRLF``. The newline character(s) are not part of the returned string.
## Returns ``false`` if the end of the file has been reached, ``true``
## otherwise. If ``false`` is returned `line` contains no new data.
## `nil`! May throw an IO exception.
## A line of text may be delimited by `CR`, `LF` or
## `CRLF`. The newline character(s) are not part of the returned string.
## Returns `false` if the end of the file has been reached, `true`
## otherwise. If `false` is returned `line` contains no new data.
stdout.write(prompt)
result = readLine(stdin, line)

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
## OS-Path normalization. Used by ``os.nim`` but also
## OS-Path normalization. Used by `os.nim` but also
## generally useful for dealing with paths.
##
## Unstable API.

View File

@@ -11,7 +11,7 @@
## Ropes can represent very long strings efficiently; especially concatenation
## is done in O(1) instead of O(n). They are essentially concatenation
## trees that are only flattened when converting to a native Nim
## string. The empty string is represented by ``nil``. Ropes are immutable and
## string. The empty string is represented by `nil`. Ropes are immutable and
## subtrees can be shared without copying.
## Leaves can be cached for better memory efficiency at the cost of
## runtime efficiency.
@@ -240,7 +240,7 @@ proc add*(a: var Rope, b: string) {.rtl, extern: "nro$1Str".} =
proc `[]`*(r: Rope, i: int): char {.rtl, extern: "nroCharAt".} =
## Returns the character at position `i` in the rope `r`. This is quite
## expensive! Worst-case: O(n). If ``i >= r.len``, ``\0`` is returned.
## expensive! Worst-case: O(n). If `i >= r.len`, `\0` is returned.
runnableExamples:
let r1 = rope("Hello, Nim!")
@@ -309,8 +309,8 @@ proc `$`*(r: Rope): string {.rtl, extern: "nroToString".} =
proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
rtl, extern: "nroFormat".} =
## `%` substitution operator for ropes. Does not support the ``$identifier``
## nor ``${identifier}`` notations.
## `%` substitution operator for ropes. Does not support the `$identifier`
## nor `${identifier}` notations.
runnableExamples:
let r1 = "$1 $2 $3" % [rope("Nim"), rope("is"), rope("a great language")]
doAssert $r1 == "Nim is a great language"
@@ -359,7 +359,7 @@ proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
proc addf*(c: var Rope, frmt: string, args: openArray[Rope]) {.
rtl, extern: "nro$1".} =
## Shortcut for ``add(c, frmt % args)``.
## Shortcut for `add(c, frmt % args)`.
runnableExamples:
var r = rope("Dash: ")
r.addf "$1 $2 $3", [rope("Nim"), rope("is"), rope("a great language")]

View File

@@ -9,11 +9,11 @@
## This module allows high-level and efficient I/O multiplexing.
##
## Supported OS primitives: ``epoll``, ``kqueue``, ``poll`` and
## Windows ``select``.
## Supported OS primitives: `epoll`, `kqueue`, `poll` and
## Windows `select`.
##
## To use threadsafe version of this module, it needs to be compiled
## with both ``-d:threadsafe`` and ``--threads:on`` options.
## with both `-d:threadsafe` and `--threads:on` options.
##
## Supported features: files, sockets, pipes, timers, processes, signals
## and user events.
@@ -25,7 +25,7 @@
## Solaris (files, sockets, handles and user events).
## Android (files, sockets, handles and user events).
##
## TODO: ``/dev/poll``, ``event ports`` and filesystem events.
## TODO: `/dev/poll`, `event ports` and filesystem events.
import os, nativesockets
@@ -36,7 +36,7 @@ const ioselSupportedPlatform* = defined(macosx) or defined(freebsd) or
defined(dragonfly) or
(defined(linux) and not defined(android) and not defined(emscripten))
## This constant is used to determine whether the destination platform is
## fully supported by ``ioselectors`` module.
## fully supported by `ioselectors` module.
const bsdPlatform = defined(macosx) or defined(freebsd) or
defined(netbsd) or defined(openbsd) or
@@ -86,62 +86,62 @@ when defined(nimdoc):
proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle,
events: set[Event], data: T) =
## Registers file/socket descriptor ``fd`` to selector ``s``
## with events set in ``events``. The ``data`` is application-defined
## Registers file/socket descriptor `fd` to selector `s`
## with events set in `events`. The `data` is application-defined
## data, which will be passed when an event is triggered.
proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle,
events: set[Event]) =
## Update file/socket descriptor ``fd``, registered in selector
## ``s`` with new events set ``event``.
## Update file/socket descriptor `fd`, registered in selector
## `s` with new events set `event`.
proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool,
data: T): int {.discardable.} =
## Registers timer notification with ``timeout`` (in milliseconds)
## to selector ``s``.
## Registers timer notification with `timeout` (in milliseconds)
## to selector `s`.
##
## If ``oneshot`` is ``true``, timer will be notified only once.
## If `oneshot` is `true`, timer will be notified only once.
##
## Set ``oneshot`` to ``false`` if you want periodic notifications.
## Set `oneshot` to `false` if you want periodic notifications.
##
## The ``data`` is application-defined data, which will be passed, when
## The `data` is application-defined data, which will be passed, when
## the timer is triggered.
##
## Returns the file descriptor for the registered timer.
proc registerSignal*[T](s: Selector[T], signal: int,
data: T): int {.discardable.} =
## Registers Unix signal notification with ``signal`` to selector
## ``s``.
## Registers Unix signal notification with `signal` to selector
## `s`.
##
## The ``data`` is application-defined data, which will be
## The `data` is application-defined data, which will be
## passed when signal raises.
##
## Returns the file descriptor for the registered signal.
##
## **Note:** This function is not supported on ``Windows``.
## **Note:** This function is not supported on `Windows`.
proc registerProcess*[T](s: Selector[T], pid: int,
data: T): int {.discardable.} =
## Registers a process id (pid) notification (when process has
## exited) in selector ``s``.
## exited) in selector `s`.
##
## The ``data`` is application-defined data, which will be passed when
## process with ``pid`` has exited.
## The `data` is application-defined data, which will be passed when
## process with `pid` has exited.
##
## Returns the file descriptor for the registered signal.
proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) =
## Registers selector event ``ev`` in selector ``s``.
## Registers selector event `ev` in selector `s`.
##
## The ``data`` is application-defined data, which will be passed when
## ``ev`` happens.
## The `data` is application-defined data, which will be passed when
## `ev` happens.
proc registerVnode*[T](s: Selector[T], fd: cint, events: set[Event],
data: T) =
## Registers selector BSD/MacOSX specific vnode events for file
## descriptor ``fd`` and events ``events``.
## ``data`` application-defined data, which to be passed, when
## descriptor `fd` and events `events`.
## `data` application-defined data, which to be passed, when
## vnode event happens.
##
## **Note:** This function is supported only by BSD and MacOSX.
@@ -150,77 +150,77 @@ when defined(nimdoc):
## Creates a new user-defined event.
proc trigger*(ev: SelectEvent) =
## Trigger event ``ev``.
## Trigger event `ev`.
proc close*(ev: SelectEvent) =
## Closes user-defined event ``ev``.
## Closes user-defined event `ev`.
proc unregister*[T](s: Selector[T], ev: SelectEvent) =
## Unregisters user-defined event ``ev`` from selector ``s``.
## Unregisters user-defined event `ev` from selector `s`.
proc unregister*[T](s: Selector[T], fd: int|SocketHandle|cint) =
## Unregisters file/socket descriptor ``fd`` from selector ``s``.
## Unregisters file/socket descriptor `fd` from selector `s`.
proc selectInto*[T](s: Selector[T], timeout: int,
results: var openArray[ReadyKey]): int =
## Waits for events registered in selector ``s``.
## Waits for events registered in selector `s`.
##
## The ``timeout`` argument specifies the maximum number of milliseconds
## The `timeout` argument specifies the maximum number of milliseconds
## the function will be blocked for if no events are ready. Specifying a
## timeout of ``-1`` causes the function to block indefinitely.
## All available events will be stored in ``results`` array.
## timeout of `-1` causes the function to block indefinitely.
## All available events will be stored in `results` array.
##
## Returns number of triggered events.
proc select*[T](s: Selector[T], timeout: int): seq[ReadyKey] =
## Waits for events registered in selector ``s``.
## Waits for events registered in selector `s`.
##
## The ``timeout`` argument specifies the maximum number of milliseconds
## The `timeout` argument specifies the maximum number of milliseconds
## the function will be blocked for if no events are ready. Specifying a
## timeout of ``-1`` causes the function to block indefinitely.
## timeout of `-1` causes the function to block indefinitely.
##
## Returns a list of triggered events.
proc getData*[T](s: Selector[T], fd: SocketHandle|int): var T =
## Retrieves application-defined ``data`` associated with descriptor ``fd``.
## If specified descriptor ``fd`` is not registered, empty/default value
## Retrieves application-defined `data` associated with descriptor `fd`.
## If specified descriptor `fd` is not registered, empty/default value
## will be returned.
proc setData*[T](s: Selector[T], fd: SocketHandle|int, data: var T): bool =
## Associate application-defined ``data`` with descriptor ``fd``.
## Associate application-defined `data` with descriptor `fd`.
##
## Returns ``true``, if data was successfully updated, ``false`` otherwise.
## Returns `true`, if data was successfully updated, `false` otherwise.
template isEmpty*[T](s: Selector[T]): bool = # TODO: Why is this a template?
## Returns ``true``, if there are no registered events or descriptors
## Returns `true`, if there are no registered events or descriptors
## in selector.
template withData*[T](s: Selector[T], fd: SocketHandle|int, value,
body: untyped) =
## Retrieves the application-data assigned with descriptor ``fd``
## to ``value``. This ``value`` can be modified in the scope of
## the ``withData`` call.
## Retrieves the application-data assigned with descriptor `fd`
## to `value`. This `value` can be modified in the scope of
## the `withData` call.
##
## .. code-block:: nim
##
## s.withData(fd, value) do:
## # block is executed only if ``fd`` registered in selector ``s``
## # block is executed only if `fd` registered in selector `s`
## value.uid = 1000
##
template withData*[T](s: Selector[T], fd: SocketHandle|int, value,
body1, body2: untyped) =
## Retrieves the application-data assigned with descriptor ``fd``
## to ``value``. This ``value`` can be modified in the scope of
## the ``withData`` call.
## Retrieves the application-data assigned with descriptor `fd`
## to `value`. This `value` can be modified in the scope of
## the `withData` call.
##
## .. code-block:: nim
##
## s.withData(fd, value) do:
## # block is executed only if ``fd`` registered in selector ``s``.
## # block is executed only if `fd` registered in selector `s`.
## value.uid = 1000
## do:
## # block is executed if ``fd`` not registered in selector ``s``.
## # block is executed if `fd` not registered in selector `s`.
## raise
##
@@ -230,7 +230,7 @@ when defined(nimdoc):
proc getFd*[T](s: Selector[T]): int =
## Retrieves the underlying selector's file descriptor.
##
## For *poll* and *select* selectors ``-1`` is returned.
## For *poll* and *select* selectors `-1` is returned.
else:
import strutils

View File

@@ -41,7 +41,7 @@
##
##
## For SSL support this module relies on OpenSSL. If you want to
## enable SSL, compile with ``-d:ssl``.
## enable SSL, compile with `-d:ssl`.
import net, strutils, strtabs, base64, os, strutils
import asyncnet, asyncdispatch
@@ -72,10 +72,10 @@ proc containsNewline(xs: seq[string]): bool =
return true
proc debugSend*(smtp: Smtp | AsyncSmtp, cmd: string) {.multisync.} =
## Sends ``cmd`` on the socket connected to the SMTP server.
## Sends `cmd` on the socket connected to the SMTP server.
##
## If the ``smtp`` object was created with ``debug`` enabled,
## debugSend will invoke ``echo("C:" & cmd)`` before sending.
## If the `smtp` object was created with `debug` enabled,
## debugSend will invoke `echo("C:" & cmd)` before sending.
##
## This is a lower level proc and not something that you typically
## would need to call when using this module. One exception to
@@ -90,8 +90,8 @@ proc debugRecv*(smtp: Smtp | AsyncSmtp): Future[string] {.multisync.} =
## Receives a line of data from the socket connected to the
## SMTP server.
##
## If the ``smtp`` object was created with ``debug`` enabled,
## debugRecv will invoke ``echo("S:" & result.string)`` after
## If the `smtp` object was created with `debug` enabled,
## debugRecv will invoke `echo("S:" & result.string)` after
## the data is received.
##
## This is a lower level proc and not something that you typically
@@ -125,8 +125,8 @@ proc createMessage*(mSubject, mBody: string, mTo, mCc: seq[string],
otherHeaders: openArray[tuple[name, value: string]]): Message =
## Creates a new MIME compliant message.
##
## You need to make sure that ``mSubject``, ``mTo`` and ``mCc`` don't contain
## any newline characters. Failing to do so will raise ``AssertionDefect``.
## You need to make sure that `mSubject`, `mTo` and `mCc` don't contain
## any newline characters. Failing to do so will raise `AssertionDefect`.
doAssert(not mSubject.contains({'\c', '\L'}),
"'mSubject' shouldn't contain any newline characters")
doAssert(not (mTo.containsNewline() or mCc.containsNewline()),
@@ -144,8 +144,8 @@ proc createMessage*(mSubject, mBody: string, mTo,
mCc: seq[string] = @[]): Message =
## Alternate version of the above.
##
## You need to make sure that ``mSubject``, ``mTo`` and ``mCc`` don't contain
## any newline characters. Failing to do so will raise ``AssertionDefect``.
## You need to make sure that `mSubject`, `mTo` and `mCc` don't contain
## any newline characters. Failing to do so will raise `AssertionDefect`.
doAssert(not mSubject.contains({'\c', '\L'}),
"'mSubject' shouldn't contain any newline characters")
doAssert(not (mTo.containsNewline() or mCc.containsNewline()),
@@ -157,7 +157,7 @@ proc createMessage*(mSubject, mBody: string, mTo,
result.msgOtherHeaders = newStringTable()
proc `$`*(msg: Message): string =
## stringify for ``Message``.
## stringify for `Message`.
result = ""
if msg.msgTo.len() > 0:
result = "TO: " & msg.msgTo.join(", ") & "\c\L"
@@ -173,7 +173,7 @@ proc `$`*(msg: Message): string =
proc newSmtp*(useSsl = false, debug = false,
sslContext: SslContext = nil): Smtp =
## Creates a new ``Smtp`` instance.
## Creates a new `Smtp` instance.
new result
result.debug = debug
result.sock = newSocket()
@@ -188,7 +188,7 @@ proc newSmtp*(useSsl = false, debug = false,
proc newAsyncSmtp*(useSsl = false, debug = false,
sslContext: SslContext = nil): AsyncSmtp =
## Creates a new ``AsyncSmtp`` instance.
## Creates a new `AsyncSmtp` instance.
new result
result.debug = debug
@@ -212,9 +212,9 @@ proc quitExcpt(smtp: AsyncSmtp, msg: string): Future[void] =
proc checkReply*(smtp: Smtp | AsyncSmtp, reply: string) {.multisync.} =
## Calls `debugRecv<#debugRecv,AsyncSmtp>`_ and checks that the received
## data starts with ``reply``. If the received data does not start
## with ``reply``, then a ``QUIT`` command will be sent to the SMTP
## server and a ``ReplyError`` exception will be raised.
## data starts with `reply`. If the received data does not start
## with `reply`, then a `QUIT` command will be sent to the SMTP
## server and a `ReplyError` exception will be raised.
##
## This is a lower level proc and not something that you typically
## would need to call when using this module. One exception to
@@ -269,12 +269,12 @@ proc auth*(smtp: Smtp | AsyncSmtp, username, password: string) {.multisync.} =
proc sendMail*(smtp: Smtp | AsyncSmtp, fromAddr: string,
toAddrs: seq[string], msg: string) {.multisync.} =
## Sends ``msg`` from ``fromAddr`` to the addresses specified in ``toAddrs``.
## Messages may be formed using ``createMessage`` by converting the
## Sends `msg` from `fromAddr` to the addresses specified in `toAddrs`.
## Messages may be formed using `createMessage` by converting the
## Message into a string.
##
## You need to make sure that ``fromAddr`` and ``toAddrs`` don't contain
## any newline characters. Failing to do so will raise ``AssertionDefect``.
## You need to make sure that `fromAddr` and `toAddrs` don't contain
## any newline characters. Failing to do so will raise `AssertionDefect`.
doAssert(not (toAddrs.containsNewline() or fromAddr.contains({'\c', '\L'})),
"'toAddrs' and 'fromAddr' shouldn't contain any newline characters")

View File

@@ -14,7 +14,7 @@
## Changing the style is permanent even after program termination! Use the
## code `exitprocs.addExitProc(resetAttributes)` to restore the defaults.
## Similarly, if you hide the cursor, make sure to unhide it with
## ``showCursor`` before quitting.
## `showCursor` before quitting.
import macros
import strformat
@@ -543,7 +543,7 @@ type
fgMagenta, ## magenta
fgCyan, ## cyan
fgWhite, ## white
fg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.)
fg8Bit, ## 256-color (not supported, see `enableTrueColors` instead.)
fgDefault ## default terminal foreground color
BackgroundColor* = enum ## terminal's background colors
@@ -555,7 +555,7 @@ type
bgMagenta, ## magenta
bgCyan, ## cyan
bgWhite, ## white
bg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.)
bg8Bit, ## 256-color (not supported, see `enableTrueColors` instead.)
bgDefault ## default terminal background color
when defined(windows):
@@ -579,7 +579,7 @@ proc setForegroundColor*(f: File, fg: ForegroundColor, bright = false) =
(FOREGROUND_RED or FOREGROUND_BLUE),
(FOREGROUND_BLUE or FOREGROUND_GREEN),
(FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED),
0, # fg8Bit not supported, see ``enableTrueColors`` instead.
0, # fg8Bit not supported, see `enableTrueColors` instead.
0] # unused
if fg == fgDefault:
discard setConsoleTextAttribute(h, toU16(old or defaultForegroundColor))
@@ -608,7 +608,7 @@ proc setBackgroundColor*(f: File, bg: BackgroundColor, bright = false) =
(BACKGROUND_RED or BACKGROUND_BLUE),
(BACKGROUND_BLUE or BACKGROUND_GREEN),
(BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED),
0, # bg8Bit not supported, see ``enableTrueColors`` instead.
0, # bg8Bit not supported, see `enableTrueColors` instead.
0] # unused
if bg == bgDefault:
discard setConsoleTextAttribute(h, toU16(old or defaultBackgroundColor))
@@ -697,10 +697,10 @@ template styledEchoProcessArg(f: File, cmd: TerminalCmd) =
term.fgSetColor = cmd == fgColor
macro styledWrite*(f: File, m: varargs[typed]): untyped =
## Similar to ``write``, but treating terminal style arguments specially.
## When some argument is ``Style``, ``set[Style]``, ``ForegroundColor``,
## ``BackgroundColor`` or ``TerminalCmd`` then it is not sent directly to
## ``f``, but instead corresponding terminal style proc is called.
## Similar to `write`, but treating terminal style arguments specially.
## When some argument is `Style`, `set[Style]`, `ForegroundColor`,
## `BackgroundColor` or `TerminalCmd` then it is not sent directly to
## `f`, but instead corresponding terminal style proc is called.
##
## Example:
##
@@ -730,7 +730,7 @@ macro styledWrite*(f: File, m: varargs[typed]): untyped =
if reset: result.add(newCall(bindSym"resetAttributes", f))
template styledWriteLine*(f: File, args: varargs[untyped]) =
## Calls ``styledWrite`` and appends a newline at the end.
## Calls `styledWrite` and appends a newline at the end.
##
## Example:
##
@@ -743,7 +743,7 @@ template styledWriteLine*(f: File, args: varargs[untyped]) =
write(f, "\n")
template styledEcho*(args: varargs[untyped]) =
## Echoes styles arguments to stdout using ``styledWriteLine``.
## Echoes styles arguments to stdout using `styledWriteLine`.
stdout.styledWriteLine(args)
proc getch*(): char =
@@ -772,8 +772,8 @@ when defined(windows):
proc readPasswordFromStdin*(prompt: string, password: var string):
bool {.tags: [ReadIOEffect, WriteIOEffect].} =
## Reads a `password` from stdin without printing it. `password` must not
## be ``nil``! Returns ``false`` if the end of the file has been reached,
## ``true`` otherwise.
## be `nil`! Returns `false` if the end of the file has been reached,
## `true` otherwise.
password.setLen(0)
stdout.write(prompt)
let hi = createFileA("CONIN$",

View File

@@ -208,7 +208,7 @@ when emulatedThreadVars:
# we preallocate a fixed size for thread local storage, so that no heap
# allocations are needed. Currently less than 16K are used on a 64bit machine.
# We use ``float`` for proper alignment:
# We use `float` for proper alignment:
const nimTlsSize {.intdefine.} = 16000
type
ThreadLocalStorage = array[0..(nimTlsSize div sizeof(float)), float]

View File

@@ -91,7 +91,7 @@ const
template ones(n: untyped): untyped = ((1 shl n)-1)
template fastRuneAt(s: cstring, i, L: int, result: untyped, doInc = true) =
## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true``
## Returns the unicode character `s[i]` in `result`. If `doInc == true`
## `i` is incremented by the number of bytes that have been processed.
bind ones

View File

@@ -1119,7 +1119,7 @@ proc SwitchToFiber*(fiber: pointer): void {.stdcall, discardable, dynlib: "kerne
proc GetCurrentFiber*(): pointer {.stdcall, importc, header: "windows.h".}
proc toFILETIME*(t: int64): FILETIME =
## Convert the Windows file time timestamp ``t`` to ``FILETIME``.
## Convert the Windows file time timestamp `t` to `FILETIME`.
result = FILETIME(dwLowDateTime: cast[DWORD](t), dwHighDateTime: DWORD(t shr 32))
type

View File

@@ -12,9 +12,9 @@
## When OpenSSL is dynamically linked, the wrapper provides partial forward and backward
## compatibility for OpenSSL versions above and below 1.1.0
##
## OpenSSL can also be statically linked using ``--dynlibOverride:ssl`` for OpenSSL >= 1.1.0.
## OpenSSL can also be statically linked using `--dynlibOverride:ssl` for OpenSSL >= 1.1.0.
## If you want to statically link against OpenSSL 1.0.x, you now have to
## define the ``openssl10`` symbol via ``-d:openssl10``.
## define the `openssl10` symbol via `-d:openssl10`.
##
## Build and test examples:
##
@@ -586,7 +586,7 @@ proc SSL_CTX_set_tlsext_servername_callback*(ctx: SslCtx, cb: proc(ssl: SslPtr,
result = SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, cast[PFunction](cb))
proc SSL_CTX_set_tlsext_servername_arg*(ctx: SslCtx, arg: pointer): int =
## Set the pointer to be used in the callback registered to ``SSL_CTX_set_tlsext_servername_callback``.
## Set the pointer to be used in the callback registered to `SSL_CTX_set_tlsext_servername_callback`.
result = SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, arg)
type