@ -620,18 +620,27 @@ func inTest() bool { return flag.Lookup("test.v") != nil }
// PollNetMap makes a /map request to download the network map, calling cb with
// PollNetMap makes a /map request to download the network map, calling cb with
// each new netmap.
// each new netmap.
//
func ( c * Direct ) PollNetMap ( ctx context . Context , cb func ( * netmap . NetworkMap ) ) error {
// maxPolls is how many network maps to download; common values are 1
return c . sendMapRequest ( ctx , - 1 , false , cb )
// or -1 (to keep a long-poll query open to the server).
}
func ( c * Direct ) PollNetMap ( ctx context . Context , maxPolls int , cb func ( * netmap . NetworkMap ) ) error {
return c . sendMapRequest ( ctx , maxPolls , cb )
// FetchNetMap fetches the netmap once.
func ( c * Direct ) FetchNetMap ( ctx context . Context ) ( * netmap . NetworkMap , error ) {
var ret * netmap . NetworkMap
err := c . sendMapRequest ( ctx , 1 , false , func ( nm * netmap . NetworkMap ) {
ret = nm
} )
if err == nil && ret == nil {
return nil , errors . New ( "[unexpected] sendMapRequest success without callback" )
}
return ret , err
}
}
// SendLiteMapUpdate makes a /map request to update the server of our latest state,
// SendLiteMapUpdate makes a /map request to update the server of our latest state,
// but does not fetch anything. It returns an error if the server did not return a
// but does not fetch anything. It returns an error if the server did not return a
// successful 200 OK response.
// successful 200 OK response.
func ( c * Direct ) SendLiteMapUpdate ( ctx context . Context ) error {
func ( c * Direct ) SendLiteMapUpdate ( ctx context . Context ) error {
return c . sendMapRequest ( ctx , 1 , nil )
return c . sendMapRequest ( ctx , 1 , false, nil)
}
}
// If we go more than pollTimeout without hearing from the server,
// If we go more than pollTimeout without hearing from the server,
@ -640,7 +649,7 @@ func (c *Direct) SendLiteMapUpdate(ctx context.Context) error {
const pollTimeout = 120 * time . Second
const pollTimeout = 120 * time . Second
// cb nil means to omit peers.
// cb nil means to omit peers.
func ( c * Direct ) sendMapRequest ( ctx context . Context , maxPolls int , cb func ( * netmap . NetworkMap ) ) error {
func ( c * Direct ) sendMapRequest ( ctx context . Context , maxPolls int , readOnly bool , cb func ( * netmap . NetworkMap ) ) error {
metricMapRequests . Add ( 1 )
metricMapRequests . Add ( 1 )
metricMapRequestsActive . Add ( 1 )
metricMapRequestsActive . Add ( 1 )
defer metricMapRequestsActive . Add ( - 1 )
defer metricMapRequestsActive . Add ( - 1 )
@ -703,6 +712,16 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netm
Hostinfo : hi ,
Hostinfo : hi ,
DebugFlags : c . debugFlags ,
DebugFlags : c . debugFlags ,
OmitPeers : cb == nil ,
OmitPeers : cb == nil ,
// On initial startup before we know our endpoints, set the ReadOnly flag
// to tell the control server not to distribute out our (empty) endpoints to peers.
// Presumably we'll learn our endpoints in a half second and do another post
// with useful results. The first POST just gets us the DERP map which we
// need to do the STUN queries to discover our endpoints.
// TODO(bradfitz): we skip this optimization in tests, though,
// because the e2e tests are currently hyperspecific about the
// ordering of things. The e2e tests need love.
ReadOnly : readOnly || ( len ( epStrs ) == 0 && ! everEndpoints && ! inTest ( ) ) ,
}
}
var extraDebugFlags [ ] string
var extraDebugFlags [ ] string
if hi != nil && c . linkMon != nil && ! c . skipIPForwardingCheck &&
if hi != nil && c . linkMon != nil && ! c . skipIPForwardingCheck &&
@ -725,17 +744,6 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netm
if c . newDecompressor != nil {
if c . newDecompressor != nil {
request . Compress = "zstd"
request . Compress = "zstd"
}
}
// On initial startup before we know our endpoints, set the ReadOnly flag
// to tell the control server not to distribute out our (empty) endpoints to peers.
// Presumably we'll learn our endpoints in a half second and do another post
// with useful results. The first POST just gets us the DERP map which we
// need to do the STUN queries to discover our endpoints.
// TODO(bradfitz): we skip this optimization in tests, though,
// because the e2e tests are currently hyperspecific about the
// ordering of things. The e2e tests need love.
if len ( epStrs ) == 0 && ! everEndpoints && ! inTest ( ) {
request . ReadOnly = true
}
bodyData , err := encode ( request , serverKey , serverNoiseKey , machinePrivKey )
bodyData , err := encode ( request , serverKey , serverNoiseKey , machinePrivKey )
if err != nil {
if err != nil {