/*
listenForFilterRequest waits for a filter request from a client to come.  Then,
it verifies the authenticity of the request and takes the appropriate action
based on the AITF filter request protocol.
*/
func listenForFilterRequest(mode complianceMode) {
	if handshakes == nil {
		handshakes = make(map[uint64](*filter.Request))
	}

	/*Open up a UDP server on the filter request port and handle any messages
	that arrive.*/
	serverAddr, err := net.ResolveUDPAddr("udp", ":54321")
	if err != nil {
		log.Fatal(err)
	}

	serverConn, err := net.ListenUDP("udp", serverAddr)
	if err != nil {
		log.Fatal(err)
	}

	defer serverConn.Close()

	buf := make([]byte, 5000)
	for {
		n, addr, _ := serverConn.ReadFromUDP(buf)

		/*Read a request from the UDP connection*/
		var req filter.Request
		_, err := req.ReadFrom(bytes.NewBuffer(buf[:n]))
		if err != nil {
			log.Println(err)
			continue
		}

		/*Throw the request away if it is not authentic.*/
		if !req.Authentic() {
			log.Println("Received a forged filter request!")
			continue
		}

		log.Println("Got", req.Type, "from", aitf.Hostname(addr.IP))

		switch req.Type {
		case filter.FilterReq:
			/*When we receive a filter request, install a temporary filter and begin
			a counter-connection with the attacker's router. Also let the victim know
			that the attack should have stopped with a filter ACK. The filter is
			installed for the full filter time instead of the temporary time, but is
			automatically removed when we get a filter ACK.*/
			filter.InstallFilter(req, filter.LongFilterTime, true)
			req.Type = filter.FilterAck
			req.Send(addr.IP)

			/*If we've blocked this filter before and it's still happening, escalate
			the filter and just block it here.*/
			for _, req2 := range shadowFilters {
				if req2.SrcIP.Equal(req.SrcIP) && req2.DstIP.Equal(req.DstIP) {
					log.Println("Escalating request.")
					return
				}
			}

			req.Type = filter.CounterConnectionSyn
			req.Send(req.Flow.Path[0].IP)

		case filter.CounterConnectionSyn:
			if mode == comply || mode == lie {
				/*When we get a counter-connection SYN, continue the three-way handshake
				with a SYN-ACK. We don't install a filter until we get an ACK back with
				the right nonce.*/
				req.Type = filter.CounterConnectionSynAck
				req.Nonce = uint64(rand.Int63())
				handshakes[req.Nonce] = &req
				req.Send(addr.IP)
			}

		case filter.CounterConnectionSynAck:
			if mode == comply || mode == lie {
				/*When we receive a response to a counter-connection, complete the
				three-way handshake.*/
				req.Type = filter.CounterConnectionAck
				req.Send(addr.IP)
			}

		case filter.CounterConnectionAck:
			if mode == comply || mode == lie {
				/*When we receive a counter-connection ACK, make sure we're actually
				waiting for a response to that handshake, then install a temporary
				filter.*/
				originalReq := handshakes[req.Nonce]
				if originalReq == nil {
					log.Println("Received a forged three-way handshake:", req)
					continue
				} else {
					delete(handshakes, req.Nonce)
				}
			}

			if mode == comply {
				/*The filter is installed for the full filter time instead of the
				temporary time, but is automatically removed when we get a filter ACK.*/
				filter.InstallFilter(req, filter.LongFilterTime, true)

				/*The attacker should be informed of its wrongdoing, and the victim's
				router should be informed that this router is complying with the
				request.*/
				req.Type = filter.FilterReq
				req.Send(req.SrcIP)
				req.Type = filter.FilterAck
				req.Send(addr.IP)
			}

		case filter.FilterAck:
			if mode == comply {
				/*When we get acknowledgement of compliance with a filter, we can remove
				our temporary filter. Nobody lies on the internet.*/
				filter.UninstallFilter(req, true)

				shadowFilters = append(shadowFilters, req)
			}
		}
	}
}