#include namespace mesytec::mnode::nng { static void work_callback(void *arg) { reinterpret_cast(arg)->work();; } AsyncReqWork::AsyncReqWork(nng_socket socket) : socket(socket) , request_(nng::make_unique_msg()) { } AsyncReqWork::~AsyncReqWork() { nng_ctx_close(ctx); nng_aio_free(aio); } void AsyncReqWork::work() { switch (state) { case INIT: nng_aio_alloc(&aio, work_callback, this); nng_ctx_open(&ctx, socket); state = SEND; request_ = make_request(); nng_aio_set_msg(aio, nng::clone_message(request_.get()).release()); nng_ctx_send(ctx, aio); break; case SEND: if (auto rv = nng_aio_result(aio)) { nng::mnode_nng_error("nng_ctx_send", rv); nng::make_unique_msg(nng_aio_get_msg(aio)).reset(); state = SEND; request_ = make_request(); nng_aio_set_msg(aio, nng::clone_message(request_.get()).release()); nng_ctx_send(ctx, aio); } else { state = RECEIVE; nng_ctx_recv(ctx, aio); } break; case RECEIVE: if (auto rv = nng_aio_result(aio)) { nng::mnode_nng_error("nng_ctx_recv", rv); state = SEND; request_ = make_request(); nng_aio_set_msg(aio, nng::clone_message(request_.get()).release()); nng_ctx_send(ctx, aio); } else { auto reply = nng::make_unique_msg(nng_aio_get_msg(aio)); handle_reply(std::move(request_), std::move(reply)); state = SEND; request_ = make_request(); nng_aio_set_msg(aio, nng::clone_message(request_.get()).release()); nng_ctx_send(ctx, aio); } break; } } AsyncRepWork::AsyncRepWork(nng_socket socket) : socket(socket) { } AsyncRepWork::~AsyncRepWork() { nng_ctx_close(ctx); nng_aio_free(aio); } void AsyncRepWork::work() { switch (state) { case INIT: nng_aio_alloc(&aio, work_callback, this); nng_ctx_open(&ctx, socket); state = RECEIVE; nng_ctx_recv(ctx, aio); break; case RECEIVE: if (auto rv = nng_aio_result(aio)) { if (rv != NNG_ETIMEDOUT) nng::mnode_nng_error("nng_ctx_recv", rv); state = RECEIVE; nng_ctx_recv(ctx, aio); break; } else { auto reply = handle_request(nng::make_unique_msg(nng_aio_get_msg(aio))); nng_aio_set_msg(aio, reply.release()); state = SEND; nng_ctx_send(ctx, aio); } break; case SEND: if (auto rv = nng_aio_result(aio)) { nng::mnode_nng_error("nng_ctx_send", rv); nng::make_unique_msg(nng_aio_get_msg(aio)).reset(); } state = RECEIVE; nng_ctx_recv(ctx, aio); break; } } }