Discover devices on all the host's capable network interfaces.
This commit is contained in:
@ -12,6 +12,20 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// ClientInterface is the general interface provided to perform HTTP-over-UDP
|
||||
// requests.
|
||||
type ClientInterface interface {
|
||||
// Do performs a request. The timeout is how long to wait for before returning
|
||||
// the responses that were received. An error is only returned for failing to
|
||||
// send the request. Failures in receipt simply do not add to the resulting
|
||||
// responses.
|
||||
Do(
|
||||
req *http.Request,
|
||||
timeout time.Duration,
|
||||
numSends int,
|
||||
) ([]*http.Response, error)
|
||||
}
|
||||
|
||||
// HTTPUClient is a client for dealing with HTTPU (HTTP over UDP). Its typical
|
||||
// function is for HTTPMU, and particularly SSDP.
|
||||
type HTTPUClient struct {
|
||||
@ -19,6 +33,8 @@ type HTTPUClient struct {
|
||||
conn net.PacketConn
|
||||
}
|
||||
|
||||
var _ ClientInterface = &HTTPUClient{}
|
||||
|
||||
// NewHTTPUClient creates a new HTTPUClient, opening up a new UDP socket for the
|
||||
// purpose.
|
||||
func NewHTTPUClient() (*HTTPUClient, error) {
|
||||
@ -51,14 +67,15 @@ func (httpu *HTTPUClient) Close() error {
|
||||
return httpu.conn.Close()
|
||||
}
|
||||
|
||||
// Do performs a request. The timeout is how long to wait for before returning
|
||||
// the responses that were received. An error is only returned for failing to
|
||||
// send the request. Failures in receipt simply do not add to the resulting
|
||||
// responses.
|
||||
// Do implements ClientInterface.Do.
|
||||
//
|
||||
// Note that at present only one concurrent connection will happen per
|
||||
// HTTPUClient.
|
||||
func (httpu *HTTPUClient) Do(req *http.Request, timeout time.Duration, numSends int) ([]*http.Response, error) {
|
||||
func (httpu *HTTPUClient) Do(
|
||||
req *http.Request,
|
||||
timeout time.Duration,
|
||||
numSends int,
|
||||
) ([]*http.Response, error) {
|
||||
httpu.connLock.Lock()
|
||||
defer httpu.connLock.Unlock()
|
||||
|
||||
|
70
httpu/multiclient.go
Normal file
70
httpu/multiclient.go
Normal file
@ -0,0 +1,70 @@
|
||||
package httpu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// MultiClient dispatches requests out to all the delegated clients.
|
||||
type MultiClient struct {
|
||||
// The HTTPU clients to delegate to.
|
||||
delegates []ClientInterface
|
||||
}
|
||||
|
||||
var _ ClientInterface = &MultiClient{}
|
||||
|
||||
// NewMultiClient creates a new MultiClient that delegates to all the given
|
||||
// clients.
|
||||
func NewMultiClient(delegates []ClientInterface) *MultiClient {
|
||||
return &MultiClient{
|
||||
delegates: delegates,
|
||||
}
|
||||
}
|
||||
|
||||
// Do implements ClientInterface.Do.
|
||||
func (mc *MultiClient) Do(
|
||||
req *http.Request,
|
||||
timeout time.Duration,
|
||||
numSends int,
|
||||
) ([]*http.Response, error) {
|
||||
tasks := &errgroup.Group{}
|
||||
|
||||
results := make(chan []*http.Response)
|
||||
tasks.Go(func() error {
|
||||
defer close(results)
|
||||
return mc.sendRequests(results, req, timeout, numSends)
|
||||
})
|
||||
|
||||
var responses []*http.Response
|
||||
tasks.Go(func() error {
|
||||
for rs := range results {
|
||||
responses = append(responses, rs...)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return responses, tasks.Wait()
|
||||
}
|
||||
|
||||
func (mc *MultiClient) sendRequests(
|
||||
results chan<-[]*http.Response,
|
||||
req *http.Request,
|
||||
timeout time.Duration,
|
||||
numSends int,
|
||||
) error {
|
||||
tasks := &errgroup.Group{}
|
||||
for _, d := range mc.delegates {
|
||||
d := d // copy for closure
|
||||
tasks.Go(func() error {
|
||||
responses, err := d.Do(req, timeout, numSends)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
results <- responses
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return tasks.Wait()
|
||||
}
|
Reference in New Issue
Block a user