skip to content
==> src/reply.c <==
1/* One-shot replies over mesh_chan. */
2#include "mesh/reply.h"
3#include "mesh/buf.h"
4
5#include <stdarg.h>
6#include <stdlib.h>
7#include <string.h>
8
9static void drop_result(void *p) { mesh_result_free(p); }
10
11mesh_reply *mesh_reply_new(void) { return mesh_chan_new(sizeof(mesh_result), 0, drop_result); }
12
13mesh_reply *mesh_reply_sender(mesh_reply *r) {
14    mesh_chan_retain(r);
15    return r;
16}
17
18mesh_reply *mesh_reply_clone(mesh_reply *r) {
19    mesh_chan_retain(r);
20    mesh_chan_add_sender(r);
21    return r;
22}
23
24void mesh_reply_send(mesh_reply *r, mesh_result res) {
25    if (!r) { mesh_result_free(&res); return; }
26    if (mesh_chan_send(r, &res) != MESH_CHAN_OK) mesh_result_free(&res);
27    mesh_chan_drop_sender(r);
28    mesh_chan_release(r);
29}
30
31void mesh_reply_drop(mesh_reply *r) {
32    if (!r) return;
33    mesh_chan_drop_sender(r);
34    mesh_chan_release(r);
35}
36
37mesh_result mesh_result_ok(const char *text) {
38    mesh_result x = {true, 0, mesh_xstrdup(text ? text : ""), NULL, 0, NULL, NULL};
39    return x;
40}
41
42mesh_result mesh_result_err(const char *text) {
43    mesh_result x = {false, 0, mesh_xstrdup(text ? text : ""), NULL, 0, NULL, NULL};
44    return x;
45}
46
47mesh_result mesh_result_copy(const mesh_result *r) {
48    mesh_result x = *r;
49    x.ptr = NULL;
50    x.ptr_free = NULL;
51    if (r->text) x.text = mesh_xstrdup(r->text);
52    if (r->bytes) {
53        x.bytes = mesh_xmalloc(r->len);
54        memcpy(x.bytes, r->bytes, r->len);
55    }
56    return x;
57}
58
59void mesh_reply_ok(mesh_reply *r, const char *text) { mesh_reply_send(r, mesh_result_ok(text)); }
60void mesh_reply_err(mesh_reply *r, const char *text) { mesh_reply_send(r, mesh_result_err(text)); }
61
62void mesh_reply_okf(mesh_reply *r, const char *fmt, ...) {
63    mesh_buf b = MESH_BUF_INIT;
64    va_list ap;
65    va_start(ap, fmt);
66    mesh_buf_vprintf(&b, fmt, ap);
67    va_end(ap);
68    mesh_result x = {true, 0, mesh_buf_take(&b), NULL, 0, NULL, NULL};
69    mesh_reply_send(r, x);
70}
71
72void mesh_reply_errf(mesh_reply *r, const char *fmt, ...) {
73    mesh_buf b = MESH_BUF_INIT;
74    va_list ap;
75    va_start(ap, fmt);
76    mesh_buf_vprintf(&b, fmt, ap);
77    va_end(ap);
78    mesh_result x = {false, 0, mesh_buf_take(&b), NULL, 0, NULL, NULL};
79    mesh_reply_send(r, x);
80}
81
82void mesh_reply_value(mesh_reply *r, uint32_t v) {
83    mesh_result x = {true, v, NULL, NULL, 0, NULL, NULL};
84    mesh_reply_send(r, x);
85}
86
87void mesh_reply_bytes(mesh_reply *r, const void *p, size_t n) {
88    mesh_result x = {true, 0, NULL, mesh_xmalloc(n), n, NULL, NULL};
89    if (n) memcpy(x.bytes, p, n);
90    mesh_reply_send(r, x);
91}
92
93void mesh_reply_ptr(mesh_reply *r, void *ptr, void (*ptr_free)(void *ptr)) {
94    mesh_result x = {true, 0, NULL, NULL, 0, ptr, ptr_free};
95    mesh_reply_send(r, x);
96}
97
98int mesh_reply_wait(mesh_reply *r, int64_t timeout_ms, mesh_result *out) {
99    memset(out, 0, sizeof *out);
100    return mesh_chan_recv(r, out, timeout_ms);
101}
102
103int mesh_reply_poll(mesh_reply *r, mesh_result *out) {
104    memset(out, 0, sizeof *out);
105    return mesh_chan_try_recv(r, out);
106}
107
108void mesh_reply_release(mesh_reply *r) {
109    if (!r) return;
110    mesh_chan_close_rx(r);
111    mesh_chan_release(r);
112}
113
114void mesh_result_free(mesh_result *r) {
115    free(r->text);
116    free(r->bytes);
117    if (r->ptr && r->ptr_free) r->ptr_free(r->ptr);
118    r->ptr = NULL;
119    r->text = NULL;
120    r->bytes = NULL;
121    r->len = 0;
122}