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