// Close removes the peer from the model and closes the underlying connection if possible. // Implements the protocol.Model interface. func (m *Model) Close(node protocol.NodeID, err error) { l.Infof("Connection to %s closed: %v", node, err) events.Default.Log(events.NodeDisconnected, map[string]string{ "id": node.String(), "error": err.Error(), }) m.pmut.Lock() m.rmut.RLock() for _, repo := range m.nodeRepos[node] { m.repoFiles[repo].Replace(node, nil) } m.rmut.RUnlock() conn, ok := m.rawConn[node] if ok { if conn, ok := conn.(*tls.Conn); ok { // If the underlying connection is a *tls.Conn, Close() does more // than it says on the tin. Specifically, it sends a TLS alert // message, which might block forever if the connection is dead // and we don't have a deadline site. conn.SetWriteDeadline(time.Now().Add(250 * time.Millisecond)) } conn.Close() } delete(m.protoConn, node) delete(m.rawConn, node) delete(m.nodeVer, node) m.pmut.Unlock() }
// IndexUpdate is called for incremental updates to connected nodes' indexes. // Implements the protocol.Model interface. func (m *Model) IndexUpdate(nodeID protocol.NodeID, repo string, fs []protocol.FileInfo) { if debug { l.Debugf("IDXUP(in): %s / %q: %d files", nodeID, repo, len(fs)) } if !m.repoSharedWith(repo, nodeID) { l.Infof("Update for unexpected repository ID %q sent from node %q; ensure that the repository exists and that this node is selected under \"Share With\" in the repository configuration.", repo, nodeID) return } for i := range fs { lamport.Default.Tick(fs[i].Version) } m.rmut.RLock() r, ok := m.repoFiles[repo] m.rmut.RUnlock() if ok { r.Update(nodeID, fs) } else { l.Fatalf("IndexUpdate for nonexistant repo %q", repo) } events.Default.Log(events.RemoteIndexUpdated, map[string]interface{}{ "node": nodeID.String(), "repo": repo, "items": len(fs), "version": r.LocalVersion(nodeID), }) }
func (d *Discoverer) Hint(node string, addrs []string) { resAddrs := resolveAddrs(addrs) var id protocol.NodeID id.UnmarshalText([]byte(node)) d.registerNode(nil, Node{ Addresses: resAddrs, ID: id[:], }) }
// Index is called when a new node is connected and we receive their full index. // Implements the protocol.Model interface. func (m *Model) Index(nodeID protocol.NodeID, repo string, fs []protocol.FileInfo) { if debug { l.Debugf("IDX(in): %s %q: %d files", nodeID, repo, len(fs)) } if !m.repoSharedWith(repo, nodeID) { events.Default.Log(events.RepoRejected, map[string]string{ "repo": repo, "node": nodeID.String(), }) l.Warnf("Unexpected repository ID %q sent from node %q; ensure that the repository exists and that this node is selected under \"Share With\" in the repository configuration.", repo, nodeID) return } m.rmut.RLock() files, ok := m.repoFiles[repo] ignores, _ := m.repoIgnores[repo] m.rmut.RUnlock() if !ok { l.Fatalf("Index for nonexistant repo %q", repo) } for i := 0; i < len(fs); { lamport.Default.Tick(fs[i].Version) if ignores.Match(fs[i].Name) { fs[i] = fs[len(fs)-1] fs = fs[:len(fs)-1] } else { i++ } } files.Replace(nodeID, fs) events.Default.Log(events.RemoteIndexUpdated, map[string]interface{}{ "node": nodeID.String(), "repo": repo, "items": len(fs), "version": files.LocalVersion(nodeID), }) }
// Close removes the peer from the model and closes the underlying connection if possible. // Implements the protocol.Model interface. func (m *Model) Close(node protocol.NodeID, err error) { l.Infof("Connection to %s closed: %v", node, err) events.Default.Log(events.NodeDisconnected, map[string]string{ "id": node.String(), "error": err.Error(), }) m.pmut.Lock() m.rmut.RLock() for _, repo := range m.nodeRepos[node] { m.repoFiles[repo].Replace(node, nil) } m.rmut.RUnlock() conn, ok := m.rawConn[node] if ok { conn.Close() } delete(m.protoConn, node) delete(m.rawConn, node) delete(m.nodeVer, node) m.pmut.Unlock() }
func (d *Discoverer) registerNode(addr net.Addr, node Node) bool { var addrs []string for _, a := range node.Addresses { var nodeAddr string if len(a.IP) > 0 { nodeAddr = fmt.Sprintf("%s:%d", net.IP(a.IP), a.Port) addrs = append(addrs, nodeAddr) } else if addr != nil { ua := addr.(*net.UDPAddr) ua.Port = int(a.Port) nodeAddr = ua.String() addrs = append(addrs, nodeAddr) } } if len(addrs) == 0 { if debug { l.Debugln("discover: no valid address for", node.ID) } } if debug { l.Debugf("discover: register: %s -> %#v", node.ID, addrs) } var id protocol.NodeID copy(id[:], node.ID) d.registryLock.Lock() _, seen := d.registry[id] d.registry[id] = addrs d.registryLock.Unlock() if !seen { events.Default.Log(events.NodeDiscovered, map[string]interface{}{ "node": id.String(), "addrs": addrs, }) } return !seen }