1 /* 2 * lws System Message Distribution 3 * 4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25 #define LWS_SMD_MAX_PAYLOAD 384 26 #define LWS_SMD_CLASS_BITFIELD_BYTES 4 27 28 #define LWS_SMD_STREAMTYPENAME "_lws_smd" 29 #define LWS_SMD_SS_RX_HEADER_LEN 16 30 31 typedef uint32_t lws_smd_class_t; 32 33 struct lws_smd_msg; /* opaque */ 34 struct lws_smd_peer; /* opaque */ 35 36 /* 37 * Well-known device classes 38 */ 39 40 enum { 41 LWSSMDCL_INTERACTION = (1 << 0), 42 /**< 43 * Any kind of event indicating a user was interacting with the device, 44 * eg, press a button, touched the screen, lifted the device etc 45 */ 46 LWSSMDCL_SYSTEM_STATE = (1 << 1), 47 /**< 48 * The lws_system state changed, eg, to OPERATIONAL 49 */ 50 LWSSMDCL_NETWORK = (1 << 2), 51 /**< 52 * Something happened on the network, eg, link-up or DHCP, or captive 53 * portal state update 54 */ 55 LWSSMDCL_METRICS = (1 << 3), 56 /**< 57 * An SS client process is reporting a metric to the proxy (this class 58 * is special in that it is not rebroadcast by the proxy) 59 */ 60 61 LWSSMDCL_USER_BASE_BITNUM = 24 62 }; 63 64 /** 65 * lws_smd_msg_alloc() - allocate a message of length len 66 * 67 * \param ctx: the lws_context 68 * \param _class: the smd message class, recipients filter on this 69 * \param len: the required payload length 70 * 71 * This helper returns an opaque lws_smd_msg pointer and sets *buf to a buffer 72 * associated with it of length \p len. 73 * 74 * In this way the lws_msg_smd type remains completely opaque and the allocated 75 * area can be prepared by the caller directly, without copying. 76 * 77 * On failure, it returns NULL... it may fail for OOM but it may also fail if 78 * you request to allocate for a message class that the system has no 79 * participant who is listening for that class of event currently... the event 80 * generation action at the caller should be bypassed without error then. 81 * 82 * This is useful if you have a message you know the length of. For text-based 83 * messages like JSON, lws_smd_msg_printf() is more convenient. 84 */ 85 LWS_VISIBLE LWS_EXTERN void * /* payload */ 86 lws_smd_msg_alloc(struct lws_context *ctx, lws_smd_class_t _class, size_t len); 87 88 /** 89 * lws_smd_msg_free() - abandon a previously allocated message before sending 90 * 91 * \param payload: pointer the previously-allocated message payload 92 * 93 * Destroys a previously-allocated opaque message object and the requested 94 * buffer space, in the case that between allocating it and sending it, some 95 * condition was met that means it can no longer be sent, eg, an error 96 * generating the content. Otherwise there is no need to destroy allocated 97 * message objects with this, lws will take care of it. 98 */ 99 LWS_VISIBLE LWS_EXTERN void 100 lws_smd_msg_free(void **payload); 101 102 /** 103 * lws_smd_msg_send() - queue a previously allocated message 104 * 105 * \param ctx: the lws_context 106 * \param msg: the prepared message 107 * 108 * Queues an allocated, prepared message for delivery to smd clients 109 * 110 * This is threadsafe to call from a non-service thread. 111 */ 112 LWS_VISIBLE LWS_EXTERN int 113 lws_smd_msg_send(struct lws_context *ctx, void *payload); 114 115 /** 116 * lws_smd_msg_printf() - queue a previously allocated message 117 * 118 * \param ctx: the lws_context 119 * \param _class: the message class 120 * \param format: the format string to prepare the payload with 121 * \param ...: arguments for the format string, if any 122 * 123 * For string-based messages, eg, JSON, allows formatted creating of the payload 124 * size discovery, allocation and message send all in one step. 125 * 126 * Unlike lws_smd_msg_alloc() you do not need to know the length beforehand as 127 * this computes it and calls lws_smd_msg_alloc() with the correct length. 128 * 129 * To be clear this also calls through to lws_smd_msg_send(), it really does 130 * everything in one step. If there are no registered participants that want 131 * messages of \p _class, this function returns immediately without doing any 132 * allocation or anything else. 133 * 134 * This is threadsafe to call from a non-service thread. 135 */ 136 LWS_VISIBLE LWS_EXTERN int 137 lws_smd_msg_printf(struct lws_context *ctx, lws_smd_class_t _class, 138 const char *format, ...) LWS_FORMAT(3); 139 140 /** 141 * lws_smd_ss_msg_printf() - helper to prepare smd ss message tx 142 * 143 * \param h: the ss handle 144 * \param buf: the ss tx buffer 145 * \param len: on entry, points to the ss tx buffer length, on exit, set to used 146 * \param _class: the message class 147 * \param format: the format string to prepare the payload with 148 * \param ...: arguments for the format string, if any 149 * 150 * This helper lets you produce SMD messages on an SS link of the builtin 151 * streamtype LWS_SMD_STREAMTYPENAME, using the same api format as 152 * lws_smd_msg_prinf(), but writing the message into the ss tx buffer from 153 * its tx() callback. 154 */ 155 156 struct lws_ss_handle; 157 LWS_VISIBLE LWS_EXTERN int 158 lws_smd_ss_msg_printf(const char *tag, uint8_t *buf, size_t *len, 159 lws_smd_class_t _class, const char *format, ...) 160 LWS_FORMAT(5); 161 162 /** 163 * lws_smd_ss_rx_forward() - helper to forward smd messages that came in by SS 164 * 165 * \param ss_user: ss user pointer, as delivered to rx callback 166 * \param buf: the ss rx buffer 167 * \param len: the length of the ss rx buffer 168 * 169 * Proxied Secure Streams with the streamtype LWS_SMD_STREAMTYPENAME receive 170 * serialized SMD messages from the proxy, this helper allows them to be 171 * translated into deserialized SMD messages and forwarded to registered SMD 172 * participants in the local context in one step. 173 * 174 * Just pass through what arrived in the LWS_SMD_STREAMTYPENAME rx() callback 175 * to this api. 176 * 177 * Returns 0 if OK else nonzero if unable to queue the SMD message. 178 */ 179 LWS_VISIBLE LWS_EXTERN int 180 lws_smd_ss_rx_forward(void *ss_user, const uint8_t *buf, size_t len); 181 182 LWS_VISIBLE LWS_EXTERN int 183 lws_smd_sspc_rx_forward(void *ss_user, const uint8_t *buf, size_t len); 184 185 typedef int (*lws_smd_notification_cb_t)(void *opaque, lws_smd_class_t _class, 186 lws_usec_t timestamp, void *buf, 187 size_t len); 188 189 #define LWSSMDREG_FLAG_PROXIED_SS (1 << 0) 190 /**< It's actually a proxied SS connection registering, opaque is the ss h */ 191 192 /* 193 * lws_smd_register() - register to receive smd messages 194 * 195 * \param ctx: the lws_context 196 * \param opaque: an opaque pointer handed to the callback 197 * \param flags: typically 0 198 * \param _class_filter: bitmap of message classes we care about 199 * \param cb: the callback to receive messages 200 * 201 * Queues an allocated, prepared message for delivery to smd clients. 202 * 203 * Returns NULL on failure, or an opaque handle which may be given to 204 * lws_smd_unregister() to stop participating in the shared message queue. 205 * 206 * This is threadsafe to call from a non-service thread. 207 */ 208 209 LWS_VISIBLE LWS_EXTERN struct lws_smd_peer * 210 lws_smd_register(struct lws_context *ctx, void *opaque, int flags, 211 lws_smd_class_t _class_filter, lws_smd_notification_cb_t cb); 212 213 /* 214 * lws_smd_unregister() - unregister receiving smd messages 215 * 216 * \param pr: the handle returned from the registration 217 * 218 * Destroys the registration of the callback for messages and ability to send 219 * messages. 220 * 221 * It's not necessary to call this if the registration wants to survive for as 222 * long as the lws_context... lws_context_destroy will also clean up any 223 * registrations still active by then. 224 */ 225 226 LWS_VISIBLE LWS_EXTERN void 227 lws_smd_unregister(struct lws_smd_peer *pr); 228