package httpu

import (
	
	
	
	
	
	
	
)

const (
	DefaultMaxMessageBytes = 2048
)

var (
	trailingWhitespaceRx = regexp.MustCompile(" +\r\n")
	crlf                 = []byte("\r\n")
)

// Handler is the interface by which received HTTPU messages are passed to
// handling code.
type Handler interface {
	// ServeMessage is called for each HTTPU message received. peerAddr contains
	// the address that the message was received from.
	ServeMessage(r *http.Request)
}

// HandlerFunc is a function-to-Handler adapter.
type HandlerFunc func(r *http.Request)

func ( HandlerFunc) ( *http.Request) {
	()
}

// A Server defines parameters for running an HTTPU server.
type Server struct {
	Addr            string         // UDP address to listen on
	Multicast       bool           // Should listen for multicast?
	Interface       *net.Interface // Network interface to listen on for multicast, nil for default multicast interface
	Handler         Handler        // handler to invoke
	MaxMessageBytes int            // maximum number of bytes to read from a packet, DefaultMaxMessageBytes if 0
}

// ListenAndServe listens on the UDP network address srv.Addr. If srv.Multicast
// is true, then a multicast UDP listener will be used on srv.Interface (or
// default interface if nil).
func ( *Server) () error {
	var  error

	var  *net.UDPAddr
	if ,  = net.ResolveUDPAddr("udp", .Addr);  != nil {
		log.Fatal()
	}

	var  net.PacketConn
	if .Multicast {
		if ,  = net.ListenMulticastUDP("udp", .Interface, );  != nil {
			return 
		}
	} else {
		if ,  = net.ListenUDP("udp", );  != nil {
			return 
		}
	}

	return .Serve()
}

// Serve messages received on the given packet listener to the srv.Handler.
func ( *Server) ( net.PacketConn) error {
	 := DefaultMaxMessageBytes
	if .MaxMessageBytes != 0 {
		 = .MaxMessageBytes
	}

	 := &sync.Pool{
		New: func() interface{} {
			return make([]byte, )
		},
	}
	for {
		 := .Get().([]byte)
		, ,  := .ReadFrom()
		if  != nil {
			return 
		}
		go func() {
			defer .Put()
			// At least one router's UPnP implementation has added a trailing space
			// after "HTTP/1.1" - trim it.
			 := trailingWhitespaceRx.ReplaceAllLiteral([:], crlf)

			,  := http.ReadRequest(bufio.NewReader(bytes.NewBuffer()))
			if  != nil {
				log.Printf("httpu: Failed to parse request: %v", )
				return
			}
			.RemoteAddr = .String()
			.Handler.ServeMessage()
			// No need to call req.Body.Close - underlying reader is bytes.Buffer.
		}()
	}
}

// Serve messages received on the given packet listener to the given handler.
func ( net.PacketConn,  Handler) error {
	 := Server{
		Handler:         ,
		MaxMessageBytes: DefaultMaxMessageBytes,
	}
	return .Serve()
}