nonblocking io
[corutils.git] / test_routed2.c
blobfbd711f1c660dc74120feaeb22b3e315c60f8b59
1 /**
2 * Connection oriented routing user space utils
3 * Copyright (C) 2009-2014
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 <stdio.h>
24 #include <string.h>
25 #include <sys/socket.h>
26 #include <assert.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/epoll.h>
31 #include "list.h"
32 #include "libcor.h"
35 #define MAX_ADDRLEN 128
38 struct route{
39 struct node *dst;
42 struct route_list{
43 struct route *routes;
44 __u16 rows_alloc;
45 __u16 numroutes;
48 struct service_list{
49 __be16 *ports;
50 __u16 rows_alloc;
51 __u16 numports;
54 #define ROUTE_MAXHOPS 7
56 struct node{
57 char *addr;
59 struct route_list routes;
61 struct service_list services;
63 __u16 addrlen;
64 __u16 minhops;
65 __u8 neighs_queried;
67 struct list_head node_list;
69 __u32 route[ROUTE_MAXHOPS + 1];
70 __u32 hopcount;
73 #define SEARCHQUERY_NEIGHSNOTQUERIED 1
74 #define SEARCHQUERY_NODEBYADDRESS 2
75 struct search_query{
76 int type;
77 union {
78 struct {
79 __u16 addrlen;
80 char *addr;
81 }nodebyaddress;
82 }query;
86 char *localaddr;
87 __u32 localaddrlen;
89 struct route_list localneighs;
90 struct service_list localservices;
92 struct list_head node_list;
94 int discover_finished = 0;
95 int epoll_fd = 0;
97 int rdsock_fd = 0;
99 #define EPOLL_EVENTS 16
101 #define EPOLLDATA_DISCOVERNETWORK 1
102 #define EPOLLDATA_RDSCONNECT 2
103 #define EPOLLDATA_RDSOCKCMD 3
105 struct nonblock_resumeinfo_connect_to_host_send{
106 int fd;
107 struct node *node;
109 __u8 state;
111 struct route_list *routes;
112 int u;
115 struct nonblock_resumeinfo_connect_to_host_recv{
116 int fd;
117 struct node *node;
119 __u8 state;
121 int u;
124 struct nonblock_resumeinfo{
125 int fd;
127 __u8 type;
129 union{
130 struct{
131 struct node *node;
133 __u8 state;
135 struct route_list *list;
136 struct service_list *service;
138 struct nonblock_resumeinfo_connect_to_host_send connect_send;
139 struct nonblock_resumeinfo_connect_to_host_recv connect_recv;
141 struct libcor_nonblock_resumeinfo lnr;
142 }discover_network;
144 struct{
145 __u8 state;
147 __u64 cookie;
148 struct node *node;
150 struct nonblock_resumeinfo_connect_to_host_send connect_send;
151 struct nonblock_resumeinfo_connect_to_host_recv connect_resp;
153 struct libcor_nonblock_resumeinfo lnr;
154 }rds_connect;
156 struct{
157 struct libcor_nonblock_resumeinfo lnr;
158 }rdsock_cmd;
159 }data;
162 #define offsetof(type, member) __builtin_offsetof (type, member)
164 #define container_of(ptr, type, member) ({ \
165 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
166 (type *)( (char *)__mptr - offsetof(type,member) );})
169 static void set_nonblock(int fd, int value)
171 int flags;
173 flags = fcntl(fd, F_GETFL, 0);
174 if (flags == -1) {
175 perror("set_nonblock F_GETFL");
176 exit(1);
179 flags = (flags & (~(O_NONBLOCK)));
180 if (value)
181 flags = flags | O_NONBLOCK;
183 if (fcntl(fd, F_SETFL, flags) == -1) {
184 perror("set_nonblock F_SETFL");
185 exit(1);
189 static int addr_eq(char *addr1, __u32 addrlen1,
190 char *addr2, __u32 addrlen2)
192 __u16 cmplen = addrlen1;
193 __u32 u;
195 if (addrlen2 < cmplen)
196 cmplen = addrlen2;
198 if (cmplen > MAX_ADDRLEN)
199 return 0;
201 if (memcmp(addr1, addr2, cmplen) != 0)
202 return 0;
204 for (u=cmplen;u<addrlen1;u++) {
205 if (addr1[u] != 0) {
206 return 0;
209 for (u=cmplen;u<addrlen2;u++) {
210 if (addr2[u] != 0) {
211 return 0;
214 return 1;
217 static int node_matches_searchquery(struct node *n, struct search_query *q)
219 if (q->type == SEARCHQUERY_NEIGHSNOTQUERIED) {
220 return n->neighs_queried == 0;
221 } else if (q->type == SEARCHQUERY_NODEBYADDRESS) {
222 return addr_eq(n->addr, n->addrlen,
223 q->query.nodebyaddress.addr,
224 q->query.nodebyaddress.addrlen);
225 } else {
226 assert(0);
227 return 0;
231 static struct node * try_find_neigh(struct search_query *q)
233 struct list_head *curr = node_list.next;
235 while (curr != &node_list) {
236 struct node *currnode = container_of(curr, struct node,
237 node_list);
239 if (node_matches_searchquery(currnode, q)) {
240 return currnode;
243 curr = curr->next;
246 return 0;
249 static struct node * try_find_neigh_byaddr(__u16 addrlen, char *addr)
251 struct search_query q;
252 bzero(&q, sizeof(struct search_query));
253 q.type = SEARCHQUERY_NODEBYADDRESS;
254 q.query.nodebyaddress.addrlen = addrlen;
255 q.query.nodebyaddress.addr = addr;
256 return try_find_neigh(&q);
259 static int check_rc(int rc, char *errormsg)
261 if (rc != RC_OK && rc != RC_WOULDBLOCK)
262 printf("%s\n", errormsg);
263 return (rc != RC_OK);
266 static int connect_to_host_recv(int fd, struct libcor_nonblock_resumeinfo *lnr,
267 struct nonblock_resumeinfo_connect_to_host_recv *rcr,
268 struct node *node)
270 if (rcr->state == 0) {
271 rcr->fd = fd;
272 rcr->node = node;
274 rcr->state = 1;
275 rcr->u=0;
278 assert(rcr->fd = fd);
279 assert(rcr->node = node);
281 assert(node->hopcount != 0);
283 for (;rcr->u < node->hopcount;rcr->u++) {
284 int rc = read_resp_nonblock(fd, lnr);
285 if (rc != RC_OK)
286 return rc;
288 bzero(rcr, sizeof(struct nonblock_resumeinfo_connect_to_host_recv));
289 return RC_OK;
292 static int connect_to_host_send(int fd,
293 struct libcor_nonblock_resumeinfo *lnr,
294 struct nonblock_resumeinfo_connect_to_host_send *cth,
295 struct node *node)
297 if (cth->state == 0) {
298 cth->fd = fd;
299 cth->node = node;
301 cth->routes = &localneighs;
303 cth->state = 1;
304 cth->u=0;
307 assert(cth->fd = fd);
308 assert(cth->node = node);
310 assert(node->hopcount != 0);
312 for (;cth->u < node->hopcount;) {
313 struct node *n = cth->routes->routes[node->route[cth->u]].dst;
314 int rc = send_connect_neigh_nonblock(fd, lnr, n->addrlen,
315 n->addr);
316 cth->u++;
317 if (rc != RC_OK)
318 return rc;
319 cth->routes = &(n->routes);
321 bzero(cth, sizeof(struct nonblock_resumeinfo_connect_to_host_send));
322 return RC_OK;
325 void add_neigh(void *ptr, __u32 addrlen, char *addr)
327 struct route_list *list = (struct route_list *) ptr;
328 struct node *node;
330 if (addrlen > MAX_ADDRLEN)
331 return;
333 if (list->numroutes >= list->rows_alloc)
334 return;
336 assert(list->routes[list->numroutes].dst == 0);
338 node = try_find_neigh_byaddr(addrlen, addr);
340 if (node == 0) {
341 node = calloc(1, sizeof(struct node));
343 node->addr = malloc(((int) addrlen));
344 node->addrlen = addrlen;
345 memcpy(node->addr, addr, addrlen);
347 list_add_tail(&(node->node_list), &node_list);
350 list->routes[list->numroutes].dst = node;
351 list->numroutes++;
354 void init_neighlist(void *ptr, __u32 numneighs)
356 struct route_list *list = (struct route_list *) ptr;
357 if (numneighs > 16)
358 numneighs = 16;
359 #warning todo limit
360 list->rows_alloc = (__u16) numneighs;
361 list->routes = calloc(numneighs, sizeof(struct route));
364 void add_service(void *ptr, __be16 port)
366 struct service_list *list = (struct service_list *) ptr;
368 printf("add service %u\n", ntohs(port));
370 if (list->numports >= list->rows_alloc)
371 return;
373 list->ports[list->numports] = port;
374 list->numports++;
377 void init_servicelist(void *ptr, __u32 numservices)
379 struct service_list *list = (struct service_list *) ptr;
381 printf("init servicelist %u\n", numservices);
383 if (numservices > 16)
384 numservices = 16;
385 list->rows_alloc = (__u16) numservices;
386 list->ports = calloc(numservices, 2);
389 static void print_hex(char *buf, int len)
391 int u;
392 for(u=0;u<len;u++) {
393 printf("%hhx ", buf[u]);
397 void neigh_printaddr(__u16 addrlen, char *addr)
399 printf("addrlen = %d addr: ", (int) addrlen);
400 print_hex(addr, addrlen);
401 printf("\n");
405 static void __recalc_routes(struct node *node)
407 struct list_head *curr;
409 curr = node_list.next;
410 while (curr != &node_list) {
411 struct node *currnode = container_of(curr, struct node,
412 node_list);
414 if (currnode->hopcount < node->hopcount)
415 break;
417 curr = curr->next;
420 list_del(&(node->node_list));
421 list_add_tail(&(node->node_list), curr);
424 static void _recalc_routes(struct node *node)
426 struct route_list *routes = (node == 0 ?
427 &localneighs : &(node->routes));
429 __u32 u;
431 for (u=0;u<routes->numroutes;u++) {
432 struct node *target = routes->routes[u].dst;
434 __u32 hopcount = (node == 0 ? 0 : node->hopcount) + 1;
436 if (target->hopcount != 0 && target->hopcount <= hopcount)
437 continue;
439 if (node == 0) {
440 bzero(&(target->route[0]), sizeof(target->route));
441 } else {
442 memcpy(&(target->route[0]), &(node->route[0]),
443 sizeof(target->route));
446 target->hopcount = hopcount;
447 target->route[hopcount-1] = u;
449 __recalc_routes(target);
453 static void recalc_routes(void)
455 struct list_head oldnodes;
456 struct list_head *curr;
458 list_add(&oldnodes, &node_list);
459 list_del(&node_list);
460 init_list_head(&node_list);
463 curr = oldnodes.next;
464 while (curr != &oldnodes) {
465 struct node *currnode = container_of(curr, struct node,
466 node_list);
468 bzero(&(currnode->route[0]), sizeof(currnode->route));
469 currnode->hopcount = 0;
471 curr = curr->next;
475 _recalc_routes(0);
477 curr = node_list.next;
478 while (curr != &node_list) {
479 struct node *currnode = container_of(curr, struct node,
480 node_list);
482 _recalc_routes(currnode);
484 curr = curr->next;
488 curr = oldnodes.next;
489 while (curr != &oldnodes) {
490 struct node *currnode = container_of(curr, struct node,
491 node_list);
493 curr = curr->next;
495 list_del(&(currnode->node_list));
497 if (currnode->addr != 0) {
498 free(currnode->addr);
499 currnode->addr = 0;
502 free(currnode);
506 void load_neigh_list(int fd, struct nonblock_resumeinfo *nr, struct node *node)
508 struct libcor_nonblock_resumeinfo *lnr;
509 int rc;
511 assert((fd == 0 && nr == 0) || (fd != 0 && nr != 0));
513 if (fd == 0 && nr == 0) {
514 struct epoll_event epe;
516 fd = socket(PF_COR, SOCK_RAW, PROTO_COR_RAW);
517 if(fd < 0) {
518 perror("socket");
519 goto early_out;
522 rc = connect(fd, 0, 0);
523 if(rc < 0) {
524 perror("connect");
525 goto out;
528 set_nonblock(fd, 1);
530 nr = (struct nonblock_resumeinfo *)
531 malloc(sizeof(struct nonblock_resumeinfo));
532 bzero(nr, sizeof(struct nonblock_resumeinfo));
533 nr->fd = fd;
534 nr->type = EPOLLDATA_DISCOVERNETWORK;
535 nr->data.discover_network.node = node;
537 epe.events = (EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLERR |
538 EPOLLET);
539 epe.data.ptr = nr;
540 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &epe);
543 lnr = &(nr->data.discover_network.lnr);
545 assert(nr->type == EPOLLDATA_DISCOVERNETWORK);
546 assert(nr->data.discover_network.node == node);
548 if (nr->data.discover_network.state == 1) {
549 goto state_1;
550 } else if (nr->data.discover_network.state == 2) {
551 goto state_2;
552 } else if (nr->data.discover_network.state == 3) {
553 goto state_3;
554 } else if (nr->data.discover_network.state == 4) {
555 goto state_4;
556 } else if (nr->data.discover_network.state == 5) {
557 goto state_5;
558 } else if (nr->data.discover_network.state == 6) {
559 goto state_6;
560 } else if (nr->data.discover_network.state == 7) {
561 goto state_7;
562 } else if (nr->data.discover_network.state == 8) {
563 goto state_8;
564 } else if (nr->data.discover_network.state != 0) {
565 assert(0);
568 if (node == 0) {
569 nr->data.discover_network.list = &localneighs;
570 nr->data.discover_network.service = &localservices;
571 } else {
572 neigh_printaddr(node->addrlen,
573 node->addr);
574 nr->data.discover_network.list = &(node->routes);
575 nr->data.discover_network.service = &(node->services);
577 nr->data.discover_network.state = 1;
578 state_1:
579 rc = connect_to_host_send(fd, lnr,
580 &(nr->data.discover_network.connect_send),
581 node);
583 if (check_rc(rc, "load_neigh_list: connect_to_host_send error"))
584 goto out;
587 rc = send_list_neigh_nonblock(fd, lnr);
588 nr->data.discover_network.state = 2;
589 if (check_rc(rc, "load_neigh_list: send_list_neigh error"))
590 goto out;
592 state_2:
593 rc = send_list_services_nonblock(fd, lnr);
594 nr->data.discover_network.state = 3;
595 if (check_rc(rc, "load_neigh_list: send_list_services error"))
596 goto out;
598 state_3:
599 if (node != 0) {
600 nr->data.discover_network.state = 4;
601 state_4:
602 rc = connect_to_host_recv(fd, lnr,
603 &(nr->data.discover_network.connect_recv),
604 node);
605 if (check_rc(rc, "load_neigh_list: connect_to_host_recv error"))
606 goto out;
609 nr->data.discover_network.state = 5;
610 state_5:
611 rc = read_resp_nonblock(fd, lnr);
612 if (check_rc(rc, "load_neigh_list: read_resp error"))
613 goto out;
615 nr->data.discover_network.state = 6;
616 state_6:
617 rc = read_neigh_list_nonblock(fd, lnr, nr->data.discover_network.list,
618 init_neighlist, add_neigh);
619 if (check_rc(rc, "load_neigh_list: read_neigh_list error"))
620 goto out;
622 nr->data.discover_network.state = 7;
623 state_7:
624 rc = read_resp_nonblock(fd, lnr);
625 if (check_rc(rc, "load_neigh_list: read_resp error"))
626 goto out;
628 nr->data.discover_network.state = 8;
629 state_8:
630 rc = read_service_list_nonblock(fd, lnr,
631 nr->data.discover_network.service,
632 init_servicelist, add_service);
633 if (check_rc(rc, "load_neigh_list: read_service_list error"))
634 goto out;
636 #warning todo rollback node->routes and node->services on error
637 recalc_routes();
638 out:
639 //printf("load_neigh_list state %d\n", nr->data.discover_network.state);
640 if (rc != RC_WOULDBLOCK) {
641 printf("load_neigh_list rc %d\n", rc);
642 close(fd);
643 if (nr != 0)
644 free(nr);
647 early_out:
648 return;
651 static void discover_network(int fd, struct nonblock_resumeinfo *nr)
653 struct search_query q;
654 bzero(&q, sizeof(struct search_query));
655 q.type = SEARCHQUERY_NEIGHSNOTQUERIED;
657 assert((fd == 0 && nr == 0) || (fd != 0 && nr != 0));
659 if (fd == 0 && nr == 0)
660 load_neigh_list(fd, nr, 0);
662 while (1) {
663 struct node *node;
664 if (nr == 0) {
665 node = try_find_neigh(&q);
666 if (node == 0)
667 break;
668 } else {
669 assert(nr->type == EPOLLDATA_DISCOVERNETWORK);
670 node = nr->data.discover_network.node;
673 load_neigh_list(fd, nr, node);
674 node->neighs_queried = 1;
675 fd = 0;
676 nr = 0;
678 discover_finished = 1;
681 struct rdscmd_connect_data{
682 int fd;
683 struct nonblock_resumeinfo *nr;
686 //cookie+addr are not passed on nonblocking resume
687 static int rdscmd_void_connect(void *ptr, __u64 cookie,
688 struct cor_sockaddr *addr)
690 int fd, rc;
691 struct rdscmd_connect_data *rcd = ((struct rdscmd_connect_data *) ptr);
693 struct libcor_nonblock_resumeinfo *lnr;
695 if (rcd->nr == 0) {
696 struct epoll_event epe;
697 struct node *node;
699 if (addr->sin_family != AF_COR) {
700 printf("rds_connect %llu not af_cor\n", cookie);
701 goto out_noclose;
704 printf("rds_connect cookie: %llu, addr: ", cookie);
705 print_hex(&(addr->addr[0]), sizeof(addr->addr));
706 printf(" port: %u\n", ntohs(addr->port));
709 if ((node = try_find_neigh_byaddr(sizeof(addr->addr),
710 &(addr->addr[0]))) == 0) {
711 printf("connect_to_host host not found\n");
712 goto out_noclose;
716 fd = socket(PF_COR, SOCK_RAW, PROTO_COR_RAW);
717 if(fd < 0) {
718 perror("socket");
719 goto out_noclose;
722 rc = connect(fd, 0, 0);
723 if(rc < 0) {
724 perror("connect");
725 goto out;
728 set_nonblock(fd, 1);
730 rcd->nr = (struct nonblock_resumeinfo *)
731 malloc(sizeof(struct nonblock_resumeinfo));
732 bzero(rcd->nr, sizeof(struct nonblock_resumeinfo));
733 rcd->nr->fd = fd;
734 rcd->nr->type = EPOLLDATA_RDSCONNECT;
735 rcd->nr->data.rds_connect.node = node;
737 epe.events = (EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLERR |
738 EPOLLET);
739 epe.data.ptr = rcd->nr;
740 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &epe);
743 lnr = &(rcd->nr->data.rds_connect.lnr);
745 assert(rcd->nr->type == EPOLLDATA_RDSCONNECT);
747 if (rcd->nr->data.rds_connect.state == 1) {
748 goto state_1;
749 } else if (rcd->nr->data.rds_connect.state == 2) {
750 goto state_2;
751 } else if (rcd->nr->data.rds_connect.state == 3) {
752 goto state_3;
753 } else if (rcd->nr->data.rds_connect.state != 0) {
754 assert(0);
757 rc = connect_to_host_send(fd, lnr,
758 &(rcd->nr->data.rds_connect.connect_send),
759 rcd->nr->data.rds_connect.node);
760 rcd->nr->data.rds_connect.state = 1;
761 if (rc != RC_OK) {
762 printf("connect_to_host_send error\n");
763 goto out;
766 state_1:
767 rc = send_connect_port_nonblock(fd, lnr, addr->port);
768 rcd->nr->data.rds_connect.state = 2;
769 if (rc != RC_OK) {
770 printf("send_connect_port error\n");
771 goto out;
775 state_2:
776 rc = connect_to_host_recv(fd, lnr,
777 &(rcd->nr->data.rds_connect.connect_resp),
778 rcd->nr->data.rds_connect.node);
779 if (rc != RC_OK) {
780 printf("connect_to_host_recv error\n");
781 goto out;
784 rcd->nr->data.rds_connect.state = 3;
785 state_3:
786 rc = read_resp_nonblock(fd, lnr);
787 if (rc != RC_OK) {
788 printf("read_resp error\n");
789 goto out;
792 rc = pass_socket(fd, cookie);
793 if (rc != RC_OK) {
794 printf("pass_socket error\n");
795 goto out;
798 if (0) {
799 out:
800 close(fd);
801 #warning todo rdsock resumeinfo
802 out_noclose:
803 printf("send_rdsock_connecterror\n");
804 rc = send_rdsock_connecterror(rdsock_fd, cookie,
805 CONNECTERROR_NETUNREACH);
806 if (rc != RC_OK) {
807 printf("send_rdsock_connecterror returned %d\n", rc);
808 return 1;
812 return 0;
815 static int proc_rdsock_cmd(int fd, struct rdsock_cmd *cmd)
817 if (cmd->cmd == CRD_KTU_CONNECT) {
818 struct rdscmd_connect_data data;
819 return parse_rdsock_connect(&data, cmd, rdscmd_void_connect);
820 } else {
821 printf("error in proc_rdsock_cmd: unknown cmd: %u\n", cmd->cmd);
822 assert(0);
823 exit(1);
824 return RC_CONNBROKEN;
828 static void nonblock_resume(struct nonblock_resumeinfo *nr)
830 #warning todo call rdscmd_void_connect
831 if (nr->type == EPOLLDATA_DISCOVERNETWORK) {
832 int rc = resume_send_ifneeded(nr->fd,
833 &(nr->data.discover_network.lnr));
835 //printf("load_neigh_list state = %d rc = %d\n", nr->data.discover_network.state, rc);
837 if (rc != RC_OK)
838 return;
840 discover_network(nr->fd, nr);
841 } else {
842 assert(0);
843 exit(1);
847 static int parse_hexchar(char c)
849 if (c == '0')
850 return 0;
851 else if (c == '1')
852 return 1;
853 else if (c == '2')
854 return 2;
855 else if (c == '3')
856 return 3;
857 else if (c == '4')
858 return 4;
859 else if (c == '5')
860 return 5;
861 else if (c == '6')
862 return 6;
863 else if (c == '7')
864 return 7;
865 else if (c == '8')
866 return 8;
867 else if (c == '9')
868 return 9;
869 else if (c == 'A' || c == 'a')
870 return 10;
871 else if (c == 'B' || c == 'b')
872 return 11;
873 else if (c == 'C' || c == 'c')
874 return 12;
875 else if (c == 'D' || c == 'd')
876 return 13;
877 else if (c == 'E' || c == 'e')
878 return 14;
879 else if (c == 'F' || c == 'f')
880 return 15;
881 else
882 return -1;
885 static int parse_hex(char *target, char *src, int srclen)
887 int u;
889 assert(src != 0);
890 assert(target != 0);
891 assert(srclen > 0);
892 assert((srclen%2) == 0);
894 for(u=0;u<(srclen/2);u++) {
895 int high = parse_hexchar(src[u*2]);
896 int low = parse_hexchar(src[u*2+1]);
898 if (high == -1 || low == -1)
899 return -1;
901 target[u] = (char) ((high << 4) + low);
904 return 0;
907 int parse_addr(char *argv_addr)
909 int rc;
910 int len = strlen(argv_addr);
911 char *noaddr = "noaddr";
913 if (strncmp(argv_addr, noaddr, len) == 0) {
914 localaddr = 0;
915 localaddrlen = 0;
916 return;
919 if ((len < 2) || (len%2) != 0)
920 goto parseerror;
922 localaddr = malloc(len/2);
923 localaddrlen = len/2;
925 rc = parse_hex(localaddr, argv_addr, len);
926 if (rc != 0)
927 goto parseerror;
929 return 0;
931 parseerror:
932 fprintf(stderr, "error: argv_addr is not a valid address (contains "
933 "non-hex characters or number of hex characters is not "
934 "a multiple of 2)\n");
935 return -1;
938 int main(int argc, char *argv[])
940 int rc;
941 struct epoll_event rds_epe;
942 struct nonblock_resumeinfo rds_nr;
944 discover_finished = 0;
945 epoll_fd = 0;
947 if (argc <= 1)
948 goto usage;
950 rc = parse_addr(argv[1]);
951 if (rc != 0)
952 goto usage;
954 init_list_head(&node_list);
957 epoll_fd = epoll_create(1);
958 if (epoll_fd <= 0) {
959 perror("epoll_create");
960 goto out;
964 rdsock_fd = socket(PF_COR, SOCK_RAW, PROTO_COR_RDEAMON);
965 if (rdsock_fd < 0) {
966 perror("socket");
967 goto out;
970 rc = connect(rdsock_fd, 0, 0);
971 if (rc < 0) {
972 perror("connect");
973 goto out;
977 bzero(&rds_nr, sizeof(struct nonblock_resumeinfo));
978 rds_nr.fd = rdsock_fd;
979 rds_nr.type = EPOLLDATA_RDSOCKCMD;
980 rds_epe.events = (EPOLLIN | EPOLLRDHUP | EPOLLERR);
981 rds_epe.data.ptr = &rds_nr;
984 send_rdsock_up(rdsock_fd, localaddr, localaddrlen);
986 sleep(30);
988 discover_network(0, 0);
990 while (1) {
991 int discover_finished_old = discover_finished;
992 int u;
993 struct epoll_event events[EPOLL_EVENTS];
995 int rdycnt = epoll_wait(epoll_fd, events, EPOLL_EVENTS, -1);
997 for (u=0;u<rdycnt;u++) {
998 struct nonblock_resumeinfo *nr = events[u].data.ptr;
999 nonblock_resume(nr);
1002 if (discover_finished_old == 0 && discover_finished != 0) {
1003 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, rdsock_fd, &rds_epe);
1008 while (1) {
1009 struct rdsock_cmd cmd;
1011 rc = read_rdsock_cmd(rdsock_fd, &cmd);
1012 if (rc != RC_OK) {
1013 printf("read_rdsock_cmd rc = %d\n", rc);
1014 break;
1017 rc = proc_rdsock_cmd(rdsock_fd, &cmd);
1018 free_rdsockcmd_data(&cmd);
1019 if (rc != RC_OK) {
1020 printf("proc_rdsock_cmd rc = %d\n", rc);
1021 break;
1026 usage:
1027 fprintf(stderr, "usage test_routed addr\n");
1028 out:
1029 return 1;