static void read_exports(char *exports, NIDList nidlist) { DIR *dirp; struct dirent *dp; char path[PATH_MAX + 1]; dirp = opendir(exports); if (dirp) { while ((dp = readdir(dirp))) { if (dp->d_type != DT_DIR) continue; if (!strcmp(dp->d_name, ".")) continue; if (!strcmp(dp->d_name, "..")) continue; if (strchr(dp->d_name, '@') == NULL) continue; snprintf(path, sizeof(path), PROC_UUID_TMPL, exports, dp->d_name); if (empty_proc_file(path)) continue; nl_add(nidlist, dp->d_name); } closedir(dirp); } }
/* Received a H(ello) message of the form H<addr>:<port>. This is the first message * that's sent over a TCP connection (in both directions) so the peers can identify * one another. The port is the server port of the endpoint rather than the * connection's port. * * Sometimes accidentally peers try to connect to one another at the same time. * This code kills one of the connections. */ void hello_received(struct file_info *fi, char *addr_port){ char *p = index(addr_port, ':'); if (p == 0) { fprintf(stderr, "do_hello: format is H<addr>:<port>\n"); return; } *p++ = 0; struct sockaddr_in addr; if (addr_get(&addr, addr_port, atoi(p)) < 0) { return; } *--p = ':'; printf("Got hello from %s:%d on socket %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), fi->fd); /* If a connection breaks and is re-established, a duplicate hello message is likely * to arrive, but we can ignore it as we already know the peer. */ if (fi->status == FI_KNOWN) { fprintf(stderr, "Duplicate hello (ignoring)\n"); if (addr_cmp(addr, fi->addr) != 0) { fprintf(stderr, "do_hello: address has changed???\n"); } return; } /* It is possible to set up a connection to self. We deal with it by ignoring the * Hello message but keeping the connection established. */ if (addr_cmp(addr, my_addr) == 0) { fprintf(stderr, "Got hello from self??? (ignoring)\n"); return; } /* Search the connections to see if there is already a connection to this peer. */ struct file_info *fi2; for (fi2 = file_info; fi2 != 0; fi2 = fi2->next) { if (fi2->type == FI_FREE || fi2->status != FI_KNOWN) { continue; } if (addr_cmp(fi2->addr, addr) != 0) { continue; } /* Found another connection. We're going to keep just one. First see if * this is actually an existing connection. It may have broken. */ if (fi2->fd == -1) { printf("Found a defunct connection---dropping that one\n"); if (fi2->type == FI_OUTGOING) { fi->type = FI_OUTGOING; fi->u.fi_outgoing = fi2->u.fi_outgoing; } fi2->type = FI_FREE; return; } /* Of the two, we keep the "lowest one". We identify a connection by the lowest * endpoint address. */ struct sockaddr_in mine, other; get_id(fi->fd, &mine); get_id(fi2->fd, &other); if (addr_cmp(mine, other) < 0) { /* We keep mine. */ printf("duplicate connection -- keep mine\n"); if (fi2->type == FI_OUTGOING) { fi->type = FI_OUTGOING; fi->u.fi_outgoing = fi2->u.fi_outgoing; } close(fi2->fd); fi2->type = FI_FREE; } else { printf("duplicate connection -- keep other\n"); /* The other one wins. */ if (fi->type == FI_OUTGOING) { fi2->type = FI_OUTGOING; fi2->u.fi_outgoing = fi->u.fi_outgoing; } close(fi->fd); fi->type = FI_FREE; return; } } /* No other connection. Keep this one. */ printf("New Connection\n"); fi->addr = addr; fi->status = FI_KNOWN; if(!nl) { nl = (struct node_list *) nl_create(); char *my_addr_str = addr_to_string(my_addr); nl_add(nl, my_addr_str); free(my_addr_str); } char *addr_str = addr_to_string(addr); nl_add(nl, addr_str); free(addr_str); updateGraph(); send_gossip(); }