1d4afb5ceSopenharmony_ci# Abstract protocols and transports
2d4afb5ceSopenharmony_ci
3d4afb5ceSopenharmony_ci## Overview
4d4afb5ceSopenharmony_ci
5d4afb5ceSopenharmony_ciUntil now protocol implementations in lws have been done directly
6d4afb5ceSopenharmony_cito the network-related apis inside lws.
7d4afb5ceSopenharmony_ci
8d4afb5ceSopenharmony_ciIn an effort to separate out completely network implementation
9d4afb5ceSopenharmony_cidetails from protocol specification, lws now supports
10d4afb5ceSopenharmony_ci"abstract protocols" and "abstract transports".
11d4afb5ceSopenharmony_ci
12d4afb5ceSopenharmony_ci![lws_abstract overview](/doc-assets/abstract-overview.svg)
13d4afb5ceSopenharmony_ci
14d4afb5ceSopenharmony_ciThe concept is that the implementation is split into two separate
15d4afb5ceSopenharmony_cichunks of code hidden behind "ops" structs... the "abstract protocol"
16d4afb5ceSopenharmony_ciimplementation is responsible for the logical protocol operation
17d4afb5ceSopenharmony_ciand reads and writes only memory buffers.
18d4afb5ceSopenharmony_ci
19d4afb5ceSopenharmony_ciThe "abstract transport" implementation is responsible for sending
20d4afb5ceSopenharmony_ciand receiving buffers on some kind of transport, and again is hidden
21d4afb5ceSopenharmony_cibehind a standardized ops struct.
22d4afb5ceSopenharmony_ci
23d4afb5ceSopenharmony_ciIn the system, both the abstract protocols and transports are
24d4afb5ceSopenharmony_cifound by their name.
25d4afb5ceSopenharmony_ci
26d4afb5ceSopenharmony_ciAn actual "connection" is created by calling a generic api
27d4afb5ceSopenharmony_ci`lws_abs_bind_and_create_instance()` to instantiate the
28d4afb5ceSopenharmony_cicombination of a protocol and a transport.
29d4afb5ceSopenharmony_ci
30d4afb5ceSopenharmony_ciThis makes it possible to confidently offer the same protocol on
31d4afb5ceSopenharmony_cicompletely different transports, eg, like serial, or to wire
32d4afb5ceSopenharmony_ciup the protocol implementation to a test jig sending canned
33d4afb5ceSopenharmony_citest vectors and confirming the response at buffer level, without
34d4afb5ceSopenharmony_ciany network.  The abstract protocol itself has no relationship
35d4afb5ceSopenharmony_cito the transport at all and is completely unchanged by changes
36d4afb5ceSopenharmony_cito the transport.
37d4afb5ceSopenharmony_ci
38d4afb5ceSopenharmony_ciIn addition, generic tokens to control settings in both the
39d4afb5ceSopenharmony_ciprotocol and the transport are passed in at instantiation-time,
40d4afb5ceSopenharmony_cieg, controlling the IP address targeted by the transport.
41d4afb5ceSopenharmony_ci
42d4afb5ceSopenharmony_cilws SMTP client support has been rewritten to use the new scheme,
43d4afb5ceSopenharmony_ciand lws provides a raw socket transport built-in.
44d4afb5ceSopenharmony_ci
45d4afb5ceSopenharmony_ci## Public API
46d4afb5ceSopenharmony_ci
47d4afb5ceSopenharmony_ciThe public api for defining abstract protocols and transports is
48d4afb5ceSopenharmony_cifound at
49d4afb5ceSopenharmony_ci
50d4afb5ceSopenharmony_ci - [abstract.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/abstract/abstract.h)
51d4afb5ceSopenharmony_ci - [protocols.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/abstract/protocols.h)
52d4afb5ceSopenharmony_ci - [transports.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/abstract/transports.h)
53d4afb5ceSopenharmony_ci
54d4afb5ceSopenharmony_ci### `lws_abs_t`
55d4afb5ceSopenharmony_ci
56d4afb5ceSopenharmony_ciThe main structure that defines the abstraction is `lws_abs_t`,
57d4afb5ceSopenharmony_cithis is a name and then pointers to the protocol and transport,
58d4afb5ceSopenharmony_cioptional tokens to control both the protocol and transport,
59d4afb5ceSopenharmony_ciand pointers to private allocations for both the
60d4afb5ceSopenharmony_ciprotocol and transport when instantiated.
61d4afb5ceSopenharmony_ci
62d4afb5ceSopenharmony_ciThe transport is selected using
63d4afb5ceSopenharmony_ci
64d4afb5ceSopenharmony_ci```
65d4afb5ceSopenharmony_ciLWS_VISIBLE LWS_EXTERN const lws_abs_transport_t *
66d4afb5ceSopenharmony_cilws_abs_transport_get_by_name(const char *name);
67d4afb5ceSopenharmony_ci```
68d4afb5ceSopenharmony_ci
69d4afb5ceSopenharmony_ciand similarly the protocol by
70d4afb5ceSopenharmony_ci
71d4afb5ceSopenharmony_ci```
72d4afb5ceSopenharmony_ciLWS_VISIBLE LWS_EXTERN const lws_abs_protocol_t *
73d4afb5ceSopenharmony_cilws_abs_protocol_get_by_name(const char *name);
74d4afb5ceSopenharmony_ci```
75d4afb5ceSopenharmony_ci
76d4afb5ceSopenharmony_ciAt the moment only "`raw-skt`" is defined as an lws built-in, athough
77d4afb5ceSopenharmony_ciyou can also create your own mock transport the same way for creating
78d4afb5ceSopenharmony_citest jigs.
79d4afb5ceSopenharmony_ci
80d4afb5ceSopenharmony_ci|transport op|meaning|
81d4afb5ceSopenharmony_ci|---|---|
82d4afb5ceSopenharmony_ci|`tx()`|transmit a buffer|
83d4afb5ceSopenharmony_ci|`client_conn()`|start a connection to a peer|
84d4afb5ceSopenharmony_ci|`close()`|request to close the connection to a peer|
85d4afb5ceSopenharmony_ci|`ask_for_writeable()`|request a `writeable()` callback when tx can be used|
86d4afb5ceSopenharmony_ci|`set_timeout()`|set a timeout that will close the connection if reached|
87d4afb5ceSopenharmony_ci|`state()`|check if the connection is established and can carry traffic|
88d4afb5ceSopenharmony_ci
89d4afb5ceSopenharmony_ciThese are called by the protocol to get things done and make queries
90d4afb5ceSopenharmony_cithrough the abstract transport.
91d4afb5ceSopenharmony_ci
92d4afb5ceSopenharmony_ci|protocol op|meaning|
93d4afb5ceSopenharmony_ci|---|---|
94d4afb5ceSopenharmony_ci|`accept()`|The peer has accepted the transport connection|
95d4afb5ceSopenharmony_ci|`rx()`|The peer has sent us some payload|
96d4afb5ceSopenharmony_ci|`writeable()`|The connection to the peer can take more tx|
97d4afb5ceSopenharmony_ci|`closed()`|The connection to the peer has closed|
98d4afb5ceSopenharmony_ci|`heartbeat()`|Called periodically even when no network events|
99d4afb5ceSopenharmony_ci
100d4afb5ceSopenharmony_ciThese are called by the transport to inform the protocol of events
101d4afb5ceSopenharmony_ciand traffic.
102d4afb5ceSopenharmony_ci
103d4afb5ceSopenharmony_ci### Instantiation
104d4afb5ceSopenharmony_ci
105d4afb5ceSopenharmony_ciThe user fills an lws_abs_t and passes a pointer to it to
106d4afb5ceSopenharmony_ci`lws_abs_bind_and_create_instance()` to create an instantiation
107d4afb5ceSopenharmony_ciof the protocol + transport.
108d4afb5ceSopenharmony_ci
109d4afb5ceSopenharmony_ci### `lws_token_map_t`
110d4afb5ceSopenharmony_ci
111d4afb5ceSopenharmony_ciThe abstract protocol has no idea about a network or network addresses
112d4afb5ceSopenharmony_cior ports or whatever... it may not even be hooked up to one.
113d4afb5ceSopenharmony_ci
114d4afb5ceSopenharmony_ciIf the transport it is bound to wants things like that, they are passed
115d4afb5ceSopenharmony_ciin using an array of `lws_token_map_t` at instantiation time.
116d4afb5ceSopenharmony_ci
117d4afb5ceSopenharmony_ciFor example this is passed to the raw socket protocol in the smtp client
118d4afb5ceSopenharmony_ciminimal example to control where it would connect to:
119d4afb5ceSopenharmony_ci
120d4afb5ceSopenharmony_ci```
121d4afb5ceSopenharmony_cistatic const lws_token_map_t smtp_abs_tokens[] = {
122d4afb5ceSopenharmony_ci{
123d4afb5ceSopenharmony_ci	.u = { .value = "127.0.0.1" },
124d4afb5ceSopenharmony_ci	.name_index = LTMI_PEER_DNS_ADDRESS,
125d4afb5ceSopenharmony_ci}, {
126d4afb5ceSopenharmony_ci	.u = { .lvalue = 25l },
127d4afb5ceSopenharmony_ci	.name_index = LTMI_PEER_PORT,
128d4afb5ceSopenharmony_ci}};
129d4afb5ceSopenharmony_ci```
130d4afb5ceSopenharmony_ci
131d4afb5ceSopenharmony_ci## Steps for adding new abstract protocols
132d4afb5ceSopenharmony_ci
133d4afb5ceSopenharmony_ci - add the public header in `./include/libwebsockets/abstract/protocols/`
134d4afb5ceSopenharmony_ci - add a directory under `./lib/abstract/protocols/`
135d4afb5ceSopenharmony_ci - add your protocol sources in the new directory
136d4afb5ceSopenharmony_ci - in CMakeLists.txt:
137d4afb5ceSopenharmony_ci   - add an `LWS_WITH_xxx` for your protocol
138d4afb5ceSopenharmony_ci   - search for "using any abstract protocol" and add your `LWS_WITH_xxx` to
139d4afb5ceSopenharmony_ci     the if so it also sets `LWS_WITH_ABSTRACT` if any set
140d4afb5ceSopenharmony_ci   - add a clause to append your source to SOURCES if `LWS_WITH_xxx` enabled
141d4afb5ceSopenharmony_ci - add your `lws_abs_protocol` to the list `available_abs_protocols` in
142d4afb5ceSopenharmony_ci   `./lib/abstract/abstract.c`
143d4afb5ceSopenharmony_ci
144d4afb5ceSopenharmony_ci## Steps for adding new abstract transports
145d4afb5ceSopenharmony_ci
146d4afb5ceSopenharmony_ci - add the public header in `./include/libwebsockets/abstract/transports/`
147d4afb5ceSopenharmony_ci - add your transport sources under `./lib/abstract/transports/`
148d4afb5ceSopenharmony_ci - in CMakeLists.txt append your transport sources to SOURCES if `LWS_WITH_ABSTRACT`
149d4afb5ceSopenharmony_ci   and any other cmake conditionals
150d4afb5ceSopenharmony_ci - add an extern for your transport `lws_protocols` in `./lib/core-net/private.h`
151d4afb5ceSopenharmony_ci - add your transport `lws_protocols` to `available_abstract_protocols` in
152d4afb5ceSopenharmony_ci   `./lib/core-net/vhost.c`
153d4afb5ceSopenharmony_ci - add your `lws_abs_transport` to the list `available_abs_transports` in
154d4afb5ceSopenharmony_ci   `./lib/abstract/abstract.c`
155d4afb5ceSopenharmony_ci
156d4afb5ceSopenharmony_ci# Protocol testing
157d4afb5ceSopenharmony_ci
158d4afb5ceSopenharmony_ci## unit tests
159d4afb5ceSopenharmony_ci
160d4afb5ceSopenharmony_cilws features an abstract transport designed to facilitate unit testing.  This
161d4afb5ceSopenharmony_cicontains an lws_sequencer that performs the steps of tests involving sending the
162d4afb5ceSopenharmony_ciprotocol test vector buffers and confirming the response of the protocol matches
163d4afb5ceSopenharmony_cithe test vectors.
164d4afb5ceSopenharmony_ci
165d4afb5ceSopenharmony_ci## test-sequencer
166d4afb5ceSopenharmony_ci
167d4afb5ceSopenharmony_citest-sequencer is a helper that sequences running an array of unit tests and
168d4afb5ceSopenharmony_cicollects the statistics and gives a PASS / FAIL result.
169d4afb5ceSopenharmony_ci
170d4afb5ceSopenharmony_ciSee the SMTP client api test for an example of how to use.
171