==> 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}