Subject: [Info-WASD] WASD TLS (SSL) processing
From: [email-masked]
To: [email-masked]
Date: Thu, 23 Apr 2026 13:08:13 +0930

(Way)TL;DR  WASD is event-driven, especially network IO; encrypted network I/O interleaves
            OpenSSL BIO calls inside WASD AST $QIO I/O with encrypted data transfer resulting.

Just before beginning (an attempt) to integrate QUIC (using OpenSSL) and HTTP/3 into WASD,
I thought it useful (to myself) to recap current mechanisms and behaviour.

Most readers will be familiar with the mantra, "WASD is event-driven".

  It eschews implicit threading in all implementations, instead explicitly
  grabbing and processing each event, software and hardware, with its own
  code elements, orchestrating these into a functional whole to deliver
  the data to the end-user.  Such a non-linear coding practise makes it more
  difficult to gain an overall grasp of functional flow (though WATCH helps).

  https://wasd.vsm.com.au/info-WASD/2026/0003

Another guiding mantra, doing it all "the VMS way" (aka, long-winded way).

One of the core intents of WASD was to familiarise a systems manager (without previous VMS
experience) with the internals of VMS by programming it.  And while a number of utilities had
previously been cobbled together, the advent and fervent adoption of the World Wide Web
presented an opportunity for greater scope, as it eventuated, a thirty-plus year scope.

  https://wasd.vsm.com.au/info-WASD/2024/0008

WATCH reporting will be used to illustrate WASD behaviours during secure communication.

For those with an insatiable need to delve, or an unfulfilled desire for self-flagellation,
the source codes for network and SSL/TLS respectively can be found at

  https://wasd.vsm.com.au/wasd_root/src/httpd/net*.*?httpd=index&nos=yes
  https://wasd.vsm.com.au/wasd_root/src/httpd/sesola*.*?httpd=index&nos=yes

The Foundational Interface
~~~~~~~~~~~~~~~~~~~~~~~~~~
All network and scripting IPC uses the QIO system service, most commonly asynchronously.  This
means data is given to the service which makes a software interrupt when the I/O has completed.
Network data is explicitly handled using the BG device driver (or emulation) using $ASSIGN,
$QIO(IO$_SETMODE), $QIO(IO$_READVBLK), $QIO(IO$_WRITEVBLK), $QIO(IO$_DEACCESS), $DASSGN and of
course $DCLAST.  OpenSSL has evolved since WASD's original use of SSLeay v0.8.1.  However the
fundamental approach remains the same.  OpenSSL Basic I/O (BIO) objects and functions are
essentially wrapped by AST calls.

Initialisation
~~~~~~~~~~~~~~
In common with most else, the OpenSSL library requires initialisation.  Callbacks need to be
established.  Ciphers, protocol versions, and other options require setting.  All of these are
rolled into a 'context' from which an 'SSL' structure is derived.

Network sockets to act as listeners for client connections are created in the usual (VMS) way.
This description is substantially abbreviated with code segments plucked from here and there.

  /* assign a channel */
  status = sys$assign (&TcpIpDeviceDsc, &ServerChannel, 0, 0);

  /* prepare to bind the server socket to the IP address and port */
  sin4ptr = &svptr->ServerSocketName.sa.v4;
  sin4ptr->SIN$B_FAMILY = TCPIP$C_AF_INET;
  sin4ptr->SIN$W_PORT = htons(IpPort);
  IPADDRESS_SET4 (&sin4ptr->SIN$L_ADDR, &IpAddress)

  /* make the channel a TCP, connection-oriented socket */
  status = sys$qiow (EfnWait, ServerChannel, qiofun,
                     &svptr->ServerIOsb, 0, 0, TcpSocketPtr, 0, 0, 0,
                     &TcpIpSocketReuseAddrOption, 0);

  /* queue an accept to the listening socket */
  qiofun = IO$_ACCESS | IO$M_ACCEPT;
  status = sys$qio (EfnNoWait, svptr->ServerChannel,
                    qiofun, &ioptr->AcceptIOsb, &NetAcceptAst, ioptr,
                    0, 0, &clptr->SocketNameItem,
                    &ioptr->Channel, &TcpIpFullDuplexCloseOption, 0);

  /* when accepted the AST is called providing the channel of a client socket allowing */
  status = sys$qio (EfnNoWait, ntptr->Channel, IO$_READVBLK, ...
  status = sys$qio (EfnNoWait, ntptr->Channel, IO$_WRITEVBLK, ...

All of these have a 'sesolaptr' (WASD defined structure), amongst other things, pointing to the
'SSL' structure which in turn points back to the associated socket, and so on and so forth.

Module WATCHing
~~~~~~~~~~~~~~~
This is an extension of the basic WATCH facility, used during development, to provide a far
more detailed functional flow, showing exact function calls and plethora of other detail.  The
wood often disappears into the forest with general usage.  Module WATCHing must be compiled in
(so not available with a general build).  Module WATCH-points are indicated by a leading
underscore not present in general WATCHing.  So "SSL" and "NETWORK" indicate general
WATCH-points and "_SESOLA" a module WATCH-point.

NOTE: There is a LOT of OpenSSL chatter going on 'under the hood', so some of the _SESOLA
module WATCH points, and the bulk of the actual data, have been snipped to reduce the clutter.

A (non-module) WATCH can be performed by any site, at any time (see 'self-flagellation' above),
including the reporting of all plaintext and ciphertext, using the following items.

  Request         Response        General        Network
  -------------   -------------   -------------  -------------
  [x]Processing   [x]Processing   [x]Connection  [x]Activity
  [x]Header       [x]Header       [x]Error       [x]Data
  [x]Body         [x]Body                        [x]SSL

In many respects the non-module WATCH shows the general flow of HTTPS much more clearly.

Use a CLI tool such as cURL (a request using a browser might be caching various data).

  $ curl --http1.1 -k https://<host-name>/ 

Client Hello
~~~~~~~~~~~~
Following network socket connection and acceptance, a handshake is sent to the server, with
supported cipher suites, key agreement protocol, and shared key, along with TLS extensions
allowing the client to specify a(n often virtual) host name, and the preferred application
protocol (e.g. "http/1.1", "h2", "acme-tls/1").

|15:08:38.24 SESOLANE 0185 000002 _SESOLA..  SesolaNetBegin()|
|15:08:38.24 SESOLANE 1212 ****** _SESOLA..  BIO_s_Sesola()|
|15:08:38.24 SESOLA   4765 ****** _SESOLA..  SesolaProtocolVersion()|
|15:08:38.24 SESOLANE 0248 000002 SSL        BEGIN TLSv1, TLSv1.1, TLSv1.2, TLSv1.3|
|15:08:38.24 SESOLANE 0337 ****** _SESOLA..  SesolaNetAccept() 001971B0() 0 FALSE FALSE FALSE %X00000000|
|15:08:38.24 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 16 1|
|15:08:38.24 SESOLANE 1246 ****** _SESOLA..  Sesola_ctrl() 6 0 0x020BF900|
|15:08:38.24 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 8193 1|
|15:08:38.24 OLANETIO 0753 000002 _SESOLA..  Sesola_netio_read() 0x003DAAA8 0x02267013 0x00000005 2060328700 FALSE FALSE|
|15:08:38.24 OLANETIO 0788 000002 NETWORK    READ 5 bytes max CIPHER (non-blocking)|
|15:08:38.24 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 8194 -1|
|15:08:38.24 SESOLANE 0351 000002 _SESOLA..  SSL_accept() -1 2|
^^^ SSL connection acceptance is in progress
|15:08:38.24 OLANETIO 0894 000002 _SESOLA..  Sesola_netio_read_ast() 0x003DAAA8 00197260() %X00000000 %X00000001 5|
|15:08:38.24 OLANETIO 0910 000002 NETWORK    READ %X00000001 5 bytes CIPHER (non-blocking)|
16030101 38                                                             ....8
^^^ SSL/TLS record header; 0x16 handshake, 0x0301 version, 0x0138 record size 312 bytes
|15:08:38.24 SESOLANE 0337 ****** _SESOLA..  SesolaNetAccept() 001971B0() 1 FALSE FALSE FALSE %X00000001|
|15:08:38.24 OLANETIO 0753 000002 _SESOLA..  Sesola_netio_read() 0x003DAAA8 0x02267013 0x00000005 2060329100 FALSE TRUE|
|15:08:38.24 OLANETIO 0753 000002 _SESOLA..  Sesola_netio_read() 0x003DAAA8 0x02267018 0x00000138 2060329100 FALSE FALSE|
|15:08:38.24 OLANETIO 0788 000002 NETWORK    READ 312 bytes max CIPHER (non-blocking)|
^^^ reads the 312 byte record
|15:08:38.24 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 8194 -1|
|15:08:38.24 SESOLANE 0351 000002 _SESOLA..  SSL_accept() -1 2|
^^^ SSL connection acceptance is in progress
|15:08:38.24 OLANETIO 0894 000002 _SESOLA..  Sesola_netio_read_ast() 0x003DAAA8 00197260() %X00000000 %X00000001 312|
|15:08:38.24 OLANETIO 0910 000002 NETWORK    READ %X00000001 312 bytes CIPHER (non-blocking)|
 8< snip 8<
|15:08:38.24 SESOLANE 0337 ****** _SESOLA..  SesolaNetAccept() 001971B0() 2 FALSE FALSE FALSE %X00000001|
|15:08:38.24 OLANETIO 0753 000002 _SESOLA..  Sesola_netio_read() 0x003DAAA8 0x02267018 0x00000138 2060329100 FALSE TRUE|
|15:08:38.24 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 8193 1|
|15:08:38.24 SESOLA   3059 ****** _SESOLA..  SesolaHelloCallback()|
 8< snip 8<
|15:08:38.24 SESOLA   3282 000002 SSL        SNI FAIL x86vms.lan|
^^^ this has connected to NOT the official service name (unimportant in this example)
|15:08:38.24 SESOLA   3103 000002 SSL        ALPN http/1.1|
^^^ application layer protocol name and is supported by the server
|15:08:38.24 SESOLA   3139 000002 SSL        OK http/1.1|

Server Hello
~~~~~~~~~~~~
The server returns a handshake containing key agreement protocol, server certificate, its own
portion of the key share, calculates the session key and ends with a server finished message.
Once the client has received these data it will authenticate the SSL certificate and use the
two key shares to calculate its own copy of the session key.  When this is complete it sends
its own finished message.  The session is then considered established.

|15:08:38.25 OLANETIO 0330 000002 NETWORK    WRITE 3293 bytes CIPHER (non-blocking)|
 8< snip 8<
|15:08:38.25 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 8194 -1|
|15:08:38.25 SESOLANE 0351 000002 _SESOLA..  SSL_accept() -1 3|
^^^ SSL connection acceptance is in progress
|15:08:38.25 OLANETIO 0419 000002 _SESOLA..  Sesola_netio_write_ast() 0x003DAAA8 00197270() %X00000000 TRUE %X00000001 3293|
|15:08:38.25 OLANETIO 0435 000002 NETWORK    WRITE %X00000001 3293 bytes CIPHER (non-blocking)|
|15:08:38.25 SESOLANE 0337 ****** _SESOLA..  SesolaNetAccept() 001971B0() 3 FALSE FALSE FALSE %X00000001|
|15:08:38.25 OLANETIO 0294 000002 _SESOLA..  Sesola_netio_write_ex() 0x003DAAA8 0x020B0970 3293 0x7ACE2394 FALSE FALSE|
|15:08:38.25 SESOLANE 1246 ****** _SESOLA..  Sesola_ctrl() 11 0 0x00000000|
|15:08:38.25 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 8193 1|
|15:08:38.25 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 8193 1|
|15:08:38.25 OLANETIO 0753 000002 _SESOLA..  Sesola_netio_read() 0x003DAAA8 0x02267013 0x00000005 2060329100 FALSE FALSE|
|15:08:38.25 OLANETIO 0788 000002 NETWORK    READ 5 bytes max CIPHER (non-blocking)|
|15:08:38.25 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 8194 -1|
 8< snip 8<
|15:08:38.30 SESOLANE 0351 000002 _SESOLA..  SSL_accept() -1 2|
|15:08:38.30 OLANETIO 0894 000002 _SESOLA..  Sesola_netio_read_ast() 0x003DAAA8 00197260() %X00000000 %X00000001 69|
|15:08:38.30 OLANETIO 0910 000002 NETWORK    READ %X00000001 69 bytes CIPHER (non-blocking)|
 8< snip 8<
|15:08:38.30 SESOLA   2880 ****** _SESOLA..  SesolaSessionTicketCallback() 1 906B2E7B00000000986B2E7B00000000|
|15:08:38.30 OLANETIO 0294 000002 _SESOLA..  Sesola_netio_write_ex() 0x003DAAA8 0x020B0970 287 0x7ACE2394 FALSE FALSE|
|15:08:38.30 OLANETIO 0330 000002 NETWORK    WRITE 287 bytes CIPHER (non-blocking)|
 8< snip 8<
|15:08:38.30 SESOLANE 0351 000002 _SESOLA..  SSL_accept() -1 3|
|15:08:38.30 OLANETIO 0419 000002 _SESOLA..  Sesola_netio_write_ast() 0x003DAAA8 00197270() %X00000000 TRUE %X00000001 287|
|15:08:38.30 OLANETIO 0435 000002 NETWORK    WRITE %X00000001 287 bytes CIPHER (non-blocking)|
|15:08:38.30 SESOLANE 0337 ****** _SESOLA..  SesolaNetAccept() 001971B0() 8 FALSE FALSE FALSE %X00000001|
|15:08:38.30 OLANETIO 0294 000002 _SESOLA..  Sesola_netio_write_ex() 0x003DAAA8 0x020B0970 287 0x7ACE2394 FALSE FALSE|
|15:08:38.30 SESOLANE 1246 ****** _SESOLA..  Sesola_ctrl() 11 0 0x00000000|
|15:08:38.30 SESOLA   3448 ****** _SESOLA..  SesolaWatchInfoCallback() 8193 1|
|15:08:38.30 SESOLA   2880 ****** _SESOLA..  SesolaSessionTicketCallback() 1 906B2E7B00000000986B2E7B00000000|
|15:08:38.30 OLANETIO 0294 000002 _SESOLA..  Sesola_netio_write_ex() 0x003DAAA8 0x020B0970 287 0x7ACE2394 FALSE FALSE|
|15:08:38.30 OLANETIO 0330 000002 NETWORK    WRITE 287 bytes CIPHER (non-blocking)|
 8< snip 8<
|15:08:38.30 SESOLANE 0351 000002 _SESOLA..  SSL_accept() 1 0|
^^^ SSL connection acceptance has completed
|15:08:38.30 SESOLA   3663 000000 SSL        SESSION hit:no protocol:TLSv1.3 cipher:TLS_AES_256_GCM_SHA384 keysize:256/256 X509:no|
^^^ session characteristics reported

Encrypted Read
~~~~~~~~~~~~~~
The server then reads encrypted data from the client.
For HTTP this is expected to be the request header.

|15:08:38.30 OLANETIO 0516 000002 _SESOLA..  SesolaNetIoRead() 0x003DAAA8 0x0185C168 16384|
|15:08:38.30 OLANETIO 0541 000002 NETWORK    READ 0/16384 bytes (non-blocking)|
^^^ the server requests to read up to 16384 bytes
|15:08:38.30 OLANETIO 0753 000002 _SESOLA..  Sesola_netio_read() 0x003DAAA8 0x018C0813 0x00000005 2060328812 FALSE FALSE|
|15:08:38.30 OLANETIO 0788 000002 NETWORK    READ 5 bytes max CIPHER (non-blocking)|
|15:08:38.30 OLANETIO 0612 000002 _SESOLA..  SSL_read() in-progress|
|15:08:38.30 OLANETIO 0894 000002 _SESOLA..  Sesola_netio_read_ast() 0x003DAAA8 00197260() %X00000000 %X00000001 5|
|15:08:38.30 OLANETIO 0910 000002 NETWORK    READ %X00000001 5 bytes CIPHER (non-blocking)|
17030300 5A                                                             ....Z
^^^ the OpenSSL BIO reads the encrypted record header
 8< snip 8<
|15:08:38.30 OLANETIO 0516 000002 _SESOLA..  SesolaNetIoRead() 0x003DAAA8 0x00000000 0|
|15:08:38.30 OLANETIO 0753 000002 _SESOLA..  Sesola_netio_read() 0x003DAAA8 0x018C0813 0x00000005 2060329324 FALSE TRUE|
|15:08:38.30 OLANETIO 0753 000002 _SESOLA..  Sesola_netio_read() 0x003DAAA8 0x018C0818 0x0000005A 2060329324 FALSE FALSE|
|15:08:38.30 OLANETIO 0788 000002 NETWORK    READ 90 bytes max CIPHER (non-blocking)|
^^^ and from the record header specifies 90 more bytes
|15:08:38.30 OLANETIO 0612 000002 _SESOLA..  SSL_read() in-progress|
|15:08:38.30 OLANETIO 0894 000002 _SESOLA..  Sesola_netio_read_ast() 0x003DAAA8 00197260() %X00000000 %X00000001 90|
|15:08:38.30 OLANETIO 0910 000002 NETWORK    READ %X00000001 90 bytes CIPHER (non-blocking)|
^^^ the 90 byte read has successfully completed
 8< snip 8<
|15:08:38.30 OLANETIO 0516 000002 _SESOLA..  SesolaNetIoRead() 0x003DAAA8 0x00000000 0|
|15:08:38.30 OLANETIO 0753 000002 _SESOLA..  Sesola_netio_read() 0x003DAAA8 0x018C0818 0x0000005A 2060329324 FALSE TRUE|
^^^ and is successfully decrypted 
|15:08:38.30 OLANETIO 0638 000002 _SESOLA..  SSL_read() 1 0 73 73/16384 %X00000001|
|15:08:38.30 OLANETIO 0660 000002 NETWORK    READ %X00000001 73 bytes PLAIN (non-blocking)|
^^^ the 73 byte plaintext header is read
47455420 2F204854 54502F31 2E310D0A 486F7374 3A207838 36766D73 2E6C616E GET / HTTP/1.1..Host: x86vms.lan
0D0A5573 65722D41 67656E74 3A206375 726C2F38 2E372E31 0D0A4163 63657074 ..User-Agent: curl/8.7.1..Accept
3A202A2F 2A0D0A0D 0A                                                    : */*....
^^^ the above three lines show the plaintext data of the header

Request Header
~~~~~~~~~~~~~~
|15:08:38.72 REQUEST  2733 000003 REQ-HEADER HEADER 73 bytes|
GET / HTTP/1.1
Host: x86vms.lan
User-Agent: curl/8.7.1
Accept: */*

|15:08:38.72 REQUEST  3704 000003 REQ-HEADER DATA|
ENTRY 001 [012] $ {12}request_line={14}GET / HTTP/1.1
ENTRY 002 [024] > {4}host={10}x86vms.lan
ENTRY 003 [001] > {10}user-agent={10}curl/8.7.1
ENTRY 004 [014] > {6}accept={3}*/*
|15:08:38.72 SERVICE  1803 000001 CONNECT    UNKNOWN service|
|15:08:38.72 REQUEST  4421 000001 REQUEST    GET /|

Response Header
~~~~~~~~~~~~~~~
After server processing of the request the response header (and any body) are generated.

|15:08:38.72 NET      2725 000001 RES-HEADER HEADER 410 bytes|
HTTP/1.1 200 OK
Server: HTTPd-WASD/12.4.1 OpenVMS/X86 SSL
Date: Mon, 16 Apr 2026 15:08:38 GMT
Accept-Ranges: bytes
Accept-Encoding: gzip, deflate
Strict-Transport-Security: max-age=0
Etag: 3cda0004000065f6c65200bb56ba
Last-Modified: Mon, 22 Dec 2025 00:28:41 GMT
Content-Type: text/html; charset=ISO-8859-1
Content-Length: 5272
Content-Security-Policy: frame-ancestors 'self'; form-action 'self';

|15:08:38.72 OLANETIO 0157 000002 NETWORK    WRITE 410 bytes PLAIN (non-blocking)|
^^^ the server writes 410 bytes plaintext to the client
 8< snip 8<
|15:38:16.72 OLANETIO 0294 000002 _SESOLA..  Sesola_netio_write_ex() 0x003051E8 0x0184C013 432 0x7ACE1FB4 FALSE FALSE|
|15:08:38.72 OLANETIO 0330 000002 NETWORK    WRITE 432 bytes CIPHER (non-blocking)|
^^^ which after encryption is sent as 432 bytes ciphertext
 8< snip 8<
|15:08:38.72 OLANETIO 0194 000002 _SESOLA..  SSL_write() 0 3 0 TRUE|
|15:08:38.72 OLANETIO 0419 000002 _SESOLA..  Sesola_netio_write_ast() 0x003051E8 00197270() %X00000000 TRUE %X00000001 432|
|15:08:38.72 OLANETIO 0435 000002 NETWORK    WRITE %X00000001 432 bytes CIPHER (non-blocking)|
^^^ the cipher text has been successfully written
|15:08:38.72 OLANETIO 0131 000002 _SESOLA..  SesolaNetIoWrite() 0x003051E8 0x00000000 0|
|15:08:38.72 OLANETIO 0294 000002 _SESOLA..  Sesola_netio_write_ex() 0x003051E8 0x0184C013 432 0x7ACE2244 FALSE FALSE|
|15:08:38.72 OLANETIO 0194 000002 _SESOLA..  SSL_write() 1 0 410 FALSE|
|15:08:38.72 OLANETIO 0225 000002 _SESOLA..  %X00000001 410|
^^^ and is reported as a successful 410 byte plaintext write
|15:08:38.72 OLANETIO 0261 000002 _SESOLA..  SesolaNetIoWriteAst()|

Response Body
~~~~~~~~~~~~~
|15:08:38.73 OLANETIO 0157 000002 NETWORK    WRITE 5272 bytes PLAIN (non-blocking)|
^^^ the server writes 5272 bytes plaintext to the client
 8< snip 8<
|15:08:38.73 OLANETIO 0294 000002 _SESOLA..  Sesola_netio_write_ex() 0x003051E8 0x0184C013 5294 0x7ACE2164 FALSE FALSE|
|15:08:38.73 OLANETIO 0330 000002 NETWORK    WRITE 5294 bytes CIPHER (non-blocking)|
^^^ which after encryption is sent as 5294 bytes ciphertext
 8< snip 8<
|15:08:38.73 OLANETIO 0194 000002 _SESOLA..  SSL_write() 0 3 0 TRUE|
|15:08:38.73 OLANETIO 0419 000002 _SESOLA..  Sesola_netio_write_ast() 0x003051E8 00197270() %X00000000 TRUE %X00000001 5294|
|15:08:38.73 OLANETIO 0435 000002 NETWORK    WRITE %X00000001 5294 bytes CIPHER (non-blocking)|
^^^ the cipher text has been successfully written
|15:08:38.73 OLANETIO 0131 000002 _SESOLA..  SesolaNetIoWrite() 0x003051E8 0x00000000 0|
|15:08:38.73 OLANETIO 0294 000002 _SESOLA..  Sesola_netio_write_ex() 0x003051E8 0x0184C013 5294 0x7ACE2244 FALSE FALSE|
|15:08:38.73 OLANETIO 0194 000002 _SESOLA..  SSL_write() 1 0 5272 FALSE|
|15:08:38.73 OLANETIO 0225 000002 _SESOLA..  %X00000001 5272|
^^^ and is reported as a successful 5272 byte plaintext write
|15:08:38.73 OLANETIO 0261 000002 _SESOLA..  SesolaNetIoWriteAst()|

Connection Closure
~~~~~~~~~~~~~~~~~~
The client socket channel is $DASSGNed and the SSL/TLS connection shutdown and freed.

|15:08:38.73 SESOLANE 0486 000003 _SESOLA..  SesolaNetEnd() 00197230() shut:2 chan:1296 count:0 read:%X0000002C AST:&00000000/null() inprog:0 write:%X00000001 AST:&00000000/null() inprog:0|
|15:08:38.73 SESOLANE 0529 000003 SSL        SHUTDOWN|
|15:08:38.73 OLANETIO 0294 000003 _SESOLA..  Sesola_netio_write_ex() 0x003051E8 0x0184C013 24 0x7ACE2354 FALSE FALSE|
|15:08:38.73 OLANETIO 0330 000003 NETWORK    WRITE 24 bytes CIPHER (non-blocking)|
17030300 13C02749 78347731 C69FD2EB 8BDC9910 884EA800
......'Ix4w1.........N..
|15:08:38.73 SESOLANE 0542 000003 _SESOLA..  SSL_shutdown() -1 3|
|15:08:38.73 SESOLANE 0568 000003 _SESOLA..  reading:0 writing:1|
|15:08:38.73 SESOLANE 0628 ****** _SESOLA..  SesolaNetFree()|

"Here endeth the lesson", Jim Malone, The Untouchables (1987)

This item is one of a collection at
https://wasd.vsm.com.au/other/#occasional