// Creates a port mapping. The mapping process is continually attempted and // maintained in the background, but the Mapping interface is returned // immediately without blocking. // // As the mapping is attempted asynchronously in the background, the mapping // will not be active when this function returns. Use the Mapping interface // returned to determine when the mapping becomes active. // // A successful mapping is not guaranteed. // // See the Config struct and the Mapping interface for more information. func New(cfg Config) (Mapping, error) { if IsGloballyRoutable() { return nil, ErrGlobalIP } gwa, err := gateway.GetIPs() if err != nil { return nil, err } if cfg.Lifetime == 0 { cfg.Lifetime = DefaultLifetime } m := &mapping{ cfg: cfg, abortChan: make(chan struct{}), notifyChan: make(chan struct{}, 1), } ssdp.Start() go m.portMappingLoop(gwa) return m, nil }
// Attempt to obtain the external IP address from the default gateway. // // If the host has a globally routable IP, returns that IP. // // Currently this only tries NAT-PMP and does not attempt to learn the external // IP address via UPnP. // // This function is not very useful because the IP address returned may still // be an RFC1918 address, due to the possibility of a double NAT setup. There // are better solutions for obtaining one's public IP address, such as STUN. func ExternalAddr() (net.IP, error) { if gr, ip := isGloballyRoutable(); gr { return ip, nil } gwa, err := gateway.GetIPs() if err != nil { return nil, err } var extaddr net.IP for _, gw := range gwa { extaddr, err = natpmp.GetExternalAddr(gw) if err == nil { return extaddr, nil } } return nil, err }