// разбор динамически создаваемого кода devctl(),
// извлечение из него длины принятого блока
unsigned int nbytes = (msg->i.dcmd - DCMD_SRR) >> 16;
msg->o.nbytes = nbytes;
// и тут же ретрансляция блока назад
return _RESMGR_PTR(ctp, &msg->i, sizeof(msg->i) + nbytes);
}
//---------------------------------------------------------
// установка однопоточного менеджера, выполняемая
// в отдельном потоке
static void* install(void* data) {
dispatch_t *dpp;
if ((dpp = dispatch_create()) == NULL)
exit("dispatch allocate");
resmgr_attr_t resmgr_attr;
memset(&resmgr_attr, 0, sizeof(resmgr_attr));
resmgr_attr.nparts_max = 1;
resmgr_attr.msg_max_size = 2048;
static resmgr_connect_funcs_t connect_funcs;
static resmgr_io_funcs_t io_funcs;
iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
_RESMGR_IO_NFUNCS, &io_funcs);
// определяем обработку, отличную от обработки по умолчанию,
// только для двух команд: read() & devctl()
io_funcs.read = &readfunc
io_funcs.devctl = &devctlfunc
static iofunc_attr_t attr;
iofunc_attr_init(&attr, S_IFNAM | 0666, 0, 0);
// связываем менеджер с его префиксным именем
if (resmgr_attach(dpp, &resmgr_attr, DEVNAME,
_FTYPE_ANY, 0, &connect_funcs, &io_funcs, &attr) == -1)
exit("prefix attach");
dispatch_context_t* ctp = dispatch_context_alloc(dpp);
while (true) {
if ((ctp = dispatch_block(ctp)) == NULL)
exit("block error");
dispatch_handler(ctp);
}
}
// размер буфера для обмена сообщениями,
// этого нам хватит с большим запасом и надолго ;)
const int blk = 100000;
// обработчик низкоуровневых сообщений,
// также работающий в отдельном потоке
void* msginout(void* с) {
static uint8_t bufin[blk];
struct _msg_info info;
while (true) {
int rcvid = MsgReceive(data chid, &bufin, blk, &info);
if (rcvid < 0) exit("message receive");
if (MsgReply(rcvid, EOK, &bufin, info.msglen) < 0)
exit("message reply");
}
}
//--------------------------------------------------------
// "пустой" обработчик реакции на ^C (сигнал SIGINT)
inline static void empty(int signo) {}
//--------------------------------------------------------
// главная программа, которая все это "хозяйство" установит
// и будет безропотно ждать завершения по ^C ;)
int main(int argc, char *argv[]) {
cout << "SRR server: " << VERSION << endl;
// открывается менеджер ресурса ...
int fd = open(DEVNAME, O_RDONLY);
// если менеджер открылся, то это нам не нужно -
// дубликаты не создавать!
if (fd > 0)
close(fd), cout << "already in use " << DEVNAME << endl, exit(EXIT_FAILURE);
// перехватываем реакцию ^C:
cout << ". . . . . . waiting ^C. . . . . ." << flush;