|
|
|
@ -426,6 +426,8 @@ func (c *Direct) SetEndpoints(localPort uint16, endpoints []string) (changed boo
|
|
|
|
|
return c.newEndpoints(localPort, endpoints)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var debugNetmap, _ = strconv.ParseBool(os.Getenv("TS_DEBUG_NETMAP"))
|
|
|
|
|
|
|
|
|
|
func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkMap)) error {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
persist := c.persist
|
|
|
|
@ -443,6 +445,11 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM
|
|
|
|
|
allowStream := maxPolls != 1
|
|
|
|
|
c.logf("PollNetMap: stream=%v :%v %v", maxPolls, localPort, ep)
|
|
|
|
|
|
|
|
|
|
vlogf := logger.Discard
|
|
|
|
|
if debugNetmap {
|
|
|
|
|
vlogf = c.logf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
request := tailcfg.MapRequest{
|
|
|
|
|
Version: 4,
|
|
|
|
|
IncludeIPv6: includeIPv6(),
|
|
|
|
@ -458,9 +465,11 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM
|
|
|
|
|
|
|
|
|
|
bodyData, err := encode(request, &serverKey, &persist.PrivateMachineKey)
|
|
|
|
|
if err != nil {
|
|
|
|
|
vlogf("netmap: encode: %v", err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t0 := time.Now()
|
|
|
|
|
u := fmt.Sprintf("%s/machine/%s/map", serverURL, persist.PrivateMachineKey.Public().HexString())
|
|
|
|
|
req, err := http.NewRequest("POST", u, bytes.NewReader(bodyData))
|
|
|
|
|
if err != nil {
|
|
|
|
@ -472,8 +481,10 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM
|
|
|
|
|
|
|
|
|
|
res, err := c.httpc.Do(req)
|
|
|
|
|
if err != nil {
|
|
|
|
|
vlogf("netmap: Do: %v", err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
vlogf("netmap: Do = %v after %v", res.StatusCode, time.Since(t0).Round(time.Millisecond))
|
|
|
|
|
if res.StatusCode != 200 {
|
|
|
|
|
msg, _ := ioutil.ReadAll(res.Body)
|
|
|
|
|
res.Body.Close()
|
|
|
|
@ -498,11 +509,13 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM
|
|
|
|
|
return
|
|
|
|
|
case _, ok := <-timeoutReset:
|
|
|
|
|
if !ok {
|
|
|
|
|
vlogf("netmap: ending timeout goroutine")
|
|
|
|
|
return // channel closed, shut down goroutine
|
|
|
|
|
}
|
|
|
|
|
if !timeout.Stop() {
|
|
|
|
|
<-timeout.C
|
|
|
|
|
}
|
|
|
|
|
vlogf("netmap: reset timeout timer")
|
|
|
|
|
timeout.Reset(pollTimeout)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -516,24 +529,32 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM
|
|
|
|
|
// We can use this same read loop either way.
|
|
|
|
|
var msg []byte
|
|
|
|
|
for i := 0; i < maxPolls || maxPolls < 0; i++ {
|
|
|
|
|
vlogf("netmap: starting size read after %v (poll %v)", time.Since(t0).Round(time.Millisecond), i)
|
|
|
|
|
var siz [4]byte
|
|
|
|
|
if _, err := io.ReadFull(res.Body, siz[:]); err != nil {
|
|
|
|
|
vlogf("netmap: size read error after %v: %v", time.Since(t0).Round(time.Millisecond), err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
size := binary.LittleEndian.Uint32(siz[:])
|
|
|
|
|
vlogf("netmap: read size %v after %v", size, time.Since(t0).Round(time.Millisecond))
|
|
|
|
|
msg = append(msg[:0], make([]byte, size)...)
|
|
|
|
|
if _, err := io.ReadFull(res.Body, msg); err != nil {
|
|
|
|
|
vlogf("netmap: body read error: %v", err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
vlogf("netmap: read body after %v", time.Since(t0).Round(time.Millisecond))
|
|
|
|
|
|
|
|
|
|
var resp tailcfg.MapResponse
|
|
|
|
|
if err := c.decodeMsg(msg, &resp); err != nil {
|
|
|
|
|
vlogf("netmap: decode error: %v")
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if resp.KeepAlive {
|
|
|
|
|
vlogf("netmap: got keep-alive")
|
|
|
|
|
timeoutReset <- struct{}{}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
vlogf("netmap: got new map")
|
|
|
|
|
|
|
|
|
|
nm := &NetworkMap{
|
|
|
|
|
NodeKey: tailcfg.NodeKey(persist.PrivateNodeKey.Public()),
|
|
|
|
|