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