cis_config
comm_header.h
1 #include <../tools.h>
2 #include <../dataio/AsciiTable.h>
3 
5 #ifndef CISCOMMHEADER_H_
6 #define CISCOMMHEADER_H_
7 
8 #define CIS_MSG_HEAD "CIS_MSG_HEAD"
9 #define HEAD_VAL_SEP ":CIS:"
10 #define HEAD_KEY_SEP ",CIS,"
11 #define COMMBUFFSIZ 2000
12 
13 
15 typedef struct comm_head_t {
16  size_t size;
17  char address[COMMBUFFSIZ];
18  int multipart;
19  size_t bodysiz;
20  size_t bodybeg;
21  int valid;
22  char id[COMMBUFFSIZ];
23  char response_address[COMMBUFFSIZ];
24  char request_id[COMMBUFFSIZ];
26  char format_str[COMMBUFFSIZ];
27  char field_names[COMMBUFFSIZ];
28  char field_units[COMMBUFFSIZ];
29  int as_array;
30 } comm_head_t;
31 
41 static inline
42 comm_head_t init_header(const size_t size, const char *address, const char *id) {
43  comm_head_t out;
44  out.size = size;
45  out.multipart = 0;
46  out.bodysiz = 0;
47  out.bodybeg = 0;
48  out.valid = 1;
49  if (address == NULL)
50  out.address[0] = '\0';
51  else
52  strcpy(out.address, address);
53  if (id == NULL)
54  out.id[0] = '\0';
55  else
56  strcpy(out.id, id);
57  out.response_address[0] = '\0';
58  out.request_id[0] = '\0';
59  out.serializer_type = -1;
60  out.format_str[0] = '\0';
61  out.as_array = 0;
62  /* if (response_address == NULL) */
63  /* out.response_address[0] = '\0'; */
64  /* else */
65  /* strcpy(out.response_address, response_address); */
66  return out;
67 };
68 
77 static inline
78 int format_header_entry(char *head, const char *key, const char *value,
79  const size_t headsiz) {
80  int ret = snprintf(head, headsiz, "%s%s%s%s",
81  key, HEAD_VAL_SEP, value, HEAD_KEY_SEP);
82  if (ret > (int)headsiz) {
83  cislog_error("format_header_entry: Formatted header is larger than bufer.\n");
84  return -1;
85  }
86  return ret;
87 };
88 
97 static inline
98 int parse_header_entry(const char *head, const char *key, char *value,
99  const size_t valsiz) {
100  // Compile
101  /*
102  if (strlen(HEAD_KEY_SEP) > 1) {
103  cislog_error("parse_header_entry: HEAD_KEY_SEP is more than one character. Fix regex.");
104  return -1;
105  } */
106  char regex_text[200];
107  regex_text[0] = '\0';
108  strcat(regex_text, HEAD_KEY_SEP);
109  strcat(regex_text, key);
110  strcat(regex_text, HEAD_VAL_SEP);
111  strcat(regex_text, "([^(");
112  strcat(regex_text, HEAD_KEY_SEP);
113  strcat(regex_text, ")]*)");
114  strcat(regex_text, HEAD_KEY_SEP);
115  // Extract substring
116  size_t *sind = NULL;
117  size_t *eind = NULL;
118  int n_sub_matches = find_matches(regex_text, head, &sind, &eind);
119  // Loop until string done
120  if (n_sub_matches < 2) {
121  cislog_debug("parse_header_entry: Could not find match to %s in %s.",
122  regex_text, head);
123  if (sind != NULL) free(sind);
124  if (eind != NULL) free(eind);
125  return -1;
126  }
127  // Extract substring
128  size_t value_size = eind[1] - sind[1];
129  if (value_size > valsiz) {
130  cislog_error("parse_header_entry: Value is larger than buffer.\n");
131  if (sind != NULL) free(sind);
132  if (eind != NULL) free(eind);
133  return -1;
134  }
135  memcpy(value, head + sind[1], value_size);
136  value[value_size] = '\0';
137  if (sind != NULL) free(sind);
138  if (eind != NULL) free(eind);
139  return (int)value_size;
140 };
141 
142 
150 static inline
151 int format_comm_header(const comm_head_t head, char *buf, const size_t bufsiz) {
152  int ret;
153  size_t pos;
154  // Header tag
155  pos = 0;
156  strcpy(buf, CIS_MSG_HEAD);
157  pos += strlen(CIS_MSG_HEAD);
158  if (pos > bufsiz) {
159  cislog_error("First header tag would exceed buffer size\n");
160  return -1;
161  }
162  // Address entry
163  if (strlen(head.address) > 0) {
164  ret = format_header_entry(buf + pos, "address", head.address, bufsiz - pos);
165  if (ret < 0) {
166  cislog_error("Adding address entry would exceed buffer size\n");
167  return ret;
168  } else {
169  pos += ret;
170  }
171  }
172  // Size entry
173  char size_str[100];
174  sprintf(size_str, "%d", (int)(head.size));
175  ret = format_header_entry(buf + pos, "size", size_str, bufsiz - pos);
176  if (ret < 0) {
177  cislog_error("Adding size entry would exceed buffer size\n");
178  return ret;
179  } else {
180  pos += ret;
181  }
182  // ID
183  if (strlen(head.id) > 0) {
184  ret = format_header_entry(buf + pos, "id", head.id, bufsiz - pos);
185  if (ret < 0) {
186  cislog_error("Adding id entry would exceed buffer size\n");
187  return ret;
188  } else {
189  pos += ret;
190  }
191  }
192  // REQUEST_ID
193  if (strlen(head.request_id) > 0) {
194  ret = format_header_entry(buf + pos, "request_id",
195  head.request_id, bufsiz - pos);
196  if (ret < 0) {
197  cislog_error("Adding request_id entry would exceed buffer size\n");
198  return ret;
199  } else {
200  pos += ret;
201  }
202  }
203  // RESPONSE_ADDRESS
204  if (strlen(head.response_address) > 0) {
205  ret = format_header_entry(buf + pos, "response_address",
206  head.response_address, bufsiz - pos);
207  if (ret < 0) {
208  cislog_error("Adding response_address entry would exceed buffer size\n");
209  return ret;
210  } else {
211  pos += ret;
212  }
213  }
214  // Serializer type
215  if (head.serializer_type >= 0) {
216  char stype_str[100];
217  sprintf(stype_str, "%d", head.serializer_type);
218  ret = format_header_entry(buf + pos, "stype", stype_str, bufsiz - pos);
219  if (ret < 0) {
220  cislog_error("Adding stype entry would exceed buffer size\n");
221  return ret;
222  } else {
223  pos += ret;
224  }
225  }
226  // Serializer format_str
227  if (strlen(head.format_str) > 0) {
228  ret = format_header_entry(buf + pos, "format_str",
229  head.format_str, bufsiz - pos);
230  if (ret < 0) {
231  cislog_error("Adding format_str entry would exceed buffer size\n");
232  return ret;
233  } else {
234  pos += ret;
235  }
236  }
237  // Serializer as_array
238  if (head.as_array > 0) {
239  char as_array_str[100];
240  sprintf(as_array_str, "%d", head.as_array);
241  ret = format_header_entry(buf + pos, "as_array", as_array_str, bufsiz - pos);
242  if (ret < 0) {
243  cislog_error("Adding as_array entry would exceed buffer size\n");
244  return ret;
245  } else {
246  pos += ret;
247  }
248  }
249  // Closing header tag
250  pos -= strlen(HEAD_KEY_SEP);
251  buf[pos] = '\0';
252  pos += strlen(CIS_MSG_HEAD);
253  if (pos > bufsiz) {
254  cislog_error("Closing header tag would exceed buffer size\n");
255  return -1;
256  }
257  strcat(buf, CIS_MSG_HEAD);
258  /* // Body */
259  /* if (head.body != NULL) { */
260  /* pos += head.bodysiz; */
261  /* if (pos > bufsiz) { */
262  /* cislog_error("Adding body would exceed buffer size\n"); */
263  /* return -1; */
264  /* } */
265  /* memcpy(buf, head.body, head.bodysiz); */
266  /* buf[pos] = '\0'; */
267  /* } */
268  return (int)pos;
269 };
270 
277 static inline
278 comm_head_t parse_comm_header(const char *buf, const size_t bufsiz) {
279  comm_head_t out = init_header(0, NULL, NULL);
280  size_t sind, eind;
281  int ret;
282 #ifdef _WIN32
283  // Windows regex of newline is buggy
284  size_t sind1, eind1, sind2, eind2;
285  char re_head_tag[COMMBUFFSIZ];
286  sprintf(re_head_tag, "(%s)", CIS_MSG_HEAD);
287  ret = find_match(re_head_tag, buf, &sind1, &eind1);
288  if (ret > 0) {
289  sind = sind1;
290  ret = find_match(re_head_tag, buf + eind1, &sind2, &eind2);
291  if (ret > 0)
292  eind = eind1 + eind2;
293  }
294 #else
295  // Extract just header
296  char re_head[COMMBUFFSIZ] = CIS_MSG_HEAD;
297  strcat(re_head, "(.*)");
298  strcat(re_head, CIS_MSG_HEAD);
299  // strcat(re_head, ".*");
300  ret = find_match(re_head, buf, &sind, &eind);
301 #endif
302  if (ret < 0) {
303  cislog_error("parse_comm_header: could not find header in '%.1000s'", buf);
304  out.valid = 0;
305  return out;
306  } else if (ret == 0) {
307  cislog_debug("parse_comm_header: No header in '%.1000s...'", buf);
308  out.multipart = 0;
309  out.size = bufsiz;
310  } else {
311  out.multipart = 1;
312  // Extract just header
313  size_t headsiz = (eind-sind);
314  out.bodysiz = bufsiz - headsiz;
315  out.bodybeg = eind;
316  headsiz -= (2*strlen(CIS_MSG_HEAD));
317  char *head = (char*)malloc(headsiz + 2*strlen(HEAD_KEY_SEP) + 1);
318  strcpy(head, HEAD_KEY_SEP);
319  memcpy(head + strlen(HEAD_KEY_SEP), buf + sind + strlen(CIS_MSG_HEAD), headsiz);
320  head[headsiz + strlen(HEAD_KEY_SEP)] = '\0';
321  strcat(head, HEAD_KEY_SEP);
322  // Extract address
323  ret = parse_header_entry(head, "address", out.address, COMMBUFFSIZ);
324  // Extract size
325  char size_str[COMMBUFFSIZ];
326  ret = parse_header_entry(head, "size", size_str, COMMBUFFSIZ);
327  if (ret < 0) {
328  cislog_error("parse_comm_header: could not find size in header");
329  out.valid = 0;
330  free(head);
331  return out;
332  }
333  out.size = atoi(size_str);
334  // Extract id & response address
335  ret = parse_header_entry(head, "id", out.id, COMMBUFFSIZ);
336  ret = parse_header_entry(head, "response_address", out.response_address, COMMBUFFSIZ);
337  ret = parse_header_entry(head, "request_id", out.request_id, COMMBUFFSIZ);
338  // Extract serializer type
339  char stype_str[COMMBUFFSIZ];
340  ret = parse_header_entry(head, "stype", stype_str, COMMBUFFSIZ);
341  if (ret >= 0)
342  out.serializer_type = atoi(stype_str);
343  // Extract as_array serialization parameter
344  char array_str[COMMBUFFSIZ];
345  ret = parse_header_entry(head, "as_array", array_str, COMMBUFFSIZ);
346  if (ret >= 0)
347  out.as_array = atoi(array_str);
348  // Extract serializer information
349  ret = parse_header_entry(head, "format_str", out.format_str, COMMBUFFSIZ);
350  ret = parse_header_entry(head, "field_names", out.field_names, COMMBUFFSIZ);
351  ret = parse_header_entry(head, "field_units", out.field_units, COMMBUFFSIZ);
352  // Free header
353  free(head);
354  }
355  return out;
356 };
357 
358 
359 #endif /*CISCOMMHEADER_H_*/
char field_names[COMMBUFFSIZ]
String containing field names.
Definition: comm_header.h:27
char response_address[COMMBUFFSIZ]
Response address.
Definition: comm_header.h:23
char request_id[COMMBUFFSIZ]
Request id.
Definition: comm_header.h:24
int multipart
1 if message is multipart, 0 if it is not.
Definition: comm_header.h:18
size_t bodybeg
Start of body in header.
Definition: comm_header.h:20
char address[COMMBUFFSIZ]
Address that message will comm in on.
Definition: comm_header.h:17
int valid
1 if the header is valid, 0 otherwise.
Definition: comm_header.h:21
char format_str[COMMBUFFSIZ]
Format string for serializer.
Definition: comm_header.h:26
size_t bodysiz
Size of body.
Definition: comm_header.h:19
size_t size
Size of incoming message.
Definition: comm_header.h:16
int as_array
1 if messages will be serialized arrays.
Definition: comm_header.h:29
int serializer_type
Code indicating the type of serializer.
Definition: comm_header.h:25
char field_units[COMMBUFFSIZ]
String containing field units.
Definition: comm_header.h:28
char id[COMMBUFFSIZ]
Unique ID associated with this message.
Definition: comm_header.h:22
Header information passed by comms for multipart messages.
Definition: comm_header.h:15