cis_config
communication.h
1 #include <../tools.h>
2 #include <../serialize/serialize.h>
3 #include <comm_header.h>
4 #include <CommBase.h>
5 #include <IPCComm.h>
6 #include <ZMQComm.h>
7 #include <RPCComm.h>
8 #include <ServerComm.h>
9 #include <ClientComm.h>
10 #include <AsciiFileComm.h>
11 #include <AsciiTableComm.h>
12 #include <DefaultComm.h>
13 
15 #ifndef CISCOMMUNICATION_H_
16 #define CISCOMMUNICATION_H_
17 
19 static void **vcomms2clean = NULL;
20 static size_t ncomms2clean = 0;
21 static size_t clean_registered = 0;
22 
23 // Forward declaration of eof
24 static
25 int comm_send_eof(const comm_t x);
26 static
27 int comm_nmsg(const comm_t x);
28 
29 
35 static
36 int free_comm_type(comm_t *x) {
37  comm_type t = x->type;
38  int ret = 1;
39  if (t == IPC_COMM)
40  ret = free_ipc_comm(x);
41  else if (t == ZMQ_COMM)
42  ret = free_zmq_comm(x);
43  else if (t == RPC_COMM)
44  ret = free_rpc_comm(x);
45  else if (t == SERVER_COMM)
46  ret = free_server_comm(x);
47  else if (t == CLIENT_COMM)
48  ret = free_client_comm(x);
49  else if (t == ASCII_FILE_COMM)
50  ret = free_ascii_file_comm(x);
51  else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
52  ret = free_ascii_table_comm(x);
53  else {
54  cislog_error("free_comm_type: Unsupported comm_type %d", t);
55  }
56  return ret;
57 };
58 
64 static
65 int free_comm(comm_t *x) {
66  int ret = 0;
67  if (x == NULL)
68  return ret;
69  comm_type t = x->type;
70  // Send EOF for output comms and then wait for messages to be recv'd
71  if ((is_send(x->direction)) && (t != CLIENT_COMM) && (x->valid)) {
72  if (_cis_error_flag == 0) {
73  comm_send_eof(*x);
74  while (comm_nmsg(*x) > 0) {
75  cislog_debug("free_comm(%s): draining %d messages",
76  x->name, comm_nmsg(*x));
77  usleep(CIS_SLEEP_TIME);
78  }
79  } else {
80  cislog_error("free_comm(%s): Error registered", x->name);
81  }
82  }
83  ret = free_comm_type(x);
84  int idx = x->index_in_register;
85  free_comm_base(x);
86  if (idx >= 0) {
87  if (vcomms2clean[idx] != NULL) {
88  free(vcomms2clean[idx]);
89  vcomms2clean[idx] = NULL;
90  }
91  }
92  return ret;
93 };
94 
98 static
99 void clean_comms(void) {
100  size_t i;
101  for (i = 0; i < ncomms2clean; i++) {
102  if (vcomms2clean[i] != NULL) {
103  free_comm((comm_t*)(vcomms2clean[i]));
104  }
105  }
106  if (vcomms2clean != NULL) {
107  free(vcomms2clean);
108  vcomms2clean = NULL;
109  }
110  ncomms2clean = 0;
111 #if defined(ZMQINSTALLED)
112  // #if defined(_WIN32) && defined(ZMQINSTALLED)
113  zsys_shutdown();
114 #endif
115  cislog_debug("atexit done");
116  /* printf(""); */
117 };
118 
125 static
126 int register_comm(comm_t *x) {
127  if (clean_registered == 0) {
128  atexit(clean_comms);
129  clean_registered = 1;
130  }
131  if (x == NULL) {
132  return 0;
133  }
134  void **t_vcomms2clean = (void**)realloc(vcomms2clean, sizeof(void*)*(ncomms2clean + 1));
135  if (t_vcomms2clean == NULL) {
136  cislog_error("register_comm(%s): Failed to realloc the comm list.", x->name);
137  return -1;
138  }
139  vcomms2clean = t_vcomms2clean;
140  x->index_in_register = (int)ncomms2clean;
141  vcomms2clean[ncomms2clean++] = (void*)x;
142  return 0;
143 };
144 
151 static
152 int new_comm_type(comm_t *x) {
153  comm_type t = x->type;
154  int flag;
155  if (t == IPC_COMM)
156  flag = new_ipc_address(x);
157  else if (t == ZMQ_COMM)
158  flag = new_zmq_address(x);
159  else if (t == RPC_COMM)
160  flag = new_rpc_address(x);
161  else if (t == SERVER_COMM)
162  flag = new_server_address(x);
163  else if (t == CLIENT_COMM)
164  flag = new_client_address(x);
165  else if (t == ASCII_FILE_COMM)
166  flag = new_ascii_file_address(x);
167  else if (t == ASCII_TABLE_COMM)
168  flag = new_ascii_table_address(x);
169  else if (t == ASCII_TABLE_ARRAY_COMM)
170  flag = new_ascii_table_array_address(x);
171  else {
172  cislog_error("new_comm_type: Unsupported comm_type %d", t);
173  flag = -1;
174  }
175  return flag;
176 };
177 
184 static
185 int init_comm_type(comm_t *x) {
186  comm_type t = x->type;
187  int flag;
188  if (t == IPC_COMM)
189  flag = init_ipc_comm(x);
190  else if (t == ZMQ_COMM)
191  flag = init_zmq_comm(x);
192  else if (t == RPC_COMM)
193  flag = init_rpc_comm(x);
194  else if (t == SERVER_COMM)
195  flag = init_server_comm(x);
196  else if (t == CLIENT_COMM)
197  flag = init_client_comm(x);
198  else if (t == ASCII_FILE_COMM)
199  flag = init_ascii_file_comm(x);
200  else if (t == ASCII_TABLE_COMM)
201  flag = init_ascii_table_comm(x);
202  else if (t == ASCII_TABLE_ARRAY_COMM)
203  flag = init_ascii_table_array_comm(x);
204  else {
205  cislog_error("init_comm_type: Unsupported comm_type %d", t);
206  flag = -1;
207  }
208  cislog_debug("init_comm_type(%s): Done, flag = %d", x->name, flag);
209  return flag;
210 };
211 
222 static
223 comm_t new_comm(char *address, const char *direction, const comm_type t,
224  void *seri_info) {
225  comm_t *ret = new_comm_base(address, direction, t, seri_info);
226  if (ret == NULL) {
227  cislog_error("new_comm: Could not initialize base.");
228  return empty_comm_base();
229  }
230  int flag;
231  if (address == NULL) {
232  flag = new_comm_type(ret);
233  } else {
234  flag = init_comm_type(ret);
235  }
236  if (flag < 0) {
237  cislog_error("new_comm: Failed to initialize new comm address.");
238  ret->valid = 0;
239  } else {
240  if (strlen(ret->name) == 0) {
241  sprintf(ret->name, "temp.%s", ret->address);
242  }
243  flag = register_comm(ret);
244  if (flag < 0) {
245  cislog_error("new_comm: Failed to register new comm.");
246  ret->valid = 0;
247  }
248  }
249  return ret[0];
250 };
251 
264 static
265 comm_t init_comm(const char *name, const char *direction, const comm_type t,
266  const void *seri_info) {
267  cislog_debug("init_comm: Initializing comm.");
268 #ifdef _WIN32
269  SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
270  _set_abort_behavior(0,_WRITE_ABORT_MSG);
271 #endif
272  comm_t *ret = init_comm_base(name, direction, t, seri_info);
273  if (ret == NULL) {
274  cislog_error("init_comm(%s): Could not initialize base.", name);
275  return empty_comm_base();
276  }
277  int flag = init_comm_type(ret);
278  if (flag < 0) {
279  cislog_error("init_comm(%s): Could not initialize comm.", name);
280  ret->valid = 0;
281  } else {
282  flag = register_comm(ret);
283  if (flag < 0) {
284  cislog_error("init_comm(%s): Failed to register new comm.", name);
285  ret->valid = 0;
286  }
287  }
288  cislog_debug("init_comm(%s): Initialized comm.", name);
289  return ret[0];
290 };
291 
297 static
298 int comm_nmsg(const comm_t x) {
299  int ret = -1;
300  if (x.valid == 0) {
301  cislog_error("comm_nmsg: Invalid comm");
302  return ret;
303  }
304  comm_type t = x.type;
305  if (t == IPC_COMM)
306  ret = ipc_comm_nmsg(x);
307  else if (t == ZMQ_COMM)
308  ret = zmq_comm_nmsg(x);
309  else if (t == RPC_COMM)
310  ret = rpc_comm_nmsg(x);
311  else if (t == SERVER_COMM)
312  ret = server_comm_nmsg(x);
313  else if (t == CLIENT_COMM)
314  ret = client_comm_nmsg(x);
315  else if (t == ASCII_FILE_COMM)
316  ret = ascii_file_comm_nmsg(x);
317  else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
318  ret = ascii_table_comm_nmsg(x);
319  else {
320  cislog_error("comm_nmsg: Unsupported comm_type %d", t);
321  }
322  return ret;
323 };
324 
334 static
335 int comm_send_single(const comm_t x, const char *data, const size_t len) {
336  int ret = -1;
337  if (x.valid == 0) {
338  cislog_error("comm_send_single: Invalid comm");
339  return ret;
340  }
341  comm_type t = x.type;
342  if (t == IPC_COMM)
343  ret = ipc_comm_send(x, data, len);
344  else if (t == ZMQ_COMM)
345  ret = zmq_comm_send(x, data, len);
346  else if (t == RPC_COMM)
347  ret = rpc_comm_send(x, data, len);
348  else if (t == SERVER_COMM)
349  ret = server_comm_send(x, data, len);
350  else if (t == CLIENT_COMM)
351  ret = client_comm_send(x, data, len);
352  else if (t == ASCII_FILE_COMM)
353  ret = ascii_file_comm_send(x, data, len);
354  else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
355  ret = ascii_table_comm_send(x, data, len);
356  else {
357  cislog_error("comm_send_single: Unsupported comm_type %d", t);
358  }
359  if (ret >= 0) {
360  time(x.last_send);
361  /* time_t now; */
362  /* time(&now); */
363  /* x.last_send[0] = now; */
364  }
365  return ret;
366 };
367 
368 
376 static
377 comm_head_t comm_send_multipart_header(const comm_t x, const size_t len) {
378  comm_head_t head = init_header(len, NULL, NULL);
379  sprintf(head.id, "%d", rand());
380  head.multipart = 1;
381  head.valid = 1;
382  // Add serializer information to header on first send
383  if ((x.used[0] == 0) && (x.is_file == 0)) {
384  seri_t *serializer;
385  if (x.type == CLIENT_COMM) {
386  comm_t *req_comm = (comm_t*)(x.handle);
387  serializer = req_comm->serializer;
388  } else {
389  serializer = x.serializer;
390  }
391  if (serializer->type == DIRECT_SERI) {
392  head.serializer_type = 0;
393  } else if (serializer->type == FORMAT_SERI) {
394  head.serializer_type = 1;
395  strcpy(head.format_str, (char*)(serializer->info));
396  } else if (serializer->type == ARRAY_SERI) {
397  head.serializer_type = 2;
398  strcpy(head.format_str, (char*)(serializer->info));
399  head.as_array = 1;
400  } else if (serializer->type == ASCII_TABLE_SERI) {
401  head.serializer_type = 1;
402  asciiTable_t *table = (asciiTable_t*)(serializer->info);
403  strcpy(head.format_str, table->format_str);
404  } else if (serializer->type == ASCII_TABLE_ARRAY_SERI) {
405  head.serializer_type = 2;
406  asciiTable_t *table = (asciiTable_t*)(serializer->info);
407  strcpy(head.format_str, table->format_str);
408  head.as_array = 1;
409  }
410  }
411  // Why was this necessary?
412  if (x.type == SERVER_COMM)
413  strcpy(head.id, x.address);
414  else if (x.type == CLIENT_COMM)
415  head = client_response_header(x, head);
416  return head;
417 };
418 
426 static
427 int comm_send_multipart(const comm_t x, const char *data, const size_t len) {
428  //char headbuf[CIS_MSG_BUF];
429  int headbuf_len = CIS_MSG_BUF;
430  int headlen = 0, ret = -1;
431  if (x.valid == 0) {
432  cislog_error("comm_send_multipart: Invalid comm");
433  return ret;
434  }
435  comm_t xmulti = empty_comm_base();
436  // Get header
437  comm_head_t head = comm_send_multipart_header(x, len);
438  if (head.valid == 0) {
439  cislog_error("comm_send_multipart: Invalid header generated.");
440  return -1;
441  }
442  char *headbuf = (char*)malloc(headbuf_len);
443  if (headbuf == NULL) {
444  cislog_error("comm_send_multipart: Failed to malloc headbuf.");
445  return -1;
446  }
447  // Try to send body in header
448  if (len < x.maxMsgSize) {
449  headlen = format_comm_header(head, headbuf, headbuf_len);
450  if (headlen < 0) {
451  cislog_error("comm_send_multipart: Failed to format header.");
452  free(headbuf);
453  return -1;
454  }
455  if (((size_t)headlen + len) < x.maxMsgSize) {
456  if (((size_t)headlen + len + 1) > (size_t)headbuf_len) {
457  char *t_headbuf = (char*)realloc(headbuf, (size_t)headlen + len + 1);
458  if (t_headbuf == NULL) {
459  cislog_error("comm_send_multipart: Failed to realloc headbuf.");
460  free(headbuf);
461  return -1;
462  }
463  headbuf = t_headbuf;
464  headbuf_len = headlen + (int)len + 1;
465  }
466  head.multipart = 0;
467  memcpy(headbuf + headlen, data, len);
468  headlen += (int)len;
469  headbuf[headlen] = '\0';
470  }
471  }
472  // Get head string
473  if (head.multipart == 1) {
474  // Get address for new comm and add to header
475  xmulti = new_comm(NULL, "send", x.type, NULL);
476  if (!(xmulti.valid)) {
477  cislog_error("comm_send_multipart: Failed to initialize a new comm.");
478  free(headbuf);
479  return -1;
480  }
481  xmulti.sent_eof[0] = 1;
482  xmulti.recv_eof[0] = 1;
483  strcpy(head.address, xmulti.address);
484  headlen = format_comm_header(head, headbuf, headbuf_len);
485  if (headlen < 0) {
486  cislog_error("comm_send_multipart: Failed to format header.");
487  free(headbuf);
488  free_comm(&xmulti);
489  return -1;
490  }
491  }
492  // Send header
493  ret = comm_send_single(x, headbuf, headlen);
494  if (ret < 0) {
495  cislog_error("comm_send_multipart: Failed to send header.");
496  if (head.multipart == 1)
497  free_comm(&xmulti);
498  free(headbuf);
499  return -1;
500  }
501  if (head.multipart == 0) {
502  cislog_debug("comm_send_multipart(%s): %d bytes completed", x.name, head.size);
503  free(headbuf);
504  return ret;
505  }
506  // Send multipart
507  size_t msgsiz;
508  size_t prev = 0;
509  while (prev < head.size) {
510  if ((head.size - prev) > xmulti.maxMsgSize)
511  msgsiz = xmulti.maxMsgSize;
512  else
513  msgsiz = head.size - prev;
514  ret = comm_send_single(xmulti, data + prev, msgsiz);
515  if (ret < 0) {
516  cislog_debug("comm_send_multipart(%s): send interupted at %d of %d bytes.",
517  x.name, prev, head.size);
518  break;
519  }
520  prev += msgsiz;
521  cislog_debug("comm_send_multipart(%s): %d of %d bytes sent",
522  x.name, prev, head.size);
523  }
524  if (ret == 0)
525  cislog_debug("comm_send_multipart(%s): %d bytes completed", x.name, head.size);
526  // Free multipart
527  free_comm(&xmulti);
528  free(headbuf);
529  if (ret >= 0)
530  x.used[0] = 1;
531  return ret;
532 };
533 
534 
544 static
545 int comm_send(const comm_t x, const char *data, const size_t len) {
546  int ret = -1;
547  if (x.valid == 0) {
548  cislog_error("comm_send: Invalid comm");
549  return ret;
550  }
551  if (x.sent_eof == NULL) {
552  cislog_error("comm_send(%s): sent_eof not initialized.", x.name);
553  return ret;
554  }
555  int sending_eof = 0;
556  if (is_eof(data)) {
557  if (x.sent_eof[0] == 0) {
558  x.sent_eof[0] = 1;
559  sending_eof = 1;
560  } else {
561  cislog_error("comm_send(%s): EOF already sent", x.name);
562  return ret;
563  }
564  }
565  if (((len > x.maxMsgSize) && (x.maxMsgSize > 0)) ||
566  (((x.always_send_header) || (x.used[0] == 0)) && (!(is_eof(data))))) {
567  return comm_send_multipart(x, data, len);
568  }
569  ret = comm_send_single(x, data, len);
570  if (sending_eof) {
571  cislog_debug("comm_send(%s): sent EOF, ret = %d", x.name, ret);
572  }
573  if (ret >= 0)
574  x.used[0] = 1;
575  return ret;
576 };
577 
583 static
584 int comm_send_eof(const comm_t x) {
585  int ret = -1;
586  char buf[100] = CIS_MSG_EOF;
587  ret = comm_send(x, buf, strlen(buf));
588  return ret;
589 };
590 
603 static
604 int comm_recv_single(const comm_t x, char **data, const size_t len,
605  const int allow_realloc) {
606  int ret = -1;
607  if (x.valid == 0) {
608  cislog_error("comm_recv_single: Invalid comm");
609  return ret;
610  }
611  comm_type t = x.type;
612  if (t == IPC_COMM)
613  ret = ipc_comm_recv(x, data, len, allow_realloc);
614  else if (t == ZMQ_COMM)
615  ret = zmq_comm_recv(x, data, len, allow_realloc);
616  else if (t == RPC_COMM)
617  ret = rpc_comm_recv(x, data, len, allow_realloc);
618  else if (t == SERVER_COMM)
619  ret = server_comm_recv(x, data, len, allow_realloc);
620  else if (t == CLIENT_COMM)
621  ret = client_comm_recv(x, data, len, allow_realloc);
622  else if (t == ASCII_FILE_COMM)
623  ret = ascii_file_comm_recv(x, data, len, allow_realloc);
624  else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
625  ret = ascii_table_comm_recv(x, data, len, allow_realloc);
626  else {
627  cislog_error("comm_recv: Unsupported comm_type %d", t);
628  }
629  return ret;
630 };
631 
642 static
643 int comm_recv_multipart(const comm_t x, char **data, const size_t len,
644  const size_t headlen, const int allow_realloc) {
645  int ret = -1;
646  if (x.valid == 0) {
647  cislog_error("comm_recv_multipart: Invalid comm");
648  return ret;
649  }
650  usleep(100);
651  comm_head_t head = parse_comm_header(*data, headlen);
652  if (!(head.valid)) {
653  cislog_error("comm_recv(%s): Error parsing header.", x.name);
654  ret = -1;
655  } else {
656  // Get serializer information from header on first recv
657  if ((x.used[0] == 0) && (x.is_file == 0) && (x.serializer->type == 0)) {
658  int new_type = -1;
659  void *new_info = (void*)(head.format_str);
660  cislog_debug("comm_recv(%s): Updating serializer type to %d",
661  x.name, head.serializer_type);
662  if (head.serializer_type == 0) {
663  new_type = DIRECT_SERI;
664  } else if (head.serializer_type == 1) {
665  new_type = FORMAT_SERI;
666  } else if (head.serializer_type == 2) {
667  new_type = ASCII_TABLE_ARRAY_SERI;
668  // TODO: Treat this as a separate class
669  // new_type = ARRAY_SERI;
670  } else if (head.serializer_type == 3) {
671  if (head.as_array == 0) {
672  new_type = ASCII_TABLE_SERI;
673  } else {
674  new_type = ASCII_TABLE_ARRAY_SERI;
675  }
676  }
677  if (new_type >= 0) {
678  ret = update_serializer(x.serializer, new_type, new_info);
679  if (ret != 0) {
680  cislog_error("comm_recv(%s): Error updating serializer.", x.name);
681  return -1;
682  }
683  }
684  // Set name for debug info & simplify formats
685  if ((new_type == ASCII_TABLE_SERI) || (new_type == ASCII_TABLE_ARRAY_SERI)) {
686  asciiTable_t *table = (asciiTable_t*)(x.serializer->info);
687  ret = at_update(table, x.name, "0");
688  if (ret != 0) {
689  cislog_error("comm_recv(%s): Failed to update asciiTable address.",
690  x.name);
691  return -1;
692  }
693  ret = simplify_formats(table->format_str, CIS_MSG_MAX);
694  if (ret < 0) {
695  cislog_error("comm_recv(%s): Failed to simplify recvd table format.", x.name);
696  return -1;
697  }
698  } else if (new_type == FORMAT_SERI) {
699  char * format_str = (char*)(x.serializer->info);
700  ret = simplify_formats(format_str, x.serializer->size_info);
701  if (ret < 0) {
702  cislog_error("comm_recv(%s): Failed to simplify recvd format.", x.name);
703  return -1;
704  }
705  }
706  }
707  if (head.multipart) {
708  // Move part of message after header to front of data
709  memmove(*data, *data + head.bodybeg, head.bodysiz);
710  (*data)[head.bodysiz] = '\0';
711  // Return early if header contained entire message
712  if (head.size == head.bodysiz) {
713  x.used[0] = 1;
714  return (int)(head.bodysiz);
715  }
716  // Get address for new comm
717  comm_t xmulti = new_comm(head.address, "recv", x.type, NULL);
718  if (!(xmulti.valid)) {
719  cislog_error("comm_recv_multipart: Failed to initialize a new comm.");
720  return -1;
721  }
722  xmulti.sent_eof[0] = 1;
723  xmulti.recv_eof[0] = 1;
724  // Receive parts of message
725  size_t prev = head.bodysiz;
726  size_t msgsiz = 0;
727  // Reallocate data if necessary
728  if ((head.size + 1) > len) {
729  if (allow_realloc) {
730  char *t_data = (char*)realloc(*data, head.size + 1);
731  if (t_data == NULL) {
732  cislog_error("comm_recv_multipart(%s): Failed to realloc buffer",
733  x.name);
734  free(*data);
735  free_comm(&xmulti);
736  return -1;
737  }
738  *data = t_data;
739  } else {
740  cislog_error("comm_recv_multipart(%s): buffer is not large enough",
741  x.name);
742  free_comm(&xmulti);
743  return -1;
744  }
745  }
746  ret = -1;
747  char *pos = (*data) + prev;
748  while (prev < head.size) {
749  if ((head.size - prev) > xmulti.maxMsgSize)
750  msgsiz = xmulti.maxMsgSize;
751  else
752  msgsiz = head.size - prev + 1;
753  ret = comm_recv_single(xmulti, &pos, msgsiz, 0);
754  if (ret < 0) {
755  cislog_debug("comm_recv_multipart(%s): recv interupted at %d of %d bytes.",
756  x.name, prev, head.size);
757  break;
758  }
759  prev += ret;
760  pos += ret;
761  cislog_debug("comm_recv_multipart(%s): %d of %d bytes received",
762  x.name, prev, head.size);
763  }
764  if (ret > 0) {
765  cislog_debug("comm_recv_multipart(%s): %d bytes completed", x.name, prev);
766  ret = (int)prev;
767  }
768  free_comm(&xmulti);
769  } else {
770  ret = (int)headlen;
771  }
772  }
773  if (ret >= 0)
774  x.used[0] = 1;
775  return ret;
776 };
777 
788 static
789 int comm_recv(const comm_t x, char *data, const size_t len) {
790  int ret = comm_recv_single(x, &data, len, 0);
791  if (ret > 0) {
792  if (is_eof(data)) {
793  cislog_debug("comm_recv(%s): EOF received.", x.name);
794  x.recv_eof[0] = 1;
795  ret = -2;
796  } else {
797  ret = comm_recv_multipart(x, &data, len, ret, 0);
798  }
799  } else {
800  cislog_error("comm_recv_realloc(%s): Failed to receive header or message.",
801  x.name);
802  }
803  return ret;
804 };
805 
815 static
816 int comm_recv_realloc(const comm_t x, char **data, const size_t len) {
817  int ret = comm_recv_single(x, data, len, 1);
818  if (ret > 0) {
819  if (is_eof(*data)) {
820  cislog_debug("comm_recv_realloc(%s): EOF received.", x.name);
821  x.recv_eof[0] = 1;
822  ret = -2;
823  } else {
824  ret = comm_recv_multipart(x, data, len, ret, 1);
825  }
826  } else {
827  cislog_error("comm_recv_realloc(%s): Failed to receive header or message.",
828  x.name);
829  }
830  return ret;
831 };
832 
833 
835 static
836 int comm_send_nolimit(const comm_t x, const char *data, const size_t len) {
837  return comm_send(x, data, len);
838 };
839 
845 static
846 int comm_send_nolimit_eof(const comm_t x) {
847  int ret = -1;
848  if (x.valid == 0) {
849  cislog_error("comm_send_nolimit_eof: Invalid comm");
850  return ret;
851  }
852  if (x.sent_eof == NULL) {
853  cislog_error("comm_send_nolimit_eof(%s): sent_eof not initialized.", x.name);
854  return ret;
855  }
856  if (x.sent_eof[0] == 0) {
857  char buf[2048] = CIS_MSG_EOF;
858  ret = comm_send_nolimit(x, buf, strlen(buf));
859  x.sent_eof[0] = 1;
860  } else {
861  cislog_error("comm_send_nolimit_eof(%s): EOF already sent", x.name);
862  }
863  return ret;
864 };
865 
879 static
880 int comm_recv_nolimit(const comm_t x, char **data, const size_t len) {
881  return comm_recv_realloc(x, data, len);
882 };
883 
894 static
895 int vcommSend(const comm_t x, va_list ap) {
896  int ret = -1;
897  if (x.valid == 0) {
898  cislog_error("vcommSend: Invalid comm");
899  return ret;
900  }
901  size_t buf_siz = CIS_MSG_BUF;
902  // char *buf = NULL;
903  char *buf = (char*)malloc(buf_siz);
904  if (buf == NULL) {
905  cislog_error("vcommSend(%s): Failed to alloc buffer", x.name);
906  return -1;
907  }
908  seri_t *serializer = x.serializer;
909  if (x.type == CLIENT_COMM) {
910  comm_t *handle = (comm_t*)(x.handle);
911  serializer = handle->serializer;
912  }
913  int args_used = 0;
914  ret = serialize(*serializer, &buf, buf_siz, 1, &args_used, ap);
915  if (ret < 0) {
916  cislog_error("vcommSend(%s): serialization error", x.name);
917  free(buf);
918  return -1;
919  }
920  ret = comm_send(x, buf, ret);
921  cislog_debug("vcommSend(%s): comm_send returns %d", x.name, ret);
922  free(buf);
923  if (ret < 0) {
924  return ret;
925  } else {
926  return args_used;
927  }
928 };
929 
942 static
943 int vcommRecv(const comm_t x, va_list ap) {
944  int ret = -1;
945  if (x.valid == 0) {
946  cislog_error("vcommRecv: Invalid comm");
947  return ret;
948  }
949  // Receive message
950  size_t buf_siz = CIS_MSG_BUF;
951  /* char *buf = NULL; */
952  char *buf = (char*)malloc(buf_siz);
953  if (buf == NULL) {
954  cislog_error("vcommSend(%s): Failed to alloc buffer", x.name);
955  return -1;
956  }
957  ret = comm_recv_nolimit(x, &buf, buf_siz);
958  if (ret < 0) {
959  // cislog_error("vcommRecv(%s): Error receiving.", x.name);
960  free(buf);
961  return ret;
962  }
963  cislog_debug("vcommRecv(%s): comm_recv returns %d: %.10s...", x.name, ret, buf);
964  // Deserialize message
965  seri_t *serializer = x.serializer;
966  if (x.type == SERVER_COMM) {
967  comm_t *handle = (comm_t*)(x.handle);
968  serializer = handle->serializer;
969  }
970  ret = deserialize(*serializer, buf, ret, ap);
971  if (ret < 0) {
972  cislog_error("vcommRecv(%s): error deserializing message (ret=%d)",
973  x.name, ret);
974  free(buf);
975  return -1;
976  }
977  cislog_debug("vcommRecv(%s): deserialize_format returns %d", x.name, ret);
978  free(buf);
979  return ret;
980 };
981 
982 #define vcommSend_nolimit vcommSend
983 #define vcommRecv_nolimit vcommRecv
984 
985 
986 #endif /*CISCOMMUNICATION_H_*/
void * handle
Pointer to handle for comm.
Definition: CommBase.h:25
char format_str[LINE_SIZE_MAX]
Format string for rows.
Definition: AsciiTable.h:78
Communication structure.
Definition: CommBase.h:19
char address[COMM_ADDRESS_SIZE]
Comm address.
Definition: CommBase.h:22
Serializer structure.
Definition: SerializeBase.h:15
time_t * last_send
Clock output at time of last send.
Definition: CommBase.h:31
void * info
Pointer to any extra info serializer requires.
Definition: SerializeBase.h:17
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
size_t maxMsgSize
The maximum message size.
Definition: CommBase.h:28
size_t size_info
Size of allocate space for info.
Definition: SerializeBase.h:18
int * used
Flag specifying if the comm has been used.
Definition: CommBase.h:34
char address[COMMBUFFSIZ]
Address that message will comm in on.
Definition: comm_header.h:17
comm_type type
Comm type.
Definition: CommBase.h:20
int valid
1 if the header is valid, 0 otherwise.
Definition: comm_header.h:21
int is_file
Flag specifying if the comm connects directly to a file.
Definition: CommBase.h:36
int always_send_header
1 if comm should always send a header.
Definition: CommBase.h:29
seri_t * serializer
Serializer for comm messages.
Definition: CommBase.h:27
char format_str[COMMBUFFSIZ]
Format string for serializer.
Definition: comm_header.h:26
size_t bodysiz
Size of body.
Definition: comm_header.h:19
char direction[COMM_DIR_SIZE]
send or recv for direction messages will go.
Definition: CommBase.h:23
char name[COMM_NAME_SIZE]
Comm name.
Definition: CommBase.h:21
int * sent_eof
Flag specifying if EOF has been sent.
Definition: CommBase.h:32
size_t size
Size of incoming message.
Definition: comm_header.h:16
int valid
1 if communicator initialized, 0 otherwise.
Definition: CommBase.h:24
int * recv_eof
Flag specifying if EOF has been received.
Definition: CommBase.h:33
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
Structure containing information about an ASCII table.
Definition: AsciiTable.h:76
char id[COMMBUFFSIZ]
Unique ID associated with this message.
Definition: comm_header.h:22
int index_in_register
Index of the comm in the comm register.
Definition: CommBase.h:30
seri_type type
Serializer type.
Definition: SerializeBase.h:16
Header information passed by comms for multipart messages.
Definition: comm_header.h:15