func (s *Server) handleQuery(source Addr, m krpc.Msg) {
	go func() {
		expvars.Add(fmt.Sprintf("received query %s", m.Q), 1)
		if a := m.A; a != nil {
			if a.NoSeed != 0 {
				expvars.Add("received argument noseed", 1)
			}
			if a.Scrape != 0 {
				expvars.Add("received argument scrape", 1)
			}
		}
	}()
	if m.SenderID() != nil {
		if n, _ := s.getNode(source, int160FromByteArray(*m.SenderID()), !m.ReadOnly); n != nil {
			n.lastGotQuery = time.Now()
		}
	}
	if s.config.OnQuery != nil {
		propagate := s.config.OnQuery(&m, source.Raw())
		if !propagate {
			return
		}
	}
	// Don't respond.
	if s.config.Passive {
		return
	}
	// TODO: Should we disallow replying to ourself?
	args := m.A
	switch m.Q {
	case "ping":
		s.reply(source, m.T, krpc.Return{})
	case "get_peers":
		var r krpc.Return
		// TODO: Return values.
		if err := s.setReturnNodes(&r, m, source); err != nil {
			s.sendError(source, m.T, *err)
			break
		}
		r.Token = func() *string {
			t := s.createToken(source)
			return &t
		}()
		s.reply(source, m.T, r)
	case "find_node":
		var r krpc.Return
		if err := s.setReturnNodes(&r, m, source); err != nil {
			s.sendError(source, m.T, *err)
			break
		}
		s.reply(source, m.T, r)
	case "announce_peer":
		if !s.validToken(args.Token, source) {
			expvars.Add("received announce_peer with invalid token", 1)
			return
		}
		expvars.Add("received announce_peer with valid token", 1)
		if h := s.config.OnAnnouncePeer; h != nil {
			p := Peer{
				IP:   source.IP(),
				Port: args.Port,
			}
			if args.ImpliedPort {
				p.Port = source.Port()
			}
			go h(metainfo.Hash(args.InfoHash), p)
		}
		s.reply(source, m.T, krpc.Return{})
	default:
		s.sendError(source, m.T, krpc.ErrorMethodUnknown)
	}
}
func (s *Server) handleQuery(source Addr, m krpc.Msg) {
	go func() {
		expvars.Add(fmt.Sprintf("received query %s", m.Q), 1)
		if a := m.A; a != nil {
			if a.NoSeed != 0 {
				expvars.Add("received argument noseed", 1)
			}
			if a.Scrape != 0 {
				expvars.Add("received argument scrape", 1)
			}
		}
	}()
	if m.SenderID() != nil {
		if n, _ := s.getNode(source, int160FromByteArray(*m.SenderID()), !m.ReadOnly); n != nil {
			n.lastGotQuery = time.Now()
		}
	}
	if s.config.OnQuery != nil {
		propagate := s.config.OnQuery(&m, source.Raw())
		if !propagate {
			return
		}
	}
	
	if s.config.Passive {
		return
	}
	
	args := m.A
	switch m.Q {
	case "ping":
		s.reply(source, m.T, krpc.Return{})
	case "get_peers":
		var r krpc.Return
		
		if err := s.setReturnNodes(&r, m, source); err != nil {
			s.sendError(source, m.T, *err)
			break
		}
		r.Token = func() *string {
			t := s.createToken(source)
			return &t
		}()
		s.reply(source, m.T, r)
	case "find_node":
		var r krpc.Return
		if err := s.setReturnNodes(&r, m, source); err != nil {
			s.sendError(source, m.T, *err)
			break
		}
		s.reply(source, m.T, r)
	case "announce_peer":
		if !s.validToken(args.Token, source) {
			expvars.Add("received announce_peer with invalid token", 1)
			return
		}
		expvars.Add("received announce_peer with valid token", 1)
		if h := s.config.OnAnnouncePeer; h != nil {
			p := Peer{
				IP:   source.IP(),
				Port: args.Port,
			}
			if args.ImpliedPort {
				p.Port = source.Port()
			}
			go h(metainfo.Hash(args.InfoHash), p)
		}
		s.reply(source, m.T, krpc.Return{})
	default:
		s.sendError(source, m.T, krpc.ErrorMethodUnknown)
	}
}
func ( s * Server ) handleQuery ( source Addr , m krpc . Msg ) { go func ( ) { expvars . Add ( fmt . Sprintf ( " " , m . Q ) , 1 ) if a := m . A ; a != nil { if a . NoSeed != 0 { expvars . Add ( " " , 1 ) } if a . Scrape != 0 { expvars . Add ( " " , 1 ) } } } ( ) if m . SenderID ( ) != nil { if n , _ := s . getNode ( source , int160FromByteArray ( * m . SenderID ( ) ) , ! m . ReadOnly ) ; n != nil { n . lastGotQuery = time . Now ( ) } } if s . config . OnQuery != nil { propagate := s . config . OnQuery ( & m , source . Raw ( ) ) if ! propagate { return } } // Don't respond. if s . config . Passive { return } // TODO: Should we disallow replying to ourself? args := m . A switch m . Q { case " " : s . reply ( source , m . T , krpc . Return { } ) case " " : var r krpc . Return // TODO: Return values. if err := s . setReturnNodes ( & r , m , source ) ; err != nil { s . sendError ( source , m . T , * err ) break } r . Token = func ( ) * string { t := s . createToken ( source ) return & t } ( ) s . reply ( source , m . T , r ) case " " : var r krpc . Return if err := s . setReturnNodes ( & r , m , source ) ; err != nil { s . sendError ( source , m . T , * err ) break } s . reply ( source , m . T , r ) case " " : if ! s . validToken ( args . Token , source ) { expvars . Add ( " " , 1 ) return } expvars . Add ( " " , 1 ) if h := s . config . OnAnnouncePeer ; h != nil { p := Peer { IP : source . IP ( ) , Port : args . Port , } if args . ImpliedPort { p . Port = source . Port ( ) } go h ( metainfo . Hash ( args . InfoHash ) , p ) } s . reply ( source , m . T , krpc . Return { } ) default : s . sendError ( source , m . T , krpc . ErrorMethodUnknown ) } }
// TODO: Probably should write error messages back to senders if something is
// wrong.
TODO : Probably should write error messages back to senders if something is wrong .