6 #include "comm_header.h" 18 static unsigned _zmq_rand_seeded = 0;
19 static unsigned _last_port_set = 0;
20 static unsigned _cisSocketsCreated = 0;
21 static int _last_port = 49152;
23 static char _reply_msg[100] =
"CIS_REPLY";
24 static char _purge_msg[100] =
"CIS_PURGE";
25 static int _zmq_sleeptime = 10000;
30 typedef struct zmq_reply_t {
41 int zmq_comm_nmsg(
const comm_t x);
43 int zmq_comm_recv(
const comm_t x,
char **data,
const size_t len,
44 const int allow_realloc);
53 int free_zmq_reply(zmq_reply_t *x) {
56 if (x->sockets != NULL) {
57 for (i = 0; i < x->nsockets; i++) {
58 if (x->sockets[i] != NULL) {
59 zsock_destroy(&(x->sockets[i]));
65 if (x->addresses != NULL) {
66 for (i = 0; i < x->nsockets; i++) {
67 if (x->addresses[i] != NULL) {
68 free(x->addresses[i]);
69 x->addresses[i] = NULL;
85 int init_zmq_reply(
comm_t *comm) {
86 zmq_reply_t *zrep = (zmq_reply_t*)malloc(
sizeof(zmq_reply_t));
88 cislog_error(
"init_zmq_reply(%s): Failed to malloc reply.", comm->
name);
93 zrep->addresses = NULL;
96 comm->
reply = (
void*)zrep;
107 int find_reply_socket(
const comm_t *comm,
const char *address) {
110 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
112 cislog_error(
"find_reply_socket(%s): Reply structure not initialized.", comm->
name);
116 for (i = 0; i < zrep->nsockets; i++) {
117 if (strcmp(zrep->addresses[i], address) == 0) {
131 int do_reply_send(
const comm_t *comm) {
133 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
135 cislog_error(
"do_reply_send(%s): Reply structure not initialized.", comm->
name);
139 zsock_t *s = (zsock_t*)(zrep->sockets[0]);
141 cislog_error(
"do_reply_send(%s): Socket is NULL.", comm->
name);
145 cislog_debug(
"do_reply_send(%s): address=%s, begin", comm->
name,
147 #if defined(__cplusplus) && defined(_WIN32) 150 zpoller_t *poller = zpoller_new(s, NULL);
152 cislog_error(
"do_reply_send(%s): Could not create poller", comm->
name);
156 cislog_debug(
"do_reply_send(%s): waiting on poller...", comm->
name);
157 void *p = zpoller_wait(poller, -1);
159 cislog_debug(
"do_reply_send(%s): poller returned", comm->
name);
160 zpoller_destroy(&poller);
162 if (zpoller_terminated(poller)) {
163 cislog_error(
"do_reply_send(%s): Poller interrupted", comm->
name);
164 }
else if (zpoller_expired(poller)) {
165 cislog_error(
"do_reply_send(%s): Poller expired", comm->
name);
167 cislog_error(
"do_reply_send(%s): Poller failed", comm->
name);
173 zframe_t *msg = zframe_recv(s);
175 cislog_error(
"do_reply_send(%s): did not receive", comm->
name);
178 char *msg_data = (
char*)zframe_data(msg);
181 if (strcmp(msg_data, CIS_MSG_EOF) == 0) {
182 cislog_debug(
"do_reply_send(%s): EOF received", comm->
name);
186 }
else if (strcmp(msg_data, _purge_msg) == 0) {
191 int ret = zframe_send(&msg, s, 0);
194 cislog_error(
"do_reply_send(%s): Error sending reply frame.", comm->
name);
195 zframe_destroy(&msg);
198 cislog_debug(
"do_reply_send(%s): PURGE received", comm->
name);
201 ret = do_reply_send(comm);
206 cislog_debug(
"do_reply_send(%s): address=%s, end", comm->
name,
219 int do_reply_recv(
const comm_t *comm,
const int isock,
const char *msg) {
221 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
223 cislog_error(
"do_reply_recv(%s): Reply structure not initialized.", comm->
name);
226 zsock_t *s = (zsock_t*)(zrep->sockets[isock]);
228 cislog_error(
"do_reply_recv(%s): Socket is NULL.", comm->
name);
231 cislog_debug(
"do_reply_recv(%s): address=%s, begin", comm->
name,
232 zrep->addresses[isock]);
233 zframe_t *msg_send = zframe_new(msg, strlen(msg));
234 if (msg_send == NULL) {
235 cislog_error(
"do_reply_recv(%s): Error creating frame.", comm->
name);
239 int ret = zframe_send(&msg_send, s, 0);
241 cislog_error(
"do_reply_recv(%s): Error sending confirmation.", comm->
name);
242 zframe_destroy(&msg_send);
245 if (strcmp(msg, CIS_MSG_EOF) == 0) {
248 zsock_set_linger(s, _zmq_sleeptime);
252 zframe_t *msg_recv = zframe_recv(s);
253 if (msg_recv == NULL) {
254 cislog_error(
"do_reply_recv(%s): did not receive", comm->
name);
257 zframe_destroy(&msg_recv);
259 cislog_debug(
"do_reply_recv(%s): address=%s, end", comm->
name,
260 zrep->addresses[isock]);
270 char *set_reply_send(
const comm_t *comm) {
273 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
275 cislog_error(
"set_reply_send(%s): Reply structure not initialized.", comm->
name);
279 if (zrep->nsockets == 0) {
280 zrep->sockets = (zsock_t**)malloc(
sizeof(zsock_t*));
281 if (zrep->sockets == NULL) {
282 cislog_error(
"set_reply_send(%s): Error mallocing sockets.", comm->
name);
286 zrep->sockets[0] = zsock_new(ZMQ_REP);
287 zsock_set_linger(zrep->sockets[0], 0);
288 if (zrep->sockets[0] == NULL) {
289 cislog_error(
"set_reply_send(%s): Could not initialize empty socket.",
293 char protocol[50] =
"tcp";
294 char host[50] =
"localhost";
295 if (strcmp(host,
"localhost") == 0)
296 strcpy(host,
"127.0.0.1");
298 if (_last_port_set == 0) {
299 cislog_debug(
"model_index = %s", getenv(
"CIS_MODEL_INDEX"));
300 _last_port = 49152 + 1000 * atoi(getenv(
"CIS_MODEL_INDEX"));
302 cislog_debug(
"_last_port = %d", _last_port);
304 sprintf(address,
"%s://%s:*[%d-]", protocol, host, _last_port + 1);
305 int port = zsock_bind(zrep->sockets[0],
"%s", address);
307 cislog_error(
"check_reply_send(%s): Could not bind socket to address = %s",
308 comm->
name, address);
312 sprintf(address,
"%s://%s:%d", protocol, host, port);
313 zrep->addresses = (
char**)malloc(
sizeof(
char*));
314 zrep->addresses[0] = (
char*)malloc((strlen(address) + 1)*
sizeof(
char));
315 strcpy(zrep->addresses[0], address);
316 cislog_debug(
"check_reply_send(%s): New reply socket: %s", comm->
name, address);
318 out = zrep->addresses[0];
328 int set_reply_recv(
const comm_t *comm,
const char* address) {
331 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
333 cislog_error(
"set_reply_recv(%s): Reply structure not initialized.", comm->
name);
337 int isock = find_reply_socket(comm, address);
340 cislog_error(
"set_reply_recv(%s): Error locating socket.", comm->
name);
344 zrep->sockets = (zsock_t**)realloc(zrep->sockets,
345 sizeof(zsock_t*)*(zrep->nsockets + 1));
346 if (zrep->sockets == NULL) {
347 cislog_error(
"set_reply_recv(%s): Error reallocing sockets.", comm->
name);
350 zrep->addresses = (
char**)realloc(zrep->addresses,
351 sizeof(
char*)*(zrep->nsockets + 1));
352 if (zrep->addresses == NULL) {
353 cislog_error(
"set_reply_recv(%s): Error reallocing addresses.", comm->
name);
357 isock = zrep->nsockets;
359 zrep->sockets[isock] = zsock_new(ZMQ_REQ);
360 zsock_set_linger(zrep->sockets[isock], 0);
361 if (zrep->sockets[isock] == NULL) {
362 cislog_error(
"set_reply_recv(%s): Could not initialize empty socket.",
366 zrep->addresses[isock] = (
char*)malloc(
sizeof(
char)*(strlen(address) + 1));
367 if (zrep->addresses[isock] == NULL) {
368 cislog_error(
"set_reply_recv(%s): Could not realloc new address.",
372 strcpy(zrep->addresses[isock], address);
373 int ret = zsock_connect(zrep->sockets[isock],
"%s", address);
375 cislog_error(
"set_reply_recv(%s): Could not connect to socket.",
379 cislog_debug(
"set_reply_recv(%s): New recv socket: %s", comm->
name, address);
392 char* check_reply_send(
const comm_t *comm,
const char *data,
const int len,
394 char *out = (
char*)malloc(len + 1);
395 memcpy(out, data, len + 1);
410 int check_reply_recv(
const comm_t *comm,
char *data,
const size_t len) {
411 int new_len = (int)len;
414 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
416 cislog_error(
"check_reply_recv(%s): Reply structure not initialized.", comm->
name);
424 if ((comm->
is_work_comm == 1) && (zrep->nsockets == 1)) {
425 address_len = strlen(zrep->addresses[0]);
426 memcpy(address, zrep->addresses[0], address_len);
429 memcpy(address, head.
zmq_reply, address_len);
431 cislog_error(
"check_reply_recv(%s): Error parsing reply header in '%s'",
435 address[address_len] =
'\0';
437 int isock = set_reply_recv(comm, address);
439 cislog_error(
"check_reply_recv(%s): Error setting reply socket.");
443 ret = do_reply_recv(comm, isock, _reply_msg);
445 cislog_error(
"check_reply_recv(%s): Error during reply.", comm->
name);
457 int new_zmq_address(
comm_t *comm) {
459 char protocol[50] =
"tcp";
460 char host[50] =
"localhost";
462 if (strcmp(host,
"localhost") == 0)
463 strcpy(host,
"127.0.0.1");
464 if ((strcmp(protocol,
"inproc") == 0) ||
465 (strcmp(protocol,
"ipc") == 0)) {
468 if (!(_zmq_rand_seeded)) {
469 srand(ptr2seed(comm));
470 _zmq_rand_seeded = 1;
472 while (key == 0) key = rand();
473 if (strlen(comm->
name) == 0)
474 sprintf(comm->
name,
"tempnewZMQ-%d", key);
475 sprintf(address,
"%s://%s", protocol, comm->
name);
477 if (_last_port_set == 0) {
478 cislog_debug(
"model_index = %s", getenv(
"CIS_MODEL_INDEX"));
479 _last_port = 49152 + 1000 * atoi(getenv(
"CIS_MODEL_INDEX"));
481 cislog_debug(
"_last_port = %d", _last_port);
483 sprintf(address,
"%s://%s:*[%d-]", protocol, host, _last_port + 1);
487 zsock_t *s = zsock_new(ZMQ_PAIR);
489 cislog_error(
"new_zmq_address: Could not initialize empty socket.");
492 zsock_set_linger(s, 0);
493 int port = zsock_bind(s,
"%s", address);
495 cislog_error(
"new_zmq_address: Could not bind socket to address = %s",
500 if ((strcmp(protocol,
"inproc") != 0) &&
501 (strcmp(protocol,
"ipc") != 0)) {
503 sprintf(address,
"%s://%s:%d", protocol, host, port);
505 strcpy(comm->
address, address);
506 cislog_debug(
"new_zmq_address: Bound socket to %s", comm->
address);
507 if (strlen(comm->
name) == 0)
508 sprintf(comm->
name,
"tempnewZMQ-%d", port);
510 _cisSocketsCreated++;
512 int ret = init_zmq_reply(comm);
522 int init_zmq_comm(
comm_t *comm) {
524 if (comm->
valid == 0)
526 zsock_t *s = zsock_new(ZMQ_PAIR);
528 cislog_error(
"init_zmq_address: Could not initialize empty socket.");
531 zsock_set_linger(s, 0);
532 ret = zsock_connect(s,
"%s", comm->
address);
534 cislog_error(
"init_zmq_address: Could not connect socket to address = %s",
539 cislog_debug(
"init_zmq_address: Connected socket to %s", comm->
address);
540 if (strlen(comm->
name) == 0)
541 sprintf(comm->
name,
"tempinitZMQ-%s", comm->
address);
544 ret = init_zmq_reply(comm);
555 int free_zmq_comm(
comm_t *x) {
561 if (_cis_error_flag == 0) {
562 size_t data_len = 100;
563 char *data = (
char*)malloc(data_len);
564 while (zmq_comm_nmsg(*x) > 0) {
565 ret = zmq_comm_recv(*x, &data, data_len, 1);
577 if (x->
reply != NULL) {
578 zmq_reply_t *zrep = (zmq_reply_t*)(x->
reply);
580 ret = free_zmq_reply(zrep);
585 zsock_t *s = (zsock_t*)(x->
handle);
587 cislog_debug(
"Destroying socket: %s", x->
address);
601 int zmq_comm_nmsg(
const comm_t x) {
605 zsock_t *s = (zsock_t*)(x.
handle);
606 zpoller_t *poller = zpoller_new(s, NULL);
607 if (poller == NULL) {
608 cislog_error(
"zmq_comm_nmsg: Could not create poller");
611 void *p = zpoller_wait(poller, 1);
613 if (zpoller_terminated(poller)) {
614 cislog_error(
"zmq_comm_nmsg: Poller interrupted");
622 zpoller_destroy(&poller);
634 zmq_reply_t *zrep = (zmq_reply_t*)(x.
reply);
636 cislog_debug(
"zmq_comm_nmsg(%s): nmsg = %d, nrep = %d",
637 x.
name, zrep->n_msg, zrep->n_rep);
638 out = zrep->n_msg - zrep->n_rep;
654 int zmq_comm_send(
const comm_t x,
const char *data,
const size_t len) {
655 cislog_debug(
"zmq_comm_send(%s): %d bytes", x.
name, len);
656 if (comm_base_send(x, data, len) == -1)
658 zsock_t *s = (zsock_t*)(x.
handle);
660 cislog_error(
"zmq_comm_send(%s): socket handle is NULL", x.
name);
664 char *new_data = check_reply_send(&x, data, (
int)len, &new_len);
665 if (new_data == NULL) {
666 cislog_error(
"zmq_comm_send(%s): Adding reply address failed.", x.
name);
669 zframe_t *f = zframe_new(new_data, new_len);
672 cislog_error(
"zmq_comm_send(%s): frame handle is NULL", x.
name);
674 ret = zframe_send(&f, s, 0);
676 cislog_error(
"zmq_comm_send(%s): Error in zframe_send", x.
name);
682 ret = do_reply_send(&x);
685 cislog_error(
"zmq_comm_send(%s): EOF received", x.
name);
687 cislog_error(
"zmq_comm_send(%s): Error in do_reply_send", x.
name);
691 cislog_debug(
"zmq_comm_send(%s): returning %d", x.
name, ret);
709 int zmq_comm_recv(
const comm_t x,
char **data,
const size_t len,
710 const int allow_realloc) {
711 cislog_debug(
"zmq_comm_recv(%s)", x.
name);
712 zsock_t *s = (zsock_t*)(x.
handle);
714 cislog_error(
"zmq_comm_recv(%s): socket handle is NULL", x.
name);
718 int nmsg = zmq_comm_nmsg(x);
719 if (nmsg < 0)
return -1;
720 else if (nmsg > 0)
break;
722 cislog_debug(
"zmq_comm_recv(%s): no messages, sleep", x.
name);
723 usleep(CIS_SLEEP_TIME);
726 zframe_t *out = zframe_recv(s);
728 cislog_debug(
"zmq_comm_recv(%s): did not receive", x.
name);
731 size_t len_recv = zframe_size(out) + 1;
732 if (len_recv > len) {
734 cislog_debug(
"zmq_comm_recv(%s): reallocating buffer from %d to %d bytes.",
735 x.
name, len, len_recv);
736 (*data) = (
char*)realloc(*data, len_recv);
738 cislog_error(
"zmq_comm_recv(%s): failed to realloc buffer.", x.
name);
739 zframe_destroy(&out);
743 cislog_error(
"zmq_comm_recv(%s): buffer (%d bytes) is not large enough for message (%d bytes)",
744 x.
name, len, len_recv);
745 zframe_destroy(&out);
746 return -((int)(len_recv - 1));
749 memcpy(*data, zframe_data(out), len_recv);
750 (*data)[len_recv-1] =
'\0';
751 zframe_destroy(&out);
752 int ret = (int)len_recv - 1;
753 ret = check_reply_recv(&x, *data, (
size_t)ret);
754 cislog_debug(
"zmq_comm_recv(%s): returning %d", x.
name, ret);
766 void zmq_install_error() {
767 cislog_error(
"Compiler flag 'ZMQINSTALLED' not defined so ZMQ bindings are disabled.");
776 int free_zmq_comm(
comm_t *x) {
787 int new_zmq_address(
comm_t *comm) {
798 int init_zmq_comm(
comm_t *comm) {
809 int zmq_comm_nmsg(
const comm_t x) {
824 int zmq_comm_send(
const comm_t x,
const char *data,
const size_t len) {
842 int zmq_comm_recv(
const comm_t x,
char **data,
const size_t len,
843 const int allow_realloc) {
854 char *set_reply_send(
const comm_t *comm) {
865 int set_reply_recv(
const comm_t *comm,
const char* address) {
void * handle
Pointer to handle for comm.
Definition: CommBase.h:29
Communication structure.
Definition: CommBase.h:23
char address[COMM_ADDRESS_SIZE]
Comm address.
Definition: CommBase.h:26
int is_work_comm
Flag specifying if comm is a temporary work comm.
Definition: CommBase.h:41
int always_send_header
1 if comm should always send a header.
Definition: CommBase.h:33
char zmq_reply[COMMBUFFSIZ]
Reply address for ZMQ sockets.
Definition: comm_header.h:34
char direction[COMM_DIR_SIZE]
send or recv for direction messages will go.
Definition: CommBase.h:27
char name[COMM_NAME_SIZE]
Comm name.
Definition: CommBase.h:25
int valid
1 if communicator initialized, 0 otherwise.
Definition: CommBase.h:28
int * recv_eof
Flag specifying if EOF has been received.
Definition: CommBase.h:37
void * reply
Reply information.
Definition: CommBase.h:39
Header information passed by comms for multipart messages.
Definition: comm_header.h:19