1/*
2 * msg.h
3 *
4 * Copyright (C) 2008-2018 Aerospike, Inc.
5 *
6 * Portions may be licensed to Aerospike, Inc. under one or more contributor
7 * license agreements.
8 *
9 * This program is free software: you can redistribute it and/or modify it under
10 * the terms of the GNU Affero General Public License as published by the Free
11 * Software Foundation, either version 3 of the License, or (at your option) any
12 * later version.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see http://www.gnu.org/licenses/
21 */
22
23#pragma once
24
25#include <stdarg.h>
26#include <stdbool.h>
27#include <stddef.h>
28#include <stdint.h>
29#include <sys/socket.h>
30
31#include "citrusleaf/cf_atomic.h"
32#include "citrusleaf/cf_vector.h"
33
34#include "dynbuf.h"
35
36
37//==========================================================
38// Typedefs & constants.
39//
40
41// These values are used on the wire - don't change them.
42typedef enum {
43 M_FT_UINT32 = 1,
44 M_FT_UNUSED_2 = 2,
45 M_FT_UINT64 = 3,
46 M_FT_UNUSED_4 = 4,
47 M_FT_STR = 5,
48 M_FT_BUF = 6,
49 M_FT_ARRAY_UINT32 = 7,
50 M_FT_ARRAY_UINT64 = 8,
51 M_FT_ARRAY_BUF = 9,
52 M_FT_ARRAY_STR = 10,
53 M_FT_MSGPACK = 11
54} msg_field_type; // encoded in uint8_t
55
56// These values are used on the wire - don't change them.
57typedef enum {
58 M_TYPE_FABRIC = 0,
59 M_TYPE_HEARTBEAT_V2 = 1,
60 M_TYPE_PAXOS = 2,
61 M_TYPE_MIGRATE = 3,
62 M_TYPE_PROXY = 4,
63 M_TYPE_HEARTBEAT = 5,
64 M_TYPE_CLUSTERING = 6,
65 M_TYPE_RW = 7,
66 M_TYPE_INFO = 8,
67 M_TYPE_EXCHANGE = 9,
68 M_TYPE_APPEAL = 10,
69 M_TYPE_XDR = 11,
70 M_TYPE_UNUSED_12 = 12,
71 M_TYPE_UNUSED_13 = 13,
72 M_TYPE_UNUSED_14 = 14,
73 M_TYPE_SMD = 15,
74 M_TYPE_UNUSED_16 = 16,
75 M_TYPE_UNUSED_17 = 17,
76 M_TYPE_MAX = 18
77} msg_type; // encoded in uint16_t
78
79typedef struct msg_template_s {
80 uint16_t id;
81 msg_field_type type;
82} msg_template;
83
84struct msg_str_array_s;
85struct msg_buf_array_s;
86
87typedef struct msg_field_s {
88 uint16_t id;
89 bool is_set;
90 bool is_free;
91 uint32_t field_sz;
92
93 union {
94 uint32_t ui32;
95 uint64_t ui64;
96 char *str;
97 uint8_t *buf;
98 uint32_t *ui32_a;
99 uint64_t *ui64_a;
100 struct msg_str_array_s *str_a;
101 struct msg_buf_array_s *buf_a;
102 void *any_buf;
103 } u;
104} msg_field;
105
106typedef struct msg_s {
107 msg_type type;
108 uint16_t n_fields;
109 bool just_parsed; // fields point into fabric buffer
110 uint32_t bytes_used;
111 uint32_t bytes_alloc;
112 uint64_t benchmark_time;
113 msg_field f[]; // indexed by id
114} msg;
115
116// msg header on wire.
117typedef struct msg_hdr_s {
118 uint32_t size;
119 uint16_t type;
120} __attribute__ ((__packed__)) msg_hdr;
121
122typedef enum {
123 MSG_GET_DIRECT,
124 MSG_GET_COPY_MALLOC
125} msg_get_type;
126
127typedef enum {
128 MSG_SET_HANDOFF_MALLOC,
129 MSG_SET_COPY
130} msg_set_type;
131
132typedef struct msg_buf_ele_s {
133 uint32_t sz;
134 uint8_t *ptr;
135} msg_buf_ele;
136
137
138//==========================================================
139// Globals.
140//
141
142extern cf_atomic_int g_num_msgs;
143extern cf_atomic_int g_num_msgs_by_type[M_TYPE_MAX];
144
145
146//==========================================================
147// Public API.
148//
149
150//------------------------------------------------
151// Object accounting.
152//
153
154// Free up a "msg" object. Call this function instead of freeing the msg
155// directly in order to keep track of all msgs.
156void msg_put(msg *m);
157
158//------------------------------------------------
159// Lifecycle.
160//
161
162void msg_type_register(msg_type type, const msg_template *mt, size_t mt_sz, size_t scratch_sz);
163bool msg_type_is_valid(msg_type type);
164msg *msg_create(msg_type type);
165void msg_destroy(msg *m);
166void msg_incr_ref(msg *m);
167
168//------------------------------------------------
169// Pack messages into flattened data.
170//
171
172size_t msg_get_wire_size(const msg *m);
173size_t msg_get_template_fixed_sz(const msg_template *mt, size_t mt_count);
174size_t msg_to_iov_buf(const msg *m, uint8_t *buf, size_t buf_sz, uint32_t *msg_sz_r);
175size_t msg_to_wire(const msg *m, uint8_t *buf);
176
177//------------------------------------------------
178// Parse flattened data into messages.
179//
180
181bool msg_parse(msg *m, const uint8_t *buf, size_t bufsz);
182bool msg_parse_hdr(uint32_t *size_r, msg_type *type_r, const uint8_t *buf, size_t sz);
183bool msg_parse_fields(msg *m, const uint8_t *buf, size_t sz);
184
185void msg_reset(msg *m);
186void msg_preserve_fields(msg *m, uint32_t n_field_ids, ...);
187void msg_preserve_all_fields(msg *m);
188
189//------------------------------------------------
190// Set fields in messages.
191//
192
193void msg_set_uint32(msg *m, int field_id, uint32_t v);
194void msg_set_uint64(msg *m, int field_id, uint64_t v);
195void msg_set_str(msg *m, int field_id, const char *v, msg_set_type type);
196void msg_set_buf(msg *m, int field_id, const uint8_t *v, size_t sz, msg_set_type type);
197
198void msg_set_uint32_array_size(msg *m, int field_id, uint32_t count);
199void msg_set_uint32_array(msg *m, int field_id, uint32_t idx, uint32_t v);
200void msg_set_uint64_array_size(msg *m, int field_id, uint32_t count);
201void msg_set_uint64_array(msg *m, int field_id, uint32_t idx, uint64_t v);
202
203void msg_msgpack_list_set_uint32(msg *m, int field_id, const uint32_t *buf, uint32_t count);
204void msg_msgpack_list_set_uint64(msg *m, int field_id, const uint64_t *buf, uint32_t count);
205void msg_msgpack_list_set_buf(msg *m, int field_id, const cf_vector *v);
206
207//------------------------------------------------
208// Get fields from messages.
209//
210
211msg_field_type msg_field_get_type(const msg *m, int field_id);
212bool msg_is_set(const msg *m, int field_id);
213int msg_get_uint32(const msg *m, int field_id, uint32_t *val_r);
214int msg_get_uint64(const msg *m, int field_id, uint64_t *val_r);
215int msg_get_str(const msg *m, int field_id, char **str_r, msg_get_type type);
216int msg_get_buf(const msg *m, int field_id, uint8_t **buf_r, size_t *sz_r, msg_get_type type);
217
218int msg_get_uint32_array(const msg *m, int field_id, uint32_t idx, uint32_t *val_r);
219int msg_get_uint64_array_count(const msg *m, int field_id, uint32_t *count_r);
220int msg_get_uint64_array(const msg *m, int field_id, uint32_t idx, uint64_t *val_r);
221
222bool msg_msgpack_list_get_count(const msg *m, int field_id, uint32_t *count_r);
223bool msg_msgpack_list_get_uint32_array(const msg *m, int field_id, uint32_t *buf_r, uint32_t *count_r);
224bool msg_msgpack_list_get_uint64_array(const msg *m, int field_id, uint64_t *buf_r, uint32_t *count_r);
225bool msg_msgpack_list_get_buf_array(const msg *m, int field_id, cf_vector *v_r, bool init_vec);
226
227static inline bool
228msg_msgpack_list_get_buf_array_presized(const msg *m, int field_id, cf_vector *v_r)
229{
230 return msg_msgpack_list_get_buf_array(m, field_id, v_r, false);
231}
232
233
234//==========================================================
235// Debugging API.
236//
237
238void msg_dump(const msg *m, const char *info);
239