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

cis_config

communication.h
1
2 #ifndef CISCOMMUNICATION_H_
3 #define CISCOMMUNICATION_H_
4
5 #include <../tools.h>
6 #include <../serialize/serialize.h>
7 #include <comm_header.h>
8 #include <CommBase.h>
9 #include <IPCComm.h>
10 #include <ZMQComm.h>
11 #include <RPCComm.h>
12 #include <ServerComm.h>
13 #include <ClientComm.h>
14 #include <AsciiFileComm.h>
15 #include <AsciiTableComm.h>
16 #include <DefaultComm.h>
17
18 #ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
19 extern "C" {
20 #endif
21
23 static void **vcomms2clean = NULL;
24 static size_t ncomms2clean = 0;
25 static size_t clean_registered = 0;
26
27 // Forward declaration of eof
28 static
29 int comm_send_eof(const comm_t x);
30 static
31 int comm_nmsg(const comm_t x);
32
33
39 static
40 int free_comm_type(comm_t *x) {
41 comm_type t = x->type;
42 int ret = 1;
43 if (t == IPC_COMM)
44 ret = free_ipc_comm(x);
45 else if (t == ZMQ_COMM)
46 ret = free_zmq_comm(x);
47 else if (t == RPC_COMM)
48 ret = free_rpc_comm(x);
49 else if (t == SERVER_COMM)
50 ret = free_server_comm(x);
51 else if (t == CLIENT_COMM)
52 ret = free_client_comm(x);
53 else if (t == ASCII_FILE_COMM)
54 ret = free_ascii_file_comm(x);
55 else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
56 ret = free_ascii_table_comm(x);
57 else {
58 cislog_error("free_comm_type: Unsupported comm_type %d", t);
59 }
60 return ret;
61 };
62
68 static
69 int free_comm(comm_t *x) {
70 int ret = 0;
71 if (x == NULL)
72 return ret;
73 cislog_debug("free_comm(%s)", x->name);
74 // Send EOF for output comms and then wait for messages to be recv'd
75 if ((is_send(x->direction)) && (x->valid)) {
76 if (_cis_error_flag == 0) {
77 cislog_debug("free_comm(%s): Sending EOF", x->name);
78 comm_send_eof(*x);
79 while (comm_nmsg(*x) > 0) {
80 cislog_debug("free_comm(%s): draining %d messages",
81 x->name, comm_nmsg(*x));
82 usleep(CIS_SLEEP_TIME);
83 }
84 } else {
85 cislog_error("free_comm(%s): Error registered", x->name);
86 }
87 }
88 ret = free_comm_type(x);
89 int idx = x->index_in_register;
90 free_comm_base(x);
91 if (idx >= 0) {
92 if (vcomms2clean[idx] != NULL) {
93 free(vcomms2clean[idx]);
94 vcomms2clean[idx] = NULL;
95 }
96 }
97 return ret;
98 };
99
103 static
104 void clean_comms(void) {
105 size_t i;
106 cislog_debug("atexit begin");
107 for (i = 0; i < ncomms2clean; i++) {
108 if (vcomms2clean[i] != NULL) {
109 free_comm((comm_t*)(vcomms2clean[i]));
110 }
111 }
112 if (vcomms2clean != NULL) {
113 free(vcomms2clean);
114 vcomms2clean = NULL;
115 }
116 ncomms2clean = 0;
117 #if defined(ZMQINSTALLED)
118 // #if defined(_WIN32) && defined(ZMQINSTALLED)
119 zsys_shutdown();
120 #endif
121 cislog_debug("atexit done");
122 /* printf(""); */
123 };
124
131 static
132 int register_comm(comm_t *x) {
133 if (clean_registered == 0) {
134 atexit(clean_comms);
135 clean_registered = 1;
136 }
137 if (x == NULL) {
138 return 0;
139 }
140 void **t_vcomms2clean = (void**)realloc(vcomms2clean, sizeof(void*)*(ncomms2clean + 1));
141 if (t_vcomms2clean == NULL) {
142 cislog_error("register_comm(%s): Failed to realloc the comm list.", x->name);
143 return -1;
144 }
145 vcomms2clean = t_vcomms2clean;
146 x->index_in_register = (int)ncomms2clean;
147 vcomms2clean[ncomms2clean++] = (void*)x;
148 return 0;
149 };
150
157 static
158 int new_comm_type(comm_t *x) {
159 comm_type t = x->type;
160 int flag;
161 if (t == IPC_COMM)
162 flag = new_ipc_address(x);
163 else if (t == ZMQ_COMM)
164 flag = new_zmq_address(x);
165 else if (t == RPC_COMM)
166 flag = new_rpc_address(x);
167 else if (t == SERVER_COMM)
168 flag = new_server_address(x);
169 else if (t == CLIENT_COMM)
170 flag = new_client_address(x);
171 else if (t == ASCII_FILE_COMM)
172 flag = new_ascii_file_address(x);
173 else if (t == ASCII_TABLE_COMM)
174 flag = new_ascii_table_address(x);
175 else if (t == ASCII_TABLE_ARRAY_COMM)
176 flag = new_ascii_table_array_address(x);
177 else {
178 cislog_error("new_comm_type: Unsupported comm_type %d", t);
179 flag = -1;
180 }
181 return flag;
182 };
183
190 static
191 int init_comm_type(comm_t *x) {
192 comm_type t = x->type;
193 int flag;
194 if (t == IPC_COMM)
195 flag = init_ipc_comm(x);
196 else if (t == ZMQ_COMM)
197 flag = init_zmq_comm(x);
198 else if (t == RPC_COMM)
199 flag = init_rpc_comm(x);
200 else if (t == SERVER_COMM)
201 flag = init_server_comm(x);
202 else if (t == CLIENT_COMM)
203 flag = init_client_comm(x);
204 else if (t == ASCII_FILE_COMM)
205 flag = init_ascii_file_comm(x);
206 else if (t == ASCII_TABLE_COMM)
207 flag = init_ascii_table_comm(x);
208 else if (t == ASCII_TABLE_ARRAY_COMM)
209 flag = init_ascii_table_array_comm(x);
210 else {
211 cislog_error("init_comm_type: Unsupported comm_type %d", t);
212 flag = -1;
213 }
214 cislog_debug("init_comm_type(%s): Done, flag = %d", x->name, flag);
215 return flag;
216 };
217
228 static
229 comm_t new_comm(char *address, const char *direction, const comm_type t,
230 void *seri_info) {
231 comm_t *ret = new_comm_base(address, direction, t, seri_info);
232 if (ret == NULL) {
233 cislog_error("new_comm: Could not initialize base.");
234 return empty_comm_base();
235 }
236 int flag;
237 if (address == NULL) {
238 flag = new_comm_type(ret);
239 } else {
240 flag = init_comm_type(ret);
241 }
242 if (flag < 0) {
243 cislog_error("new_comm: Failed to initialize new comm address.");
244 ret->valid = 0;
245 } else {
246 if (strlen(ret->name) == 0) {
247 sprintf(ret->name, "temp.%s", ret->address);
248 }
249 flag = register_comm(ret);
250 if (flag < 0) {
251 cislog_error("new_comm: Failed to register new comm.");
252 ret->valid = 0;
253 }
254 }
255 return ret[0];
256 };
257
270 static
271 comm_t init_comm(const char *name, const char *direction, const comm_type t,
272 const void *seri_info) {
273 cislog_debug("init_comm: Initializing comm.");
274 #ifdef _WIN32
275 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
276 _set_abort_behavior(0,_WRITE_ABORT_MSG);
277 #endif
278 comm_t *ret = init_comm_base(name, direction, t, seri_info);
279 if (ret == NULL) {
280 cislog_error("init_comm(%s): Could not initialize base.", name);
281 return empty_comm_base();
282 }
283 int flag = init_comm_type(ret);
284 if (flag < 0) {
285 cislog_error("init_comm(%s): Could not initialize comm.", name);
286 ret->valid = 0;
287 } else {
288 flag = register_comm(ret);
289 if (flag < 0) {
290 cislog_error("init_comm(%s): Failed to register new comm.", name);
291 ret->valid = 0;
292 }
293 }
294 cislog_debug("init_comm(%s): Initialized comm.", name);
295 return ret[0];
296 };
297
303 static
304 int comm_nmsg(const comm_t x) {
305 int ret = -1;
306 if (x.valid == 0) {
307 cislog_error("comm_nmsg: Invalid comm");
308 return ret;
309 }
310 comm_type t = x.type;
311 if (t == IPC_COMM)
312 ret = ipc_comm_nmsg(x);
313 else if (t == ZMQ_COMM)
314 ret = zmq_comm_nmsg(x);
315 else if (t == RPC_COMM)
316 ret = rpc_comm_nmsg(x);
317 else if (t == SERVER_COMM)
318 ret = server_comm_nmsg(x);
319 else if (t == CLIENT_COMM)
320 ret = client_comm_nmsg(x);
321 else if (t == ASCII_FILE_COMM)
322 ret = ascii_file_comm_nmsg(x);
323 else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
324 ret = ascii_table_comm_nmsg(x);
325 else {
326 cislog_error("comm_nmsg: Unsupported comm_type %d", t);
327 }
328 return ret;
329 };
330
340 static
341 int comm_send_single(const comm_t x, const char *data, const size_t len) {
342 int ret = -1;
343 if (x.valid == 0) {
344 cislog_error("comm_send_single: Invalid comm");
345 return ret;
346 }
347 comm_type t = x.type;
348 if (t == IPC_COMM)
349 ret = ipc_comm_send(x, data, len);
350 else if (t == ZMQ_COMM)
351 ret = zmq_comm_send(x, data, len);
352 else if (t == RPC_COMM)
353 ret = rpc_comm_send(x, data, len);
354 else if (t == SERVER_COMM)
355 ret = server_comm_send(x, data, len);
356 else if (t == CLIENT_COMM)
357 ret = client_comm_send(x, data, len);
358 else if (t == ASCII_FILE_COMM)
359 ret = ascii_file_comm_send(x, data, len);
360 else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
361 ret = ascii_table_comm_send(x, data, len);
362 else {
363 cislog_error("comm_send_single: Unsupported comm_type %d", t);
364 }
365 if (ret >= 0) {
366 time(x.last_send);
367 /* time_t now; */
368 /* time(&now); */
369 /* x.last_send[0] = now; */
370 }
371 return ret;
372 };
373
374
383 static
384 comm_head_t comm_send_multipart_header(const comm_t x, const char * data,
385 const size_t len) {
386 comm_head_t head = init_header(len, NULL, NULL);
387 sprintf(head.id, "%d", rand());
388 head.multipart = 1;
389 head.valid = 1;
390 // Add serializer information to header on first send
391 if ((x.used[0] == 0) && (x.is_file == 0)) {
392 seri_t *serializer;
393 if (x.type == CLIENT_COMM) {
394 comm_t *req_comm = (comm_t*)(x.handle);
395 serializer = req_comm->serializer;
396 } else {
397 serializer = x.serializer;
398 }
399 if (serializer->type == DIRECT_SERI) {
400 head.serializer_type = 0;
401 } else if (serializer->type == FORMAT_SERI) {
402 head.serializer_type = 1;
403 strcpy(head.format_str, (char*)(serializer->info));
404 } else if (serializer->type == ARRAY_SERI) {
405 head.serializer_type = 2;
406 strcpy(head.format_str, (char*)(serializer->info));
407 head.as_array = 1;
408 } else if (serializer->type == ASCII_TABLE_SERI) {
409 head.serializer_type = 1;
410 asciiTable_t *table = (asciiTable_t*)(serializer->info);
411 strcpy(head.format_str, table->format_str);
412 } else if (serializer->type == ASCII_TABLE_ARRAY_SERI) {
413 head.serializer_type = 2;
414 asciiTable_t *table = (asciiTable_t*)(serializer->info);
415 strcpy(head.format_str, table->format_str);
416 head.as_array = 1;
417 } else if (serializer->type == PLY_SERI) {
418 head.serializer_type = 8;
419 } else if (serializer->type == OBJ_SERI) {
420 head.serializer_type = 9;
421 }
422 }
423 const comm_t *x0;
424 if (x.type == SERVER_COMM) {
425 comm_t **res_comm = (comm_t**)(x.info);
426 if (res_comm[0] == NULL) {
427 cislog_error("comm_send_multipart_header(%s): no response comm registered",
428 x.name);
429 head.valid = 0;
430 return head;
431 }
432 x0 = &((*res_comm)[0]);
433 // Why was this necessary?
434 strcpy(head.id, x.address);
435 } else if (x.type == CLIENT_COMM) {
436 if (!(is_eof(data))) {
437 head = client_response_header(x, head);
438 }
439 x0 = (comm_t*)(x.handle);
440 } else {
441 x0 = &x;
442 }
443 // Get ZMQ header info
444 if (x0->type == ZMQ_COMM) {
445 char *reply_address = set_reply_send(x0);
446 if (reply_address == NULL) {
447 cislog_error("comm_send_multipart_header: Could not set reply address.");
448 head.valid = 0;
449 return head;
450 }
451 strcpy(head.zmq_reply, reply_address);
452 }
453 return head;
454 };
455
463 static
464 int comm_send_multipart(const comm_t x, const char *data, const size_t len) {
465 //char headbuf[CIS_MSG_BUF];
466 int headbuf_len = CIS_MSG_BUF;
467 int headlen = 0, ret = -1;
468 if (x.valid == 0) {
469 cislog_error("comm_send_multipart: Invalid comm");
470 return ret;
471 }
472 comm_t xmulti = empty_comm_base();
473 // Get header
474 comm_head_t head = comm_send_multipart_header(x, data, len);
475 if (head.valid == 0) {
476 cislog_error("comm_send_multipart: Invalid header generated.");
477 return -1;
478 }
479 char *headbuf = (char*)malloc(headbuf_len);
480 if (headbuf == NULL) {
481 cislog_error("comm_send_multipart: Failed to malloc headbuf.");
482 return -1;
483 }
484 // Try to send body in header
485 if (len < x.maxMsgSize) {
486 headlen = format_comm_header(head, headbuf, headbuf_len);
487 if (headlen < 0) {
488 cislog_error("comm_send_multipart: Failed to format header.");
489 free(headbuf);
490 return -1;
491 }
492 if (((size_t)headlen + len) < x.maxMsgSize) {
493 if (((size_t)headlen + len + 1) > (size_t)headbuf_len) {
494 char *t_headbuf = (char*)realloc(headbuf, (size_t)headlen + len + 1);
495 if (t_headbuf == NULL) {
496 cislog_error("comm_send_multipart: Failed to realloc headbuf.");
497 free(headbuf);
498 return -1;
499 }
500 headbuf = t_headbuf;
501 headbuf_len = headlen + (int)len + 1;
502 }
503 head.multipart = 0;
504 memcpy(headbuf + headlen, data, len);
505 headlen += (int)len;
506 headbuf[headlen] = '\0';
507 }
508 }
509 // Get head string
510 if (head.multipart == 1) {
511 // Get address for new comm and add to header
512 xmulti = new_comm(NULL, "send", x.type, NULL);
513 if (!(xmulti.valid)) {
514 cislog_error("comm_send_multipart: Failed to initialize a new comm.");
515 free(headbuf);
516 return -1;
517 }
518 xmulti.sent_eof[0] = 1;
519 xmulti.recv_eof[0] = 1;
520 xmulti.is_work_comm = 1;
521 strcpy(head.address, xmulti.address);
522 if (xmulti.type == ZMQ_COMM) {
523 char *reply_address = set_reply_send(&xmulti);
524 if (reply_address == NULL) {
525 cislog_error("comm_send_multipart: Could not set worker reply address.");
526 return -1;
527 }
528 strcpy(head.zmq_reply_worker, reply_address);
529 }
530 headlen = format_comm_header(head, headbuf, headbuf_len);
531 if (headlen < 0) {
532 cislog_error("comm_send_multipart: Failed to format header.");
533 free(headbuf);
534 free_comm(&xmulti);
535 return -1;
536 }
537 }
538 // Send header
539 ret = comm_send_single(x, headbuf, headlen);
540 if (ret < 0) {
541 cislog_error("comm_send_multipart: Failed to send header.");
542 if (head.multipart == 1)
543 free_comm(&xmulti);
544 free(headbuf);
545 return -1;
546 }
547 if (head.multipart == 0) {
548 cislog_debug("comm_send_multipart(%s): %d bytes completed", x.name, head.size);
549 free(headbuf);
550 return ret;
551 }
552 // Send multipart
553 size_t msgsiz;
554 size_t prev = 0;
555 while (prev < head.size) {
556 if ((head.size - prev) > xmulti.maxMsgSize)
557 msgsiz = xmulti.maxMsgSize;
558 else
559 msgsiz = head.size - prev;
560 ret = comm_send_single(xmulti, data + prev, msgsiz);
561 if (ret < 0) {
562 cislog_debug("comm_send_multipart(%s): send interupted at %d of %d bytes.",
563 x.name, prev, head.size);
564 break;
565 }
566 prev += msgsiz;
567 cislog_debug("comm_send_multipart(%s): %d of %d bytes sent",
568 x.name, prev, head.size);
569 }
570 if (ret == 0)
571 cislog_debug("comm_send_multipart(%s): %d bytes completed", x.name, head.size);
572 // Free multipart
573 free_comm(&xmulti);
574 free(headbuf);
575 if (ret >= 0)
576 x.used[0] = 1;
577 return ret;
578 };
579
580
590 static
591 int comm_send(const comm_t x, const char *data, const size_t len) {
592 int ret = -1;
593 if (x.valid == 0) {
594 cislog_error("comm_send: Invalid comm");
595 return ret;
596 }
597 if (x.sent_eof == NULL) {
598 cislog_error("comm_send(%s): sent_eof not initialized.", x.name);
599 return ret;
600 }
601 int sending_eof = 0;
602 if (is_eof(data)) {
603 if (x.sent_eof[0] == 0) {
604 x.sent_eof[0] = 1;
605 if (x.type == CLIENT_COMM) {
606 comm_t *req_comm = (comm_t*)(x.handle);
607 req_comm->sent_eof[0] = 1;
608 }
609 sending_eof = 1;
610 cislog_debug("comm_send(%s): Sending EOF", x.name);
611 } else {
612 cislog_error("comm_send(%s): EOF already sent", x.name);
613 return ret;
614 }
615 }
616 if (((len > x.maxMsgSize) && (x.maxMsgSize > 0)) ||
617 (((x.always_send_header) || (x.used[0] == 0)))) { // && (!(is_eof(data))))) {
618 ret = comm_send_multipart(x, data, len);
619 } else {
620 cislog_debug("comm_send(%s): Sending as single message without a header.",
621 x.name);
622 ret = comm_send_single(x, data, len);
623 }
624 if (sending_eof) {
625 cislog_debug("comm_send(%s): sent EOF, ret = %d", x.name, ret);
626 }
627 if (ret >= 0)
628 x.used[0] = 1;
629 return ret;
630 };
631
637 static
638 int comm_send_eof(const comm_t x) {
639 int ret = -1;
640 char buf[100] = CIS_MSG_EOF;
641 ret = comm_send(x, buf, strlen(buf));
642 return ret;
643 };
644
657 static
658 int comm_recv_single(const comm_t x, char **data, const size_t len,
659 const int allow_realloc) {
660 int ret = -1;
661 if (x.valid == 0) {
662 cislog_error("comm_recv_single: Invalid comm");
663 return ret;
664 }
665 comm_type t = x.type;
666 if (t == IPC_COMM)
667 ret = ipc_comm_recv(x, data, len, allow_realloc);
668 else if (t == ZMQ_COMM)
669 ret = zmq_comm_recv(x, data, len, allow_realloc);
670 else if (t == RPC_COMM)
671 ret = rpc_comm_recv(x, data, len, allow_realloc);
672 else if (t == SERVER_COMM)
673 ret = server_comm_recv(x, data, len, allow_realloc);
674 else if (t == CLIENT_COMM)
675 ret = client_comm_recv(x, data, len, allow_realloc);
676 else if (t == ASCII_FILE_COMM)
677 ret = ascii_file_comm_recv(x, data, len, allow_realloc);
678 else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
679 ret = ascii_table_comm_recv(x, data, len, allow_realloc);
680 else {
681 cislog_error("comm_recv: Unsupported comm_type %d", t);
682 }
683 return ret;
684 };
685
696 static
697 int comm_recv_multipart(const comm_t x, char **data, const size_t len,
698 const size_t headlen, const int allow_realloc) {
699 int ret = -1;
700 if (x.valid == 0) {
701 cislog_error("comm_recv_multipart: Invalid comm");
702 return ret;
703 }
704 usleep(100);
705 comm_head_t head = parse_comm_header(*data, headlen);
706 if (!(head.valid)) {
707 cislog_error("comm_recv_multipart(%s): Error parsing header.", x.name);
708 ret = -1;
709 } else {
710 // Get serializer information from header on first recv
711 if ((x.used[0] == 0) && (x.is_file == 0) && (x.serializer->type == 0)) {
712 int new_type = -1;
713 void *new_info = (void*)(head.format_str);
714 cislog_debug("comm_recv_multipart(%s): Updating serializer type to %d",
715 x.name, head.serializer_type);
716 if (head.serializer_type == 0) {
717 new_type = DIRECT_SERI;
718 } else if (head.serializer_type == 1) {
719 new_type = FORMAT_SERI;
720 } else if (head.serializer_type == 2) {
721 new_type = ASCII_TABLE_ARRAY_SERI;
722 // TODO: Treat this as a separate class
723 // new_type = ARRAY_SERI;
724 } else if (head.serializer_type == 3) {
725 if (head.as_array == 0) {
726 new_type = ASCII_TABLE_SERI;
727 } else {
728 new_type = ASCII_TABLE_ARRAY_SERI;
729 }
730 } else if (head.serializer_type == 8) {
731 new_type = PLY_SERI;
732 } else if (head.serializer_type == 9) {
733 new_type = OBJ_SERI;
734 }
735 if (new_type >= 0) {
736 ret = update_serializer(x.serializer, new_type, new_info);
737 if (ret != 0) {
738 cislog_error("comm_recv_multipart(%s): Error updating serializer.", x.name);
739 return -1;
740 }
741 }
742 // Set name for debug info & simplify formats
743 if ((new_type == ASCII_TABLE_SERI) || (new_type == ASCII_TABLE_ARRAY_SERI)) {
744 asciiTable_t *table = (asciiTable_t*)(x.serializer->info);
745 ret = at_update(table, x.name, "0");
746 if (ret != 0) {
747 cislog_error("comm_recv_multipart(%s): Failed to update asciiTable address.",
748 x.name);
749 return -1;
750 }
751 ret = simplify_formats(table->format_str, CIS_MSG_MAX);
752 if (ret < 0) {
753 cislog_error("comm_recv_multipart(%s): Failed to simplify recvd table format.", x.name);
754 return -1;
755 }
756 } else if (new_type == FORMAT_SERI) {
757 char * format_str = (char*)(x.serializer->info);
758 ret = simplify_formats(format_str, x.serializer->size_info);
759 if (ret < 0) {
760 cislog_error("comm_recv_multipart(%s): Failed to simplify recvd format.", x.name);
761 return -1;
762 }
763 }
764 }
765 if (head.multipart) {
766 // Move part of message after header to front of data
767 memmove(*data, *data + head.bodybeg, head.bodysiz);
768 (*data)[head.bodysiz] = '\0';
769 if (is_eof(*data)) {
770 cislog_debug("comm_recv_multipart(%s): EOF received.", x.name);
771 x.recv_eof[0] = 1;
772 return -2;
773 }
774 // Return early if header contained entire message
775 if (head.size == head.bodysiz) {
776 x.used[0] = 1;
777 return (int)(head.bodysiz);
778 }
779 // Get address for new comm
780 comm_t xmulti = new_comm(head.address, "recv", x.type, NULL);
781 if (!(xmulti.valid)) {
782 cislog_error("comm_recv_multipart: Failed to initialize a new comm.");
783 return -1;
784 }
785 xmulti.sent_eof[0] = 1;
786 xmulti.recv_eof[0] = 1;
787 xmulti.is_work_comm = 1;
788 if (xmulti.type == ZMQ_COMM) {
789 int reply_socket = set_reply_recv(&xmulti, head.zmq_reply_worker);
790 if (reply_socket < 0) {
791 cislog_error("comm_recv_multipart: Failed to set worker reply address.");
792 return -1;
793 }
794 }
795 // Receive parts of message
796 size_t prev = head.bodysiz;
797 size_t msgsiz = 0;
798 // Reallocate data if necessary
799 if ((head.size + 1) > len) {
800 if (allow_realloc) {
801 char *t_data = (char*)realloc(*data, head.size + 1);
802 if (t_data == NULL) {
803 cislog_error("comm_recv_multipart(%s): Failed to realloc buffer",
804 x.name);
805 free(*data);
806 free_comm(&xmulti);
807 return -1;
808 }
809 *data = t_data;
810 } else {
811 cislog_error("comm_recv_multipart(%s): buffer is not large enough",
812 x.name);
813 free_comm(&xmulti);
814 return -1;
815 }
816 }
817 ret = -1;
818 char *pos = (*data) + prev;
819 while (prev < head.size) {
820 msgsiz = head.size - prev + 1;
821 ret = comm_recv_single(xmulti, &pos, msgsiz, 0);
822 if (ret < 0) {
823 cislog_debug("comm_recv_multipart(%s): recv interupted at %d of %d bytes.",
824 x.name, prev, head.size);
825 break;
826 }
827 prev += ret;
828 pos += ret;
829 cislog_debug("comm_recv_multipart(%s): %d of %d bytes received",
830 x.name, prev, head.size);
831 }
832 if (ret > 0) {
833 cislog_debug("comm_recv_multipart(%s): %d bytes completed", x.name, prev);
834 ret = (int)prev;
835 }
836 free_comm(&xmulti);
837 } else {
838 ret = (int)headlen;
839 }
840 }
841 if (ret >= 0)
842 x.used[0] = 1;
843 return ret;
844 };
845
856 static
857 int comm_recv(const comm_t x, char *data, const size_t len) {
858 int ret = comm_recv_single(x, &data, len, 0);
859 if (ret > 0) {
860 if (is_eof(data)) {
861 cislog_debug("comm_recv(%s): EOF received.", x.name);
862 x.recv_eof[0] = 1;
863 ret = -2;
864 } else {
865 ret = comm_recv_multipart(x, &data, len, ret, 0);
866 }
867 } else {
868 cislog_error("comm_recv_realloc(%s): Failed to receive header or message.",
869 x.name);
870 }
871 return ret;
872 };
873
883 static
884 int comm_recv_realloc(const comm_t x, char **data, const size_t len) {
885 int ret = comm_recv_single(x, data, len, 1);
886 if (ret > 0) {
887 if (is_eof(*data)) {
888 cislog_debug("comm_recv_realloc(%s): EOF received.", x.name);
889 x.recv_eof[0] = 1;
890 ret = -2;
891 } else {
892 ret = comm_recv_multipart(x, data, len, ret, 1);
893 }
894 } else {
895 cislog_error("comm_recv_realloc(%s): Failed to receive header or message.",
896 x.name);
897 }
898 return ret;
899 };
900
901
903 static
904 int comm_send_nolimit(const comm_t x, const char *data, const size_t len) {
905 return comm_send(x, data, len);
906 };
907
913 static
914 int comm_send_nolimit_eof(const comm_t x) {
915 int ret = -1;
916 if (x.valid == 0) {
917 cislog_error("comm_send_nolimit_eof: Invalid comm");
918 return ret;
919 }
920 if (x.sent_eof == NULL) {
921 cislog_error("comm_send_nolimit_eof(%s): sent_eof not initialized.", x.name);
922 return ret;
923 }
924 if (x.sent_eof[0] == 0) {
925 char buf[2048] = CIS_MSG_EOF;
926 ret = comm_send_nolimit(x, buf, strlen(buf));
927 x.sent_eof[0] = 1;
928 } else {
929 cislog_error("comm_send_nolimit_eof(%s): EOF already sent", x.name);
930 }
931 return ret;
932 };
933
947 static
948 int comm_recv_nolimit(const comm_t x, char **data, const size_t len) {
949 return comm_recv_realloc(x, data, len);
950 };
951
962 static
963 int vcommSend(const comm_t x, va_list ap) {
964 int ret = -1;
965 if (x.valid == 0) {
966 cislog_error("vcommSend: Invalid comm");
967 return ret;
968 }
969 size_t buf_siz = CIS_MSG_BUF;
970 // char *buf = NULL;
971 char *buf = (char*)malloc(buf_siz);
972 if (buf == NULL) {
973 cislog_error("vcommSend(%s): Failed to alloc buffer", x.name);
974 return -1;
975 }
976 seri_t *serializer = x.serializer;
977 if (x.type == CLIENT_COMM) {
978 comm_t *handle = (comm_t*)(x.handle);
979 serializer = handle->serializer;
980 }
981 int args_used = 0;
982 ret = serialize(*serializer, &buf, buf_siz, 1, &args_used, ap);
983 if (ret < 0) {
984 cislog_error("vcommSend(%s): serialization error", x.name);
985 free(buf);
986 return -1;
987 }
988 ret = comm_send(x, buf, ret);
989 cislog_debug("vcommSend(%s): comm_send returns %d", x.name, ret);
990 free(buf);
991 if (ret < 0) {
992 return ret;
993 } else {
994 return args_used;
995 }
996 };
997
1010 static
1011 int vcommRecv(const comm_t x, va_list ap) {
1012 int ret = -1;
1013 if (x.valid == 0) {
1014 cislog_error("vcommRecv: Invalid comm");
1015 return ret;
1016 }
1017 // Receive message
1018 size_t buf_siz = CIS_MSG_BUF;
1019 /* char *buf = NULL; */
1020 char *buf = (char*)malloc(buf_siz);
1021 if (buf == NULL) {
1022 cislog_error("vcommSend(%s): Failed to alloc buffer", x.name);
1023 return -1;
1024 }
1025 ret = comm_recv_nolimit(x, &buf, buf_siz);
1026 if (ret < 0) {
1027 // cislog_error("vcommRecv(%s): Error receiving.", x.name);
1028 free(buf);
1029 return ret;
1030 }
1031 cislog_debug("vcommRecv(%s): comm_recv returns %d: %.10s...", x.name, ret, buf);
1032 // Deserialize message
1033 seri_t *serializer = x.serializer;
1034 if (x.type == SERVER_COMM) {
1035 comm_t *handle = (comm_t*)(x.handle);
1036 serializer = handle->serializer;
1037 }
1038 ret = deserialize(*serializer, buf, ret, ap);
1039 if (ret < 0) {
1040 cislog_error("vcommRecv(%s): error deserializing message (ret=%d)",
1041 x.name, ret);
1042 free(buf);
1043 return -1;
1044 }
1045 cislog_debug("vcommRecv(%s): deserialize_format returns %d", x.name, ret);
1046 free(buf);
1047 return ret;
1048 };
1049
1050 #define vcommSend_nolimit vcommSend
1051 #define vcommRecv_nolimit vcommRecv
1052
1053 #ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
1054 }
1055 #endif
1056
1057 #endif /*CISCOMMUNICATION_H_*/
comm_t::handle
void * handle
Pointer to handle for comm.
Definition: CommBase.h:29
asciiTable_t::format_str
char format_str[LINE_SIZE_MAX]
Format string for rows.
Definition: AsciiTable.h:82
comm_t::info
void * info
Pointer to any extra info comm requires.
Definition: CommBase.h:30
comm_t
Communication structure.
Definition: CommBase.h:23
comm_t::address
char address[COMM_ADDRESS_SIZE]
Comm address.
Definition: CommBase.h:26
comm_head_t::zmq_reply_worker
char zmq_reply_worker[COMMBUFFSIZ]
Reply address for worker socket.
Definition: comm_header.h:35
comm_t::is_work_comm
int is_work_comm
Flag specifying if comm is a temporary work comm.
Definition: CommBase.h:41
seri_t
Serializer structure.
Definition: SerializeBase.h:19
comm_t::last_send
time_t * last_send
Clock output at time of last send.
Definition: CommBase.h:35
seri_t::info
void * info
Pointer to any extra info serializer requires.
Definition: SerializeBase.h:21
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_t::maxMsgSize
size_t maxMsgSize
The maximum message size.
Definition: CommBase.h:32
seri_t::size_info
size_t size_info
Size of allocate space for info.
Definition: SerializeBase.h:22
comm_t::used
int * used
Flag specifying if the comm has been used.
Definition: CommBase.h:38
comm_head_t::address
char address[COMMBUFFSIZ]
Address that message will comm in on.
Definition: comm_header.h:21
comm_t::type
comm_type type
Comm type.
Definition: CommBase.h:24
comm_head_t::valid
int valid
1 if the header is valid, 0 otherwise.
Definition: comm_header.h:25
comm_t::is_file
int is_file
Flag specifying if the comm connects directly to a file.
Definition: CommBase.h:40
comm_t::always_send_header
int always_send_header
1 if comm should always send a header.
Definition: CommBase.h:33
comm_t::serializer
seri_t * serializer
Serializer for comm messages.
Definition: CommBase.h:31
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_t::direction
char direction[COMM_DIR_SIZE]
send or recv for direction messages will go.
Definition: CommBase.h:27
comm_t::name
char name[COMM_NAME_SIZE]
Comm name.
Definition: CommBase.h:25
comm_t::sent_eof
int * sent_eof
Flag specifying if EOF has been sent.
Definition: CommBase.h:36
comm_head_t::size
size_t size
Size of incoming message.
Definition: comm_header.h:20
comm_t::valid
int valid
1 if communicator initialized, 0 otherwise.
Definition: CommBase.h:28
comm_t::recv_eof
int * recv_eof
Flag specifying if EOF has been received.
Definition: CommBase.h:37
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
asciiTable_t
Structure containing information about an ASCII table.
Definition: AsciiTable.h:80
comm_head_t::id
char id[COMMBUFFSIZ]
Unique ID associated with this message.
Definition: comm_header.h:26
comm_t::index_in_register
int index_in_register
Index of the comm in the comm register.
Definition: CommBase.h:34
seri_t::type
seri_type type
Serializer type.
Definition: SerializeBase.h:20
comm_head_t
Header information passed by comms for multipart messages.
Definition: comm_header.h:19