/*********************************************************/
/* toksvc: a framework-native token broker service */
/* Copyright (C) 2020 Z. Gilboa */
/* Released under GPLv2 and GPLv3; see COPYING.TOKSVC. */
/*********************************************************/
#include <psxtypes/psxtypes.h>
#include <ntapi/ntapi.h>
#include <toksvc/toksvc.h>
#include "toksvc_daemon_impl.h"
#include "toksvc_driver_impl.h"
#include "toksvc_log_impl.h"
#define TOKS_VTBL_ELEMENTS TOKS_DAEMON_OPCODE_CAP - TOKS_DAEMON_OPCODE_BASE
#define TOKS_OPCODE_IDX(IDX) TOKS_DAEMON_ ## IDX - TOKS_DAEMON_OPCODE_BASE
#define TOKS_HANDLER(IDX,fn) [TOKS_OPCODE_IDX(IDX)] = fn
static toks_daemon_routine * toks_daemon_vtbl[TOKS_VTBL_ELEMENTS] = {
TOKS_HANDLER(CONNECT, toks_daemon_connect),
TOKS_HANDLER(TTYSIGNAL, toks_daemon_signal),
TOKS_HANDLER(ACQUIRE, toks_daemon_acquire),
TOKS_HANDLER(RELEASE, toks_daemon_release),
TOKS_HANDLER(CANCEL, toks_daemon_cancel),
TOKS_HANDLER(ABORT, toks_daemon_abort),
};
static toks_daemon_routine * toks_client_vtbl[TOKS_VTBL_ELEMENTS] = {
TOKS_HANDLER(CONNECT, toks_daemon_connect),
TOKS_HANDLER(TTYSIGNAL, toks_daemon_signal),
};
int32_t __stdcall toks_daemon_loop(void * ctx)
{
struct toks_daemon_ctx * dctx;
toks_daemon_routine ** svcvtbl;
nt_rtdata * rtdata;
nt_tty_port_msg * request;
nt_tty_port_msg * reply;
intptr_t port_id;
int32_t opcode;
if (ntapi->tt_get_runtime_data(&rtdata,0))
return NT_STATUS_INTERNAL_ERROR;
dctx = (struct toks_daemon_ctx *)ctx;
svcvtbl = (dctx->driver_ctx->cctx->drvflags & TOKS_DRIVER_MODE_SERVER)
? toks_daemon_vtbl
: toks_client_vtbl;
/* init */
request = &dctx->request;
reply = &dctx->reply;
ntapi->tt_aligned_block_memset(
request,0,sizeof(*request));
/* get first message */
ntapi->zw_reply_wait_receive_port(
dctx->hport_daemon,
&port_id,
0,(nt_port_message *)request);
/* message loop */
do {
switch (request->header.msg_type) {
case NT_LPC_REQUEST:
case NT_LPC_DATAGRAM:
opcode = request->ttyinfo.opcode;
break;
case NT_LPC_CONNECTION_REQUEST:
opcode = TOKS_DAEMON_CONNECT;
break;
default:
opcode = -1;
break;
}
/* dispatch */
dctx->opcode = opcode;
request->ipcinfo.ctrlsvc.keys.padding = 0;
if (svcvtbl == toks_daemon_vtbl)
toks_log_lpc_request(
dctx,request);
ntapi->tt_aligned_block_memcpy(
(uintptr_t *)reply,
(uintptr_t *)request,
sizeof(*reply));
reply->header.msg_type = NT_LPC_REPLY;
if ((opcode >= TOKS_DAEMON_OPCODE_BASE) && (opcode < TOKS_DAEMON_OPCODE_CAP)) {
reply->ttyinfo.exarg = (void *)request->header.client_id.process_id;
opcode -= TOKS_DAEMON_OPCODE_BASE;
if (svcvtbl[opcode])
reply->ttyinfo.status = svcvtbl[opcode](dctx);
else
reply->ttyinfo.status = NT_STATUS_NOT_IMPLEMENTED;
} else {
reply->ttyinfo.exarg = NT_INVALID_HANDLE_VALUE;
reply->ttyinfo.status = NT_STATUS_LPC_INVALID_CONNECTION_USAGE;
}
if (svcvtbl == toks_daemon_vtbl)
toks_log_lpc_reply(
dctx,reply);
ntapi->tt_aligned_block_memset(
request,0,sizeof(*request));
if (!reply->ttyinfo.exarg)
ntapi->zw_reply_wait_receive_port(
dctx->hport_daemon,
&port_id,
0,&request->header);
else if (reply->header.client_id.process_id == rtdata->cid_self.process_id)
ntapi->zw_reply_wait_receive_port(
dctx->hport_daemon,
&port_id,
&reply->header,
&request->header);
else {
ntapi->zw_reply_port(
dctx->hport_daemon,
&reply->header);
ntapi->zw_reply_wait_receive_port(
dctx->hport_daemon,
&port_id,
0,&request->header);
}
} while (request->header.msg_id);
return NT_STATUS_INTERNAL_ERROR;
}