11 static unsigned _zmq_rand_seeded = 0;
12 static unsigned _last_port_set = 0;
13 static unsigned _cisSocketsCreated = 0;
14 static int _last_port = 49152;
16 static char _reply_msg[100] =
"CIS_REPLY";
17 static char _purge_msg[100] =
"CIS_PURGE";
18 static int _zmq_sleeptime = 10000;
23 typedef struct zmq_reply_t {
34 int zmq_comm_nmsg(
const comm_t x);
36 int zmq_comm_recv(
const comm_t x,
char **data,
const size_t len,
37 const int allow_realloc);
46 int free_zmq_reply(zmq_reply_t *x) {
49 if (x->sockets != NULL) {
50 for (i = 0; i < x->nsockets; i++) {
51 if (x->sockets[i] != NULL) {
52 zsock_destroy(&(x->sockets[i]));
58 if (x->addresses != NULL) {
59 for (i = 0; i < x->nsockets; i++) {
60 if (x->addresses[i] != NULL) {
61 free(x->addresses[i]);
62 x->addresses[i] = NULL;
78 int init_zmq_reply(
comm_t *comm) {
79 zmq_reply_t *zrep = (zmq_reply_t*)malloc(
sizeof(zmq_reply_t));
81 cislog_error(
"init_zmq_reply(%s): Failed to malloc reply.", comm->
name);
86 zrep->addresses = NULL;
89 comm->
reply = (
void*)zrep;
100 int find_reply_socket(
const comm_t *comm,
const char *address) {
103 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
105 cislog_error(
"find_reply_socket(%s): Reply structure not initialized.", comm->
name);
109 for (i = 0; i < zrep->nsockets; i++) {
110 if (strcmp(zrep->addresses[i], address) == 0) {
124 int do_reply_send(
const comm_t *comm) {
126 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
128 cislog_error(
"do_reply_send(%s): Reply structure not initialized.", comm->
name);
132 zsock_t *s = (zsock_t*)(zrep->sockets[0]);
134 cislog_error(
"do_reply_send(%s): Socket is NULL.", comm->
name);
138 cislog_debug(
"do_reply_send(%s): address=%s, begin", comm->
name,
140 zpoller_t *poller = zpoller_new(s, NULL);
141 if (poller == NULL) {
142 cislog_error(
"do_reply_send(%s): Could not create poller", comm->
name);
145 void *p = zpoller_wait(poller, -1);
146 zpoller_destroy(&poller);
148 if (zpoller_terminated(poller)) {
149 cislog_error(
"do_reply_send(%s): Poller interrupted", comm->
name);
150 }
else if (zpoller_expired(poller)) {
151 cislog_error(
"do_reply_send(%s): Poller expired", comm->
name);
153 cislog_error(
"do_reply_send(%s): Poller failed", comm->
name);
158 zframe_t *msg = zframe_recv(s);
160 cislog_error(
"do_reply_send(%s): did not receive", comm->
name);
163 char *msg_data = (
char*)zframe_data(msg);
166 if (strcmp(msg_data, CIS_MSG_EOF) == 0) {
167 cislog_debug(
"do_reply_send(%s): EOF received", comm->
name);
171 }
else if (strcmp(msg_data, _purge_msg) == 0) {
176 int ret = zframe_send(&msg, s, 0);
179 cislog_error(
"do_reply_send(%s): Error sending reply frame.", comm->
name);
180 zframe_destroy(&msg);
183 cislog_debug(
"do_reply_send(%s): PURGE received", comm->
name);
186 ret = do_reply_send(comm);
191 cislog_debug(
"do_reply_send(%s): address=%s, end", comm->
name,
204 int do_reply_recv(
const comm_t *comm,
const int isock,
const char *msg) {
206 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
208 cislog_error(
"do_reply_recv(%s): Reply structure not initialized.", comm->
name);
211 zsock_t *s = (zsock_t*)(zrep->sockets[isock]);
213 cislog_error(
"do_reply_recv(%s): Socket is NULL.", comm->
name);
216 cislog_debug(
"do_reply_recv(%s): address=%s, begin", comm->
name,
217 zrep->addresses[isock]);
218 zframe_t *msg_send = zframe_new(msg, strlen(msg));
219 if (msg_send == NULL) {
220 cislog_error(
"do_reply_recv(%s): Error creating frame.", comm->
name);
224 int ret = zframe_send(&msg_send, s, 0);
226 cislog_error(
"do_reply_recv(%s): Error sending confirmation.", comm->
name);
227 zframe_destroy(&msg_send);
230 if (strcmp(msg, CIS_MSG_EOF) == 0) {
233 zsock_set_linger(s, _zmq_sleeptime);
237 zframe_t *msg_recv = zframe_recv(s);
238 if (msg_recv == NULL) {
239 cislog_error(
"do_reply_recv(%s): did not receive", comm->
name);
242 zframe_destroy(&msg_recv);
244 cislog_debug(
"do_reply_recv(%s): address=%s, end", comm->
name,
245 zrep->addresses[isock]);
257 char* check_reply_send(
const comm_t *comm,
const char *data,
const int len,
262 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
264 cislog_error(
"check_reply_send(%s): Reply structure not initialized.", comm->
name);
268 if (zrep->nsockets == 0) {
269 zrep->sockets = (zsock_t**)malloc(
sizeof(zsock_t*));
270 if (zrep->sockets == NULL) {
271 cislog_error(
"check_reply_send(%s): Error mallocing sockets.", comm->
name);
275 zrep->sockets[0] = zsock_new(ZMQ_REP);
276 zsock_set_linger(zrep->sockets[0], 0);
277 if (zrep->sockets[0] == NULL) {
278 cislog_error(
"check_reply_send(%s): Could not initialize empty socket.",
282 char protocol[50] =
"tcp";
283 char host[50] =
"localhost";
284 if (strcmp(host,
"localhost") == 0)
285 strcpy(host,
"127.0.0.1");
287 if (_last_port_set == 0) {
288 cislog_debug(
"model_index = %s", getenv(
"CIS_MODEL_INDEX"));
289 _last_port = 49152 + 1000 * atoi(getenv(
"CIS_MODEL_INDEX"));
291 cislog_debug(
"_last_port = %d", _last_port);
293 sprintf(address,
"%s://%s:*[%d-]", protocol, host, _last_port + 1);
294 int port = zsock_bind(zrep->sockets[0],
"%s", address);
296 cislog_error(
"check_reply_send(%s): Could not bind socket to address = %s",
297 comm->
name, address);
301 sprintf(address,
"%s://%s:%d", protocol, host, port);
302 zrep->addresses = (
char**)malloc(
sizeof(
char*));
303 zrep->addresses[0] = (
char*)malloc((strlen(address) + 1)*
sizeof(
char));
304 strcpy(zrep->addresses[0], address);
307 out = (
char*)malloc(2*(strlen(_reply_msg) + 2) +
308 strlen(zrep->addresses[0]) + len + 1);
309 sprintf(out,
":%s:%s:%s:", _reply_msg, zrep->addresses[0], _reply_msg);
310 new_len[0] = len + (int)strlen(out);
311 memcpy(out + strlen(out), data, len);
312 out[new_len[0]] =
'\0';
326 int check_reply_recv(
const comm_t *comm,
char *data,
const size_t len) {
327 int new_len = (int)len;
330 zmq_reply_t *zrep = (zmq_reply_t*)(comm->
reply);
332 cislog_error(
"check_reply_recv(%s): Reply structure not initialized.", comm->
name);
338 sprintf(re_reply,
":%s:(.*):%s:", _reply_msg, _reply_msg);
340 ret = find_match(re_reply, data, &sind, &eind);
342 cislog_error(
"check_reply_recv(%s): Error parsing reply header in '%s'",
346 size_t headsiz = (eind-sind);
347 new_len = (int)(len - headsiz);
349 headsiz -= (2*(strlen(_reply_msg) + 2));
350 memcpy(address, data + sind + strlen(_reply_msg) + 2, headsiz);
351 address[headsiz] =
'\0';
352 memmove(data, data + eind, new_len);
353 data[new_len] =
'\0';
355 int isock = find_reply_socket(comm, address);
358 cislog_error(
"check_reply_recv(%s): Error locating socket.", comm->
name);
362 zrep->sockets = (zsock_t**)realloc(zrep->sockets,
363 sizeof(zsock_t*)*(zrep->nsockets + 1));
364 if (zrep->sockets == NULL) {
365 cislog_error(
"check_reply_recv(%s): Error reallocing sockets.", comm->
name);
368 zrep->addresses = (
char**)realloc(zrep->addresses,
369 sizeof(
char*)*(zrep->nsockets + 1));
370 if (zrep->addresses == NULL) {
371 cislog_error(
"check_reply_recv(%s): Error reallocing addresses.", comm->
name);
375 isock = zrep->nsockets;
377 zrep->sockets[isock] = zsock_new(ZMQ_REQ);
378 zsock_set_linger(zrep->sockets[isock], 0);
379 if (zrep->sockets[isock] == NULL) {
380 cislog_error(
"check_reply_recv(%s): Could not initialize empty socket.",
384 zrep->addresses[isock] = (
char*)malloc(
sizeof(
char)*(strlen(address) + 1));
385 if (zrep->addresses[isock] == NULL) {
386 cislog_error(
"check_reply_recv(%s): Could not realloc new address.",
390 strcpy(zrep->addresses[isock], address);
391 ret = zsock_connect(zrep->sockets[isock],
"%s", address);
393 cislog_error(
"check_reply_recv(%s): Could not connect to socket.",
399 ret = do_reply_recv(comm, isock, _reply_msg);
401 cislog_error(
"check_reply_recv(%s): Error during reply.", comm->
name);
413 int new_zmq_address(
comm_t *comm) {
415 char protocol[50] =
"tcp";
416 char host[50] =
"localhost";
418 if (strcmp(host,
"localhost") == 0)
419 strcpy(host,
"127.0.0.1");
420 if ((strcmp(protocol,
"inproc") == 0) ||
421 (strcmp(protocol,
"ipc") == 0)) {
424 if (!(_zmq_rand_seeded)) {
425 srand(ptr2seed(comm));
426 _zmq_rand_seeded = 1;
428 while (key == 0) key = rand();
429 if (strlen(comm->
name) == 0)
430 sprintf(comm->
name,
"tempnewZMQ-%d", key);
431 sprintf(address,
"%s://%s", protocol, comm->
name);
433 if (_last_port_set == 0) {
434 cislog_debug(
"model_index = %s", getenv(
"CIS_MODEL_INDEX"));
435 _last_port = 49152 + 1000 * atoi(getenv(
"CIS_MODEL_INDEX"));
437 cislog_debug(
"_last_port = %d", _last_port);
439 sprintf(address,
"%s://%s:*[%d-]", protocol, host, _last_port + 1);
443 zsock_t *s = zsock_new(ZMQ_PAIR);
445 cislog_error(
"new_zmq_address: Could not initialize empty socket.");
448 zsock_set_linger(s, 0);
449 int port = zsock_bind(s,
"%s", address);
451 cislog_error(
"new_zmq_address: Could not bind socket to address = %s",
456 if ((strcmp(protocol,
"inproc") != 0) &&
457 (strcmp(protocol,
"ipc") != 0)) {
459 sprintf(address,
"%s://%s:%d", protocol, host, port);
461 strcpy(comm->
address, address);
462 cislog_debug(
"new_zmq_address: Bound socket to %s", comm->
address);
463 if (strlen(comm->
name) == 0)
464 sprintf(comm->
name,
"tempnewZMQ-%d", port);
466 _cisSocketsCreated++;
468 int ret = init_zmq_reply(comm);
478 int init_zmq_comm(
comm_t *comm) {
480 if (comm->
valid == 0)
482 zsock_t *s = zsock_new(ZMQ_PAIR);
484 cislog_error(
"init_zmq_address: Could not initialize empty socket.");
487 zsock_set_linger(s, 0);
488 ret = zsock_connect(s,
"%s", comm->
address);
490 cislog_error(
"init_zmq_address: Could not connect socket to address = %s",
495 cislog_debug(
"init_zmq_address: Connected socket to %s", comm->
address);
496 if (strlen(comm->
name) == 0)
497 sprintf(comm->
name,
"tempinitZMQ-%s", comm->
address);
500 ret = init_zmq_reply(comm);
510 int free_zmq_comm(
comm_t *x) {
516 if (_cis_error_flag == 0) {
517 size_t data_len = 100;
518 char *data = (
char*)malloc(data_len);
519 while (zmq_comm_nmsg(*x) > 0) {
520 ret = zmq_comm_recv(*x, &data, data_len, 1);
532 if (x->
reply != NULL) {
533 zmq_reply_t *zrep = (zmq_reply_t*)(x->
reply);
535 ret = free_zmq_reply(zrep);
540 zsock_t *s = (zsock_t*)(x->
handle);
542 cislog_debug(
"Destroying socket: %s", x->
address);
556 int zmq_comm_nmsg(
const comm_t x) {
560 zsock_t *s = (zsock_t*)(x.
handle);
561 zpoller_t *poller = zpoller_new(s, NULL);
562 if (poller == NULL) {
563 cislog_error(
"zmq_comm_nmsg: Could not create poller");
566 void *p = zpoller_wait(poller, 1);
568 if (zpoller_terminated(poller)) {
569 cislog_error(
"zmq_comm_nmsg: Poller interrupted");
577 zpoller_destroy(&poller);
589 zmq_reply_t *zrep = (zmq_reply_t*)(x.
reply);
591 cislog_debug(
"zmq_comm_nmsg(%s): nmsg = %d, nrep = %d",
592 x.
name, zrep->n_msg, zrep->n_rep);
593 out = zrep->n_msg - zrep->n_rep;
609 int zmq_comm_send(
const comm_t x,
const char *data,
const size_t len) {
610 cislog_debug(
"zmq_comm_send(%s): %d bytes", x.
name, len);
611 if (comm_base_send(x, data, len) == -1)
613 zsock_t *s = (zsock_t*)(x.
handle);
615 cislog_error(
"zmq_comm_send(%s): socket handle is NULL", x.
name);
619 char *new_data = check_reply_send(&x, data, (
int)len, &new_len);
620 if (new_data == NULL) {
621 cislog_error(
"zmq_comm_send(%s): Adding reply address failed.", x.
name);
624 zframe_t *f = zframe_new(new_data, new_len);
627 cislog_error(
"zmq_comm_send(%s): frame handle is NULL", x.
name);
629 ret = zframe_send(&f, s, 0);
631 cislog_error(
"zmq_comm_send(%s): Error in zframe_send", x.
name);
637 ret = do_reply_send(&x);
640 cislog_error(
"zmq_comm_send(%s): EOF received", x.
name);
642 cislog_error(
"zmq_comm_send(%s): Error in do_reply_send", x.
name);
646 cislog_debug(
"zmq_comm_send(%s): returning %d", x.
name, ret);
664 int zmq_comm_recv(
const comm_t x,
char **data,
const size_t len,
665 const int allow_realloc) {
666 cislog_debug(
"zmq_comm_recv(%s)", x.
name);
667 zsock_t *s = (zsock_t*)(x.
handle);
669 cislog_error(
"zmq_comm_recv(%s): socket handle is NULL", x.
name);
673 int nmsg = zmq_comm_nmsg(x);
674 if (nmsg < 0)
return -1;
675 else if (nmsg > 0)
break;
677 cislog_debug(
"zmq_comm_recv(%s): no messages, sleep", x.
name);
678 usleep(CIS_SLEEP_TIME);
681 zframe_t *out = zframe_recv(s);
683 cislog_debug(
"zmq_comm_recv(%s): did not receive", x.
name);
686 size_t len_recv = zframe_size(out) + 1;
687 if (len_recv > len) {
689 cislog_debug(
"zmq_comm_recv(%s): reallocating buffer from %d to %d bytes.",
690 x.
name, len, len_recv);
691 (*data) = (
char*)realloc(*data, len_recv);
693 cislog_error(
"zmq_comm_recv(%s): failed to realloc buffer.", x.
name);
694 zframe_destroy(&out);
698 cislog_error(
"zmq_comm_recv(%s): buffer (%d bytes) is not large enough for message (%d bytes)",
699 x.
name, len, len_recv);
700 zframe_destroy(&out);
701 return -((int)(len_recv - 1));
704 memcpy(*data, zframe_data(out), len_recv);
705 (*data)[len_recv-1] =
'\0';
706 zframe_destroy(&out);
707 int ret = (int)len_recv - 1;
708 ret = check_reply_recv(&x, *data, (
size_t)ret);
709 cislog_debug(
"zmq_comm_recv(%s): returning %d", x.
name, ret);
721 void zmq_install_error() {
722 cislog_error(
"Compiler flag 'ZMQINSTALLED' not defined so ZMQ bindings are disabled.");
731 int free_zmq_comm(
comm_t *x) {
742 int new_zmq_address(
comm_t *comm) {
753 int init_zmq_comm(
comm_t *comm) {
764 int zmq_comm_nmsg(
const comm_t x) {
779 int zmq_comm_send(
const comm_t x,
const char *data,
const size_t len) {
797 int zmq_comm_recv(
const comm_t x,
char **data,
const size_t len,
798 const int allow_realloc) {
void * handle
Pointer to handle for comm.
Definition: CommBase.h:25
Communication structure.
Definition: CommBase.h:19
char address[COMM_ADDRESS_SIZE]
Comm address.
Definition: CommBase.h:22
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 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
void * reply
Reply information.
Definition: CommBase.h:35