/src/opensips/bin_interface.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2013 OpenSIPS Solutions |
3 | | * |
4 | | * This file is part of opensips, a free SIP server. |
5 | | * |
6 | | * opensips is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version |
10 | | * |
11 | | * opensips is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | * |
20 | | * History: |
21 | | * ------- |
22 | | * 2013-04-10: Created (Liviu) |
23 | | */ |
24 | | |
25 | | #ifndef __BINARY_INTERFACE__ |
26 | | #define __BINARY_INTERFACE__ |
27 | | |
28 | | #include "ip_addr.h" |
29 | | #include "crc.h" |
30 | | #include "net/proto_tcp/tcp_common_defs.h" |
31 | | |
32 | | /* this padding helps us simply "cast" a received packet as a sending packet |
33 | | * with zero overhead; otherwise, we'd need to memcpy it from SHM->PKG */ |
34 | | #define BIN_CL_RSV_SZ ((1+3+1) * sizeof(int)) |
35 | | // req_like + msg_add_trailer() + src_cluster (agg) |
36 | | |
37 | | #define BIN_MAX_BUF_LEN (TCP_BUF_SIZE - BIN_CL_RSV_SZ) |
38 | | #define BIN_PACKET_MARKER "P4CK" |
39 | | #define BIN_PACKET_MARKER_SIZE 4 |
40 | | #define PKG_LEN_FIELD_SIZE 4 |
41 | | #define VERSION_FIELD_SIZE 2 |
42 | | #define LEN_FIELD_SIZE (sizeof(unsigned short)) |
43 | | #define CMD_FIELD_SIZE sizeof(int) |
44 | | #define HEADER_SIZE \ |
45 | | (BIN_PACKET_MARKER_SIZE + PKG_LEN_FIELD_SIZE + VERSION_FIELD_SIZE) |
46 | | #define MIN_BIN_PACKET_SIZE \ |
47 | | (HEADER_SIZE + LEN_FIELD_SIZE + 1 + CMD_FIELD_SIZE) |
48 | | /* ^ capability */ |
49 | | |
50 | | #define is_valid_bin_packet(_p) \ |
51 | | (memcmp(_p, BIN_PACKET_MARKER, BIN_PACKET_MARKER_SIZE) == 0) |
52 | | |
53 | | /* make sure a BIN packet has an exact version or a range of versions */ |
54 | | #define ensure_bin_version(pkt, needed) _ensure_bin_version(pkt, needed, "") |
55 | | #define ensure_bin_version2(pkt, v1, v2) _ensure_bin_version2(pkt, v1, v2, "") |
56 | | #define _ensure_bin_version(pkt, needed, pkt_desc) \ |
57 | | do { \ |
58 | | if (get_bin_pkg_version(pkt) != (needed)) \ |
59 | | _bin_version_error_return(pkt, pkt_desc, needed) \ |
60 | | } while (0) |
61 | | #define _ensure_bin_version2(pkt, vmin, vmax, pkt_desc) \ |
62 | | do { \ |
63 | | if (get_bin_pkg_version(pkt)<(vmin) || get_bin_pkg_version(pkt)>(vmax)) \ |
64 | | _bin_version_error_return(pkt, pkt_desc, vmax) \ |
65 | | } while (0) |
66 | | #define _bin_version_error_return(pkt, pkt_desc, needed) \ |
67 | | { \ |
68 | | if (pkt_desc && *pkt_desc) \ |
69 | | LM_INFO("discarding %s (%d), ver %d: need ver %d\n", \ |
70 | | pkt_desc, pkt->type, get_bin_pkg_version(pkt), (needed)); \ |
71 | | else \ |
72 | | LM_INFO("discarding packet type %d, ver %d: need ver %d\n", \ |
73 | | pkt->type, get_bin_pkg_version(pkt), (needed)); \ |
74 | | return; \ |
75 | | } |
76 | | |
77 | | typedef unsigned bin_packet_flags_t; |
78 | | #define BINFL_SYSMEM (1U<<0) |
79 | | |
80 | | typedef struct bin_packet { |
81 | | str buffer; |
82 | | char *front_pointer; |
83 | | struct bin_packet *next; |
84 | | int size; |
85 | | int type; |
86 | | bin_packet_flags_t flags; |
87 | | /* not populated by bin_interface */ |
88 | | int src_id; |
89 | | } bin_packet_t; |
90 | | |
91 | | struct packet_cb_list { |
92 | | str capability; /* registered capability */ |
93 | | void (*cbf)(bin_packet_t *, int packet_type, /* callback */ |
94 | | struct receive_info *ri, void *att); |
95 | | void *att; |
96 | | |
97 | | struct packet_cb_list *next; |
98 | | }; |
99 | | |
100 | | /* returns the version of the bin protocol from the given message */ |
101 | | static inline short get_bin_pkg_version(bin_packet_t *packet) |
102 | 0 | { |
103 | 0 | short rval; |
104 | 0 |
|
105 | 0 | memcpy(&rval, packet->buffer.s + BIN_PACKET_MARKER_SIZE |
106 | 0 | + PKG_LEN_FIELD_SIZE, sizeof(rval)); |
107 | 0 | return rval; |
108 | 0 | } Unexecuted instantiation: pt.c:get_bin_pkg_version Unexecuted instantiation: cfg.tab.c:get_bin_pkg_version |
109 | | |
110 | | /* overrides the version of the bin protocol from the given message */ |
111 | | static inline void set_bin_pkg_version(bin_packet_t *packet, short new_version) |
112 | 0 | { |
113 | 0 | memcpy(packet->buffer.s + BIN_PACKET_MARKER_SIZE |
114 | 0 | + PKG_LEN_FIELD_SIZE, &new_version, sizeof(new_version)); |
115 | 0 | } Unexecuted instantiation: pt.c:set_bin_pkg_version Unexecuted instantiation: cfg.tab.c:set_bin_pkg_version |
116 | | |
117 | | /* |
118 | | * returns the capability from the message |
119 | | */ |
120 | | void bin_get_capability(bin_packet_t *packet, str *capability); |
121 | | void bin_set_packet_type(bin_packet_t *packet, int packet_type); |
122 | | |
123 | | |
124 | | /** |
125 | | calls all the registered functions |
126 | | |
127 | | @buffer: buffer containing a complete bin message |
128 | | @rcv: information about the sender of the message |
129 | | */ |
130 | | void call_callbacks(char* buffer, struct receive_info *rcv); |
131 | | /* |
132 | | * registers a callback function to be triggered on a received |
133 | | * binary packet marked with the @cap capability |
134 | | */ |
135 | | int bin_register_cb(str *cap, void (*cb)(bin_packet_t *, int, |
136 | | struct receive_info *, void * atr), void *att, int att_len); |
137 | | |
138 | | |
139 | | /** |
140 | | * first function called when building a binary packet |
141 | | * |
142 | | * @capability: capability string |
143 | | * @packet_type: capability specific identifier for this new packet |
144 | | * |
145 | | * @return: 0 on success |
146 | | */ |
147 | | int _bin_init(bin_packet_t *packet, str *capability, int packet_type, short version, |
148 | | int length, int use_sysmalloc); |
149 | | #define bin_init(_pk, _cap, _pt, _ver, _len) \ |
150 | | _bin_init(_pk, _cap, _pt, _ver, _len, 0) |
151 | | |
152 | | /** |
153 | | * function called to build a binary packet with a known buffer |
154 | | * |
155 | | * @packet: the packet that will be populated |
156 | | * @buffer: the buffer that will be attached to the packet |
157 | | * @length: the length of the buffer attached |
158 | | */ |
159 | | void bin_init_buffer(bin_packet_t *packet, char *buffer, int length); |
160 | | |
161 | | /* |
162 | | * appends a buffer to a binary packet |
163 | | * @buf: buffer to be appended |
164 | | * @len: length of @buf |
165 | | * |
166 | | * @return: |
167 | | * > 0: success, the size of the buffer |
168 | | * < 0: internal buffer limit reached |
169 | | */ |
170 | | int bin_append_buffer(bin_packet_t *packet, str *buf); |
171 | | |
172 | | /* |
173 | | * adds a new string value to the packet being currently built |
174 | | * @info: may also be NULL |
175 | | * |
176 | | * @return: |
177 | | * > 0: success, the size of the buffer |
178 | | * < 0: internal buffer limit reached |
179 | | */ |
180 | | int bin_push_str(bin_packet_t *packet, const str *info); |
181 | | |
182 | | /* |
183 | | * adds a new integer value to the packet being currently built |
184 | | * |
185 | | * @return: |
186 | | * > 0: success, the size of the buffer |
187 | | * < 0: internal buffer limit reached |
188 | | */ |
189 | | int bin_push_int(bin_packet_t *packet, int info); |
190 | | |
191 | | /* |
192 | | * removes an integer from the end of the packet |
193 | | * |
194 | | * @return: |
195 | | * 0: success |
196 | | * < 0: error, no more integers in buffer |
197 | | */ |
198 | | int bin_remove_int_buffer_end(bin_packet_t *packet, int count); |
199 | | |
200 | | /* |
201 | | * skips @count integers in the end of the packet |
202 | | * |
203 | | * @return: |
204 | | * 0: success |
205 | | * < 0: error, no more integers in buffer |
206 | | */ |
207 | | int bin_skip_int_packet_end(bin_packet_t *packet, int count); |
208 | | |
209 | | /* |
210 | | * pops a str structure from binary packet |
211 | | * @info: pointer to store the result |
212 | | * |
213 | | * @return: |
214 | | * 0 (success): info retrieved |
215 | | * 1 (success): nothing returned, all data has been consumed! |
216 | | * < 0: error |
217 | | * |
218 | | * Note: The pointer returned in @info is only valid for the duration of |
219 | | * the callback. Don't forget to copy the data into a safe buffer! |
220 | | * |
221 | | * Note2: Information is retrieved in the same order it was stored |
222 | | */ |
223 | | int bin_pop_str(bin_packet_t *packet, str *info); |
224 | | |
225 | | /* |
226 | | * pops an integer from the front of the packet |
227 | | * @info: pointer to store the result |
228 | | * |
229 | | * @return: |
230 | | * 0 (success): info retrieved |
231 | | * 1 (success): nothing returned, all data has been consumed! |
232 | | * < 0: error |
233 | | * |
234 | | * Note: Information is retrieved in the same order it was stored |
235 | | */ |
236 | | int bin_pop_int(bin_packet_t *packet, void *info); |
237 | | |
238 | | /* |
239 | | * pops an integer from the end of binary packet |
240 | | * @info: pointer to store the result |
241 | | * |
242 | | * @return: |
243 | | * 0 (success): info retrieved |
244 | | * 1 (success): nothing returned, all data has been consumed! |
245 | | * < 0: error |
246 | | */ |
247 | | int bin_pop_back_int(bin_packet_t *packet, void *info); |
248 | | |
249 | | /* |
250 | | * skips @count integers from a received binary packet |
251 | | * |
252 | | * @return: |
253 | | * >= 0: success, number of skipped bytes |
254 | | * < 0: error, buffer limit reached |
255 | | */ |
256 | | int bin_skip_int(bin_packet_t *packet, int count); |
257 | | |
258 | | /* |
259 | | * skips @count strings from a received binary packet |
260 | | * |
261 | | * @return: |
262 | | * >= 0: success, number of skipped bytes |
263 | | * < 0: error, buffer limit reached |
264 | | */ |
265 | | int bin_skip_str(bin_packet_t *packet, int count); |
266 | | |
267 | | /* |
268 | | * frees the memory used by the binary packet |
269 | | */ |
270 | | void bin_free_packet(bin_packet_t *packet); |
271 | | |
272 | | /* |
273 | | * resets the packet, equivalent to calling bin_free_packet, |
274 | | * then reinitializing the packet |
275 | | */ |
276 | | int bin_reset_back_pointer(bin_packet_t *packet); |
277 | | /* |
278 | | * returns the buffer with the data in the bin packet |
279 | | */ |
280 | | int bin_get_buffer(bin_packet_t *packet, str *buffer); |
281 | | |
282 | | /* |
283 | | * returns the bin packet's buffer from the position where |
284 | | * the serialized content actually starts |
285 | | */ |
286 | | int bin_get_content_start(bin_packet_t *packet, str *buf); |
287 | | |
288 | | /* |
289 | | * returns the bin packet's buffer from the position of the |
290 | | * next field to be consumed |
291 | | */ |
292 | | int bin_get_content_pos(bin_packet_t *packet, str *buf); |
293 | | |
294 | | #endif /* __BINARY_INTERFACE__ */ |
295 | | |