//doJoin adds node specified in url to searchlist and nodelist.
//if nodelist>#defaultnode removes and says bye one node in nodelist and returns welcome its ip:port.
func doJoin(w http.ResponseWriter, r *http.Request) {
	s, err := new(w, r)
	if err != nil {
		log.Println(err)
		return
	}
	host, path, port := s.extractHost("join")
	host = s.remoteIP(host)
	if host == "" {
		return
	}
	n, err := node.MakeNode(host, path, port)
	if err != nil || !n.IsAllowed() {
		return
	}
	if _, err := n.Ping(); err != nil {
		return
	}
	suggest := manager.ReplaceNodeInList(n)
	if suggest == nil {
		fmt.Fprintln(s.WR, "WELCOME")
		return
	}
	fmt.Fprintf(s.WR, "WELCOME\n%s\n", suggest.Nodestr)
}
//doUpdate adds remote node to searchlist and lookuptable with datfile specified in url.
//if stamp is in range of defaultUpdateRange adds to updateque.
func doUpdate(w http.ResponseWriter, r *http.Request) {
	s, err := new(w, r)
	if err != nil {
		log.Println(err)
		log.Println("failed to create cgi struct")
		return
	}
	reg := regexp.MustCompile(`^update/(\w+)/(\d+)/(\w+)/([^\+]*)(\+.*)`)
	m := reg.FindStringSubmatch(s.Path())
	if m == nil {
		log.Println("illegal url")
		return
	}
	datfile, stamp, id, hostport, path := m[1], m[2], m[3], m[4], m[5]
	host, portstr, err := net.SplitHostPort(hostport)
	if err != nil {
		log.Println(err)
		return
	}
	port, err := strconv.Atoi(portstr)
	if err != nil {
		log.Println(err)
		return
	}
	host = s.remoteIP(host)
	if host == "" {
		log.Println("host is null")
		return
	}

	n, err := node.MakeNode(host, path, port)
	if err != nil || !n.IsAllowed() {
		log.Println("detects spam")
		return
	}
	manager.AppendToTable(datfile, n)
	nstamp, err := strconv.ParseInt(stamp, 10, 64)
	if err != nil {
		log.Println(err)
		return
	}

	if !recentlist.IsInUpdateRange(nstamp) {
		return
	}
	rec := record.New(datfile, id, nstamp)
	go updateque.UpdateNodes(rec, n)
	fmt.Fprintln(w, "OK")
}
//doBye  removes from nodelist and says bye to the node specified in url.
func doBye(w http.ResponseWriter, r *http.Request) {
	s, err := new(w, r)
	if err != nil {
		log.Println(err)
		return
	}
	host, path, port := s.extractHost("bye")
	host = s.checkRemote(host)
	if host == "" {
		return
	}
	n, err := node.MakeNode(host, path, port)
	if err == nil {
		manager.RemoveFromList(n)
	}
	fmt.Fprintln(s.WR, "BYEBYE")
}