Esempio n. 1
0
func (s *Server) handleHandshake(conn *Conn, msg *protocol.Message) {
	handshake := msg.GetHandshake()
	conn.Peer = handshake.GetSender()

	s.peersLock.RLock()
	peer := s.Peers[conn.Peer.Id]
	s.peersLock.RUnlock()

	if peer != nil {
		s.Printf("Ignoring duplicate peer %s.", conn.PrettyID())
		if err := conn.Close(); err != nil && err != io.EOF {
			s.Printf("ERR closing connection %s", err)
		}
		return
	}

	s.peersLock.Lock()
	s.Peers[conn.Peer.Id] = conn
	s.peersLock.Unlock()

	s.Print(color.GreenString("New peer %s", conn.PrettyID()))
	if !handshake.Response {
		if err := s.sendHandshake(conn, true); err != nil {
			s.Printf("ERR sendHandshake %s", err)
		}
	} else {
		if err := s.sendPeerRequest(conn); err != nil {
			s.Printf("ERR sendPeerRequest %s", err)
		}
	}
	go s.connHeartbeat(conn)
}
Esempio n. 2
0
// Request sends a message on a connection and waits for a response.
// Returns error network.Timeout if no response in 10 seconds.
func (c *Conn) Request(m *protocol.Message) (*protocol.Message, error) {
	m.Id = uint64(rand.Int63())
	m.ResponseRequired = true
	if err := c.Send(m); err != nil {
		return nil, err
	}

	timeout := make(chan bool, 1)
	go func() {
		time.Sleep(10 * time.Second)
		timeout <- true
	}()
	resp := make(chan *protocol.Message, 1)
	c.expectedMessages[m.Id] = resp

	var msg *protocol.Message
	var err error
	select {
	case msg = <-resp:
	case <-timeout:
		err = Timeout
	}
	delete(c.expectedMessages, m.Id)
	return msg, err
}
Esempio n. 3
0
func (s *Server) handlePeerNotify(conn *Conn, msg *protocol.Message) {
	peers := msg.GetPeerNotify().Peers
	for _, peer := range peers {
		if _, ok := s.Peers[peer.Id]; !ok {
			s.Peers[peer.Id] = nil
			s.Connect(peer.Id)
		}
	}
}
Esempio n. 4
0
// Send a message on the specified connection. Consider Request.
func (c *Conn) Send(m *protocol.Message) error {
	msg, err := m.Marshal()
	if err != nil {
		return err
	}
	packet := make([]byte, len(msg)+4)
	binary.BigEndian.PutUint32(packet, uint32(len(msg)))
	copy(packet[4:], msg)
	_, err = c.Conn.Write(packet)
	return err
}
Esempio n. 5
0
func (s *Server) handlePeerNotify(conn *Conn, msg *protocol.Message) {
	conn.peerRequest <- true
	s.Printf("PeerNotify %+v", conn)
	peers := msg.GetPeerNotify().Peers
	for _, peer := range peers {
		if _, ok := s.Peers[peer.Id]; !ok {
			s.Peers[peer.Id] = nil
			s.Connect(peer.Id)
		}
	}
}
Esempio n. 6
0
// Send a message to the specified connection.
func (c *Conn) Send(m *protocol.Message) error {
	msg, err := m.Marshal()
	if err != nil {
		return err
	}
	packet := make([]byte, len(msg)+4)
	binary.BigEndian.PutUint32(packet, uint32(len(msg)))
	copy(packet[4:], msg)

	if _, err := c.Write(packet); err != nil {
		return err
	}
	c.server.Printf("Message: -> %s, %+v", c.PrettyID(), m.GetMessage())
	return nil
}
Esempio n. 7
0
// Broadcast sends a message to all peers with that have the hash in their keyspace.
func (s *Server) Broadcast(hash *uint64, msg *protocol.Message) error {
	alreadySentTo := make(map[uint64]bool)
	if msg.Gossip {
		for _, to := range msg.SentTo {
			alreadySentTo[to] = true
		}
	}
	sentTo := []uint64{murmur3.Sum64([]byte(s.LocalPeer().Id))}
	var toPeers []*Conn
	for _, peer := range s.Peers {
		peerHash := murmur3.Sum64([]byte(peer.Peer.Id))
		if (hash == nil || peer.Peer.GetKeyspace().Includes(*hash)) && !alreadySentTo[peerHash] {
			sentTo = append(sentTo, peerHash)
			toPeers = append(toPeers, peer)
		}
	}
	if msg.Gossip {
		msg.SentTo = append(msg.SentTo, sentTo...)
	}
	for _, peer := range toPeers {
		s.Printf("Broadcasting to %s", peer.Peer.Id)
		if err := peer.Send(msg); err != nil {
			return err
		}
	}
	return nil
}
Esempio n. 8
0
func (s *server) handleQueryRequest(conn *network.Conn, msg *protocol.Message) {
	triples, err := s.ExecuteQuery(msg.GetQueryRequest())
	resp := &protocol.Message{
		Message: &protocol.Message_QueryResponse{
			QueryResponse: &protocol.QueryResponse{
				Triples: triples,
			},
		},
	}
	if err != nil {
		resp.Error = err.Error()
	}
	if err := conn.RespondTo(msg, resp); err != nil {
		s.Printf("ERR send QueryResponse %s", err)
	}
}
Esempio n. 9
0
func (s *Server) handleHandshake(conn *Conn, msg *protocol.Message) {
	handshake := msg.GetHandshake()
	conn.Peer = handshake.GetSender()
	s.Peers[conn.Peer.Id] = conn
	s.Printf("New peer %s", conn.Peer.Id)
	if !handshake.Response {
		if err := s.sendHandshake(conn, true); err != nil {
			log.Printf("ERR sendHandshake %s", err)
		}
	} else {
		msg := &protocol.Message{Message: &protocol.Message_PeerRequest{
			PeerRequest: &protocol.PeerRequest{
				Limit: -1,
				//Keyspace: s.LocalPeer().Keyspace,
			}}}
		if err := conn.Send(msg); err != nil {
			log.Printf("ERR sending PeerRequest: %s", err)
		}
	}
}
Esempio n. 10
0
func (s *Server) handlePeerNotify(conn *Conn, msg *protocol.Message) {
	conn.peerRequest <- true
	peers := msg.GetPeerNotify().Peers
	for _, peer := range peers {
		s.peersLock.RLock()
		_, ok := s.Peers[peer.Id]
		s.peersLock.RUnlock()

		if ok {
			continue
		}

		s.peersLock.Lock()
		s.Peers[peer.Id] = nil
		s.peersLock.Unlock()

		if err := s.Connect(peer.Id); err != nil {
			s.Printf("ERR failed to connect to peer %s", err)
		}
	}
}
Esempio n. 11
0
func (s *server) handleInsertTriples(conn *network.Conn, msg *protocol.Message) {
	triples := msg.GetInsertTriples().Triples
	localKS := s.network.LocalPeer().Keyspace

	var validTriples []*protocol.Triple
	idHashes := make(map[string]uint64)
	for _, triple := range triples {
		hash, ok := idHashes[triple.Subj]
		if !ok {
			hash = murmur3.Sum64([]byte(triple.Subj))
			idHashes[triple.Subj] = hash
		}
		if !localKS.Includes(hash) {
			s.Printf("ERR insert triple dropped due to keyspace %#v from %#v", triple, conn.Peer)
			// TODO(d4l3k): Follow up on bad triple by reannouncing keyspace.
			continue
		}
		validTriples = append(validTriples, triple)
	}
	s.ts.Insert(validTriples)
}
Esempio n. 12
0
func (s *Server) handlePeerRequest(conn *Conn, msg *protocol.Message) {
	// TODO(d4l3k): Handle keyspace check.
	req := msg.GetPeerRequest()

	var peers []*protocol.Peer
	for id, v := range s.Peers {
		if conn.Peer.Id == id || v == nil {
			continue
		}
		peers = append(peers, v.Peer)
		if req.Limit > 0 && int32(len(peers)) >= req.Limit {
			break
		}
	}
	err := conn.Send(&protocol.Message{Message: &protocol.Message_PeerNotify{
		PeerNotify: &protocol.PeerNotify{
			Peers: peers,
		}}})
	if err != nil {
		log.Printf("ERR sending PeerNotify: %s", err)
	}
}
Esempio n. 13
0
// RespondTo sends `resp` as a response to the request `to`.
func (c *Conn) RespondTo(to *protocol.Message, resp *protocol.Message) error {
	resp.ResponseTo = to.Id
	return c.Send(resp)
}
Esempio n. 14
0
func (s *server) ExecuteQuery(q *protocol.QueryRequest) ([]*protocol.Triple, error) {
	var triples []*protocol.Triple
	switch q.Type {
	case protocol.BASIC:
		for i, step := range q.Steps {
			if i != 0 {
				var midTriples []*protocol.Triple
				for _, triple := range triples {
					midTriples = append(midTriples, &protocol.Triple{
						Subj: triple.Obj,
					})
				}
				step = &protocol.ArrayOp{
					Arguments: []*protocol.ArrayOp{step},
					Mode:      protocol.AND,
					Triples:   midTriples,
				}
			}

			// External request and is already sharded.
			if q.Sharded {
				return s.ts.QueryArrayOp(step, int(q.Limit))
			}

			var wg sync.WaitGroup
			var triplesLock sync.RWMutex
			triples = nil
			shards := query.ShardQueryByHash(step)

			// Unrooted queries
			if arrayOp, ok := shards[0]; ok {
				// TODO localnode
				set := s.network.MinimumCoveringPeers()
				s.Printf("Minimum covering set %+v", set)
				_ = arrayOp
				wg.Add(len(set))
				req := basicReq(arrayOp)
				var err error
				for _, conn := range set {
					conn := conn
					go func() {
						var msg *protocol.Message
						msg, err = conn.Request(req)
						if err != nil {
							return
						}
						triplesLock.Lock()
						// TODO(d4l3k): Deduplicate triples
						triples = append(triples, msg.GetQueryResponse().Triples...)
						triplesLock.Unlock()
						done := make(chan bool, 1)
						go func() {
							wg.Done()
							done <- true
						}()
						go func() {
							time.Sleep(10 * time.Second)
							done <- true
						}()
						<-done
					}()
				}
				wg.Wait()
				return triples, err
			}

			// Rooted queries
			for hash, arrayOp := range shards {
				if hash == 0 {
					return nil, query.ErrUnRooted
				}
				if s.network.LocalPeer().Keyspace.Includes(hash) {
					trips, err := s.ts.QueryArrayOp(arrayOp, int(q.Limit))
					if err != nil {
						return nil, err
					}
					triples = append(triples, trips...)
					continue
				}
			Peers:
				for _, conn := range s.network.Peers {
					if conn == nil || conn.Peer == nil {
						continue
					}
					if conn.Peer.Keyspace.Includes(hash) {
						req := basicReq(arrayOp)
						// TODO(d4l3k) Parallelize
						msg, err := conn.Request(req)
						if err != nil {
							return nil, err
						}
						triples = append(triples, msg.GetQueryResponse().Triples...)
						break Peers
					}
				}
			}
		}

	//case protocol.GREMLIN:
	//case protocol.MQL:
	default:
		return nil, query.ErrNotImplemented
	}
	return triples, nil
}