rdsock version info
[corutils.git] / libcor.c
blob47c33ab9f8f521bdb9bd744a7e5dd32a0e53f51a
1 /**
2 * Connection oriented routing user space utils
3 * Copyright (C) 2009-2011
4 * Authors:
5 * Michael Blizek
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
23 #include <linux/types.h>
24 #include <errno.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
29 #include "libcor.h"
31 #define likely(x) __builtin_expect((x), 1)
32 #define unlikely(x) __builtin_expect((x), 0)
35 #define CD_CONNECT_NB 1
36 #define CD_CONNECT_PORT 2
37 #define CD_LIST_NEIGH 3
38 #define CD_LIST_SERVICES 4
40 #define CDR_EXECOK 1
42 #define CDR_EXECFAILED 2
43 #define CDR_EXECFAILED_UNKNOWN_COMMAND 1
44 #define CDR_EXECFAILED_PERMISSION_DENIED 2
45 #define CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES 3
46 #define CDR_EXECFAILED_CMD_TOO_SHORT 4
47 #define CDR_EXECFAILED_CMD_TOO_LONG 5
48 #define CDR_EXECFAILED_TARGETADDR_DOESNTEXIST 6
49 #define CDR_EXECFAILED_PORTCLOSED 7
50 #define CDR_EXECFAILED_LISTENERQUEUE_FULL 8
51 #define CDR_EXECFAILED_ILLEGAL_COMMAND 9
53 #define CDR_BINDATA 3
55 #define LIST_NEIGH_FIELD_ADDR 1
56 #define LIST_NEIGH_FIELD_LATENCY 2
59 static int bzero_nr_iffinished(struct libcor_nonblock_resumeinfo *nr, int rc)
61 /*if (rc == RC_WOULDBLOCK) {
62 printf("wouldblock\n");
63 }*/
65 if (rc != RC_WOULDBLOCK) {
66 bzero(nr, sizeof(struct libcor_nonblock_resumeinfo));
68 return rc;
71 #define LIBCOR_ASSERT_ERR() \
72 do { \
73 assert(0); \
74 exit(1); \
75 while (1) { \
76 } \
77 } while(0) \
80 static __u64 htonll(__u64 in)
82 __u64 out = 0;
83 char *p_out = (char *) &out;
85 p_out[7] = in & 255;
86 in = in >> 8;
87 p_out[6] = in & 255;
88 in = in >> 8;
89 p_out[5] = in & 255;
90 in = in >> 8;
91 p_out[4] = in & 255;
92 in = in >> 8;
93 p_out[3] = in & 255;
94 in = in >> 8;
95 p_out[2] = in & 255;
96 in = in >> 8;
97 p_out[1] = in & 255;
98 in = in >> 8;
99 p_out[0] = in & 255;
101 return out;
104 static __u64 ntohll(__u64 in)
106 __u64 out = 0;
107 char *p_in = (char *) &in;
109 out += p_in[7];
110 out << 8;
111 out += p_in[6];
112 out << 8;
113 out += p_in[5];
114 out << 8;
115 out += p_in[4];
116 out << 8;
117 out += p_in[3];
118 out << 8;
119 out += p_in[2];
120 out << 8;
121 out += p_in[1];
122 out << 8;
123 out += p_in[0];
125 return out;
128 #warning todo commands are sent via multiple packets
129 int resume_send(int fd, struct libcor_nonblock_resumeinfo *nr)
131 if (unlikely(nr->type != RESUME_TYPE_WRITE || nr->data.write.fd !=fd))
132 LIBCOR_ASSERT_ERR();
134 if (sizeof(nr->data.write.buf) != WRITE_BUF_SIZE ||
135 unlikely(nr->data.write.len > WRITE_BUF_SIZE))
136 LIBCOR_ASSERT_ERR();
138 while (nr->data.write.totalsent < nr->data.write.len) {
139 char *buf = &(nr->data.write.buf[0]);
140 int sent = send(fd, buf + nr->data.write.totalsent,
141 nr->data.write.len - nr->data.write.totalsent,
144 if (sent < 0 && (errno == EAGAIN ||
145 errno == EWOULDBLOCK))
146 return bzero_nr_iffinished(nr, RC_WOULDBLOCK);
148 if (sent <= 0) {
149 if (errno == EINTR)
150 continue;
152 perror("send");
153 return bzero_nr_iffinished(nr, RC_CONNBROKEN);
156 nr->data.write.totalsent += sent;
159 return bzero_nr_iffinished(nr, RC_OK);
162 static int read_fully(int fd, struct libcor_nonblock_resumeinfo *nr,
163 char *buf, __u32 len, __u32 *maxread)
165 int rc = RC_OK;
167 if (unlikely(nr->type != RESUME_TYPE_READ))
168 LIBCOR_ASSERT_ERR();
170 if (unlikely(nr->data.read.read_fully.state != 0 && (
171 nr->data.read.read_fully.fd != fd ||
172 nr->data.read.read_fully.buf != buf ||
173 nr->data.read.read_fully.len != len ||
174 nr->data.read.read_fully.maxread != maxread)))
175 LIBCOR_ASSERT_ERR();
177 if (nr->data.read.read_fully.state == 1) {
178 goto state_1;
179 } else if (unlikely(nr->data.read.read_fully.state != 0)) {
180 LIBCOR_ASSERT_ERR();
183 nr->data.read.read_fully.fd = fd;
184 nr->data.read.read_fully.buf = buf;
185 nr->data.read.read_fully.len = len;
186 nr->data.read.read_fully.maxread = maxread;
187 nr->data.read.read_fully.totalread = 0;
189 nr->data.read.read_fully.state = 1;
190 state_1:
192 if (maxread != 0) {
193 if (len > (*maxread)) {
194 printf("error in read_fully: maxread reached\n");
195 rc = RC_CONNBROKEN;
196 goto out;
198 (*maxread) -= len;
201 while (len > nr->data.read.read_fully.totalread) {
202 int rcvd = recv(fd, buf + nr->data.read.read_fully.totalread,
203 len - nr->data.read.read_fully.totalread, 0);
204 int u;
206 if (rcvd < 0 && (errno == EAGAIN ||
207 errno == EWOULDBLOCK)) {
208 rc = RC_WOULDBLOCK;
209 /* printf("wouldblock\n"); */
210 goto out;
213 if (rcvd <= 0) {
214 if (errno == EINTR)
215 continue;
217 perror("recv");
218 rc = RC_CONNBROKEN;
219 goto out;
222 /*printf("rcvd: %d:", rcvd);
223 for(u=0;u<rcvd;u++) {
224 printf(" %d, ", (__s32) ((__u8) buf[totalread+u]));
226 printf("\n");*/
228 nr->data.read.read_fully.totalread += (__u32) rcvd;
231 out:
232 if (rc != RC_WOULDBLOCK) {
233 bzero(&(nr->data.read.read_fully),
234 sizeof(nr->data.read.read_fully));
237 return rc;
240 static int read_discard(int fd, struct libcor_nonblock_resumeinfo *nr,
241 __u32 len)
243 char buf[128];
244 int rc = RC_OK;
246 if (unlikely(nr->type != RESUME_TYPE_READ))
247 LIBCOR_ASSERT_ERR();
249 if (unlikely(nr->data.read.read_discard.state != 0 && (
250 nr->data.read.read_discard.fd != fd ||
251 nr->data.read.read_discard.len != len)))
252 LIBCOR_ASSERT_ERR();
254 if (nr->data.read.read_discard.state == 1) {
255 goto state_1;
256 } else if (unlikely(nr->data.read.read_discard.state != 0)) {
257 LIBCOR_ASSERT_ERR();
260 nr->data.read.read_discard.fd = fd;
261 nr->data.read.read_discard.len = len;
262 nr->data.read.read_discard.discarded = 0;
265 nr->data.read.read_discard.state = 1;
266 state_1:
268 while (len > 0) {
269 int rcvd;
271 __u32 rcvlen = len - nr->data.read.read_discard.discarded;
272 if (rcvlen > 128)
273 rcvlen = 128;
275 rcvd = recv(fd, buf, rcvlen, 0);
277 if (rcvd < 0 && (errno == EAGAIN ||
278 errno == EWOULDBLOCK)) {
279 rc = RC_WOULDBLOCK;
280 break;
283 if (rcvd <= 0) {
284 if (errno == EINTR)
285 continue;
287 perror("recv");
288 rc = RC_CONNBROKEN;
289 goto out;
292 nr->data.read.read_discard.discarded -= rcvd;
295 out:
296 if (rc != RC_WOULDBLOCK) {
297 bzero(&(nr->data.read.read_discard),
298 sizeof(nr->data.read.read_discard));
301 return rc;
304 static int encode_len(char *buf, int buflen, __u32 len)
306 if (unlikely(buf == 0))
307 return -1;
309 if (unlikely(buflen < 4))
310 return -1;
312 if (len <= 127) {
313 buf[0] = (__u8) len;
314 return 1;
317 if (len <= 16511) {
318 buf[0] = (__u8) ((len - 128) /256 + 128);
319 buf[1] = (__u8) ((len- 128) & 255);
320 return 2;
323 if (len < 1073741951) {
324 __u32 len_be = htonl(len - 16511);
325 char *len_p = (char *) &len_be;
327 buf[0] = len_p[0] + 192;
328 buf[1] = len_p[1];
329 buf[2] = len_p[2];
330 buf[3] = len_p[3];
331 return 4;
334 return -1;
337 static int decode_len(char *buf, int buflen, __u32 *len)
339 if (unlikely(buflen < 1))
340 return 0;
342 if ((__u8) buf[0] <= 127) {
343 *len = (__u8) buf[0];
344 return 1;
347 if (buflen < 2)
348 return 0;
350 if ((__u8) buf[0] <= 191) {
351 *len = 128 + ((__u32) ((__u8) buf[0]) - 128) * 256 +
352 ((__u8) buf[1]);
353 return 2;
356 if (buflen < 4)
357 return 0;
359 ((char *) len)[0] = buf[0] - 192;
360 ((char *) len)[1] = buf[1];
361 ((char *) len)[2] = buf[2];
362 ((char *) len)[3] = buf[3];
364 *len = ntohl(*len) + 16511;
366 return 4;
369 static int read_len(int fd, struct libcor_nonblock_resumeinfo *nr,
370 __u32 *len, __u32 *maxread)
372 int rc = RC_CONNBROKEN;
374 if (unlikely(nr->type != RESUME_TYPE_READ))
375 LIBCOR_ASSERT_ERR();
377 if (unlikely(nr->data.read.read_len.state != 0 && (
378 nr->data.read.read_len.fd != fd ||
379 nr->data.read.read_len.len != len ||
380 nr->data.read.read_len.maxread != maxread)))
381 LIBCOR_ASSERT_ERR();
383 if (sizeof(nr->data.read.read_len.buf) != 4)
384 LIBCOR_ASSERT_ERR();
386 if (nr->data.read.read_len.state == 1) {
387 goto state_1;
388 } else if (unlikely(nr->data.read.read_len.state != 0)) {
389 LIBCOR_ASSERT_ERR();
392 nr->data.read.read_len.fd = fd;
393 nr->data.read.read_len.len = len;
394 nr->data.read.read_len.maxread = maxread;
395 bzero(&(nr->data.read.read_len.buf[0]), 4);
396 nr->data.read.read_len.read = 0;
399 while(1) {
400 nr->data.read.read_len.state = 1;
401 state_1:
402 if (nr->data.read.read_len.read >= 4) {
403 printf("error in readlen: read to high\n");
404 rc = RC_CONNBROKEN;
405 goto out;
408 rc = read_fully(fd, nr, &(nr->data.read.read_len.buf[0]) +
409 nr->data.read.read_len.read, 1, maxread);
410 if (rc != RC_OK)
411 return rc;
413 nr->data.read.read_len.read++;
415 rc = decode_len(&(nr->data.read.read_len.buf[0]),
416 nr->data.read.read_len.read, len);
417 if (rc > 0) {
418 if (unlikely(rc < nr->data.read.read_len.read)) {
419 printf("error in readlen: decode_len has not "
420 "consumed the whole buffer\n");
421 rc = RC_CONNBROKEN;
422 goto out;
424 rc = RC_OK;
425 break;
429 out:
430 if (rc != RC_WOULDBLOCK) {
431 bzero(&(nr->data.read.read_len),
432 sizeof(nr->data.read.read_len));
435 return rc;
438 static int _send_cmd(int fd, struct libcor_nonblock_resumeinfo *nr, __u16 cmd)
440 char buf[6];
441 int rc;
442 __u32 hdrlen = 0;
445 if (unlikely(nr->type != RESUME_TYPE_WRITE || nr->data.write.fd != fd))
446 LIBCOR_ASSERT_ERR();
448 cmd = htons(cmd);
449 buf[0] = ((char *) &cmd)[0];
450 buf[1] = ((char *) &cmd)[1];
452 rc = encode_len(&(buf[2]), 4, nr->data.write.len);
453 if (rc <= 0 || rc > 4)
454 LIBCOR_ASSERT_ERR();
456 if (sizeof(nr->data.write.buf) != WRITE_BUF_SIZE)
457 LIBCOR_ASSERT_ERR();
459 hdrlen = 2 + ((__u32) rc);
461 if (unlikely(nr->data.write.len + hdrlen < nr->data.write.len ||
462 nr->data.write.len + hdrlen > WRITE_BUF_SIZE))
463 LIBCOR_ASSERT_ERR();
465 memmove(&(nr->data.write.buf[hdrlen]), &(nr->data.write.buf[0]),
466 nr->data.write.len);
467 memcpy(&(nr->data.write.buf[0]), &(buf[0]), hdrlen);
468 nr->data.write.len += hdrlen;
470 return resume_send(fd, nr);
473 static int send_cmd(int fd, struct libcor_nonblock_resumeinfo *nr,
474 __u16 cmd, char *buf, __u32 len)
476 if (unlikely(nr->type != RESUME_TYPE_NONE))
477 LIBCOR_ASSERT_ERR();
479 bzero(nr, sizeof(struct libcor_nonblock_resumeinfo));
480 nr->type = RESUME_TYPE_WRITE;
481 nr->data.write.fd = fd;
483 if (sizeof(nr->data.write.buf) != WRITE_BUF_SIZE)
484 LIBCOR_ASSERT_ERR();
486 if (unlikely(WRITE_BUF_SIZE < len))
487 LIBCOR_ASSERT_ERR();
489 if (len != 0) {
490 memcpy(&(nr->data.write.buf[0]), buf, len);
491 nr->data.write.len = len;
494 return _send_cmd(fd, nr, cmd);
497 int read_resp_nonblock(int fd, struct libcor_nonblock_resumeinfo *nr)
499 int rc;
501 struct libcor_nonblock_resumeinfo_resp *nr_resp =
502 &(nr->data.read.funcdata.resp);
504 if (nr->type == RESUME_TYPE_NONE) {
505 bzero(nr, sizeof(struct libcor_nonblock_resumeinfo));
506 nr->type = RESUME_TYPE_READ;
507 nr->data.read.functype = RESUME_READ_FUNC_RESP;
508 nr_resp->fd = fd;
509 } else if (unlikely(nr->type != RESUME_TYPE_READ ||
510 nr->data.read.functype != RESUME_READ_FUNC_RESP)) {
511 LIBCOR_ASSERT_ERR();
512 } else if (unlikely(nr_resp->fd != fd)) {
513 LIBCOR_ASSERT_ERR();
514 } else {
515 __u8 state = nr_resp->state;
517 if (state == 1) {
518 goto state_1;
519 } else if (state == 2) {
520 goto state_2;
521 } else if (state == 3) {
522 goto state_3;
523 } else if (unlikely(state != 0)) {
524 LIBCOR_ASSERT_ERR();
528 nr_resp->respcode = 0;
529 rc = read_fully(fd, nr, (char *) &(nr_resp->respcode), 1, 0);
531 if (rc != RC_OK)
532 return bzero_nr_iffinished(nr, rc);
534 if (nr_resp->respcode == CDR_EXECFAILED) {
535 nr_resp->reasoncode = 0;
537 nr_resp->state = 1;
538 state_1:
539 rc = read_fully(fd, nr, (char *) &(nr_resp->reasoncode), 2, 0);
540 if (rc != RC_OK)
541 return bzero_nr_iffinished(nr, rc);
543 nr_resp->reasoncode = ntohs(nr_resp->reasoncode);
545 printf("execfailed: reasoncode = %d\n", (__s32)
546 nr_resp->reasoncode);
548 nr_resp->state = 2;
549 state_2:
550 rc = read_len(fd, nr, &(nr_resp->reasonlen),
552 if (rc != RC_OK)
553 return bzero_nr_iffinished(nr, rc);
555 nr_resp->state = 3;
556 state_3:
557 rc = read_discard(fd, nr, nr_resp->reasonlen);
558 if (rc != RC_OK)
559 return bzero_nr_iffinished(nr, rc);
562 while (reasonlen > 0) {
563 __u32 nextread = reasonlen;
565 if (reasonlen > 4093)
566 nextread = 4093;
567 reasonlen -= nextread;
568 int rc = read_fully(fd, buf, nextread, 0);
570 if (rc)
571 return rc;
573 buf[nextread] = 0;
574 printf("%s", buf);
576 printf("\n");*/
579 //printf("read_resp: respcode = %d\n", nr_resp->respcode);
581 if (nr_resp->respcode == CDR_EXECOK)
582 return bzero_nr_iffinished(nr, RC_OK);
584 return bzero_nr_iffinished(nr, RC_CONNBROKEN);
587 int read_resp(int fd)
589 int rc = RC_WOULDBLOCK;
590 struct libcor_nonblock_resumeinfo nr;
591 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
593 rc = read_resp_nonblock(fd, &nr);
594 if (unlikely(rc == RC_WOULDBLOCK)) {
595 LIBCOR_ASSERT_ERR();
596 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
598 return rc;
602 int send_connect_neigh_nonblock(int fd, struct libcor_nonblock_resumeinfo *nr,
603 __u32 addrlen, char *addr)
605 __u32 hdrlen = 0;
606 int rc;
608 if (unlikely(nr->type != RESUME_TYPE_NONE))
609 LIBCOR_ASSERT_ERR();
611 if (unlikely(addrlen > (1024 * 1024 * 1024) ||
612 addrlen + 4 > WRITE_BUF_SIZE))
613 LIBCOR_ASSERT_ERR();
615 bzero(nr, sizeof(struct libcor_nonblock_resumeinfo));
616 nr->type = RESUME_TYPE_WRITE;
617 nr->data.write.fd = fd;
619 if (sizeof(nr->data.write.buf) != WRITE_BUF_SIZE)
620 LIBCOR_ASSERT_ERR();
622 if (unlikely(WRITE_BUF_SIZE < 4))
623 LIBCOR_ASSERT_ERR();
625 rc = encode_len(&(nr->data.write.buf[nr->data.write.len]), 4, addrlen);
626 if (unlikely(rc <= 0 || rc > 4))
627 LIBCOR_ASSERT_ERR();
629 nr->data.write.len += (__u32) rc;
631 if (unlikely(nr->data.write.len > WRITE_BUF_SIZE ||
632 WRITE_BUF_SIZE - nr->data.write.len < addrlen))
633 LIBCOR_ASSERT_ERR();
635 memcpy(&(nr->data.write.buf[nr->data.write.len]), addr, addrlen);
636 nr->data.write.len += addrlen;
638 if (unlikely(nr->data.write.len > WRITE_BUF_SIZE))
639 LIBCOR_ASSERT_ERR();
641 return _send_cmd(fd, nr, CD_CONNECT_NB);
644 int send_connect_neigh(int fd, __u32 addrlen, char *addr)
646 int rc = RC_WOULDBLOCK;
647 struct libcor_nonblock_resumeinfo nr;
648 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
650 rc = send_connect_neigh_nonblock(fd, &nr, addrlen, addr);
651 if (unlikely(rc == RC_WOULDBLOCK)) {
652 LIBCOR_ASSERT_ERR();
653 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
655 return rc;
658 int send_connect_port_nonblock(int fd,
659 struct libcor_nonblock_resumeinfo *nr, __be16 port)
661 return send_cmd(fd, nr, CD_CONNECT_PORT, (char *) &port, 2);
664 int send_connect_port(int fd, __be16 port)
666 int rc = RC_WOULDBLOCK;
667 struct libcor_nonblock_resumeinfo nr;
668 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
670 rc = send_connect_port_nonblock(fd, &nr, port);
671 if (unlikely(rc == RC_WOULDBLOCK)) {
672 LIBCOR_ASSERT_ERR();
673 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
675 return rc;
678 int send_list_services_nonblock(int fd, struct libcor_nonblock_resumeinfo *nr)
680 return send_cmd(fd, nr, CD_LIST_SERVICES, 0, 0);
683 int send_list_services(int fd)
685 int rc = RC_WOULDBLOCK;
686 struct libcor_nonblock_resumeinfo nr;
687 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
689 rc = send_list_services_nonblock(fd, &nr);
690 if (unlikely(rc == RC_WOULDBLOCK)) {
691 LIBCOR_ASSERT_ERR();
692 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
694 return rc;
697 int read_service_list_nonblock(int fd, struct libcor_nonblock_resumeinfo *nr,
698 void *ptr,
699 void (*init)(void *ptr, __u32 numservices),
700 void (*next_service)(void *ptr, __be16 port))
702 int rc;
704 struct libcor_nonblock_resumeinfo_servicelist *nr_sl =
705 &(nr->data.read.funcdata.servicelist);
707 if (nr->type == RESUME_TYPE_NONE) {
708 bzero(nr, sizeof(struct libcor_nonblock_resumeinfo));
709 nr->type = RESUME_TYPE_READ;
710 nr->data.read.functype = RESUME_READ_FUNC_SERVICELIST;
711 nr_sl->fd = fd;
712 nr_sl->ptr = ptr;
713 nr_sl->init = init;
714 nr_sl->next_service = next_service;
715 } else if (unlikely(nr->type != RESUME_TYPE_READ ||
716 nr->data.read.functype !=
717 RESUME_READ_FUNC_SERVICELIST)) {
718 LIBCOR_ASSERT_ERR();
719 } else if (unlikely(nr_sl->fd != fd ||
720 nr_sl->ptr != ptr ||
721 nr_sl->init != init ||
722 nr_sl->next_service != next_service)) {
723 LIBCOR_ASSERT_ERR();
724 } else {
725 __u8 state = nr_sl->state;
726 if (state == 1) {
727 goto state_1;
728 } else if (state == 2) {
729 goto state_2;
730 } else if (state == 3) {
731 goto state_3;
732 } else if (unlikely(state != 0)) {
733 LIBCOR_ASSERT_ERR();
737 nr_sl->respcode = 0;
739 rc = read_fully(fd, nr, (char *) &(nr_sl->respcode), 1, 0);
740 if (rc != RC_OK)
741 return bzero_nr_iffinished(nr, rc);
743 if (unlikely(nr_sl->respcode != CDR_BINDATA))
744 return bzero_nr_iffinished(nr, RC_CONNBROKEN);
746 nr_sl->state = 1;
747 state_1:
748 rc = read_len(fd, nr, &(nr_sl->len), 0);
749 if (rc != RC_OK)
750 return bzero_nr_iffinished(nr, rc);
752 nr_sl->state = 2;
753 state_2:
754 rc = read_len(fd, nr, &(nr_sl->numservices), &(nr_sl->len));
755 if (rc != RC_OK)
756 return bzero_nr_iffinished(nr, rc);
758 init(ptr, nr_sl->numservices);
760 for(nr_sl->q=0; nr_sl->q < nr_sl->numservices; nr_sl->q++) {
761 nr_sl->port = 0;
763 nr_sl->state = 3;
764 state_3:
765 rc = read_fully(fd, nr, (char *) &(nr_sl->port), 2,
766 &(nr_sl->len));
767 if (rc != RC_OK)
768 return bzero_nr_iffinished(nr, rc);
770 next_service(ptr, nr_sl->port);
771 nr_sl->port = 0;
774 return bzero_nr_iffinished(nr, rc);
777 int read_service_list(int fd, void *ptr,
778 void (*init)(void *ptr, __u32 numservices),
779 void (*next_service)(void *ptr, __be16 port))
781 int rc = RC_WOULDBLOCK;
782 struct libcor_nonblock_resumeinfo nr;
783 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
785 rc = read_service_list_nonblock(fd, &nr, ptr, init, next_service);
786 if (unlikely(rc == RC_WOULDBLOCK)) {
787 LIBCOR_ASSERT_ERR();
788 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
790 return rc;
794 int send_list_neigh_nonblock(int fd, struct libcor_nonblock_resumeinfo *nr)
796 return send_cmd(fd, nr, CD_LIST_NEIGH, 0, 0);
799 int send_list_neigh(int fd)
801 int rc = RC_WOULDBLOCK;
802 struct libcor_nonblock_resumeinfo nr;
803 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
805 rc = send_list_neigh_nonblock(fd, &nr);
806 if (unlikely(rc == RC_WOULDBLOCK)) {
807 LIBCOR_ASSERT_ERR();
808 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
810 return rc;
813 static int field_present(struct listneigh_field *fields, __u32 numfields,
814 __u16 field)
816 __u64 u;
817 for(u=0;u<numfields;u++) {
818 if (fields[u].field == field)
819 return 1;
821 return 0;
824 int read_neigh_list_nonblock(int fd, struct libcor_nonblock_resumeinfo *nr,
825 void *ptr,
826 void (*init)(void *ptr, __u32 numneigh),
827 void (*next_neigh)(void *ptr, __u32 addrlen, char *addr))
829 int rc;
831 struct libcor_nonblock_resumeinfo_neighlist *nr_nl =
832 &(nr->data.read.funcdata.neighlist);
834 if (nr->type == RESUME_TYPE_NONE) {
835 bzero(nr, sizeof(struct libcor_nonblock_resumeinfo));
836 nr->type = RESUME_TYPE_READ;
837 nr->data.read.functype = RESUME_READ_FUNC_NEIGHLIST;
838 nr_nl->fd = fd;
839 nr_nl->ptr = ptr;
840 nr_nl->init = init;
841 nr_nl->next_neigh = next_neigh;
842 } else if (unlikely(nr->type != RESUME_TYPE_READ ||
843 nr->data.read.functype != RESUME_READ_FUNC_NEIGHLIST)) {
844 LIBCOR_ASSERT_ERR();
845 } else if (unlikely(nr_nl->fd != fd ||
846 nr_nl->ptr != ptr ||
847 nr_nl->init != init ||
848 nr_nl->next_neigh != next_neigh)) {
849 LIBCOR_ASSERT_ERR();
850 } else {
851 __u8 state = nr_nl->state;
852 if (state == 1) {
853 goto state_1;
854 } else if (state == 2) {
855 goto state_2;
856 } else if (state == 3) {
857 goto state_3;
858 } else if (state == 4) {
859 goto state_4;
860 } else if (state == 5) {
861 goto state_5;
862 } else if (state == 6) {
863 goto state_6;
864 } else if (state == 7) {
865 goto state_7;
866 } else if (state == 8) {
867 goto state_8;
868 } else if (state == 9) {
869 goto state_9;
870 } else if (unlikely(state != 0)) {
871 LIBCOR_ASSERT_ERR();
875 nr_nl->respcode = 0;
877 rc = read_fully(fd, nr, (char *) &(nr_nl->respcode), 1, 0);
878 if (rc != RC_OK)
879 return bzero_nr_iffinished(nr, rc);
881 if (unlikely(nr_nl->respcode != CDR_BINDATA))
882 return bzero_nr_iffinished(nr, RC_CONNBROKEN);
884 nr_nl->state = 1;
885 state_1:
886 rc = read_len(fd, nr, &(nr_nl->len), 0);
887 if (rc != RC_OK)
888 return bzero_nr_iffinished(nr, rc);
890 nr_nl->state = 2;
891 state_2:
892 rc = read_len(fd, nr, &(nr_nl->numneighs), &(nr_nl->len));
893 if (rc != RC_OK)
894 return bzero_nr_iffinished(nr, rc);
896 nr_nl->state = 3;
897 state_3:
898 rc = read_len(fd, nr, &(nr_nl->numfields), &(nr_nl->len));
899 if (rc != RC_OK)
900 return bzero_nr_iffinished(nr, rc);
902 if (unlikely(nr_nl->numfields > NEIGHLIST_MAX_FIELDS))
903 return bzero_nr_iffinished(nr, RC_CONNBROKEN);
905 for(nr_nl->u=0; nr_nl->u < nr_nl->numfields; nr_nl->u++) {
906 nr_nl->fields[nr_nl->u].field = 0;
908 nr_nl->state = 4;
909 state_4:
910 rc = read_fully(fd, nr,
911 (char *) &(nr_nl->fields[nr_nl->u].field),
912 2, &(nr_nl->len));
913 if (rc != RC_OK)
914 return bzero_nr_iffinished(nr, rc);
915 nr_nl->fields[nr_nl->u].field =
916 ntohs(nr_nl->fields[nr_nl->u].field);
918 nr_nl->state = 5;
919 state_5:
920 nr_nl->fieldlen = 0;
921 rc = read_len(fd, nr, &(nr_nl->fieldlen), &(nr_nl->len));
922 if (rc != RC_OK)
923 return bzero_nr_iffinished(nr, rc);
925 if (unlikely(nr_nl->fieldlen > 65535))
926 return bzero_nr_iffinished(nr, RC_CONNBROKEN);
928 nr_nl->fields[nr_nl->u].len = (__u16) nr_nl->fieldlen;
929 nr_nl->fieldlen = 0;
932 if (unlikely(field_present(nr_nl->fields, nr_nl->numfields,
933 LIST_NEIGH_FIELD_ADDR) == 0))
934 return bzero_nr_iffinished(nr, RC_CONNBROKEN);
936 init(ptr, nr_nl->numneighs);
938 for (nr_nl->u=0; nr_nl->u < nr_nl->numneighs; nr_nl->u++) {
939 bzero(&(nr_nl->addr[0]), ADDR_MAX_LEN);
940 nr_nl->addrlen = 0;
941 nr_nl->latency = 0;
943 for(nr_nl->v=0; nr_nl->v < nr_nl->numfields; nr_nl->v++) {
944 nr_nl->fieldlen = nr_nl->fields[nr_nl->v].len;
945 if (nr_nl->fieldlen == 0) {
946 nr_nl->state = 6;
947 state_6:
948 rc = read_len(fd, nr, &(nr_nl->fieldlen),
949 &(nr_nl->len));
950 if (rc != RC_OK)
951 return bzero_nr_iffinished(nr, rc);
954 if (nr_nl->fieldlen > nr_nl->len)
955 return bzero_nr_iffinished(nr, RC_CONNBROKEN);
957 nr_nl->len -= nr_nl->fieldlen;
959 if (field_present(nr_nl->fields, nr_nl->v,
960 nr_nl->fields[nr_nl->v].field)) {
961 goto discard_field;
962 } else if (nr_nl->fields[nr_nl->v].field ==
963 LIST_NEIGH_FIELD_ADDR) {
965 nr_nl->addrlen = nr_nl->fieldlen;
967 if (unlikely(nr_nl->addrlen > ADDR_MAX_LEN))
968 goto discard_field;
970 if (sizeof(nr_nl->addr) != ADDR_MAX_LEN)
971 LIBCOR_ASSERT_ERR();
973 bzero(&(nr_nl->addr[0]), ADDR_MAX_LEN);
975 nr_nl->state = 7;
976 state_7:
977 rc = read_fully(fd, nr, &(nr_nl->addr[0]),
978 nr_nl->addrlen,
979 &(nr_nl->fieldlen));
980 if (rc != RC_OK)
981 return bzero_nr_iffinished(nr, rc);
982 } else if (nr_nl->fields[nr_nl->v].field ==
983 LIST_NEIGH_FIELD_LATENCY) {
984 nr_nl->latency = 0;
986 nr_nl->state = 8;
987 state_8:
988 rc = read_fully(fd, nr, &nr_nl->latency, 1,
989 &(nr_nl->fieldlen));
990 if (rc != RC_OK)
991 return bzero_nr_iffinished(nr, rc);
993 printf("latency %d\n", (int) nr_nl->latency);
996 discard_field:
997 if (nr_nl->fieldlen > 0) {
998 nr_nl->state = 9;
999 state_9:
1000 rc = read_discard(fd, nr, nr_nl->fieldlen);
1001 if (rc != RC_OK)
1002 return bzero_nr_iffinished(nr, rc);
1005 nr_nl->fieldlen = 0;
1008 if (nr_nl->addrlen > ADDR_MAX_LEN)
1009 LIBCOR_ASSERT_ERR();
1011 next_neigh(ptr, nr_nl->addrlen, &(nr_nl->addr[0]));
1012 bzero(&(nr_nl->addr[0]), ADDR_MAX_LEN);
1013 nr_nl->addrlen = 0;
1014 nr_nl->latency = 0;
1017 return bzero_nr_iffinished(nr, rc);
1020 int read_neigh_list(int fd, void *ptr,
1021 void (*init)(void *ptr, __u32 numneighs),
1022 void (*next_neigh)(void *ptr, __u32 addrlen, char *addr))
1024 int rc = RC_WOULDBLOCK;
1025 struct libcor_nonblock_resumeinfo nr;
1026 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
1028 rc = read_neigh_list_nonblock(fd, &nr, ptr, init, next_neigh);
1029 if (unlikely(rc == RC_WOULDBLOCK)) {
1030 LIBCOR_ASSERT_ERR();
1031 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
1033 return rc;
1036 int pass_socket(int fd, __u64 cookie)
1038 int rc;
1040 rc = setsockopt(fd, SOL_COR, COR_PASS_ON_CLOSE, &cookie, 8);
1041 if (rc != 0) {
1042 perror("pass_socket");
1043 return RC_CONNBROKEN;
1046 close(fd);
1048 return RC_OK;
1051 static int send_rdsock_cmd(int fd, struct libcor_nonblock_resumeinfo *nr,
1052 __u32 cmd, char *data, __u32 datalen)
1054 __u32 be_cmd = htonl(cmd);
1055 __u32 be_datalen = htonl(datalen);
1057 if (unlikely(nr->type != RESUME_TYPE_NONE))
1058 LIBCOR_ASSERT_ERR();
1060 bzero(nr, sizeof(struct libcor_nonblock_resumeinfo));
1061 nr->type = RESUME_TYPE_WRITE;
1062 nr->data.write.fd = fd;
1064 if (sizeof(nr->data.write.buf) != WRITE_BUF_SIZE)
1065 LIBCOR_ASSERT_ERR();
1067 if (unlikely(datalen + 8 < datalen || WRITE_BUF_SIZE < (datalen + 8)))
1068 LIBCOR_ASSERT_ERR();
1070 memcpy(&(nr->data.write.buf[0]), (char *) &be_cmd, 4);
1071 memcpy(&(nr->data.write.buf[4]), (char *) &be_datalen, 4);
1072 memcpy(&(nr->data.write.buf[8]), data, datalen);
1073 nr->data.write.len = datalen + 8;
1075 return resume_send(fd, nr);
1078 int send_rdsock_version_nonblock(int fd,
1079 struct libcor_nonblock_resumeinfo *nr,
1080 __u32 version)
1082 char data[4];
1084 version = htonl(version);
1086 memcpy(&(data[0]), (char *) &version, 4);
1088 return send_rdsock_cmd(fd, nr, CRD_UTK_VERSION, &(data[0]), 4);
1091 int send_rdsock_version(int fd, __u32 version)
1093 int rc = RC_WOULDBLOCK;
1094 struct libcor_nonblock_resumeinfo nr;
1095 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
1097 rc = send_rdsock_version_nonblock(fd, &nr, version);
1098 if (unlikely(rc == RC_WOULDBLOCK)) {
1099 LIBCOR_ASSERT_ERR();
1100 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
1102 return rc;
1105 int send_rdsock_up_nonblock(int fd, struct libcor_nonblock_resumeinfo *nr,
1106 char *addr, __u32 addrlen)
1108 char data[72];
1110 __u64 flags = 0;
1112 __u32 addrlenbe;
1114 if (addr == 0 && addrlen != 0)
1115 return RC_CONNBROKEN;
1117 if (addrlen > 64)
1118 return RC_CONNBROKEN;
1120 flags = htonll(flags);
1121 addrlenbe = htonl(addrlen);
1123 memcpy(&(data[0]), (char *) &flags, 8);
1124 memcpy(&(data[8]), (char *) &addrlenbe, 4);
1125 if (addrlen > 0)
1126 memcpy(&(data[12]), addr, addrlen);
1128 return send_rdsock_cmd(fd, nr, CRD_UTK_UP, &(data[0]), 12 + addrlen);
1131 int send_rdsock_up(int fd, char *addr, __u32 addrlen)
1133 int rc = RC_WOULDBLOCK;
1134 struct libcor_nonblock_resumeinfo nr;
1135 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
1137 rc = send_rdsock_up_nonblock(fd, &nr, addr, addrlen);
1138 if (unlikely(rc == RC_WOULDBLOCK)) {
1139 LIBCOR_ASSERT_ERR();
1140 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
1142 return rc;
1145 int send_rdsock_connecterror_nonblock(int fd,
1146 struct libcor_nonblock_resumeinfo *nr,
1147 __u64 cookie, __u32 error)
1149 char data[12];
1151 error = htonl(error);
1153 memcpy(&(data[0]), (char *) &cookie, 8);
1154 memcpy(&(data[8]), (char *) &error, 4);
1156 return send_rdsock_cmd(fd, nr, CRD_UTK_CONNECTERROR, &(data[0]), 12);
1159 int send_rdsock_connecterror(int fd, __u64 cookie, __u32 error)
1161 int rc = RC_WOULDBLOCK;
1162 struct libcor_nonblock_resumeinfo nr;
1163 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
1165 rc = send_rdsock_connecterror_nonblock(fd, &nr, cookie, error);
1166 if (unlikely(rc == RC_WOULDBLOCK)) {
1167 LIBCOR_ASSERT_ERR();
1168 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
1170 return rc;
1173 int parse_rdsock_supported_versions(struct rdsock_cmd *cmd,
1174 __u32 *versionmin, __u32 *versionmax)
1176 if (cmd->cmddatalen != 8)
1177 return 1;
1179 memcpy((char *) versionmin, cmd->cmddata, 4);
1180 *versionmin = htonl(*versionmin);
1181 memcpy((char *) versionmax, cmd->cmddata + 4, 4);
1182 *versionmax = htonl(*versionmax);
1184 return 0;
1187 int parse_rdsock_connect(void *ptr, struct rdsock_cmd *cmd,
1188 int (*proc_connect)(void *ptr, __u64 cookie,
1189 struct cor_sockaddr *addr))
1191 __u64 cookie;
1192 struct cor_sockaddr addr;
1194 memcpy((char *) &cookie, cmd->cmddata, 8);
1196 if ((sizeof(struct cor_sockaddr) + 8) != cmd->cmddatalen)
1197 return 1;
1199 memcpy((char *) &addr, cmd->cmddata + 8, sizeof(struct cor_sockaddr));
1201 return proc_connect(ptr, cookie, &addr);
1204 int read_rdsock_cmd_nonblock(int fd,
1205 struct libcor_nonblock_resumeinfo *nr,
1206 struct rdsock_cmd *cmd)
1208 int rc;
1210 struct libcor_nonblock_resumeinfo_rdsockcmd *nr_rd =
1211 &(nr->data.read.funcdata.rdsock_cmd);
1213 bzero(cmd, sizeof(struct rdsock_cmd));
1215 if (nr->type == RESUME_TYPE_NONE) {
1216 bzero(nr, sizeof(struct libcor_nonblock_resumeinfo));
1217 nr->type = RESUME_TYPE_READ;
1218 nr->data.read.functype = RESUME_READ_FUNC_RDSOCK_CMD;
1219 nr_rd->fd = fd;
1220 } else if (unlikely(nr->type != RESUME_TYPE_READ ||
1221 nr->data.read.functype != RESUME_READ_FUNC_RDSOCK_CMD)){
1222 LIBCOR_ASSERT_ERR();
1223 } else if (unlikely(nr_rd->fd != fd)) {
1224 LIBCOR_ASSERT_ERR();
1225 } else {
1226 __u8 state = nr_rd->state;
1228 if (state == 1) {
1229 goto state_1;
1230 } else if (state == 2) {
1231 goto state_2;
1232 } else if (unlikely(state != 0)) {
1233 LIBCOR_ASSERT_ERR();
1237 if (sizeof(nr_rd->buf) != 8)
1238 LIBCOR_ASSERT_ERR();
1240 rc = read_fully(fd, nr, (char *) &(nr_rd->buf[0]), 8, 0);
1241 if (rc != RC_OK)
1242 return bzero_nr_iffinished(nr, rc);
1244 ((char *) &(nr_rd->cmd))[0] = nr_rd->buf[0];
1245 ((char *) &(nr_rd->cmd))[1] = nr_rd->buf[1];
1246 ((char *) &(nr_rd->cmd))[2] = nr_rd->buf[2];
1247 ((char *) &(nr_rd->cmd))[3] = nr_rd->buf[3];
1248 ((char *) &(nr_rd->cmddatalen))[0] = nr_rd->buf[4];
1249 ((char *) &(nr_rd->cmddatalen))[1] = nr_rd->buf[5];
1250 ((char *) &(nr_rd->cmddatalen))[2] = nr_rd->buf[6];
1251 ((char *) &(nr_rd->cmddatalen))[3] = nr_rd->buf[7];
1253 nr_rd->cmd = ntohl(nr_rd->cmd);
1254 nr_rd->cmddatalen = ntohl(nr_rd->cmddatalen);
1256 if (nr_rd->cmddatalen > 65536)
1257 goto discard;
1259 nr_rd->cmddata = malloc(nr_rd->cmddatalen);
1260 if (nr_rd->cmddata == 0)
1261 goto discard;
1263 nr_rd->state = 1;
1264 state_1:
1265 rc = read_fully(fd, nr, nr_rd->cmddata, nr_rd->cmddatalen, 0);
1266 if (rc != RC_OK) {
1267 if (rc != RC_WOULDBLOCK) {
1268 free(nr_rd->cmddata);
1269 nr_rd->cmddata = 0;
1271 return bzero_nr_iffinished(nr, rc);
1274 cmd->cmd = nr_rd->cmd;
1275 cmd->cmddata = nr_rd->cmddata;
1276 cmd->cmddatalen = nr_rd->cmddatalen;
1278 if (0) {
1279 discard:
1280 nr_rd->state = 2;
1281 state_2:
1282 rc = read_discard(fd, nr, nr_rd->cmddatalen);
1283 if (rc != RC_OK)
1284 return bzero_nr_iffinished(nr, rc);
1286 return bzero_nr_iffinished(nr, rc);
1289 int read_rdsock_cmd(int fd, struct rdsock_cmd *cmd)
1291 int rc = RC_WOULDBLOCK;
1292 struct libcor_nonblock_resumeinfo nr;
1293 bzero(&nr, sizeof(struct libcor_nonblock_resumeinfo));
1295 rc = read_rdsock_cmd_nonblock(fd, &nr, cmd);
1296 if (unlikely(rc == RC_WOULDBLOCK)) {
1297 LIBCOR_ASSERT_ERR();
1298 return bzero_nr_iffinished(&nr, RC_CONNBROKEN);
1300 return rc;