cis_config: /root/cis_interface/cis_interface/cis_interface/communication/comm_header.h Source File

cis_config

comm_header.h
1
2 #ifndef CISCOMMHEADER_H_
3 #define CISCOMMHEADER_H_
4
5 #include <../tools.h>
6 #include <../dataio/AsciiTable.h>
7
8 #ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
9 extern "C" {
10 #endif
11
12 #define CIS_MSG_HEAD "CIS_MSG_HEAD"
13 #define HEAD_VAL_SEP ":CIS:"
14 #define HEAD_KEY_SEP ",CIS,"
15 #define COMMBUFFSIZ 2000
16
17
19 typedef struct comm_head_t {
20 size_t size;
21 char address[COMMBUFFSIZ];
22 int multipart;
23 size_t bodysiz;
24 size_t bodybeg;
25 int valid;
26 char id[COMMBUFFSIZ];
27 char response_address[COMMBUFFSIZ];
28 char request_id[COMMBUFFSIZ];
29 int serializer_type;
30 char format_str[COMMBUFFSIZ];
31 char field_names[COMMBUFFSIZ];
32 char field_units[COMMBUFFSIZ];
33 int as_array;
34 char zmq_reply[COMMBUFFSIZ];
35 char zmq_reply_worker[COMMBUFFSIZ];
36 } comm_head_t;
37
47 static inline
48 comm_head_t init_header(const size_t size, const char *address, const char *id) {
49 comm_head_t out;
50 out.size = size;
51 out.multipart = 0;
52 out.bodysiz = 0;
53 out.bodybeg = 0;
54 out.valid = 1;
55 if (address == NULL)
56 out.address[0] = '\0';
57 else
58 strcpy(out.address, address);
59 if (id == NULL)
60 out.id[0] = '\0';
61 else
62 strcpy(out.id, id);
63 out.response_address[0] = '\0';
64 out.request_id[0] = '\0';
65 out.serializer_type = -1;
66 out.format_str[0] = '\0';
67 out.as_array = 0;
68 out.zmq_reply[0] = '\0';
69 out.zmq_reply_worker[0] = '\0';
70 /* if (response_address == NULL) */
71 /* out.response_address[0] = '\0'; */
72 /* else */
73 /* strcpy(out.response_address, response_address); */
74 return out;
75 };
76
85 static inline
86 int format_header_entry(char *head, const char *key, const char *value,
87 const size_t headsiz) {
88 int ret = snprintf(head, headsiz, "%s%s%s%s",
89 key, HEAD_VAL_SEP, value, HEAD_KEY_SEP);
90 if (ret > (int)headsiz) {
91 cislog_error("format_header_entry: Formatted header is larger than bufer.\n");
92 return -1;
93 }
94 return ret;
95 };
96
105 static inline
106 int parse_header_entry(const char *head, const char *key, char *value,
107 const size_t valsiz) {
108 // Compile
109 /*
110 if (strlen(HEAD_KEY_SEP) > 1) {
111 cislog_error("parse_header_entry: HEAD_KEY_SEP is more than one character. Fix regex.");
112 return -1;
113 } */
114 char regex_text[200];
115 regex_text[0] = '\0';
116 strcat(regex_text, HEAD_KEY_SEP);
117 strcat(regex_text, key);
118 strcat(regex_text, HEAD_VAL_SEP);
119 strcat(regex_text, "([^(");
120 strcat(regex_text, HEAD_KEY_SEP);
121 strcat(regex_text, ")]*)");
122 strcat(regex_text, HEAD_KEY_SEP);
123 // Extract substring
124 size_t *sind = NULL;
125 size_t *eind = NULL;
126 int n_sub_matches = find_matches(regex_text, head, &sind, &eind);
127 // Loop until string done
128 if (n_sub_matches < 2) {
129 cislog_debug("parse_header_entry: Could not find match to %s in %s.",
130 regex_text, head);
131 if (sind != NULL) free(sind);
132 if (eind != NULL) free(eind);
133 return -1;
134 }
135 // Extract substring
136 size_t value_size = eind[1] - sind[1];
137 if (value_size > valsiz) {
138 cislog_error("parse_header_entry: Value is larger than buffer.\n");
139 if (sind != NULL) free(sind);
140 if (eind != NULL) free(eind);
141 return -1;
142 }
143 memcpy(value, head + sind[1], value_size);
144 value[value_size] = '\0';
145 if (sind != NULL) free(sind);
146 if (eind != NULL) free(eind);
147 return (int)value_size;
148 };
149
150
158 static inline
159 int format_comm_header(const comm_head_t head, char *buf, const size_t bufsiz) {
160 int ret;
161 size_t pos;
162 // Header tag
163 pos = 0;
164 strcpy(buf, CIS_MSG_HEAD);
165 pos += strlen(CIS_MSG_HEAD);
166 if (pos > bufsiz) {
167 cislog_error("First header tag would exceed buffer size\n");
168 return -1;
169 }
170 // Address entry
171 if (strlen(head.address) > 0) {
172 ret = format_header_entry(buf + pos, "address", head.address, bufsiz - pos);
173 if (ret < 0) {
174 cislog_error("Adding address entry would exceed buffer size\n");
175 return ret;
176 } else {
177 pos += ret;
178 }
179 }
180 // Size entry
181 char size_str[100];
182 sprintf(size_str, "%d", (int)(head.size));
183 ret = format_header_entry(buf + pos, "size", size_str, bufsiz - pos);
184 if (ret < 0) {
185 cislog_error("Adding size entry would exceed buffer size\n");
186 return ret;
187 } else {
188 pos += ret;
189 }
190 // ID
191 if (strlen(head.id) > 0) {
192 ret = format_header_entry(buf + pos, "id", head.id, bufsiz - pos);
193 if (ret < 0) {
194 cislog_error("Adding id entry would exceed buffer size\n");
195 return ret;
196 } else {
197 pos += ret;
198 }
199 }
200 // REQUEST_ID
201 if (strlen(head.request_id) > 0) {
202 ret = format_header_entry(buf + pos, "request_id",
203 head.request_id, bufsiz - pos);
204 if (ret < 0) {
205 cislog_error("Adding request_id entry would exceed buffer size\n");
206 return ret;
207 } else {
208 pos += ret;
209 }
210 }
211 // RESPONSE_ADDRESS
212 if (strlen(head.response_address) > 0) {
213 ret = format_header_entry(buf + pos, "response_address",
214 head.response_address, bufsiz - pos);
215 if (ret < 0) {
216 cislog_error("Adding response_address entry would exceed buffer size\n");
217 return ret;
218 } else {
219 pos += ret;
220 }
221 }
222 // Serializer type
223 if (head.serializer_type >= 0) {
224 char stype_str[100];
225 sprintf(stype_str, "%d", head.serializer_type);
226 ret = format_header_entry(buf + pos, "stype", stype_str, bufsiz - pos);
227 if (ret < 0) {
228 cislog_error("Adding stype entry would exceed buffer size\n");
229 return ret;
230 } else {
231 pos += ret;
232 }
233 }
234 // Serializer format_str
235 if (strlen(head.format_str) > 0) {
236 ret = format_header_entry(buf + pos, "format_str",
237 head.format_str, bufsiz - pos);
238 if (ret < 0) {
239 cislog_error("Adding format_str entry would exceed buffer size\n");
240 return ret;
241 } else {
242 pos += ret;
243 }
244 }
245 // Serializer as_array
246 if (head.as_array > 0) {
247 char as_array_str[100];
248 sprintf(as_array_str, "%d", head.as_array);
249 ret = format_header_entry(buf + pos, "as_array", as_array_str, bufsiz - pos);
250 if (ret < 0) {
251 cislog_error("Adding as_array entry would exceed buffer size\n");
252 return ret;
253 } else {
254 pos += ret;
255 }
256 }
257 // ZMQ Reply address
258 if (strlen(head.zmq_reply) > 0) {
259 ret = format_header_entry(buf + pos, "zmq_reply",
260 head.zmq_reply, bufsiz - pos);
261 if (ret < 0) {
262 cislog_error("Adding zmq_reply entry would exceed buffer size\n");
263 return ret;
264 } else {
265 pos += ret;
266 }
267 }
268 // ZMQ Reply address for worker
269 if (strlen(head.zmq_reply_worker) > 0) {
270 ret = format_header_entry(buf + pos, "zmq_reply_worker",
271 head.zmq_reply_worker, bufsiz - pos);
272 if (ret < 0) {
273 cislog_error("Adding zmq_reply_worker entry would exceed buffer size\n");
274 return ret;
275 } else {
276 pos += ret;
277 }
278 }
279 // Closing header tag
280 pos -= strlen(HEAD_KEY_SEP);
281 buf[pos] = '\0';
282 pos += strlen(CIS_MSG_HEAD);
283 if (pos > bufsiz) {
284 cislog_error("Closing header tag would exceed buffer size\n");
285 return -1;
286 }
287 strcat(buf, CIS_MSG_HEAD);
288 /* // Body */
289 /* if (head.body != NULL) { */
290 /* pos += head.bodysiz; */
291 /* if (pos > bufsiz) { */
292 /* cislog_error("Adding body would exceed buffer size\n"); */
293 /* return -1; */
294 /* } */
295 /* memcpy(buf, head.body, head.bodysiz); */
296 /* buf[pos] = '\0'; */
297 /* } */
298 return (int)pos;
299 };
300
307 static inline
308 comm_head_t parse_comm_header(const char *buf, const size_t bufsiz) {
309 comm_head_t out = init_header(0, NULL, NULL);
310 size_t sind, eind;
311 int ret;
312 #ifdef _WIN32
313 // Windows regex of newline is buggy
314 size_t sind1, eind1, sind2, eind2;
315 char re_head_tag[COMMBUFFSIZ];
316 sprintf(re_head_tag, "(%s)", CIS_MSG_HEAD);
317 ret = find_match(re_head_tag, buf, &sind1, &eind1);
318 if (ret > 0) {
319 sind = sind1;
320 ret = find_match(re_head_tag, buf + eind1, &sind2, &eind2);
321 if (ret > 0)
322 eind = eind1 + eind2;
323 }
324 #else
325 // Extract just header
326 char re_head[COMMBUFFSIZ] = CIS_MSG_HEAD;
327 strcat(re_head, "(.*)");
328 strcat(re_head, CIS_MSG_HEAD);
329 // strcat(re_head, ".*");
330 ret = find_match(re_head, buf, &sind, &eind);
331 #endif
332 if (ret < 0) {
333 cislog_error("parse_comm_header: could not find header in '%.1000s'", buf);
334 out.valid = 0;
335 return out;
336 } else if (ret == 0) {
337 cislog_debug("parse_comm_header: No header in '%.1000s...'", buf);
338 out.multipart = 0;
339 out.size = bufsiz;
340 } else {
341 out.multipart = 1;
342 // Extract just header
343 size_t headsiz = (eind-sind);
344 out.bodysiz = bufsiz - headsiz;
345 out.bodybeg = eind;
346 headsiz -= (2*strlen(CIS_MSG_HEAD));
347 char *head = (char*)malloc(headsiz + 2*strlen(HEAD_KEY_SEP) + 1);
348 strcpy(head, HEAD_KEY_SEP);
349 memcpy(head + strlen(HEAD_KEY_SEP), buf + sind + strlen(CIS_MSG_HEAD), headsiz);
350 head[headsiz + strlen(HEAD_KEY_SEP)] = '\0';
351 strcat(head, HEAD_KEY_SEP);
352 // Extract address
353 ret = parse_header_entry(head, "address", out.address, COMMBUFFSIZ);
354 // Extract size
355 char size_str[COMMBUFFSIZ];
356 ret = parse_header_entry(head, "size", size_str, COMMBUFFSIZ);
357 if (ret < 0) {
358 cislog_error("parse_comm_header: could not find size in header");
359 out.valid = 0;
360 free(head);
361 return out;
362 }
363 out.size = atoi(size_str);
364 // Extract id & response address
365 ret = parse_header_entry(head, "id", out.id, COMMBUFFSIZ);
366 ret = parse_header_entry(head, "response_address", out.response_address, COMMBUFFSIZ);
367 ret = parse_header_entry(head, "request_id", out.request_id, COMMBUFFSIZ);
368 // Extract serializer type
369 char stype_str[COMMBUFFSIZ];
370 ret = parse_header_entry(head, "stype", stype_str, COMMBUFFSIZ);
371 if (ret >= 0)
372 out.serializer_type = atoi(stype_str);
373 // Extract as_array serialization parameter
374 char array_str[COMMBUFFSIZ];
375 ret = parse_header_entry(head, "as_array", array_str, COMMBUFFSIZ);
376 if (ret >= 0)
377 out.as_array = atoi(array_str);
378 // Extract serializer information
379 ret = parse_header_entry(head, "format_str", out.format_str, COMMBUFFSIZ);
380 ret = parse_header_entry(head, "field_names", out.field_names, COMMBUFFSIZ);
381 ret = parse_header_entry(head, "field_units", out.field_units, COMMBUFFSIZ);
382 // ZMQ reply addresses
383 ret = parse_header_entry(head, "zmq_reply", out.zmq_reply, COMMBUFFSIZ);
384 ret = parse_header_entry(head, "zmq_reply_worker", out.zmq_reply_worker, COMMBUFFSIZ);
385 // Free header
386 free(head);
387 }
388 return out;
389 };
390
391 #ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
392 }
393 #endif
394
395 #endif /*CISCOMMHEADER_H_*/
comm_head_t::field_names
char field_names[COMMBUFFSIZ]
String containing field names.
Definition: comm_header.h:31
comm_head_t::response_address
char response_address[COMMBUFFSIZ]
Response address.
Definition: comm_header.h:27
comm_head_t::request_id
char request_id[COMMBUFFSIZ]
Request id.
Definition: comm_header.h:28
comm_head_t::zmq_reply_worker
char zmq_reply_worker[COMMBUFFSIZ]
Reply address for worker socket.
Definition: comm_header.h:35
comm_head_t::multipart
int multipart
1 if message is multipart, 0 if it is not.
Definition: comm_header.h:22
comm_head_t::bodybeg
size_t bodybeg
Start of body in header.
Definition: comm_header.h:24
comm_head_t::address
char address[COMMBUFFSIZ]
Address that message will comm in on.
Definition: comm_header.h:21
comm_head_t::valid
int valid
1 if the header is valid, 0 otherwise.
Definition: comm_header.h:25
comm_head_t::zmq_reply
char zmq_reply[COMMBUFFSIZ]
Reply address for ZMQ sockets.
Definition: comm_header.h:34
comm_head_t::format_str
char format_str[COMMBUFFSIZ]
Format string for serializer.
Definition: comm_header.h:30
comm_head_t::bodysiz
size_t bodysiz
Size of body.
Definition: comm_header.h:23
comm_head_t::size
size_t size
Size of incoming message.
Definition: comm_header.h:20
comm_head_t::as_array
int as_array
1 if messages will be serialized arrays.
Definition: comm_header.h:33
comm_head_t::serializer_type
int serializer_type
Code indicating the type of serializer.
Definition: comm_header.h:29
comm_head_t::field_units
char field_units[COMMBUFFSIZ]
String containing field units.
Definition: comm_header.h:32
comm_head_t::id
char id[COMMBUFFSIZ]
Unique ID associated with this message.
Definition: comm_header.h:26
comm_head_t
Header information passed by comms for multipart messages.
Definition: comm_header.h:19