• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# `lws_system`
2
3See `include/libwebsockets/lws-system.h` for function and object prototypes.
4
5## System integration api
6
7`lws_system` allows you to set a `system_ops` struct at context creation time,
8which can write up some function callbacks for system integration.  The goal
9is the user code calls these by getting the ops struct pointer from the
10context using `lws_system_get_ops(context)` and so does not spread system
11dependencies around the user code, making it directly usable on completely
12different platforms.
13
14```
15typedef struct lws_system_ops {
16	int (*reboot)(void);
17	int (*set_clock)(lws_usec_t us);
18	int (*attach)(struct lws_context *context, int tsi, lws_attach_cb_t cb,
19		      lws_system_states_t state, void *opaque,
20		      struct lws_attach_item **get);
21} lws_system_ops_t;
22```
23
24|Item|Meaning|
25|---|---|
26|`(*reboot)()`|Reboot the system|
27|`(*set_clock)()`|Set the system clock|
28|`(*attach)()`|Request an event loop callback from another thread context|
29
30### `reboot`
31
32Reboots the device
33
34### `set_clock`
35
36Set the system clock to us-resolution Unix time in seconds
37
38### `attach`
39
40Request a callback from the event loop from a foreign thread.  This is used, for
41example, for foreign threads to set up their event loop activity in their
42callback, and eg, exit once it is done, with their event loop activity able to
43continue wholly from the lws event loop thread and stack context.
44
45## Foreign thread `attach` architecture
46
47When lws is started, it should define an `lws_system_ops_t` at context creation
48time which defines its `.attach` handler.  In the `.attach` handler
49implementation, it should perform platform-specific locking around a call to
50`__lws_system_attach()`, a public lws api that actually queues the callback
51request and does the main work.  The platform-specific wrapper is just there to
52do the locking so multiple calls from different threads to the `.attach()`
53operation can't conflict.
54
55User code can indicate it wants a callback from the lws event loop like this:
56
57```
58lws_system_get_ops(context)->attach(context, tsi, cb, state, opaque, NULL)
59```
60
61`context` is a pointer to the lws_context, `tsi` is normally 0, `cb` is the user
62callback in the form
63
64```
65void (*lws_attach_cb_t)(struct lws_context *context, int tsi, void *opaque);
66```
67
68`state` is the `lws_system` state we should have reached before performing the
69callback (usually, `LWS_SYSTATE_OPERATIONAL`), and `opaque` is a user pointer that
70will be passed into the callback.
71
72`cb` will normally want to create scheduled events and set up lws network-related
73activity from the event loop thread and stack context.
74
75Once the event loop callback has been booked by calling this api, the thread and
76its stack context that booked it may be freed.  It will be called back and can
77continue operations from the lws event loop thread and stack context.  For that
78reason, if `opaque` is needed it will usually point to something on the heap,
79since the stack context active at the time the callback was booked may be long
80dead by the time of the callback.
81
82See ./lib/system/README.md for more details.
83
84## `lws_system` blobs
85
86"Blobs" are arbitrary binary objects that have a total length.  Lws lets you set
87them in two ways
88
89 - "directly", by pointing to them, which has no heap implication
90
91 - "heap", by adding one or more arbitrary chunk to a chained heap object
92
93In the "heap" case, it can be incrementally defined and the blob doesn't all
94have to be declared at once.
95
96For read, the same api allows you to read all or part of the blob into a user
97buffer.
98
99The following kinds of blob are defined
100
101|Item|Meaning|
102|---|---|
103|`LWS_SYSBLOB_TYPE_AUTH`|Auth-related blob 1, typically a registration token|
104|`LWS_SYSBLOB_TYPE_AUTH + 1`|Auth-related blob 2, typically an auth token|
105|`LWS_SYSBLOB_TYPE_CLIENT_CERT_DER`|Client cert public part|
106|`LWS_SYSBLOB_TYPE_CLIENT_KEY_DER`|Client cert key part|
107|`LWS_SYSBLOB_TYPE_DEVICE_SERIAL`|Arbitrary device serial number|
108|`LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION`|Arbitrary firmware version|
109|`LWS_SYSBLOB_TYPE_DEVICE_TYPE`|Arbitrary Device Type identifier|
110|`LWS_SYSBLOB_TYPE_NTP_SERVER`|String with the ntp server address (defaults to pool.ntp.org)|
111
112### Blob handle api
113
114Returns an object representing the blob for a particular type (listed above)
115
116```
117lws_system_blob_t *
118lws_system_get_blob(struct lws_context *context, lws_system_blob_item_t type,
119                    int idx);
120```
121
122### Blob Setting apis
123
124Sets the blob to point length `len` at `ptr`.  No heap allocation is used.
125
126```
127void
128lws_system_blob_direct_set(lws_system_blob_t *b, const uint8_t *ptr, size_t len);
129```
130
131Allocates and copied `len` bytes from `buf` into heap and chains it on the end of
132any existing.
133
134```
135int
136lws_system_blob_heap_append(lws_system_blob_t *b, const uint8_t *buf, size_t len)
137```
138
139Remove any content from the blob, freeing it if it was on the heap
140
141```
142void
143lws_system_blob_heap_empty(lws_system_blob_t *b)
144```
145
146### Blob getting apis
147
148Get the total size of the blob (ie, if on the heap, the aggreate size of all the
149chunks that were appeneded)
150
151```
152size_t
153lws_system_blob_get_size(lws_system_blob_t *b)
154```
155
156Copy part or all of the blob starting at offset ofs into a user buffer at buf.
157`*len` should be the length of the user buffer on entry, on exit it's set to
158the used extent of `buf`.  This works the same whether the bob is a direct pointer
159or on the heap.
160
161```
162int
163lws_system_blob_get(lws_system_blob_t *b, uint8_t *buf, size_t *len, size_t ofs)
164```
165
166If you know that the blob was handled as a single direct pointer, or a single
167allocation, you can get a pointer to it without copying using this.
168
169```
170int
171lws_system_blob_get_single_ptr(lws_system_blob_t *b, const uint8_t **ptr)
172```
173
174### Blob destroy api
175
176Deallocates any heap allocation for the blob
177
178```
179void
180lws_system_blob_destroy(lws_system_blob_t *b)
181```
182
183
184## System state and notifiers
185
186Lws implements a state in the context that reflects the readiness of the system
187for various steps leading up to normal operation.  By default it acts in a
188backwards-compatible way and directly reaches the OPERATIONAL state just after
189the context is created.
190
191However other pieces of lws, and user, code may define notification handlers
192that get called back when the state changes incrementally, and may veto or delay
193the changes until work necessary for the new state has completed asynchronously.
194
195The generic states defined are:
196
197|State|Meaning|
198|---|---|
199|`LWS_SYSTATE_CONTEXT_CREATED`|The context was just created.|
200|`LWS_SYSTATE_INITIALIZED`|The vhost protocols have been initialized|
201|`LWS_SYSTATE_IFACE_COLDPLUG`|Existing network interfaces have been iterated|
202|`LWS_SYSTATE_DHCP`|Network identity is available|
203|`LWS_SYSTATE_TIME_VALID`|The system knows the time|
204|`LWS_SYSTATE_POLICY_VALID`|If the system needs information about how to act from the net, it has it|
205|`LWS_SYSTATE_REGISTERED`|The device has a registered identity|
206|`LWS_SYSTATE_AUTH1`|The device identity has produced a time-limited access token|
207|`LWS_SYSTATE_AUTH2`|Optional second access token for different services|
208|`LWS_SYSTATE_OPERATIONAL`|The system is ready for user code to work normally|
209|`LWS_SYSTATE_POLICY_INVALID`|All connections are being dropped because policy information is changing.  It will transition back to `LWS_SYSTATE_INITIALIZED` and onward to `OPERATIONAL` again afterwards with the new policy|
210|`LWS_SYSTATE_CONTEXT_DESTROYING`|Context is going down and smd with it|
211
212### Inserting a notifier
213
214You should create an object `lws_system_notify_link_t` in non-const memory and zero it down.
215Set the `notify_cb` member and the `name` member and then register it using either
216`lws_system_reg_notifier()` or the `.register_notifier_list`
217member of the context creation info struct to make sure it will exist early
218enough to see all events.  The context creation info method takes a list of
219pointers to notify_link structs ending with a NULL entry.
220
221