#include "ui.h" #include "utils.h" #include #include #include #include ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ipc class namespace devui { class ui_messenger { std::function cb_; safe_fifo sent_que_; volatile bool run_ = true; bool ui_; bool ready_ = true; safe_thread workers_; int fdo_ = -1; int fdi_ = -1; std::string fmode(int m) { if(m == O_RDONLY) return "O_RDONLY"; if(m == O_WRONLY) return "O_WRONLY"; return "Unk"; } void init(void) { const char* fifo[] = {"/tmp/worker", "/tmp/ui"}; int mode[] = {O_RDONLY, O_WRONLY}; int *fd[] = {&fdi_, &fdo_}; if(ui_) { mkfifo(fifo[!ui_], 0777); mkfifo(fifo[ui_], 0777); fdo_ = open(fifo[1], mode[1]); fdi_ = open(fifo[0], mode[0]); } else { fdi_ = open(fifo[1], mode[0]); fdo_ = open(fifo[0], mode[1]); } if(fdo_ == -1 || fdi_ == -1) { printf("Out fd = %d, In fd = %d\n", fdo_, fdi_); this->close(); } else { auto r = [this](void) -> void { receiver(); }; auto s = [this](void) -> void { sender(); }; workers_.start(r, "receiver"); workers_.start(s, "sender"); } } void close(void) { ready_ = false; if(fdo_ != -1) ::close(fdo_); if(fdi_ != -1) ::close(fdi_); fdi_ = fdo_ = -1; } void receiver(void) { std::string rcv(""); char buf[300] = {0}; LPMSGSTREAM pack = nullptr; printf("ui-receiver running ...\n"); while(run_) { int r = read(fdi_, buf, _countof(buf)); if(r == -1) { printf("Read UI message failed: %d(%s)\n", errno, strerror(errno)); utils::to_log(LOG_LEVEL_FATAL, "Read UI message failed: %d(%s)\n", errno, strerror(errno)); this->close(); break; } if(rcv.length()) { rcv += std::string(buf, r); pack = (LPMSGSTREAM)&rcv[0]; if(pack->whole_size() <= rcv.length()) { cb_(pack); rcv.erase(0, pack->whole_size()); } } else { int off = 0; pack = (LPMSGSTREAM)buf; if(pack->whole_size() <= r) { cb_(pack); off = pack->whole_size(); } if(off < r) { rcv = std::string(buf + off, r - off); } } } printf("ui-receiver exited.\n"); } void sender(void) { printf("ui-sender running ...\n"); while(run_) { std::string cont(""); if(sent_que_.take(cont, true)) { int s = 0, off = 0; do { s = write(fdo_, cont.c_str() + off, cont.length() - off); if(s == -1) { printf("Send UI message failed: %d(%s)\n", errno, strerror(errno)); utils::to_log(LOG_LEVEL_FATAL, "Send UI message failed: %d(%s)\n", errno, strerror(errno)); this->close(); break; } off += s; }while(off < cont.length()); if(s == -1) break; } } printf("ui-sender exited.\n"); } public: ui_messenger(std::function uicb , bool ui) : sent_que_("ui-sent-que") , cb_(uicb), ui_(ui) { sent_que_.enable_wait_log(false); init(); } ~ui_messenger() { close(); } public: bool send(std::string& msg) { if(ready_) sent_que_.save(msg, true); return ready_; } void stop(void) { sent_que_.trigger(); run_ = false; this->close(); } }; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // interface static MUTEX msg_lk_; static devui::ui_messenger *msgr = nullptr; namespace devui { void init_ui(std::function uicb, bool ui) { SIMPLE_LOCK(msg_lk_); if(!msgr) msgr = new ui_messenger(uicb, ui); } void uninit_ui(void) { SIMPLE_LOCK(msg_lk_); if(msgr) { msgr->stop(); delete msgr; } msgr = nullptr; } bool send_message(uint32_t msgid, uint8_t* data, uint8_t size) { std::string stream(""); MSGSTREAM pack; bool ret = false; memset(&pack, 0, sizeof(pack)); pack.ver = 1; pack.msg = msgid; pack.size = size; if(size) pack.data[0] = data[0]; stream = std::string((char*)&pack, sizeof(pack)); if(size > 1) stream += std::string((char*)data + 1, size - 1); { SIMPLE_LOCK(msg_lk_); if(msgr) ret = msgr->send(stream); } return ret; } };