Internally handle port range

This commit is contained in:
Asim 2016-03-02 14:20:28 +00:00
parent 1adcb237d9
commit 4ef44db161

View File

@ -5,11 +5,14 @@ import (
"bytes" "bytes"
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
"strings"
"sync" "sync"
mls "github.com/micro/misc/lib/tls" mls "github.com/micro/misc/lib/tls"
@ -49,6 +52,58 @@ type httpTransportListener struct {
listener net.Listener listener net.Listener
} }
func listen(addr string, fn func(string) (net.Listener, error)) (net.Listener, error) {
// host:port || host:min-max
parts := strings.Split(addr, ":")
//
if len(parts) < 2 {
return fn(addr)
}
// try to extract port range
ports := strings.Split(parts[len(parts)-1], "-")
// single port
if len(ports) < 2 {
return fn(addr)
}
// we have a port range
// extract min port
min, err := strconv.Atoi(ports[0])
if err != nil {
return nil, errors.New("unable to extract port range")
}
// extract max port
max, err := strconv.Atoi(ports[1])
if err != nil {
return nil, errors.New("unable to extract port range")
}
// set host
host := parts[:len(parts)-1]
// range the ports
for port := min; port <= max; port++ {
// try bind to host:port
ln, err := fn(fmt.Sprintf("%s:%d", host, port))
if err == nil {
return ln, nil
}
// hit max port
if port == max {
return nil, err
}
}
// why are we here?
return nil, fmt.Errorf("unable to bind to %s", addr)
}
func (b *buffer) Close() error { func (b *buffer) Close() error {
return nil return nil
} }
@ -331,16 +386,25 @@ func (h *httpTransport) Listen(addr string, opts ...ListenOption) (Listener, err
// TODO: support use of listen options // TODO: support use of listen options
if h.opts.Secure || h.opts.TLSConfig != nil { if h.opts.Secure || h.opts.TLSConfig != nil {
config := h.opts.TLSConfig config := h.opts.TLSConfig
if config == nil {
cert, err := mls.Certificate(addr) fn := func(addr string) (net.Listener, error) {
if err != nil { if config == nil {
return nil, err cert, err := mls.Certificate(addr)
if err != nil {
return nil, err
}
config = &tls.Config{Certificates: []tls.Certificate{cert}}
} }
config = &tls.Config{Certificates: []tls.Certificate{cert}} return tls.Listen("tcp", addr, config)
} }
l, err = tls.Listen("tcp", addr, config)
l, err = listen(addr, fn)
} else { } else {
l, err = net.Listen("tcp", addr) fn := func(addr string) (net.Listener, error) {
return net.Listen("tcp", addr)
}
l, err = listen(addr, fn)
} }
if err != nil { if err != nil {