diff --git a/network/default.go b/network/default.go index e6dff7c5..ece93d82 100644 --- a/network/default.go +++ b/network/default.go @@ -131,21 +131,52 @@ func (n *node) getNeighbours(pbNeighbours *pbNet.Neighbour, depth int) error { return nil } -// updateNeighbour updates node neighbour up to given depth -func (n *node) updateNeighbour(neighbour *pbNet.Neighbour, depth int) error { - if neighbour == nil { - return errors.New("neighbour not initialized") +// unpackNeighbour unpacks pbNet.Neighbour into node of given depth +func unpackNeighbour(pbNeighbour *pbNet.Neighbour, depth int) (*node, error) { + if pbNeighbour == nil { + return nil, errors.New("neighbour not initialized") + } + + neighbourNode := &node{ + id: pbNeighbour.Node.Id, + address: pbNeighbour.Node.Address, + neighbours: make(map[string]*node), } // return if have either reached the depth or have no more neighbours - if depth == 0 { - return nil + if depth == 0 || len(pbNeighbour.Neighbours) == 0 { + return neighbourNode, nil } // decrement the depth depth-- - // TODO: implement this + neighbours := make(map[string]*node) + for _, pbNode := range pbNeighbour.Neighbours { + node, err := unpackNeighbour(pbNode, depth) + if err != nil { + return nil, err + } + neighbours[pbNode.Node.Id] = node + } + + neighbourNode.neighbours = neighbours + + return neighbourNode, nil +} + +// updateNeighbour updates node neighbour up to given depth +func (n *node) updateNeighbour(neighbour *pbNet.Neighbour, depth int) error { + // unpack neighbour into topology of size MaxDepth-1 + // NOTE: we need MaxDepth-1 because node n is the parent adding which + // gives us the max neighbour topology we maintain and propagate + node, err := unpackNeighbour(neighbour, MaxDepth-1) + if err != nil { + return err + } + + // update node neighbours with new topology + n.neighbours[neighbour.Node.Id] = node return nil } @@ -423,31 +454,24 @@ func (n *network) processNetChan(client transport.Client, listener tunnel.Listen neighbours: make(map[string]*node), lastSeen: now, } - } - // update lastSeen timestamp - if n.neighbours[pbNetNeighbour.Node.Id].lastSeen.Before(now) { - n.neighbours[pbNetNeighbour.Node.Id].lastSeen = now - } - // update/store the node neighbour neighbours up to TopologyDepth - // NOTE: * we do NOT update lastSeen time for the neighbours of the neighbour - // * even though we are NOT interested in neighbours over TopologyDepth - // we still allocate the map of neighbours for each of them - //for _, pbNeighbour := range pbNetNeighbour.Neighbours { - // neighbourNode := &node{ - // id: pbNeighbour.Node.Id, - // address: pbNeighbour.Node.Address, - // neighbours: make(map[string]*node), - // } - // n.neighbours[pbNetNeighbour.Node.Id].neighbours[pbNeighbour.Node.Id] = neighbourNode - //} - n.Unlock() - // send a solicit message when discovering a new node - // NOTE: we need to send the solicit message here after the Lock is released as sendMsg locks, too - if !exists { + n.Unlock() + // send a solicit message when discovering new neighbour + // NOTE: we need to release the Lock here as sendMsg locsk, too if err := n.sendMsg("solicit", ControlChannel); err != nil { log.Debugf("Network failed to send solicit message: %s", err) } + continue } + // update/store the node neighbour neighbours up to (MaxDepth-1) topology depth + // NOTE: we don't update max topology depth as we dont include this network node + if err := n.node.updateNeighbour(pbNetNeighbour, MaxDepth-1); err != nil { + log.Debugf("Network failed to update neighbours") + } + // update lastSeen timestamp if outdated + if n.neighbours[pbNetNeighbour.Node.Id].lastSeen.Before(now) { + n.neighbours[pbNetNeighbour.Node.Id].lastSeen = now + } + n.Unlock() case "close": pbNetClose := &pbNet.Close{} if err := proto.Unmarshal(m.Body, pbNetClose); err != nil { @@ -1031,32 +1055,26 @@ func (n *network) close() error { // Close closes network connection func (n *network) Close() error { - // lock this operation n.Lock() + defer n.Unlock() if !n.connected { - n.Unlock() return nil } select { case <-n.closed: - n.Unlock() return nil default: - // TODO: send close message to the network channel - close(n.closed) - // set connected to false - n.connected = false - - // unlock the lock otherwise we'll deadlock sending the close - n.Unlock() - // send close message only if we managed to connect to NetworkChannel log.Debugf("Sending close message from: %s", n.options.Id) if err := n.sendMsg("close", NetworkChannel); err != nil { log.Debugf("Network failed to send close message: %s", err) } + // TODO: send close message to the network channel + close(n.closed) + // set connected to false + n.connected = false } return n.close()