components/websocket/include/websocket.h

Mon, 19 Feb 2024 15:07:28 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 19 Feb 2024 15:07:28 +0100
changeset 128
64886971967b
parent 30
3cc32f97410c
permissions
-rw-r--r--

Fix current year display

/**
 * @file websocket.h
 * @brief Websocket functions.
 * @author Blake Felt - blake.w.felt@gmail.com`
 */


#ifdef __cplusplus
extern "C" {
#endif

#ifndef WEBSOCKET_H
#define WEBSOCKET_H

#include "lwip/api.h"


/**
 * @brief the different codes for the callbacks
 */
typedef enum {
  WEBSOCKET_CONNECT,			///< Connect
  WEBSOCKET_DISCONNECT_EXTERNAL, 	///< the other side disconnected
  WEBSOCKET_DISCONNECT_INTERNAL, 	///< the esp32 disconnected
  WEBSOCKET_DISCONNECT_ERROR, 		///< disconnect due to error
  WEBSOCKET_TEXT,			///< Text message
  WEBSOCKET_BIN,			///< Binary message
  WEBSOCKET_PING,			///< PING message
  WEBSOCKET_PONG			///< PONG message
} WEBSOCKET_TYPE_t;



/**
 * @brief websocket operation codes
 */
typedef enum {
  WEBSOCKET_OPCODE_CONT  = 0x0,		///< Continue
  WEBSOCKET_OPCODE_TEXT  = 0x1,		///< Text
  WEBSOCKET_OPCODE_BIN   = 0x2,		///< Binary
  WEBSOCKET_OPCODE_CLOSE = 0x8,		///< Close connection
  WEBSOCKET_OPCODE_PING  = 0x9,		///< PING message
  WEBSOCKET_OPCODE_PONG  = 0xA		///< PONG message
} WEBSOCKET_OPCODES_t;


/**
 * @brief the header, useful for creating and quickly passing to functions
 */
typedef struct {
  union {
    struct {
      uint16_t LEN:7;     		///< bits 0..  6
      uint16_t MASK:1;    		///< bit  7
      uint16_t OPCODE:4;  		///< bits 8..  11
      uint16_t :3;        		///< bits 12.. 14 reserved
      uint16_t FIN:1;     		///< bit  15
    } bit;
    struct {
      uint16_t ONE:8;     		///< bits 0..  7
      uint16_t ZERO:8;    		///< bits 8..  15
    } pos;
  } param; 				///< the initial parameters of the header
  uint64_t length; 			///< actual message length
  union {
    char part[4]; 			///< the mask, array
    uint32_t full; 			///< the mask, all 32 bits
  } key; 				///< masking key
  bool received; 			///< was a message successfully received?
} ws_header_t;


/**
 * @brief A client, with space for a server callback or a client callback (depending on use)
 */
typedef struct {
  struct netconn* conn; 		///< the connection
  bool connected;			///< connection state
  char* url;            		///< the associated url,  null terminated
  char* protocol;			///< the associated protocol, null terminated
  bool ping;            		///< did we send a ping?
  WEBSOCKET_OPCODES_t last_opcode; 	///< the previous opcode
  char* contin;         		///< any continuation piece
  bool contin_text;     		///< is the continue a binary or text?
  uint64_t len;         		///< length of continuation
  uint32_t unfinished;      		///< sometimes netconn doesn't read a full frame, treated similarly to a continuation frame
  void (*ccallback)(WEBSOCKET_TYPE_t type,char* msg,uint64_t len); 		///< client callback
  void (*scallback)(uint8_t num,WEBSOCKET_TYPE_t type,char* msg,uint64_t len); 	///< server callback
} ws_client_t;


/**
 * @brief returns the populated client struct
 *        does not send any header, assumes the proper handshake has already occurred
 * @param conn The network connection
 * @param url The connection url.
 * @param ccallback  callback for client (userspace)
 * @param scallback  callback for server (userspace)
 * @return The Websocket client structure.
 */
ws_client_t ws_connect_client(struct netconn* conn,
                              char* url,
                              void (*ccallback)(WEBSOCKET_TYPE_t type,char* msg,uint64_t len),
                              void (*scallback)(uint8_t num,WEBSOCKET_TYPE_t type,char* msg,uint64_t len)
                             );


/**
 * @brief Disconnect a websocket client.
 * @param client The ws_client_t structure with the client information.
 */
void ws_disconnect_client(ws_client_t* client);

/**
 * @brief Test if the client is connected.
 *        status updates after send/read/connect/disconnect.
 * @param client The ws_client_t structure with the client information.
 * @return True if connected, false if not.
 */
bool ws_is_connected(ws_client_t client);

/**
 * @brief Send data via websocjet to a client. This function performs the masking.
 * @param client The ws_client_t structure with the client information.
 * @param opcode The opcode to send the message.
 * @param msg The message itself.
 * @param len The length of the message.
 * @param mask Encrypt??
 * @return error code or ERR_OK
 */
err_t ws_send(ws_client_t* client,WEBSOCKET_OPCODES_t opcode,char* msg,uint64_t len,bool mask);

/**
 * @brief Receive a message from a websocket connection.
 * @param client The ws_client_t structure with the client information.
 * @param header unmasks and returns message. populates header.
 * @return Unmasks and returns message. populates header.
 */
char* ws_read(ws_client_t* client,ws_header_t* header);

/**
 * @brief Create a handshake hashed string.
 * @param key The key for the hash.
 * @param len The length.
 * @return The string of output.
 */
char* ws_hash_handshake(char* key,uint8_t len);

#endif // ifndef WEBSOCKET_H

#ifdef __cplusplus
}
#endif

mercurial