1/* 2 * lws-minimal-raw-file 3 * 4 * Written in 2010-2019 by Andy Green <andy@warmcat.com> 5 * 6 * This file is made available under the Creative Commons CC0 1.0 7 * Universal Public Domain Dedication. 8 * 9 * This demonstrates adopting a file descriptor into the lws event 10 * loop. 11 */ 12 13#include <libwebsockets.h> 14#include <string.h> 15#include <signal.h> 16#include <sys/types.h> 17#include <sys/stat.h> 18#include <fcntl.h> 19 20struct raw_vhd { 21// lws_sock_file_fd_type u; 22 int filefd; 23}; 24 25static char filepath[256]; 26 27static int 28callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, 29 void *user, void *in, size_t len) 30{ 31 struct raw_vhd *vhd = (struct raw_vhd *)lws_protocol_vh_priv_get( 32 lws_get_vhost(wsi), lws_get_protocol(wsi)); 33 lws_sock_file_fd_type u; 34 uint8_t buf[1024]; 35 int n; 36 37 switch (reason) { 38 case LWS_CALLBACK_PROTOCOL_INIT: 39 vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), 40 lws_get_protocol(wsi), sizeof(struct raw_vhd)); 41 vhd->filefd = lws_open(filepath, O_RDWR); 42 if (vhd->filefd == -1) { 43 lwsl_err("Unable to open %s\n", filepath); 44 45 return 1; 46 } 47 u.filefd = (lws_filefd_type)(long long)vhd->filefd; 48 if (!lws_adopt_descriptor_vhost(lws_get_vhost(wsi), 49 LWS_ADOPT_RAW_FILE_DESC, u, 50 "raw-test", NULL)) { 51 lwsl_err("Failed to adopt fifo descriptor\n"); 52 close(vhd->filefd); 53 vhd->filefd = -1; 54 55 return 1; 56 } 57 break; 58 59 case LWS_CALLBACK_PROTOCOL_DESTROY: 60 if (vhd && vhd->filefd != -1) 61 close(vhd->filefd); 62 break; 63 64 /* callbacks related to raw file descriptor */ 65 66 case LWS_CALLBACK_RAW_ADOPT_FILE: 67 lwsl_notice("LWS_CALLBACK_RAW_ADOPT_FILE\n"); 68 break; 69 70 case LWS_CALLBACK_RAW_RX_FILE: 71 lwsl_notice("LWS_CALLBACK_RAW_RX_FILE\n"); 72 n = (int)read(vhd->filefd, buf, sizeof(buf)); 73 if (n < 0) { 74 lwsl_err("Reading from %s failed\n", filepath); 75 76 return 1; 77 } 78 lwsl_hexdump_level(LLL_NOTICE, buf, (unsigned int)n); 79 break; 80 81 case LWS_CALLBACK_RAW_CLOSE_FILE: 82 lwsl_notice("LWS_CALLBACK_RAW_CLOSE_FILE\n"); 83 break; 84 85 case LWS_CALLBACK_RAW_WRITEABLE_FILE: 86 lwsl_notice("LWS_CALLBACK_RAW_WRITEABLE_FILE\n"); 87 /* 88 * you can call lws_callback_on_writable() on a raw file wsi as 89 * usual, and then write directly into the raw filefd here. 90 */ 91 break; 92 93 default: 94 break; 95 } 96 97 return 0; 98} 99 100static struct lws_protocols protocols[] = { 101 { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 }, 102 LWS_PROTOCOL_LIST_TERM 103}; 104 105static int interrupted; 106 107void sigint_handler(int sig) 108{ 109 interrupted = 1; 110} 111 112int main(int argc, const char **argv) 113{ 114 struct lws_context_creation_info info; 115 struct lws_context *context; 116 const char *p; 117 int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE 118 /* for LLL_ verbosity above NOTICE to be built into lws, 119 * lws must have been configured and built with 120 * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ 121 /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ 122 /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ 123 /* | LLL_DEBUG */; 124 125 signal(SIGINT, sigint_handler); 126 127 if ((p = lws_cmdline_option(argc, argv, "-d"))) 128 logs = atoi(p); 129 130 lws_set_log_level(logs, NULL); 131 lwsl_user("LWS minimal raw file\n"); 132 if (argc < 2) { 133 lwsl_user("Usage: %s <file to monitor> " 134 " eg, /dev/ttyUSB0 or /dev/input/event0 or " 135 "/proc/self/fd/0\n", argv[0]); 136 137 return 1; 138 } 139 140 signal(SIGINT, sigint_handler); 141 142 memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ 143 info.port = CONTEXT_PORT_NO_LISTEN_SERVER; /* no listen socket for demo */ 144 info.protocols = protocols; 145 146 lws_strncpy(filepath, argv[1], sizeof(filepath)); 147 148 context = lws_create_context(&info); 149 if (!context) { 150 lwsl_err("lws init failed\n"); 151 return 1; 152 } 153 154 while (n >= 0 && !interrupted) 155 n = lws_service(context, 0); 156 157 lws_context_destroy(context); 158 159 return 0; 160} 161