232 lines
6.4 KiB
C++
232 lines
6.4 KiB
C++
#include "ui.h"
|
|
|
|
#include "utils.h"
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// ipc class
|
|
namespace devui
|
|
{
|
|
class ui_messenger
|
|
{
|
|
std::function<void(LPMSGSTREAM)> cb_;
|
|
safe_fifo<std::string> 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<void(LPMSGSTREAM)> 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<void(LPMSGSTREAM)> 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;
|
|
}
|
|
};
|