diff --git a/ifaddrs.go b/ifaddrs.go index 80f61bef..6df6cfc4 100644 --- a/ifaddrs.go +++ b/ifaddrs.go @@ -104,34 +104,29 @@ func AscIfAddress(p1Ptr, p2Ptr *IfAddr) int { // AscIfDefault is a sorting function to sort IfAddrs by whether or not they // have a default route or not. Non-equal types are deferred in the sort. // -// FIXME: This is a particularly expensive sorting operation because of the -// non-memoized calls to NewRouteInfo(). In an ideal world the routeInfo data -// once at the start of the sort and pass it along as a context or by wrapping -// the IfAddr type with this information (this would also solve the inability to -// return errors and the possibility of failing silently). Fortunately, -// N*log(N) where N = 3 is only ~6.2 invocations. Not ideal, but not worth -// optimizing today. The common case is this gets called once or twice. -// Patches welcome. -func AscIfDefault(p1Ptr, p2Ptr *IfAddr) int { +// Returns a sorting function containing a memoized default interface name. +func AscIfDefault() func(p1Ptr, p2Ptr *IfAddr) int { ri, err := NewRouteInfo() if err != nil { - return sortDeferDecision + return func(p1Ptr, p2Ptr *IfAddr) int { return sortDeferDecision } } defaultIfName, err := ri.GetDefaultInterfaceName() if err != nil { - return sortDeferDecision + return func(p1Ptr, p2Ptr *IfAddr) int { return sortDeferDecision } } - switch { - case p1Ptr.Interface.Name == defaultIfName && p2Ptr.Interface.Name == defaultIfName: - return sortDeferDecision - case p1Ptr.Interface.Name == defaultIfName: - return sortReceiverBeforeArg - case p2Ptr.Interface.Name == defaultIfName: - return sortArgBeforeReceiver - default: - return sortDeferDecision + return func(p1Ptr, p2Ptr *IfAddr) int { + switch { + case p1Ptr.Interface.Name == defaultIfName && p2Ptr.Interface.Name == defaultIfName: + return sortDeferDecision + case p1Ptr.Interface.Name == defaultIfName: + return sortReceiverBeforeArg + case p2Ptr.Interface.Name == defaultIfName: + return sortArgBeforeReceiver + default: + return sortDeferDecision + } } } @@ -172,8 +167,11 @@ func DescIfAddress(p1Ptr, p2Ptr *IfAddr) int { } // DescIfDefault is identical to AscIfDefault but reverse ordered. -func DescIfDefault(p1Ptr, p2Ptr *IfAddr) int { - return -1 * AscIfDefault(p1Ptr, p2Ptr) +func DescIfDefault() func(p1Ptr, p2Ptr *IfAddr) int { + ascIfDefault := AscIfDefault() + return func(p1Ptr, p2Ptr *IfAddr) int { + return -1 * ascIfDefault(p1Ptr, p2Ptr) + } } // DescIfName is identical to AscIfName but reverse ordered. @@ -330,7 +328,7 @@ func GetPrivateInterfaces() (IfAddrs, error) { return IfAddrs{}, nil } - OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(privateIfs) + OrderedIfAddrBy(AscIfDefault(), AscIfType, AscIfNetworkSize).Sort(privateIfs) privateIfs, _, err = IfByRFC("6890", privateIfs) if err != nil { @@ -378,7 +376,7 @@ func GetPublicInterfaces() (IfAddrs, error) { return IfAddrs{}, nil } - OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(publicIfs) + OrderedIfAddrBy(AscIfDefault(), AscIfType, AscIfNetworkSize).Sort(publicIfs) _, publicIfs, err = IfByRFC("6890", publicIfs) if err != nil { @@ -1045,9 +1043,9 @@ func SortIfBy(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) { case "-address": sortFuncs[i] = DescIfAddress case "+default", "default": - sortFuncs[i] = AscIfDefault + sortFuncs[i] = AscIfDefault() case "-default": - sortFuncs[i] = DescIfDefault + sortFuncs[i] = DescIfDefault() case "+name", "name": // The "name" selector returns an array of IfAddrs // ordered by the interface name.